on master help sign in
.github/actions/common_setup/action.yamlnew file+42
since splitsnapshots
unifiedsplit
@@ -0,0 +1,42 @@
1+name: "Common setup"
2+description: "Common setup steps"
3+inputs:
4+ authToken:
5+ description: "Cachix auth token"
6+ required: true
7+runs:
8+ using: "composite"
9+ steps:
10+ - name: Increase swap if linux
11+ shell: bash
12+ run: |
13+ if [ "$RUNNER_OS" == "Linux" ]; then
14+
15+ echo "Is Linux"
16+
17+ free -h
18+
19+ sudo swapoff /mnt/swapfile
20+ sudo fallocate -l 12G /mnt/swapfile
21+ sudo mkswap /mnt/swapfile
22+ sudo swapon /mnt/swapfile
23+
24+ free -h
25+
26+ else
27+
28+ echo "Not Linux"
29+
30+ fi
31+
32+ - name: Install Nix
33+ uses: cachix/install-nix-action@v16
34+ with:
35+ extra_nix_config: |
36+ system-features = kvm
37+ trusted-public-keys = hydra.iohk.io:f/Ea+s+dFdN+3Y/G+FDgSq+a5NEWhJGzdjvKNGv0/EQ= cache.nixos.org-1:6NCHdD59X431o0gWypbMrAURkbJ16ZPMQFGspcDShjY=
38+ substituters = https://hydra.iohk.io https://cache.nixos.org/
39+ - uses: cachix/cachix-action@v10
40+ with:
41+ name: typeable
42+ authToken: "${{ inputs.authToken }}"
.github/workflows/github-actions-image.yamlnew file+311
@@ -0,0 +1,311 @@
1+name: Github Action Docker Image
2+
3+on:
4+ push:
5+ branches: [master]
6+ pull_request:
7+ branches: [master]
8+ release:
9+ types: [prereleased]
10+
11+jobs:
12+ check-formatting:
13+ name: Check Haskell formatting
14+ runs-on: ubuntu-latest
15+ steps:
16+ - uses: actions/checkout@v2
17+
18+ - name: Common setup
19+ uses: ./.github/actions/common_setup
20+ with:
21+ authToken: ${{ secrets.CACHIX_AUTH_TOKEN }}
22+
23+ - name: Run fourmolu
24+ run: |
25+ nix-shell nix/ci.nix -j auto --run "git ls-files '*.hs' | xargs fourmolu -m inplace -o -XRecursiveDo -o -XTypeApplications -o -XPatternSynonyms -o -XBangPatterns"
26+ git diff --exit-code
27+
28+ policeman:
29+ runs-on: ubuntu-latest
30+ steps:
31+ - uses: actions/checkout@v2
32+ with:
33+ submodules: recursive
34+
35+ - name: Common setup
36+ uses: ./.github/actions/common_setup
37+ with:
38+ authToken: ${{ secrets.CACHIX_AUTH_TOKEN }}
39+
40+ - name: Run policeman
41+ run: |
42+ jq --argjson msg "$( $(nix-build ci/policeman.nix)/bin/policeman | grep -v "โš™" | jq -aRs . )" ".[0].message = \$msg" <policeman.json >message.json
43+ cat message.json
44+
45+ - name: Post notice
46+ uses: yuzutech/annotations-action@v0.4.0
47+ with:
48+ title: ๐Ÿ‘ฎ Policeman
49+ repo-token: "${{ secrets.GITHUB_TOKEN }}"
50+ input: "./message.json"
51+
52+ check_versions:
53+ runs-on: ubuntu-latest
54+ steps:
55+ - uses: actions/checkout@v2
56+ with:
57+ submodules: recursive
58+
59+ - name: Check library version
60+ if: github.event_name == 'release'
61+ run: |
62+ if [ "$(awk -F ':' '/^version/ {gsub(/ /, "", $2); print $2}' compaREST.cabal)" != "${{ github.event.release.tag_name }}" ]; then
63+ echo "::error file=compaREST.cabal::Library version does not match release version."
64+ exit 1
65+ fi
66+
67+ - name: Check docker tag
68+ if: github.event_name == 'release'
69+ run: |
70+ if [ "$(yq eval '.runs.image' action.yaml | awk -F ':' '{print $NF}')" != "${{ github.event.release.tag_name }}" ]; then
71+ echo "::error file=action.yaml::Action docker tag does not match release tag."
72+ exit 1
73+ fi
74+
75+ - name: Check changelog
76+ if: github.event_name == 'release'
77+ run: |
78+ if ! grep '^## ${{ github.event.release.tag_name }}$' CHANGELOG.md; then
79+ echo "::error file=CHANGELOG.md::CHANGELOG.md does not contain an entry for this release."
80+ exit 1
81+ fi
82+
83+ Linux:
84+ needs: check_versions
85+ runs-on: ubuntu-latest
86+ steps:
87+ - uses: actions/checkout@v2
88+ with:
89+ submodules: recursive
90+
91+ - name: Common setup
92+ uses: ./.github/actions/common_setup
93+ with:
94+ authToken: ${{ secrets.CACHIX_AUTH_TOKEN }}
95+
96+ - name: Test
97+ shell: bash
98+ run: |
99+ $(nix-build -A test -j auto --no-out-link)/bin/compaREST-tests
100+
101+ - name: Build Linux static binary
102+ shell: bash
103+ run: |
104+ cp $(nix-build -A compaRESTStaticBin -j auto --no-out-link)/bin/compaREST compaREST
105+
106+ - name: Upload compaREST Linux Binary
107+ uses: actions/upload-artifact@v2
108+ with:
109+ name: compaREST-Linux
110+ path: compaREST
111+
112+ - name: Build Docker Images
113+ shell: bash
114+ run: |
115+ cp $(nix-build -A compaRESTGithubAction -j auto --no-out-link) compaREST-Github-Action-image.tar.gz
116+ cp $(nix-build -A compaRESTImage -j auto --no-out-link) compaREST-image.tar.gz
117+
118+ - name: Upload compaREST Docker Github Action Image
119+ uses: actions/upload-artifact@v2
120+ with:
121+ name: compaREST Github Action Docker Image
122+ path: compaREST-Github-Action-image.tar.gz
123+
124+ - name: Upload compaREST Docker Image
125+ uses: actions/upload-artifact@v2
126+ with:
127+ name: compaREST Docker Image
128+ path: compaREST-image.tar.gz
129+
130+ - name: Install skopeo
131+ if: github.event_name == 'release'
132+ shell: bash
133+ run: |
134+ sudo apt-get -y update
135+ sudo apt-get -y install skopeo
136+
137+ - name: Login to DockerHub
138+ uses: docker/login-action@v1.10.0
139+ with:
140+ username: ${{ secrets.DOCKER_HUB_USERNAME }}
141+ password: ${{ secrets.DOCKER_HUB_ACCESS_TOKEN }}
142+
143+ - name: Push Nightly Docker Images to DockerHub
144+ if: github.ref == 'refs/heads/master' && github.event_name == 'push'
145+ shell: bash
146+ run: |
147+ skopeo copy docker-archive:$(nix-build -A compaRESTGithubAction -j auto --no-out-link) docker://ilyakooo0/comparest-github-action:nightly
148+ skopeo copy docker-archive:$(nix-build -A compaRESTImage -j auto --no-out-link) docker://ilyakooo0/comparest:nightly
149+
150+ - name: Push Release Docker Images to DockerHub
151+ if: github.event_name == 'release'
152+ shell: bash
153+ run: |
154+ skopeo copy docker-archive:$(nix-build -A compaRESTGithubAction -j auto --no-out-link) docker://ilyakooo0/comparest-github-action:${{ github.event.release.tag_name }}
155+ skopeo copy docker-archive:$(nix-build -A compaRESTImage -j auto --no-out-link) docker://ilyakooo0/comparest:${{ github.event.release.tag_name }}
156+
157+ - name: Zip Release Assets
158+ if: github.event_name == 'release'
159+ shell: bash
160+ run: |
161+ zip compaREST-Linux-x86.zip compaREST
162+
163+ - name: Upload compaREST Github Action Docker Image to release
164+ if: github.event_name == 'release'
165+ uses: svenstaro/upload-release-action@2.2.1
166+ with:
167+ repo_token: ${{ secrets.GITHUB_TOKEN }}
168+ file: compaREST-Github-Action-image.tar.gz
169+ tag: ${{ github.ref }}
170+
171+ - name: Upload compaREST Docker Image to release
172+ if: github.event_name == 'release'
173+ uses: svenstaro/upload-release-action@2.2.1
174+ with:
175+ repo_token: ${{ secrets.GITHUB_TOKEN }}
176+ file: compaREST-image.tar.gz
177+ tag: ${{ github.ref }}
178+
179+ - name: Upload compaREST binary โ€“ Linux โ€“ x86 to release
180+ if: github.event_name == 'release'
181+ uses: svenstaro/upload-release-action@2.2.1
182+ with:
183+ repo_token: ${{ secrets.GITHUB_TOKEN }}
184+ file: compaREST-Linux-x86.zip
185+ tag: ${{ github.ref }}
186+
187+ dist:
188+ needs: check_versions
189+ runs-on: ubuntu-latest
190+ steps:
191+ - uses: actions/checkout@v2
192+ with:
193+ submodules: recursive
194+
195+ - name: Cache
196+ uses: actions/cache@v1
197+ with:
198+ path: |
199+ ~/.stack
200+ .stack-work
201+ key: ${{ runner.os }}-stack-${{ hashFiles('stack.yaml') }}-${{ hashFiles('**.cabal') }}
202+ restore-keys: |
203+ ${{ runner.os }}-stack-${{ hashFiles('stack.yaml') }}
204+ ${{ runner.os }}-stack
205+
206+ - name: Upgrade stack
207+ shell: bash
208+ # Needed for Hackage token authorization
209+ run: stack upgrade --git
210+
211+ - name: Build dist
212+ run: |
213+ stack sdist --pvp-bounds both --test-tarball
214+ echo "distPath=$(stack path | awk -F ": " '/dist-dir/ {print $2}')" >> $GITHUB_ENV
215+
216+ - name: Upload compaREST sources artifact
217+ uses: actions/upload-artifact@v2
218+ with:
219+ name: compaREST sources
220+ path: ${{ env.distPath }}/*.tar.gz
221+
222+ - name: Upload compaREST sources to release
223+ if: github.event_name == 'release'
224+ uses: svenstaro/upload-release-action@2.2.1
225+ with:
226+ repo_token: ${{ secrets.GITHUB_TOKEN }}
227+ file_glob: true
228+ file: ${{ env.distPath }}/*.tar.gz
229+ tag: ${{ github.ref }}
230+
231+ - name: Publish compaREST candidate to Hackage
232+ shell: bash
233+ if: github.event_name == 'release'
234+ env:
235+ HACKAGE_KEY: ${{ secrets.HACKAGE_KEY }}
236+ run: |
237+ stack upload --pvp-bounds both --test-tarball --candidate .
238+
239+ macOS:
240+ needs: check_versions
241+ runs-on: macos-latest
242+ steps:
243+ - uses: actions/checkout@v2
244+ with:
245+ submodules: recursive
246+
247+ - name: Common setup
248+ uses: ./.github/actions/common_setup
249+ with:
250+ authToken: ${{ secrets.CACHIX_AUTH_TOKEN }}
251+
252+ - name: Build macOS binary bundle
253+ run: |
254+ cp -LR $(nix-build -A macOSCompaRESTBundle -j auto --no-out-link) compaREST
255+
256+ - name: Upload macOS compaREST bundle
257+ uses: actions/upload-artifact@v2
258+ with:
259+ name: compaREST binary โ€“ macOS โ€“ x86
260+ path: compaREST
261+
262+ - name: Zip Release Assets
263+ if: github.event_name == 'release'
264+ shell: bash
265+ run: |
266+ zip -r compaREST-macOS-x86.zip compaREST
267+
268+ - name: Upload compaREST binary โ€“ macOS โ€“ x86 to release
269+ if: github.event_name == 'release'
270+ uses: svenstaro/upload-release-action@2.2.1
271+ with:
272+ repo_token: ${{ secrets.GITHUB_TOKEN }}
273+ file: compaREST-macOS-x86.zip
274+ tag: ${{ github.ref }}
275+
276+ Linux-Windows:
277+ needs: check_versions
278+ runs-on: ubuntu-latest
279+ steps:
280+ - uses: actions/checkout@v2
281+ with:
282+ submodules: recursive
283+
284+ - name: Common setup
285+ uses: ./.github/actions/common_setup
286+ with:
287+ authToken: ${{ secrets.CACHIX_AUTH_TOKEN }}
288+
289+ - name: Build Windows binary
290+ run: |
291+ cp -LR $(nix-build -A WindowsCompaRESTBin -j auto --no-out-link)/bin compaREST
292+
293+ - name: Upload Windows compaREST bundle
294+ uses: actions/upload-artifact@v2
295+ with:
296+ name: compaREST binary โ€“ Windows
297+ path: compaREST
298+
299+ - name: Zip Release Assets
300+ if: github.event_name == 'release'
301+ shell: bash
302+ run: |
303+ zip -r compaREST-Windows.zip compaREST
304+
305+ - name: Upload compaREST binary โ€“ Windows to release
306+ if: github.event_name == 'release'
307+ uses: svenstaro/upload-release-action@2.2.1
308+ with:
309+ repo_token: ${{ secrets.GITHUB_TOKEN }}
310+ file: compaREST-Windows.zip
311+ tag: ${{ github.ref }}
.github/workflows/haskell.ymldeletedโˆ’54
@@ -1,54 +0,0 @@
1โˆ’name: Haskell CI
2โˆ’
3โˆ’on:
4โˆ’ push:
5โˆ’ branches: [master]
6โˆ’ pull_request:
7โˆ’ branches: [master]
8โˆ’
9โˆ’jobs:
10โˆ’ linux-build:
11โˆ’ runs-on: ubuntu-latest
12โˆ’
13โˆ’ steps:
14โˆ’ - uses: actions/checkout@v2
15โˆ’ with:
16โˆ’ submodules: recursive
17โˆ’ - name: Cache
18โˆ’ uses: actions/cache@v1
19โˆ’ with:
20โˆ’ path: ~/.stack
21โˆ’ key: ${{ runner.os }}-build-stack-${{ hashFiles('**/stack.yaml') }}-${{ hashFiles('**/*.cabal') }}
22โˆ’ restore-keys: |
23โˆ’ ${{ runner.os }}-build-stack-${{ hashFiles('**/stack.yaml') }}
24โˆ’ ${{ runner.os }}-build-stack-
25โˆ’ - name: Increase swap
26โˆ’ run: |
27โˆ’ free -h
28โˆ’
29โˆ’ sudo swapoff /mnt/swapfile
30โˆ’ sudo fallocate -l 12G /mnt/swapfile
31โˆ’ sudo mkswap /mnt/swapfile
32โˆ’ sudo swapon /mnt/swapfile
33โˆ’
34โˆ’ free -h
35โˆ’
36โˆ’ - name: Build
37โˆ’ run: |
38โˆ’ stack build --ghc-options=-O3 --local-bin-path openapi-diff-linux --copy-bins --flag openapi-diff:Static
39โˆ’ - name: Test
40โˆ’ run: stack test --ghc-options=-O3 --flag openapi-diff:Static --test-arguments='--hide-successes --no-create'
41โˆ’
42โˆ’ - name: Zip
43โˆ’ if: github.ref == 'refs/heads/master'
44โˆ’ run: |
45โˆ’ zip openapi-diff-linux openapi-diff-linux/openapi-diff
46โˆ’ - uses: "marvinpinto/action-automatic-releases@latest"
47โˆ’ if: github.ref == 'refs/heads/master'
48โˆ’ with:
49โˆ’ repo_token: "${{ secrets.GITHUB_TOKEN }}"
50โˆ’ automatic_release_tag: "latest"
51โˆ’ prerelease: false
52โˆ’ title: "Pre-Release"
53โˆ’ files: |
54โˆ’ *.zip
.github/workflows/remove-artifacts.yamldeletedโˆ’17
@@ -1,17 +0,0 @@
1โˆ’name: Remove old artifacts
2โˆ’
3โˆ’on:
4โˆ’ schedule:
5โˆ’ - cron: '0 0 * * *'
6โˆ’jobs:
7โˆ’ remove-old-artifacts:
8โˆ’ runs-on: ubuntu-latest
9โˆ’ timeout-minutes: 10
10โˆ’
11โˆ’ steps:
12โˆ’ - name: Remove old artifacts
13โˆ’ uses: c-hive/gha-remove-artifacts@v1
14โˆ’ with:
15โˆ’ age: '7 days'
16โˆ’ skip-tags: true
17โˆ’ skip-recent: 10
CHANGELOG.md+1โˆ’1
@@ -1,6 +1,6 @@
1# Changelog
1# Changelog
2
2
3โˆ’`openapi-diff` uses [PVP Versioning][1].
3+`comparest` uses [PVP Versioning][1].
4
4
5## 0.0.0.0
5## 0.0.0.0
6
6
README.md+305โˆ’4
@@ -1,8 +1,309 @@
1โˆ’# openapi-diff
1+# CompaREST
2
2
3โˆ’[![Hackage](https://img.shields.io/hackage/v/openapi-diff.svg?logo=haskell)](https://hackage.haskell.org/package/openapi-diff)
3+[![Hackage](https://img.shields.io/hackage/v/comparest.svg?logo=haskell)](https://hackage.haskell.org/package/comparest)
4โˆ’[![Stackage Lts](http://stackage.org/package/openapi-diff/badge/lts)](http://stackage.org/lts/package/openapi-diff)
4+[![Stackage Lts](http://stackage.org/package/comparest/badge/lts)](http://stackage.org/lts/package/comparest)
5โˆ’[![Stackage Nightly](http://stackage.org/package/openapi-diff/badge/nightly)](http://stackage.org/nightly/package/openapi-diff)
5+[![Stackage Nightly](http://stackage.org/package/comparest/badge/nightly)](http://stackage.org/nightly/package/comparest)
6[![MIT license](https://img.shields.io/badge/license-MIT-blue.svg)](LICENSE)
6[![MIT license](https://img.shields.io/badge/license-MIT-blue.svg)](LICENSE)
7
7
8Compatibility checker for OpenAPI
8Compatibility checker for OpenAPI
9+# Quick Start Guide
10+
11+## Your situation
12+
13+You are developing a very important server with a REST API. You have clients who use your API that you do not control. Say, you are also developing a mobile app that uses your API and you can't force someone to update to the latest version. (Or you prefer not to for UX reasons.)
14+
15+You have recently released version 1.0 and things are going great: user are downloading your app, servers are processing requests.
16+
17+You describe your API in a file `api-1.0.0.yaml`:
18+
19+```yaml
20+openapi: "3.0.0"
21+info:
22+ version: 1.0.0
23+ title: Swagger Petstore
24+ license:
25+ name: MIT
26+servers:
27+ - url: https://example.com
28+paths:
29+ /pets:
30+ get:
31+ parameters:
32+ - name: limit
33+ in: query
34+ required: false
35+ schema:
36+ type: integer
37+ maximum: 20
38+ responses:
39+ "200":
40+ description: ""
41+ headers:
42+ x-next:
43+ schema:
44+ type: string
45+ content:
46+ application/json:
47+ schema:
48+ $ref: "#/components/schemas/Pets"
49+ post:
50+ requestBody:
51+ content:
52+ application/json:
53+ schema:
54+ $ref: "#/components/schemas/Pet"
55+ responses:
56+ "201":
57+ description: ""
58+components:
59+ schemas:
60+ Pet:
61+ type: object
62+ required:
63+ - id
64+ - name
65+ properties:
66+ id:
67+ type: integer
68+ name:
69+ type: string
70+ minLength: 3
71+ maxLength: 10
72+ Pets:
73+ type: array
74+ items:
75+ $ref: "#/components/schemas/Pet"
76+```
77+
78+## Evolving your product
79+
80+Enthused over your initial success you hurry to release a new and improved version of your API and mobile app.
81+
82+After a round of very intense programming you take a look at your new `api-1.1.0.yaml`:
83+
84+```yaml
85+openapi: "3.0.0"
86+info:
87+ version: 1.1.0
88+ title: Swagger Petstore
89+ license:
90+ name: MIT
91+servers:
92+ - url: https://example.com
93+paths:
94+ /pets:
95+ get:
96+ parameters:
97+ - name: limit
98+ in: query
99+ required: false
100+ schema:
101+ type: integer
102+ maximum: 30
103+ responses:
104+ "200":
105+ description: ""
106+ headers:
107+ x-next:
108+ schema:
109+ type: string
110+ content:
111+ application/json:
112+ schema:
113+ $ref: "#/components/schemas/Pets"
114+ post:
115+ requestBody:
116+ content:
117+ application/json:
118+ schema:
119+ $ref: "#/components/schemas/Pet"
120+ responses:
121+ "201":
122+ description: ""
123+components:
124+ schemas:
125+ Pet:
126+ type: object
127+ required:
128+ - id
129+ - name
130+ properties:
131+ id:
132+ type: integer
133+ name:
134+ type: string
135+ minLength: 1
136+ maxLength: 15
137+ weight:
138+ type: integer
139+ Pets:
140+ type: array
141+ items:
142+ $ref: "#/components/schemas/Pet"
143+```
144+
145+Looking at the very large and complex API description, you grow more and more concerned that your old mobile app might stop working when you update the server. But the spec is too large and too complex to reasonably assess this manually.
146+
147+## Assessing compatibility automatically
148+
149+Luckily, you have access to compaREST which can programmatically analyze your APIs and determine what, if anything, breaks compatibility and what doesn't.
150+
151+You can call it, passing the API your client will be aware of, and the API your server will serve like so:
152+
153+```bash
154+docker run --rm -v $(pwd):/data:rw typeable/comparest --client /data/api-1.0.0.yaml --server /data/api-1.1.0.yaml --output /data/report.md
155+```
156+
157+Running this command will output a file `report.md`, containing the compatibility report between the two APIs:
158+
159+> # Summary
160+>
161+> | [โš ๏ธ Breaking changes](#breaking-changes) | [๐Ÿ™† Non-breaking changes](#non-breaking-changes) | ๐Ÿคท Unsupported feature changes |
162+> |------------------------------------------|-------------------------------------------------|-------------------------------|
163+> | 5 | 6 | 0 |
164+>
165+> # <span id="breaking-changes"></span>โš ๏ธ Breaking changes
166+>
167+> ## **GET** /pets
168+>
169+> ### ๐Ÿ“ฑโฌ…๏ธ JSON Response โ€“ 200
170+>
171+> #### `$[*].name(String)`
172+>
173+> 1. Maximum length of the string changed from 10 to 15.
174+>
175+> 2. Minimum length of the string changed from 3 to 1.
176+>
177+> ## **POST** /pets
178+>
179+> ### ๐Ÿ“ฑโžก๏ธ JSON Request
180+>
181+> #### `$.weight`
182+>
183+> 1. Values are now limited to the following types:
184+>
185+> - Number
186+>
187+> 2. The property was previously implicitly described by the catch-all
188+> "additional properties" case. It is now explicitly defined.
189+>
190+> #### `$.weight(Number)`
191+>
192+> Value is now a multiple of 1.0.
193+>
194+> # <span id="non-breaking-changes"></span>๐Ÿ™† Non-breaking changes
195+>
196+> ## **GET** /pets
197+>
198+> ### Parameter limit
199+>
200+> #### JSON Schema
201+>
202+> ##### `$(Number)`
203+>
204+> Upper bound changed from 20.0 inclusive to 30.0 inclusive.
205+>
206+> ### ๐Ÿ“ฑโฌ…๏ธ JSON Response โ€“ 200
207+>
208+> #### `$[*].weight`
209+>
210+> 1. Values are now limited to the following types:
211+>
212+> - Number
213+>
214+> 2. The property was previously implicitly described by the catch-all
215+> "additional properties" case. It is now explicitly defined.
216+>
217+> #### `$[*].weight(Number)`
218+>
219+> Value is now a multiple of 1.0.
220+>
221+> ## **POST** /pets
222+>
223+> ### ๐Ÿ“ฑโžก๏ธ JSON Request
224+>
225+> #### `$.name(String)`
226+>
227+> 1. Maximum length of the string changed from 10 to 15.
228+>
229+> 2. Minimum length of the string changed from 3 to 1.
230+
231+You now know exactly in what situations and in what way your 1.0 version of the app will break if you deploy your 1.1 version of the server.
232+
233+## Additional formats
234+
235+You can also produce a self-contained HTML report that you can open in your browser by simply omitting the file extension of the output file:
236+
237+```bash
238+docker run --rm -v $(pwd):/data:rw typeable/comparest --client /data/api-1.0.0.yaml --server /data/api-1.1.0.yaml --output /data/report
239+```
240+
241+# CLI docs
242+
243+```
244+Usage: comparest (-c|--client ARG) (-s|--server ARG)
245+ [--silent | --only-breaking | --all] [-o|--output ARG]
246+ [--folding-block-quotes-style | --header-style]
247+ [--signal-exit-code]
248+ A tool to check compatibility between two OpenAPI specifications.
249+
250+ Usage examples
251+
252+ Compare files old.yaml with new.yaml and output the resulting report to
253+ stdout:
254+
255+ comparest -c old.yaml -s new.yaml
256+
257+ Only output breaking changes and write a styled HTML report to file
258+ report.html:
259+
260+ comparest -c old.yaml -s new.yaml --only-breaking -o report
261+
262+ Don't output anything, only fail if there are breaking changes:
263+
264+ comparest -c old.json -s new.json --silent
265+
266+ Write full report suitable for embedding into a GitHub comment to
267+ report.html:
268+
269+ comparest -c old.json -s new.json --folding-block-quotes-style -o report.html
270+
271+Available options:
272+ -h,--help Show this help text
273+ -c,--client ARG A path to the file containing the specification that
274+ will be used for the client of the API. Can be either
275+ a YAML or JSON file.
276+ -s,--server ARG A path to the file containing the specification that
277+ will be used for the server of the API. Can be either
278+ a YAML or JSON file.
279+ --silent Silence all output. Only makes sense in combination
280+ with --signal-exit-code.
281+ --only-breaking Only report breaking changes in the output.
282+ --all Report both incompatible and compatible changes.
283+ Compatible changes will not trigger a failure exit
284+ code.
285+ -o,--output ARG The file path where the output should be written. If
286+ the option is omitted the result will be written to
287+ stdout.
288+
289+ The file extension is used to determine the type of
290+ the output file.
291+
292+ Supports many formats such as markdown, html, rtf,
293+ doc, txt, rst, and many more.
294+
295+ Leave out the extension to produce a self-contained
296+ HTML report with styling.
297+ --folding-block-quotes-style
298+ The report tree is structured using summary/detail
299+ HTML elements and indented using block quotes. This
300+ style renders well on GitHub.Intended for HTML output
301+ format. Markdown has rendering bugs on GitHub.
302+ --header-style The report tree is structured using increasing levels
303+ of headers.
304+ --signal-exit-code Signal API compatibility with the exit code.
305+
306+ Exit with 0 if there are no breaking changes.
307+ Exit with 1 if there are breaking changes.
308+ Exit with 2 if could not determine compatibility.
309+```
action.yamlnew file+47
@@ -0,0 +1,47 @@
1+name: compaREST
2+author: Typeable
3+description: API reliability checker
4+inputs:
5+ GITHUB_TOKEN:
6+ description: "The GitHub access token (e.g. secrets.GITHUB_TOKEN) used to create or update the comment. This defaults to {{ github.token }}."
7+ default: "${{ github.token }}"
8+ required: false
9+ repo:
10+ description: The owner of the repo in which to post the comment.
11+ default: "${{ github.repository }}"
12+ required: false
13+ project_name:
14+ description: The name of the project to which the API pertains.
15+ required: true
16+ footer:
17+ description: A footer that can be appended to the comment.
18+ required: false
19+ default: ""
20+ old:
21+ description: The path to old specification of the API.
22+ required: true
23+ new:
24+ description: The path to new specification of the API.
25+ required: true
26+ sha:
27+ description: The sha of the commit to post the check for.
28+ required: false
29+ default: "${{ github.event.pull_request.head.sha }}"
30+runs:
31+ using: "docker"
32+ image: "docker://typeable/comparest-github-action:0.0.0.0"
33+ env:
34+ GITHUB_TOKEN: "${{ inputs.GITHUB_TOKEN }}"
35+ REPO: "${{ inputs.repo }}"
36+ PROJECT_NAME: "${{ inputs.project_name }}"
37+ FOOTER: "${{ inputs.footer }}"
38+ ROOT: "/github/workspace"
39+ OLD: "${{ inputs.old }}"
40+ NEW: "${{ inputs.new }}"
41+ SHA: "${{ inputs.sha }}"
42+ pre-entrypoint: "/bin/pre"
43+ entrypoint: "/bin/run"
44+
45+branding:
46+ icon: crosshair
47+ color: gray-dark
app/Data/OpenApi/Compare/Options.hsnew file+134
@@ -0,0 +1,134 @@
1+module Data.OpenApi.Compare.Options
2+ ( Options (..),
3+ OutputMode (..),
4+ parseOptions,
5+ )
6+where
7+
8+import Data.OpenApi.Compare.Report
9+import GHC.Generics (Generic)
10+import Options.Applicative
11+import Options.Applicative.Help hiding (fullDesc)
12+
13+parseOptions :: IO Options
14+parseOptions = customExecParser (prefs $ showHelpOnError) optionsParserInfo
15+
16+data Options = Options
17+ { clientFile :: FilePath
18+ , serverFile :: FilePath
19+ , -- | 'Nothing' means "don't produce any output"
20+ mode :: Maybe ReportMode
21+ , outputMode :: OutputMode
22+ , reportTreeStyle :: ReportTreeStyle
23+ , signalExitCode :: Bool
24+ }
25+ deriving stock (Generic)
26+
27+data OutputMode = StdoutMode | FileMode FilePath
28+
29+optionsParserInfo :: ParserInfo Options
30+optionsParserInfo =
31+ info
32+ (helper <*> optionsParser)
33+ ( fullDesc
34+ <> header "CompaREST"
35+ <> progDescDoc
36+ ( Just $
37+ par "A tool to check compatibility between two OpenAPI specifications."
38+ <$$> hardline <> par "Usage examples" <> hardline
39+ <$$> indent
40+ 4
41+ ( par "Compare files old.yaml with new.yaml and output the resulting report to stdout:"
42+ <$$> hardline <> indent 4 "comparest -c old.yaml -s new.yaml"
43+ <$$> hardline <> par "Only output breaking changes and write a styled HTML report to file report.html:"
44+ <$$> hardline <> indent 4 "comparest -c old.yaml -s new.yaml --only-breaking -o report"
45+ <$$> hardline <> par "Don't output anything, only fail if there are breaking changes:"
46+ <$$> hardline <> indent 4 "comparest -c old.json -s new.json --silent"
47+ <$$> hardline <> par "Write full report suitable for embedding into a GitHub comment to report.html:"
48+ <$$> hardline <> indent 4 "comparest -c old.json -s new.json --folding-block-quotes-style -o report.html"
49+ )
50+ )
51+ )
52+
53+optionsParser :: Parser Options
54+optionsParser =
55+ Options
56+ <$> strOption
57+ ( short 'c'
58+ <> long "client"
59+ <> help
60+ "A path to the file containing the specification that will be \
61+ \used for the client of the API. Can be either a YAML or JSON file."
62+ )
63+ <*> strOption
64+ ( short 's'
65+ <> long "server"
66+ <> help
67+ "A path to the file containing the specification that will be \
68+ \used for the server of the API. Can be either a YAML or JSON file."
69+ )
70+ <*> ( flag'
71+ Nothing
72+ ( long "silent"
73+ <> help "Silence all output. Only makes sense in combination with --signal-exit-code."
74+ )
75+ <|> flag'
76+ (Just OnlyErrors)
77+ ( long "only-breaking"
78+ <> help "Only report breaking changes in the output."
79+ )
80+ <|> flag'
81+ (Just All)
82+ ( long "all"
83+ <> help
84+ "Report both incompatible and compatible changes. \
85+ \Compatible changes will not trigger a failure exit code."
86+ )
87+ <|> pure (Just All)
88+ )
89+ <*> ( ( FileMode
90+ <$> strOption
91+ ( short 'o' <> long "output"
92+ <> helpDoc
93+ ( Just $
94+ par "The file path where the output should be written. If the option is omitted the result will be written to stdout."
95+ <$$> hardline <> par "The file extension is used to determine the type of the output file."
96+ <$$> hardline <> par "Supports many formats such as markdown, html, rtf, doc, txt, rst, and many more."
97+ <$$> hardline <> par "Leave out the extension to produce a self-contained HTML report with styling."
98+ )
99+ )
100+ )
101+ <|> pure StdoutMode
102+ )
103+ <*> ( flag'
104+ FoldingBlockquotesTreeStyle
105+ ( long "folding-block-quotes-style"
106+ <> help
107+ "The report tree is structured using \
108+ \summary/detail HTML elements and indented using \
109+ \block quotes. This style renders well on GitHub.\
110+ \Intended for HTML output format. Markdown has rendering \
111+ \bugs on GitHub."
112+ )
113+ <|> flag'
114+ HeadersTreeStyle
115+ ( long "header-style"
116+ <> help
117+ "The report tree is structured using \
118+ \increasing levels of headers."
119+ )
120+ <|> pure HeadersTreeStyle
121+ )
122+ <*> switch
123+ ( long "signal-exit-code"
124+ <> helpDoc
125+ ( Just $
126+ par "Signal API compatibility with the exit code."
127+ <$$> hardline <> par "Exit with 0 if there are no breaking changes."
128+ <$$> par "Exit with 1 if there are breaking changes."
129+ <$$> par "Exit with 2 if could not determine compatibility."
130+ )
131+ )
132+
133+par :: String -> Doc
134+par = foldr1 (</>) . fmap string . words
app/FormatHeuristic.hs+58โˆ’55
@@ -2,7 +2,7 @@
2-- Originally based on:
2-- Originally based on:
3-- https://github.com/jgm/pandoc/blob/master/src/Text/Pandoc/App/FormatHeuristics.hs
3-- https://github.com/jgm/pandoc/blob/master/src/Text/Pandoc/App/FormatHeuristics.hs
4module FormatHeuristic
4module FormatHeuristic
5โˆ’ ( formatFromFilePath
5+ ( formatFromFilePath,
6 )
6 )
7where
7where
8
8
@@ -10,34 +10,34 @@ import Data.ByteString.Lazy (ByteString)
10import Data.Char (toLower)
10import Data.Char (toLower)
11import Data.Functor
11import Data.Functor
12import qualified Data.Map as M
12import qualified Data.Map as M
13+import qualified Data.OpenApi.Compare.Report.Html.Template as Html
13import Data.Text (Text)
14import Data.Text (Text)
14import qualified Data.Text.Lazy as TL
15import qualified Data.Text.Lazy as TL
15import qualified Data.Text.Lazy.Encoding as TL
16import qualified Data.Text.Lazy.Encoding as TL
16โˆ’import qualified OpenAPI.Checker.Report.Html.Template as Html
17import System.FilePath (takeExtension)
17import System.FilePath (takeExtension)
18import Text.DocTemplates.Internal
18import Text.DocTemplates.Internal
19import Text.Pandoc
19import Text.Pandoc
20
20
21โˆ’formatFromFilePath :: forall m. PandocMonad m => FilePath -> Maybe (Pandoc -> m ByteString)
21+formatFromFilePath :: forall m. PandocMonad m => FilePath -> Maybe (Pandoc -> m ByteString, FilePath)
22formatFromFilePath x =
22formatFromFilePath x =
23 case takeExtension (map toLower x) of
23 case takeExtension (map toLower x) of
24โˆ’ ".adoc" -> f "asciidoc" def
24+ ".adoc" -> fWithDefaultFile "asciidoc" def
25โˆ’ ".asciidoc" -> f "asciidoc" def
25+ ".asciidoc" -> fWithDefaultFile "asciidoc" def
26โˆ’ ".context" -> f "context" def
26+ ".context" -> fWithDefaultFile "context" def
27โˆ’ ".ctx" -> f "context" def
27+ ".ctx" -> fWithDefaultFile "context" def
28โˆ’ ".db" -> f "docbook" def
28+ ".db" -> fWithDefaultFile "docbook" def
29โˆ’ ".doc" -> f "doc" def -- so we get an "unknown reader" error
29+ ".doc" -> fWithDefaultFile "doc" def -- so we get an "unknown reader" error
30โˆ’ ".docx" -> f "docx" def
30+ ".docx" -> fWithDefaultFile "docx" def
31โˆ’ ".dokuwiki" -> f "dokuwiki" def
31+ ".dokuwiki" -> fWithDefaultFile "dokuwiki" def
32โˆ’ ".epub" -> f "epub" def
32+ ".epub" -> fWithDefaultFile "epub" def
33โˆ’ ".fb2" -> f "fb2" def
33+ ".fb2" -> fWithDefaultFile "fb2" def
34โˆ’ ".htm" -> html
34+ ".htm" -> fWithDefaultFile "html" def
35โˆ’ ".html" -> html
35+ ".html" -> fWithDefaultFile "html" def
36โˆ’ ".icml" -> f "icml" def
36+ ".icml" -> fWithDefaultFile "icml" def
37โˆ’ ".json" -> f "json" def
37+ ".json" -> fWithDefaultFile "json" def
38โˆ’ ".latex" -> f "latex" def
38+ ".latex" -> fWithDefaultFile "latex" def
39โˆ’ ".lhs" -> f "markdown+lhs" def
39+ ".lhs" -> fWithDefaultFile "markdown+lhs" def
40โˆ’ ".ltx" -> f "latex" def
40+ ".ltx" -> fWithDefaultFile "latex" def
41 ".markdown" -> markdown
41 ".markdown" -> markdown
42 ".mkdn" -> markdown
42 ".mkdn" -> markdown
43 ".mkd" -> markdown
43 ".mkd" -> markdown
@@ -45,47 +45,50 @@ formatFromFilePath x =
45 ".mdown" -> markdown
45 ".mdown" -> markdown
46 ".Rmd" -> markdown
46 ".Rmd" -> markdown
47 ".md" -> markdown
47 ".md" -> markdown
48โˆ’ ".ms" -> f "ms" def
48+ ".ms" -> fWithDefaultFile "ms" def
49โˆ’ ".muse" -> f "muse" def
49+ ".muse" -> fWithDefaultFile "muse" def
50โˆ’ ".native" -> f "native" def
50+ ".native" -> fWithDefaultFile "native" def
51โˆ’ ".odt" -> f "odt" def
51+ ".odt" -> fWithDefaultFile "odt" def
52โˆ’ ".opml" -> f "opml" def
52+ ".opml" -> fWithDefaultFile "opml" def
53โˆ’ ".org" -> f "org" def
53+ ".org" -> fWithDefaultFile "org" def
54 -- so we get an "unknown reader" error
54 -- so we get an "unknown reader" error
55โˆ’ ".pdf" -> f "pdf" def
55+ ".pdf" -> fWithDefaultFile "pdf" def
56โˆ’ ".pptx" -> f "pptx" def
56+ ".pptx" -> fWithDefaultFile "pptx" def
57โˆ’ ".roff" -> f "ms" def
57+ ".roff" -> fWithDefaultFile "ms" def
58โˆ’ ".rst" -> f "rst" def
58+ ".rst" -> fWithDefaultFile "rst" def
59โˆ’ ".rtf" -> f "rtf" def
59+ ".rtf" -> fWithDefaultFile "rtf" def
60โˆ’ ".s5" -> f "s5" def
60+ ".s5" -> fWithDefaultFile "s5" def
61โˆ’ ".t2t" -> f "t2t" def
61+ ".t2t" -> fWithDefaultFile "t2t" def
62โˆ’ ".tei" -> f "tei" def
62+ ".tei" -> fWithDefaultFile "tei" def
63โˆ’ ".tei.xml" -> f "tei" def
63+ ".tei.xml" -> fWithDefaultFile "tei" def
64โˆ’ ".tex" -> f "latex" def
64+ ".tex" -> fWithDefaultFile "latex" def
65โˆ’ ".texi" -> f "texinfo" def
65+ ".texi" -> fWithDefaultFile "texinfo" def
66โˆ’ ".texinfo" -> f "texinfo" def
66+ ".texinfo" -> fWithDefaultFile "texinfo" def
67 ".text" -> markdown
67 ".text" -> markdown
68โˆ’ ".textile" -> f "textile" def
68+ ".textile" -> fWithDefaultFile "textile" def
69 ".txt" -> markdown
69 ".txt" -> markdown
70โˆ’ ".wiki" -> f "mediawiki" def
70+ ".wiki" -> fWithDefaultFile "mediawiki" def
71โˆ’ ".xhtml" -> f "html" def
71+ ".xhtml" -> fWithDefaultFile "html" def
72โˆ’ ".ipynb" -> f "ipynb" def
72+ ".ipynb" -> fWithDefaultFile "ipynb" def
73โˆ’ ".csv" -> f "csv" def
73+ ".csv" -> fWithDefaultFile "csv" def
74โˆ’ ".bib" -> f "biblatex" def
74+ ".bib" -> fWithDefaultFile "biblatex" def
75โˆ’ ['.', y] | y `elem` ['1' .. '9'] -> f "man" def
75+ ['.', y] | y `elem` ['1' .. '9'] -> fWithDefaultFile "man" def
76+ "" ->
77+ (,x <> ".html")
78+ <$> f
79+ "html"
80+ def
81+ { writerTemplate = Just Html.template
82+ , -- Not actually used. Needed to silence warning.
83+ writerVariables = Context $ M.fromList [("pagetitle", toVal ("CompaREST" :: Text))]
84+ }
76 _ -> Nothing
85 _ -> Nothing
77 where
86 where
78โˆ’ markdown, html :: Maybe (Pandoc -> m ByteString)
87+ markdown :: Maybe (Pandoc -> m ByteString, FilePath)
79โˆ’ markdown = f "markdown" markdownOpt
88+ markdown = fWithDefaultFile "markdown" markdownOpt
80โˆ’ html =
89+
81โˆ’ f
82โˆ’ "html"
83โˆ’ def
84โˆ’ { writerTemplate = Just Html.template
85โˆ’ , -- Not actually used. Needed to silence warning.
86โˆ’ writerVariables = Context $ M.fromList [("pagetitle", toVal ("OpenApi Diff" :: Text))]
87โˆ’ }
88 markdownOpt = def {writerExtensions = githubMarkdownExtensions}
90 markdownOpt = def {writerExtensions = githubMarkdownExtensions}
91+ fWithDefaultFile k opt = (,x) <$> f k opt
89 f k opt =
92 f k opt =
90 lookup k writers <&> \case
93 lookup k writers <&> \case
91 TextWriter g -> fmap (TL.encodeUtf8 . TL.fromStrict) . g opt
94 TextWriter g -> fmap (TL.encodeUtf8 . TL.fromStrict) . g opt
app/Main.hs+20โˆ’10
@@ -5,18 +5,20 @@ import Control.Monad.Except
5import Data.Aeson
5import Data.Aeson
6import qualified Data.ByteString.Lazy as BSL
6import qualified Data.ByteString.Lazy as BSL
7import Data.Default
7import Data.Default
8+import Data.Maybe
9+import Data.OpenApi.Compare.Options
10+import Data.OpenApi.Compare.Run
8import qualified Data.Text.IO as T
11import qualified Data.Text.IO as T
9import qualified Data.Yaml as Yaml
12import qualified Data.Yaml as Yaml
10import FormatHeuristic
13import FormatHeuristic
11โˆ’import OpenAPI.Checker.Options
12โˆ’import OpenAPI.Checker.Run
13import System.Exit
14import System.Exit
14import System.IO
15import System.IO
15import Text.Pandoc hiding (report)
16import Text.Pandoc hiding (report)
17+import Text.Pandoc.Builder
16
18
17main :: IO ()
19main :: IO ()
18main = do
20main = do
19โˆ’ opts <- execParser optionsParserInfo
21+ opts <- parseOptions
20 let parseSchema path =
22 let parseSchema path =
21 eitherDecodeFileStrict path >>= \case
23 eitherDecodeFileStrict path >>= \case
22 Left jsonErr -> do
24 Left jsonErr -> do
@@ -38,13 +40,21 @@ main = do
38 StdoutMode -> lift . T.putStrLn <=< runPandocIO . writeMarkdown options
40 StdoutMode -> lift . T.putStrLn <=< runPandocIO . writeMarkdown options
39 FileMode f -> case formatFromFilePath f of
41 FileMode f -> case formatFromFilePath f of
40 Nothing -> \_ -> throwError UnknownOutputFormat
42 Nothing -> \_ -> throwError UnknownOutputFormat
41โˆ’ Just writer -> lift . BSL.writeFile f <=< runPandocIO . writer
43+ Just (writer, f') -> lift . BSL.writeFile f' <=< runPandocIO . writer
44+ reportConfig =
45+ ReportConfig
46+ { treeStyle = reportTreeStyle opts
47+ , reportMode = fromMaybe All $ mode opts
48+ }
42โˆ’ (report, status) = runReport (a, b)
49+ (report, status) = runReport reportConfig (a, b)
50+ case mode opts of
43โˆ’ either handler pure <=< runExceptT $ write report
51+ Just _ -> either handler pure <=< runExceptT $ write $ doc report
52+ Nothing -> pure ()
53+ when (signalExitCode opts) $
44โˆ’ case status of
54+ case status of
45โˆ’ NoBreakingChanges -> exitSuccess
55+ NoBreakingChanges -> exitSuccess
46โˆ’ BreakingChanges -> exitWith $ ExitFailure 1
56+ BreakingChanges -> exitWith $ ExitFailure 1
47โˆ’ OnlyUnsupportedChanges -> exitWith $ ExitFailure 2
57+ OnlyUnsupportedChanges -> exitWith $ ExitFailure 2
48
58
49data Errors
59data Errors
50 = DocumentError PandocError
60 = DocumentError PandocError
app/OpenAPI/Checker/Options.hsdeletedโˆ’65
@@ -1,65 +0,0 @@
1โˆ’module OpenAPI.Checker.Options
2โˆ’ ( Options (..)
3โˆ’ , Mode (..)
4โˆ’ , OutputMode (..)
5โˆ’ , optionsParserInfo
6โˆ’ , execParser
7โˆ’ )
8โˆ’where
9โˆ’
10โˆ’import GHC.Generics (Generic)
11โˆ’import Options.Applicative
12โˆ’
13โˆ’data Options = Options
14โˆ’ { clientFile :: FilePath
15โˆ’ , serverFile :: FilePath
16โˆ’ , mode :: Mode
17โˆ’ , outputMode :: OutputMode
18โˆ’ }
19โˆ’ deriving stock (Generic)
20โˆ’
21โˆ’data Mode = Silent | OnlyErrors | All
22โˆ’
23โˆ’data OutputMode = StdoutMode | FileMode FilePath
24โˆ’
25โˆ’optionsParserInfo :: ParserInfo Options
26โˆ’optionsParserInfo =
27โˆ’ info
28โˆ’ (helper <*> optionsParser)
29โˆ’ (fullDesc
30โˆ’ <> header "openapi-diff"
31โˆ’ <> progDesc "A tool to check compatibility between two OpenApi specifications.")
32โˆ’
33โˆ’optionsParser :: Parser Options
34โˆ’optionsParser =
35โˆ’ Options
36โˆ’ <$> strOption
37โˆ’ (short 'c'
38โˆ’ <> long "client"
39โˆ’ <> help "The specification that will be used for the client of the API.")
40โˆ’ <*> strOption
41โˆ’ (short 's'
42โˆ’ <> long "server"
43โˆ’ <> help "The specification that will be used for the server of the API.")
44โˆ’ <*> (flag'
45โˆ’ Silent
46โˆ’ (long "silent"
47โˆ’ <> help "Silence all output.")
48โˆ’ <|> flag'
49โˆ’ OnlyErrors
50โˆ’ (long "only-errors"
51โˆ’ <> help "Only report incompatibility errors in the output.")
52โˆ’ <|> flag'
53โˆ’ All
54โˆ’ (long "all"
55โˆ’ <> help
56โˆ’ "Report both incompatible and compatible changes. \
57โˆ’ \Compatible changes will not trigger a failure exit code.")
58โˆ’ <|> pure All)
59โˆ’ <*> (pure StdoutMode
60โˆ’ <|> (FileMode
61โˆ’ <$> strOption
62โˆ’ (short 'o' <> long "output"
63โˆ’ <> help
64โˆ’ "The file path where the output should be writtrn. \
65โˆ’ \Leave blank to output result to stdout.")))
benchmarks/README.mdnew file+27
@@ -0,0 +1,27 @@
1+# OpenApi comparison benchmarks
2+
3+This is a nix expression that automatically downloads, builds and runs multiple OpenAPI comparison tools on the same set of inputs to compare how well they behave.
4+
5+To run the benchmarks run the following command in this directory:
6+
7+```bash
8+nix-build
9+```
10+
11+## The tools
12+
13+| Tool | Output file name |
14+| -------------------------------------------------------------------------- | ------------------------------------------- |
15+| [Typeable CompaREST](https://github.com/typeable/compaREST) | `typeable.md` |
16+| [Atlassian OpenApi Diff](https://bitbucket.org/atlassian/openapi-diff) | `atlassian.json`, `atlassian.error.txt` |
17+| [OpenApi Tools OpenApi Diff](https://github.com/OpenAPITools/openapi-diff) | `openapitools.md`, `openapitools.error.txt` |
18+| [Tufin OpenApi Diff](https://github.com/tufin/oasdiff) | `oasdiff.txt`, `oasdiff.error.txt` |
19+| [Bump](https://bump.sh) | `bump.txt` |
20+
21+## Running with Bump.sh
22+
23+Bump.sh is a closed-source tool that is only available via REST API. To include bump.sh in the benchmark results you have to supply your credentials as arguments:
24+
25+```bash
26+nix-build --argstr bumpToken <TOKEN> --argstr bumpDocumentation <DOCUMENTATION IDENTIFIER>
27+```
benchmarks/atlassian/addDist.patchnew file+10
@@ -0,0 +1,10 @@
1+diff --git a/gulpfile.js b/gulpfile.js
2+index c3161cf..c123cc0 100644
3+--- a/gulpfile.js
4++++ b/gulpfile.js
5+@@ -153,3 +153,5 @@ exports.watch = gulp.series(
6+ exports.watchE2e = function () {
7+ gulp.watch(['build-output/lib/**/*', 'build-output/test/e2e/**/*', 'test/e2e/**/*.json'], gulp.series(e2eTest));
8+ };
9++
10++exports.compileDist = compileDist
benchmarks/atlassian/yarn.locknew file+4918
@@ -0,0 +1,4918 @@
1+# THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY.
2+# yarn lockfile v1
3+
4+
5+"@apidevtools/json-schema-ref-parser@9.0.9", "@apidevtools/json-schema-ref-parser@^9.0.6":
6+ version "9.0.9"
7+ resolved "https://registry.yarnpkg.com/@apidevtools/json-schema-ref-parser/-/json-schema-ref-parser-9.0.9.tgz#d720f9256e3609621280584f2b47ae165359268b"
8+ integrity sha512-GBD2Le9w2+lVFoc4vswGI/TjkNIZSVp7+9xPf+X3uidBfWnAeUWmquteSyt0+VCrhNMWj/FTABISQrD3Z/YA+w==
9+ dependencies:
10+ "@jsdevtools/ono" "^7.1.3"
11+ "@types/json-schema" "^7.0.6"
12+ call-me-maybe "^1.0.1"
13+ js-yaml "^4.1.0"
14+
15+"@apidevtools/openapi-schemas@^2.0.4":
16+ version "2.1.0"
17+ resolved "https://registry.yarnpkg.com/@apidevtools/openapi-schemas/-/openapi-schemas-2.1.0.tgz#9fa08017fb59d80538812f03fc7cac5992caaa17"
18+ integrity sha512-Zc1AlqrJlX3SlpupFGpiLi2EbteyP7fXmUOGup6/DnkRgjP9bgMM/ag+n91rsv0U1Gpz0H3VILA/o3bW7Ua6BQ==
19+
20+"@apidevtools/swagger-methods@^3.0.2":
21+ version "3.0.2"
22+ resolved "https://registry.yarnpkg.com/@apidevtools/swagger-methods/-/swagger-methods-3.0.2.tgz#b789a362e055b0340d04712eafe7027ddc1ac267"
23+ integrity sha512-QAkD5kK2b1WfjDS/UQn/qQkbwF31uqRjPTrsCs5ZG9BQGAkjwvqGFjjPqAuzac/IYzpPtRzjCP1WrTuAIjMrXg==
24+
25+"@apidevtools/swagger-parser@10.0.2":
26+ version "10.0.2"
27+ resolved "https://registry.yarnpkg.com/@apidevtools/swagger-parser/-/swagger-parser-10.0.2.tgz#f4145afb7c3a3bafe0376f003b5c3bdeae17a952"
28+ integrity sha512-JFxcEyp8RlNHgBCE98nwuTkZT6eNFPc1aosWV6wPcQph72TSEEu1k3baJD4/x1qznU+JiDdz8F5pTwabZh+Dhg==
29+ dependencies:
30+ "@apidevtools/json-schema-ref-parser" "^9.0.6"
31+ "@apidevtools/openapi-schemas" "^2.0.4"
32+ "@apidevtools/swagger-methods" "^3.0.2"
33+ "@jsdevtools/ono" "^7.1.3"
34+ call-me-maybe "^1.0.1"
35+ z-schema "^4.2.3"
36+
37+"@babel/code-frame@^7.0.0":
38+ version "7.14.5"
39+ resolved "https://registry.yarnpkg.com/@babel/code-frame/-/code-frame-7.14.5.tgz#23b08d740e83f49c5e59945fbf1b43e80bbf4edb"
40+ integrity sha512-9pzDqyc6OLDaqe+zbACgFkb6fKMNG6CObKpnYXChRsvYGyEdc7CA2BaqeOM+vOtCS5ndmJicPJhKAwYRI6UfFw==
41+ dependencies:
42+ "@babel/highlight" "^7.14.5"
43+
44+"@babel/helper-validator-identifier@^7.14.5":
45+ version "7.14.5"
46+ resolved "https://registry.yarnpkg.com/@babel/helper-validator-identifier/-/helper-validator-identifier-7.14.5.tgz#d0f0e277c512e0c938277faa85a3968c9a44c0e8"
47+ integrity sha512-5lsetuxCLilmVGyiLEfoHBRX8UCFD+1m2x3Rj97WrW3V7H3u4RWRXA4evMjImCsin2J2YT0QaVDGf+z8ondbAg==
48+
49+"@babel/highlight@^7.14.5":
50+ version "7.14.5"
51+ resolved "https://registry.yarnpkg.com/@babel/highlight/-/highlight-7.14.5.tgz#6861a52f03966405001f6aa534a01a24d99e8cd9"
52+ integrity sha512-qf9u2WFWVV0MppaL877j2dBtQIDgmidgjGk5VIMw3OadXvYaXn66U1BFlH2t4+t3i+8PhedppRv+i40ABzd+gg==
53+ dependencies:
54+ "@babel/helper-validator-identifier" "^7.14.5"
55+ chalk "^2.0.0"
56+ js-tokens "^4.0.0"
57+
58+"@commitlint/cli@^8.3.5":
59+ version "8.3.5"
60+ resolved "https://registry.yarnpkg.com/@commitlint/cli/-/cli-8.3.5.tgz#6d93a3a8b2437fa978999d3f6a336bcc70be3fd3"
61+ integrity sha512-6+L0vbw55UEdht71pgWOE55SRgb+8OHcEwGDB234VlIBFGK9P2QOBU7MHiYJ5cjdjCQ0rReNrGjOHmJ99jwf0w==
62+ dependencies:
63+ "@commitlint/format" "^8.3.4"
64+ "@commitlint/lint" "^8.3.5"
65+ "@commitlint/load" "^8.3.5"
66+ "@commitlint/read" "^8.3.4"
67+ babel-polyfill "6.26.0"
68+ chalk "2.4.2"
69+ get-stdin "7.0.0"
70+ lodash "4.17.15"
71+ meow "5.0.0"
72+ resolve-from "5.0.0"
73+ resolve-global "1.0.0"
74+
75+"@commitlint/config-conventional@^8.3.4":
76+ version "8.3.4"
77+ resolved "https://registry.yarnpkg.com/@commitlint/config-conventional/-/config-conventional-8.3.4.tgz#fed13b3711690663b176c1f6b39c205a565618d2"
78+ integrity sha512-w0Yc5+aVAjZgjYqx29igBOnVCj8O22gy3Vo6Fyp7PwoS7+AYS1x3sN7IBq6i7Ae15Mv5P+rEx1pkxXo5zOMe4g==
79+ dependencies:
80+ conventional-changelog-conventionalcommits "4.2.1"
81+
82+"@commitlint/ensure@^8.3.4":
83+ version "8.3.4"
84+ resolved "https://registry.yarnpkg.com/@commitlint/ensure/-/ensure-8.3.4.tgz#6931677e4ca0fde71686ae3b7a367261647a341d"
85+ integrity sha512-8NW77VxviLhD16O3EUd02lApMFnrHexq10YS4F4NftNoErKbKaJ0YYedktk2boKrtNRf/gQHY/Qf65edPx4ipw==
86+ dependencies:
87+ lodash "4.17.15"
88+
89+"@commitlint/execute-rule@^8.3.4":
90+ version "8.3.4"
91+ resolved "https://registry.yarnpkg.com/@commitlint/execute-rule/-/execute-rule-8.3.4.tgz#1b63f0713b197889d90b76f9eea1abc010d256b1"
92+ integrity sha512-f4HigYjeIBn9f7OuNv5zh2y5vWaAhNFrfeul8CRJDy82l3Y+09lxOTGxfF3uMXKrZq4LmuK6qvvRCZ8mUrVvzQ==
93+
94+"@commitlint/format@^8.3.4":
95+ version "8.3.4"
96+ resolved "https://registry.yarnpkg.com/@commitlint/format/-/format-8.3.4.tgz#7cd1f0ba5a3289c8d14d7dac29ee1fc1597fe1d9"
97+ integrity sha512-809wlQ/ND6CLZON+w2Rb3YM2TLNDfU2xyyqpZeqzf2reJNpySMSUAeaO/fNDJSOKIsOsR3bI01rGu6hv28k+Nw==
98+ dependencies:
99+ chalk "^2.0.1"
100+
101+"@commitlint/is-ignored@^8.3.5":
102+ version "8.3.5"
103+ resolved "https://registry.yarnpkg.com/@commitlint/is-ignored/-/is-ignored-8.3.5.tgz#e6f59496e1b1ce58020d519cd578ad0f43169199"
104+ integrity sha512-Zo+8a6gJLFDTqyNRx53wQi/XTiz8mncvmWf/4oRG+6WRcBfjSSHY7KPVj5Y6UaLy2EgZ0WQ2Tt6RdTDeQiQplA==
105+ dependencies:
106+ semver "6.3.0"
107+
108+"@commitlint/lint@^8.3.5":
109+ version "8.3.5"
110+ resolved "https://registry.yarnpkg.com/@commitlint/lint/-/lint-8.3.5.tgz#627e75adb1cc803cc723e33cc2ba4aa27cbb9f0c"
111+ integrity sha512-02AkI0a6PU6rzqUvuDkSi6rDQ2hUgkq9GpmdJqfai5bDbxx2939mK4ZO+7apbIh4H6Pae7EpYi7ffxuJgm+3hQ==
112+ dependencies:
113+ "@commitlint/is-ignored" "^8.3.5"
114+ "@commitlint/parse" "^8.3.4"
115+ "@commitlint/rules" "^8.3.4"
116+ babel-runtime "^6.23.0"
117+ lodash "4.17.15"
118+
119+"@commitlint/load@^8.3.5":
120+ version "8.3.5"
121+ resolved "https://registry.yarnpkg.com/@commitlint/load/-/load-8.3.5.tgz#3f059225ede92166ba94cf4c48e3d67c8b08b18a"
122+ integrity sha512-poF7R1CtQvIXRmVIe63FjSQmN9KDqjRtU5A6hxqXBga87yB2VUJzic85TV6PcQc+wStk52cjrMI+g0zFx+Zxrw==
123+ dependencies:
124+ "@commitlint/execute-rule" "^8.3.4"
125+ "@commitlint/resolve-extends" "^8.3.5"
126+ babel-runtime "^6.23.0"
127+ chalk "2.4.2"
128+ cosmiconfig "^5.2.0"
129+ lodash "4.17.15"
130+ resolve-from "^5.0.0"
131+
132+"@commitlint/message@^8.3.4":
133+ version "8.3.4"
134+ resolved "https://registry.yarnpkg.com/@commitlint/message/-/message-8.3.4.tgz#b4e50d14aa6e15a5ad0767b952a7953f3681d768"
135+ integrity sha512-nEj5tknoOKXqBsaQtCtgPcsAaf5VCg3+fWhss4Vmtq40633xLq0irkdDdMEsYIx8rGR0XPBTukqzln9kAWCkcA==
136+
137+"@commitlint/parse@^8.3.4":
138+ version "8.3.4"
139+ resolved "https://registry.yarnpkg.com/@commitlint/parse/-/parse-8.3.4.tgz#d741f8b9104b35d0f4c10938165b20cbf167f81e"
140+ integrity sha512-b3uQvpUQWC20EBfKSfMRnyx5Wc4Cn778bVeVOFErF/cXQK725L1bYFvPnEjQO/GT8yGVzq2wtLaoEqjm1NJ/Bw==
141+ dependencies:
142+ conventional-changelog-angular "^1.3.3"
143+ conventional-commits-parser "^3.0.0"
144+ lodash "^4.17.11"
145+
146+"@commitlint/read@^8.3.4":
147+ version "8.3.4"
148+ resolved "https://registry.yarnpkg.com/@commitlint/read/-/read-8.3.4.tgz#81a34283d8cd7b2acdf57829a91761e9c7791455"
149+ integrity sha512-FKv1kHPrvcAG5j+OSbd41IWexsbLhfIXpxVC/YwQZO+FR0EHmygxQNYs66r+GnhD1EfYJYM4WQIqd5bJRx6OIw==
150+ dependencies:
151+ "@commitlint/top-level" "^8.3.4"
152+ "@marionebl/sander" "^0.6.0"
153+ babel-runtime "^6.23.0"
154+ git-raw-commits "^2.0.0"
155+
156+"@commitlint/resolve-extends@^8.3.5":
157+ version "8.3.5"
158+ resolved "https://registry.yarnpkg.com/@commitlint/resolve-extends/-/resolve-extends-8.3.5.tgz#8fff800f292ac217ae30b1862f5f9a84b278310a"
159+ integrity sha512-nHhFAK29qiXNe6oH6uG5wqBnCR+BQnxlBW/q5fjtxIaQALgfoNLHwLS9exzbIRFqwJckpR6yMCfgMbmbAOtklQ==
160+ dependencies:
161+ import-fresh "^3.0.0"
162+ lodash "4.17.15"
163+ resolve-from "^5.0.0"
164+ resolve-global "^1.0.0"
165+
166+"@commitlint/rules@^8.3.4":
167+ version "8.3.4"
168+ resolved "https://registry.yarnpkg.com/@commitlint/rules/-/rules-8.3.4.tgz#41da7e16c6b89af268fe81c87a158c1fd2ac82b1"
169+ integrity sha512-xuC9dlqD5xgAoDFgnbs578cJySvwOSkMLQyZADb1xD5n7BNcUJfP8WjT9W1Aw8K3Wf8+Ym/ysr9FZHXInLeaRg==
170+ dependencies:
171+ "@commitlint/ensure" "^8.3.4"
172+ "@commitlint/message" "^8.3.4"
173+ "@commitlint/to-lines" "^8.3.4"
174+ babel-runtime "^6.23.0"
175+
176+"@commitlint/to-lines@^8.3.4":
177+ version "8.3.4"
178+ resolved "https://registry.yarnpkg.com/@commitlint/to-lines/-/to-lines-8.3.4.tgz#ce24963b6d86dbe51d88d5e3028ab28f38562e2e"
179+ integrity sha512-5AvcdwRsMIVq0lrzXTwpbbG5fKRTWcHkhn/hCXJJ9pm1JidsnidS1y0RGkb3O50TEHGewhXwNoavxW9VToscUA==
180+
181+"@commitlint/top-level@^8.3.4":
182+ version "8.3.4"
183+ resolved "https://registry.yarnpkg.com/@commitlint/top-level/-/top-level-8.3.4.tgz#803fc6e8f5be5efa5f3551761acfca961f1d8685"
184+ integrity sha512-nOaeLBbAqSZNpKgEtO6NAxmui1G8ZvLG+0wb4rvv6mWhPDzK1GNZkCd8FUZPahCoJ1iHDoatw7F8BbJLg4nDjg==
185+ dependencies:
186+ find-up "^4.0.0"
187+
188+"@hutson/parse-repository-url@^3.0.0":
189+ version "3.0.2"
190+ resolved "https://registry.yarnpkg.com/@hutson/parse-repository-url/-/parse-repository-url-3.0.2.tgz#98c23c950a3d9b6c8f0daed06da6c3af06981340"
191+ integrity sha512-H9XAx3hc0BQHY6l+IFSWHDySypcXsvsuLhgYLUGywmJ5pswRVQJUHpOsobnLYp2ZUaUlKiKDrgWWhosOwAEM8Q==
192+
193+"@jsdevtools/ono@^7.1.3":
194+ version "7.1.3"
195+ resolved "https://registry.yarnpkg.com/@jsdevtools/ono/-/ono-7.1.3.tgz#9df03bbd7c696a5c58885c34aa06da41c8543796"
196+ integrity sha512-4JQNk+3mVzK3xh2rqd6RB4J46qUR19azEHBneZyTZM+c456qOrbbM/5xcR8huNCCcbVt7+UmizG6GuUvPvKUYg==
197+
198+"@marionebl/sander@^0.6.0":
199+ version "0.6.1"
200+ resolved "https://registry.yarnpkg.com/@marionebl/sander/-/sander-0.6.1.tgz#1958965874f24bc51be48875feb50d642fc41f7b"
201+ integrity sha1-GViWWHTyS8Ub5Ih1/rUNZC/EH3s=
202+ dependencies:
203+ graceful-fs "^4.1.3"
204+ mkdirp "^0.5.1"
205+ rimraf "^2.5.2"
206+
207+"@nodelib/fs.scandir@2.1.5":
208+ version "2.1.5"
209+ resolved "https://registry.yarnpkg.com/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz#7619c2eb21b25483f6d167548b4cfd5a7488c3d5"
210+ integrity sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==
211+ dependencies:
212+ "@nodelib/fs.stat" "2.0.5"
213+ run-parallel "^1.1.9"
214+
215+"@nodelib/fs.stat@2.0.5", "@nodelib/fs.stat@^2.0.2":
216+ version "2.0.5"
217+ resolved "https://registry.yarnpkg.com/@nodelib/fs.stat/-/fs.stat-2.0.5.tgz#5bd262af94e9d25bd1e71b05deed44876a222e8b"
218+ integrity sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==
219+
220+"@nodelib/fs.walk@^1.2.3":
221+ version "1.2.7"
222+ resolved "https://registry.yarnpkg.com/@nodelib/fs.walk/-/fs.walk-1.2.7.tgz#94c23db18ee4653e129abd26fb06f870ac9e1ee2"
223+ integrity sha512-BTIhocbPBSrRmHxOAJFtR18oLhxTtAFDAvL8hY1S3iU8k+E60W/YFs4jrixGzQjMpF4qPXxIQHcjVD9dz1C2QA==
224+ dependencies:
225+ "@nodelib/fs.scandir" "2.1.5"
226+ fastq "^1.6.0"
227+
228+"@types/body-parser@*":
229+ version "1.19.0"
230+ resolved "https://registry.yarnpkg.com/@types/body-parser/-/body-parser-1.19.0.tgz#0685b3c47eb3006ffed117cdd55164b61f80538f"
231+ integrity sha512-W98JrE0j2K78swW4ukqMleo8R7h/pFETjM2DQ90MF6XK2i4LO4W3gQ71Lt4w3bfm2EvVSyWHplECvB5sK22yFQ==
232+ dependencies:
233+ "@types/connect" "*"
234+ "@types/node" "*"
235+
236+"@types/caseless@*":
237+ version "0.12.2"
238+ resolved "https://registry.yarnpkg.com/@types/caseless/-/caseless-0.12.2.tgz#f65d3d6389e01eeb458bd54dc8f52b95a9463bc8"
239+ integrity sha512-6ckxMjBBD8URvjB6J3NcnuAn5Pkl7t3TizAg+xdlzzQGSPSmBcXf8KoIH0ua/i+tio+ZRUHEXp0HEmvaR4kt0w==
240+
241+"@types/connect@*":
242+ version "3.4.34"
243+ resolved "https://registry.yarnpkg.com/@types/connect/-/connect-3.4.34.tgz#170a40223a6d666006d93ca128af2beb1d9b1901"
244+ integrity sha512-ePPA/JuI+X0vb+gSWlPKOY0NdNAie/rPUqX2GUPpbZwiKTkSPhjXWuee47E4MtE54QVzGCQMQkAL6JhV2E1+cQ==
245+ dependencies:
246+ "@types/node" "*"
247+
248+"@types/express-serve-static-core@^4.17.18":
249+ version "4.17.22"
250+ resolved "https://registry.yarnpkg.com/@types/express-serve-static-core/-/express-serve-static-core-4.17.22.tgz#e011c55de3f17ddf1161f790042a15c5a218744d"
251+ integrity sha512-WdqmrUsRS4ootGha6tVwk/IVHM1iorU8tGehftQD2NWiPniw/sm7xdJOIlXLwqdInL9wBw/p7oO8vaYEF3NDmA==
252+ dependencies:
253+ "@types/node" "*"
254+ "@types/qs" "*"
255+ "@types/range-parser" "*"
256+
257+"@types/express@^4.17.8":
258+ version "4.17.12"
259+ resolved "https://registry.yarnpkg.com/@types/express/-/express-4.17.12.tgz#4bc1bf3cd0cfe6d3f6f2853648b40db7d54de350"
260+ integrity sha512-pTYas6FrP15B1Oa0bkN5tQMNqOcVXa9j4FTFtO8DWI9kppKib+6NJtfTOOLcwxuuYvcX2+dVG6et1SxW/Kc17Q==
261+ dependencies:
262+ "@types/body-parser" "*"
263+ "@types/express-serve-static-core" "^4.17.18"
264+ "@types/qs" "*"
265+ "@types/serve-static" "*"
266+
267+"@types/fancy-log@1.3.0":
268+ version "1.3.0"
269+ resolved "https://registry.yarnpkg.com/@types/fancy-log/-/fancy-log-1.3.0.tgz#a61ab476e5e628cd07a846330df53b85e05c8ce0"
270+ integrity sha512-mQjDxyOM1Cpocd+vm1kZBP7smwKZ4TNokFeds9LV7OZibmPJFEzY3+xZMrKfUdNT71lv8GoCPD6upKwHxubClw==
271+
272+"@types/jasmine@^3.5.14":
273+ version "3.7.7"
274+ resolved "https://registry.yarnpkg.com/@types/jasmine/-/jasmine-3.7.7.tgz#56718af036be3c9f86eca560a22e39440b2b0784"
275+ integrity sha512-yZzGe1d1T0y+imXDZ79F030nn8qbmiwpWKCZKvKN0KbTzwXAVYShUxkIxu1ba+vhIdabTGVGCfbtZC0oOam8TQ==
276+
277+"@types/js-yaml@^4.0.0":
278+ version "4.0.1"
279+ resolved "https://registry.yarnpkg.com/@types/js-yaml/-/js-yaml-4.0.1.tgz#5544730b65a480b18ace6b6ce914e519cec2d43b"
280+ integrity sha512-xdOvNmXmrZqqPy3kuCQ+fz6wA0xU5pji9cd1nDrflWaAWtYLLGk5ykW0H6yg5TVyehHP1pfmuuSaZkhP+kspVA==
281+
282+"@types/json-schema@^7.0.6":
283+ version "7.0.7"
284+ resolved "https://registry.yarnpkg.com/@types/json-schema/-/json-schema-7.0.7.tgz#98a993516c859eb0d5c4c8f098317a9ea68db9ad"
285+ integrity sha512-cxWFQVseBm6O9Gbw1IWb8r6OS4OhSt3hPZLkFApLjM8TEXROBuQGLAH2i2gZpcXdLBIrpXuTDhH7Vbm1iXmNGA==
286+
287+"@types/lodash@^4.14.162":
288+ version "4.14.170"
289+ resolved "https://registry.yarnpkg.com/@types/lodash/-/lodash-4.14.170.tgz#0d67711d4bf7f4ca5147e9091b847479b87925d6"
290+ integrity sha512-bpcvu/MKHHeYX+qeEN8GE7DIravODWdACVA1ctevD8CN24RhPZIKMn9ntfAsrvLfSX3cR5RrBKAbYm9bGs0A+Q==
291+
292+"@types/mime@^1":
293+ version "1.3.2"
294+ resolved "https://registry.yarnpkg.com/@types/mime/-/mime-1.3.2.tgz#93e25bf9ee75fe0fd80b594bc4feb0e862111b5a"
295+ integrity sha512-YATxVxgRqNH6nHEIsvg6k2Boc1JHI9ZbH5iWFFv/MTkchz3b1ieGDa5T0a9RznNdI0KhVbdbWSN+KWWrQZRxTw==
296+
297+"@types/minimatch@^3.0.3":
298+ version "3.0.4"
299+ resolved "https://registry.yarnpkg.com/@types/minimatch/-/minimatch-3.0.4.tgz#f0ec25dbf2f0e4b18647313ac031134ca5b24b21"
300+ integrity sha512-1z8k4wzFnNjVK/tlxvrWuK5WMt6mydWWP7+zvH5eFep4oj+UkrfiJTRtjCeBXNpwaA/FYqqtb4/QS4ianFpIRA==
301+
302+"@types/minimist@^1.2.0":
303+ version "1.2.1"
304+ resolved "https://registry.yarnpkg.com/@types/minimist/-/minimist-1.2.1.tgz#283f669ff76d7b8260df8ab7a4262cc83d988256"
305+ integrity sha512-fZQQafSREFyuZcdWFAExYjBiCL7AUCdgsk80iO0q4yihYYdcIiH28CcuPTGFgLOCC8RlW49GSQxdHwZP+I7CNg==
306+
307+"@types/node@*":
308+ version "16.0.0"
309+ resolved "https://registry.yarnpkg.com/@types/node/-/node-16.0.0.tgz#067a6c49dc7a5c2412a505628e26902ae967bf6f"
310+ integrity sha512-TmCW5HoZ2o2/z2EYi109jLqIaPIi9y/lc2LmDCWzuCi35bcaQ+OtUh6nwBiFK7SOu25FAU5+YKdqFZUwtqGSdg==
311+
312+"@types/node@^10.17.39":
313+ version "10.17.60"
314+ resolved "https://registry.yarnpkg.com/@types/node/-/node-10.17.60.tgz#35f3d6213daed95da7f0f73e75bcc6980e90597b"
315+ integrity sha512-F0KIgDJfy2nA3zMLmWGKxcH2ZVEtCZXHHdOQs2gSaQ27+lNeEfGxzkIw90aXswATX7AZ33tahPbzy6KAfUreVw==
316+
317+"@types/normalize-package-data@^2.4.0":
318+ version "2.4.0"
319+ resolved "https://registry.yarnpkg.com/@types/normalize-package-data/-/normalize-package-data-2.4.0.tgz#e486d0d97396d79beedd0a6e33f4534ff6b4973e"
320+ integrity sha512-f5j5b/Gf71L+dbqxIpQ4Z2WlmI/mPJ0fOkGGmFgtb6sAu97EPczzbS3/tJKxmcYDj55OX6ssqwDAWOHIYDRDGA==
321+
322+"@types/qs@*":
323+ version "6.9.6"
324+ resolved "https://registry.yarnpkg.com/@types/qs/-/qs-6.9.6.tgz#df9c3c8b31a247ec315e6996566be3171df4b3b1"
325+ integrity sha512-0/HnwIfW4ki2D8L8c9GVcG5I72s9jP5GSLVF0VIXDW00kmIpA6O33G7a8n59Tmh7Nz0WUC3rSb7PTY/sdW2JzA==
326+
327+"@types/range-parser@*":
328+ version "1.2.3"
329+ resolved "https://registry.yarnpkg.com/@types/range-parser/-/range-parser-1.2.3.tgz#7ee330ba7caafb98090bece86a5ee44115904c2c"
330+ integrity sha512-ewFXqrQHlFsgc09MK5jP5iR7vumV/BYayNC6PgJO2LPe8vrnNFyjQjSppfEngITi0qvfKtzFvgKymGheFM9UOA==
331+
332+"@types/request@^2.48.5":
333+ version "2.48.5"
334+ resolved "https://registry.yarnpkg.com/@types/request/-/request-2.48.5.tgz#019b8536b402069f6d11bee1b2c03e7f232937a0"
335+ integrity sha512-/LO7xRVnL3DxJ1WkPGDQrp4VTV1reX9RkC85mJ+Qzykj2Bdw+mG15aAfDahc76HtknjzE16SX/Yddn6MxVbmGQ==
336+ dependencies:
337+ "@types/caseless" "*"
338+ "@types/node" "*"
339+ "@types/tough-cookie" "*"
340+ form-data "^2.5.0"
341+
342+"@types/serve-static@*":
343+ version "1.13.9"
344+ resolved "https://registry.yarnpkg.com/@types/serve-static/-/serve-static-1.13.9.tgz#aacf28a85a05ee29a11fb7c3ead935ac56f33e4e"
345+ integrity sha512-ZFqF6qa48XsPdjXV5Gsz0Zqmux2PerNd3a/ktL45mHpa19cuMi/cL8tcxdAx497yRh+QtYPuofjT9oWw9P7nkA==
346+ dependencies:
347+ "@types/mime" "^1"
348+ "@types/node" "*"
349+
350+"@types/swagger-schema-official@^2.0.21":
351+ version "2.0.22"
352+ resolved "https://registry.yarnpkg.com/@types/swagger-schema-official/-/swagger-schema-official-2.0.22.tgz#f7e06168e6994574dfd86928ac04b196870ab043"
353+ integrity sha512-7yQiX6MWSFSvc/1wW5smJMZTZ4fHOd+hqLr3qr/HONDxHEa2bnYAsOcGBOEqFIjd4yetwMOdEDdeW+udRAQnHA==
354+
355+"@types/tough-cookie@*":
356+ version "4.0.1"
357+ resolved "https://registry.yarnpkg.com/@types/tough-cookie/-/tough-cookie-4.0.1.tgz#8f80dd965ad81f3e1bc26d6f5c727e132721ff40"
358+ integrity sha512-Y0K95ThC3esLEYD6ZuqNek29lNX2EM1qxV8y2FTLUB0ff5wWrk7az+mLrnNFUnaXcgKye22+sFBRXOgpPILZNg==
359+
360+"@types/verror@^1.10.4":
361+ version "1.10.5"
362+ resolved "https://registry.yarnpkg.com/@types/verror/-/verror-1.10.5.tgz#2a1413aded46e67a1fe2386800e291123ed75eb1"
363+ integrity sha512-9UjMCHK5GPgQRoNbqdLIAvAy0EInuiqbW0PBMtVP6B5B2HQJlvoJHM+KodPZMEjOa5VkSc+5LH7xy+cUzQdmHw==
364+
365+JSONStream@^1.0.4:
366+ version "1.3.5"
367+ resolved "https://registry.yarnpkg.com/JSONStream/-/JSONStream-1.3.5.tgz#3208c1f08d3a4d99261ab64f92302bc15e111ca0"
368+ integrity sha512-E+iruNOY8VV9s4JEbe1aNEm6MiszPRr/UfcHMz0TQh1BXSxHK+ASV1R6W4HpjBhSeS+54PIsAMCBmwD06LLsqQ==
369+ dependencies:
370+ jsonparse "^1.2.0"
371+ through ">=2.2.7 <3"
372+
373+accepts@~1.3.7:
374+ version "1.3.7"
375+ resolved "https://registry.yarnpkg.com/accepts/-/accepts-1.3.7.tgz#531bc726517a3b2b41f850021c6cc15eaab507cd"
376+ integrity sha512-Il80Qs2WjYlJIBNzNkK6KYqlVMTbZLXgHx2oT0pU/fjRHyEp+PEfEPY0R3WCwAGVOtauxh1hOxNgIf5bv7dQpA==
377+ dependencies:
378+ mime-types "~2.1.24"
379+ negotiator "0.6.2"
380+
381+add-stream@^1.0.0:
382+ version "1.0.0"
383+ resolved "https://registry.yarnpkg.com/add-stream/-/add-stream-1.0.0.tgz#6a7990437ca736d5e1288db92bd3266d5f5cb2aa"
384+ integrity sha1-anmQQ3ynNtXhKI25K9MmbV9csqo=
385+
386+aggregate-error@^3.0.0:
387+ version "3.1.0"
388+ resolved "https://registry.yarnpkg.com/aggregate-error/-/aggregate-error-3.1.0.tgz#92670ff50f5359bdb7a3e0d40d0ec30c5737687a"
389+ integrity sha512-4I7Td01quW/RpocfNayFdFVk1qSuoh0E7JrbRJ16nH01HhKFQ88INq9Sd+nd72zqRySlr9BmDA8xlEJ6vJMrYA==
390+ dependencies:
391+ clean-stack "^2.0.0"
392+ indent-string "^4.0.0"
393+
394+ajv@^6.12.3:
395+ version "6.12.6"
396+ resolved "https://registry.yarnpkg.com/ajv/-/ajv-6.12.6.tgz#baf5a62e802b07d977034586f8c3baf5adf26df4"
397+ integrity sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==
398+ dependencies:
399+ fast-deep-equal "^3.1.1"
400+ fast-json-stable-stringify "^2.0.0"
401+ json-schema-traverse "^0.4.1"
402+ uri-js "^4.2.2"
403+
404+ansi-colors@^1.0.1:
405+ version "1.1.0"
406+ resolved "https://registry.yarnpkg.com/ansi-colors/-/ansi-colors-1.1.0.tgz#6374b4dd5d4718ff3ce27a671a3b1cad077132a9"
407+ integrity sha512-SFKX67auSNoVR38N3L+nvsPjOE0bybKTYbkf5tRvushrAPQ9V75huw0ZxBkKVeRU9kqH3d6HA4xTckbwZ4ixmA==
408+ dependencies:
409+ ansi-wrap "^0.1.0"
410+
411+ansi-colors@^3.0.5:
412+ version "3.2.4"
413+ resolved "https://registry.yarnpkg.com/ansi-colors/-/ansi-colors-3.2.4.tgz#e3a3da4bfbae6c86a9c285625de124a234026fbf"
414+ integrity sha512-hHUXGagefjN2iRrID63xckIvotOXOojhQKWIPUZ4mNUZ9nLZW+7FMNoE1lOkEhNWYsx/7ysGIuJYCiMAA9FnrA==
415+
416+ansi-colors@^4.1.1:
417+ version "4.1.1"
418+ resolved "https://registry.yarnpkg.com/ansi-colors/-/ansi-colors-4.1.1.tgz#cbb9ae256bf750af1eab344f229aa27fe94ba348"
419+ integrity sha512-JoX0apGbHaUJBNl6yF+p6JAFYZ666/hhCGKN5t9QFjbJQKUU/g8MNbFDbvfrgKXvI1QpZplPOnwIo99lX/AAmA==
420+
421+ansi-cyan@^0.1.1:
422+ version "0.1.1"
423+ resolved "https://registry.yarnpkg.com/ansi-cyan/-/ansi-cyan-0.1.1.tgz#538ae528af8982f28ae30d86f2f17456d2609873"
424+ integrity sha1-U4rlKK+JgvKK4w2G8vF0VtJgmHM=
425+ dependencies:
426+ ansi-wrap "0.1.0"
427+
428+ansi-gray@^0.1.1:
429+ version "0.1.1"
430+ resolved "https://registry.yarnpkg.com/ansi-gray/-/ansi-gray-0.1.1.tgz#2962cf54ec9792c48510a3deb524436861ef7251"
431+ integrity sha1-KWLPVOyXksSFEKPetSRDaGHvclE=
432+ dependencies:
433+ ansi-wrap "0.1.0"
434+
435+ansi-red@^0.1.1:
436+ version "0.1.1"
437+ resolved "https://registry.yarnpkg.com/ansi-red/-/ansi-red-0.1.1.tgz#8c638f9d1080800a353c9c28c8a81ca4705d946c"
438+ integrity sha1-jGOPnRCAgAo1PJwoyKgcpHBdlGw=
439+ dependencies:
440+ ansi-wrap "0.1.0"
441+
442+ansi-regex@^2.0.0:
443+ version "2.1.1"
444+ resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-2.1.1.tgz#c3b33ab5ee360d86e0e628f0468ae7ef27d654df"
445+ integrity sha1-w7M6te42DYbg5ijwRorn7yfWVN8=
446+
447+ansi-styles@^3.2.1:
448+ version "3.2.1"
449+ resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-3.2.1.tgz#41fbb20243e50b12be0f04b8dedbf07520ce841d"
450+ integrity sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==
451+ dependencies:
452+ color-convert "^1.9.0"
453+
454+ansi-wrap@0.1.0, ansi-wrap@^0.1.0:
455+ version "0.1.0"
456+ resolved "https://registry.yarnpkg.com/ansi-wrap/-/ansi-wrap-0.1.0.tgz#a82250ddb0015e9a27ca82e82ea603bbfa45efaf"
457+ integrity sha1-qCJQ3bABXponyoLoLqYDu/pF768=
458+
459+any-shell-escape@^0.1.1:
460+ version "0.1.1"
461+ resolved "https://registry.yarnpkg.com/any-shell-escape/-/any-shell-escape-0.1.1.tgz#d55ab972244c71a9a5e1ab0879f30bf110806959"
462+ integrity sha1-1Vq5ciRMcaml4asIefML8RCAaVk=
463+
464+anymatch@^2.0.0:
465+ version "2.0.0"
466+ resolved "https://registry.yarnpkg.com/anymatch/-/anymatch-2.0.0.tgz#bcb24b4f37934d9aa7ac17b4adaf89e7c76ef2eb"
467+ integrity sha512-5teOsQWABXHHBFP9y3skS5P3d/WfWXpv3FUpy+LorMrNYaT9pI4oLMQX7jzQ2KklNpGpWHzdCXTDT2Y3XGlZBw==
468+ dependencies:
469+ micromatch "^3.1.4"
470+ normalize-path "^2.1.1"
471+
472+append-buffer@^1.0.2:
473+ version "1.0.2"
474+ resolved "https://registry.yarnpkg.com/append-buffer/-/append-buffer-1.0.2.tgz#d8220cf466081525efea50614f3de6514dfa58f1"
475+ integrity sha1-2CIM9GYIFSXv6lBhTz3mUU36WPE=
476+ dependencies:
477+ buffer-equal "^1.0.0"
478+
479+archy@^1.0.0:
480+ version "1.0.0"
481+ resolved "https://registry.yarnpkg.com/archy/-/archy-1.0.0.tgz#f9c8c13757cc1dd7bc379ac77b2c62a5c2868c40"
482+ integrity sha1-+cjBN1fMHde8N5rHeyxipcKGjEA=
483+
484+argparse@^1.0.7:
485+ version "1.0.10"
486+ resolved "https://registry.yarnpkg.com/argparse/-/argparse-1.0.10.tgz#bcd6791ea5ae09725e17e5ad988134cd40b3d911"
487+ integrity sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==
488+ dependencies:
489+ sprintf-js "~1.0.2"
490+
491+argparse@^2.0.1:
492+ version "2.0.1"
493+ resolved "https://registry.yarnpkg.com/argparse/-/argparse-2.0.1.tgz#246f50f3ca78a3240f6c997e8a9bd1eac49e4b38"
494+ integrity sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==
495+
496+arr-diff@^1.0.1:
497+ version "1.1.0"
498+ resolved "https://registry.yarnpkg.com/arr-diff/-/arr-diff-1.1.0.tgz#687c32758163588fef7de7b36fabe495eb1a399a"
499+ integrity sha1-aHwydYFjWI/vfeezb6vklesaOZo=
500+ dependencies:
501+ arr-flatten "^1.0.1"
502+ array-slice "^0.2.3"
503+
504+arr-diff@^4.0.0:
505+ version "4.0.0"
506+ resolved "https://registry.yarnpkg.com/arr-diff/-/arr-diff-4.0.0.tgz#d6461074febfec71e7e15235761a329a5dc7c520"
507+ integrity sha1-1kYQdP6/7HHn4VI1dhoyml3HxSA=
508+
509+arr-filter@^1.1.1:
510+ version "1.1.2"
511+ resolved "https://registry.yarnpkg.com/arr-filter/-/arr-filter-1.1.2.tgz#43fdddd091e8ef11aa4c45d9cdc18e2dff1711ee"
512+ integrity sha1-Q/3d0JHo7xGqTEXZzcGOLf8XEe4=
513+ dependencies:
514+ make-iterator "^1.0.0"
515+
516+arr-flatten@^1.0.1, arr-flatten@^1.1.0:
517+ version "1.1.0"
518+ resolved "https://registry.yarnpkg.com/arr-flatten/-/arr-flatten-1.1.0.tgz#36048bbff4e7b47e136644316c99669ea5ae91f1"
519+ integrity sha512-L3hKV5R/p5o81R7O02IGnwpDmkp6E982XhtbuwSe3O4qOtMMMtodicASA1Cny2U+aCXcNpml+m4dPsvsJ3jatg==
520+
521+arr-map@^2.0.0, arr-map@^2.0.2:
522+ version "2.0.2"
523+ resolved "https://registry.yarnpkg.com/arr-map/-/arr-map-2.0.2.tgz#3a77345ffc1cf35e2a91825601f9e58f2e24cac4"
524+ integrity sha1-Onc0X/wc814qkYJWAfnljy4kysQ=
525+ dependencies:
526+ make-iterator "^1.0.0"
527+
528+arr-union@^2.0.1:
529+ version "2.1.0"
530+ resolved "https://registry.yarnpkg.com/arr-union/-/arr-union-2.1.0.tgz#20f9eab5ec70f5c7d215b1077b1c39161d292c7d"
531+ integrity sha1-IPnqtexw9cfSFbEHexw5Fh0pLH0=
532+
533+arr-union@^3.1.0:
534+ version "3.1.0"
535+ resolved "https://registry.yarnpkg.com/arr-union/-/arr-union-3.1.0.tgz#e39b09aea9def866a8f206e288af63919bae39c4"
536+ integrity sha1-45sJrqne+Gao8gbiiK9jkZuuOcQ=
537+
538+array-differ@^3.0.0:
539+ version "3.0.0"
540+ resolved "https://registry.yarnpkg.com/array-differ/-/array-differ-3.0.0.tgz#3cbb3d0f316810eafcc47624734237d6aee4ae6b"
541+ integrity sha512-THtfYS6KtME/yIAhKjZ2ul7XI96lQGHRputJQHO80LAWQnuGP4iCIN8vdMRboGbIEYBwU33q8Tch1os2+X0kMg==
542+
543+array-each@^1.0.0, array-each@^1.0.1:
544+ version "1.0.1"
545+ resolved "https://registry.yarnpkg.com/array-each/-/array-each-1.0.1.tgz#a794af0c05ab1752846ee753a1f211a05ba0c44f"
546+ integrity sha1-p5SvDAWrF1KEbudTofIRoFugxE8=
547+
548+array-find-index@^1.0.1:
549+ version "1.0.2"
550+ resolved "https://registry.yarnpkg.com/array-find-index/-/array-find-index-1.0.2.tgz#df010aa1287e164bbda6f9723b0a96a1ec4187a1"
551+ integrity sha1-3wEKoSh+Fku9pvlyOwqWoexBh6E=
552+
553+array-flatten@1.1.1:
554+ version "1.1.1"
555+ resolved "https://registry.yarnpkg.com/array-flatten/-/array-flatten-1.1.1.tgz#9a5f699051b1e7073328f2a008968b64ea2955d2"
556+ integrity sha1-ml9pkFGx5wczKPKgCJaLZOopVdI=
557+
558+array-ify@^1.0.0:
559+ version "1.0.0"
560+ resolved "https://registry.yarnpkg.com/array-ify/-/array-ify-1.0.0.tgz#9e528762b4a9066ad163a6962a364418e9626ece"
561+ integrity sha1-nlKHYrSpBmrRY6aWKjZEGOlibs4=
562+
563+array-initial@^1.0.0:
564+ version "1.1.0"
565+ resolved "https://registry.yarnpkg.com/array-initial/-/array-initial-1.1.0.tgz#2fa74b26739371c3947bd7a7adc73be334b3d795"
566+ integrity sha1-L6dLJnOTccOUe9enrcc74zSz15U=
567+ dependencies:
568+ array-slice "^1.0.0"
569+ is-number "^4.0.0"
570+
571+array-last@^1.1.1:
572+ version "1.3.0"
573+ resolved "https://registry.yarnpkg.com/array-last/-/array-last-1.3.0.tgz#7aa77073fec565ddab2493f5f88185f404a9d336"
574+ integrity sha512-eOCut5rXlI6aCOS7Z7kCplKRKyiFQ6dHFBem4PwlwKeNFk2/XxTrhRh5T9PyaEWGy/NHTZWbY+nsZlNFJu9rYg==
575+ dependencies:
576+ is-number "^4.0.0"
577+
578+array-slice@^0.2.3:
579+ version "0.2.3"
580+ resolved "https://registry.yarnpkg.com/array-slice/-/array-slice-0.2.3.tgz#dd3cfb80ed7973a75117cdac69b0b99ec86186f5"
581+ integrity sha1-3Tz7gO15c6dRF82sabC5nshhhvU=
582+
583+array-slice@^1.0.0:
584+ version "1.1.0"
585+ resolved "https://registry.yarnpkg.com/array-slice/-/array-slice-1.1.0.tgz#e368ea15f89bc7069f7ffb89aec3a6c7d4ac22d4"
586+ integrity sha512-B1qMD3RBP7O8o0H2KbrXDyB0IccejMF15+87Lvlor12ONPRHP6gTjXMNkt/d3ZuOGbAe66hFmaCfECI24Ufp6w==
587+
588+array-sort@^1.0.0:
589+ version "1.0.0"
590+ resolved "https://registry.yarnpkg.com/array-sort/-/array-sort-1.0.0.tgz#e4c05356453f56f53512a7d1d6123f2c54c0a88a"
591+ integrity sha512-ihLeJkonmdiAsD7vpgN3CRcx2J2S0TiYW+IS/5zHBI7mKUq3ySvBdzzBfD236ubDBQFiiyG3SWCPc+msQ9KoYg==
592+ dependencies:
593+ default-compare "^1.0.0"
594+ get-value "^2.0.6"
595+ kind-of "^5.0.2"
596+
597+array-union@^2.1.0:
598+ version "2.1.0"
599+ resolved "https://registry.yarnpkg.com/array-union/-/array-union-2.1.0.tgz#b798420adbeb1de828d84acd8a2e23d3efe85e8d"
600+ integrity sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw==
601+
602+array-unique@^0.3.2:
603+ version "0.3.2"
604+ resolved "https://registry.yarnpkg.com/array-unique/-/array-unique-0.3.2.tgz#a894b75d4bc4f6cd679ef3244a9fd8f46ae2d428"
605+ integrity sha1-qJS3XUvE9s1nnvMkSp/Y9Gri1Cg=
606+
607+arrify@^1.0.1:
608+ version "1.0.1"
609+ resolved "https://registry.yarnpkg.com/arrify/-/arrify-1.0.1.tgz#898508da2226f380df904728456849c1501a4b0d"
610+ integrity sha1-iYUI2iIm84DfkEcoRWhJwVAaSw0=
611+
612+arrify@^2.0.1:
613+ version "2.0.1"
614+ resolved "https://registry.yarnpkg.com/arrify/-/arrify-2.0.1.tgz#c9655e9331e0abcd588d2a7cad7e9956f66701fa"
615+ integrity sha512-3duEwti880xqi4eAMN8AyR4a0ByT90zoYdLlevfrvU43vb0YZwZVfxOgxWrLXXXpyugL0hNZc9G6BiB5B3nUug==
616+
617+asn1@~0.2.3:
618+ version "0.2.4"
619+ resolved "https://registry.yarnpkg.com/asn1/-/asn1-0.2.4.tgz#8d2475dfab553bb33e77b54e59e880bb8ce23136"
620+ integrity sha512-jxwzQpLQjSmWXgwaCZE9Nz+glAG01yF1QnWgbhGwHI5A6FRIEY6IVqtHhIepHqI7/kyEyQEagBC5mBEFlIYvdg==
621+ dependencies:
622+ safer-buffer "~2.1.0"
623+
624+assert-plus@1.0.0, assert-plus@^1.0.0:
625+ version "1.0.0"
626+ resolved "https://registry.yarnpkg.com/assert-plus/-/assert-plus-1.0.0.tgz#f12e0f3c5d77b0b1cdd9146942e4e96c1e4dd525"
627+ integrity sha1-8S4PPF13sLHN2RRpQuTpbB5N1SU=
628+
629+assign-symbols@^1.0.0:
630+ version "1.0.0"
631+ resolved "https://registry.yarnpkg.com/assign-symbols/-/assign-symbols-1.0.0.tgz#59667f41fadd4f20ccbc2bb96b8d4f7f78ec0367"
632+ integrity sha1-WWZ/QfrdTyDMvCu5a41Pf3jsA2c=
633+
634+async-done@^1.2.0, async-done@^1.2.2:
635+ version "1.3.2"
636+ resolved "https://registry.yarnpkg.com/async-done/-/async-done-1.3.2.tgz#5e15aa729962a4b07414f528a88cdf18e0b290a2"
637+ integrity sha512-uYkTP8dw2og1tu1nmza1n1CMW0qb8gWWlwqMmLb7MhBVs4BXrFziT6HXUd+/RlRA/i4H9AkofYloUbs1fwMqlw==
638+ dependencies:
639+ end-of-stream "^1.1.0"
640+ once "^1.3.2"
641+ process-nextick-args "^2.0.0"
642+ stream-exhaust "^1.0.1"
643+
644+async-each@^1.0.1:
645+ version "1.0.3"
646+ resolved "https://registry.yarnpkg.com/async-each/-/async-each-1.0.3.tgz#b727dbf87d7651602f06f4d4ac387f47d91b0cbf"
647+ integrity sha512-z/WhQ5FPySLdvREByI2vZiTWwCnF0moMJ1hK9YQwDTHKh6I7/uSckMetoRGb5UBZPC1z0jlw+n/XCgjeH7y1AQ==
648+
649+async-settle@^1.0.0:
650+ version "1.0.0"
651+ resolved "https://registry.yarnpkg.com/async-settle/-/async-settle-1.0.0.tgz#1d0a914bb02575bec8a8f3a74e5080f72b2c0c6b"
652+ integrity sha1-HQqRS7Aldb7IqPOnTlCA9yssDGs=
653+ dependencies:
654+ async-done "^1.2.2"
655+
656+asynckit@^0.4.0:
657+ version "0.4.0"
658+ resolved "https://registry.yarnpkg.com/asynckit/-/asynckit-0.4.0.tgz#c79ed97f7f34cb8f2ba1bc9790bcc366474b4b79"
659+ integrity sha1-x57Zf380y48robyXkLzDZkdLS3k=
660+
661+atob@^2.1.2:
662+ version "2.1.2"
663+ resolved "https://registry.yarnpkg.com/atob/-/atob-2.1.2.tgz#6d9517eb9e030d2436666651e86bd9f6f13533c9"
664+ integrity sha512-Wm6ukoaOGJi/73p/cl2GvLjTI5JM1k/O14isD73YML8StrH/7/lRFgmg8nICZgD3bZZvjwCGxtMOD3wWNAu8cg==
665+
666+aws-sign2@~0.7.0:
667+ version "0.7.0"
668+ resolved "https://registry.yarnpkg.com/aws-sign2/-/aws-sign2-0.7.0.tgz#b46e890934a9591f2d2f6f86d7e6a9f1b3fe76a8"
669+ integrity sha1-tG6JCTSpWR8tL2+G1+ap8bP+dqg=
670+
671+aws4@^1.8.0:
672+ version "1.11.0"
673+ resolved "https://registry.yarnpkg.com/aws4/-/aws4-1.11.0.tgz#d61f46d83b2519250e2784daf5b09479a8b41c59"
674+ integrity sha512-xh1Rl34h6Fi1DC2WWKfxUTVqRsNnr6LsKz2+hfwDxQJWmrx8+c7ylaqBMcHfl1U1r2dsifOvKX3LQuLNZ+XSvA==
675+
676+babel-polyfill@6.26.0:
677+ version "6.26.0"
678+ resolved "https://registry.yarnpkg.com/babel-polyfill/-/babel-polyfill-6.26.0.tgz#379937abc67d7895970adc621f284cd966cf2153"
679+ integrity sha1-N5k3q8Z9eJWXCtxiHyhM2WbPIVM=
680+ dependencies:
681+ babel-runtime "^6.26.0"
682+ core-js "^2.5.0"
683+ regenerator-runtime "^0.10.5"
684+
685+babel-runtime@^6.23.0, babel-runtime@^6.26.0:
686+ version "6.26.0"
687+ resolved "https://registry.yarnpkg.com/babel-runtime/-/babel-runtime-6.26.0.tgz#965c7058668e82b55d7bfe04ff2337bc8b5647fe"
688+ integrity sha1-llxwWGaOgrVde/4E/yM3vItWR/4=
689+ dependencies:
690+ core-js "^2.4.0"
691+ regenerator-runtime "^0.11.0"
692+
693+bach@^1.0.0:
694+ version "1.2.0"
695+ resolved "https://registry.yarnpkg.com/bach/-/bach-1.2.0.tgz#4b3ce96bf27134f79a1b414a51c14e34c3bd9880"
696+ integrity sha1-Szzpa/JxNPeaG0FKUcFONMO9mIA=
697+ dependencies:
698+ arr-filter "^1.1.1"
699+ arr-flatten "^1.0.1"
700+ arr-map "^2.0.0"
701+ array-each "^1.0.0"
702+ array-initial "^1.0.0"
703+ array-last "^1.1.1"
704+ async-done "^1.2.2"
705+ async-settle "^1.0.0"
706+ now-and-later "^2.0.0"
707+
708+balanced-match@^1.0.0:
709+ version "1.0.2"
710+ resolved "https://registry.yarnpkg.com/balanced-match/-/balanced-match-1.0.2.tgz#e83e3a7e3f300b34cb9d87f615fa0cbf357690ee"
711+ integrity sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==
712+
713+base@^0.11.1:
714+ version "0.11.2"
715+ resolved "https://registry.yarnpkg.com/base/-/base-0.11.2.tgz#7bde5ced145b6d551a90db87f83c558b4eb48a8f"
716+ integrity sha512-5T6P4xPgpp0YDFvSWwEZ4NoE3aM4QBQXDzmVbraCkFj8zHM+mba8SyqB5DbZWyR7mYHo6Y7BdQo3MoA4m0TeQg==
717+ dependencies:
718+ cache-base "^1.0.1"
719+ class-utils "^0.3.5"
720+ component-emitter "^1.2.1"
721+ define-property "^1.0.0"
722+ isobject "^3.0.1"
723+ mixin-deep "^1.2.0"
724+ pascalcase "^0.1.1"
725+
726+bcrypt-pbkdf@^1.0.0:
727+ version "1.0.2"
728+ resolved "https://registry.yarnpkg.com/bcrypt-pbkdf/-/bcrypt-pbkdf-1.0.2.tgz#a4301d389b6a43f9b67ff3ca11a3f6637e360e9e"
729+ integrity sha1-pDAdOJtqQ/m2f/PKEaP2Y342Dp4=
730+ dependencies:
731+ tweetnacl "^0.14.3"
732+
733+binary-extensions@^1.0.0:
734+ version "1.13.1"
735+ resolved "https://registry.yarnpkg.com/binary-extensions/-/binary-extensions-1.13.1.tgz#598afe54755b2868a5330d2aff9d4ebb53209b65"
736+ integrity sha512-Un7MIEDdUC5gNpcGDV97op1Ywk748MpHcFTHoYs6qnj1Z3j7I53VG3nwZhKzoBZmbdRNnb6WRdFlwl7tSDuZGw==
737+
738+bindings@^1.5.0:
739+ version "1.5.0"
740+ resolved "https://registry.yarnpkg.com/bindings/-/bindings-1.5.0.tgz#10353c9e945334bc0511a6d90b38fbc7c9c504df"
741+ integrity sha512-p2q/t/mhvuOj/UeLlV6566GD/guowlr0hHxClI0W9m7MWYkL1F0hLo+0Aexs9HSPCtR1SXQ0TD3MMKrXZajbiQ==
742+ dependencies:
743+ file-uri-to-path "1.0.0"
744+
745+body-parser@1.19.0:
746+ version "1.19.0"
747+ resolved "https://registry.yarnpkg.com/body-parser/-/body-parser-1.19.0.tgz#96b2709e57c9c4e09a6fd66a8fd979844f69f08a"
748+ integrity sha512-dhEPs72UPbDnAQJ9ZKMNTP6ptJaionhP5cBb541nXPlW60Jepo9RV/a4fX4XWW9CuFNK22krhrj1+rgzifNCsw==
749+ dependencies:
750+ bytes "3.1.0"
751+ content-type "~1.0.4"
752+ debug "2.6.9"
753+ depd "~1.1.2"
754+ http-errors "1.7.2"
755+ iconv-lite "0.4.24"
756+ on-finished "~2.3.0"
757+ qs "6.7.0"
758+ raw-body "2.4.0"
759+ type-is "~1.6.17"
760+
761+brace-expansion@^1.1.7:
762+ version "1.1.11"
763+ resolved "https://registry.yarnpkg.com/brace-expansion/-/brace-expansion-1.1.11.tgz#3c7fcbf529d87226f3d2f52b966ff5271eb441dd"
764+ integrity sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==
765+ dependencies:
766+ balanced-match "^1.0.0"
767+ concat-map "0.0.1"
768+
769+braces@^2.3.1, braces@^2.3.2:
770+ version "2.3.2"
771+ resolved "https://registry.yarnpkg.com/braces/-/braces-2.3.2.tgz#5979fd3f14cd531565e5fa2df1abfff1dfaee729"
772+ integrity sha512-aNdbnj9P8PjdXU4ybaWLK2IF3jc/EoDYbC7AazW6to3TRsfXxscC9UXOB5iDiEQrkyIbWp2SLQda4+QAa7nc3w==
773+ dependencies:
774+ arr-flatten "^1.1.0"
775+ array-unique "^0.3.2"
776+ extend-shallow "^2.0.1"
777+ fill-range "^4.0.0"
778+ isobject "^3.0.1"
779+ repeat-element "^1.1.2"
780+ snapdragon "^0.8.1"
781+ snapdragon-node "^2.0.1"
782+ split-string "^3.0.2"
783+ to-regex "^3.0.1"
784+
785+braces@^3.0.1:
786+ version "3.0.2"
787+ resolved "https://registry.yarnpkg.com/braces/-/braces-3.0.2.tgz#3454e1a462ee8d599e236df336cd9ea4f8afe107"
788+ integrity sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==
789+ dependencies:
790+ fill-range "^7.0.1"
791+
792+buffer-equal@^1.0.0:
793+ version "1.0.0"
794+ resolved "https://registry.yarnpkg.com/buffer-equal/-/buffer-equal-1.0.0.tgz#59616b498304d556abd466966b22eeda3eca5fbe"
795+ integrity sha1-WWFrSYME1Var1GaWayLu2j7KX74=
796+
797+buffer-from@^1.0.0:
798+ version "1.1.1"
799+ resolved "https://registry.yarnpkg.com/buffer-from/-/buffer-from-1.1.1.tgz#32713bc028f75c02fdb710d7c7bcec1f2c6070ef"
800+ integrity sha512-MQcXEUbCKtEo7bhqEs6560Hyd4XaovZlO/k9V3hjVUF/zwW7KBVdSK4gIt/bzwS9MbR5qob+F5jusZsb0YQK2A==
801+
802+builtin-modules@^1.1.1:
803+ version "1.1.1"
804+ resolved "https://registry.yarnpkg.com/builtin-modules/-/builtin-modules-1.1.1.tgz#270f076c5a72c02f5b65a47df94c5fe3a278892f"
805+ integrity sha1-Jw8HbFpywC9bZaR9+Uxf46J4iS8=
806+
807+bytes@3.1.0:
808+ version "3.1.0"
809+ resolved "https://registry.yarnpkg.com/bytes/-/bytes-3.1.0.tgz#f6cf7933a360e0588fa9fde85651cdc7f805d1f6"
810+ integrity sha512-zauLjrfCG+xvoyaqLoV8bLVXXNGC4JqlxFCutSDWA6fJrTo2ZuvLYTqZ7aHBLZSMOopbzwv8f+wZcVzfVTI2Dg==
811+
812+cache-base@^1.0.1:
813+ version "1.0.1"
814+ resolved "https://registry.yarnpkg.com/cache-base/-/cache-base-1.0.1.tgz#0a7f46416831c8b662ee36fe4e7c59d76f666ab2"
815+ integrity sha512-AKcdTnFSWATd5/GCPRxr2ChwIJ85CeyrEyjRHlKxQ56d4XJMGym0uAiKn0xbLOGOl3+yRpOTi484dVCEc5AUzQ==
816+ dependencies:
817+ collection-visit "^1.0.0"
818+ component-emitter "^1.2.1"
819+ get-value "^2.0.6"
820+ has-value "^1.0.0"
821+ isobject "^3.0.1"
822+ set-value "^2.0.0"
823+ to-object-path "^0.3.0"
824+ union-value "^1.0.0"
825+ unset-value "^1.0.0"
826+
827+call-bind@^1.0.0:
828+ version "1.0.2"
829+ resolved "https://registry.yarnpkg.com/call-bind/-/call-bind-1.0.2.tgz#b1d4e89e688119c3c9a903ad30abb2f6a919be3c"
830+ integrity sha512-7O+FbCihrB5WGbFYesctwmTKae6rOiIzmz1icreWJ+0aA7LJfuqhEso2T9ncpcFtzMQtzXf2QGGueWJGTYsqrA==
831+ dependencies:
832+ function-bind "^1.1.1"
833+ get-intrinsic "^1.0.2"
834+
835+call-me-maybe@^1.0.1:
836+ version "1.0.1"
837+ resolved "https://registry.yarnpkg.com/call-me-maybe/-/call-me-maybe-1.0.1.tgz#26d208ea89e37b5cbde60250a15f031c16a4d66b"
838+ integrity sha1-JtII6onje1y95gJQoV8DHBak1ms=
839+
840+caller-callsite@^2.0.0:
841+ version "2.0.0"
842+ resolved "https://registry.yarnpkg.com/caller-callsite/-/caller-callsite-2.0.0.tgz#847e0fce0a223750a9a027c54b33731ad3154134"
843+ integrity sha1-hH4PzgoiN1CpoCfFSzNzGtMVQTQ=
844+ dependencies:
845+ callsites "^2.0.0"
846+
847+caller-path@^2.0.0:
848+ version "2.0.0"
849+ resolved "https://registry.yarnpkg.com/caller-path/-/caller-path-2.0.0.tgz#468f83044e369ab2010fac5f06ceee15bb2cb1f4"
850+ integrity sha1-Ro+DBE42mrIBD6xfBs7uFbsssfQ=
851+ dependencies:
852+ caller-callsite "^2.0.0"
853+
854+callsites@^2.0.0:
855+ version "2.0.0"
856+ resolved "https://registry.yarnpkg.com/callsites/-/callsites-2.0.0.tgz#06eb84f00eea413da86affefacbffb36093b3c50"
857+ integrity sha1-BuuE8A7qQT2oav/vrL/7Ngk7PFA=
858+
859+callsites@^3.0.0:
860+ version "3.1.0"
861+ resolved "https://registry.yarnpkg.com/callsites/-/callsites-3.1.0.tgz#b3630abd8943432f54b3f0519238e33cd7df2f73"
862+ integrity sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==
863+
864+camelcase-keys@^4.0.0:
865+ version "4.2.0"
866+ resolved "https://registry.yarnpkg.com/camelcase-keys/-/camelcase-keys-4.2.0.tgz#a2aa5fb1af688758259c32c141426d78923b9b77"
867+ integrity sha1-oqpfsa9oh1glnDLBQUJteJI7m3c=
868+ dependencies:
869+ camelcase "^4.1.0"
870+ map-obj "^2.0.0"
871+ quick-lru "^1.0.0"
872+
873+camelcase-keys@^6.2.2:
874+ version "6.2.2"
875+ resolved "https://registry.yarnpkg.com/camelcase-keys/-/camelcase-keys-6.2.2.tgz#5e755d6ba51aa223ec7d3d52f25778210f9dc3c0"
876+ integrity sha512-YrwaA0vEKazPBkn0ipTiMpSajYDSe+KjQfrjhcBMxJt/znbvlHd8Pw/Vamaz5EB4Wfhs3SUR3Z9mwRu/P3s3Yg==
877+ dependencies:
878+ camelcase "^5.3.1"
879+ map-obj "^4.0.0"
880+ quick-lru "^4.0.1"
881+
882+camelcase@^3.0.0:
883+ version "3.0.0"
884+ resolved "https://registry.yarnpkg.com/camelcase/-/camelcase-3.0.0.tgz#32fc4b9fcdaf845fcdf7e73bb97cac2261f0ab0a"
885+ integrity sha1-MvxLn82vhF/N9+c7uXysImHwqwo=
886+
887+camelcase@^4.1.0:
888+ version "4.1.0"
889+ resolved "https://registry.yarnpkg.com/camelcase/-/camelcase-4.1.0.tgz#d545635be1e33c542649c69173e5de6acfae34dd"
890+ integrity sha1-1UVjW+HjPFQmScaRc+Xeas+uNN0=
891+
892+camelcase@^5.0.0, camelcase@^5.3.1:
893+ version "5.3.1"
894+ resolved "https://registry.yarnpkg.com/camelcase/-/camelcase-5.3.1.tgz#e3c9b31569e106811df242f715725a1f4c494320"
895+ integrity sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==
896+
897+caseless@~0.12.0:
898+ version "0.12.0"
899+ resolved "https://registry.yarnpkg.com/caseless/-/caseless-0.12.0.tgz#1b681c21ff84033c826543090689420d187151dc"
900+ integrity sha1-G2gcIf+EAzyCZUMJBolCDRhxUdw=
901+
902+chalk@2.4.2, chalk@^2.0.0, chalk@^2.0.1, chalk@^2.3.0:
903+ version "2.4.2"
904+ resolved "https://registry.yarnpkg.com/chalk/-/chalk-2.4.2.tgz#cd42541677a54333cf541a49108c1432b44c9424"
905+ integrity sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==
906+ dependencies:
907+ ansi-styles "^3.2.1"
908+ escape-string-regexp "^1.0.5"
909+ supports-color "^5.3.0"
910+
911+chokidar@^2.0.0:
912+ version "2.1.8"
913+ resolved "https://registry.yarnpkg.com/chokidar/-/chokidar-2.1.8.tgz#804b3a7b6a99358c3c5c61e71d8728f041cff917"
914+ integrity sha512-ZmZUazfOzf0Nve7duiCKD23PFSCs4JPoYyccjUFF3aQkQadqBhfzhjkwBH2mNOG9cTBwhamM37EIsIkZw3nRgg==
915+ dependencies:
916+ anymatch "^2.0.0"
917+ async-each "^1.0.1"
918+ braces "^2.3.2"
919+ glob-parent "^3.1.0"
920+ inherits "^2.0.3"
921+ is-binary-path "^1.0.0"
922+ is-glob "^4.0.0"
923+ normalize-path "^3.0.0"
924+ path-is-absolute "^1.0.0"
925+ readdirp "^2.2.1"
926+ upath "^1.1.1"
927+ optionalDependencies:
928+ fsevents "^1.2.7"
929+
930+class-utils@^0.3.5:
931+ version "0.3.6"
932+ resolved "https://registry.yarnpkg.com/class-utils/-/class-utils-0.3.6.tgz#f93369ae8b9a7ce02fd41faad0ca83033190c463"
933+ integrity sha512-qOhPa/Fj7s6TY8H8esGu5QNpMMQxz79h+urzrNYN6mn+9BnxlDGf5QZ+XeCDsxSjPqsSR56XOZOJmpeurnLMeg==
934+ dependencies:
935+ arr-union "^3.1.0"
936+ define-property "^0.2.5"
937+ isobject "^3.0.0"
938+ static-extend "^0.1.1"
939+
940+clean-stack@^2.0.0:
941+ version "2.2.0"
942+ resolved "https://registry.yarnpkg.com/clean-stack/-/clean-stack-2.2.0.tgz#ee8472dbb129e727b31e8a10a427dee9dfe4008b"
943+ integrity sha512-4diC9HaTE+KRAMWhDhrGOECgWZxoevMc5TlkObMqNSsVU62PYzXZ/SMTjzyGAFF1YusgxGcSWTEXBhp0CPwQ1A==
944+
945+cliui@^3.2.0:
946+ version "3.2.0"
947+ resolved "https://registry.yarnpkg.com/cliui/-/cliui-3.2.0.tgz#120601537a916d29940f934da3b48d585a39213d"
948+ integrity sha1-EgYBU3qRbSmUD5NNo7SNWFo5IT0=
949+ dependencies:
950+ string-width "^1.0.1"
951+ strip-ansi "^3.0.1"
952+ wrap-ansi "^2.0.0"
953+
954+clone-buffer@^1.0.0:
955+ version "1.0.0"
956+ resolved "https://registry.yarnpkg.com/clone-buffer/-/clone-buffer-1.0.0.tgz#e3e25b207ac4e701af721e2cb5a16792cac3dc58"
957+ integrity sha1-4+JbIHrE5wGvch4staFnksrD3Fg=
958+
959+clone-stats@^1.0.0:
960+ version "1.0.0"
961+ resolved "https://registry.yarnpkg.com/clone-stats/-/clone-stats-1.0.0.tgz#b3782dff8bb5474e18b9b6bf0fdfe782f8777680"
962+ integrity sha1-s3gt/4u1R04Yuba/D9/ngvh3doA=
963+
964+clone@^2.1.1:
965+ version "2.1.2"
966+ resolved "https://registry.yarnpkg.com/clone/-/clone-2.1.2.tgz#1b7f4b9f591f1e8f83670401600345a02887435f"
967+ integrity sha1-G39Ln1kfHo+DZwQBYANFoCiHQ18=
968+
969+cloneable-readable@^1.0.0:
970+ version "1.1.3"
971+ resolved "https://registry.yarnpkg.com/cloneable-readable/-/cloneable-readable-1.1.3.tgz#120a00cb053bfb63a222e709f9683ea2e11d8cec"
972+ integrity sha512-2EF8zTQOxYq70Y4XKtorQupqF0m49MBz2/yf5Bj+MHjvpG3Hy7sImifnqD6UA+TKYxeSV+u6qqQPawN5UvnpKQ==
973+ dependencies:
974+ inherits "^2.0.1"
975+ process-nextick-args "^2.0.0"
976+ readable-stream "^2.3.5"
977+
978+code-point-at@^1.0.0:
979+ version "1.1.0"
980+ resolved "https://registry.yarnpkg.com/code-point-at/-/code-point-at-1.1.0.tgz#0d070b4d043a5bea33a2f1a40e2edb3d9a4ccf77"
981+ integrity sha1-DQcLTQQ6W+ozovGkDi7bPZpMz3c=
982+
983+collection-map@^1.0.0:
984+ version "1.0.0"
985+ resolved "https://registry.yarnpkg.com/collection-map/-/collection-map-1.0.0.tgz#aea0f06f8d26c780c2b75494385544b2255af18c"
986+ integrity sha1-rqDwb40mx4DCt1SUOFVEsiVa8Yw=
987+ dependencies:
988+ arr-map "^2.0.2"
989+ for-own "^1.0.0"
990+ make-iterator "^1.0.0"
991+
992+collection-visit@^1.0.0:
993+ version "1.0.0"
994+ resolved "https://registry.yarnpkg.com/collection-visit/-/collection-visit-1.0.0.tgz#4bc0373c164bc3291b4d368c829cf1a80a59dca0"
995+ integrity sha1-S8A3PBZLwykbTTaMgpzxqApZ3KA=
996+ dependencies:
997+ map-visit "^1.0.0"
998+ object-visit "^1.0.0"
999+
1000+color-convert@^1.9.0:
1001+ version "1.9.3"
1002+ resolved "https://registry.yarnpkg.com/color-convert/-/color-convert-1.9.3.tgz#bb71850690e1f136567de629d2d5471deda4c1e8"
1003+ integrity sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==
1004+ dependencies:
1005+ color-name "1.1.3"
1006+
1007+color-name@1.1.3:
1008+ version "1.1.3"
1009+ resolved "https://registry.yarnpkg.com/color-name/-/color-name-1.1.3.tgz#a7d0558bd89c42f795dd42328f740831ca53bc25"
1010+ integrity sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=
1011+
1012+color-support@^1.1.3:
1013+ version "1.1.3"
1014+ resolved "https://registry.yarnpkg.com/color-support/-/color-support-1.1.3.tgz#93834379a1cc9a0c61f82f52f0d04322251bd5a2"
1015+ integrity sha512-qiBjkpbMLO/HL68y+lh4q0/O1MZFj2RX6X/KmMa3+gJD3z+WwI1ZzDHysvqHGS3mP6mznPckpXmw1nI9cJjyRg==
1016+
1017+combined-stream@^1.0.6, combined-stream@~1.0.6:
1018+ version "1.0.8"
1019+ resolved "https://registry.yarnpkg.com/combined-stream/-/combined-stream-1.0.8.tgz#c3d45a8b34fd730631a110a8a2520682b31d5a7f"
1020+ integrity sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==
1021+ dependencies:
1022+ delayed-stream "~1.0.0"
1023+
1024+commander@^2.12.1, commander@^2.7.1:
1025+ version "2.20.3"
1026+ resolved "https://registry.yarnpkg.com/commander/-/commander-2.20.3.tgz#fd485e84c03eb4881c20722ba48035e8531aeb33"
1027+ integrity sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==
1028+
1029+commander@^5.0.0:
1030+ version "5.1.0"
1031+ resolved "https://registry.yarnpkg.com/commander/-/commander-5.1.0.tgz#46abbd1652f8e059bddaef99bbdcb2ad9cf179ae"
1032+ integrity sha512-P0CysNDQ7rtVw4QIQtm+MRxV66vKFSvlsQvGYXZWR3qFU0jlMKHZZZgw8e+8DSah4UDKMqnknRDQz+xuQXQ/Zg==
1033+
1034+commander@^6.1.0:
1035+ version "6.2.1"
1036+ resolved "https://registry.yarnpkg.com/commander/-/commander-6.2.1.tgz#0792eb682dfbc325999bb2b84fddddba110ac73c"
1037+ integrity sha512-U7VdrJFnJgo4xjrHpTzu0yrHPGImdsmD95ZlgYSEajAn2JKzDhDTPG9kBTefmObL2w/ngeZnilk+OV9CG3d7UA==
1038+
1039+compare-func@^1.3.1:
1040+ version "1.3.4"
1041+ resolved "https://registry.yarnpkg.com/compare-func/-/compare-func-1.3.4.tgz#6b07c4c5e8341119baf44578085bda0f4a823516"
1042+ integrity sha512-sq2sWtrqKPkEXAC8tEJA1+BqAH9GbFkGBtUOqrUX57VSfwp8xyktctk+uLoRy5eccTdxzDcVIztlYDpKs3Jv1Q==
1043+ dependencies:
1044+ array-ify "^1.0.0"
1045+ dot-prop "^3.0.0"
1046+
1047+compare-func@^2.0.0:
1048+ version "2.0.0"
1049+ resolved "https://registry.yarnpkg.com/compare-func/-/compare-func-2.0.0.tgz#fb65e75edbddfd2e568554e8b5b05fff7a51fcb3"
1050+ integrity sha512-zHig5N+tPWARooBnb0Zx1MFcdfpyJrfTJ3Y5L+IFvUm8rM74hHz66z0gw0x4tijh5CorKkKUCnW82R2vmpeCRA==
1051+ dependencies:
1052+ array-ify "^1.0.0"
1053+ dot-prop "^5.1.0"
1054+
1055+component-emitter@^1.2.1:
1056+ version "1.3.0"
1057+ resolved "https://registry.yarnpkg.com/component-emitter/-/component-emitter-1.3.0.tgz#16e4070fba8ae29b679f2215853ee181ab2eabc0"
1058+ integrity sha512-Rd3se6QB+sO1TwqZjscQrurpEPIfO0/yYnSin6Q/rD3mOutHvUrCAhJub3r90uNb+SESBuE0QYoB90YdfatsRg==
1059+
1060+concat-map@0.0.1:
1061+ version "0.0.1"
1062+ resolved "https://registry.yarnpkg.com/concat-map/-/concat-map-0.0.1.tgz#d8a96bd77fd68df7793a73036a3ba0d5405d477b"
1063+ integrity sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=
1064+
1065+concat-stream@^1.6.0:
1066+ version "1.6.2"
1067+ resolved "https://registry.yarnpkg.com/concat-stream/-/concat-stream-1.6.2.tgz#904bdf194cd3122fc675c77fc4ac3d4ff0fd1a34"
1068+ integrity sha512-27HBghJxjiZtIk3Ycvn/4kbJk/1uZuJFfuPEns6LaEvpvG1f0hTea8lilrouyo9mVc2GWdcEZ8OLoGmSADlrCw==
1069+ dependencies:
1070+ buffer-from "^1.0.0"
1071+ inherits "^2.0.3"
1072+ readable-stream "^2.2.2"
1073+ typedarray "^0.0.6"
1074+
1075+concat-stream@^2.0.0:
1076+ version "2.0.0"
1077+ resolved "https://registry.yarnpkg.com/concat-stream/-/concat-stream-2.0.0.tgz#414cf5af790a48c60ab9be4527d56d5e41133cb1"
1078+ integrity sha512-MWufYdFw53ccGjCA+Ol7XJYpAlW6/prSMzuPOTRnJGcGzuhLn4Scrz7qf6o8bROZ514ltazcIFJZevcfbo0x7A==
1079+ dependencies:
1080+ buffer-from "^1.0.0"
1081+ inherits "^2.0.3"
1082+ readable-stream "^3.0.2"
1083+ typedarray "^0.0.6"
1084+
1085+content-disposition@0.5.3:
1086+ version "0.5.3"
1087+ resolved "https://registry.yarnpkg.com/content-disposition/-/content-disposition-0.5.3.tgz#e130caf7e7279087c5616c2007d0485698984fbd"
1088+ integrity sha512-ExO0774ikEObIAEV9kDo50o+79VCUdEB6n6lzKgGwupcVeRlhrj3qGAfwq8G6uBJjkqLrhT0qEYFcWng8z1z0g==
1089+ dependencies:
1090+ safe-buffer "5.1.2"
1091+
1092+content-type@~1.0.4:
1093+ version "1.0.4"
1094+ resolved "https://registry.yarnpkg.com/content-type/-/content-type-1.0.4.tgz#e138cc75e040c727b1966fe5e5f8c9aee256fe3b"
1095+ integrity sha512-hIP3EEPs8tB9AT1L+NUqtwOAps4mk2Zob89MWXMHjHWg9milF/j4osnnQLXBCBFBk/tvIG/tUc9mOUJiPBhPXA==
1096+
1097+conventional-changelog-angular@^1.3.3:
1098+ version "1.6.6"
1099+ resolved "https://registry.yarnpkg.com/conventional-changelog-angular/-/conventional-changelog-angular-1.6.6.tgz#b27f2b315c16d0a1f23eb181309d0e6a4698ea0f"
1100+ integrity sha512-suQnFSqCxRwyBxY68pYTsFkG0taIdinHLNEAX5ivtw8bCRnIgnpvcHmlR/yjUyZIrNPYAoXlY1WiEKWgSE4BNg==
1101+ dependencies:
1102+ compare-func "^1.3.1"
1103+ q "^1.5.1"
1104+
1105+conventional-changelog-angular@^5.0.12:
1106+ version "5.0.12"
1107+ resolved "https://registry.yarnpkg.com/conventional-changelog-angular/-/conventional-changelog-angular-5.0.12.tgz#c979b8b921cbfe26402eb3da5bbfda02d865a2b9"
1108+ integrity sha512-5GLsbnkR/7A89RyHLvvoExbiGbd9xKdKqDTrArnPbOqBqG/2wIosu0fHwpeIRI8Tl94MhVNBXcLJZl92ZQ5USw==
1109+ dependencies:
1110+ compare-func "^2.0.0"
1111+ q "^1.5.1"
1112+
1113+conventional-changelog-atom@^2.0.8:
1114+ version "2.0.8"
1115+ resolved "https://registry.yarnpkg.com/conventional-changelog-atom/-/conventional-changelog-atom-2.0.8.tgz#a759ec61c22d1c1196925fca88fe3ae89fd7d8de"
1116+ integrity sha512-xo6v46icsFTK3bb7dY/8m2qvc8sZemRgdqLb/bjpBsH2UyOS8rKNTgcb5025Hri6IpANPApbXMg15QLb1LJpBw==
1117+ dependencies:
1118+ q "^1.5.1"
1119+
1120+conventional-changelog-codemirror@^2.0.8:
1121+ version "2.0.8"
1122+ resolved "https://registry.yarnpkg.com/conventional-changelog-codemirror/-/conventional-changelog-codemirror-2.0.8.tgz#398e9530f08ce34ec4640af98eeaf3022eb1f7dc"
1123+ integrity sha512-z5DAsn3uj1Vfp7po3gpt2Boc+Bdwmw2++ZHa5Ak9k0UKsYAO5mH1UBTN0qSCuJZREIhX6WU4E1p3IW2oRCNzQw==
1124+ dependencies:
1125+ q "^1.5.1"
1126+
1127+conventional-changelog-conventionalcommits@4.2.1:
1128+ version "4.2.1"
1129+ resolved "https://registry.yarnpkg.com/conventional-changelog-conventionalcommits/-/conventional-changelog-conventionalcommits-4.2.1.tgz#d6cb2e2c5d7bfca044a08b9dba84b4082e1a1bd9"
1130+ integrity sha512-vC02KucnkNNap+foDKFm7BVUSDAXktXrUJqGszUuYnt6T0J2azsbYz/w9TDc3VsrW2v6JOtiQWVcgZnporHr4Q==
1131+ dependencies:
1132+ compare-func "^1.3.1"
1133+ lodash "^4.2.1"
1134+ q "^1.5.1"
1135+
1136+conventional-changelog-conventionalcommits@^4.5.0:
1137+ version "4.6.0"
1138+ resolved "https://registry.yarnpkg.com/conventional-changelog-conventionalcommits/-/conventional-changelog-conventionalcommits-4.6.0.tgz#7fc17211dbca160acf24687bd2fdd5fd767750eb"
1139+ integrity sha512-sj9tj3z5cnHaSJCYObA9nISf7eq/YjscLPoq6nmew4SiOjxqL2KRpK20fjnjVbpNDjJ2HR3MoVcWKXwbVvzS0A==
1140+ dependencies:
1141+ compare-func "^2.0.0"
1142+ lodash "^4.17.15"
1143+ q "^1.5.1"
1144+
1145+conventional-changelog-core@^4.2.1:
1146+ version "4.2.3"
1147+ resolved "https://registry.yarnpkg.com/conventional-changelog-core/-/conventional-changelog-core-4.2.3.tgz#ce44d4bbba4032e3dc14c00fcd5b53fc00b66433"
1148+ integrity sha512-MwnZjIoMRL3jtPH5GywVNqetGILC7g6RQFvdb8LRU/fA/338JbeWAku3PZ8yQ+mtVRViiISqJlb0sOz0htBZig==
1149+ dependencies:
1150+ add-stream "^1.0.0"
1151+ conventional-changelog-writer "^5.0.0"
1152+ conventional-commits-parser "^3.2.0"
1153+ dateformat "^3.0.0"
1154+ get-pkg-repo "^4.0.0"
1155+ git-raw-commits "^2.0.8"
1156+ git-remote-origin-url "^2.0.0"
1157+ git-semver-tags "^4.1.1"
1158+ lodash "^4.17.15"
1159+ normalize-package-data "^3.0.0"
1160+ q "^1.5.1"
1161+ read-pkg "^3.0.0"
1162+ read-pkg-up "^3.0.0"
1163+ through2 "^4.0.0"
1164+
1165+conventional-changelog-ember@^2.0.9:
1166+ version "2.0.9"
1167+ resolved "https://registry.yarnpkg.com/conventional-changelog-ember/-/conventional-changelog-ember-2.0.9.tgz#619b37ec708be9e74a220f4dcf79212ae1c92962"
1168+ integrity sha512-ulzIReoZEvZCBDhcNYfDIsLTHzYHc7awh+eI44ZtV5cx6LVxLlVtEmcO+2/kGIHGtw+qVabJYjdI5cJOQgXh1A==
1169+ dependencies:
1170+ q "^1.5.1"
1171+
1172+conventional-changelog-eslint@^3.0.9:
1173+ version "3.0.9"
1174+ resolved "https://registry.yarnpkg.com/conventional-changelog-eslint/-/conventional-changelog-eslint-3.0.9.tgz#689bd0a470e02f7baafe21a495880deea18b7cdb"
1175+ integrity sha512-6NpUCMgU8qmWmyAMSZO5NrRd7rTgErjrm4VASam2u5jrZS0n38V7Y9CzTtLT2qwz5xEChDR4BduoWIr8TfwvXA==
1176+ dependencies:
1177+ q "^1.5.1"
1178+
1179+conventional-changelog-express@^2.0.6:
1180+ version "2.0.6"
1181+ resolved "https://registry.yarnpkg.com/conventional-changelog-express/-/conventional-changelog-express-2.0.6.tgz#420c9d92a347b72a91544750bffa9387665a6ee8"
1182+ integrity sha512-SDez2f3iVJw6V563O3pRtNwXtQaSmEfTCaTBPCqn0oG0mfkq0rX4hHBq5P7De2MncoRixrALj3u3oQsNK+Q0pQ==
1183+ dependencies:
1184+ q "^1.5.1"
1185+
1186+conventional-changelog-jquery@^3.0.11:
1187+ version "3.0.11"
1188+ resolved "https://registry.yarnpkg.com/conventional-changelog-jquery/-/conventional-changelog-jquery-3.0.11.tgz#d142207400f51c9e5bb588596598e24bba8994bf"
1189+ integrity sha512-x8AWz5/Td55F7+o/9LQ6cQIPwrCjfJQ5Zmfqi8thwUEKHstEn4kTIofXub7plf1xvFA2TqhZlq7fy5OmV6BOMw==
1190+ dependencies:
1191+ q "^1.5.1"
1192+
1193+conventional-changelog-jshint@^2.0.9:
1194+ version "2.0.9"
1195+ resolved "https://registry.yarnpkg.com/conventional-changelog-jshint/-/conventional-changelog-jshint-2.0.9.tgz#f2d7f23e6acd4927a238555d92c09b50fe3852ff"
1196+ integrity sha512-wMLdaIzq6TNnMHMy31hql02OEQ8nCQfExw1SE0hYL5KvU+JCTuPaDO+7JiogGT2gJAxiUGATdtYYfh+nT+6riA==
1197+ dependencies:
1198+ compare-func "^2.0.0"
1199+ q "^1.5.1"
1200+
1201+conventional-changelog-preset-loader@^2.3.4:
1202+ version "2.3.4"
1203+ resolved "https://registry.yarnpkg.com/conventional-changelog-preset-loader/-/conventional-changelog-preset-loader-2.3.4.tgz#14a855abbffd59027fd602581f1f34d9862ea44c"
1204+ integrity sha512-GEKRWkrSAZeTq5+YjUZOYxdHq+ci4dNwHvpaBC3+ENalzFWuCWa9EZXSuZBpkr72sMdKB+1fyDV4takK1Lf58g==
1205+
1206+conventional-changelog-writer@^5.0.0:
1207+ version "5.0.0"
1208+ resolved "https://registry.yarnpkg.com/conventional-changelog-writer/-/conventional-changelog-writer-5.0.0.tgz#c4042f3f1542f2f41d7d2e0d6cad23aba8df8eec"
1209+ integrity sha512-HnDh9QHLNWfL6E1uHz6krZEQOgm8hN7z/m7tT16xwd802fwgMN0Wqd7AQYVkhpsjDUx/99oo+nGgvKF657XP5g==
1210+ dependencies:
1211+ conventional-commits-filter "^2.0.7"
1212+ dateformat "^3.0.0"
1213+ handlebars "^4.7.6"
1214+ json-stringify-safe "^5.0.1"
1215+ lodash "^4.17.15"
1216+ meow "^8.0.0"
1217+ semver "^6.0.0"
1218+ split "^1.0.0"
1219+ through2 "^4.0.0"
1220+
1221+conventional-changelog@^3.1.24:
1222+ version "3.1.24"
1223+ resolved "https://registry.yarnpkg.com/conventional-changelog/-/conventional-changelog-3.1.24.tgz#ebd180b0fd1b2e1f0095c4b04fd088698348a464"
1224+ integrity sha512-ed6k8PO00UVvhExYohroVPXcOJ/K1N0/drJHx/faTH37OIZthlecuLIRX/T6uOp682CAoVoFpu+sSEaeuH6Asg==
1225+ dependencies:
1226+ conventional-changelog-angular "^5.0.12"
1227+ conventional-changelog-atom "^2.0.8"
1228+ conventional-changelog-codemirror "^2.0.8"
1229+ conventional-changelog-conventionalcommits "^4.5.0"
1230+ conventional-changelog-core "^4.2.1"
1231+ conventional-changelog-ember "^2.0.9"
1232+ conventional-changelog-eslint "^3.0.9"
1233+ conventional-changelog-express "^2.0.6"
1234+ conventional-changelog-jquery "^3.0.11"
1235+ conventional-changelog-jshint "^2.0.9"
1236+ conventional-changelog-preset-loader "^2.3.4"
1237+
1238+conventional-commits-filter@^2.0.7:
1239+ version "2.0.7"
1240+ resolved "https://registry.yarnpkg.com/conventional-commits-filter/-/conventional-commits-filter-2.0.7.tgz#f8d9b4f182fce00c9af7139da49365b136c8a0b3"
1241+ integrity sha512-ASS9SamOP4TbCClsRHxIHXRfcGCnIoQqkvAzCSbZzTFLfcTqJVugB0agRgsEELsqaeWgsXv513eS116wnlSSPA==
1242+ dependencies:
1243+ lodash.ismatch "^4.4.0"
1244+ modify-values "^1.0.0"
1245+
1246+conventional-commits-parser@^3.0.0, conventional-commits-parser@^3.2.0:
1247+ version "3.2.1"
1248+ resolved "https://registry.yarnpkg.com/conventional-commits-parser/-/conventional-commits-parser-3.2.1.tgz#ba44f0b3b6588da2ee9fd8da508ebff50d116ce2"
1249+ integrity sha512-OG9kQtmMZBJD/32NEw5IhN5+HnBqVjy03eC+I71I0oQRFA5rOgA4OtPOYG7mz1GkCfCNxn3gKIX8EiHJYuf1cA==
1250+ dependencies:
1251+ JSONStream "^1.0.4"
1252+ is-text-path "^1.0.1"
1253+ lodash "^4.17.15"
1254+ meow "^8.0.0"
1255+ split2 "^3.0.0"
1256+ through2 "^4.0.0"
1257+ trim-off-newlines "^1.0.0"
1258+
1259+convert-source-map@^1.5.0:
1260+ version "1.8.0"
1261+ resolved "https://registry.yarnpkg.com/convert-source-map/-/convert-source-map-1.8.0.tgz#f3373c32d21b4d780dd8004514684fb791ca4369"
1262+ integrity sha512-+OQdjP49zViI/6i7nIJpA8rAl4sV/JdPfU9nZs3VqOwGIgizICvuN2ru6fMd+4llL0tar18UYJXfZ/TWtmhUjA==
1263+ dependencies:
1264+ safe-buffer "~5.1.1"
1265+
1266+cookie-signature@1.0.6:
1267+ version "1.0.6"
1268+ resolved "https://registry.yarnpkg.com/cookie-signature/-/cookie-signature-1.0.6.tgz#e303a882b342cc3ee8ca513a79999734dab3ae2c"
1269+ integrity sha1-4wOogrNCzD7oylE6eZmXNNqzriw=
1270+
1271+cookie@0.4.0:
1272+ version "0.4.0"
1273+ resolved "https://registry.yarnpkg.com/cookie/-/cookie-0.4.0.tgz#beb437e7022b3b6d49019d088665303ebe9c14ba"
1274+ integrity sha512-+Hp8fLp57wnUSt0tY0tHEXh4voZRDnoIrZPqlo3DPiI4y9lwg/jqx+1Om94/W6ZaPDOUbnjOt/99w66zk+l1Xg==
1275+
1276+copy-descriptor@^0.1.0:
1277+ version "0.1.1"
1278+ resolved "https://registry.yarnpkg.com/copy-descriptor/-/copy-descriptor-0.1.1.tgz#676f6eb3c39997c2ee1ac3a924fd6124748f578d"
1279+ integrity sha1-Z29us8OZl8LuGsOpJP1hJHSPV40=
1280+
1281+copy-props@^2.0.1:
1282+ version "2.0.5"
1283+ resolved "https://registry.yarnpkg.com/copy-props/-/copy-props-2.0.5.tgz#03cf9ae328d4ebb36f8f1d804448a6af9ee3f2d2"
1284+ integrity sha512-XBlx8HSqrT0ObQwmSzM7WE5k8FxTV75h1DX1Z3n6NhQ/UYYAvInWYmG06vFt7hQZArE2fuO62aihiWIVQwh1sw==
1285+ dependencies:
1286+ each-props "^1.3.2"
1287+ is-plain-object "^5.0.0"
1288+
1289+core-js@^2.4.0, core-js@^2.5.0:
1290+ version "2.6.12"
1291+ resolved "https://registry.yarnpkg.com/core-js/-/core-js-2.6.12.tgz#d9333dfa7b065e347cc5682219d6f690859cc2ec"
1292+ integrity sha512-Kb2wC0fvsWfQrgk8HU5lW6U/Lcs8+9aaYcy4ZFc6DDlo4nZ7n70dEgE5rtR0oG6ufKDUnrwfWL1mXR5ljDatrQ==
1293+
1294+core-util-is@1.0.2, core-util-is@~1.0.0:
1295+ version "1.0.2"
1296+ resolved "https://registry.yarnpkg.com/core-util-is/-/core-util-is-1.0.2.tgz#b5fd54220aa2bc5ab57aab7140c940754503c1a7"
1297+ integrity sha1-tf1UIgqivFq1eqtxQMlAdUUDwac=
1298+
1299+cosmiconfig@^5.2.0:
1300+ version "5.2.1"
1301+ resolved "https://registry.yarnpkg.com/cosmiconfig/-/cosmiconfig-5.2.1.tgz#040f726809c591e77a17c0a3626ca45b4f168b1a"
1302+ integrity sha512-H65gsXo1SKjf8zmrJ67eJk8aIRKV5ff2D4uKZIBZShbhGSpEmsQOPW/SKMKYhSTrqR7ufy6RP69rPogdaPh/kA==
1303+ dependencies:
1304+ import-fresh "^2.0.0"
1305+ is-directory "^0.3.1"
1306+ js-yaml "^3.13.1"
1307+ parse-json "^4.0.0"
1308+
1309+currently-unhandled@^0.4.1:
1310+ version "0.4.1"
1311+ resolved "https://registry.yarnpkg.com/currently-unhandled/-/currently-unhandled-0.4.1.tgz#988df33feab191ef799a61369dd76c17adf957ea"
1312+ integrity sha1-mI3zP+qxke95mmE2nddsF635V+o=
1313+ dependencies:
1314+ array-find-index "^1.0.1"
1315+
1316+d@1, d@^1.0.1:
1317+ version "1.0.1"
1318+ resolved "https://registry.yarnpkg.com/d/-/d-1.0.1.tgz#8698095372d58dbee346ffd0c7093f99f8f9eb5a"
1319+ integrity sha512-m62ShEObQ39CfralilEQRjH6oAMtNCV1xJyEx5LpRYUVN+EviphDgUc/F3hnYbADmkiNs67Y+3ylmlG7Lnu+FA==
1320+ dependencies:
1321+ es5-ext "^0.10.50"
1322+ type "^1.0.1"
1323+
1324+dargs@^7.0.0:
1325+ version "7.0.0"
1326+ resolved "https://registry.yarnpkg.com/dargs/-/dargs-7.0.0.tgz#04015c41de0bcb69ec84050f3d9be0caf8d6d5cc"
1327+ integrity sha512-2iy1EkLdlBzQGvbweYRFxmFath8+K7+AKB0TlhHWkNuH+TmovaMH/Wp7V7R4u7f4SnX3OgLsU9t1NI9ioDnUpg==
1328+
1329+dashdash@^1.12.0:
1330+ version "1.14.1"
1331+ resolved "https://registry.yarnpkg.com/dashdash/-/dashdash-1.14.1.tgz#853cfa0f7cbe2fed5de20326b8dd581035f6e2f0"
1332+ integrity sha1-hTz6D3y+L+1d4gMmuN1YEDX24vA=
1333+ dependencies:
1334+ assert-plus "^1.0.0"
1335+
1336+dateformat@^3.0.0:
1337+ version "3.0.3"
1338+ resolved "https://registry.yarnpkg.com/dateformat/-/dateformat-3.0.3.tgz#a6e37499a4d9a9cf85ef5872044d62901c9889ae"
1339+ integrity sha512-jyCETtSl3VMZMWeRo7iY1FL19ges1t55hMo5yaam4Jrsm5EPL89UQkoQRyiI+Yf4k8r2ZpdngkV8hr1lIdjb3Q==
1340+
1341+debug@2.6.9, debug@^2.2.0, debug@^2.3.3:
1342+ version "2.6.9"
1343+ resolved "https://registry.yarnpkg.com/debug/-/debug-2.6.9.tgz#5d128515df134ff327e90a4c93f4e077a536341f"
1344+ integrity sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==
1345+ dependencies:
1346+ ms "2.0.0"
1347+
1348+decamelize-keys@^1.0.0, decamelize-keys@^1.1.0:
1349+ version "1.1.0"
1350+ resolved "https://registry.yarnpkg.com/decamelize-keys/-/decamelize-keys-1.1.0.tgz#d171a87933252807eb3cb61dc1c1445d078df2d9"
1351+ integrity sha1-0XGoeTMlKAfrPLYdwcFEXQeN8tk=
1352+ dependencies:
1353+ decamelize "^1.1.0"
1354+ map-obj "^1.0.0"
1355+
1356+decamelize@^1.1.0, decamelize@^1.1.1, decamelize@^1.2.0:
1357+ version "1.2.0"
1358+ resolved "https://registry.yarnpkg.com/decamelize/-/decamelize-1.2.0.tgz#f6534d15148269b20352e7bee26f501f9a191290"
1359+ integrity sha1-9lNNFRSCabIDUue+4m9QH5oZEpA=
1360+
1361+decode-uri-component@^0.2.0:
1362+ version "0.2.0"
1363+ resolved "https://registry.yarnpkg.com/decode-uri-component/-/decode-uri-component-0.2.0.tgz#eb3913333458775cb84cd1a1fae062106bb87545"
1364+ integrity sha1-6zkTMzRYd1y4TNGh+uBiEGu4dUU=
1365+
1366+default-compare@^1.0.0:
1367+ version "1.0.0"
1368+ resolved "https://registry.yarnpkg.com/default-compare/-/default-compare-1.0.0.tgz#cb61131844ad84d84788fb68fd01681ca7781a2f"
1369+ integrity sha512-QWfXlM0EkAbqOCbD/6HjdwT19j7WCkMyiRhWilc4H9/5h/RzTF9gv5LYh1+CmDV5d1rki6KAWLtQale0xt20eQ==
1370+ dependencies:
1371+ kind-of "^5.0.2"
1372+
1373+default-resolution@^2.0.0:
1374+ version "2.0.0"
1375+ resolved "https://registry.yarnpkg.com/default-resolution/-/default-resolution-2.0.0.tgz#bcb82baa72ad79b426a76732f1a81ad6df26d684"
1376+ integrity sha1-vLgrqnKtebQmp2cy8aga1t8m1oQ=
1377+
1378+define-properties@^1.1.3:
1379+ version "1.1.3"
1380+ resolved "https://registry.yarnpkg.com/define-properties/-/define-properties-1.1.3.tgz#cf88da6cbee26fe6db7094f61d870cbd84cee9f1"
1381+ integrity sha512-3MqfYKj2lLzdMSf8ZIZE/V+Zuy+BgD6f164e8K2w7dgnpKArBDerGYpM46IYYcjnkdPNMjPk9A6VFB8+3SKlXQ==
1382+ dependencies:
1383+ object-keys "^1.0.12"
1384+
1385+define-property@^0.2.5:
1386+ version "0.2.5"
1387+ resolved "https://registry.yarnpkg.com/define-property/-/define-property-0.2.5.tgz#c35b1ef918ec3c990f9a5bc57be04aacec5c8116"
1388+ integrity sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=
1389+ dependencies:
1390+ is-descriptor "^0.1.0"
1391+
1392+define-property@^1.0.0:
1393+ version "1.0.0"
1394+ resolved "https://registry.yarnpkg.com/define-property/-/define-property-1.0.0.tgz#769ebaaf3f4a63aad3af9e8d304c9bbe79bfb0e6"
1395+ integrity sha1-dp66rz9KY6rTr56NMEybvnm/sOY=
1396+ dependencies:
1397+ is-descriptor "^1.0.0"
1398+
1399+define-property@^2.0.2:
1400+ version "2.0.2"
1401+ resolved "https://registry.yarnpkg.com/define-property/-/define-property-2.0.2.tgz#d459689e8d654ba77e02a817f8710d702cb16e9d"
1402+ integrity sha512-jwK2UV4cnPpbcG7+VRARKTZPUWowwXA8bzH5NP6ud0oeAxyYPuGZUAC7hMugpCdz4BeSZl2Dl9k66CHJ/46ZYQ==
1403+ dependencies:
1404+ is-descriptor "^1.0.2"
1405+ isobject "^3.0.1"
1406+
1407+del@^6.0.0:
1408+ version "6.0.0"
1409+ resolved "https://registry.yarnpkg.com/del/-/del-6.0.0.tgz#0b40d0332cea743f1614f818be4feb717714c952"
1410+ integrity sha512-1shh9DQ23L16oXSZKB2JxpL7iMy2E0S9d517ptA1P8iw0alkPtQcrKH7ru31rYtKwF499HkTu+DRzq3TCKDFRQ==
1411+ dependencies:
1412+ globby "^11.0.1"
1413+ graceful-fs "^4.2.4"
1414+ is-glob "^4.0.1"
1415+ is-path-cwd "^2.2.0"
1416+ is-path-inside "^3.0.2"
1417+ p-map "^4.0.0"
1418+ rimraf "^3.0.2"
1419+ slash "^3.0.0"
1420+
1421+delayed-stream@~1.0.0:
1422+ version "1.0.0"
1423+ resolved "https://registry.yarnpkg.com/delayed-stream/-/delayed-stream-1.0.0.tgz#df3ae199acadfb7d440aaae0b29e2272b24ec619"
1424+ integrity sha1-3zrhmayt+31ECqrgsp4icrJOxhk=
1425+
1426+depd@~1.1.2:
1427+ version "1.1.2"
1428+ resolved "https://registry.yarnpkg.com/depd/-/depd-1.1.2.tgz#9bcd52e14c097763e749b274c4346ed2e560b5a9"
1429+ integrity sha1-m81S4UwJd2PnSbJ0xDRu0uVgtak=
1430+
1431+destroy@~1.0.4:
1432+ version "1.0.4"
1433+ resolved "https://registry.yarnpkg.com/destroy/-/destroy-1.0.4.tgz#978857442c44749e4206613e37946205826abd80"
1434+ integrity sha1-l4hXRCxEdJ5CBmE+N5RiBYJqvYA=
1435+
1436+detect-file@^1.0.0:
1437+ version "1.0.0"
1438+ resolved "https://registry.yarnpkg.com/detect-file/-/detect-file-1.0.0.tgz#f0d66d03672a825cb1b73bdb3fe62310c8e552b7"
1439+ integrity sha1-8NZtA2cqglyxtzvbP+YjEMjlUrc=
1440+
1441+diff@^4.0.1:
1442+ version "4.0.2"
1443+ resolved "https://registry.yarnpkg.com/diff/-/diff-4.0.2.tgz#60f3aecb89d5fae520c11aa19efc2bb982aade7d"
1444+ integrity sha512-58lmxKSA4BNyLz+HHMUzlOEpg09FV+ev6ZMe3vJihgdxzgcwZ8VoEEPmALCZG9LmqfVoNMMKpttIYTVG6uDY7A==
1445+
1446+dir-glob@^3.0.1:
1447+ version "3.0.1"
1448+ resolved "https://registry.yarnpkg.com/dir-glob/-/dir-glob-3.0.1.tgz#56dbf73d992a4a93ba1584f4534063fd2e41717f"
1449+ integrity sha512-WkrWp9GR4KXfKGYzOLmTuGVi1UWFfws377n9cc55/tb6DuqyF6pcQ5AbiHEshaDpY9v6oaSr2XCDidGmMwdzIA==
1450+ dependencies:
1451+ path-type "^4.0.0"
1452+
1453+dot-prop@^3.0.0:
1454+ version "3.0.0"
1455+ resolved "https://registry.yarnpkg.com/dot-prop/-/dot-prop-3.0.0.tgz#1b708af094a49c9a0e7dbcad790aba539dac1177"
1456+ integrity sha1-G3CK8JSknJoOfbyteQq6U52sEXc=
1457+ dependencies:
1458+ is-obj "^1.0.0"
1459+
1460+dot-prop@^5.1.0:
1461+ version "5.3.0"
1462+ resolved "https://registry.yarnpkg.com/dot-prop/-/dot-prop-5.3.0.tgz#90ccce708cd9cd82cc4dc8c3ddd9abdd55b20e88"
1463+ integrity sha512-QM8q3zDe58hqUqjraQOmzZ1LIH9SWQJTlEKCH4kJ2oQvLZk7RbQXvtDM2XEq3fwkV9CCvvH4LA0AV+ogFsBM2Q==
1464+ dependencies:
1465+ is-obj "^2.0.0"
1466+
1467+duplexify@^3.6.0:
1468+ version "3.7.1"
1469+ resolved "https://registry.yarnpkg.com/duplexify/-/duplexify-3.7.1.tgz#2a4df5317f6ccfd91f86d6fd25d8d8a103b88309"
1470+ integrity sha512-07z8uv2wMyS51kKhD1KsdXJg5WQ6t93RneqRxUHnskXVtlYYkLqM0gqStQZ3pj073g687jPCHrqNfCzawLYh5g==
1471+ dependencies:
1472+ end-of-stream "^1.0.0"
1473+ inherits "^2.0.1"
1474+ readable-stream "^2.0.0"
1475+ stream-shift "^1.0.0"
1476+
1477+each-props@^1.3.2:
1478+ version "1.3.2"
1479+ resolved "https://registry.yarnpkg.com/each-props/-/each-props-1.3.2.tgz#ea45a414d16dd5cfa419b1a81720d5ca06892333"
1480+ integrity sha512-vV0Hem3zAGkJAyU7JSjixeU66rwdynTAa1vofCrSA5fEln+m67Az9CcnkVD776/fsN/UjIWmBDoNRS6t6G9RfA==
1481+ dependencies:
1482+ is-plain-object "^2.0.1"
1483+ object.defaults "^1.1.0"
1484+
1485+ecc-jsbn@~0.1.1:
1486+ version "0.1.2"
1487+ resolved "https://registry.yarnpkg.com/ecc-jsbn/-/ecc-jsbn-0.1.2.tgz#3a83a904e54353287874c564b7549386849a98c9"
1488+ integrity sha1-OoOpBOVDUyh4dMVkt1SThoSamMk=
1489+ dependencies:
1490+ jsbn "~0.1.0"
1491+ safer-buffer "^2.1.0"
1492+
1493+ee-first@1.1.1:
1494+ version "1.1.1"
1495+ resolved "https://registry.yarnpkg.com/ee-first/-/ee-first-1.1.1.tgz#590c61156b0ae2f4f0255732a158b266bc56b21d"
1496+ integrity sha1-WQxhFWsK4vTwJVcyoViyZrxWsh0=
1497+
1498+encodeurl@~1.0.2:
1499+ version "1.0.2"
1500+ resolved "https://registry.yarnpkg.com/encodeurl/-/encodeurl-1.0.2.tgz#ad3ff4c86ec2d029322f5a02c3a9a606c95b3f59"
1501+ integrity sha1-rT/0yG7C0CkyL1oCw6mmBslbP1k=
1502+
1503+end-of-stream@^1.0.0, end-of-stream@^1.1.0:
1504+ version "1.4.4"
1505+ resolved "https://registry.yarnpkg.com/end-of-stream/-/end-of-stream-1.4.4.tgz#5ae64a5f45057baf3626ec14da0ca5e4b2431eb0"
1506+ integrity sha512-+uw1inIHVPQoaVuHzRyXd21icM+cnt4CzD5rW+NC1wjOUSTOs+Te7FOv7AhN7vS9x/oIyhLP5PR1H+phQAHu5Q==
1507+ dependencies:
1508+ once "^1.4.0"
1509+
1510+error-ex@^1.2.0, error-ex@^1.3.1:
1511+ version "1.3.2"
1512+ resolved "https://registry.yarnpkg.com/error-ex/-/error-ex-1.3.2.tgz#b4ac40648107fdcdcfae242f428bea8a14d4f1bf"
1513+ integrity sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g==
1514+ dependencies:
1515+ is-arrayish "^0.2.1"
1516+
1517+es5-ext@^0.10.35, es5-ext@^0.10.46, es5-ext@^0.10.50:
1518+ version "0.10.53"
1519+ resolved "https://registry.yarnpkg.com/es5-ext/-/es5-ext-0.10.53.tgz#93c5a3acfdbef275220ad72644ad02ee18368de1"
1520+ integrity sha512-Xs2Stw6NiNHWypzRTY1MtaG/uJlwCk8kH81920ma8mvN8Xq1gsfhZvpkImLQArw8AHnv8MT2I45J3c0R8slE+Q==
1521+ dependencies:
1522+ es6-iterator "~2.0.3"
1523+ es6-symbol "~3.1.3"
1524+ next-tick "~1.0.0"
1525+
1526+es6-iterator@^2.0.1, es6-iterator@^2.0.3, es6-iterator@~2.0.3:
1527+ version "2.0.3"
1528+ resolved "https://registry.yarnpkg.com/es6-iterator/-/es6-iterator-2.0.3.tgz#a7de889141a05a94b0854403b2d0a0fbfa98f3b7"
1529+ integrity sha1-p96IkUGgWpSwhUQDstCg+/qY87c=
1530+ dependencies:
1531+ d "1"
1532+ es5-ext "^0.10.35"
1533+ es6-symbol "^3.1.1"
1534+
1535+es6-symbol@^3.1.1, es6-symbol@~3.1.3:
1536+ version "3.1.3"
1537+ resolved "https://registry.yarnpkg.com/es6-symbol/-/es6-symbol-3.1.3.tgz#bad5d3c1bcdac28269f4cb331e431c78ac705d18"
1538+ integrity sha512-NJ6Yn3FuDinBaBRWl/q5X/s4koRHBrgKAu+yGI6JCBeiu3qrcbJhwT2GeR/EXVfylRk8dpQVJoLEFhK+Mu31NA==
1539+ dependencies:
1540+ d "^1.0.1"
1541+ ext "^1.1.2"
1542+
1543+es6-weak-map@^2.0.1:
1544+ version "2.0.3"
1545+ resolved "https://registry.yarnpkg.com/es6-weak-map/-/es6-weak-map-2.0.3.tgz#b6da1f16cc2cc0d9be43e6bdbfc5e7dfcdf31d53"
1546+ integrity sha512-p5um32HOTO1kP+w7PRnB+5lQ43Z6muuMuIMffvDN8ZB4GcnjLBV6zGStpbASIMk4DCAvEaamhe2zhyCb/QXXsA==
1547+ dependencies:
1548+ d "1"
1549+ es5-ext "^0.10.46"
1550+ es6-iterator "^2.0.3"
1551+ es6-symbol "^3.1.1"
1552+
1553+escape-html@~1.0.3:
1554+ version "1.0.3"
1555+ resolved "https://registry.yarnpkg.com/escape-html/-/escape-html-1.0.3.tgz#0258eae4d3d0c0974de1c169188ef0051d1d1988"
1556+ integrity sha1-Aljq5NPQwJdN4cFpGI7wBR0dGYg=
1557+
1558+escape-string-regexp@^1.0.5:
1559+ version "1.0.5"
1560+ resolved "https://registry.yarnpkg.com/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz#1b61c0562190a8dff6ae3bb2cf0200ca130b86d4"
1561+ integrity sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=
1562+
1563+esprima@^4.0.0:
1564+ version "4.0.1"
1565+ resolved "https://registry.yarnpkg.com/esprima/-/esprima-4.0.1.tgz#13b04cdb3e6c5d19df91ab6987a8695619b0aa71"
1566+ integrity sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==
1567+
1568+etag@~1.8.1:
1569+ version "1.8.1"
1570+ resolved "https://registry.yarnpkg.com/etag/-/etag-1.8.1.tgz#41ae2eeb65efa62268aebfea83ac7d79299b0887"
1571+ integrity sha1-Qa4u62XvpiJorr/qg6x9eSmbCIc=
1572+
1573+expand-brackets@^2.1.4:
1574+ version "2.1.4"
1575+ resolved "https://registry.yarnpkg.com/expand-brackets/-/expand-brackets-2.1.4.tgz#b77735e315ce30f6b6eff0f83b04151a22449622"
1576+ integrity sha1-t3c14xXOMPa27/D4OwQVGiJEliI=
1577+ dependencies:
1578+ debug "^2.3.3"
1579+ define-property "^0.2.5"
1580+ extend-shallow "^2.0.1"
1581+ posix-character-classes "^0.1.0"
1582+ regex-not "^1.0.0"
1583+ snapdragon "^0.8.1"
1584+ to-regex "^3.0.1"
1585+
1586+expand-tilde@^2.0.0, expand-tilde@^2.0.2:
1587+ version "2.0.2"
1588+ resolved "https://registry.yarnpkg.com/expand-tilde/-/expand-tilde-2.0.2.tgz#97e801aa052df02454de46b02bf621642cdc8502"
1589+ integrity sha1-l+gBqgUt8CRU3kawK/YhZCzchQI=
1590+ dependencies:
1591+ homedir-polyfill "^1.0.1"
1592+
1593+express@^4.17.1:
1594+ version "4.17.1"
1595+ resolved "https://registry.yarnpkg.com/express/-/express-4.17.1.tgz#4491fc38605cf51f8629d39c2b5d026f98a4c134"
1596+ integrity sha512-mHJ9O79RqluphRrcw2X/GTh3k9tVv8YcoyY4Kkh4WDMUYKRZUq0h1o0w2rrrxBqM7VoeUVqgb27xlEMXTnYt4g==
1597+ dependencies:
1598+ accepts "~1.3.7"
1599+ array-flatten "1.1.1"
1600+ body-parser "1.19.0"
1601+ content-disposition "0.5.3"
1602+ content-type "~1.0.4"
1603+ cookie "0.4.0"
1604+ cookie-signature "1.0.6"
1605+ debug "2.6.9"
1606+ depd "~1.1.2"
1607+ encodeurl "~1.0.2"
1608+ escape-html "~1.0.3"
1609+ etag "~1.8.1"
1610+ finalhandler "~1.1.2"
1611+ fresh "0.5.2"
1612+ merge-descriptors "1.0.1"
1613+ methods "~1.1.2"
1614+ on-finished "~2.3.0"
1615+ parseurl "~1.3.3"
1616+ path-to-regexp "0.1.7"
1617+ proxy-addr "~2.0.5"
1618+ qs "6.7.0"
1619+ range-parser "~1.2.1"
1620+ safe-buffer "5.1.2"
1621+ send "0.17.1"
1622+ serve-static "1.14.1"
1623+ setprototypeof "1.1.1"
1624+ statuses "~1.5.0"
1625+ type-is "~1.6.18"
1626+ utils-merge "1.0.1"
1627+ vary "~1.1.2"
1628+
1629+ext@^1.1.2:
1630+ version "1.4.0"
1631+ resolved "https://registry.yarnpkg.com/ext/-/ext-1.4.0.tgz#89ae7a07158f79d35517882904324077e4379244"
1632+ integrity sha512-Key5NIsUxdqKg3vIsdw9dSuXpPCQ297y6wBjL30edxwPgt2E44WcWBZey/ZvUc6sERLTxKdyCu4gZFmUbk1Q7A==
1633+ dependencies:
1634+ type "^2.0.0"
1635+
1636+extend-shallow@^1.1.2:
1637+ version "1.1.4"
1638+ resolved "https://registry.yarnpkg.com/extend-shallow/-/extend-shallow-1.1.4.tgz#19d6bf94dfc09d76ba711f39b872d21ff4dd9071"
1639+ integrity sha1-Gda/lN/AnXa6cR85uHLSH/TdkHE=
1640+ dependencies:
1641+ kind-of "^1.1.0"
1642+
1643+extend-shallow@^2.0.1:
1644+ version "2.0.1"
1645+ resolved "https://registry.yarnpkg.com/extend-shallow/-/extend-shallow-2.0.1.tgz#51af7d614ad9a9f610ea1bafbb989d6b1c56890f"
1646+ integrity sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=
1647+ dependencies:
1648+ is-extendable "^0.1.0"
1649+
1650+extend-shallow@^3.0.0, extend-shallow@^3.0.2:
1651+ version "3.0.2"
1652+ resolved "https://registry.yarnpkg.com/extend-shallow/-/extend-shallow-3.0.2.tgz#26a71aaf073b39fb2127172746131c2704028db8"
1653+ integrity sha1-Jqcarwc7OfshJxcnRhMcJwQCjbg=
1654+ dependencies:
1655+ assign-symbols "^1.0.0"
1656+ is-extendable "^1.0.1"
1657+
1658+extend@^3.0.0, extend@~3.0.2:
1659+ version "3.0.2"
1660+ resolved "https://registry.yarnpkg.com/extend/-/extend-3.0.2.tgz#f8b1136b4071fbd8eb140aff858b1019ec2915fa"
1661+ integrity sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g==
1662+
1663+extglob@^2.0.4:
1664+ version "2.0.4"
1665+ resolved "https://registry.yarnpkg.com/extglob/-/extglob-2.0.4.tgz#ad00fe4dc612a9232e8718711dc5cb5ab0285543"
1666+ integrity sha512-Nmb6QXkELsuBr24CJSkilo6UHHgbekK5UiZgfE6UHD3Eb27YC6oD+bhcT+tJ6cl8dmsgdQxnWlcry8ksBIBLpw==
1667+ dependencies:
1668+ array-unique "^0.3.2"
1669+ define-property "^1.0.0"
1670+ expand-brackets "^2.1.4"
1671+ extend-shallow "^2.0.1"
1672+ fragment-cache "^0.2.1"
1673+ regex-not "^1.0.0"
1674+ snapdragon "^0.8.1"
1675+ to-regex "^3.0.1"
1676+
1677+extsprintf@1.3.0:
1678+ version "1.3.0"
1679+ resolved "https://registry.yarnpkg.com/extsprintf/-/extsprintf-1.3.0.tgz#96918440e3041a7a414f8c52e3c574eb3c3e1e05"
1680+ integrity sha1-lpGEQOMEGnpBT4xS48V06zw+HgU=
1681+
1682+extsprintf@^1.2.0:
1683+ version "1.4.0"
1684+ resolved "https://registry.yarnpkg.com/extsprintf/-/extsprintf-1.4.0.tgz#e2689f8f356fad62cca65a3a91c5df5f9551692f"
1685+ integrity sha1-4mifjzVvrWLMplo6kcXfX5VRaS8=
1686+
1687+fancy-log@1.3.3, fancy-log@^1.3.2:
1688+ version "1.3.3"
1689+ resolved "https://registry.yarnpkg.com/fancy-log/-/fancy-log-1.3.3.tgz#dbc19154f558690150a23953a0adbd035be45fc7"
1690+ integrity sha512-k9oEhlyc0FrVh25qYuSELjr8oxsCoc4/LEZfg2iJJrfEk/tZL9bCoJE47gqAvI2m/AUjluCS4+3I0eTx8n3AEw==
1691+ dependencies:
1692+ ansi-gray "^0.1.1"
1693+ color-support "^1.1.3"
1694+ parse-node-version "^1.0.0"
1695+ time-stamp "^1.0.0"
1696+
1697+fast-deep-equal@^3.1.1:
1698+ version "3.1.3"
1699+ resolved "https://registry.yarnpkg.com/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz#3a7d56b559d6cbc3eb512325244e619a65c6c525"
1700+ integrity sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==
1701+
1702+fast-glob@^3.1.1:
1703+ version "3.2.6"
1704+ resolved "https://registry.yarnpkg.com/fast-glob/-/fast-glob-3.2.6.tgz#434dd9529845176ea049acc9343e8282765c6e1a"
1705+ integrity sha512-GnLuqj/pvQ7pX8/L4J84nijv6sAnlwvSDpMkJi9i7nPmPxGtRPkBSStfvDW5l6nMdX9VWe+pkKWFTgD+vF2QSQ==
1706+ dependencies:
1707+ "@nodelib/fs.stat" "^2.0.2"
1708+ "@nodelib/fs.walk" "^1.2.3"
1709+ glob-parent "^5.1.2"
1710+ merge2 "^1.3.0"
1711+ micromatch "^4.0.4"
1712+
1713+fast-json-stable-stringify@^2.0.0:
1714+ version "2.1.0"
1715+ resolved "https://registry.yarnpkg.com/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz#874bf69c6f404c2b5d99c481341399fd55892633"
1716+ integrity sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==
1717+
1718+fast-levenshtein@^1.0.0:
1719+ version "1.1.4"
1720+ resolved "https://registry.yarnpkg.com/fast-levenshtein/-/fast-levenshtein-1.1.4.tgz#e6a754cc8f15e58987aa9cbd27af66fd6f4e5af9"
1721+ integrity sha1-5qdUzI8V5YmHqpy9J69m/W9OWvk=
1722+
1723+fastq@^1.6.0:
1724+ version "1.11.1"
1725+ resolved "https://registry.yarnpkg.com/fastq/-/fastq-1.11.1.tgz#5d8175aae17db61947f8b162cfc7f63264d22807"
1726+ integrity sha512-HOnr8Mc60eNYl1gzwp6r5RoUyAn5/glBolUzP/Ez6IFVPMPirxn/9phgL6zhOtaTy7ISwPvQ+wT+hfcRZh/bzw==
1727+ dependencies:
1728+ reusify "^1.0.4"
1729+
1730+file-uri-to-path@1.0.0:
1731+ version "1.0.0"
1732+ resolved "https://registry.yarnpkg.com/file-uri-to-path/-/file-uri-to-path-1.0.0.tgz#553a7b8446ff6f684359c445f1e37a05dacc33dd"
1733+ integrity sha512-0Zt+s3L7Vf1biwWZ29aARiVYLx7iMGnEUl9x33fbB/j3jR81u/O2LbqK+Bm1CDSNDKVtJ/YjwY7TUd5SkeLQLw==
1734+
1735+fill-range@^4.0.0:
1736+ version "4.0.0"
1737+ resolved "https://registry.yarnpkg.com/fill-range/-/fill-range-4.0.0.tgz#d544811d428f98eb06a63dc402d2403c328c38f7"
1738+ integrity sha1-1USBHUKPmOsGpj3EAtJAPDKMOPc=
1739+ dependencies:
1740+ extend-shallow "^2.0.1"
1741+ is-number "^3.0.0"
1742+ repeat-string "^1.6.1"
1743+ to-regex-range "^2.1.0"
1744+
1745+fill-range@^7.0.1:
1746+ version "7.0.1"
1747+ resolved "https://registry.yarnpkg.com/fill-range/-/fill-range-7.0.1.tgz#1919a6a7c75fe38b2c7c77e5198535da9acdda40"
1748+ integrity sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==
1749+ dependencies:
1750+ to-regex-range "^5.0.1"
1751+
1752+finalhandler@~1.1.2:
1753+ version "1.1.2"
1754+ resolved "https://registry.yarnpkg.com/finalhandler/-/finalhandler-1.1.2.tgz#b7e7d000ffd11938d0fdb053506f6ebabe9f587d"
1755+ integrity sha512-aAWcW57uxVNrQZqFXjITpW3sIUQmHGG3qSb9mUah9MgMC4NeWhNOlNjXEYq3HjRAvL6arUviZGGJsBg6z0zsWA==
1756+ dependencies:
1757+ debug "2.6.9"
1758+ encodeurl "~1.0.2"
1759+ escape-html "~1.0.3"
1760+ on-finished "~2.3.0"
1761+ parseurl "~1.3.3"
1762+ statuses "~1.5.0"
1763+ unpipe "~1.0.0"
1764+
1765+find-up@^1.0.0:
1766+ version "1.1.2"
1767+ resolved "https://registry.yarnpkg.com/find-up/-/find-up-1.1.2.tgz#6b2e9822b1a2ce0a60ab64d610eccad53cb24d0f"
1768+ integrity sha1-ay6YIrGizgpgq2TWEOzK1TyyTQ8=
1769+ dependencies:
1770+ path-exists "^2.0.0"
1771+ pinkie-promise "^2.0.0"
1772+
1773+find-up@^2.0.0:
1774+ version "2.1.0"
1775+ resolved "https://registry.yarnpkg.com/find-up/-/find-up-2.1.0.tgz#45d1b7e506c717ddd482775a2b77920a3c0c57a7"
1776+ integrity sha1-RdG35QbHF93UgndaK3eSCjwMV6c=
1777+ dependencies:
1778+ locate-path "^2.0.0"
1779+
1780+find-up@^4.0.0, find-up@^4.1.0:
1781+ version "4.1.0"
1782+ resolved "https://registry.yarnpkg.com/find-up/-/find-up-4.1.0.tgz#97afe7d6cdc0bc5928584b7c8d7b16e8a9aa5d19"
1783+ integrity sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==
1784+ dependencies:
1785+ locate-path "^5.0.0"
1786+ path-exists "^4.0.0"
1787+
1788+findup-sync@^2.0.0:
1789+ version "2.0.0"
1790+ resolved "https://registry.yarnpkg.com/findup-sync/-/findup-sync-2.0.0.tgz#9326b1488c22d1a6088650a86901b2d9a90a2cbc"
1791+ integrity sha1-kyaxSIwi0aYIhlCoaQGy2akKLLw=
1792+ dependencies:
1793+ detect-file "^1.0.0"
1794+ is-glob "^3.1.0"
1795+ micromatch "^3.0.4"
1796+ resolve-dir "^1.0.1"
1797+
1798+findup-sync@^3.0.0:
1799+ version "3.0.0"
1800+ resolved "https://registry.yarnpkg.com/findup-sync/-/findup-sync-3.0.0.tgz#17b108f9ee512dfb7a5c7f3c8b27ea9e1a9c08d1"
1801+ integrity sha512-YbffarhcicEhOrm4CtrwdKBdCuz576RLdhJDsIfvNtxUuhdRet1qZcsMjqbePtAseKdAnDyM/IyXbu7PRPRLYg==
1802+ dependencies:
1803+ detect-file "^1.0.0"
1804+ is-glob "^4.0.0"
1805+ micromatch "^3.0.4"
1806+ resolve-dir "^1.0.1"
1807+
1808+fined@^1.0.1:
1809+ version "1.2.0"
1810+ resolved "https://registry.yarnpkg.com/fined/-/fined-1.2.0.tgz#d00beccf1aa2b475d16d423b0238b713a2c4a37b"
1811+ integrity sha512-ZYDqPLGxDkDhDZBjZBb+oD1+j0rA4E0pXY50eplAAOPg2N/gUBSSk5IM1/QhPfyVo19lJ+CvXpqfvk+b2p/8Ng==
1812+ dependencies:
1813+ expand-tilde "^2.0.2"
1814+ is-plain-object "^2.0.3"
1815+ object.defaults "^1.1.0"
1816+ object.pick "^1.2.0"
1817+ parse-filepath "^1.0.1"
1818+
1819+first-chunk-stream@^2.0.0:
1820+ version "2.0.0"
1821+ resolved "https://registry.yarnpkg.com/first-chunk-stream/-/first-chunk-stream-2.0.0.tgz#1bdecdb8e083c0664b91945581577a43a9f31d70"
1822+ integrity sha1-G97NuOCDwGZLkZRVgVd6Q6nzHXA=
1823+ dependencies:
1824+ readable-stream "^2.0.2"
1825+
1826+flagged-respawn@^1.0.0:
1827+ version "1.0.1"
1828+ resolved "https://registry.yarnpkg.com/flagged-respawn/-/flagged-respawn-1.0.1.tgz#e7de6f1279ddd9ca9aac8a5971d618606b3aab41"
1829+ integrity sha512-lNaHNVymajmk0OJMBn8fVUAU1BtDeKIqKoVhk4xAALB57aALg6b4W0MfJ/cUE0g9YBXy5XhSlPIpYIJ7HaY/3Q==
1830+
1831+flush-write-stream@^1.0.2:
1832+ version "1.1.1"
1833+ resolved "https://registry.yarnpkg.com/flush-write-stream/-/flush-write-stream-1.1.1.tgz#8dd7d873a1babc207d94ead0c2e0e44276ebf2e8"
1834+ integrity sha512-3Z4XhFZ3992uIq0XOqb9AreonueSYphE6oYbpt5+3u06JWklbsPkNv3ZKkP9Bz/r+1MWCaMoSQ28P85+1Yc77w==
1835+ dependencies:
1836+ inherits "^2.0.3"
1837+ readable-stream "^2.3.6"
1838+
1839+for-in@^1.0.1, for-in@^1.0.2:
1840+ version "1.0.2"
1841+ resolved "https://registry.yarnpkg.com/for-in/-/for-in-1.0.2.tgz#81068d295a8142ec0ac726c6e2200c30fb6d5e80"
1842+ integrity sha1-gQaNKVqBQuwKxybG4iAMMPttXoA=
1843+
1844+for-own@^1.0.0:
1845+ version "1.0.0"
1846+ resolved "https://registry.yarnpkg.com/for-own/-/for-own-1.0.0.tgz#c63332f415cedc4b04dbfe70cf836494c53cb44b"
1847+ integrity sha1-xjMy9BXO3EsE2/5wz4NklMU8tEs=
1848+ dependencies:
1849+ for-in "^1.0.1"
1850+
1851+forever-agent@~0.6.1:
1852+ version "0.6.1"
1853+ resolved "https://registry.yarnpkg.com/forever-agent/-/forever-agent-0.6.1.tgz#fbc71f0c41adeb37f96c577ad1ed42d8fdacca91"
1854+ integrity sha1-+8cfDEGt6zf5bFd60e1C2P2sypE=
1855+
1856+form-data@^2.5.0:
1857+ version "2.5.1"
1858+ resolved "https://registry.yarnpkg.com/form-data/-/form-data-2.5.1.tgz#f2cbec57b5e59e23716e128fe44d4e5dd23895f4"
1859+ integrity sha512-m21N3WOmEEURgk6B9GLOE4RuWOFf28Lhh9qGYeNlGq4VDXUlJy2th2slBNU8Gp8EzloYZOibZJ7t5ecIrFSjVA==
1860+ dependencies:
1861+ asynckit "^0.4.0"
1862+ combined-stream "^1.0.6"
1863+ mime-types "^2.1.12"
1864+
1865+form-data@~2.3.2:
1866+ version "2.3.3"
1867+ resolved "https://registry.yarnpkg.com/form-data/-/form-data-2.3.3.tgz#dcce52c05f644f298c6a7ab936bd724ceffbf3a6"
1868+ integrity sha512-1lLKB2Mu3aGP1Q/2eCOx0fNbRMe7XdwktwOruhfqqd0rIJWwN4Dh+E3hrPSlDCXnSR7UtZ1N38rVXm+6+MEhJQ==
1869+ dependencies:
1870+ asynckit "^0.4.0"
1871+ combined-stream "^1.0.6"
1872+ mime-types "^2.1.12"
1873+
1874+forwarded@0.2.0:
1875+ version "0.2.0"
1876+ resolved "https://registry.yarnpkg.com/forwarded/-/forwarded-0.2.0.tgz#2269936428aad4c15c7ebe9779a84bf0b2a81811"
1877+ integrity sha512-buRG0fpBtRHSTCOASe6hD258tEubFoRLb4ZNA6NxMVHNw2gOcwHo9wyablzMzOA5z9xA9L1KNjk/Nt6MT9aYow==
1878+
1879+fragment-cache@^0.2.1:
1880+ version "0.2.1"
1881+ resolved "https://registry.yarnpkg.com/fragment-cache/-/fragment-cache-0.2.1.tgz#4290fad27f13e89be7f33799c6bc5a0abfff0d19"
1882+ integrity sha1-QpD60n8T6Jvn8zeZxrxaCr//DRk=
1883+ dependencies:
1884+ map-cache "^0.2.2"
1885+
1886+fresh@0.5.2:
1887+ version "0.5.2"
1888+ resolved "https://registry.yarnpkg.com/fresh/-/fresh-0.5.2.tgz#3d8cadd90d976569fa835ab1f8e4b23a105605a7"
1889+ integrity sha1-PYyt2Q2XZWn6g1qx+OSyOhBWBac=
1890+
1891+fs-mkdirp-stream@^1.0.0:
1892+ version "1.0.0"
1893+ resolved "https://registry.yarnpkg.com/fs-mkdirp-stream/-/fs-mkdirp-stream-1.0.0.tgz#0b7815fc3201c6a69e14db98ce098c16935259eb"
1894+ integrity sha1-C3gV/DIBxqaeFNuYzgmMFpNSWes=
1895+ dependencies:
1896+ graceful-fs "^4.1.11"
1897+ through2 "^2.0.3"
1898+
1899+fs.realpath@^1.0.0:
1900+ version "1.0.0"
1901+ resolved "https://registry.yarnpkg.com/fs.realpath/-/fs.realpath-1.0.0.tgz#1504ad2523158caa40db4a2787cb01411994ea4f"
1902+ integrity sha1-FQStJSMVjKpA20onh8sBQRmU6k8=
1903+
1904+fsevents@^1.2.7:
1905+ version "1.2.13"
1906+ resolved "https://registry.yarnpkg.com/fsevents/-/fsevents-1.2.13.tgz#f325cb0455592428bcf11b383370ef70e3bfcc38"
1907+ integrity sha512-oWb1Z6mkHIskLzEJ/XWX0srkpkTQ7vaopMQkyaEIoq0fmtFVxOthb8cCxeT+p3ynTdkk/RZwbgG4brR5BeWECw==
1908+ dependencies:
1909+ bindings "^1.5.0"
1910+ nan "^2.12.1"
1911+
1912+function-bind@^1.1.1:
1913+ version "1.1.1"
1914+ resolved "https://registry.yarnpkg.com/function-bind/-/function-bind-1.1.1.tgz#a56899d3ea3c9bab874bb9773b7c5ede92f4895d"
1915+ integrity sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==
1916+
1917+get-caller-file@^1.0.1:
1918+ version "1.0.3"
1919+ resolved "https://registry.yarnpkg.com/get-caller-file/-/get-caller-file-1.0.3.tgz#f978fa4c90d1dfe7ff2d6beda2a515e713bdcf4a"
1920+ integrity sha512-3t6rVToeoZfYSGd8YoLFR2DJkiQrIiUrGcjvFX2mDw3bn6k2OtwHN0TNCLbBO+w8qTvimhDkv+LSscbJY1vE6w==
1921+
1922+get-intrinsic@^1.0.2:
1923+ version "1.1.1"
1924+ resolved "https://registry.yarnpkg.com/get-intrinsic/-/get-intrinsic-1.1.1.tgz#15f59f376f855c446963948f0d24cd3637b4abc6"
1925+ integrity sha512-kWZrnVM42QCiEA2Ig1bG8zjoIMOgxWwYCEeNdwY6Tv/cOSeGpcoX4pXHfKUxNKVoArnrEr2e9srnAxxGIraS9Q==
1926+ dependencies:
1927+ function-bind "^1.1.1"
1928+ has "^1.0.3"
1929+ has-symbols "^1.0.1"
1930+
1931+get-pkg-repo@^4.0.0:
1932+ version "4.1.2"
1933+ resolved "https://registry.yarnpkg.com/get-pkg-repo/-/get-pkg-repo-4.1.2.tgz#c4ffd60015cf091be666a0212753fc158f01a4c0"
1934+ integrity sha512-/FjamZL9cBYllEbReZkxF2IMh80d8TJoC4e3bmLNif8ibHw95aj0N/tzqK0kZz9eU/3w3dL6lF4fnnX/sDdW3A==
1935+ dependencies:
1936+ "@hutson/parse-repository-url" "^3.0.0"
1937+ hosted-git-info "^4.0.0"
1938+ meow "^7.0.0"
1939+ through2 "^2.0.0"
1940+
1941+get-stdin@7.0.0:
1942+ version "7.0.0"
1943+ resolved "https://registry.yarnpkg.com/get-stdin/-/get-stdin-7.0.0.tgz#8d5de98f15171a125c5e516643c7a6d0ea8a96f6"
1944+ integrity sha512-zRKcywvrXlXsA0v0i9Io4KDRaAw7+a1ZpjRwl9Wox8PFlVCCHra7E9c4kqXCoCM9nR5tBkaTTZRBoCm60bFqTQ==
1945+
1946+get-value@^2.0.3, get-value@^2.0.6:
1947+ version "2.0.6"
1948+ resolved "https://registry.yarnpkg.com/get-value/-/get-value-2.0.6.tgz#dc15ca1c672387ca76bd37ac0a395ba2042a2c28"
1949+ integrity sha1-3BXKHGcjh8p2vTesCjlbogQqLCg=
1950+
1951+getpass@^0.1.1:
1952+ version "0.1.7"
1953+ resolved "https://registry.yarnpkg.com/getpass/-/getpass-0.1.7.tgz#5eff8e3e684d569ae4cb2b1282604e8ba62149fa"
1954+ integrity sha1-Xv+OPmhNVprkyysSgmBOi6YhSfo=
1955+ dependencies:
1956+ assert-plus "^1.0.0"
1957+
1958+git-raw-commits@^2.0.0, git-raw-commits@^2.0.8:
1959+ version "2.0.10"
1960+ resolved "https://registry.yarnpkg.com/git-raw-commits/-/git-raw-commits-2.0.10.tgz#e2255ed9563b1c9c3ea6bd05806410290297bbc1"
1961+ integrity sha512-sHhX5lsbG9SOO6yXdlwgEMQ/ljIn7qMpAbJZCGfXX2fq5T8M5SrDnpYk9/4HswTildcIqatsWa91vty6VhWSaQ==
1962+ dependencies:
1963+ dargs "^7.0.0"
1964+ lodash "^4.17.15"
1965+ meow "^8.0.0"
1966+ split2 "^3.0.0"
1967+ through2 "^4.0.0"
1968+
1969+git-remote-origin-url@^2.0.0:
1970+ version "2.0.0"
1971+ resolved "https://registry.yarnpkg.com/git-remote-origin-url/-/git-remote-origin-url-2.0.0.tgz#5282659dae2107145a11126112ad3216ec5fa65f"
1972+ integrity sha1-UoJlna4hBxRaERJhEq0yFuxfpl8=
1973+ dependencies:
1974+ gitconfiglocal "^1.0.0"
1975+ pify "^2.3.0"
1976+
1977+git-semver-tags@^4.1.1:
1978+ version "4.1.1"
1979+ resolved "https://registry.yarnpkg.com/git-semver-tags/-/git-semver-tags-4.1.1.tgz#63191bcd809b0ec3e151ba4751c16c444e5b5780"
1980+ integrity sha512-OWyMt5zBe7xFs8vglMmhM9lRQzCWL3WjHtxNNfJTMngGym7pC1kh8sP6jevfydJ6LP3ZvGxfb6ABYgPUM0mtsA==
1981+ dependencies:
1982+ meow "^8.0.0"
1983+ semver "^6.0.0"
1984+
1985+gitconfiglocal@^1.0.0:
1986+ version "1.0.0"
1987+ resolved "https://registry.yarnpkg.com/gitconfiglocal/-/gitconfiglocal-1.0.0.tgz#41d045f3851a5ea88f03f24ca1c6178114464b9b"
1988+ integrity sha1-QdBF84UaXqiPA/JMocYXgRRGS5s=
1989+ dependencies:
1990+ ini "^1.3.2"
1991+
1992+glob-parent@^3.1.0:
1993+ version "3.1.0"
1994+ resolved "https://registry.yarnpkg.com/glob-parent/-/glob-parent-3.1.0.tgz#9e6af6299d8d3bd2bd40430832bd113df906c5ae"
1995+ integrity sha1-nmr2KZ2NO9K9QEMIMr0RPfkGxa4=
1996+ dependencies:
1997+ is-glob "^3.1.0"
1998+ path-dirname "^1.0.0"
1999+
2000+glob-parent@^5.1.2:
2001+ version "5.1.2"
2002+ resolved "https://registry.yarnpkg.com/glob-parent/-/glob-parent-5.1.2.tgz#869832c58034fe68a4093c17dc15e8340d8401c4"
2003+ integrity sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==
2004+ dependencies:
2005+ is-glob "^4.0.1"
2006+
2007+glob-stream@^6.1.0:
2008+ version "6.1.0"
2009+ resolved "https://registry.yarnpkg.com/glob-stream/-/glob-stream-6.1.0.tgz#7045c99413b3eb94888d83ab46d0b404cc7bdde4"
2010+ integrity sha1-cEXJlBOz65SIjYOrRtC0BMx73eQ=
2011+ dependencies:
2012+ extend "^3.0.0"
2013+ glob "^7.1.1"
2014+ glob-parent "^3.1.0"
2015+ is-negated-glob "^1.0.0"
2016+ ordered-read-streams "^1.0.0"
2017+ pumpify "^1.3.5"
2018+ readable-stream "^2.1.5"
2019+ remove-trailing-separator "^1.0.1"
2020+ to-absolute-glob "^2.0.0"
2021+ unique-stream "^2.0.2"
2022+
2023+glob-watcher@^5.0.3:
2024+ version "5.0.5"
2025+ resolved "https://registry.yarnpkg.com/glob-watcher/-/glob-watcher-5.0.5.tgz#aa6bce648332924d9a8489be41e3e5c52d4186dc"
2026+ integrity sha512-zOZgGGEHPklZNjZQaZ9f41i7F2YwE+tS5ZHrDhbBCk3stwahn5vQxnFmBJZHoYdusR6R1bLSXeGUy/BhctwKzw==
2027+ dependencies:
2028+ anymatch "^2.0.0"
2029+ async-done "^1.2.0"
2030+ chokidar "^2.0.0"
2031+ is-negated-glob "^1.0.0"
2032+ just-debounce "^1.0.0"
2033+ normalize-path "^3.0.0"
2034+ object.defaults "^1.1.0"
2035+
2036+glob@^7.1.1, glob@^7.1.3, glob@^7.1.6:
2037+ version "7.1.7"
2038+ resolved "https://registry.yarnpkg.com/glob/-/glob-7.1.7.tgz#3b193e9233f01d42d0b3f78294bbeeb418f94a90"
2039+ integrity sha512-OvD9ENzPLbegENnYP5UUfJIirTg4+XwMWGaQfQTY0JenxNvvIKP3U3/tAQSPIu/lHxXYSZmpXlUHeqAIdKzBLQ==
2040+ dependencies:
2041+ fs.realpath "^1.0.0"
2042+ inflight "^1.0.4"
2043+ inherits "2"
2044+ minimatch "^3.0.4"
2045+ once "^1.3.0"
2046+ path-is-absolute "^1.0.0"
2047+
2048+global-dirs@^0.1.1:
2049+ version "0.1.1"
2050+ resolved "https://registry.yarnpkg.com/global-dirs/-/global-dirs-0.1.1.tgz#b319c0dd4607f353f3be9cca4c72fc148c49f445"
2051+ integrity sha1-sxnA3UYH81PzvpzKTHL8FIxJ9EU=
2052+ dependencies:
2053+ ini "^1.3.4"
2054+
2055+global-modules@^1.0.0:
2056+ version "1.0.0"
2057+ resolved "https://registry.yarnpkg.com/global-modules/-/global-modules-1.0.0.tgz#6d770f0eb523ac78164d72b5e71a8877265cc3ea"
2058+ integrity sha512-sKzpEkf11GpOFuw0Zzjzmt4B4UZwjOcG757PPvrfhxcLFbq0wpsgpOqxpxtxFiCG4DtG93M6XRVbF2oGdev7bg==
2059+ dependencies:
2060+ global-prefix "^1.0.1"
2061+ is-windows "^1.0.1"
2062+ resolve-dir "^1.0.0"
2063+
2064+global-prefix@^1.0.1:
2065+ version "1.0.2"
2066+ resolved "https://registry.yarnpkg.com/global-prefix/-/global-prefix-1.0.2.tgz#dbf743c6c14992593c655568cb66ed32c0122ebe"
2067+ integrity sha1-2/dDxsFJklk8ZVVoy2btMsASLr4=
2068+ dependencies:
2069+ expand-tilde "^2.0.2"
2070+ homedir-polyfill "^1.0.1"
2071+ ini "^1.3.4"
2072+ is-windows "^1.0.1"
2073+ which "^1.2.14"
2074+
2075+globby@^11.0.1:
2076+ version "11.0.4"
2077+ resolved "https://registry.yarnpkg.com/globby/-/globby-11.0.4.tgz#2cbaff77c2f2a62e71e9b2813a67b97a3a3001a5"
2078+ integrity sha512-9O4MVG9ioZJ08ffbcyVYyLOJLk5JQ688pJ4eMGLpdWLHq/Wr1D9BlriLQyL0E+jbkuePVZXYFj47QM/v093wHg==
2079+ dependencies:
2080+ array-union "^2.1.0"
2081+ dir-glob "^3.0.1"
2082+ fast-glob "^3.1.1"
2083+ ignore "^5.1.4"
2084+ merge2 "^1.3.0"
2085+ slash "^3.0.0"
2086+
2087+glogg@^1.0.0:
2088+ version "1.0.2"
2089+ resolved "https://registry.yarnpkg.com/glogg/-/glogg-1.0.2.tgz#2d7dd702beda22eb3bffadf880696da6d846313f"
2090+ integrity sha512-5mwUoSuBk44Y4EshyiqcH95ZntbDdTQqA3QYSrxmzj28Ai0vXBGMH1ApSANH14j2sIRtqCEyg6PfsuP7ElOEDA==
2091+ dependencies:
2092+ sparkles "^1.0.0"
2093+
2094+graceful-fs@^4.0.0, graceful-fs@^4.1.11, graceful-fs@^4.1.2, graceful-fs@^4.1.3, graceful-fs@^4.1.6, graceful-fs@^4.2.4:
2095+ version "4.2.6"
2096+ resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.2.6.tgz#ff040b2b0853b23c3d31027523706f1885d76bee"
2097+ integrity sha512-nTnJ528pbqxYanhpDYsi4Rd8MAeaBA67+RZ10CM1m3bTAVFEDcd5AuA4a6W5YkGZ1iNXHzZz8T6TBKLeBuNriQ==
2098+
2099+gulp-clean@^0.4.0:
2100+ version "0.4.0"
2101+ resolved "https://registry.yarnpkg.com/gulp-clean/-/gulp-clean-0.4.0.tgz#3bc25e7084e641bbd7bde057cf90c01c50d95950"
2102+ integrity sha512-DARK8rNMo4lHOFLGTiHEJdf19GuoBDHqGUaypz+fOhrvOs3iFO7ntdYtdpNxv+AzSJBx/JfypF0yEj9ks1IStQ==
2103+ dependencies:
2104+ fancy-log "^1.3.2"
2105+ plugin-error "^0.1.2"
2106+ rimraf "^2.6.2"
2107+ through2 "^2.0.3"
2108+ vinyl "^2.1.0"
2109+
2110+gulp-cli@^2.2.0:
2111+ version "2.3.0"
2112+ resolved "https://registry.yarnpkg.com/gulp-cli/-/gulp-cli-2.3.0.tgz#ec0d380e29e52aa45e47977f0d32e18fd161122f"
2113+ integrity sha512-zzGBl5fHo0EKSXsHzjspp3y5CONegCm8ErO5Qh0UzFzk2y4tMvzLWhoDokADbarfZRL2pGpRp7yt6gfJX4ph7A==
2114+ dependencies:
2115+ ansi-colors "^1.0.1"
2116+ archy "^1.0.0"
2117+ array-sort "^1.0.0"
2118+ color-support "^1.1.3"
2119+ concat-stream "^1.6.0"
2120+ copy-props "^2.0.1"
2121+ fancy-log "^1.3.2"
2122+ gulplog "^1.0.0"
2123+ interpret "^1.4.0"
2124+ isobject "^3.0.1"
2125+ liftoff "^3.1.0"
2126+ matchdep "^2.0.0"
2127+ mute-stdout "^1.0.0"
2128+ pretty-hrtime "^1.0.0"
2129+ replace-homedir "^1.0.0"
2130+ semver-greatest-satisfied-range "^1.1.0"
2131+ v8flags "^3.2.0"
2132+ yargs "^7.1.0"
2133+
2134+gulp-conventional-changelog@^2.0.32:
2135+ version "2.0.35"
2136+ resolved "https://registry.yarnpkg.com/gulp-conventional-changelog/-/gulp-conventional-changelog-2.0.35.tgz#4ef5391ea46cca4b35fd262586e99de6d2c7017b"
2137+ integrity sha512-9khc2fGUc6qWUoQYnqck6/d28lIgP+49kOyYtOIJtp6pthqikSL1UQ8n+Erg9X/z83+z9OX1HWWuVIXbpxvdkw==
2138+ dependencies:
2139+ add-stream "^1.0.0"
2140+ concat-stream "^2.0.0"
2141+ conventional-changelog "^3.1.24"
2142+ fancy-log "^1.3.2"
2143+ object-assign "^4.0.1"
2144+ plugin-error "^1.0.1"
2145+ through2 "^4.0.0"
2146+
2147+gulp-filter@^6.0.0:
2148+ version "6.0.0"
2149+ resolved "https://registry.yarnpkg.com/gulp-filter/-/gulp-filter-6.0.0.tgz#9d69a408f1a9f60534264fb14464841f1b1746c2"
2150+ integrity sha512-veQFW93kf6jBdWdF/RxMEIlDK2mkjHyPftM381DID2C9ImTVngwYpyyThxm4/EpgcNOT37BLefzMOjEKbyYg0Q==
2151+ dependencies:
2152+ multimatch "^4.0.0"
2153+ plugin-error "^1.0.1"
2154+ streamfilter "^3.0.0"
2155+
2156+gulp-git@^2.10.1:
2157+ version "2.10.1"
2158+ resolved "https://registry.yarnpkg.com/gulp-git/-/gulp-git-2.10.1.tgz#218615c94bbf90660c1cb07a37054041d5e4f2eb"
2159+ integrity sha512-qiXYYDXchMZU/AWAgtphi4zbJb/0gXgfPw7TlZwu/7qPS3Bdcc3zbVe1B0xY9S8on6RQTmWoi+KaTGACIXQeNg==
2160+ dependencies:
2161+ any-shell-escape "^0.1.1"
2162+ fancy-log "^1.3.2"
2163+ lodash.template "^4.4.0"
2164+ plugin-error "^1.0.1"
2165+ require-dir "^1.0.0"
2166+ strip-bom-stream "^3.0.0"
2167+ through2 "^2.0.3"
2168+ vinyl "^2.0.1"
2169+
2170+gulp-jasmine@^4.0.0:
2171+ version "4.0.0"
2172+ resolved "https://registry.yarnpkg.com/gulp-jasmine/-/gulp-jasmine-4.0.0.tgz#efe566b8350f41a14f63ffaecc6ccdf8646709a9"
2173+ integrity sha512-0UqY2fA6RCdUDJDsVym3zXYSWmt0AV7YY/6PAeKb+oGTKEgS7zZOH5w/4gcSKs+2FXiWrucQwLDvtEKIDbpF4A==
2174+ dependencies:
2175+ arrify "^1.0.1"
2176+ jasmine "^3.1.0"
2177+ jasmine-terminal-reporter "^1.0.3"
2178+ plugin-error "^1.0.1"
2179+ through2 "^2.0.3"
2180+
2181+gulp-tslint@^8.1.4:
2182+ version "8.1.4"
2183+ resolved "https://registry.yarnpkg.com/gulp-tslint/-/gulp-tslint-8.1.4.tgz#8519ee25ff97aa749e691d4af0fdaccce5f01f7a"
2184+ integrity sha512-wBoZIEMJRz9urHwolsvQpngA9l931p6g/Liwz1b/KrsVP6jEBFZv/o0NS1TFCQZi/l8mXxz8+v3twhf4HOXxPQ==
2185+ dependencies:
2186+ "@types/fancy-log" "1.3.0"
2187+ ansi-colors "^1.0.1"
2188+ fancy-log "1.3.3"
2189+ map-stream "~0.0.7"
2190+ plugin-error "1.0.1"
2191+ through "~2.3.8"
2192+
2193+gulp-typescript@^5.0.1:
2194+ version "5.0.1"
2195+ resolved "https://registry.yarnpkg.com/gulp-typescript/-/gulp-typescript-5.0.1.tgz#96c6565a6eb31e08c2aae1c857b1a079e6226d94"
2196+ integrity sha512-YuMMlylyJtUSHG1/wuSVTrZp60k1dMEFKYOvDf7OvbAJWrDtxxD4oZon4ancdWwzjj30ztiidhe4VXJniF0pIQ==
2197+ dependencies:
2198+ ansi-colors "^3.0.5"
2199+ plugin-error "^1.0.1"
2200+ source-map "^0.7.3"
2201+ through2 "^3.0.0"
2202+ vinyl "^2.1.0"
2203+ vinyl-fs "^3.0.3"
2204+
2205+gulp@^4.0.2:
2206+ version "4.0.2"
2207+ resolved "https://registry.yarnpkg.com/gulp/-/gulp-4.0.2.tgz#543651070fd0f6ab0a0650c6a3e6ff5a7cb09caa"
2208+ integrity sha512-dvEs27SCZt2ibF29xYgmnwwCYZxdxhQ/+LFWlbAW8y7jt68L/65402Lz3+CKy0Ov4rOs+NERmDq7YlZaDqUIfA==
2209+ dependencies:
2210+ glob-watcher "^5.0.3"
2211+ gulp-cli "^2.2.0"
2212+ undertaker "^1.2.1"
2213+ vinyl-fs "^3.0.0"
2214+
2215+gulplog@^1.0.0:
2216+ version "1.0.0"
2217+ resolved "https://registry.yarnpkg.com/gulplog/-/gulplog-1.0.0.tgz#e28c4d45d05ecbbed818363ce8f9c5926229ffe5"
2218+ integrity sha1-4oxNRdBey77YGDY86PnFkmIp/+U=
2219+ dependencies:
2220+ glogg "^1.0.0"
2221+
2222+handlebars@^4.7.6:
2223+ version "4.7.7"
2224+ resolved "https://registry.yarnpkg.com/handlebars/-/handlebars-4.7.7.tgz#9ce33416aad02dbd6c8fafa8240d5d98004945a1"
2225+ integrity sha512-aAcXm5OAfE/8IXkcZvCepKU3VzW1/39Fb5ZuqMtgI/hT8X2YgoMvBY5dLhq/cpOvw7Lk1nK/UF71aLG/ZnVYRA==
2226+ dependencies:
2227+ minimist "^1.2.5"
2228+ neo-async "^2.6.0"
2229+ source-map "^0.6.1"
2230+ wordwrap "^1.0.0"
2231+ optionalDependencies:
2232+ uglify-js "^3.1.4"
2233+
2234+har-schema@^2.0.0:
2235+ version "2.0.0"
2236+ resolved "https://registry.yarnpkg.com/har-schema/-/har-schema-2.0.0.tgz#a94c2224ebcac04782a0d9035521f24735b7ec92"
2237+ integrity sha1-qUwiJOvKwEeCoNkDVSHyRzW37JI=
2238+
2239+har-validator@~5.1.3:
2240+ version "5.1.5"
2241+ resolved "https://registry.yarnpkg.com/har-validator/-/har-validator-5.1.5.tgz#1f0803b9f8cb20c0fa13822df1ecddb36bde1efd"
2242+ integrity sha512-nmT2T0lljbxdQZfspsno9hgrG3Uir6Ks5afism62poxqBM6sDnMEuPmzTq8XN0OEwqKLLdh1jQI3qyE66Nzb3w==
2243+ dependencies:
2244+ ajv "^6.12.3"
2245+ har-schema "^2.0.0"
2246+
2247+hard-rejection@^2.1.0:
2248+ version "2.1.0"
2249+ resolved "https://registry.yarnpkg.com/hard-rejection/-/hard-rejection-2.1.0.tgz#1c6eda5c1685c63942766d79bb40ae773cecd883"
2250+ integrity sha512-VIZB+ibDhx7ObhAe7OVtoEbuP4h/MuOTHJ+J8h/eBXotJYl0fBgR72xDFCKgIh22OJZIOVNxBMWuhAr10r8HdA==
2251+
2252+has-flag@^3.0.0:
2253+ version "3.0.0"
2254+ resolved "https://registry.yarnpkg.com/has-flag/-/has-flag-3.0.0.tgz#b5d454dc2199ae225699f3467e5a07f3b955bafd"
2255+ integrity sha1-tdRU3CGZriJWmfNGfloH87lVuv0=
2256+
2257+has-symbols@^1.0.1:
2258+ version "1.0.2"
2259+ resolved "https://registry.yarnpkg.com/has-symbols/-/has-symbols-1.0.2.tgz#165d3070c00309752a1236a479331e3ac56f1423"
2260+ integrity sha512-chXa79rL/UC2KlX17jo3vRGz0azaWEx5tGqZg5pO3NUyEJVB17dMruQlzCCOfUvElghKcm5194+BCRvi2Rv/Gw==
2261+
2262+has-value@^0.3.1:
2263+ version "0.3.1"
2264+ resolved "https://registry.yarnpkg.com/has-value/-/has-value-0.3.1.tgz#7b1f58bada62ca827ec0a2078025654845995e1f"
2265+ integrity sha1-ex9YutpiyoJ+wKIHgCVlSEWZXh8=
2266+ dependencies:
2267+ get-value "^2.0.3"
2268+ has-values "^0.1.4"
2269+ isobject "^2.0.0"
2270+
2271+has-value@^1.0.0:
2272+ version "1.0.0"
2273+ resolved "https://registry.yarnpkg.com/has-value/-/has-value-1.0.0.tgz#18b281da585b1c5c51def24c930ed29a0be6b177"
2274+ integrity sha1-GLKB2lhbHFxR3vJMkw7SmgvmsXc=
2275+ dependencies:
2276+ get-value "^2.0.6"
2277+ has-values "^1.0.0"
2278+ isobject "^3.0.0"
2279+
2280+has-values@^0.1.4:
2281+ version "0.1.4"
2282+ resolved "https://registry.yarnpkg.com/has-values/-/has-values-0.1.4.tgz#6d61de95d91dfca9b9a02089ad384bff8f62b771"
2283+ integrity sha1-bWHeldkd/Km5oCCJrThL/49it3E=
2284+
2285+has-values@^1.0.0:
2286+ version "1.0.0"
2287+ resolved "https://registry.yarnpkg.com/has-values/-/has-values-1.0.0.tgz#95b0b63fec2146619a6fe57fe75628d5a39efe4f"
2288+ integrity sha1-lbC2P+whRmGab+V/51Yo1aOe/k8=
2289+ dependencies:
2290+ is-number "^3.0.0"
2291+ kind-of "^4.0.0"
2292+
2293+has@^1.0.3:
2294+ version "1.0.3"
2295+ resolved "https://registry.yarnpkg.com/has/-/has-1.0.3.tgz#722d7cbfc1f6aa8241f16dd814e011e1f41e8796"
2296+ integrity sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==
2297+ dependencies:
2298+ function-bind "^1.1.1"
2299+
2300+homedir-polyfill@^1.0.1:
2301+ version "1.0.3"
2302+ resolved "https://registry.yarnpkg.com/homedir-polyfill/-/homedir-polyfill-1.0.3.tgz#743298cef4e5af3e194161fbadcc2151d3a058e8"
2303+ integrity sha512-eSmmWE5bZTK2Nou4g0AI3zZ9rswp7GRKoKXS1BLUkvPviOqs4YTN1djQIqrXy9k5gEtdLPy86JjRwsNM9tnDcA==
2304+ dependencies:
2305+ parse-passwd "^1.0.0"
2306+
2307+hosted-git-info@^2.1.4:
2308+ version "2.8.9"
2309+ resolved "https://registry.yarnpkg.com/hosted-git-info/-/hosted-git-info-2.8.9.tgz#dffc0bf9a21c02209090f2aa69429e1414daf3f9"
2310+ integrity sha512-mxIDAb9Lsm6DoOJ7xH+5+X4y1LU/4Hi50L9C5sIswK3JzULS4bwk1FvjdBgvYR4bzT4tuUQiC15FE2f5HbLvYw==
2311+
2312+hosted-git-info@^4.0.0, hosted-git-info@^4.0.1:
2313+ version "4.0.2"
2314+ resolved "https://registry.yarnpkg.com/hosted-git-info/-/hosted-git-info-4.0.2.tgz#5e425507eede4fea846b7262f0838456c4209961"
2315+ integrity sha512-c9OGXbZ3guC/xOlCg1Ci/VgWlwsqDv1yMQL1CWqXDL0hDjXuNcq0zuR4xqPSuasI3kqFDhqSyTjREz5gzq0fXg==
2316+ dependencies:
2317+ lru-cache "^6.0.0"
2318+
2319+http-errors@1.7.2:
2320+ version "1.7.2"
2321+ resolved "https://registry.yarnpkg.com/http-errors/-/http-errors-1.7.2.tgz#4f5029cf13239f31036e5b2e55292bcfbcc85c8f"
2322+ integrity sha512-uUQBt3H/cSIVfch6i1EuPNy/YsRSOUBXTVfZ+yR7Zjez3qjBz6i9+i4zjNaoqcoFVI4lQJ5plg63TvGfRSDCRg==
2323+ dependencies:
2324+ depd "~1.1.2"
2325+ inherits "2.0.3"
2326+ setprototypeof "1.1.1"
2327+ statuses ">= 1.5.0 < 2"
2328+ toidentifier "1.0.0"
2329+
2330+http-errors@~1.7.2:
2331+ version "1.7.3"
2332+ resolved "https://registry.yarnpkg.com/http-errors/-/http-errors-1.7.3.tgz#6c619e4f9c60308c38519498c14fbb10aacebb06"
2333+ integrity sha512-ZTTX0MWrsQ2ZAhA1cejAwDLycFsd7I7nVtnkT3Ol0aqodaKW+0CTZDQ1uBv5whptCnc8e8HeRRJxRs0kmm/Qfw==
2334+ dependencies:
2335+ depd "~1.1.2"
2336+ inherits "2.0.4"
2337+ setprototypeof "1.1.1"
2338+ statuses ">= 1.5.0 < 2"
2339+ toidentifier "1.0.0"
2340+
2341+http-signature@~1.2.0:
2342+ version "1.2.0"
2343+ resolved "https://registry.yarnpkg.com/http-signature/-/http-signature-1.2.0.tgz#9aecd925114772f3d95b65a60abb8f7c18fbace1"
2344+ integrity sha1-muzZJRFHcvPZW2WmCruPfBj7rOE=
2345+ dependencies:
2346+ assert-plus "^1.0.0"
2347+ jsprim "^1.2.2"
2348+ sshpk "^1.7.0"
2349+
2350+iconv-lite@0.4.24:
2351+ version "0.4.24"
2352+ resolved "https://registry.yarnpkg.com/iconv-lite/-/iconv-lite-0.4.24.tgz#2022b4b25fbddc21d2f524974a474aafe733908b"
2353+ integrity sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==
2354+ dependencies:
2355+ safer-buffer ">= 2.1.2 < 3"
2356+
2357+ignore@^5.1.4:
2358+ version "5.1.8"
2359+ resolved "https://registry.yarnpkg.com/ignore/-/ignore-5.1.8.tgz#f150a8b50a34289b33e22f5889abd4d8016f0e57"
2360+ integrity sha512-BMpfD7PpiETpBl/A6S498BaIJ6Y/ABT93ETbby2fP00v4EbvPBXWEoaR1UBPKs3iR53pJY7EtZk5KACI57i1Uw==
2361+
2362+import-fresh@^2.0.0:
2363+ version "2.0.0"
2364+ resolved "https://registry.yarnpkg.com/import-fresh/-/import-fresh-2.0.0.tgz#d81355c15612d386c61f9ddd3922d4304822a546"
2365+ integrity sha1-2BNVwVYS04bGH53dOSLUMEgipUY=
2366+ dependencies:
2367+ caller-path "^2.0.0"
2368+ resolve-from "^3.0.0"
2369+
2370+import-fresh@^3.0.0:
2371+ version "3.3.0"
2372+ resolved "https://registry.yarnpkg.com/import-fresh/-/import-fresh-3.3.0.tgz#37162c25fcb9ebaa2e6e53d5b4d88ce17d9e0c2b"
2373+ integrity sha512-veYYhQa+D1QBKznvhUHxb8faxlrwUnxseDAbAp457E0wLNio2bOSKnjYDhMj+YiAq61xrMGhQk9iXVk5FzgQMw==
2374+ dependencies:
2375+ parent-module "^1.0.0"
2376+ resolve-from "^4.0.0"
2377+
2378+indent-string@^2.1.0:
2379+ version "2.1.0"
2380+ resolved "https://registry.yarnpkg.com/indent-string/-/indent-string-2.1.0.tgz#8e2d48348742121b4a8218b7a137e9a52049dc80"
2381+ integrity sha1-ji1INIdCEhtKghi3oTfppSBJ3IA=
2382+ dependencies:
2383+ repeating "^2.0.0"
2384+
2385+indent-string@^3.0.0:
2386+ version "3.2.0"
2387+ resolved "https://registry.yarnpkg.com/indent-string/-/indent-string-3.2.0.tgz#4a5fd6d27cc332f37e5419a504dbb837105c9289"
2388+ integrity sha1-Sl/W0nzDMvN+VBmlBNu4NxBckok=
2389+
2390+indent-string@^4.0.0:
2391+ version "4.0.0"
2392+ resolved "https://registry.yarnpkg.com/indent-string/-/indent-string-4.0.0.tgz#624f8f4497d619b2d9768531d58f4122854d7251"
2393+ integrity sha512-EdDDZu4A2OyIK7Lr/2zG+w5jmbuk1DVBnEwREQvBzspBJkCEbRa8GxU1lghYcaGJCnRWibjDXlq779X1/y5xwg==
2394+
2395+inflight@^1.0.4:
2396+ version "1.0.6"
2397+ resolved "https://registry.yarnpkg.com/inflight/-/inflight-1.0.6.tgz#49bd6331d7d02d0c09bc910a1075ba8165b56df9"
2398+ integrity sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=
2399+ dependencies:
2400+ once "^1.3.0"
2401+ wrappy "1"
2402+
2403+inherits@2, inherits@2.0.4, inherits@^2.0.1, inherits@^2.0.3, inherits@^2.0.4, inherits@~2.0.3:
2404+ version "2.0.4"
2405+ resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.4.tgz#0fa2c64f932917c3433a0ded55363aae37416b7c"
2406+ integrity sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==
2407+
2408+inherits@2.0.3:
2409+ version "2.0.3"
2410+ resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.3.tgz#633c2c83e3da42a502f52466022480f4208261de"
2411+ integrity sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=
2412+
2413+ini@^1.3.2, ini@^1.3.4:
2414+ version "1.3.8"
2415+ resolved "https://registry.yarnpkg.com/ini/-/ini-1.3.8.tgz#a29da425b48806f34767a4efce397269af28432c"
2416+ integrity sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew==
2417+
2418+interpret@^1.4.0:
2419+ version "1.4.0"
2420+ resolved "https://registry.yarnpkg.com/interpret/-/interpret-1.4.0.tgz#665ab8bc4da27a774a40584e812e3e0fa45b1a1e"
2421+ integrity sha512-agE4QfB2Lkp9uICn7BAqoscw4SZP9kTE2hxiFI3jBPmXJfdqiahTbUuKGsMoN2GtqL9AxhYioAcVvgsb1HvRbA==
2422+
2423+invert-kv@^1.0.0:
2424+ version "1.0.0"
2425+ resolved "https://registry.yarnpkg.com/invert-kv/-/invert-kv-1.0.0.tgz#104a8e4aaca6d3d8cd157a8ef8bfab2d7a3ffdb6"
2426+ integrity sha1-EEqOSqym09jNFXqO+L+rLXo//bY=
2427+
2428+ipaddr.js@1.9.1:
2429+ version "1.9.1"
2430+ resolved "https://registry.yarnpkg.com/ipaddr.js/-/ipaddr.js-1.9.1.tgz#bff38543eeb8984825079ff3a2a8e6cbd46781b3"
2431+ integrity sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g==
2432+
2433+is-absolute@^1.0.0:
2434+ version "1.0.0"
2435+ resolved "https://registry.yarnpkg.com/is-absolute/-/is-absolute-1.0.0.tgz#395e1ae84b11f26ad1795e73c17378e48a301576"
2436+ integrity sha512-dOWoqflvcydARa360Gvv18DZ/gRuHKi2NU/wU5X1ZFzdYfH29nkiNZsF3mp4OJ3H4yo9Mx8A/uAGNzpzPN3yBA==
2437+ dependencies:
2438+ is-relative "^1.0.0"
2439+ is-windows "^1.0.1"
2440+
2441+is-accessor-descriptor@^0.1.6:
2442+ version "0.1.6"
2443+ resolved "https://registry.yarnpkg.com/is-accessor-descriptor/-/is-accessor-descriptor-0.1.6.tgz#a9e12cb3ae8d876727eeef3843f8a0897b5c98d6"
2444+ integrity sha1-qeEss66Nh2cn7u84Q/igiXtcmNY=
2445+ dependencies:
2446+ kind-of "^3.0.2"
2447+
2448+is-accessor-descriptor@^1.0.0:
2449+ version "1.0.0"
2450+ resolved "https://registry.yarnpkg.com/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz#169c2f6d3df1f992618072365c9b0ea1f6878656"
2451+ integrity sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ==
2452+ dependencies:
2453+ kind-of "^6.0.0"
2454+
2455+is-arrayish@^0.2.1:
2456+ version "0.2.1"
2457+ resolved "https://registry.yarnpkg.com/is-arrayish/-/is-arrayish-0.2.1.tgz#77c99840527aa8ecb1a8ba697b80645a7a926a9d"
2458+ integrity sha1-d8mYQFJ6qOyxqLppe4BkWnqSap0=
2459+
2460+is-binary-path@^1.0.0:
2461+ version "1.0.1"
2462+ resolved "https://registry.yarnpkg.com/is-binary-path/-/is-binary-path-1.0.1.tgz#75f16642b480f187a711c814161fd3a4a7655898"
2463+ integrity sha1-dfFmQrSA8YenEcgUFh/TpKdlWJg=
2464+ dependencies:
2465+ binary-extensions "^1.0.0"
2466+
2467+is-buffer@^1.1.5:
2468+ version "1.1.6"
2469+ resolved "https://registry.yarnpkg.com/is-buffer/-/is-buffer-1.1.6.tgz#efaa2ea9daa0d7ab2ea13a97b2b8ad51fefbe8be"
2470+ integrity sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w==
2471+
2472+is-core-module@^2.2.0:
2473+ version "2.4.0"
2474+ resolved "https://registry.yarnpkg.com/is-core-module/-/is-core-module-2.4.0.tgz#8e9fc8e15027b011418026e98f0e6f4d86305cc1"
2475+ integrity sha512-6A2fkfq1rfeQZjxrZJGerpLCTHRNEBiSgnu0+obeJpEPZRUooHgsizvzv0ZjJwOz3iWIHdJtVWJ/tmPr3D21/A==
2476+ dependencies:
2477+ has "^1.0.3"
2478+
2479+is-data-descriptor@^0.1.4:
2480+ version "0.1.4"
2481+ resolved "https://registry.yarnpkg.com/is-data-descriptor/-/is-data-descriptor-0.1.4.tgz#0b5ee648388e2c860282e793f1856fec3f301b56"
2482+ integrity sha1-C17mSDiOLIYCgueT8YVv7D8wG1Y=
2483+ dependencies:
2484+ kind-of "^3.0.2"
2485+
2486+is-data-descriptor@^1.0.0:
2487+ version "1.0.0"
2488+ resolved "https://registry.yarnpkg.com/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz#d84876321d0e7add03990406abbbbd36ba9268c7"
2489+ integrity sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ==
2490+ dependencies:
2491+ kind-of "^6.0.0"
2492+
2493+is-descriptor@^0.1.0:
2494+ version "0.1.6"
2495+ resolved "https://registry.yarnpkg.com/is-descriptor/-/is-descriptor-0.1.6.tgz#366d8240dde487ca51823b1ab9f07a10a78251ca"
2496+ integrity sha512-avDYr0SB3DwO9zsMov0gKCESFYqCnE4hq/4z3TdUlukEy5t9C0YRq7HLrsN52NAcqXKaepeCD0n+B0arnVG3Hg==
2497+ dependencies:
2498+ is-accessor-descriptor "^0.1.6"
2499+ is-data-descriptor "^0.1.4"
2500+ kind-of "^5.0.0"
2501+
2502+is-descriptor@^1.0.0, is-descriptor@^1.0.2:
2503+ version "1.0.2"
2504+ resolved "https://registry.yarnpkg.com/is-descriptor/-/is-descriptor-1.0.2.tgz#3b159746a66604b04f8c81524ba365c5f14d86ec"
2505+ integrity sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==
2506+ dependencies:
2507+ is-accessor-descriptor "^1.0.0"
2508+ is-data-descriptor "^1.0.0"
2509+ kind-of "^6.0.2"
2510+
2511+is-directory@^0.3.1:
2512+ version "0.3.1"
2513+ resolved "https://registry.yarnpkg.com/is-directory/-/is-directory-0.3.1.tgz#61339b6f2475fc772fd9c9d83f5c8575dc154ae1"
2514+ integrity sha1-YTObbyR1/Hcv2cnYP1yFddwVSuE=
2515+
2516+is-extendable@^0.1.0, is-extendable@^0.1.1:
2517+ version "0.1.1"
2518+ resolved "https://registry.yarnpkg.com/is-extendable/-/is-extendable-0.1.1.tgz#62b110e289a471418e3ec36a617d472e301dfc89"
2519+ integrity sha1-YrEQ4omkcUGOPsNqYX1HLjAd/Ik=
2520+
2521+is-extendable@^1.0.1:
2522+ version "1.0.1"
2523+ resolved "https://registry.yarnpkg.com/is-extendable/-/is-extendable-1.0.1.tgz#a7470f9e426733d81bd81e1155264e3a3507cab4"
2524+ integrity sha512-arnXMxT1hhoKo9k1LZdmlNyJdDDfy2v0fXjFlmok4+i8ul/6WlbVge9bhM74OpNPQPMGUToDtz+KXa1PneJxOA==
2525+ dependencies:
2526+ is-plain-object "^2.0.4"
2527+
2528+is-extglob@^2.1.0, is-extglob@^2.1.1:
2529+ version "2.1.1"
2530+ resolved "https://registry.yarnpkg.com/is-extglob/-/is-extglob-2.1.1.tgz#a88c02535791f02ed37c76a1b9ea9773c833f8c2"
2531+ integrity sha1-qIwCU1eR8C7TfHahueqXc8gz+MI=
2532+
2533+is-finite@^1.0.0:
2534+ version "1.1.0"
2535+ resolved "https://registry.yarnpkg.com/is-finite/-/is-finite-1.1.0.tgz#904135c77fb42c0641d6aa1bcdbc4daa8da082f3"
2536+ integrity sha512-cdyMtqX/BOqqNBBiKlIVkytNHm49MtMlYyn1zxzvJKWmFMlGzm+ry5BBfYyeY9YmNKbRSo/o7OX9w9ale0wg3w==
2537+
2538+is-fullwidth-code-point@^1.0.0:
2539+ version "1.0.0"
2540+ resolved "https://registry.yarnpkg.com/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz#ef9e31386f031a7f0d643af82fde50c457ef00cb"
2541+ integrity sha1-754xOG8DGn8NZDr4L95QxFfvAMs=
2542+ dependencies:
2543+ number-is-nan "^1.0.0"
2544+
2545+is-glob@^3.1.0:
2546+ version "3.1.0"
2547+ resolved "https://registry.yarnpkg.com/is-glob/-/is-glob-3.1.0.tgz#7ba5ae24217804ac70707b96922567486cc3e84a"
2548+ integrity sha1-e6WuJCF4BKxwcHuWkiVnSGzD6Eo=
2549+ dependencies:
2550+ is-extglob "^2.1.0"
2551+
2552+is-glob@^4.0.0, is-glob@^4.0.1:
2553+ version "4.0.1"
2554+ resolved "https://registry.yarnpkg.com/is-glob/-/is-glob-4.0.1.tgz#7567dbe9f2f5e2467bc77ab83c4a29482407a5dc"
2555+ integrity sha512-5G0tKtBTFImOqDnLB2hG6Bp2qcKEFduo4tZu9MT/H6NQv/ghhy30o55ufafxJ/LdH79LLs2Kfrn85TLKyA7BUg==
2556+ dependencies:
2557+ is-extglob "^2.1.1"
2558+
2559+is-negated-glob@^1.0.0:
2560+ version "1.0.0"
2561+ resolved "https://registry.yarnpkg.com/is-negated-glob/-/is-negated-glob-1.0.0.tgz#6910bca5da8c95e784b5751b976cf5a10fee36d2"
2562+ integrity sha1-aRC8pdqMleeEtXUbl2z1oQ/uNtI=
2563+
2564+is-number@^3.0.0:
2565+ version "3.0.0"
2566+ resolved "https://registry.yarnpkg.com/is-number/-/is-number-3.0.0.tgz#24fd6201a4782cf50561c810276afc7d12d71195"
2567+ integrity sha1-JP1iAaR4LPUFYcgQJ2r8fRLXEZU=
2568+ dependencies:
2569+ kind-of "^3.0.2"
2570+
2571+is-number@^4.0.0:
2572+ version "4.0.0"
2573+ resolved "https://registry.yarnpkg.com/is-number/-/is-number-4.0.0.tgz#0026e37f5454d73e356dfe6564699867c6a7f0ff"
2574+ integrity sha512-rSklcAIlf1OmFdyAqbnWTLVelsQ58uvZ66S/ZyawjWqIviTWCjg2PzVGw8WUA+nNuPTqb4wgA+NszrJ+08LlgQ==
2575+
2576+is-number@^7.0.0:
2577+ version "7.0.0"
2578+ resolved "https://registry.yarnpkg.com/is-number/-/is-number-7.0.0.tgz#7535345b896734d5f80c4d06c50955527a14f12b"
2579+ integrity sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==
2580+
2581+is-obj@^1.0.0:
2582+ version "1.0.1"
2583+ resolved "https://registry.yarnpkg.com/is-obj/-/is-obj-1.0.1.tgz#3e4729ac1f5fde025cd7d83a896dab9f4f67db0f"
2584+ integrity sha1-PkcprB9f3gJc19g6iW2rn09n2w8=
2585+
2586+is-obj@^2.0.0:
2587+ version "2.0.0"
2588+ resolved "https://registry.yarnpkg.com/is-obj/-/is-obj-2.0.0.tgz#473fb05d973705e3fd9620545018ca8e22ef4982"
2589+ integrity sha512-drqDG3cbczxxEJRoOXcOjtdp1J/lyp1mNn0xaznRs8+muBhgQcrnbspox5X5fOw0HnMnbfDzvnEMEtqDEJEo8w==
2590+
2591+is-path-cwd@^2.2.0:
2592+ version "2.2.0"
2593+ resolved "https://registry.yarnpkg.com/is-path-cwd/-/is-path-cwd-2.2.0.tgz#67d43b82664a7b5191fd9119127eb300048a9fdb"
2594+ integrity sha512-w942bTcih8fdJPJmQHFzkS76NEP8Kzzvmw92cXsazb8intwLqPibPPdXf4ANdKV3rYMuuQYGIWtvz9JilB3NFQ==
2595+
2596+is-path-inside@^3.0.2:
2597+ version "3.0.3"
2598+ resolved "https://registry.yarnpkg.com/is-path-inside/-/is-path-inside-3.0.3.tgz#d231362e53a07ff2b0e0ea7fed049161ffd16283"
2599+ integrity sha512-Fd4gABb+ycGAmKou8eMftCupSir5lRxqf4aD/vd0cD2qc4HL07OjCeuHMr8Ro4CoMaeCKDB0/ECBOVWjTwUvPQ==
2600+
2601+is-plain-obj@^1.1.0:
2602+ version "1.1.0"
2603+ resolved "https://registry.yarnpkg.com/is-plain-obj/-/is-plain-obj-1.1.0.tgz#71a50c8429dfca773c92a390a4a03b39fcd51d3e"
2604+ integrity sha1-caUMhCnfync8kqOQpKA7OfzVHT4=
2605+
2606+is-plain-object@^2.0.1, is-plain-object@^2.0.3, is-plain-object@^2.0.4:
2607+ version "2.0.4"
2608+ resolved "https://registry.yarnpkg.com/is-plain-object/-/is-plain-object-2.0.4.tgz#2c163b3fafb1b606d9d17928f05c2a1c38e07677"
2609+ integrity sha512-h5PpgXkWitc38BBMYawTYMWJHFZJVnBquFE57xFpjB8pJFiF6gZ+bU+WyI/yqXiFR5mdLsgYNaPe8uao6Uv9Og==
2610+ dependencies:
2611+ isobject "^3.0.1"
2612+
2613+is-plain-object@^5.0.0:
2614+ version "5.0.0"
2615+ resolved "https://registry.yarnpkg.com/is-plain-object/-/is-plain-object-5.0.0.tgz#4427f50ab3429e9025ea7d52e9043a9ef4159344"
2616+ integrity sha512-VRSzKkbMm5jMDoKLbltAkFQ5Qr7VDiTFGXxYFXXowVj387GeGNOCsOH6Msy00SGZ3Fp84b1Naa1psqgcCIEP5Q==
2617+
2618+is-relative@^1.0.0:
2619+ version "1.0.0"
2620+ resolved "https://registry.yarnpkg.com/is-relative/-/is-relative-1.0.0.tgz#a1bb6935ce8c5dba1e8b9754b9b2dcc020e2260d"
2621+ integrity sha512-Kw/ReK0iqwKeu0MITLFuj0jbPAmEiOsIwyIXvvbfa6QfmN9pkD1M+8pdk7Rl/dTKbH34/XBFMbgD4iMJhLQbGA==
2622+ dependencies:
2623+ is-unc-path "^1.0.0"
2624+
2625+is-text-path@^1.0.1:
2626+ version "1.0.1"
2627+ resolved "https://registry.yarnpkg.com/is-text-path/-/is-text-path-1.0.1.tgz#4e1aa0fb51bfbcb3e92688001397202c1775b66e"
2628+ integrity sha1-Thqg+1G/vLPpJogAE5cgLBd1tm4=
2629+ dependencies:
2630+ text-extensions "^1.0.0"
2631+
2632+is-typedarray@~1.0.0:
2633+ version "1.0.0"
2634+ resolved "https://registry.yarnpkg.com/is-typedarray/-/is-typedarray-1.0.0.tgz#e479c80858df0c1b11ddda6940f96011fcda4a9a"
2635+ integrity sha1-5HnICFjfDBsR3dppQPlgEfzaSpo=
2636+
2637+is-unc-path@^1.0.0:
2638+ version "1.0.0"
2639+ resolved "https://registry.yarnpkg.com/is-unc-path/-/is-unc-path-1.0.0.tgz#d731e8898ed090a12c352ad2eaed5095ad322c9d"
2640+ integrity sha512-mrGpVd0fs7WWLfVsStvgF6iEJnbjDFZh9/emhRDcGWTduTfNHd9CHeUwH3gYIjdbwo4On6hunkztwOaAw0yllQ==
2641+ dependencies:
2642+ unc-path-regex "^0.1.2"
2643+
2644+is-utf8@^0.2.0, is-utf8@^0.2.1:
2645+ version "0.2.1"
2646+ resolved "https://registry.yarnpkg.com/is-utf8/-/is-utf8-0.2.1.tgz#4b0da1442104d1b336340e80797e865cf39f7d72"
2647+ integrity sha1-Sw2hRCEE0bM2NA6AeX6GXPOffXI=
2648+
2649+is-valid-glob@^1.0.0:
2650+ version "1.0.0"
2651+ resolved "https://registry.yarnpkg.com/is-valid-glob/-/is-valid-glob-1.0.0.tgz#29bf3eff701be2d4d315dbacc39bc39fe8f601aa"
2652+ integrity sha1-Kb8+/3Ab4tTTFdusw5vDn+j2Aao=
2653+
2654+is-windows@^1.0.1, is-windows@^1.0.2:
2655+ version "1.0.2"
2656+ resolved "https://registry.yarnpkg.com/is-windows/-/is-windows-1.0.2.tgz#d1850eb9791ecd18e6182ce12a30f396634bb19d"
2657+ integrity sha512-eXK1UInq2bPmjyX6e3VHIzMLobc4J94i4AWn+Hpq3OU5KkrRC96OAcR3PRJ/pGu6m8TRnBHP9dkXQVsT/COVIA==
2658+
2659+isarray@1.0.0, isarray@~1.0.0:
2660+ version "1.0.0"
2661+ resolved "https://registry.yarnpkg.com/isarray/-/isarray-1.0.0.tgz#bb935d48582cba168c06834957a54a3e07124f11"
2662+ integrity sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=
2663+
2664+isexe@^2.0.0:
2665+ version "2.0.0"
2666+ resolved "https://registry.yarnpkg.com/isexe/-/isexe-2.0.0.tgz#e8fbf374dc556ff8947a10dcb0572d633f2cfa10"
2667+ integrity sha1-6PvzdNxVb/iUehDcsFctYz8s+hA=
2668+
2669+isobject@^2.0.0:
2670+ version "2.1.0"
2671+ resolved "https://registry.yarnpkg.com/isobject/-/isobject-2.1.0.tgz#f065561096a3f1da2ef46272f815c840d87e0c89"
2672+ integrity sha1-8GVWEJaj8dou9GJy+BXIQNh+DIk=
2673+ dependencies:
2674+ isarray "1.0.0"
2675+
2676+isobject@^3.0.0, isobject@^3.0.1:
2677+ version "3.0.1"
2678+ resolved "https://registry.yarnpkg.com/isobject/-/isobject-3.0.1.tgz#4e431e92b11a9731636aa1f9c8d1ccbcfdab78df"
2679+ integrity sha1-TkMekrEalzFjaqH5yNHMvP2reN8=
2680+
2681+isstream@~0.1.2:
2682+ version "0.1.2"
2683+ resolved "https://registry.yarnpkg.com/isstream/-/isstream-0.1.2.tgz#47e63f7af55afa6f92e1500e690eb8b8529c099a"
2684+ integrity sha1-R+Y/evVa+m+S4VAOaQ64uFKcCZo=
2685+
2686+jasmine-core@~3.8.0:
2687+ version "3.8.0"
2688+ resolved "https://registry.yarnpkg.com/jasmine-core/-/jasmine-core-3.8.0.tgz#815399aae5aa5d9beeb1262805f981b99ffc9bf0"
2689+ integrity sha512-zl0nZWDrmbCiKns0NcjkFGYkVTGCPUgoHypTaj+G2AzaWus7QGoXARSlYsSle2VRpSdfJmM+hzmFKzQNhF2kHg==
2690+
2691+jasmine-terminal-reporter@^1.0.3:
2692+ version "1.0.3"
2693+ resolved "https://registry.yarnpkg.com/jasmine-terminal-reporter/-/jasmine-terminal-reporter-1.0.3.tgz#896f1ec8fdf4bf6aecdd41c503eda7347f61526b"
2694+ integrity sha1-iW8eyP30v2rs3UHFA+2nNH9hUms=
2695+ dependencies:
2696+ indent-string "^2.1.0"
2697+ pluralize "^1.2.1"
2698+
2699+jasmine@^3.1.0, jasmine@^3.6.1:
2700+ version "3.8.0"
2701+ resolved "https://registry.yarnpkg.com/jasmine/-/jasmine-3.8.0.tgz#4497bc797eede7ca9de18179aedd4cf50245d8dc"
2702+ integrity sha512-kdQ3SfcNpMbbMdgJPLyFe9IksixdnrgYaCJapP9sS0aLgdWdIZADNXEr+11Zafxm1VDfRSC5ZL4fzXT0bexzXw==
2703+ dependencies:
2704+ glob "^7.1.6"
2705+ jasmine-core "~3.8.0"
2706+
2707+js-tokens@^4.0.0:
2708+ version "4.0.0"
2709+ resolved "https://registry.yarnpkg.com/js-tokens/-/js-tokens-4.0.0.tgz#19203fb59991df98e3a287050d4647cdeaf32499"
2710+ integrity sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==
2711+
2712+js-yaml@^3.13.1:
2713+ version "3.14.1"
2714+ resolved "https://registry.yarnpkg.com/js-yaml/-/js-yaml-3.14.1.tgz#dae812fdb3825fa306609a8717383c50c36a0537"
2715+ integrity sha512-okMH7OXXJ7YrN9Ok3/SXrnu4iX9yOk+25nqX4imS2npuvTYDmo/QEZoqwZkYaIDk3jVvBOTOIEgEhaLOynBS9g==
2716+ dependencies:
2717+ argparse "^1.0.7"
2718+ esprima "^4.0.0"
2719+
2720+js-yaml@^4.0.0, js-yaml@^4.1.0:
2721+ version "4.1.0"
2722+ resolved "https://registry.yarnpkg.com/js-yaml/-/js-yaml-4.1.0.tgz#c1fb65f8f5017901cdd2c951864ba18458a10602"
2723+ integrity sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==
2724+ dependencies:
2725+ argparse "^2.0.1"
2726+
2727+jsbn@~0.1.0:
2728+ version "0.1.1"
2729+ resolved "https://registry.yarnpkg.com/jsbn/-/jsbn-0.1.1.tgz#a5e654c2e5a2deb5f201d96cefbca80c0ef2f513"
2730+ integrity sha1-peZUwuWi3rXyAdls77yoDA7y9RM=
2731+
2732+json-parse-better-errors@^1.0.1:
2733+ version "1.0.2"
2734+ resolved "https://registry.yarnpkg.com/json-parse-better-errors/-/json-parse-better-errors-1.0.2.tgz#bb867cfb3450e69107c131d1c514bab3dc8bcaa9"
2735+ integrity sha512-mrqyZKfX5EhL7hvqcV6WG1yYjnjeuYDzDhhcAAUrq8Po85NBQBJP+ZDUT75qZQ98IkUoBqdkExkukOU7Ts2wrw==
2736+
2737+json-parse-even-better-errors@^2.3.0:
2738+ version "2.3.1"
2739+ resolved "https://registry.yarnpkg.com/json-parse-even-better-errors/-/json-parse-even-better-errors-2.3.1.tgz#7c47805a94319928e05777405dc12e1f7a4ee02d"
2740+ integrity sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w==
2741+
2742+json-schema-diff@^0.16.0:
2743+ version "0.16.0"
2744+ resolved "https://registry.yarnpkg.com/json-schema-diff/-/json-schema-diff-0.16.0.tgz#ee703abe7d23983244c0cfd7f11daca60fd31454"
2745+ integrity sha512-jNpsidxig8D9WdK1O4hMkcqtnNiGgtk9gxKQfhGGJT9EhOVKLR6YZX+Ft81nz1Rp5FXS4XNwgtGUMUICx3cBYA==
2746+ dependencies:
2747+ ajv "^6.12.3"
2748+ commander "^5.0.0"
2749+ json-schema-ref-parser "^9.0.6"
2750+ json-schema-spec-types "^0.1.2"
2751+ lodash "^4.17.19"
2752+ verror "^1.10.0"
2753+
2754+json-schema-ref-parser@^9.0.6:
2755+ version "9.0.9"
2756+ resolved "https://registry.yarnpkg.com/json-schema-ref-parser/-/json-schema-ref-parser-9.0.9.tgz#66ea538e7450b12af342fa3d5b8458bc1e1e013f"
2757+ integrity sha512-qcP2lmGy+JUoQJ4DOQeLaZDqH9qSkeGCK3suKWxJXS82dg728Mn3j97azDMaOUmJAN4uCq91LdPx4K7E8F1a7Q==
2758+ dependencies:
2759+ "@apidevtools/json-schema-ref-parser" "9.0.9"
2760+
2761+json-schema-spec-types@^0.1.2:
2762+ version "0.1.2"
2763+ resolved "https://registry.yarnpkg.com/json-schema-spec-types/-/json-schema-spec-types-0.1.2.tgz#c4dac1c8b70c99f19b24afedb210e1dfc48665e2"
2764+ integrity sha512-MDl8fA8ONckmQOm2+eXKJaFJNvxk7eGin+XFofNjS3q3PRKSoEvgMVb0ehOpCAYkUiLoMiqdU7obV7AmzAmyLw==
2765+
2766+json-schema-traverse@^0.4.1:
2767+ version "0.4.1"
2768+ resolved "https://registry.yarnpkg.com/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz#69f6a87d9513ab8bb8fe63bdb0979c448e684660"
2769+ integrity sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==
2770+
2771+json-schema@0.2.3:
2772+ version "0.2.3"
2773+ resolved "https://registry.yarnpkg.com/json-schema/-/json-schema-0.2.3.tgz#b480c892e59a2f05954ce727bd3f2a4e882f9e13"
2774+ integrity sha1-tIDIkuWaLwWVTOcnvT8qTogvnhM=
2775+
2776+json-stable-stringify-without-jsonify@^1.0.1:
2777+ version "1.0.1"
2778+ resolved "https://registry.yarnpkg.com/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz#9db7b59496ad3f3cfef30a75142d2d930ad72651"
2779+ integrity sha1-nbe1lJatPzz+8wp1FC0tkwrXJlE=
2780+
2781+json-stringify-safe@^5.0.1, json-stringify-safe@~5.0.1:
2782+ version "5.0.1"
2783+ resolved "https://registry.yarnpkg.com/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz#1296a2d58fd45f19a0f6ce01d65701e2c735b6eb"
2784+ integrity sha1-Epai1Y/UXxmg9s4B1lcB4sc1tus=
2785+
2786+jsonparse@^1.2.0:
2787+ version "1.3.1"
2788+ resolved "https://registry.yarnpkg.com/jsonparse/-/jsonparse-1.3.1.tgz#3f4dae4a91fac315f71062f8521cc239f1366280"
2789+ integrity sha1-P02uSpH6wxX3EGL4UhzCOfE2YoA=
2790+
2791+jsonpointer@^4.1.0:
2792+ version "4.1.0"
2793+ resolved "https://registry.yarnpkg.com/jsonpointer/-/jsonpointer-4.1.0.tgz#501fb89986a2389765ba09e6053299ceb4f2c2cc"
2794+ integrity sha512-CXcRvMyTlnR53xMcKnuMzfCA5i/nfblTnnr74CZb6C4vG39eu6w51t7nKmU5MfLfbTgGItliNyjO/ciNPDqClg==
2795+
2796+jsprim@^1.2.2:
2797+ version "1.4.1"
2798+ resolved "https://registry.yarnpkg.com/jsprim/-/jsprim-1.4.1.tgz#313e66bc1e5cc06e438bc1b7499c2e5c56acb6a2"
2799+ integrity sha1-MT5mvB5cwG5Di8G3SZwuXFastqI=
2800+ dependencies:
2801+ assert-plus "1.0.0"
2802+ extsprintf "1.3.0"
2803+ json-schema "0.2.3"
2804+ verror "1.10.0"
2805+
2806+just-debounce@^1.0.0:
2807+ version "1.1.0"
2808+ resolved "https://registry.yarnpkg.com/just-debounce/-/just-debounce-1.1.0.tgz#2f81a3ad4121a76bc7cb45dbf704c0d76a8e5ddf"
2809+ integrity sha512-qpcRocdkUmf+UTNBYx5w6dexX5J31AKK1OmPwH630a83DdVVUIngk55RSAiIGpQyoH0dlr872VHfPjnQnK1qDQ==
2810+
2811+kind-of@^1.1.0:
2812+ version "1.1.0"
2813+ resolved "https://registry.yarnpkg.com/kind-of/-/kind-of-1.1.0.tgz#140a3d2d41a36d2efcfa9377b62c24f8495a5c44"
2814+ integrity sha1-FAo9LUGjbS78+pN3tiwk+ElaXEQ=
2815+
2816+kind-of@^3.0.2, kind-of@^3.0.3, kind-of@^3.2.0:
2817+ version "3.2.2"
2818+ resolved "https://registry.yarnpkg.com/kind-of/-/kind-of-3.2.2.tgz#31ea21a734bab9bbb0f32466d893aea51e4a3c64"
2819+ integrity sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=
2820+ dependencies:
2821+ is-buffer "^1.1.5"
2822+
2823+kind-of@^4.0.0:
2824+ version "4.0.0"
2825+ resolved "https://registry.yarnpkg.com/kind-of/-/kind-of-4.0.0.tgz#20813df3d712928b207378691a45066fae72dd57"
2826+ integrity sha1-IIE989cSkosgc3hpGkUGb65y3Vc=
2827+ dependencies:
2828+ is-buffer "^1.1.5"
2829+
2830+kind-of@^5.0.0, kind-of@^5.0.2:
2831+ version "5.1.0"
2832+ resolved "https://registry.yarnpkg.com/kind-of/-/kind-of-5.1.0.tgz#729c91e2d857b7a419a1f9aa65685c4c33f5845d"
2833+ integrity sha512-NGEErnH6F2vUuXDh+OlbcKW7/wOcfdRHaZ7VWtqCztfHri/++YKmP51OdWeGPuqCOba6kk2OTe5d02VmTB80Pw==
2834+
2835+kind-of@^6.0.0, kind-of@^6.0.2, kind-of@^6.0.3:
2836+ version "6.0.3"
2837+ resolved "https://registry.yarnpkg.com/kind-of/-/kind-of-6.0.3.tgz#07c05034a6c349fa06e24fa35aa76db4580ce4dd"
2838+ integrity sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw==
2839+
2840+last-run@^1.1.0:
2841+ version "1.1.1"
2842+ resolved "https://registry.yarnpkg.com/last-run/-/last-run-1.1.1.tgz#45b96942c17b1c79c772198259ba943bebf8ca5b"
2843+ integrity sha1-RblpQsF7HHnHchmCWbqUO+v4yls=
2844+ dependencies:
2845+ default-resolution "^2.0.0"
2846+ es6-weak-map "^2.0.1"
2847+
2848+lazystream@^1.0.0:
2849+ version "1.0.0"
2850+ resolved "https://registry.yarnpkg.com/lazystream/-/lazystream-1.0.0.tgz#f6995fe0f820392f61396be89462407bb77168e4"
2851+ integrity sha1-9plf4PggOS9hOWvolGJAe7dxaOQ=
2852+ dependencies:
2853+ readable-stream "^2.0.5"
2854+
2855+lcid@^1.0.0:
2856+ version "1.0.0"
2857+ resolved "https://registry.yarnpkg.com/lcid/-/lcid-1.0.0.tgz#308accafa0bc483a3867b4b6f2b9506251d1b835"
2858+ integrity sha1-MIrMr6C8SDo4Z7S28rlQYlHRuDU=
2859+ dependencies:
2860+ invert-kv "^1.0.0"
2861+
2862+lead@^1.0.0:
2863+ version "1.0.0"
2864+ resolved "https://registry.yarnpkg.com/lead/-/lead-1.0.0.tgz#6f14f99a37be3a9dd784f5495690e5903466ee42"
2865+ integrity sha1-bxT5mje+Op3XhPVJVpDlkDRm7kI=
2866+ dependencies:
2867+ flush-write-stream "^1.0.2"
2868+
2869+liftoff@^3.1.0:
2870+ version "3.1.0"
2871+ resolved "https://registry.yarnpkg.com/liftoff/-/liftoff-3.1.0.tgz#c9ba6081f908670607ee79062d700df062c52ed3"
2872+ integrity sha512-DlIPlJUkCV0Ips2zf2pJP0unEoT1kwYhiiPUGF3s/jtxTCjziNLoiVVh+jqWOWeFi6mmwQ5fNxvAUyPad4Dfog==
2873+ dependencies:
2874+ extend "^3.0.0"
2875+ findup-sync "^3.0.0"
2876+ fined "^1.0.1"
2877+ flagged-respawn "^1.0.0"
2878+ is-plain-object "^2.0.4"
2879+ object.map "^1.0.0"
2880+ rechoir "^0.6.2"
2881+ resolve "^1.1.7"
2882+
2883+lines-and-columns@^1.1.6:
2884+ version "1.1.6"
2885+ resolved "https://registry.yarnpkg.com/lines-and-columns/-/lines-and-columns-1.1.6.tgz#1c00c743b433cd0a4e80758f7b64a57440d9ff00"
2886+ integrity sha1-HADHQ7QzzQpOgHWPe2SldEDZ/wA=
2887+
2888+load-json-file@^1.0.0:
2889+ version "1.1.0"
2890+ resolved "https://registry.yarnpkg.com/load-json-file/-/load-json-file-1.1.0.tgz#956905708d58b4bab4c2261b04f59f31c99374c0"
2891+ integrity sha1-lWkFcI1YtLq0wiYbBPWfMcmTdMA=
2892+ dependencies:
2893+ graceful-fs "^4.1.2"
2894+ parse-json "^2.2.0"
2895+ pify "^2.0.0"
2896+ pinkie-promise "^2.0.0"
2897+ strip-bom "^2.0.0"
2898+
2899+load-json-file@^4.0.0:
2900+ version "4.0.0"
2901+ resolved "https://registry.yarnpkg.com/load-json-file/-/load-json-file-4.0.0.tgz#2f5f45ab91e33216234fd53adab668eb4ec0993b"
2902+ integrity sha1-L19Fq5HjMhYjT9U62rZo607AmTs=
2903+ dependencies:
2904+ graceful-fs "^4.1.2"
2905+ parse-json "^4.0.0"
2906+ pify "^3.0.0"
2907+ strip-bom "^3.0.0"
2908+
2909+locate-path@^2.0.0:
2910+ version "2.0.0"
2911+ resolved "https://registry.yarnpkg.com/locate-path/-/locate-path-2.0.0.tgz#2b568b265eec944c6d9c0de9c3dbbbca0354cd8e"
2912+ integrity sha1-K1aLJl7slExtnA3pw9u7ygNUzY4=
2913+ dependencies:
2914+ p-locate "^2.0.0"
2915+ path-exists "^3.0.0"
2916+
2917+locate-path@^5.0.0:
2918+ version "5.0.0"
2919+ resolved "https://registry.yarnpkg.com/locate-path/-/locate-path-5.0.0.tgz#1afba396afd676a6d42504d0a67a3a7eb9f62aa0"
2920+ integrity sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==
2921+ dependencies:
2922+ p-locate "^4.1.0"
2923+
2924+lodash._reinterpolate@^3.0.0:
2925+ version "3.0.0"
2926+ resolved "https://registry.yarnpkg.com/lodash._reinterpolate/-/lodash._reinterpolate-3.0.0.tgz#0ccf2d89166af03b3663c796538b75ac6e114d9d"
2927+ integrity sha1-DM8tiRZq8Ds2Y8eWU4t1rG4RTZ0=
2928+
2929+lodash.get@^4.4.2:
2930+ version "4.4.2"
2931+ resolved "https://registry.yarnpkg.com/lodash.get/-/lodash.get-4.4.2.tgz#2d177f652fa31e939b4438d5341499dfa3825e99"
2932+ integrity sha1-LRd/ZS+jHpObRDjVNBSZ36OCXpk=
2933+
2934+lodash.isequal@^4.5.0:
2935+ version "4.5.0"
2936+ resolved "https://registry.yarnpkg.com/lodash.isequal/-/lodash.isequal-4.5.0.tgz#415c4478f2bcc30120c22ce10ed3226f7d3e18e0"
2937+ integrity sha1-QVxEePK8wwEgwizhDtMib30+GOA=
2938+
2939+lodash.ismatch@^4.4.0:
2940+ version "4.4.0"
2941+ resolved "https://registry.yarnpkg.com/lodash.ismatch/-/lodash.ismatch-4.4.0.tgz#756cb5150ca3ba6f11085a78849645f188f85f37"
2942+ integrity sha1-dWy1FQyjum8RCFp4hJZF8Yj4Xzc=
2943+
2944+lodash.template@^4.4.0:
2945+ version "4.5.0"
2946+ resolved "https://registry.yarnpkg.com/lodash.template/-/lodash.template-4.5.0.tgz#f976195cf3f347d0d5f52483569fe8031ccce8ab"
2947+ integrity sha512-84vYFxIkmidUiFxidA/KjjH9pAycqW+h980j7Fuz5qxRtO9pgB7MDFTdys1N7A5mcucRiDyEq4fusljItR1T/A==
2948+ dependencies:
2949+ lodash._reinterpolate "^3.0.0"
2950+ lodash.templatesettings "^4.0.0"
2951+
2952+lodash.templatesettings@^4.0.0:
2953+ version "4.2.0"
2954+ resolved "https://registry.yarnpkg.com/lodash.templatesettings/-/lodash.templatesettings-4.2.0.tgz#e481310f049d3cf6d47e912ad09313b154f0fb33"
2955+ integrity sha512-stgLz+i3Aa9mZgnjr/O+v9ruKZsPsndy7qPZOchbqk2cnTU1ZaldKK+v7m54WoKIyxiuMZTKT2H81F8BeAc3ZQ==
2956+ dependencies:
2957+ lodash._reinterpolate "^3.0.0"
2958+
2959+lodash@4.17.15:
2960+ version "4.17.15"
2961+ resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.15.tgz#b447f6670a0455bbfeedd11392eff330ea097548"
2962+ integrity sha512-8xOcRHvCjnocdS5cpwXQXVzmmh5e5+saE2QGoeQmbKmRS6J3VQppPOIt0MnmE+4xlZoumy0GPG0D0MVIQbNA1A==
2963+
2964+lodash@^4.17.11, lodash@^4.17.15, lodash@^4.17.19, lodash@^4.17.20, lodash@^4.2.1:
2965+ version "4.17.21"
2966+ resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.21.tgz#679591c564c3bffaae8454cf0b3df370c3d6911c"
2967+ integrity sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==
2968+
2969+loud-rejection@^1.0.0:
2970+ version "1.6.0"
2971+ resolved "https://registry.yarnpkg.com/loud-rejection/-/loud-rejection-1.6.0.tgz#5b46f80147edee578870f086d04821cf998e551f"
2972+ integrity sha1-W0b4AUft7leIcPCG0Eghz5mOVR8=
2973+ dependencies:
2974+ currently-unhandled "^0.4.1"
2975+ signal-exit "^3.0.0"
2976+
2977+lru-cache@^6.0.0:
2978+ version "6.0.0"
2979+ resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-6.0.0.tgz#6d6fe6570ebd96aaf90fcad1dafa3b2566db3a94"
2980+ integrity sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==
2981+ dependencies:
2982+ yallist "^4.0.0"
2983+
2984+make-iterator@^1.0.0:
2985+ version "1.0.1"
2986+ resolved "https://registry.yarnpkg.com/make-iterator/-/make-iterator-1.0.1.tgz#29b33f312aa8f547c4a5e490f56afcec99133ad6"
2987+ integrity sha512-pxiuXh0iVEq7VM7KMIhs5gxsfxCux2URptUQaXo4iZZJxBAzTPOLE2BumO5dbfVYq/hBJFBR/a1mFDmOx5AGmw==
2988+ dependencies:
2989+ kind-of "^6.0.2"
2990+
2991+map-cache@^0.2.0, map-cache@^0.2.2:
2992+ version "0.2.2"
2993+ resolved "https://registry.yarnpkg.com/map-cache/-/map-cache-0.2.2.tgz#c32abd0bd6525d9b051645bb4f26ac5dc98a0dbf"
2994+ integrity sha1-wyq9C9ZSXZsFFkW7TyasXcmKDb8=
2995+
2996+map-obj@^1.0.0:
2997+ version "1.0.1"
2998+ resolved "https://registry.yarnpkg.com/map-obj/-/map-obj-1.0.1.tgz#d933ceb9205d82bdcf4886f6742bdc2b4dea146d"
2999+ integrity sha1-2TPOuSBdgr3PSIb2dCvcK03qFG0=
3000+
3001+map-obj@^2.0.0:
3002+ version "2.0.0"
3003+ resolved "https://registry.yarnpkg.com/map-obj/-/map-obj-2.0.0.tgz#a65cd29087a92598b8791257a523e021222ac1f9"
3004+ integrity sha1-plzSkIepJZi4eRJXpSPgISIqwfk=
3005+
3006+map-obj@^4.0.0:
3007+ version "4.2.1"
3008+ resolved "https://registry.yarnpkg.com/map-obj/-/map-obj-4.2.1.tgz#e4ea399dbc979ae735c83c863dd31bdf364277b7"
3009+ integrity sha512-+WA2/1sPmDj1dlvvJmB5G6JKfY9dpn7EVBUL06+y6PoljPkh+6V1QihwxNkbcGxCRjt2b0F9K0taiCuo7MbdFQ==
3010+
3011+map-stream@~0.0.7:
3012+ version "0.0.7"
3013+ resolved "https://registry.yarnpkg.com/map-stream/-/map-stream-0.0.7.tgz#8a1f07896d82b10926bd3744a2420009f88974a8"
3014+ integrity sha1-ih8HiW2CsQkmvTdEokIACfiJdKg=
3015+
3016+map-visit@^1.0.0:
3017+ version "1.0.0"
3018+ resolved "https://registry.yarnpkg.com/map-visit/-/map-visit-1.0.0.tgz#ecdca8f13144e660f1b5bd41f12f3479d98dfb8f"
3019+ integrity sha1-7Nyo8TFE5mDxtb1B8S80edmN+48=
3020+ dependencies:
3021+ object-visit "^1.0.0"
3022+
3023+matchdep@^2.0.0:
3024+ version "2.0.0"
3025+ resolved "https://registry.yarnpkg.com/matchdep/-/matchdep-2.0.0.tgz#c6f34834a0d8dbc3b37c27ee8bbcb27c7775582e"
3026+ integrity sha1-xvNINKDY28OzfCfui7yyfHd1WC4=
3027+ dependencies:
3028+ findup-sync "^2.0.0"
3029+ micromatch "^3.0.4"
3030+ resolve "^1.4.0"
3031+ stack-trace "0.0.10"
3032+
3033+media-typer@0.3.0:
3034+ version "0.3.0"
3035+ resolved "https://registry.yarnpkg.com/media-typer/-/media-typer-0.3.0.tgz#8710d7af0aa626f8fffa1ce00168545263255748"
3036+ integrity sha1-hxDXrwqmJvj/+hzgAWhUUmMlV0g=
3037+
3038+meow@5.0.0:
3039+ version "5.0.0"
3040+ resolved "https://registry.yarnpkg.com/meow/-/meow-5.0.0.tgz#dfc73d63a9afc714a5e371760eb5c88b91078aa4"
3041+ integrity sha512-CbTqYU17ABaLefO8vCU153ZZlprKYWDljcndKKDCFcYQITzWCXZAVk4QMFZPgvzrnUQ3uItnIE/LoUOwrT15Ig==
3042+ dependencies:
3043+ camelcase-keys "^4.0.0"
3044+ decamelize-keys "^1.0.0"
3045+ loud-rejection "^1.0.0"
3046+ minimist-options "^3.0.1"
3047+ normalize-package-data "^2.3.4"
3048+ read-pkg-up "^3.0.0"
3049+ redent "^2.0.0"
3050+ trim-newlines "^2.0.0"
3051+ yargs-parser "^10.0.0"
3052+
3053+meow@^7.0.0:
3054+ version "7.1.1"
3055+ resolved "https://registry.yarnpkg.com/meow/-/meow-7.1.1.tgz#7c01595e3d337fcb0ec4e8eed1666ea95903d306"
3056+ integrity sha512-GWHvA5QOcS412WCo8vwKDlTelGLsCGBVevQB5Kva961rmNfun0PCbv5+xta2kUMFJyR8/oWnn7ddeKdosbAPbA==
3057+ dependencies:
3058+ "@types/minimist" "^1.2.0"
3059+ camelcase-keys "^6.2.2"
3060+ decamelize-keys "^1.1.0"
3061+ hard-rejection "^2.1.0"
3062+ minimist-options "4.1.0"
3063+ normalize-package-data "^2.5.0"
3064+ read-pkg-up "^7.0.1"
3065+ redent "^3.0.0"
3066+ trim-newlines "^3.0.0"
3067+ type-fest "^0.13.1"
3068+ yargs-parser "^18.1.3"
3069+
3070+meow@^8.0.0:
3071+ version "8.1.2"
3072+ resolved "https://registry.yarnpkg.com/meow/-/meow-8.1.2.tgz#bcbe45bda0ee1729d350c03cffc8395a36c4e897"
3073+ integrity sha512-r85E3NdZ+mpYk1C6RjPFEMSE+s1iZMuHtsHAqY0DT3jZczl0diWUZ8g6oU7h0M9cD2EL+PzaYghhCLzR0ZNn5Q==
3074+ dependencies:
3075+ "@types/minimist" "^1.2.0"
3076+ camelcase-keys "^6.2.2"
3077+ decamelize-keys "^1.1.0"
3078+ hard-rejection "^2.1.0"
3079+ minimist-options "4.1.0"
3080+ normalize-package-data "^3.0.0"
3081+ read-pkg-up "^7.0.1"
3082+ redent "^3.0.0"
3083+ trim-newlines "^3.0.0"
3084+ type-fest "^0.18.0"
3085+ yargs-parser "^20.2.3"
3086+
3087+merge-descriptors@1.0.1:
3088+ version "1.0.1"
3089+ resolved "https://registry.yarnpkg.com/merge-descriptors/-/merge-descriptors-1.0.1.tgz#b00aaa556dd8b44568150ec9d1b953f3f90cbb61"
3090+ integrity sha1-sAqqVW3YtEVoFQ7J0blT8/kMu2E=
3091+
3092+merge2@^1.3.0:
3093+ version "1.4.1"
3094+ resolved "https://registry.yarnpkg.com/merge2/-/merge2-1.4.1.tgz#4368892f885e907455a6fd7dc55c0c9d404990ae"
3095+ integrity sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==
3096+
3097+methods@~1.1.2:
3098+ version "1.1.2"
3099+ resolved "https://registry.yarnpkg.com/methods/-/methods-1.1.2.tgz#5529a4d67654134edcc5266656835b0f851afcee"
3100+ integrity sha1-VSmk1nZUE07cxSZmVoNbD4Ua/O4=
3101+
3102+micromatch@^3.0.4, micromatch@^3.1.10, micromatch@^3.1.4:
3103+ version "3.1.10"
3104+ resolved "https://registry.yarnpkg.com/micromatch/-/micromatch-3.1.10.tgz#70859bc95c9840952f359a068a3fc49f9ecfac23"
3105+ integrity sha512-MWikgl9n9M3w+bpsY3He8L+w9eF9338xRl8IAO5viDizwSzziFEyUzo2xrrloB64ADbTf8uA8vRqqttDTOmccg==
3106+ dependencies:
3107+ arr-diff "^4.0.0"
3108+ array-unique "^0.3.2"
3109+ braces "^2.3.1"
3110+ define-property "^2.0.2"
3111+ extend-shallow "^3.0.2"
3112+ extglob "^2.0.4"
3113+ fragment-cache "^0.2.1"
3114+ kind-of "^6.0.2"
3115+ nanomatch "^1.2.9"
3116+ object.pick "^1.3.0"
3117+ regex-not "^1.0.0"
3118+ snapdragon "^0.8.1"
3119+ to-regex "^3.0.2"
3120+
3121+micromatch@^4.0.4:
3122+ version "4.0.4"
3123+ resolved "https://registry.yarnpkg.com/micromatch/-/micromatch-4.0.4.tgz#896d519dfe9db25fce94ceb7a500919bf881ebf9"
3124+ integrity sha512-pRmzw/XUcwXGpD9aI9q/0XOwLNygjETJ8y0ao0wdqprrzDa4YnxLcz7fQRZr8voh8V10kGhABbNcHVk5wHgWwg==
3125+ dependencies:
3126+ braces "^3.0.1"
3127+ picomatch "^2.2.3"
3128+
3129+mime-db@1.48.0:
3130+ version "1.48.0"
3131+ resolved "https://registry.yarnpkg.com/mime-db/-/mime-db-1.48.0.tgz#e35b31045dd7eada3aaad537ed88a33afbef2d1d"
3132+ integrity sha512-FM3QwxV+TnZYQ2aRqhlKBMHxk10lTbMt3bBkMAp54ddrNeVSfcQYOOKuGuy3Ddrm38I04If834fOUSq1yzslJQ==
3133+
3134+mime-types@^2.1.12, mime-types@~2.1.19, mime-types@~2.1.24:
3135+ version "2.1.31"
3136+ resolved "https://registry.yarnpkg.com/mime-types/-/mime-types-2.1.31.tgz#a00d76b74317c61f9c2db2218b8e9f8e9c5c9e6b"
3137+ integrity sha512-XGZnNzm3QvgKxa8dpzyhFTHmpP3l5YNusmne07VUOXxou9CqUqYa/HBy124RqtVh/O2pECas/MOcsDgpilPOPg==
3138+ dependencies:
3139+ mime-db "1.48.0"
3140+
3141+mime@1.6.0:
3142+ version "1.6.0"
3143+ resolved "https://registry.yarnpkg.com/mime/-/mime-1.6.0.tgz#32cd9e5c64553bd58d19a568af452acff04981b1"
3144+ integrity sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg==
3145+
3146+min-indent@^1.0.0:
3147+ version "1.0.1"
3148+ resolved "https://registry.yarnpkg.com/min-indent/-/min-indent-1.0.1.tgz#a63f681673b30571fbe8bc25686ae746eefa9869"
3149+ integrity sha512-I9jwMn07Sy/IwOj3zVkVik2JTvgpaykDZEigL6Rx6N9LbMywwUSMtxET+7lVoDLLd3O3IXwJwvuuns8UB/HeAg==
3150+
3151+minimatch@^3.0.4:
3152+ version "3.0.4"
3153+ resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-3.0.4.tgz#5166e286457f03306064be5497e8dbb0c3d32083"
3154+ integrity sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==
3155+ dependencies:
3156+ brace-expansion "^1.1.7"
3157+
3158+minimist-options@4.1.0:
3159+ version "4.1.0"
3160+ resolved "https://registry.yarnpkg.com/minimist-options/-/minimist-options-4.1.0.tgz#c0655713c53a8a2ebd77ffa247d342c40f010619"
3161+ integrity sha512-Q4r8ghd80yhO/0j1O3B2BjweX3fiHg9cdOwjJd2J76Q135c+NDxGCqdYKQ1SKBuFfgWbAUzBfvYjPUEeNgqN1A==
3162+ dependencies:
3163+ arrify "^1.0.1"
3164+ is-plain-obj "^1.1.0"
3165+ kind-of "^6.0.3"
3166+
3167+minimist-options@^3.0.1:
3168+ version "3.0.2"
3169+ resolved "https://registry.yarnpkg.com/minimist-options/-/minimist-options-3.0.2.tgz#fba4c8191339e13ecf4d61beb03f070103f3d954"
3170+ integrity sha512-FyBrT/d0d4+uiZRbqznPXqw3IpZZG3gl3wKWiX784FycUKVwBt0uLBFkQrtE4tZOrgo78nZp2jnKz3L65T5LdQ==
3171+ dependencies:
3172+ arrify "^1.0.1"
3173+ is-plain-obj "^1.1.0"
3174+
3175+minimist@^1.2.5:
3176+ version "1.2.5"
3177+ resolved "https://registry.yarnpkg.com/minimist/-/minimist-1.2.5.tgz#67d66014b66a6a8aaa0c083c5fd58df4e4e97602"
3178+ integrity sha512-FM9nNUYrRBAELZQT3xeZQ7fmMOBg6nWNmJKTcgsJeaLstP/UODVpGsr5OhXhhXg6f+qtJ8uiZ+PUxkDWcgIXLw==
3179+
3180+mixin-deep@^1.2.0:
3181+ version "1.3.2"
3182+ resolved "https://registry.yarnpkg.com/mixin-deep/-/mixin-deep-1.3.2.tgz#1120b43dc359a785dce65b55b82e257ccf479566"
3183+ integrity sha512-WRoDn//mXBiJ1H40rqa3vH0toePwSsGb45iInWlTySa+Uu4k3tYUSxa2v1KqAiLtvlrSzaExqS1gtk96A9zvEA==
3184+ dependencies:
3185+ for-in "^1.0.2"
3186+ is-extendable "^1.0.1"
3187+
3188+mkdirp@^0.5.1, mkdirp@^0.5.3:
3189+ version "0.5.5"
3190+ resolved "https://registry.yarnpkg.com/mkdirp/-/mkdirp-0.5.5.tgz#d91cefd62d1436ca0f41620e251288d420099def"
3191+ integrity sha512-NKmAlESf6jMGym1++R0Ra7wvhV+wFW63FaSOFPwRahvea0gMUcGUhVeAg/0BC0wiv9ih5NYPB1Wn1UEI1/L+xQ==
3192+ dependencies:
3193+ minimist "^1.2.5"
3194+
3195+modify-values@^1.0.0:
3196+ version "1.0.1"
3197+ resolved "https://registry.yarnpkg.com/modify-values/-/modify-values-1.0.1.tgz#b3939fa605546474e3e3e3c63d64bd43b4ee6022"
3198+ integrity sha512-xV2bxeN6F7oYjZWTe/YPAy6MN2M+sL4u/Rlm2AHCIVGfo2p1yGmBHQ6vHehl4bRTZBdHu3TSkWdYgkwpYzAGSw==
3199+
3200+ms@2.0.0:
3201+ version "2.0.0"
3202+ resolved "https://registry.yarnpkg.com/ms/-/ms-2.0.0.tgz#5608aeadfc00be6c2901df5f9861788de0d597c8"
3203+ integrity sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=
3204+
3205+ms@2.1.1:
3206+ version "2.1.1"
3207+ resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.1.tgz#30a5864eb3ebb0a66f2ebe6d727af06a09d86e0a"
3208+ integrity sha512-tgp+dl5cGk28utYktBsrFqA7HKgrhgPsg6Z/EfhWI4gl1Hwq8B/GmY/0oXZ6nF8hDVesS/FpnYaD/kOWhYQvyg==
3209+
3210+multimatch@^4.0.0:
3211+ version "4.0.0"
3212+ resolved "https://registry.yarnpkg.com/multimatch/-/multimatch-4.0.0.tgz#8c3c0f6e3e8449ada0af3dd29efb491a375191b3"
3213+ integrity sha512-lDmx79y1z6i7RNx0ZGCPq1bzJ6ZoDDKbvh7jxr9SJcWLkShMzXrHbYVpTdnhNM5MXpDUxCQ4DgqVttVXlBgiBQ==
3214+ dependencies:
3215+ "@types/minimatch" "^3.0.3"
3216+ array-differ "^3.0.0"
3217+ array-union "^2.1.0"
3218+ arrify "^2.0.1"
3219+ minimatch "^3.0.4"
3220+
3221+mute-stdout@^1.0.0:
3222+ version "1.0.1"
3223+ resolved "https://registry.yarnpkg.com/mute-stdout/-/mute-stdout-1.0.1.tgz#acb0300eb4de23a7ddeec014e3e96044b3472331"
3224+ integrity sha512-kDcwXR4PS7caBpuRYYBUz9iVixUk3anO3f5OYFiIPwK/20vCzKCHyKoulbiDY1S53zD2bxUpxN/IJ+TnXjfvxg==
3225+
3226+nan@^2.12.1:
3227+ version "2.14.2"
3228+ resolved "https://registry.yarnpkg.com/nan/-/nan-2.14.2.tgz#f5376400695168f4cc694ac9393d0c9585eeea19"
3229+ integrity sha512-M2ufzIiINKCuDfBSAUr1vWQ+vuVcA9kqx8JJUsbQi6yf1uGRyb7HfpdfUr5qLXf3B/t8dPvcjhKMmlfnP47EzQ==
3230+
3231+nanomatch@^1.2.9:
3232+ version "1.2.13"
3233+ resolved "https://registry.yarnpkg.com/nanomatch/-/nanomatch-1.2.13.tgz#b87a8aa4fc0de8fe6be88895b38983ff265bd119"
3234+ integrity sha512-fpoe2T0RbHwBTBUOftAfBPaDEi06ufaUai0mE6Yn1kacc3SnTErfb/h+X94VXzI64rKFHYImXSvdwGGCmwOqCA==
3235+ dependencies:
3236+ arr-diff "^4.0.0"
3237+ array-unique "^0.3.2"
3238+ define-property "^2.0.2"
3239+ extend-shallow "^3.0.2"
3240+ fragment-cache "^0.2.1"
3241+ is-windows "^1.0.2"
3242+ kind-of "^6.0.2"
3243+ object.pick "^1.3.0"
3244+ regex-not "^1.0.0"
3245+ snapdragon "^0.8.1"
3246+ to-regex "^3.0.1"
3247+
3248+negotiator@0.6.2:
3249+ version "0.6.2"
3250+ resolved "https://registry.yarnpkg.com/negotiator/-/negotiator-0.6.2.tgz#feacf7ccf525a77ae9634436a64883ffeca346fb"
3251+ integrity sha512-hZXc7K2e+PgeI1eDBe/10Ard4ekbfrrqG8Ep+8Jmf4JID2bNg7NvCPOZN+kfF574pFQI7mum2AUqDidoKqcTOw==
3252+
3253+neo-async@^2.6.0:
3254+ version "2.6.2"
3255+ resolved "https://registry.yarnpkg.com/neo-async/-/neo-async-2.6.2.tgz#b4aafb93e3aeb2d8174ca53cf163ab7d7308305f"
3256+ integrity sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw==
3257+
3258+next-tick@~1.0.0:
3259+ version "1.0.0"
3260+ resolved "https://registry.yarnpkg.com/next-tick/-/next-tick-1.0.0.tgz#ca86d1fe8828169b0120208e3dc8424b9db8342c"
3261+ integrity sha1-yobR/ogoFpsBICCOPchCS524NCw=
3262+
3263+normalize-package-data@^2.3.2, normalize-package-data@^2.3.4, normalize-package-data@^2.5.0:
3264+ version "2.5.0"
3265+ resolved "https://registry.yarnpkg.com/normalize-package-data/-/normalize-package-data-2.5.0.tgz#e66db1838b200c1dfc233225d12cb36520e234a8"
3266+ integrity sha512-/5CMN3T0R4XTj4DcGaexo+roZSdSFW/0AOOTROrjxzCG1wrWXEsGbRKevjlIL+ZDE4sZlJr5ED4YW0yqmkK+eA==
3267+ dependencies:
3268+ hosted-git-info "^2.1.4"
3269+ resolve "^1.10.0"
3270+ semver "2 || 3 || 4 || 5"
3271+ validate-npm-package-license "^3.0.1"
3272+
3273+normalize-package-data@^3.0.0:
3274+ version "3.0.2"
3275+ resolved "https://registry.yarnpkg.com/normalize-package-data/-/normalize-package-data-3.0.2.tgz#cae5c410ae2434f9a6c1baa65d5bc3b9366c8699"
3276+ integrity sha512-6CdZocmfGaKnIHPVFhJJZ3GuR8SsLKvDANFp47Jmy51aKIr8akjAWTSxtpI+MBgBFdSMRyo4hMpDlT6dTffgZg==
3277+ dependencies:
3278+ hosted-git-info "^4.0.1"
3279+ resolve "^1.20.0"
3280+ semver "^7.3.4"
3281+ validate-npm-package-license "^3.0.1"
3282+
3283+normalize-path@^2.1.1:
3284+ version "2.1.1"
3285+ resolved "https://registry.yarnpkg.com/normalize-path/-/normalize-path-2.1.1.tgz#1ab28b556e198363a8c1a6f7e6fa20137fe6aed9"
3286+ integrity sha1-GrKLVW4Zg2Oowab35vogE3/mrtk=
3287+ dependencies:
3288+ remove-trailing-separator "^1.0.1"
3289+
3290+normalize-path@^3.0.0:
3291+ version "3.0.0"
3292+ resolved "https://registry.yarnpkg.com/normalize-path/-/normalize-path-3.0.0.tgz#0dcd69ff23a1c9b11fd0978316644a0388216a65"
3293+ integrity sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==
3294+
3295+now-and-later@^2.0.0:
3296+ version "2.0.1"
3297+ resolved "https://registry.yarnpkg.com/now-and-later/-/now-and-later-2.0.1.tgz#8e579c8685764a7cc02cb680380e94f43ccb1f7c"
3298+ integrity sha512-KGvQ0cB70AQfg107Xvs/Fbu+dGmZoTRJp2TaPwcwQm3/7PteUyN2BCgk8KBMPGBUXZdVwyWS8fDCGFygBm19UQ==
3299+ dependencies:
3300+ once "^1.3.2"
3301+
3302+number-is-nan@^1.0.0:
3303+ version "1.0.1"
3304+ resolved "https://registry.yarnpkg.com/number-is-nan/-/number-is-nan-1.0.1.tgz#097b602b53422a522c1afb8790318336941a011d"
3305+ integrity sha1-CXtgK1NCKlIsGvuHkDGDNpQaAR0=
3306+
3307+oauth-sign@~0.9.0:
3308+ version "0.9.0"
3309+ resolved "https://registry.yarnpkg.com/oauth-sign/-/oauth-sign-0.9.0.tgz#47a7b016baa68b5fa0ecf3dee08a85c679ac6455"
3310+ integrity sha512-fexhUFFPTGV8ybAtSIGbV6gOkSv8UtRbDBnAyLQw4QPKkgNlsH2ByPGtMUqdWkos6YCRmAqViwgZrJc/mRDzZQ==
3311+
3312+object-assign@^4.0.1:
3313+ version "4.1.1"
3314+ resolved "https://registry.yarnpkg.com/object-assign/-/object-assign-4.1.1.tgz#2109adc7965887cfc05cbbd442cac8bfbb360863"
3315+ integrity sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM=
3316+
3317+object-copy@^0.1.0:
3318+ version "0.1.0"
3319+ resolved "https://registry.yarnpkg.com/object-copy/-/object-copy-0.1.0.tgz#7e7d858b781bd7c991a41ba975ed3812754e998c"
3320+ integrity sha1-fn2Fi3gb18mRpBupde04EnVOmYw=
3321+ dependencies:
3322+ copy-descriptor "^0.1.0"
3323+ define-property "^0.2.5"
3324+ kind-of "^3.0.3"
3325+
3326+object-keys@^1.0.12, object-keys@^1.1.1:
3327+ version "1.1.1"
3328+ resolved "https://registry.yarnpkg.com/object-keys/-/object-keys-1.1.1.tgz#1c47f272df277f3b1daf061677d9c82e2322c60e"
3329+ integrity sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==
3330+
3331+object-visit@^1.0.0:
3332+ version "1.0.1"
3333+ resolved "https://registry.yarnpkg.com/object-visit/-/object-visit-1.0.1.tgz#f79c4493af0c5377b59fe39d395e41042dd045bb"
3334+ integrity sha1-95xEk68MU3e1n+OdOV5BBC3QRbs=
3335+ dependencies:
3336+ isobject "^3.0.0"
3337+
3338+object.assign@^4.0.4, object.assign@^4.1.0:
3339+ version "4.1.2"
3340+ resolved "https://registry.yarnpkg.com/object.assign/-/object.assign-4.1.2.tgz#0ed54a342eceb37b38ff76eb831a0e788cb63940"
3341+ integrity sha512-ixT2L5THXsApyiUPYKmW+2EHpXXe5Ii3M+f4e+aJFAHao5amFRW6J0OO6c/LU8Be47utCx2GL89hxGB6XSmKuQ==
3342+ dependencies:
3343+ call-bind "^1.0.0"
3344+ define-properties "^1.1.3"
3345+ has-symbols "^1.0.1"
3346+ object-keys "^1.1.1"
3347+
3348+object.defaults@^1.0.0, object.defaults@^1.1.0:
3349+ version "1.1.0"
3350+ resolved "https://registry.yarnpkg.com/object.defaults/-/object.defaults-1.1.0.tgz#3a7f868334b407dea06da16d88d5cd29e435fecf"
3351+ integrity sha1-On+GgzS0B96gbaFtiNXNKeQ1/s8=
3352+ dependencies:
3353+ array-each "^1.0.1"
3354+ array-slice "^1.0.0"
3355+ for-own "^1.0.0"
3356+ isobject "^3.0.0"
3357+
3358+object.map@^1.0.0:
3359+ version "1.0.1"
3360+ resolved "https://registry.yarnpkg.com/object.map/-/object.map-1.0.1.tgz#cf83e59dc8fcc0ad5f4250e1f78b3b81bd801d37"
3361+ integrity sha1-z4Plncj8wK1fQlDh94s7gb2AHTc=
3362+ dependencies:
3363+ for-own "^1.0.0"
3364+ make-iterator "^1.0.0"
3365+
3366+object.pick@^1.2.0, object.pick@^1.3.0:
3367+ version "1.3.0"
3368+ resolved "https://registry.yarnpkg.com/object.pick/-/object.pick-1.3.0.tgz#87a10ac4c1694bd2e1cbf53591a66141fb5dd747"
3369+ integrity sha1-h6EKxMFpS9Lhy/U1kaZhQftd10c=
3370+ dependencies:
3371+ isobject "^3.0.1"
3372+
3373+object.reduce@^1.0.0:
3374+ version "1.0.1"
3375+ resolved "https://registry.yarnpkg.com/object.reduce/-/object.reduce-1.0.1.tgz#6fe348f2ac7fa0f95ca621226599096825bb03ad"
3376+ integrity sha1-b+NI8qx/oPlcpiEiZZkJaCW7A60=
3377+ dependencies:
3378+ for-own "^1.0.0"
3379+ make-iterator "^1.0.0"
3380+
3381+on-finished@~2.3.0:
3382+ version "2.3.0"
3383+ resolved "https://registry.yarnpkg.com/on-finished/-/on-finished-2.3.0.tgz#20f1336481b083cd75337992a16971aa2d906947"
3384+ integrity sha1-IPEzZIGwg811M3mSoWlxqi2QaUc=
3385+ dependencies:
3386+ ee-first "1.1.1"
3387+
3388+once@^1.3.0, once@^1.3.1, once@^1.3.2, once@^1.4.0:
3389+ version "1.4.0"
3390+ resolved "https://registry.yarnpkg.com/once/-/once-1.4.0.tgz#583b1aa775961d4b113ac17d9c50baef9dd76bd1"
3391+ integrity sha1-WDsap3WWHUsROsF9nFC6753Xa9E=
3392+ dependencies:
3393+ wrappy "1"
3394+
3395+openapi-types@^7.0.1:
3396+ version "7.2.3"
3397+ resolved "https://registry.yarnpkg.com/openapi-types/-/openapi-types-7.2.3.tgz#83829911a3410a022f0e0cf2b0b2e67232ccf96e"
3398+ integrity sha512-olbaNxz12R27+mTyJ/ZAFEfUruauHH27AkeQHDHRq5AF0LdNkK1SSV7EourXQDK+4aX7dv2HtyirAGK06WMAsA==
3399+
3400+openapi3-ts@^2.0.0:
3401+ version "2.0.1"
3402+ resolved "https://registry.yarnpkg.com/openapi3-ts/-/openapi3-ts-2.0.1.tgz#b270aecea09e924f1886bc02a72608fca5a98d85"
3403+ integrity sha512-v6X3iwddhi276siej96jHGIqTx3wzVfMTmpGJEQDt7GPI7pI6sywItURLzpEci21SBRpPN/aOWSF5mVfFVNmcg==
3404+ dependencies:
3405+ yaml "^1.10.0"
3406+
3407+ordered-read-streams@^1.0.0:
3408+ version "1.0.1"
3409+ resolved "https://registry.yarnpkg.com/ordered-read-streams/-/ordered-read-streams-1.0.1.tgz#77c0cb37c41525d64166d990ffad7ec6a0e1363e"
3410+ integrity sha1-d8DLN8QVJdZBZtmQ/61+xqDhNj4=
3411+ dependencies:
3412+ readable-stream "^2.0.1"
3413+
3414+os-locale@^1.4.0:
3415+ version "1.4.0"
3416+ resolved "https://registry.yarnpkg.com/os-locale/-/os-locale-1.4.0.tgz#20f9f17ae29ed345e8bde583b13d2009803c14d9"
3417+ integrity sha1-IPnxeuKe00XoveWDsT0gCYA8FNk=
3418+ dependencies:
3419+ lcid "^1.0.0"
3420+
3421+p-limit@^1.1.0:
3422+ version "1.3.0"
3423+ resolved "https://registry.yarnpkg.com/p-limit/-/p-limit-1.3.0.tgz#b86bd5f0c25690911c7590fcbfc2010d54b3ccb8"
3424+ integrity sha512-vvcXsLAJ9Dr5rQOPk7toZQZJApBl2K4J6dANSsEuh6QI41JYcsS/qhTGa9ErIUUgK3WNQoJYvylxvjqmiqEA9Q==
3425+ dependencies:
3426+ p-try "^1.0.0"
3427+
3428+p-limit@^2.2.0:
3429+ version "2.3.0"
3430+ resolved "https://registry.yarnpkg.com/p-limit/-/p-limit-2.3.0.tgz#3dd33c647a214fdfffd835933eb086da0dc21db1"
3431+ integrity sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==
3432+ dependencies:
3433+ p-try "^2.0.0"
3434+
3435+p-locate@^2.0.0:
3436+ version "2.0.0"
3437+ resolved "https://registry.yarnpkg.com/p-locate/-/p-locate-2.0.0.tgz#20a0103b222a70c8fd39cc2e580680f3dde5ec43"
3438+ integrity sha1-IKAQOyIqcMj9OcwuWAaA893l7EM=
3439+ dependencies:
3440+ p-limit "^1.1.0"
3441+
3442+p-locate@^4.1.0:
3443+ version "4.1.0"
3444+ resolved "https://registry.yarnpkg.com/p-locate/-/p-locate-4.1.0.tgz#a3428bb7088b3a60292f66919278b7c297ad4f07"
3445+ integrity sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==
3446+ dependencies:
3447+ p-limit "^2.2.0"
3448+
3449+p-map@^4.0.0:
3450+ version "4.0.0"
3451+ resolved "https://registry.yarnpkg.com/p-map/-/p-map-4.0.0.tgz#bb2f95a5eda2ec168ec9274e06a747c3e2904d2b"
3452+ integrity sha512-/bjOqmgETBYB5BoEeGVea8dmvHb2m9GLy1E9W43yeyfP6QQCZGFNa+XRceJEuDB6zqr+gKpIAmlLebMpykw/MQ==
3453+ dependencies:
3454+ aggregate-error "^3.0.0"
3455+
3456+p-try@^1.0.0:
3457+ version "1.0.0"
3458+ resolved "https://registry.yarnpkg.com/p-try/-/p-try-1.0.0.tgz#cbc79cdbaf8fd4228e13f621f2b1a237c1b207b3"
3459+ integrity sha1-y8ec26+P1CKOE/Yh8rGiN8GyB7M=
3460+
3461+p-try@^2.0.0:
3462+ version "2.2.0"
3463+ resolved "https://registry.yarnpkg.com/p-try/-/p-try-2.2.0.tgz#cb2868540e313d61de58fafbe35ce9004d5540e6"
3464+ integrity sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==
3465+
3466+parent-module@^1.0.0:
3467+ version "1.0.1"
3468+ resolved "https://registry.yarnpkg.com/parent-module/-/parent-module-1.0.1.tgz#691d2709e78c79fae3a156622452d00762caaaa2"
3469+ integrity sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==
3470+ dependencies:
3471+ callsites "^3.0.0"
3472+
3473+parse-filepath@^1.0.1:
3474+ version "1.0.2"
3475+ resolved "https://registry.yarnpkg.com/parse-filepath/-/parse-filepath-1.0.2.tgz#a632127f53aaf3d15876f5872f3ffac763d6c891"
3476+ integrity sha1-pjISf1Oq89FYdvWHLz/6x2PWyJE=
3477+ dependencies:
3478+ is-absolute "^1.0.0"
3479+ map-cache "^0.2.0"
3480+ path-root "^0.1.1"
3481+
3482+parse-json@^2.2.0:
3483+ version "2.2.0"
3484+ resolved "https://registry.yarnpkg.com/parse-json/-/parse-json-2.2.0.tgz#f480f40434ef80741f8469099f8dea18f55a4dc9"
3485+ integrity sha1-9ID0BDTvgHQfhGkJn43qGPVaTck=
3486+ dependencies:
3487+ error-ex "^1.2.0"
3488+
3489+parse-json@^4.0.0:
3490+ version "4.0.0"
3491+ resolved "https://registry.yarnpkg.com/parse-json/-/parse-json-4.0.0.tgz#be35f5425be1f7f6c747184f98a788cb99477ee0"
3492+ integrity sha1-vjX1Qlvh9/bHRxhPmKeIy5lHfuA=
3493+ dependencies:
3494+ error-ex "^1.3.1"
3495+ json-parse-better-errors "^1.0.1"
3496+
3497+parse-json@^5.0.0:
3498+ version "5.2.0"
3499+ resolved "https://registry.yarnpkg.com/parse-json/-/parse-json-5.2.0.tgz#c76fc66dee54231c962b22bcc8a72cf2f99753cd"
3500+ integrity sha512-ayCKvm/phCGxOkYRSCM82iDwct8/EonSEgCSxWxD7ve6jHggsFl4fZVQBPRNgQoKiuV/odhFrGzQXZwbifC8Rg==
3501+ dependencies:
3502+ "@babel/code-frame" "^7.0.0"
3503+ error-ex "^1.3.1"
3504+ json-parse-even-better-errors "^2.3.0"
3505+ lines-and-columns "^1.1.6"
3506+
3507+parse-node-version@^1.0.0:
3508+ version "1.0.1"
3509+ resolved "https://registry.yarnpkg.com/parse-node-version/-/parse-node-version-1.0.1.tgz#e2b5dbede00e7fa9bc363607f53327e8b073189b"
3510+ integrity sha512-3YHlOa/JgH6Mnpr05jP9eDG254US9ek25LyIxZlDItp2iJtwyaXQb57lBYLdT3MowkUFYEV2XXNAYIPlESvJlA==
3511+
3512+parse-passwd@^1.0.0:
3513+ version "1.0.0"
3514+ resolved "https://registry.yarnpkg.com/parse-passwd/-/parse-passwd-1.0.0.tgz#6d5b934a456993b23d37f40a382d6f1666a8e5c6"
3515+ integrity sha1-bVuTSkVpk7I9N/QKOC1vFmao5cY=
3516+
3517+parseurl@~1.3.3:
3518+ version "1.3.3"
3519+ resolved "https://registry.yarnpkg.com/parseurl/-/parseurl-1.3.3.tgz#9da19e7bee8d12dff0513ed5b76957793bc2e8d4"
3520+ integrity sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ==
3521+
3522+pascalcase@^0.1.1:
3523+ version "0.1.1"
3524+ resolved "https://registry.yarnpkg.com/pascalcase/-/pascalcase-0.1.1.tgz#b363e55e8006ca6fe21784d2db22bd15d7917f14"
3525+ integrity sha1-s2PlXoAGym/iF4TS2yK9FdeRfxQ=
3526+
3527+path-dirname@^1.0.0:
3528+ version "1.0.2"
3529+ resolved "https://registry.yarnpkg.com/path-dirname/-/path-dirname-1.0.2.tgz#cc33d24d525e099a5388c0336c6e32b9160609e0"
3530+ integrity sha1-zDPSTVJeCZpTiMAzbG4yuRYGCeA=
3531+
3532+path-exists@^2.0.0:
3533+ version "2.1.0"
3534+ resolved "https://registry.yarnpkg.com/path-exists/-/path-exists-2.1.0.tgz#0feb6c64f0fc518d9a754dd5efb62c7022761f4b"
3535+ integrity sha1-D+tsZPD8UY2adU3V77YscCJ2H0s=
3536+ dependencies:
3537+ pinkie-promise "^2.0.0"
3538+
3539+path-exists@^3.0.0:
3540+ version "3.0.0"
3541+ resolved "https://registry.yarnpkg.com/path-exists/-/path-exists-3.0.0.tgz#ce0ebeaa5f78cb18925ea7d810d7b59b010fd515"
3542+ integrity sha1-zg6+ql94yxiSXqfYENe1mwEP1RU=
3543+
3544+path-exists@^4.0.0:
3545+ version "4.0.0"
3546+ resolved "https://registry.yarnpkg.com/path-exists/-/path-exists-4.0.0.tgz#513bdbe2d3b95d7762e8c1137efa195c6c61b5b3"
3547+ integrity sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==
3548+
3549+path-is-absolute@^1.0.0:
3550+ version "1.0.1"
3551+ resolved "https://registry.yarnpkg.com/path-is-absolute/-/path-is-absolute-1.0.1.tgz#174b9268735534ffbc7ace6bf53a5a9e1b5c5f5f"
3552+ integrity sha1-F0uSaHNVNP+8es5r9TpanhtcX18=
3553+
3554+path-parse@^1.0.6:
3555+ version "1.0.7"
3556+ resolved "https://registry.yarnpkg.com/path-parse/-/path-parse-1.0.7.tgz#fbc114b60ca42b30d9daf5858e4bd68bbedb6735"
3557+ integrity sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==
3558+
3559+path-root-regex@^0.1.0:
3560+ version "0.1.2"
3561+ resolved "https://registry.yarnpkg.com/path-root-regex/-/path-root-regex-0.1.2.tgz#bfccdc8df5b12dc52c8b43ec38d18d72c04ba96d"
3562+ integrity sha1-v8zcjfWxLcUsi0PsONGNcsBLqW0=
3563+
3564+path-root@^0.1.1:
3565+ version "0.1.1"
3566+ resolved "https://registry.yarnpkg.com/path-root/-/path-root-0.1.1.tgz#9a4a6814cac1c0cd73360a95f32083c8ea4745b7"
3567+ integrity sha1-mkpoFMrBwM1zNgqV8yCDyOpHRbc=
3568+ dependencies:
3569+ path-root-regex "^0.1.0"
3570+
3571+path-to-regexp@0.1.7:
3572+ version "0.1.7"
3573+ resolved "https://registry.yarnpkg.com/path-to-regexp/-/path-to-regexp-0.1.7.tgz#df604178005f522f15eb4490e7247a1bfaa67f8c"
3574+ integrity sha1-32BBeABfUi8V60SQ5yR6G/qmf4w=
3575+
3576+path-type@^1.0.0:
3577+ version "1.1.0"
3578+ resolved "https://registry.yarnpkg.com/path-type/-/path-type-1.1.0.tgz#59c44f7ee491da704da415da5a4070ba4f8fe441"
3579+ integrity sha1-WcRPfuSR2nBNpBXaWkBwuk+P5EE=
3580+ dependencies:
3581+ graceful-fs "^4.1.2"
3582+ pify "^2.0.0"
3583+ pinkie-promise "^2.0.0"
3584+
3585+path-type@^3.0.0:
3586+ version "3.0.0"
3587+ resolved "https://registry.yarnpkg.com/path-type/-/path-type-3.0.0.tgz#cef31dc8e0a1a3bb0d105c0cd97cf3bf47f4e36f"
3588+ integrity sha512-T2ZUsdZFHgA3u4e5PfPbjd7HDDpxPnQb5jN0SrDsjNSuVXHJqtwTnWqG0B1jZrgmJ/7lj1EmVIByWt1gxGkWvg==
3589+ dependencies:
3590+ pify "^3.0.0"
3591+
3592+path-type@^4.0.0:
3593+ version "4.0.0"
3594+ resolved "https://registry.yarnpkg.com/path-type/-/path-type-4.0.0.tgz#84ed01c0a7ba380afe09d90a8c180dcd9d03043b"
3595+ integrity sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==
3596+
3597+performance-now@^2.1.0:
3598+ version "2.1.0"
3599+ resolved "https://registry.yarnpkg.com/performance-now/-/performance-now-2.1.0.tgz#6309f4e0e5fa913ec1c69307ae364b4b377c9e7b"
3600+ integrity sha1-Ywn04OX6kT7BxpMHrjZLSzd8nns=
3601+
3602+picomatch@^2.2.3:
3603+ version "2.3.0"
3604+ resolved "https://registry.yarnpkg.com/picomatch/-/picomatch-2.3.0.tgz#f1f061de8f6a4bf022892e2d128234fb98302972"
3605+ integrity sha512-lY1Q/PiJGC2zOv/z391WOTD+Z02bCgsFfvxoXXf6h7kv9o+WmsmzYqrAwY63sNgOxE4xEdq0WyUnXfKeBrSvYw==
3606+
3607+pify@^2.0.0, pify@^2.3.0:
3608+ version "2.3.0"
3609+ resolved "https://registry.yarnpkg.com/pify/-/pify-2.3.0.tgz#ed141a6ac043a849ea588498e7dca8b15330e90c"
3610+ integrity sha1-7RQaasBDqEnqWISY59yosVMw6Qw=
3611+
3612+pify@^3.0.0:
3613+ version "3.0.0"
3614+ resolved "https://registry.yarnpkg.com/pify/-/pify-3.0.0.tgz#e5a4acd2c101fdf3d9a4d07f0dbc4db49dd28176"
3615+ integrity sha1-5aSs0sEB/fPZpNB/DbxNtJ3SgXY=
3616+
3617+pinkie-promise@^2.0.0:
3618+ version "2.0.1"
3619+ resolved "https://registry.yarnpkg.com/pinkie-promise/-/pinkie-promise-2.0.1.tgz#2135d6dfa7a358c069ac9b178776288228450ffa"
3620+ integrity sha1-ITXW36ejWMBprJsXh3YogihFD/o=
3621+ dependencies:
3622+ pinkie "^2.0.0"
3623+
3624+pinkie@^2.0.0:
3625+ version "2.0.4"
3626+ resolved "https://registry.yarnpkg.com/pinkie/-/pinkie-2.0.4.tgz#72556b80cfa0d48a974e80e77248e80ed4f7f870"
3627+ integrity sha1-clVrgM+g1IqXToDnckjoDtT3+HA=
3628+
3629+plugin-error@1.0.1, plugin-error@^1.0.1:
3630+ version "1.0.1"
3631+ resolved "https://registry.yarnpkg.com/plugin-error/-/plugin-error-1.0.1.tgz#77016bd8919d0ac377fdcdd0322328953ca5781c"
3632+ integrity sha512-L1zP0dk7vGweZME2i+EeakvUNqSrdiI3F91TwEoYiGrAfUXmVv6fJIq4g82PAXxNsWOp0J7ZqQy/3Szz0ajTxA==
3633+ dependencies:
3634+ ansi-colors "^1.0.1"
3635+ arr-diff "^4.0.0"
3636+ arr-union "^3.1.0"
3637+ extend-shallow "^3.0.2"
3638+
3639+plugin-error@^0.1.2:
3640+ version "0.1.2"
3641+ resolved "https://registry.yarnpkg.com/plugin-error/-/plugin-error-0.1.2.tgz#3b9bb3335ccf00f425e07437e19276967da47ace"
3642+ integrity sha1-O5uzM1zPAPQl4HQ34ZJ2ln2kes4=
3643+ dependencies:
3644+ ansi-cyan "^0.1.1"
3645+ ansi-red "^0.1.1"
3646+ arr-diff "^1.0.1"
3647+ arr-union "^2.0.1"
3648+ extend-shallow "^1.1.2"
3649+
3650+pluralize@^1.2.1:
3651+ version "1.2.1"
3652+ resolved "https://registry.yarnpkg.com/pluralize/-/pluralize-1.2.1.tgz#d1a21483fd22bb41e58a12fa3421823140897c45"
3653+ integrity sha1-0aIUg/0iu0HlihL6NCGCMUCJfEU=
3654+
3655+posix-character-classes@^0.1.0:
3656+ version "0.1.1"
3657+ resolved "https://registry.yarnpkg.com/posix-character-classes/-/posix-character-classes-0.1.1.tgz#01eac0fe3b5af71a2a6c02feabb8c1fef7e00eab"
3658+ integrity sha1-AerA/jta9xoqbAL+q7jB/vfgDqs=
3659+
3660+pretty-hrtime@^1.0.0:
3661+ version "1.0.3"
3662+ resolved "https://registry.yarnpkg.com/pretty-hrtime/-/pretty-hrtime-1.0.3.tgz#b7e3ea42435a4c9b2759d99e0f201eb195802ee1"
3663+ integrity sha1-t+PqQkNaTJsnWdmeDyAesZWALuE=
3664+
3665+process-nextick-args@^2.0.0, process-nextick-args@~2.0.0:
3666+ version "2.0.1"
3667+ resolved "https://registry.yarnpkg.com/process-nextick-args/-/process-nextick-args-2.0.1.tgz#7820d9b16120cc55ca9ae7792680ae7dba6d7fe2"
3668+ integrity sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==
3669+
3670+proxy-addr@~2.0.5:
3671+ version "2.0.7"
3672+ resolved "https://registry.yarnpkg.com/proxy-addr/-/proxy-addr-2.0.7.tgz#f19fe69ceab311eeb94b42e70e8c2070f9ba1025"
3673+ integrity sha512-llQsMLSUDUPT44jdrU/O37qlnifitDP+ZwrmmZcoSKyLKvtZxpyV0n2/bD/N4tBAAZ/gJEdZU7KMraoK1+XYAg==
3674+ dependencies:
3675+ forwarded "0.2.0"
3676+ ipaddr.js "1.9.1"
3677+
3678+psl@^1.1.28:
3679+ version "1.8.0"
3680+ resolved "https://registry.yarnpkg.com/psl/-/psl-1.8.0.tgz#9326f8bcfb013adcc005fdff056acce020e51c24"
3681+ integrity sha512-RIdOzyoavK+hA18OGGWDqUTsCLhtA7IcZ/6NCs4fFJaHBDab+pDDmDIByWFRQJq2Cd7r1OoQxBGKOaztq+hjIQ==
3682+
3683+pump@^2.0.0:
3684+ version "2.0.1"
3685+ resolved "https://registry.yarnpkg.com/pump/-/pump-2.0.1.tgz#12399add6e4cf7526d973cbc8b5ce2e2908b3909"
3686+ integrity sha512-ruPMNRkN3MHP1cWJc9OWr+T/xDP0jhXYCLfJcBuX54hhfIBnaQmAUMfDcG4DM5UMWByBbJY69QSphm3jtDKIkA==
3687+ dependencies:
3688+ end-of-stream "^1.1.0"
3689+ once "^1.3.1"
3690+
3691+pumpify@^1.3.5:
3692+ version "1.5.1"
3693+ resolved "https://registry.yarnpkg.com/pumpify/-/pumpify-1.5.1.tgz#36513be246ab27570b1a374a5ce278bfd74370ce"
3694+ integrity sha512-oClZI37HvuUJJxSKKrC17bZ9Cu0ZYhEAGPsPUy9KlMUmv9dKX2o77RUmq7f3XjIxbwyGwYzbzQ1L2Ks8sIradQ==
3695+ dependencies:
3696+ duplexify "^3.6.0"
3697+ inherits "^2.0.3"
3698+ pump "^2.0.0"
3699+
3700+punycode@^2.1.0, punycode@^2.1.1:
3701+ version "2.1.1"
3702+ resolved "https://registry.yarnpkg.com/punycode/-/punycode-2.1.1.tgz#b58b010ac40c22c5657616c8d2c2c02c7bf479ec"
3703+ integrity sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A==
3704+
3705+q@^1.5.1:
3706+ version "1.5.1"
3707+ resolved "https://registry.yarnpkg.com/q/-/q-1.5.1.tgz#7e32f75b41381291d04611f1bf14109ac00651d7"
3708+ integrity sha1-fjL3W0E4EpHQRhHxvxQQmsAGUdc=
3709+
3710+qs@6.7.0:
3711+ version "6.7.0"
3712+ resolved "https://registry.yarnpkg.com/qs/-/qs-6.7.0.tgz#41dc1a015e3d581f1621776be31afb2876a9b1bc"
3713+ integrity sha512-VCdBRNFTX1fyE7Nb6FYoURo/SPe62QCaAyzJvUjwRaIsc+NePBEniHlvxFmmX56+HZphIGtV0XeCirBtpDrTyQ==
3714+
3715+qs@~6.5.2:
3716+ version "6.5.2"
3717+ resolved "https://registry.yarnpkg.com/qs/-/qs-6.5.2.tgz#cb3ae806e8740444584ef154ce8ee98d403f3e36"
3718+ integrity sha512-N5ZAX4/LxJmF+7wN74pUD6qAh9/wnvdQcjq9TZjevvXzSUo7bfmw91saqMjzGS2xq91/odN2dW/WOl7qQHNDGA==
3719+
3720+queue-microtask@^1.2.2:
3721+ version "1.2.3"
3722+ resolved "https://registry.yarnpkg.com/queue-microtask/-/queue-microtask-1.2.3.tgz#4929228bbc724dfac43e0efb058caf7b6cfb6243"
3723+ integrity sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==
3724+
3725+quick-lru@^1.0.0:
3726+ version "1.1.0"
3727+ resolved "https://registry.yarnpkg.com/quick-lru/-/quick-lru-1.1.0.tgz#4360b17c61136ad38078397ff11416e186dcfbb8"
3728+ integrity sha1-Q2CxfGETatOAeDl/8RQW4Ybc+7g=
3729+
3730+quick-lru@^4.0.1:
3731+ version "4.0.1"
3732+ resolved "https://registry.yarnpkg.com/quick-lru/-/quick-lru-4.0.1.tgz#5b8878f113a58217848c6482026c73e1ba57727f"
3733+ integrity sha512-ARhCpm70fzdcvNQfPoy49IaanKkTlRWF2JMzqhcJbhSFRZv7nPTvZJdcY7301IPmvW+/p0RgIWnQDLJxifsQ7g==
3734+
3735+range-parser@~1.2.1:
3736+ version "1.2.1"
3737+ resolved "https://registry.yarnpkg.com/range-parser/-/range-parser-1.2.1.tgz#3cf37023d199e1c24d1a55b84800c2f3e6468031"
3738+ integrity sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg==
3739+
3740+raw-body@2.4.0:
3741+ version "2.4.0"
3742+ resolved "https://registry.yarnpkg.com/raw-body/-/raw-body-2.4.0.tgz#a1ce6fb9c9bc356ca52e89256ab59059e13d0332"
3743+ integrity sha512-4Oz8DUIwdvoa5qMJelxipzi/iJIi40O5cGV1wNYp5hvZP8ZN0T+jiNkL0QepXs+EsQ9XJ8ipEDoiH70ySUJP3Q==
3744+ dependencies:
3745+ bytes "3.1.0"
3746+ http-errors "1.7.2"
3747+ iconv-lite "0.4.24"
3748+ unpipe "1.0.0"
3749+
3750+read-pkg-up@^1.0.1:
3751+ version "1.0.1"
3752+ resolved "https://registry.yarnpkg.com/read-pkg-up/-/read-pkg-up-1.0.1.tgz#9d63c13276c065918d57f002a57f40a1b643fb02"
3753+ integrity sha1-nWPBMnbAZZGNV/ACpX9AobZD+wI=
3754+ dependencies:
3755+ find-up "^1.0.0"
3756+ read-pkg "^1.0.0"
3757+
3758+read-pkg-up@^3.0.0:
3759+ version "3.0.0"
3760+ resolved "https://registry.yarnpkg.com/read-pkg-up/-/read-pkg-up-3.0.0.tgz#3ed496685dba0f8fe118d0691dc51f4a1ff96f07"
3761+ integrity sha1-PtSWaF26D4/hGNBpHcUfSh/5bwc=
3762+ dependencies:
3763+ find-up "^2.0.0"
3764+ read-pkg "^3.0.0"
3765+
3766+read-pkg-up@^7.0.1:
3767+ version "7.0.1"
3768+ resolved "https://registry.yarnpkg.com/read-pkg-up/-/read-pkg-up-7.0.1.tgz#f3a6135758459733ae2b95638056e1854e7ef507"
3769+ integrity sha512-zK0TB7Xd6JpCLmlLmufqykGE+/TlOePD6qKClNW7hHDKFh/J7/7gCWGR7joEQEW1bKq3a3yUZSObOoWLFQ4ohg==
3770+ dependencies:
3771+ find-up "^4.1.0"
3772+ read-pkg "^5.2.0"
3773+ type-fest "^0.8.1"
3774+
3775+read-pkg@^1.0.0:
3776+ version "1.1.0"
3777+ resolved "https://registry.yarnpkg.com/read-pkg/-/read-pkg-1.1.0.tgz#f5ffaa5ecd29cb31c0474bca7d756b6bb29e3f28"
3778+ integrity sha1-9f+qXs0pyzHAR0vKfXVra7KePyg=
3779+ dependencies:
3780+ load-json-file "^1.0.0"
3781+ normalize-package-data "^2.3.2"
3782+ path-type "^1.0.0"
3783+
3784+read-pkg@^3.0.0:
3785+ version "3.0.0"
3786+ resolved "https://registry.yarnpkg.com/read-pkg/-/read-pkg-3.0.0.tgz#9cbc686978fee65d16c00e2b19c237fcf6e38389"
3787+ integrity sha1-nLxoaXj+5l0WwA4rGcI3/Pbjg4k=
3788+ dependencies:
3789+ load-json-file "^4.0.0"
3790+ normalize-package-data "^2.3.2"
3791+ path-type "^3.0.0"
3792+
3793+read-pkg@^5.2.0:
3794+ version "5.2.0"
3795+ resolved "https://registry.yarnpkg.com/read-pkg/-/read-pkg-5.2.0.tgz#7bf295438ca5a33e56cd30e053b34ee7250c93cc"
3796+ integrity sha512-Ug69mNOpfvKDAc2Q8DRpMjjzdtrnv9HcSMX+4VsZxD1aZ6ZzrIE7rlzXBtWTyhULSMKg076AW6WR5iZpD0JiOg==
3797+ dependencies:
3798+ "@types/normalize-package-data" "^2.4.0"
3799+ normalize-package-data "^2.5.0"
3800+ parse-json "^5.0.0"
3801+ type-fest "^0.6.0"
3802+
3803+"readable-stream@2 || 3", readable-stream@3, readable-stream@^3.0.0, readable-stream@^3.0.2, readable-stream@^3.0.6:
3804+ version "3.6.0"
3805+ resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-3.6.0.tgz#337bbda3adc0706bd3e024426a286d4b4b2c9198"
3806+ integrity sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==
3807+ dependencies:
3808+ inherits "^2.0.3"
3809+ string_decoder "^1.1.1"
3810+ util-deprecate "^1.0.1"
3811+
3812+readable-stream@^2.0.0, readable-stream@^2.0.1, readable-stream@^2.0.2, readable-stream@^2.0.5, readable-stream@^2.1.5, readable-stream@^2.2.2, readable-stream@^2.3.3, readable-stream@^2.3.5, readable-stream@^2.3.6, readable-stream@~2.3.6:
3813+ version "2.3.7"
3814+ resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-2.3.7.tgz#1eca1cf711aef814c04f62252a36a62f6cb23b57"
3815+ integrity sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==
3816+ dependencies:
3817+ core-util-is "~1.0.0"
3818+ inherits "~2.0.3"
3819+ isarray "~1.0.0"
3820+ process-nextick-args "~2.0.0"
3821+ safe-buffer "~5.1.1"
3822+ string_decoder "~1.1.1"
3823+ util-deprecate "~1.0.1"
3824+
3825+readdirp@^2.2.1:
3826+ version "2.2.1"
3827+ resolved "https://registry.yarnpkg.com/readdirp/-/readdirp-2.2.1.tgz#0e87622a3325aa33e892285caf8b4e846529a525"
3828+ integrity sha512-1JU/8q+VgFZyxwrJ+SVIOsh+KywWGpds3NTqikiKpDMZWScmAYyKIgqkO+ARvNWJfXeXR1zxz7aHF4u4CyH6vQ==
3829+ dependencies:
3830+ graceful-fs "^4.1.11"
3831+ micromatch "^3.1.10"
3832+ readable-stream "^2.0.2"
3833+
3834+rechoir@^0.6.2:
3835+ version "0.6.2"
3836+ resolved "https://registry.yarnpkg.com/rechoir/-/rechoir-0.6.2.tgz#85204b54dba82d5742e28c96756ef43af50e3384"
3837+ integrity sha1-hSBLVNuoLVdC4oyWdW70OvUOM4Q=
3838+ dependencies:
3839+ resolve "^1.1.6"
3840+
3841+redent@^2.0.0:
3842+ version "2.0.0"
3843+ resolved "https://registry.yarnpkg.com/redent/-/redent-2.0.0.tgz#c1b2007b42d57eb1389079b3c8333639d5e1ccaa"
3844+ integrity sha1-wbIAe0LVfrE4kHmzyDM2OdXhzKo=
3845+ dependencies:
3846+ indent-string "^3.0.0"
3847+ strip-indent "^2.0.0"
3848+
3849+redent@^3.0.0:
3850+ version "3.0.0"
3851+ resolved "https://registry.yarnpkg.com/redent/-/redent-3.0.0.tgz#e557b7998316bb53c9f1f56fa626352c6963059f"
3852+ integrity sha512-6tDA8g98We0zd0GvVeMT9arEOnTw9qM03L9cJXaCjrip1OO764RDBLBfrB4cwzNGDj5OA5ioymC9GkizgWJDUg==
3853+ dependencies:
3854+ indent-string "^4.0.0"
3855+ strip-indent "^3.0.0"
3856+
3857+regenerator-runtime@^0.10.5:
3858+ version "0.10.5"
3859+ resolved "https://registry.yarnpkg.com/regenerator-runtime/-/regenerator-runtime-0.10.5.tgz#336c3efc1220adcedda2c9fab67b5a7955a33658"
3860+ integrity sha1-M2w+/BIgrc7dosn6tntaeVWjNlg=
3861+
3862+regenerator-runtime@^0.11.0:
3863+ version "0.11.1"
3864+ resolved "https://registry.yarnpkg.com/regenerator-runtime/-/regenerator-runtime-0.11.1.tgz#be05ad7f9bf7d22e056f9726cee5017fbf19e2e9"
3865+ integrity sha512-MguG95oij0fC3QV3URf4V2SDYGJhJnJGqvIIgdECeODCT98wSWDAJ94SSuVpYQUoTcGUIL6L4yNB7j1DFFHSBg==
3866+
3867+regex-not@^1.0.0, regex-not@^1.0.2:
3868+ version "1.0.2"
3869+ resolved "https://registry.yarnpkg.com/regex-not/-/regex-not-1.0.2.tgz#1f4ece27e00b0b65e0247a6810e6a85d83a5752c"
3870+ integrity sha512-J6SDjUgDxQj5NusnOtdFxDwN/+HWykR8GELwctJ7mdqhcyy1xEc4SRFHUXvxTp661YaVKAjfRLZ9cCqS6tn32A==
3871+ dependencies:
3872+ extend-shallow "^3.0.2"
3873+ safe-regex "^1.1.0"
3874+
3875+remove-bom-buffer@^3.0.0:
3876+ version "3.0.0"
3877+ resolved "https://registry.yarnpkg.com/remove-bom-buffer/-/remove-bom-buffer-3.0.0.tgz#c2bf1e377520d324f623892e33c10cac2c252b53"
3878+ integrity sha512-8v2rWhaakv18qcvNeli2mZ/TMTL2nEyAKRvzo1WtnZBl15SHyEhrCu2/xKlJyUFKHiHgfXIyuY6g2dObJJycXQ==
3879+ dependencies:
3880+ is-buffer "^1.1.5"
3881+ is-utf8 "^0.2.1"
3882+
3883+remove-bom-stream@^1.2.0:
3884+ version "1.2.0"
3885+ resolved "https://registry.yarnpkg.com/remove-bom-stream/-/remove-bom-stream-1.2.0.tgz#05f1a593f16e42e1fb90ebf59de8e569525f9523"
3886+ integrity sha1-BfGlk/FuQuH7kOv1nejlaVJflSM=
3887+ dependencies:
3888+ remove-bom-buffer "^3.0.0"
3889+ safe-buffer "^5.1.0"
3890+ through2 "^2.0.3"
3891+
3892+remove-trailing-separator@^1.0.1, remove-trailing-separator@^1.1.0:
3893+ version "1.1.0"
3894+ resolved "https://registry.yarnpkg.com/remove-trailing-separator/-/remove-trailing-separator-1.1.0.tgz#c24bce2a283adad5bc3f58e0d48249b92379d8ef"
3895+ integrity sha1-wkvOKig62tW8P1jg1IJJuSN52O8=
3896+
3897+repeat-element@^1.1.2:
3898+ version "1.1.4"
3899+ resolved "https://registry.yarnpkg.com/repeat-element/-/repeat-element-1.1.4.tgz#be681520847ab58c7568ac75fbfad28ed42d39e9"
3900+ integrity sha512-LFiNfRcSu7KK3evMyYOuCzv3L10TW7yC1G2/+StMjK8Y6Vqd2MG7r/Qjw4ghtuCOjFvlnms/iMmLqpvW/ES/WQ==
3901+
3902+repeat-string@^1.6.1:
3903+ version "1.6.1"
3904+ resolved "https://registry.yarnpkg.com/repeat-string/-/repeat-string-1.6.1.tgz#8dcae470e1c88abc2d600fff4a776286da75e637"
3905+ integrity sha1-jcrkcOHIirwtYA//Sndihtp15jc=
3906+
3907+repeating@^2.0.0:
3908+ version "2.0.1"
3909+ resolved "https://registry.yarnpkg.com/repeating/-/repeating-2.0.1.tgz#5214c53a926d3552707527fbab415dbc08d06dda"
3910+ integrity sha1-UhTFOpJtNVJwdSf7q0FdvAjQbdo=
3911+ dependencies:
3912+ is-finite "^1.0.0"
3913+
3914+replace-ext@^1.0.0:
3915+ version "1.0.1"
3916+ resolved "https://registry.yarnpkg.com/replace-ext/-/replace-ext-1.0.1.tgz#2d6d996d04a15855d967443631dd5f77825b016a"
3917+ integrity sha512-yD5BHCe7quCgBph4rMQ+0KkIRKwWCrHDOX1p1Gp6HwjPM5kVoCdKGNhN7ydqqsX6lJEnQDKZ/tFMiEdQ1dvPEw==
3918+
3919+replace-homedir@^1.0.0:
3920+ version "1.0.0"
3921+ resolved "https://registry.yarnpkg.com/replace-homedir/-/replace-homedir-1.0.0.tgz#e87f6d513b928dde808260c12be7fec6ff6e798c"
3922+ integrity sha1-6H9tUTuSjd6AgmDBK+f+xv9ueYw=
3923+ dependencies:
3924+ homedir-polyfill "^1.0.1"
3925+ is-absolute "^1.0.0"
3926+ remove-trailing-separator "^1.1.0"
3927+
3928+request@^2.88.2:
3929+ version "2.88.2"
3930+ resolved "https://registry.yarnpkg.com/request/-/request-2.88.2.tgz#d73c918731cb5a87da047e207234146f664d12b3"
3931+ integrity sha512-MsvtOrfG9ZcrOwAW+Qi+F6HbD0CWXEh9ou77uOb7FM2WPhwT7smM833PzanhJLsgXjN89Ir6V2PczXNnMpwKhw==
3932+ dependencies:
3933+ aws-sign2 "~0.7.0"
3934+ aws4 "^1.8.0"
3935+ caseless "~0.12.0"
3936+ combined-stream "~1.0.6"
3937+ extend "~3.0.2"
3938+ forever-agent "~0.6.1"
3939+ form-data "~2.3.2"
3940+ har-validator "~5.1.3"
3941+ http-signature "~1.2.0"
3942+ is-typedarray "~1.0.0"
3943+ isstream "~0.1.2"
3944+ json-stringify-safe "~5.0.1"
3945+ mime-types "~2.1.19"
3946+ oauth-sign "~0.9.0"
3947+ performance-now "^2.1.0"
3948+ qs "~6.5.2"
3949+ safe-buffer "^5.1.2"
3950+ tough-cookie "~2.5.0"
3951+ tunnel-agent "^0.6.0"
3952+ uuid "^3.3.2"
3953+
3954+require-dir@^1.0.0:
3955+ version "1.2.0"
3956+ resolved "https://registry.yarnpkg.com/require-dir/-/require-dir-1.2.0.tgz#0d443b75e96012d3ca749cf19f529a789ae74817"
3957+ integrity sha512-LY85DTSu+heYgDqq/mK+7zFHWkttVNRXC9NKcKGyuGLdlsfbjEPrIEYdCVrx6hqnJb+xSu3Lzaoo8VnmOhhjNA==
3958+
3959+require-directory@^2.1.1:
3960+ version "2.1.1"
3961+ resolved "https://registry.yarnpkg.com/require-directory/-/require-directory-2.1.1.tgz#8c64ad5fd30dab1c976e2344ffe7f792a6a6df42"
3962+ integrity sha1-jGStX9MNqxyXbiNE/+f3kqam30I=
3963+
3964+require-main-filename@^1.0.1:
3965+ version "1.0.1"
3966+ resolved "https://registry.yarnpkg.com/require-main-filename/-/require-main-filename-1.0.1.tgz#97f717b69d48784f5f526a6c5aa8ffdda055a4d1"
3967+ integrity sha1-l/cXtp1IeE9fUmpsWqj/3aBVpNE=
3968+
3969+resolve-dir@^1.0.0, resolve-dir@^1.0.1:
3970+ version "1.0.1"
3971+ resolved "https://registry.yarnpkg.com/resolve-dir/-/resolve-dir-1.0.1.tgz#79a40644c362be82f26effe739c9bb5382046f43"
3972+ integrity sha1-eaQGRMNivoLybv/nOcm7U4IEb0M=
3973+ dependencies:
3974+ expand-tilde "^2.0.0"
3975+ global-modules "^1.0.0"
3976+
3977+resolve-from@5.0.0, resolve-from@^5.0.0:
3978+ version "5.0.0"
3979+ resolved "https://registry.yarnpkg.com/resolve-from/-/resolve-from-5.0.0.tgz#c35225843df8f776df21c57557bc087e9dfdfc69"
3980+ integrity sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw==
3981+
3982+resolve-from@^3.0.0:
3983+ version "3.0.0"
3984+ resolved "https://registry.yarnpkg.com/resolve-from/-/resolve-from-3.0.0.tgz#b22c7af7d9d6881bc8b6e653335eebcb0a188748"
3985+ integrity sha1-six699nWiBvItuZTM17rywoYh0g=
3986+
3987+resolve-from@^4.0.0:
3988+ version "4.0.0"
3989+ resolved "https://registry.yarnpkg.com/resolve-from/-/resolve-from-4.0.0.tgz#4abcd852ad32dd7baabfe9b40e00a36db5f392e6"
3990+ integrity sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==
3991+
3992+resolve-global@1.0.0, resolve-global@^1.0.0:
3993+ version "1.0.0"
3994+ resolved "https://registry.yarnpkg.com/resolve-global/-/resolve-global-1.0.0.tgz#a2a79df4af2ca3f49bf77ef9ddacd322dad19255"
3995+ integrity sha512-zFa12V4OLtT5XUX/Q4VLvTfBf+Ok0SPc1FNGM/z9ctUdiU618qwKpWnd0CHs3+RqROfyEg/DhuHbMWYqcgljEw==
3996+ dependencies:
3997+ global-dirs "^0.1.1"
3998+
3999+resolve-options@^1.1.0:
4000+ version "1.1.0"
4001+ resolved "https://registry.yarnpkg.com/resolve-options/-/resolve-options-1.1.0.tgz#32bb9e39c06d67338dc9378c0d6d6074566ad131"
4002+ integrity sha1-MrueOcBtZzONyTeMDW1gdFZq0TE=
4003+ dependencies:
4004+ value-or-function "^3.0.0"
4005+
4006+resolve-url@^0.2.1:
4007+ version "0.2.1"
4008+ resolved "https://registry.yarnpkg.com/resolve-url/-/resolve-url-0.2.1.tgz#2c637fe77c893afd2a663fe21aa9080068e2052a"
4009+ integrity sha1-LGN/53yJOv0qZj/iGqkIAGjiBSo=
4010+
4011+resolve@^1.1.6, resolve@^1.1.7, resolve@^1.10.0, resolve@^1.20.0, resolve@^1.3.2, resolve@^1.4.0:
4012+ version "1.20.0"
4013+ resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.20.0.tgz#629a013fb3f70755d6f0b7935cc1c2c5378b1975"
4014+ integrity sha512-wENBPt4ySzg4ybFQW2TT1zMQucPK95HSh/nq2CFTZVOGut2+pQvSsgtda4d26YrYcr067wjbmzOG8byDPBX63A==
4015+ dependencies:
4016+ is-core-module "^2.2.0"
4017+ path-parse "^1.0.6"
4018+
4019+ret@~0.1.10:
4020+ version "0.1.15"
4021+ resolved "https://registry.yarnpkg.com/ret/-/ret-0.1.15.tgz#b8a4825d5bdb1fc3f6f53c2bc33f81388681c7bc"
4022+ integrity sha512-TTlYpa+OL+vMMNG24xSlQGEJ3B/RzEfUlLct7b5G/ytav+wPrplCpVMFuwzXbkecJrb6IYo1iFb0S9v37754mg==
4023+
4024+reusify@^1.0.4:
4025+ version "1.0.4"
4026+ resolved "https://registry.yarnpkg.com/reusify/-/reusify-1.0.4.tgz#90da382b1e126efc02146e90845a88db12925d76"
4027+ integrity sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw==
4028+
4029+rimraf@^2.5.2, rimraf@^2.6.2:
4030+ version "2.7.1"
4031+ resolved "https://registry.yarnpkg.com/rimraf/-/rimraf-2.7.1.tgz#35797f13a7fdadc566142c29d4f07ccad483e3ec"
4032+ integrity sha512-uWjbaKIK3T1OSVptzX7Nl6PvQ3qAGtKEtVRjRuazjfL3Bx5eI409VZSqgND+4UNnmzLVdPj9FqFJNPqBZFve4w==
4033+ dependencies:
4034+ glob "^7.1.3"
4035+
4036+rimraf@^3.0.2:
4037+ version "3.0.2"
4038+ resolved "https://registry.yarnpkg.com/rimraf/-/rimraf-3.0.2.tgz#f1a5402ba6220ad52cc1282bac1ae3aa49fd061a"
4039+ integrity sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==
4040+ dependencies:
4041+ glob "^7.1.3"
4042+
4043+run-parallel@^1.1.9:
4044+ version "1.2.0"
4045+ resolved "https://registry.yarnpkg.com/run-parallel/-/run-parallel-1.2.0.tgz#66d1368da7bdf921eb9d95bd1a9229e7f21a43ee"
4046+ integrity sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==
4047+ dependencies:
4048+ queue-microtask "^1.2.2"
4049+
4050+safe-buffer@5.1.2, safe-buffer@~5.1.0, safe-buffer@~5.1.1:
4051+ version "5.1.2"
4052+ resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.1.2.tgz#991ec69d296e0313747d59bdfd2b745c35f8828d"
4053+ integrity sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==
4054+
4055+safe-buffer@^5.0.1, safe-buffer@^5.1.0, safe-buffer@^5.1.2, safe-buffer@~5.2.0:
4056+ version "5.2.1"
4057+ resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.2.1.tgz#1eaf9fa9bdb1fdd4ec75f58f9cdb4e6b7827eec6"
4058+ integrity sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==
4059+
4060+safe-regex@^1.1.0:
4061+ version "1.1.0"
4062+ resolved "https://registry.yarnpkg.com/safe-regex/-/safe-regex-1.1.0.tgz#40a3669f3b077d1e943d44629e157dd48023bf2e"
4063+ integrity sha1-QKNmnzsHfR6UPURinhV91IAjvy4=
4064+ dependencies:
4065+ ret "~0.1.10"
4066+
4067+"safer-buffer@>= 2.1.2 < 3", safer-buffer@^2.0.2, safer-buffer@^2.1.0, safer-buffer@~2.1.0:
4068+ version "2.1.2"
4069+ resolved "https://registry.yarnpkg.com/safer-buffer/-/safer-buffer-2.1.2.tgz#44fa161b0187b9549dd84bb91802f9bd8385cd6a"
4070+ integrity sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==
4071+
4072+semver-greatest-satisfied-range@^1.1.0:
4073+ version "1.1.0"
4074+ resolved "https://registry.yarnpkg.com/semver-greatest-satisfied-range/-/semver-greatest-satisfied-range-1.1.0.tgz#13e8c2658ab9691cb0cd71093240280d36f77a5b"
4075+ integrity sha1-E+jCZYq5aRywzXEJMkAoDTb3els=
4076+ dependencies:
4077+ sver-compat "^1.5.0"
4078+
4079+"semver@2 || 3 || 4 || 5", semver@^5.3.0:
4080+ version "5.7.1"
4081+ resolved "https://registry.yarnpkg.com/semver/-/semver-5.7.1.tgz#a954f931aeba508d307bbf069eff0c01c96116f7"
4082+ integrity sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==
4083+
4084+semver@6.3.0, semver@^6.0.0:
4085+ version "6.3.0"
4086+ resolved "https://registry.yarnpkg.com/semver/-/semver-6.3.0.tgz#ee0a64c8af5e8ceea67687b133761e1becbd1d3d"
4087+ integrity sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==
4088+
4089+semver@^7.3.4:
4090+ version "7.3.5"
4091+ resolved "https://registry.yarnpkg.com/semver/-/semver-7.3.5.tgz#0b621c879348d8998e4b0e4be94b3f12e6018ef7"
4092+ integrity sha512-PoeGJYh8HK4BTO/a9Tf6ZG3veo/A7ZVsYrSA6J8ny9nb3B1VrpkuN+z9OE5wfE5p6H4LchYZsegiQgbJD94ZFQ==
4093+ dependencies:
4094+ lru-cache "^6.0.0"
4095+
4096+send@0.17.1:
4097+ version "0.17.1"
4098+ resolved "https://registry.yarnpkg.com/send/-/send-0.17.1.tgz#c1d8b059f7900f7466dd4938bdc44e11ddb376c8"
4099+ integrity sha512-BsVKsiGcQMFwT8UxypobUKyv7irCNRHk1T0G680vk88yf6LBByGcZJOTJCrTP2xVN6yI+XjPJcNuE3V4fT9sAg==
4100+ dependencies:
4101+ debug "2.6.9"
4102+ depd "~1.1.2"
4103+ destroy "~1.0.4"
4104+ encodeurl "~1.0.2"
4105+ escape-html "~1.0.3"
4106+ etag "~1.8.1"
4107+ fresh "0.5.2"
4108+ http-errors "~1.7.2"
4109+ mime "1.6.0"
4110+ ms "2.1.1"
4111+ on-finished "~2.3.0"
4112+ range-parser "~1.2.1"
4113+ statuses "~1.5.0"
4114+
4115+serve-static@1.14.1:
4116+ version "1.14.1"
4117+ resolved "https://registry.yarnpkg.com/serve-static/-/serve-static-1.14.1.tgz#666e636dc4f010f7ef29970a88a674320898b2f9"
4118+ integrity sha512-JMrvUwE54emCYWlTI+hGrGv5I8dEwmco/00EvkzIIsR7MqrHonbD9pO2MOfFnpFntl7ecpZs+3mW+XbQZu9QCg==
4119+ dependencies:
4120+ encodeurl "~1.0.2"
4121+ escape-html "~1.0.3"
4122+ parseurl "~1.3.3"
4123+ send "0.17.1"
4124+
4125+set-blocking@^2.0.0:
4126+ version "2.0.0"
4127+ resolved "https://registry.yarnpkg.com/set-blocking/-/set-blocking-2.0.0.tgz#045f9782d011ae9a6803ddd382b24392b3d890f7"
4128+ integrity sha1-BF+XgtARrppoA93TgrJDkrPYkPc=
4129+
4130+set-value@^2.0.0, set-value@^2.0.1:
4131+ version "2.0.1"
4132+ resolved "https://registry.yarnpkg.com/set-value/-/set-value-2.0.1.tgz#a18d40530e6f07de4228c7defe4227af8cad005b"
4133+ integrity sha512-JxHc1weCN68wRY0fhCoXpyK55m/XPHafOmK4UWD7m2CI14GMcFypt4w/0+NV5f/ZMby2F6S2wwA7fgynh9gWSw==
4134+ dependencies:
4135+ extend-shallow "^2.0.1"
4136+ is-extendable "^0.1.1"
4137+ is-plain-object "^2.0.3"
4138+ split-string "^3.0.1"
4139+
4140+setprototypeof@1.1.1:
4141+ version "1.1.1"
4142+ resolved "https://registry.yarnpkg.com/setprototypeof/-/setprototypeof-1.1.1.tgz#7e95acb24aa92f5885e0abef5ba131330d4ae683"
4143+ integrity sha512-JvdAWfbXeIGaZ9cILp38HntZSFSo3mWg6xGcJJsd+d4aRMOqauag1C63dJfDw7OaMYwEbHMOxEZ1lqVRYP2OAw==
4144+
4145+signal-exit@^3.0.0:
4146+ version "3.0.3"
4147+ resolved "https://registry.yarnpkg.com/signal-exit/-/signal-exit-3.0.3.tgz#a1410c2edd8f077b08b4e253c8eacfcaf057461c"
4148+ integrity sha512-VUJ49FC8U1OxwZLxIbTTrDvLnf/6TDgxZcK8wxR8zs13xpx7xbG60ndBlhNrFi2EMuFRoeDoJO7wthSLq42EjA==
4149+
4150+slash@^3.0.0:
4151+ version "3.0.0"
4152+ resolved "https://registry.yarnpkg.com/slash/-/slash-3.0.0.tgz#6539be870c165adbd5240220dbe361f1bc4d4634"
4153+ integrity sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==
4154+
4155+snapdragon-node@^2.0.1:
4156+ version "2.1.1"
4157+ resolved "https://registry.yarnpkg.com/snapdragon-node/-/snapdragon-node-2.1.1.tgz#6c175f86ff14bdb0724563e8f3c1b021a286853b"
4158+ integrity sha512-O27l4xaMYt/RSQ5TR3vpWCAB5Kb/czIcqUFOM/C4fYcLnbZUc1PkjTAMjof2pBWaSTwOUd6qUHcFGVGj7aIwnw==
4159+ dependencies:
4160+ define-property "^1.0.0"
4161+ isobject "^3.0.0"
4162+ snapdragon-util "^3.0.1"
4163+
4164+snapdragon-util@^3.0.1:
4165+ version "3.0.1"
4166+ resolved "https://registry.yarnpkg.com/snapdragon-util/-/snapdragon-util-3.0.1.tgz#f956479486f2acd79700693f6f7b805e45ab56e2"
4167+ integrity sha512-mbKkMdQKsjX4BAL4bRYTj21edOf8cN7XHdYUJEe+Zn99hVEYcMvKPct1IqNe7+AZPirn8BCDOQBHQZknqmKlZQ==
4168+ dependencies:
4169+ kind-of "^3.2.0"
4170+
4171+snapdragon@^0.8.1:
4172+ version "0.8.2"
4173+ resolved "https://registry.yarnpkg.com/snapdragon/-/snapdragon-0.8.2.tgz#64922e7c565b0e14204ba1aa7d6964278d25182d"
4174+ integrity sha512-FtyOnWN/wCHTVXOMwvSv26d+ko5vWlIDD6zoUJ7LW8vh+ZBC8QdljveRP+crNrtBwioEUWy/4dMtbBjA4ioNlg==
4175+ dependencies:
4176+ base "^0.11.1"
4177+ debug "^2.2.0"
4178+ define-property "^0.2.5"
4179+ extend-shallow "^2.0.1"
4180+ map-cache "^0.2.2"
4181+ source-map "^0.5.6"
4182+ source-map-resolve "^0.5.0"
4183+ use "^3.1.0"
4184+
4185+source-map-resolve@^0.5.0:
4186+ version "0.5.3"
4187+ resolved "https://registry.yarnpkg.com/source-map-resolve/-/source-map-resolve-0.5.3.tgz#190866bece7553e1f8f267a2ee82c606b5509a1a"
4188+ integrity sha512-Htz+RnsXWk5+P2slx5Jh3Q66vhQj1Cllm0zvnaY98+NFx+Dv2CF/f5O/t8x+KaNdrdIAsruNzoh/KpialbqAnw==
4189+ dependencies:
4190+ atob "^2.1.2"
4191+ decode-uri-component "^0.2.0"
4192+ resolve-url "^0.2.1"
4193+ source-map-url "^0.4.0"
4194+ urix "^0.1.0"
4195+
4196+source-map-url@^0.4.0:
4197+ version "0.4.1"
4198+ resolved "https://registry.yarnpkg.com/source-map-url/-/source-map-url-0.4.1.tgz#0af66605a745a5a2f91cf1bbf8a7afbc283dec56"
4199+ integrity sha512-cPiFOTLUKvJFIg4SKVScy4ilPPW6rFgMgfuZJPNoDuMs3nC1HbMUycBoJw77xFIp6z1UJQJOfx6C9GMH80DiTw==
4200+
4201+source-map@^0.5.6:
4202+ version "0.5.7"
4203+ resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.5.7.tgz#8a039d2d1021d22d1ea14c80d8ea468ba2ef3fcc"
4204+ integrity sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=
4205+
4206+source-map@^0.6.1:
4207+ version "0.6.1"
4208+ resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.6.1.tgz#74722af32e9614e9c287a8d0bbde48b5e2f1a263"
4209+ integrity sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==
4210+
4211+source-map@^0.7.3:
4212+ version "0.7.3"
4213+ resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.7.3.tgz#5302f8169031735226544092e64981f751750383"
4214+ integrity sha512-CkCj6giN3S+n9qrYiBTX5gystlENnRW5jZeNLHpe6aue+SrHcG5VYwujhW9s4dY31mEGsxBDrHR6oI69fTXsaQ==
4215+
4216+sparkles@^1.0.0:
4217+ version "1.0.1"
4218+ resolved "https://registry.yarnpkg.com/sparkles/-/sparkles-1.0.1.tgz#008db65edce6c50eec0c5e228e1945061dd0437c"
4219+ integrity sha512-dSO0DDYUahUt/0/pD/Is3VIm5TGJjludZ0HVymmhYF6eNA53PVLhnUk0znSYbH8IYBuJdCE+1luR22jNLMaQdw==
4220+
4221+spdx-correct@^3.0.0:
4222+ version "3.1.1"
4223+ resolved "https://registry.yarnpkg.com/spdx-correct/-/spdx-correct-3.1.1.tgz#dece81ac9c1e6713e5f7d1b6f17d468fa53d89a9"
4224+ integrity sha512-cOYcUWwhCuHCXi49RhFRCyJEK3iPj1Ziz9DpViV3tbZOwXD49QzIN3MpOLJNxh2qwq2lJJZaKMVw9qNi4jTC0w==
4225+ dependencies:
4226+ spdx-expression-parse "^3.0.0"
4227+ spdx-license-ids "^3.0.0"
4228+
4229+spdx-exceptions@^2.1.0:
4230+ version "2.3.0"
4231+ resolved "https://registry.yarnpkg.com/spdx-exceptions/-/spdx-exceptions-2.3.0.tgz#3f28ce1a77a00372683eade4a433183527a2163d"
4232+ integrity sha512-/tTrYOC7PPI1nUAgx34hUpqXuyJG+DTHJTnIULG4rDygi4xu/tfgmq1e1cIRwRzwZgo4NLySi+ricLkZkw4i5A==
4233+
4234+spdx-expression-parse@^3.0.0:
4235+ version "3.0.1"
4236+ resolved "https://registry.yarnpkg.com/spdx-expression-parse/-/spdx-expression-parse-3.0.1.tgz#cf70f50482eefdc98e3ce0a6833e4a53ceeba679"
4237+ integrity sha512-cbqHunsQWnJNE6KhVSMsMeH5H/L9EpymbzqTQ3uLwNCLZ1Q481oWaofqH7nO6V07xlXwY6PhQdQ2IedWx/ZK4Q==
4238+ dependencies:
4239+ spdx-exceptions "^2.1.0"
4240+ spdx-license-ids "^3.0.0"
4241+
4242+spdx-license-ids@^3.0.0:
4243+ version "3.0.9"
4244+ resolved "https://registry.yarnpkg.com/spdx-license-ids/-/spdx-license-ids-3.0.9.tgz#8a595135def9592bda69709474f1cbeea7c2467f"
4245+ integrity sha512-Ki212dKK4ogX+xDo4CtOZBVIwhsKBEfsEEcwmJfLQzirgc2jIWdzg40Unxz/HzEUqM1WFzVlQSMF9kZZ2HboLQ==
4246+
4247+split-string@^3.0.1, split-string@^3.0.2:
4248+ version "3.1.0"
4249+ resolved "https://registry.yarnpkg.com/split-string/-/split-string-3.1.0.tgz#7cb09dda3a86585705c64b39a6466038682e8fe2"
4250+ integrity sha512-NzNVhJDYpwceVVii8/Hu6DKfD2G+NrQHlS/V/qgv763EYudVwEcMQNxd2lh+0VrUByXN/oJkl5grOhYWvQUYiw==
4251+ dependencies:
4252+ extend-shallow "^3.0.0"
4253+
4254+split2@^3.0.0:
4255+ version "3.2.2"
4256+ resolved "https://registry.yarnpkg.com/split2/-/split2-3.2.2.tgz#bf2cf2a37d838312c249c89206fd7a17dd12365f"
4257+ integrity sha512-9NThjpgZnifTkJpzTZ7Eue85S49QwpNhZTq6GRJwObb6jnLFNGB7Qm73V5HewTROPyxD0C29xqmaI68bQtV+hg==
4258+ dependencies:
4259+ readable-stream "^3.0.0"
4260+
4261+split@^1.0.0:
4262+ version "1.0.1"
4263+ resolved "https://registry.yarnpkg.com/split/-/split-1.0.1.tgz#605bd9be303aa59fb35f9229fbea0ddec9ea07d9"
4264+ integrity sha512-mTyOoPbrivtXnwnIxZRFYRrPNtEFKlpB2fvjSnCQUiAA6qAZzqwna5envK4uk6OIeP17CsdF3rSBGYVBsU0Tkg==
4265+ dependencies:
4266+ through "2"
4267+
4268+sprintf-js@~1.0.2:
4269+ version "1.0.3"
4270+ resolved "https://registry.yarnpkg.com/sprintf-js/-/sprintf-js-1.0.3.tgz#04e6926f662895354f3dd015203633b857297e2c"
4271+ integrity sha1-BOaSb2YolTVPPdAVIDYzuFcpfiw=
4272+
4273+sshpk@^1.7.0:
4274+ version "1.16.1"
4275+ resolved "https://registry.yarnpkg.com/sshpk/-/sshpk-1.16.1.tgz#fb661c0bef29b39db40769ee39fa70093d6f6877"
4276+ integrity sha512-HXXqVUq7+pcKeLqqZj6mHFUMvXtOJt1uoUx09pFW6011inTMxqI8BA8PM95myrIyyKwdnzjdFjLiE6KBPVtJIg==
4277+ dependencies:
4278+ asn1 "~0.2.3"
4279+ assert-plus "^1.0.0"
4280+ bcrypt-pbkdf "^1.0.0"
4281+ dashdash "^1.12.0"
4282+ ecc-jsbn "~0.1.1"
4283+ getpass "^0.1.1"
4284+ jsbn "~0.1.0"
4285+ safer-buffer "^2.0.2"
4286+ tweetnacl "~0.14.0"
4287+
4288+stack-trace@0.0.10:
4289+ version "0.0.10"
4290+ resolved "https://registry.yarnpkg.com/stack-trace/-/stack-trace-0.0.10.tgz#547c70b347e8d32b4e108ea1a2a159e5fdde19c0"
4291+ integrity sha1-VHxws0fo0ytOEI6hoqFZ5f3eGcA=
4292+
4293+static-extend@^0.1.1:
4294+ version "0.1.2"
4295+ resolved "https://registry.yarnpkg.com/static-extend/-/static-extend-0.1.2.tgz#60809c39cbff55337226fd5e0b520f341f1fb5c6"
4296+ integrity sha1-YICcOcv/VTNyJv1eC1IPNB8ftcY=
4297+ dependencies:
4298+ define-property "^0.2.5"
4299+ object-copy "^0.1.0"
4300+
4301+"statuses@>= 1.5.0 < 2", statuses@~1.5.0:
4302+ version "1.5.0"
4303+ resolved "https://registry.yarnpkg.com/statuses/-/statuses-1.5.0.tgz#161c7dac177659fd9811f43771fa99381478628c"
4304+ integrity sha1-Fhx9rBd2Wf2YEfQ3cfqZOBR4Yow=
4305+
4306+stream-exhaust@^1.0.1:
4307+ version "1.0.2"
4308+ resolved "https://registry.yarnpkg.com/stream-exhaust/-/stream-exhaust-1.0.2.tgz#acdac8da59ef2bc1e17a2c0ccf6c320d120e555d"
4309+ integrity sha512-b/qaq/GlBK5xaq1yrK9/zFcyRSTNxmcZwFLGSTG0mXgZl/4Z6GgiyYOXOvY7N3eEvFRAG1bkDRz5EPGSvPYQlw==
4310+
4311+stream-shift@^1.0.0:
4312+ version "1.0.1"
4313+ resolved "https://registry.yarnpkg.com/stream-shift/-/stream-shift-1.0.1.tgz#d7088281559ab2778424279b0877da3c392d5a3d"
4314+ integrity sha512-AiisoFqQ0vbGcZgQPY1cdP2I76glaVA/RauYR4G4thNFgkTqr90yXTo4LYX60Jl+sIlPNHHdGSwo01AvbKUSVQ==
4315+
4316+streamfilter@^3.0.0:
4317+ version "3.0.0"
4318+ resolved "https://registry.yarnpkg.com/streamfilter/-/streamfilter-3.0.0.tgz#8c61b08179a6c336c6efccc5df30861b7a9675e7"
4319+ integrity sha512-kvKNfXCmUyC8lAXSSHCIXBUlo/lhsLcCU/OmzACZYpRUdtKIH68xYhm/+HI15jFJYtNJGYtCgn2wmIiExY1VwA==
4320+ dependencies:
4321+ readable-stream "^3.0.6"
4322+
4323+string-width@^1.0.1, string-width@^1.0.2:
4324+ version "1.0.2"
4325+ resolved "https://registry.yarnpkg.com/string-width/-/string-width-1.0.2.tgz#118bdf5b8cdc51a2a7e70d211e07e2b0b9b107d3"
4326+ integrity sha1-EYvfW4zcUaKn5w0hHgfisLmxB9M=
4327+ dependencies:
4328+ code-point-at "^1.0.0"
4329+ is-fullwidth-code-point "^1.0.0"
4330+ strip-ansi "^3.0.0"
4331+
4332+string_decoder@^1.1.1:
4333+ version "1.3.0"
4334+ resolved "https://registry.yarnpkg.com/string_decoder/-/string_decoder-1.3.0.tgz#42f114594a46cf1a8e30b0a84f56c78c3edac21e"
4335+ integrity sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==
4336+ dependencies:
4337+ safe-buffer "~5.2.0"
4338+
4339+string_decoder@~1.1.1:
4340+ version "1.1.1"
4341+ resolved "https://registry.yarnpkg.com/string_decoder/-/string_decoder-1.1.1.tgz#9cf1611ba62685d7030ae9e4ba34149c3af03fc8"
4342+ integrity sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==
4343+ dependencies:
4344+ safe-buffer "~5.1.0"
4345+
4346+strip-ansi@^3.0.0, strip-ansi@^3.0.1:
4347+ version "3.0.1"
4348+ resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-3.0.1.tgz#6a385fb8853d952d5ff05d0e8aaf94278dc63dcf"
4349+ integrity sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=
4350+ dependencies:
4351+ ansi-regex "^2.0.0"
4352+
4353+strip-bom-buf@^1.0.0:
4354+ version "1.0.0"
4355+ resolved "https://registry.yarnpkg.com/strip-bom-buf/-/strip-bom-buf-1.0.0.tgz#1cb45aaf57530f4caf86c7f75179d2c9a51dd572"
4356+ integrity sha1-HLRar1dTD0yvhsf3UXnSyaUd1XI=
4357+ dependencies:
4358+ is-utf8 "^0.2.1"
4359+
4360+strip-bom-stream@^3.0.0:
4361+ version "3.0.0"
4362+ resolved "https://registry.yarnpkg.com/strip-bom-stream/-/strip-bom-stream-3.0.0.tgz#956bcc5d84430f69256a90ed823765cd858e159c"
4363+ integrity sha1-lWvMXYRDD2klapDtgjdlzYWOFZw=
4364+ dependencies:
4365+ first-chunk-stream "^2.0.0"
4366+ strip-bom-buf "^1.0.0"
4367+
4368+strip-bom@^2.0.0:
4369+ version "2.0.0"
4370+ resolved "https://registry.yarnpkg.com/strip-bom/-/strip-bom-2.0.0.tgz#6219a85616520491f35788bdbf1447a99c7e6b0e"
4371+ integrity sha1-YhmoVhZSBJHzV4i9vxRHqZx+aw4=
4372+ dependencies:
4373+ is-utf8 "^0.2.0"
4374+
4375+strip-bom@^3.0.0:
4376+ version "3.0.0"
4377+ resolved "https://registry.yarnpkg.com/strip-bom/-/strip-bom-3.0.0.tgz#2334c18e9c759f7bdd56fdef7e9ae3d588e68ed3"
4378+ integrity sha1-IzTBjpx1n3vdVv3vfprj1YjmjtM=
4379+
4380+strip-indent@^2.0.0:
4381+ version "2.0.0"
4382+ resolved "https://registry.yarnpkg.com/strip-indent/-/strip-indent-2.0.0.tgz#5ef8db295d01e6ed6cbf7aab96998d7822527b68"
4383+ integrity sha1-XvjbKV0B5u1sv3qrlpmNeCJSe2g=
4384+
4385+strip-indent@^3.0.0:
4386+ version "3.0.0"
4387+ resolved "https://registry.yarnpkg.com/strip-indent/-/strip-indent-3.0.0.tgz#c32e1cee940b6b3432c771bc2c54bcce73cd3001"
4388+ integrity sha512-laJTa3Jb+VQpaC6DseHhF7dXVqHTfJPCRDaEbid/drOhgitgYku/letMUqOXFoWV0zIIUbjpdH2t+tYj4bQMRQ==
4389+ dependencies:
4390+ min-indent "^1.0.0"
4391+
4392+supports-color@^5.3.0:
4393+ version "5.5.0"
4394+ resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-5.5.0.tgz#e2e69a44ac8772f78a1ec0b35b689df6530efc8f"
4395+ integrity sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==
4396+ dependencies:
4397+ has-flag "^3.0.0"
4398+
4399+sver-compat@^1.5.0:
4400+ version "1.5.0"
4401+ resolved "https://registry.yarnpkg.com/sver-compat/-/sver-compat-1.5.0.tgz#3cf87dfeb4d07b4a3f14827bc186b3fd0c645cd8"
4402+ integrity sha1-PPh9/rTQe0o/FIJ7wYaz/QxkXNg=
4403+ dependencies:
4404+ es6-iterator "^2.0.1"
4405+ es6-symbol "^3.1.1"
4406+
4407+swagger-parser@^10.0.2:
4408+ version "10.0.2"
4409+ resolved "https://registry.yarnpkg.com/swagger-parser/-/swagger-parser-10.0.2.tgz#d7f18faa09c9c145e938977c9bd6c3435998b667"
4410+ integrity sha512-9jHkHM+QXyLGFLk1DkXBwV+4HyNm0Za3b8/zk/+mjr8jgOSiqm3FOTHBSDsBjtn9scdL+8eWcHdupp2NLM8tDw==
4411+ dependencies:
4412+ "@apidevtools/swagger-parser" "10.0.2"
4413+
4414+text-extensions@^1.0.0:
4415+ version "1.9.0"
4416+ resolved "https://registry.yarnpkg.com/text-extensions/-/text-extensions-1.9.0.tgz#1853e45fee39c945ce6f6c36b2d659b5aabc2a26"
4417+ integrity sha512-wiBrwC1EhBelW12Zy26JeOUkQ5mRu+5o8rpsJk5+2t+Y5vE7e842qtZDQ2g1NpX/29HdyFeJ4nSIhI47ENSxlQ==
4418+
4419+through2-filter@^3.0.0:
4420+ version "3.0.0"
4421+ resolved "https://registry.yarnpkg.com/through2-filter/-/through2-filter-3.0.0.tgz#700e786df2367c2c88cd8aa5be4cf9c1e7831254"
4422+ integrity sha512-jaRjI2WxN3W1V8/FMZ9HKIBXixtiqs3SQSX4/YGIiP3gL6djW48VoZq9tDqeCWs3MT8YY5wb/zli8VW8snY1CA==
4423+ dependencies:
4424+ through2 "~2.0.0"
4425+ xtend "~4.0.0"
4426+
4427+through2@^2.0.0, through2@^2.0.3, through2@~2.0.0:
4428+ version "2.0.5"
4429+ resolved "https://registry.yarnpkg.com/through2/-/through2-2.0.5.tgz#01c1e39eb31d07cb7d03a96a70823260b23132cd"
4430+ integrity sha512-/mrRod8xqpA+IHSLyGCQ2s8SPHiCDEeQJSep1jqLYeEUClOFG2Qsh+4FU6G9VeqpZnGW/Su8LQGc4YKni5rYSQ==
4431+ dependencies:
4432+ readable-stream "~2.3.6"
4433+ xtend "~4.0.1"
4434+
4435+through2@^3.0.0:
4436+ version "3.0.2"
4437+ resolved "https://registry.yarnpkg.com/through2/-/through2-3.0.2.tgz#99f88931cfc761ec7678b41d5d7336b5b6a07bf4"
4438+ integrity sha512-enaDQ4MUyP2W6ZyT6EsMzqBPZaM/avg8iuo+l2d3QCs0J+6RaqkHV/2/lOwDTueBHeJ/2LG9lrLW3d5rWPucuQ==
4439+ dependencies:
4440+ inherits "^2.0.4"
4441+ readable-stream "2 || 3"
4442+
4443+through2@^4.0.0:
4444+ version "4.0.2"
4445+ resolved "https://registry.yarnpkg.com/through2/-/through2-4.0.2.tgz#a7ce3ac2a7a8b0b966c80e7c49f0484c3b239764"
4446+ integrity sha512-iOqSav00cVxEEICeD7TjLB1sueEL+81Wpzp2bY17uZjZN0pWZPuo4suZ/61VujxmqSGFfgOcNuTZ85QJwNZQpw==
4447+ dependencies:
4448+ readable-stream "3"
4449+
4450+through@2, "through@>=2.2.7 <3", through@~2.3.8:
4451+ version "2.3.8"
4452+ resolved "https://registry.yarnpkg.com/through/-/through-2.3.8.tgz#0dd4c9ffaabc357960b1b724115d7e0e86a2e1f5"
4453+ integrity sha1-DdTJ/6q8NXlgsbckEV1+Doai4fU=
4454+
4455+time-stamp@^1.0.0:
4456+ version "1.1.0"
4457+ resolved "https://registry.yarnpkg.com/time-stamp/-/time-stamp-1.1.0.tgz#764a5a11af50561921b133f3b44e618687e0f5c3"
4458+ integrity sha1-dkpaEa9QVhkhsTPztE5hhofg9cM=
4459+
4460+to-absolute-glob@^2.0.0:
4461+ version "2.0.2"
4462+ resolved "https://registry.yarnpkg.com/to-absolute-glob/-/to-absolute-glob-2.0.2.tgz#1865f43d9e74b0822db9f145b78cff7d0f7c849b"
4463+ integrity sha1-GGX0PZ50sIItufFFt4z/fQ98hJs=
4464+ dependencies:
4465+ is-absolute "^1.0.0"
4466+ is-negated-glob "^1.0.0"
4467+
4468+to-object-path@^0.3.0:
4469+ version "0.3.0"
4470+ resolved "https://registry.yarnpkg.com/to-object-path/-/to-object-path-0.3.0.tgz#297588b7b0e7e0ac08e04e672f85c1f4999e17af"
4471+ integrity sha1-KXWIt7Dn4KwI4E5nL4XB9JmeF68=
4472+ dependencies:
4473+ kind-of "^3.0.2"
4474+
4475+to-regex-range@^2.1.0:
4476+ version "2.1.1"
4477+ resolved "https://registry.yarnpkg.com/to-regex-range/-/to-regex-range-2.1.1.tgz#7c80c17b9dfebe599e27367e0d4dd5590141db38"
4478+ integrity sha1-fIDBe53+vlmeJzZ+DU3VWQFB2zg=
4479+ dependencies:
4480+ is-number "^3.0.0"
4481+ repeat-string "^1.6.1"
4482+
4483+to-regex-range@^5.0.1:
4484+ version "5.0.1"
4485+ resolved "https://registry.yarnpkg.com/to-regex-range/-/to-regex-range-5.0.1.tgz#1648c44aae7c8d988a326018ed72f5b4dd0392e4"
4486+ integrity sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==
4487+ dependencies:
4488+ is-number "^7.0.0"
4489+
4490+to-regex@^3.0.1, to-regex@^3.0.2:
4491+ version "3.0.2"
4492+ resolved "https://registry.yarnpkg.com/to-regex/-/to-regex-3.0.2.tgz#13cfdd9b336552f30b51f33a8ae1b42a7a7599ce"
4493+ integrity sha512-FWtleNAtZ/Ki2qtqej2CXTOayOH9bHDQF+Q48VpWyDXjbYxA4Yz8iDB31zXOBUlOHHKidDbqGVrTUvQMPmBGBw==
4494+ dependencies:
4495+ define-property "^2.0.2"
4496+ extend-shallow "^3.0.2"
4497+ regex-not "^1.0.2"
4498+ safe-regex "^1.1.0"
4499+
4500+to-through@^2.0.0:
4501+ version "2.0.0"
4502+ resolved "https://registry.yarnpkg.com/to-through/-/to-through-2.0.0.tgz#fc92adaba072647bc0b67d6b03664aa195093af6"
4503+ integrity sha1-/JKtq6ByZHvAtn1rA2ZKoZUJOvY=
4504+ dependencies:
4505+ through2 "^2.0.3"
4506+
4507+toidentifier@1.0.0:
4508+ version "1.0.0"
4509+ resolved "https://registry.yarnpkg.com/toidentifier/-/toidentifier-1.0.0.tgz#7e1be3470f1e77948bc43d94a3c8f4d7752ba553"
4510+ integrity sha512-yaOH/Pk/VEhBWWTlhI+qXxDFXlejDGcQipMlyxda9nthulaxLZUNcUqFxokp0vcYnvteJln5FNQDRrxj3YcbVw==
4511+
4512+tough-cookie@~2.5.0:
4513+ version "2.5.0"
4514+ resolved "https://registry.yarnpkg.com/tough-cookie/-/tough-cookie-2.5.0.tgz#cd9fb2a0aa1d5a12b473bd9fb96fa3dcff65ade2"
4515+ integrity sha512-nlLsUzgm1kfLXSXfRZMc1KLAugd4hqJHDTvc2hDIwS3mZAfMEuMbc03SujMF+GEcpaX/qboeycw6iO8JwVv2+g==
4516+ dependencies:
4517+ psl "^1.1.28"
4518+ punycode "^2.1.1"
4519+
4520+trim-newlines@^2.0.0:
4521+ version "2.0.0"
4522+ resolved "https://registry.yarnpkg.com/trim-newlines/-/trim-newlines-2.0.0.tgz#b403d0b91be50c331dfc4b82eeceb22c3de16d20"
4523+ integrity sha1-tAPQuRvlDDMd/EuC7s6yLD3hbSA=
4524+
4525+trim-newlines@^3.0.0:
4526+ version "3.0.1"
4527+ resolved "https://registry.yarnpkg.com/trim-newlines/-/trim-newlines-3.0.1.tgz#260a5d962d8b752425b32f3a7db0dcacd176c144"
4528+ integrity sha512-c1PTsA3tYrIsLGkJkzHF+w9F2EyxfXGo4UyJc4pFL++FMjnq0HJS69T3M7d//gKrFKwy429bouPescbjecU+Zw==
4529+
4530+trim-off-newlines@^1.0.0:
4531+ version "1.0.1"
4532+ resolved "https://registry.yarnpkg.com/trim-off-newlines/-/trim-off-newlines-1.0.1.tgz#9f9ba9d9efa8764c387698bcbfeb2c848f11adb3"
4533+ integrity sha1-n5up2e+odkw4dpi8v+sshI8RrbM=
4534+
4535+tslib@^1.13.0, tslib@^1.8.1:
4536+ version "1.14.1"
4537+ resolved "https://registry.yarnpkg.com/tslib/-/tslib-1.14.1.tgz#cf2d38bdc34a134bcaf1091c41f6619e2f672d00"
4538+ integrity sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==
4539+
4540+tslint@6.1.3:
4541+ version "6.1.3"
4542+ resolved "https://registry.yarnpkg.com/tslint/-/tslint-6.1.3.tgz#5c23b2eccc32487d5523bd3a470e9aa31789d904"
4543+ integrity sha512-IbR4nkT96EQOvKE2PW/djGz8iGNeJ4rF2mBfiYaR/nvUWYKJhLwimoJKgjIFEIDibBtOevj7BqCRL4oHeWWUCg==
4544+ dependencies:
4545+ "@babel/code-frame" "^7.0.0"
4546+ builtin-modules "^1.1.1"
4547+ chalk "^2.3.0"
4548+ commander "^2.12.1"
4549+ diff "^4.0.1"
4550+ glob "^7.1.1"
4551+ js-yaml "^3.13.1"
4552+ minimatch "^3.0.4"
4553+ mkdirp "^0.5.3"
4554+ resolve "^1.3.2"
4555+ semver "^5.3.0"
4556+ tslib "^1.13.0"
4557+ tsutils "^2.29.0"
4558+
4559+tsutils@^2.29.0:
4560+ version "2.29.0"
4561+ resolved "https://registry.yarnpkg.com/tsutils/-/tsutils-2.29.0.tgz#32b488501467acbedd4b85498673a0812aca0b99"
4562+ integrity sha512-g5JVHCIJwzfISaXpXE1qvNalca5Jwob6FjI4AoPlqMusJ6ftFE7IkkFoMhVLRgK+4Kx3gkzb8UZK5t5yTTvEmA==
4563+ dependencies:
4564+ tslib "^1.8.1"
4565+
4566+tunnel-agent@^0.6.0:
4567+ version "0.6.0"
4568+ resolved "https://registry.yarnpkg.com/tunnel-agent/-/tunnel-agent-0.6.0.tgz#27a5dea06b36b04a0a9966774b290868f0fc40fd"
4569+ integrity sha1-J6XeoGs2sEoKmWZ3SykIaPD8QP0=
4570+ dependencies:
4571+ safe-buffer "^5.0.1"
4572+
4573+tweetnacl@^0.14.3, tweetnacl@~0.14.0:
4574+ version "0.14.5"
4575+ resolved "https://registry.yarnpkg.com/tweetnacl/-/tweetnacl-0.14.5.tgz#5ae68177f192d4456269d108afa93ff8743f4f64"
4576+ integrity sha1-WuaBd/GS1EViadEIr6k/+HQ/T2Q=
4577+
4578+type-fest@^0.13.1:
4579+ version "0.13.1"
4580+ resolved "https://registry.yarnpkg.com/type-fest/-/type-fest-0.13.1.tgz#0172cb5bce80b0bd542ea348db50c7e21834d934"
4581+ integrity sha512-34R7HTnG0XIJcBSn5XhDd7nNFPRcXYRZrBB2O2jdKqYODldSzBAqzsWoZYYvduky73toYS/ESqxPvkDf/F0XMg==
4582+
4583+type-fest@^0.18.0:
4584+ version "0.18.1"
4585+ resolved "https://registry.yarnpkg.com/type-fest/-/type-fest-0.18.1.tgz#db4bc151a4a2cf4eebf9add5db75508db6cc841f"
4586+ integrity sha512-OIAYXk8+ISY+qTOwkHtKqzAuxchoMiD9Udx+FSGQDuiRR+PJKJHc2NJAXlbhkGwTt/4/nKZxELY1w3ReWOL8mw==
4587+
4588+type-fest@^0.6.0:
4589+ version "0.6.0"
4590+ resolved "https://registry.yarnpkg.com/type-fest/-/type-fest-0.6.0.tgz#8d2a2370d3df886eb5c90ada1c5bf6188acf838b"
4591+ integrity sha512-q+MB8nYR1KDLrgr4G5yemftpMC7/QLqVndBmEEdqzmNj5dcFOO4Oo8qlwZE3ULT3+Zim1F8Kq4cBnikNhlCMlg==
4592+
4593+type-fest@^0.8.1:
4594+ version "0.8.1"
4595+ resolved "https://registry.yarnpkg.com/type-fest/-/type-fest-0.8.1.tgz#09e249ebde851d3b1e48d27c105444667f17b83d"
4596+ integrity sha512-4dbzIzqvjtgiM5rw1k5rEHtBANKmdudhGyBEajN01fEyhaAIhsoKNy6y7+IN93IfpFtwY9iqi7kD+xwKhQsNJA==
4597+
4598+type-is@~1.6.17, type-is@~1.6.18:
4599+ version "1.6.18"
4600+ resolved "https://registry.yarnpkg.com/type-is/-/type-is-1.6.18.tgz#4e552cd05df09467dcbc4ef739de89f2cf37c131"
4601+ integrity sha512-TkRKr9sUTxEH8MdfuCSP7VizJyzRNMjj2J2do2Jr3Kym598JVdEksuzPQCnlFPW4ky9Q+iA+ma9BGm06XQBy8g==
4602+ dependencies:
4603+ media-typer "0.3.0"
4604+ mime-types "~2.1.24"
4605+
4606+type@^1.0.1:
4607+ version "1.2.0"
4608+ resolved "https://registry.yarnpkg.com/type/-/type-1.2.0.tgz#848dd7698dafa3e54a6c479e759c4bc3f18847a0"
4609+ integrity sha512-+5nt5AAniqsCnu2cEQQdpzCAh33kVx8n0VoFidKpB1dVVLAN/F+bgVOqOJqOnEnrhp222clB5p3vUlD+1QAnfg==
4610+
4611+type@^2.0.0:
4612+ version "2.5.0"
4613+ resolved "https://registry.yarnpkg.com/type/-/type-2.5.0.tgz#0a2e78c2e77907b252abe5f298c1b01c63f0db3d"
4614+ integrity sha512-180WMDQaIMm3+7hGXWf12GtdniDEy7nYcyFMKJn/eZz/6tSLXrUN9V0wKSbMjej0I1WHWbpREDEKHtqPQa9NNw==
4615+
4616+typedarray@^0.0.6:
4617+ version "0.0.6"
4618+ resolved "https://registry.yarnpkg.com/typedarray/-/typedarray-0.0.6.tgz#867ac74e3864187b1d3d47d996a78ec5c8830777"
4619+ integrity sha1-hnrHTjhkGHsdPUfZlqeOxciDB3c=
4620+
4621+typescript@4.0.3:
4622+ version "4.0.3"
4623+ resolved "https://registry.yarnpkg.com/typescript/-/typescript-4.0.3.tgz#153bbd468ef07725c1df9c77e8b453f8d36abba5"
4624+ integrity sha512-tEu6DGxGgRJPb/mVPIZ48e69xCn2yRmCgYmDugAVwmJ6o+0u1RI18eO7E7WBTLYLaEVVOhwQmcdhQHweux/WPg==
4625+
4626+uglify-js@^3.1.4:
4627+ version "3.13.10"
4628+ resolved "https://registry.yarnpkg.com/uglify-js/-/uglify-js-3.13.10.tgz#a6bd0d28d38f592c3adb6b180ea6e07e1e540a8d"
4629+ integrity sha512-57H3ACYFXeo1IaZ1w02sfA71wI60MGco/IQFjOqK+WtKoprh7Go2/yvd2HPtoJILO2Or84ncLccI4xoHMTSbGg==
4630+
4631+unc-path-regex@^0.1.2:
4632+ version "0.1.2"
4633+ resolved "https://registry.yarnpkg.com/unc-path-regex/-/unc-path-regex-0.1.2.tgz#e73dd3d7b0d7c5ed86fbac6b0ae7d8c6a69d50fa"
4634+ integrity sha1-5z3T17DXxe2G+6xrCufYxqadUPo=
4635+
4636+undertaker-registry@^1.0.0:
4637+ version "1.0.1"
4638+ resolved "https://registry.yarnpkg.com/undertaker-registry/-/undertaker-registry-1.0.1.tgz#5e4bda308e4a8a2ae584f9b9a4359a499825cc50"
4639+ integrity sha1-XkvaMI5KiirlhPm5pDWaSZglzFA=
4640+
4641+undertaker@^1.2.1:
4642+ version "1.3.0"
4643+ resolved "https://registry.yarnpkg.com/undertaker/-/undertaker-1.3.0.tgz#363a6e541f27954d5791d6fa3c1d321666f86d18"
4644+ integrity sha512-/RXwi5m/Mu3H6IHQGww3GNt1PNXlbeCuclF2QYR14L/2CHPz3DFZkvB5hZ0N/QUkiXWCACML2jXViIQEQc2MLg==
4645+ dependencies:
4646+ arr-flatten "^1.0.1"
4647+ arr-map "^2.0.0"
4648+ bach "^1.0.0"
4649+ collection-map "^1.0.0"
4650+ es6-weak-map "^2.0.1"
4651+ fast-levenshtein "^1.0.0"
4652+ last-run "^1.1.0"
4653+ object.defaults "^1.0.0"
4654+ object.reduce "^1.0.0"
4655+ undertaker-registry "^1.0.0"
4656+
4657+union-value@^1.0.0:
4658+ version "1.0.1"
4659+ resolved "https://registry.yarnpkg.com/union-value/-/union-value-1.0.1.tgz#0b6fe7b835aecda61c6ea4d4f02c14221e109847"
4660+ integrity sha512-tJfXmxMeWYnczCVs7XAEvIV7ieppALdyepWMkHkwciRpZraG/xwT+s2JN8+pr1+8jCRf80FFzvr+MpQeeoF4Xg==
4661+ dependencies:
4662+ arr-union "^3.1.0"
4663+ get-value "^2.0.6"
4664+ is-extendable "^0.1.1"
4665+ set-value "^2.0.1"
4666+
4667+unique-stream@^2.0.2:
4668+ version "2.3.1"
4669+ resolved "https://registry.yarnpkg.com/unique-stream/-/unique-stream-2.3.1.tgz#c65d110e9a4adf9a6c5948b28053d9a8d04cbeac"
4670+ integrity sha512-2nY4TnBE70yoxHkDli7DMazpWiP7xMdCYqU2nBRO0UB+ZpEkGsSija7MvmvnZFUeC+mrgiUfcHSr3LmRFIg4+A==
4671+ dependencies:
4672+ json-stable-stringify-without-jsonify "^1.0.1"
4673+ through2-filter "^3.0.0"
4674+
4675+unpipe@1.0.0, unpipe@~1.0.0:
4676+ version "1.0.0"
4677+ resolved "https://registry.yarnpkg.com/unpipe/-/unpipe-1.0.0.tgz#b2bf4ee8514aae6165b4817829d21b2ef49904ec"
4678+ integrity sha1-sr9O6FFKrmFltIF4KdIbLvSZBOw=
4679+
4680+unset-value@^1.0.0:
4681+ version "1.0.0"
4682+ resolved "https://registry.yarnpkg.com/unset-value/-/unset-value-1.0.0.tgz#8376873f7d2335179ffb1e6fc3a8ed0dfc8ab559"
4683+ integrity sha1-g3aHP30jNRef+x5vw6jtDfyKtVk=
4684+ dependencies:
4685+ has-value "^0.3.1"
4686+ isobject "^3.0.0"
4687+
4688+upath@^1.1.1:
4689+ version "1.2.0"
4690+ resolved "https://registry.yarnpkg.com/upath/-/upath-1.2.0.tgz#8f66dbcd55a883acdae4408af8b035a5044c1894"
4691+ integrity sha512-aZwGpamFO61g3OlfT7OQCHqhGnW43ieH9WZeP7QxN/G/jS4jfqUkZxoryvJgVPEcrl5NL/ggHsSmLMHuH64Lhg==
4692+
4693+uri-js@^4.2.2:
4694+ version "4.4.1"
4695+ resolved "https://registry.yarnpkg.com/uri-js/-/uri-js-4.4.1.tgz#9b1a52595225859e55f669d928f88c6c57f2a77e"
4696+ integrity sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==
4697+ dependencies:
4698+ punycode "^2.1.0"
4699+
4700+urix@^0.1.0:
4701+ version "0.1.0"
4702+ resolved "https://registry.yarnpkg.com/urix/-/urix-0.1.0.tgz#da937f7a62e21fec1fd18d49b35c2935067a6c72"
4703+ integrity sha1-2pN/emLiH+wf0Y1Js1wpNQZ6bHI=
4704+
4705+use@^3.1.0:
4706+ version "3.1.1"
4707+ resolved "https://registry.yarnpkg.com/use/-/use-3.1.1.tgz#d50c8cac79a19fbc20f2911f56eb973f4e10070f"
4708+ integrity sha512-cwESVXlO3url9YWlFW/TA9cshCEhtu7IKJ/p5soJ/gGpj7vbvFrAY/eIioQ6Dw23KjZhYgiIo8HOs1nQ2vr/oQ==
4709+
4710+util-deprecate@^1.0.1, util-deprecate@~1.0.1:
4711+ version "1.0.2"
4712+ resolved "https://registry.yarnpkg.com/util-deprecate/-/util-deprecate-1.0.2.tgz#450d4dc9fa70de732762fbd2d4a28981419a0ccf"
4713+ integrity sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=
4714+
4715+utils-merge@1.0.1:
4716+ version "1.0.1"
4717+ resolved "https://registry.yarnpkg.com/utils-merge/-/utils-merge-1.0.1.tgz#9f95710f50a267947b2ccc124741c1028427e713"
4718+ integrity sha1-n5VxD1CiZ5R7LMwSR0HBAoQn5xM=
4719+
4720+uuid@^3.3.2:
4721+ version "3.4.0"
4722+ resolved "https://registry.yarnpkg.com/uuid/-/uuid-3.4.0.tgz#b23e4358afa8a202fe7a100af1f5f883f02007ee"
4723+ integrity sha512-HjSDRw6gZE5JMggctHBcjVak08+KEVhSIiDzFnT9S9aegmp85S/bReBVTb4QTFaRNptJ9kuYaNhnbNEOkbKb/A==
4724+
4725+v8flags@^3.2.0:
4726+ version "3.2.0"
4727+ resolved "https://registry.yarnpkg.com/v8flags/-/v8flags-3.2.0.tgz#b243e3b4dfd731fa774e7492128109a0fe66d656"
4728+ integrity sha512-mH8etigqMfiGWdeXpaaqGfs6BndypxusHHcv2qSHyZkGEznCd/qAXCWWRzeowtL54147cktFOC4P5y+kl8d8Jg==
4729+ dependencies:
4730+ homedir-polyfill "^1.0.1"
4731+
4732+validate-npm-package-license@^3.0.1:
4733+ version "3.0.4"
4734+ resolved "https://registry.yarnpkg.com/validate-npm-package-license/-/validate-npm-package-license-3.0.4.tgz#fc91f6b9c7ba15c857f4cb2c5defeec39d4f410a"
4735+ integrity sha512-DpKm2Ui/xN7/HQKCtpZxoRWBhZ9Z0kqtygG8XCgNQ8ZlDnxuQmWhj566j8fN4Cu3/JmbhsDo7fcAJq4s9h27Ew==
4736+ dependencies:
4737+ spdx-correct "^3.0.0"
4738+ spdx-expression-parse "^3.0.0"
4739+
4740+validator@^12.0.0:
4741+ version "12.2.0"
4742+ resolved "https://registry.yarnpkg.com/validator/-/validator-12.2.0.tgz#660d47e96267033fd070096c3b1a6f2db4380a0a"
4743+ integrity sha512-jJfE/DW6tIK1Ek8nCfNFqt8Wb3nzMoAbocBF6/Icgg1ZFSBpObdnwVY2jQj6qUqzhx5jc71fpvBWyLGO7Xl+nQ==
4744+
4745+value-or-function@^3.0.0:
4746+ version "3.0.0"
4747+ resolved "https://registry.yarnpkg.com/value-or-function/-/value-or-function-3.0.0.tgz#1c243a50b595c1be54a754bfece8563b9ff8d813"
4748+ integrity sha1-HCQ6ULWVwb5Up1S/7OhWO5/42BM=
4749+
4750+vary@~1.1.2:
4751+ version "1.1.2"
4752+ resolved "https://registry.yarnpkg.com/vary/-/vary-1.1.2.tgz#2299f02c6ded30d4a5961b0b9f74524a18f634fc"
4753+ integrity sha1-IpnwLG3tMNSllhsLn3RSShj2NPw=
4754+
4755+verror@1.10.0, verror@^1.10.0:
4756+ version "1.10.0"
4757+ resolved "https://registry.yarnpkg.com/verror/-/verror-1.10.0.tgz#3a105ca17053af55d6e270c1f8288682e18da400"
4758+ integrity sha1-OhBcoXBTr1XW4nDB+CiGguGNpAA=
4759+ dependencies:
4760+ assert-plus "^1.0.0"
4761+ core-util-is "1.0.2"
4762+ extsprintf "^1.2.0"
4763+
4764+vinyl-fs@^3.0.0, vinyl-fs@^3.0.3:
4765+ version "3.0.3"
4766+ resolved "https://registry.yarnpkg.com/vinyl-fs/-/vinyl-fs-3.0.3.tgz#c85849405f67428feabbbd5c5dbdd64f47d31bc7"
4767+ integrity sha512-vIu34EkyNyJxmP0jscNzWBSygh7VWhqun6RmqVfXePrOwi9lhvRs//dOaGOTRUQr4tx7/zd26Tk5WeSVZitgng==
4768+ dependencies:
4769+ fs-mkdirp-stream "^1.0.0"
4770+ glob-stream "^6.1.0"
4771+ graceful-fs "^4.0.0"
4772+ is-valid-glob "^1.0.0"
4773+ lazystream "^1.0.0"
4774+ lead "^1.0.0"
4775+ object.assign "^4.0.4"
4776+ pumpify "^1.3.5"
4777+ readable-stream "^2.3.3"
4778+ remove-bom-buffer "^3.0.0"
4779+ remove-bom-stream "^1.2.0"
4780+ resolve-options "^1.1.0"
4781+ through2 "^2.0.0"
4782+ to-through "^2.0.0"
4783+ value-or-function "^3.0.0"
4784+ vinyl "^2.0.0"
4785+ vinyl-sourcemap "^1.1.0"
4786+
4787+vinyl-sourcemap@^1.1.0:
4788+ version "1.1.0"
4789+ resolved "https://registry.yarnpkg.com/vinyl-sourcemap/-/vinyl-sourcemap-1.1.0.tgz#92a800593a38703a8cdb11d8b300ad4be63b3e16"
4790+ integrity sha1-kqgAWTo4cDqM2xHYswCtS+Y7PhY=
4791+ dependencies:
4792+ append-buffer "^1.0.2"
4793+ convert-source-map "^1.5.0"
4794+ graceful-fs "^4.1.6"
4795+ normalize-path "^2.1.1"
4796+ now-and-later "^2.0.0"
4797+ remove-bom-buffer "^3.0.0"
4798+ vinyl "^2.0.0"
4799+
4800+vinyl@^2.0.0, vinyl@^2.0.1, vinyl@^2.1.0:
4801+ version "2.2.1"
4802+ resolved "https://registry.yarnpkg.com/vinyl/-/vinyl-2.2.1.tgz#23cfb8bbab5ece3803aa2c0a1eb28af7cbba1974"
4803+ integrity sha512-LII3bXRFBZLlezoG5FfZVcXflZgWP/4dCwKtxd5ky9+LOtM4CS3bIRQsmR1KMnMW07jpE8fqR2lcxPZ+8sJIcw==
4804+ dependencies:
4805+ clone "^2.1.1"
4806+ clone-buffer "^1.0.0"
4807+ clone-stats "^1.0.0"
4808+ cloneable-readable "^1.0.0"
4809+ remove-trailing-separator "^1.0.1"
4810+ replace-ext "^1.0.0"
4811+
4812+which-module@^1.0.0:
4813+ version "1.0.0"
4814+ resolved "https://registry.yarnpkg.com/which-module/-/which-module-1.0.0.tgz#bba63ca861948994ff307736089e3b96026c2a4f"
4815+ integrity sha1-u6Y8qGGUiZT/MHc2CJ47lgJsKk8=
4816+
4817+which@^1.2.14:
4818+ version "1.3.1"
4819+ resolved "https://registry.yarnpkg.com/which/-/which-1.3.1.tgz#a45043d54f5805316da8d62f9f50918d3da70b0a"
4820+ integrity sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ==
4821+ dependencies:
4822+ isexe "^2.0.0"
4823+
4824+wordwrap@^1.0.0:
4825+ version "1.0.0"
4826+ resolved "https://registry.yarnpkg.com/wordwrap/-/wordwrap-1.0.0.tgz#27584810891456a4171c8d0226441ade90cbcaeb"
4827+ integrity sha1-J1hIEIkUVqQXHI0CJkQa3pDLyus=
4828+
4829+wrap-ansi@^2.0.0:
4830+ version "2.1.0"
4831+ resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-2.1.0.tgz#d8fc3d284dd05794fe84973caecdd1cf824fdd85"
4832+ integrity sha1-2Pw9KE3QV5T+hJc8rs3Rz4JP3YU=
4833+ dependencies:
4834+ string-width "^1.0.1"
4835+ strip-ansi "^3.0.1"
4836+
4837+wrappy@1:
4838+ version "1.0.2"
4839+ resolved "https://registry.yarnpkg.com/wrappy/-/wrappy-1.0.2.tgz#b5243d8f3ec1aa35f1364605bc0d1036e30ab69f"
4840+ integrity sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=
4841+
4842+xtend@~4.0.0, xtend@~4.0.1:
4843+ version "4.0.2"
4844+ resolved "https://registry.yarnpkg.com/xtend/-/xtend-4.0.2.tgz#bb72779f5fa465186b1f438f674fa347fdb5db54"
4845+ integrity sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==
4846+
4847+y18n@^3.2.1:
4848+ version "3.2.2"
4849+ resolved "https://registry.yarnpkg.com/y18n/-/y18n-3.2.2.tgz#85c901bd6470ce71fc4bb723ad209b70f7f28696"
4850+ integrity sha512-uGZHXkHnhF0XeeAPgnKfPv1bgKAYyVvmNL1xlKsPYZPaIHxGti2hHqvOCQv71XMsLxu1QjergkqogUnms5D3YQ==
4851+
4852+yallist@^4.0.0:
4853+ version "4.0.0"
4854+ resolved "https://registry.yarnpkg.com/yallist/-/yallist-4.0.0.tgz#9bb92790d9c0effec63be73519e11a35019a3a72"
4855+ integrity sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==
4856+
4857+yaml@^1.10.0:
4858+ version "1.10.2"
4859+ resolved "https://registry.yarnpkg.com/yaml/-/yaml-1.10.2.tgz#2301c5ffbf12b467de8da2333a459e29e7920e4b"
4860+ integrity sha512-r3vXyErRCYJ7wg28yvBY5VSoAF8ZvlcW9/BwUzEtUsjvX/DKs24dIkuwjtuprwJJHsbyUbLApepYTR1BN4uHrg==
4861+
4862+yargs-parser@^10.0.0:
4863+ version "10.1.0"
4864+ resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-10.1.0.tgz#7202265b89f7e9e9f2e5765e0fe735a905edbaa8"
4865+ integrity sha512-VCIyR1wJoEBZUqk5PA+oOBF6ypbwh5aNB3I50guxAL/quggdfs4TtNHQrSazFA3fYZ+tEqfs0zIGlv0c/rgjbQ==
4866+ dependencies:
4867+ camelcase "^4.1.0"
4868+
4869+yargs-parser@^18.1.3:
4870+ version "18.1.3"
4871+ resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-18.1.3.tgz#be68c4975c6b2abf469236b0c870362fab09a7b0"
4872+ integrity sha512-o50j0JeToy/4K6OZcaQmW6lyXXKhq7csREXcDwk2omFPJEwUNOVtJKvmDr9EI1fAJZUyZcRF7kxGBWmRXudrCQ==
4873+ dependencies:
4874+ camelcase "^5.0.0"
4875+ decamelize "^1.2.0"
4876+
4877+yargs-parser@^20.2.3:
4878+ version "20.2.9"
4879+ resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-20.2.9.tgz#2eb7dc3b0289718fc295f362753845c41a0c94ee"
4880+ integrity sha512-y11nGElTIV+CT3Zv9t7VKl+Q3hTQoT9a1Qzezhhl6Rp21gJ/IVTW7Z3y9EWXhuUBC2Shnf+DX0antecpAwSP8w==
4881+
4882+yargs-parser@^5.0.1:
4883+ version "5.0.1"
4884+ resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-5.0.1.tgz#7ede329c1d8cdbbe209bd25cdb990e9b1ebbb394"
4885+ integrity sha512-wpav5XYiddjXxirPoCTUPbqM0PXvJ9hiBMvuJgInvo4/lAOTZzUprArw17q2O1P2+GHhbBr18/iQwjL5Z9BqfA==
4886+ dependencies:
4887+ camelcase "^3.0.0"
4888+ object.assign "^4.1.0"
4889+
4890+yargs@^7.1.0:
4891+ version "7.1.2"
4892+ resolved "https://registry.yarnpkg.com/yargs/-/yargs-7.1.2.tgz#63a0a5d42143879fdbb30370741374e0641d55db"
4893+ integrity sha512-ZEjj/dQYQy0Zx0lgLMLR8QuaqTihnxirir7EwUHp1Axq4e3+k8jXU5K0VLbNvedv1f4EWtBonDIZm0NUr+jCcA==
4894+ dependencies:
4895+ camelcase "^3.0.0"
4896+ cliui "^3.2.0"
4897+ decamelize "^1.1.1"
4898+ get-caller-file "^1.0.1"
4899+ os-locale "^1.4.0"
4900+ read-pkg-up "^1.0.1"
4901+ require-directory "^2.1.1"
4902+ require-main-filename "^1.0.1"
4903+ set-blocking "^2.0.0"
4904+ string-width "^1.0.2"
4905+ which-module "^1.0.0"
4906+ y18n "^3.2.1"
4907+ yargs-parser "^5.0.1"
4908+
4909+z-schema@^4.2.3:
4910+ version "4.2.3"
4911+ resolved "https://registry.yarnpkg.com/z-schema/-/z-schema-4.2.3.tgz#85f7eea7e6d4fe59a483462a98f511bd78fe9882"
4912+ integrity sha512-zkvK/9TC6p38IwcrbnT3ul9in1UX4cm1y/VZSs4GHKIiDCrlafc+YQBgQBUdDXLAoZHf2qvQ7gJJOo6yT1LH6A==
4913+ dependencies:
4914+ lodash.get "^4.4.2"
4915+ lodash.isequal "^4.5.0"
4916+ validator "^12.0.0"
4917+ optionalDependencies:
4918+ commander "^2.7.1"
benchmarks/default.nixnew file+181
@@ -0,0 +1,181 @@
1+{ sources ? import ./nix/sources.nix
2+, gomod2nix ? sources.gomod2nix
3+, haskellNix ? (import ../. {}).haskellNix
4+, pkgs ? import haskellNix.sources.nixpkgs-2105 (haskellNix.nixpkgsArgs // {
5+ overlays = haskellNix.nixpkgsArgs.overlays ++ [
6+ (self: super: {
7+ buildGoApplication = super.callPackage (gomod2nix + "/builder") { };
8+ })
9+ ];
10+ })
11+, compaRESThsPkgs ? (import ../. {}).hsPkgs
12+, npmNix ? import (sources.npmNix + "/npmPackages") { inherit pkgs; }
13+, mavenix ? import (sources.mavenix) { inherit pkgs; }
14+, bumpToken ? null
15+, bumpDocumentation ? null
16+}:
17+let
18+ typeable-comparest = compaRESThsPkgs.comparest.components.exes.comparest;
19+ typeable-comparest-exe = typeable-comparest + "/bin/comparest";
20+ typeable-comparest-differ = pkgs.writeScript "typeable-comparest-differ" ''
21+ #!${pkgs.stdenv.shell}
22+ set +e
23+ ${typeable-comparest-exe} -c $1 -s $2 -o $3/typeable.md
24+ exit 0
25+ '';
26+
27+ atlassian-openapi-diff = pkgs.mkYarnPackage {
28+ name = "openapi-diff";
29+ src = sources.atlassian-openapi-diff;
30+ yarnLock = ./atlassian/yarn.lock;
31+ patches = [ ./atlassian/addDist.patch ];
32+ postBuild = "yarn run gulp compileDist";
33+ };
34+ atlassian-openapi-diff-exe = atlassian-openapi-diff + "/bin/openapi-diff";
35+ atlassian-openapi-diff-differ = pkgs.writeScript "atlassian-openapi-diff-differ" ''
36+ #!${pkgs.stdenv.shell}
37+ set +e
38+ ${atlassian-openapi-diff-exe} $1 $2 >$3/atlassian.json 2>$3/atlassian.error.txt
39+ if [ ! -s $3/atlassian.error.txt ]; then
40+ rm $3/atlassian.error.txt
41+ fi
42+ exit 0
43+ '';
44+
45+ openapitools-openapi-diff = mavenix.buildMaven {
46+ maven = pkgs.maven;
47+ src = sources.openapitools-openapi-diff;
48+ doCheck = false;
49+ infoFile = ./openapitools/mavenix.lock;
50+ MAVEN_OPTS = "-Dgithook.plugin.skip=true";
51+ };
52+ openapitools-openapi-diff-exe =
53+ pkgs.runCommand "openapitools-openapi-diff"
54+ { buildInputs = [ pkgs.makeWrapper ]; }
55+ ''makeWrapper ${pkgs.jdk}/bin/java $out --add-flags "-jar ${openapitools-openapi-diff}/share/java/openapi-diff-cli-2.0.0-SNAPSHOT-all.jar"'';
56+ openapitools-openapi-diff-differ = pkgs.writeScript "openapitools-openapi-diff-differ" ''
57+ #!${pkgs.stdenv.shell}
58+ set +e
59+ ${openapitools-openapi-diff-exe} $1 $2 --off --markdown $3/openapitools.md 2>$3/openapitools.error.txt
60+ if [ ! -s $3/openapitools.error.txt ]; then
61+ rm $3/openapitools.error.txt
62+ fi
63+ exit 0
64+ '';
65+
66+ oasdiff = pkgs.pkgs.buildGoApplication {
67+ pname = "oasdiff";
68+ version = "0.1";
69+ src = sources.oasdiff;
70+ modules = ./oasdiff/gomod2nix.toml;
71+ };
72+ oasdiff-differ = pkgs.writeScript "oasdiff-differ" ''
73+ #!${pkgs.stdenv.shell}
74+ set +e
75+ ${oasdiff}/bin/oasdiff -base $1 -revision $2 -format text >$3/oasdiff.txt 2>$3/oasdiff.error.txt
76+ if [ ! -s $3/oasdiff.error.txt ]; then
77+ rm $3/oasdiff.error.txt
78+ fi
79+ exit 0
80+ '';
81+
82+ bump-differ = { bumpToken, bumpDocumentation }: pkgs.writeScript "bump-differ" ''
83+ #!${pkgs.stdenv.shell}
84+
85+ ${pkgs.httpie}/bin/https --ignore-stdin POST bump.sh/api/v1/versions definition=@$1 documentation=${bumpDocumentation} -a ${bumpToken}: >/dev/null
86+ id=$(${pkgs.httpie}/bin/https --ignore-stdin POST bump.sh/api/v1/versions definition=@$2 documentation=${bumpDocumentation} -a ${bumpToken}: | ${pkgs.jq}/bin/jq -r .id)
87+
88+ if [ -z "$id" ]
89+ then
90+ echo "Not changed" > $3/bump.txt
91+ else
92+ state=""
93+
94+ while [ "$state" != "deployed" ]
95+ do
96+ state=$(${pkgs.httpie}/bin/https --ignore-stdin GET bump.sh/api/v1/versions/$id -a ${bumpToken}: | ${pkgs.jq}/bin/jq -r .state)
97+ done
98+
99+ ${pkgs.httpie}/bin/https --ignore-stdin GET bump.sh/api/v1/versions/$id -a ${bumpToken}: | ${pkgs.jq}/bin/jq -r .diff_summary > $3/bump.txt
100+ fi
101+ '';
102+
103+ getInputs = with pkgs;
104+ dir: lib.flatten (lib.mapAttrsToList
105+ (name: type:
106+ if type == "directory" then
107+ let
108+ path = dir + "/${name}";
109+ contents = builtins.readDir path;
110+ in
111+ if contents."a.yaml" or null == "regular" && contents."b.yaml" or null == "regular"
112+ then path
113+ else getInputs path
114+ else [ ]
115+ )
116+ (builtins.readDir dir)
117+ );
118+
119+ runBenchmark = root: pkgs.runCommand "openapi-diff-benchmarks"
120+ {
121+ dirs = map
122+ (path: builtins.toJSON {
123+ relativePath = pkgs.lib.removePrefix (builtins.toString root) (builtins.toString path);
124+ a = path + "/a.yaml";
125+ b = path + "/b.yaml";
126+ })
127+ (getInputs root);
128+ differs = [
129+ typeable-comparest-differ
130+ atlassian-openapi-diff-differ
131+ openapitools-openapi-diff-differ
132+ oasdiff-differ
133+ ] ++ (
134+ if bumpToken == null || bumpDocumentation == null
135+ then builtins.trace "Warning: bumpToken or bumpDocumentation not provided. Skipping bump.sh benchmarks." [ ]
136+ else [ (bump-differ { inherit bumpToken bumpDocumentation; }) ]
137+ );
138+ }
139+ ''
140+ echo "Running compatibility checks:"
141+ for dir in $dirs
142+ do
143+ a=$(echo $dir | ${pkgs.jq}/bin/jq -r .a)
144+ b=$(echo $dir | ${pkgs.jq}/bin/jq -r .b)
145+ relativePath=$(echo $dir | ${pkgs.jq}/bin/jq -r .relativePath)
146+ echo "''\t$relativePath"
147+ output=$out$relativePath
148+ mkdir -p $output
149+ for differ in $differs
150+ do
151+ $differ $a $b $output
152+ done
153+ cp $a $output/a.yaml
154+ cp $b $output/b.yaml
155+ done
156+ '';
157+
158+ benchmarkReportTemplate = root:
159+ let
160+ tools = [
161+ "Typeable"
162+ "Atlassian"
163+ "OpenAPI Tools"
164+ "oasdiff"
165+ "Bump.sh"
166+ ];
167+ foo = with pkgs.lib.strings;
168+ concatMapStrings (x: "| " + x) ([ "" ] ++ tools) + "| \n" + concatMapStrings (_: "|---") ([ "" ] ++ tools) + "| \n" +
169+ concatMapStrings
170+ (path:
171+ let
172+ relativePath = pkgs.lib.removePrefix (builtins.toString root + "/") (builtins.toString path);
173+
174+ in
175+ "[${relativePath}](./${relativePath})${concatMapStrings (_: " | โœ…โŒ") tools} \n")
176+ (getInputs root);
177+ in
178+ foo;
179+
180+in
181+runBenchmark ../test/golden/common
benchmarks/nix/sources.jsonnew file+92
@@ -0,0 +1,92 @@
1+{
2+ "atlassian-openapi-diff": {
3+ "branch": "master",
4+ "repo": "https://bitbucket.org/atlassian/openapi-diff.git",
5+ "rev": "68a0ebce1ec07f21b8e51a008321208c58eab1d6",
6+ "type": "git"
7+ },
8+ "gomod2nix": {
9+ "branch": "master",
10+ "description": "Convert applications using Go modules to Nix expressions",
11+ "homepage": null,
12+ "owner": "tweag",
13+ "repo": "gomod2nix",
14+ "rev": "c78d7b9f15a24eba95fbc228509f513c83709d8b",
15+ "sha256": "15qjp1g2pkkpr5b1mfjfiwl8kyfabi66hklk7apk7jh9sb2qqf85",
16+ "type": "tarball",
17+ "url": "https://github.com/tweag/gomod2nix/archive/c78d7b9f15a24eba95fbc228509f513c83709d8b.tar.gz",
18+ "url_template": "https://github.com/<owner>/<repo>/archive/<rev>.tar.gz"
19+ },
20+ "haskellNix": {
21+ "branch": "master",
22+ "description": "Alternative Haskell Infrastructure for Nixpkgs",
23+ "homepage": "https://input-output-hk.github.io/haskell.nix",
24+ "owner": "input-output-hk",
25+ "repo": "haskell.nix",
26+ "rev": "062a0317b6f1ec231864df49cb9c0fcc838e9c8a",
27+ "sha256": "0s5f8hnwqmz9anz175a53vay20f0185m92vyiga6yrslsar3vpin",
28+ "type": "tarball",
29+ "url": "https://github.com/input-output-hk/haskell.nix/archive/062a0317b6f1ec231864df49cb9c0fcc838e9c8a.tar.gz",
30+ "url_template": "https://github.com/<owner>/<repo>/archive/<rev>.tar.gz"
31+ },
32+ "mavenix": {
33+ "branch": "master",
34+ "description": "Deterministic Maven builds using Nix [maintainer=@icetan]",
35+ "homepage": "",
36+ "owner": "nix-community",
37+ "repo": "mavenix",
38+ "rev": "7416dbd2861520d44a4d6ecee9d94f89737412dc",
39+ "sha256": "0gkn29q63y2l700vravfl8nqjvd0zx7nvfcb3vj64fal3prh1l7y",
40+ "type": "tarball",
41+ "url": "https://github.com/nix-community/mavenix/archive/7416dbd2861520d44a4d6ecee9d94f89737412dc.tar.gz",
42+ "url_template": "https://github.com/<owner>/<repo>/archive/<rev>.tar.gz"
43+ },
44+ "niv": {
45+ "branch": "master",
46+ "description": "Easy dependency management for Nix projects",
47+ "homepage": "https://github.com/nmattia/niv",
48+ "owner": "nmattia",
49+ "repo": "niv",
50+ "rev": "e0ca65c81a2d7a4d82a189f1e23a48d59ad42070",
51+ "sha256": "1pq9nh1d8nn3xvbdny8fafzw87mj7gsmp6pxkdl65w2g18rmcmzx",
52+ "type": "tarball",
53+ "url": "https://github.com/nmattia/niv/archive/e0ca65c81a2d7a4d82a189f1e23a48d59ad42070.tar.gz",
54+ "url_template": "https://github.com/<owner>/<repo>/archive/<rev>.tar.gz"
55+ },
56+ "npmNix": {
57+ "branch": "master",
58+ "description": "Organize JavaScript packages with the Nix package manager.",
59+ "homepage": "https://medium.com/commitlog/the-internet-is-at-the-mercy-of-a-handful-of-people-73fac4bc5068",
60+ "owner": "ip1981",
61+ "repo": "npm.nix",
62+ "rev": "dd31fae2cfe7d4ed21fc9a9f226a81f382b86022",
63+ "sha256": "1a0aqawv6hslxn756yzb3f8ajf4gcms8b1abw2dwm0ck81jq2snc",
64+ "type": "tarball",
65+ "url": "https://github.com/ip1981/npm.nix/archive/dd31fae2cfe7d4ed21fc9a9f226a81f382b86022.tar.gz",
66+ "url_template": "https://github.com/<owner>/<repo>/archive/<rev>.tar.gz"
67+ },
68+ "oasdiff": {
69+ "branch": "main",
70+ "description": "A diff tool for OpenAPI Specification 3",
71+ "homepage": "",
72+ "owner": "tufin",
73+ "repo": "oasdiff",
74+ "rev": "8630d1b6eda369db321d0f7e153002c9bb7515b8",
75+ "sha256": "1p8lskhckgnwdy7vq28qvvls6j9flwliky8qwfhpzmsf43cxkjg6",
76+ "type": "tarball",
77+ "url": "https://github.com/tufin/oasdiff/archive/8630d1b6eda369db321d0f7e153002c9bb7515b8.tar.gz",
78+ "url_template": "https://github.com/<owner>/<repo>/archive/<rev>.tar.gz"
79+ },
80+ "openapitools-openapi-diff": {
81+ "branch": "master",
82+ "description": "Utility for comparing two OpenAPI specifications.",
83+ "homepage": null,
84+ "owner": "OpenAPITools",
85+ "repo": "openapi-diff",
86+ "rev": "1ae6fb0baa56cd7b61b50904f2c664cd86d64547",
87+ "sha256": "1aigv0hgzxfz3i3d0qxn7jp1hgkrlmhwcilpzza2y9j5qdfxkrvs",
88+ "type": "tarball",
89+ "url": "https://github.com/OpenAPITools/openapi-diff/archive/1ae6fb0baa56cd7b61b50904f2c664cd86d64547.tar.gz",
90+ "url_template": "https://github.com/<owner>/<repo>/archive/<rev>.tar.gz"
91+ }
92+}
benchmarks/nix/sources.nixnew file+171
@@ -0,0 +1,171 @@
1+# This file has been generated by Niv.
2+
3+let
4+
5+ #
6+ # The fetchers. fetch_<type> fetches specs of type <type>.
7+ #
8+
9+ fetch_file = pkgs: name: spec:
10+ let
11+ name' = sanitizeName name + "-src";
12+ in
13+ if spec.builtin or true then
14+ builtins_fetchurl { inherit (spec) url sha256; name = name'; }
15+ else
16+ pkgs.fetchurl { inherit (spec) url sha256; name = name'; };
17+
18+ fetch_tarball = pkgs: name: spec:
19+ let
20+ name' = sanitizeName name + "-src";
21+ in
22+ if spec.builtin or true then
23+ builtins_fetchTarball { name = name'; inherit (spec) url sha256; }
24+ else
25+ pkgs.fetchzip { name = name'; inherit (spec) url sha256; };
26+
27+ fetch_git = name: spec:
28+ let
29+ ref =
30+ if spec ? ref then spec.ref else
31+ if spec ? branch then "refs/heads/${spec.branch}" else
32+ if spec ? tag then "refs/tags/${spec.tag}" else
33+ abort "In git source '${name}': Please specify `ref`, `tag` or `branch`!";
34+ in
35+ builtins.fetchGit { url = spec.repo; inherit (spec) rev; inherit ref; };
36+
37+ fetch_local = spec: spec.path;
38+
39+ fetch_builtin-tarball = name: throw
40+ ''[${name}] The niv type "builtin-tarball" is deprecated. You should instead use `builtin = true`.
41+ $ niv modify ${name} -a type=tarball -a builtin=true'';
42+
43+ fetch_builtin-url = name: throw
44+ ''[${name}] The niv type "builtin-url" will soon be deprecated. You should instead use `builtin = true`.
45+ $ niv modify ${name} -a type=file -a builtin=true'';
46+
47+ #
48+ # Various helpers
49+ #
50+
51+ # https://github.com/NixOS/nixpkgs/pull/83241/files#diff-c6f540a4f3bfa4b0e8b6bafd4cd54e8bR695
52+ sanitizeName = name:
53+ (
54+ concatMapStrings (s: if builtins.isList s then "-" else s)
55+ (
56+ builtins.split "[^[:alnum:]+._?=-]+"
57+ ((x: builtins.elemAt (builtins.match "\\.*(.*)" x) 0) name)
58+ )
59+ );
60+
61+ # The set of packages used when specs are fetched using non-builtins.
62+ mkPkgs = sources: system:
63+ let
64+ sourcesNixpkgs =
65+ import (builtins_fetchTarball { inherit (sources.nixpkgs) url sha256; }) { inherit system; };
66+ hasNixpkgsPath = builtins.any (x: x.prefix == "nixpkgs") builtins.nixPath;
67+ hasThisAsNixpkgsPath = <nixpkgs> == ./.;
68+ in
69+ if builtins.hasAttr "nixpkgs" sources
70+ then sourcesNixpkgs
71+ else if hasNixpkgsPath && ! hasThisAsNixpkgsPath then
72+ import <nixpkgs> {}
73+ else
74+ abort
75+ ''
76+ Please specify either <nixpkgs> (through -I or NIX_PATH=nixpkgs=...) or
77+ add a package called "nixpkgs" to your sources.json.
78+ '';
79+
80+ # The actual fetching function.
81+ fetch = pkgs: name: spec:
82+
83+ if ! builtins.hasAttr "type" spec then
84+ abort "ERROR: niv spec ${name} does not have a 'type' attribute"
85+ else if spec.type == "file" then fetch_file pkgs name spec
86+ else if spec.type == "tarball" then fetch_tarball pkgs name spec
87+ else if spec.type == "git" then fetch_git name spec
88+ else if spec.type == "local" then fetch_local spec
89+ else if spec.type == "builtin-tarball" then fetch_builtin-tarball name
90+ else if spec.type == "builtin-url" then fetch_builtin-url name
91+ else
92+ abort "ERROR: niv spec ${name} has unknown type ${builtins.toJSON spec.type}";
93+
94+ # If the environment variable NIV_OVERRIDE_${name} is set, then use
95+ # the path directly as opposed to the fetched source.
96+ replace = name: drv:
97+ let
98+ saneName = stringAsChars (c: if isNull (builtins.match "[a-zA-Z0-9]" c) then "_" else c) name;
99+ ersatz = builtins.getEnv "NIV_OVERRIDE_${saneName}";
100+ in
101+ if ersatz == "" then drv else ersatz;
102+
103+ # Ports of functions for older nix versions
104+
105+ # a Nix version of mapAttrs if the built-in doesn't exist
106+ mapAttrs = builtins.mapAttrs or (
107+ f: set: with builtins;
108+ listToAttrs (map (attr: { name = attr; value = f attr set.${attr}; }) (attrNames set))
109+ );
110+
111+ # https://github.com/NixOS/nixpkgs/blob/0258808f5744ca980b9a1f24fe0b1e6f0fecee9c/lib/lists.nix#L295
112+ range = first: last: if first > last then [] else builtins.genList (n: first + n) (last - first + 1);
113+
114+ # https://github.com/NixOS/nixpkgs/blob/0258808f5744ca980b9a1f24fe0b1e6f0fecee9c/lib/strings.nix#L257
115+ stringToCharacters = s: map (p: builtins.substring p 1 s) (range 0 (builtins.stringLength s - 1));
116+
117+ # https://github.com/NixOS/nixpkgs/blob/0258808f5744ca980b9a1f24fe0b1e6f0fecee9c/lib/strings.nix#L269
118+ stringAsChars = f: s: concatStrings (map f (stringToCharacters s));
119+ concatMapStrings = f: list: concatStrings (map f list);
120+ concatStrings = builtins.concatStringsSep "";
121+
122+ # https://github.com/NixOS/nixpkgs/blob/8a9f58a375c401b96da862d969f66429def1d118/lib/attrsets.nix#L331
123+ optionalAttrs = cond: as: if cond then as else {};
124+
125+ # fetchTarball version that is compatible between all the versions of Nix
126+ builtins_fetchTarball = { url, name ? null, sha256 }@attrs:
127+ let
128+ inherit (builtins) lessThan nixVersion fetchTarball;
129+ in
130+ if lessThan nixVersion "1.12" then
131+ fetchTarball ({ inherit url; } // (optionalAttrs (!isNull name) { inherit name; }))
132+ else
133+ fetchTarball attrs;
134+
135+ # fetchurl version that is compatible between all the versions of Nix
136+ builtins_fetchurl = { url, name ? null, sha256 }@attrs:
137+ let
138+ inherit (builtins) lessThan nixVersion fetchurl;
139+ in
140+ if lessThan nixVersion "1.12" then
141+ fetchurl ({ inherit url; } // (optionalAttrs (!isNull name) { inherit name; }))
142+ else
143+ fetchurl attrs;
144+
145+ # Create the final "sources" from the config
146+ mkSources = config:
147+ mapAttrs (
148+ name: spec:
149+ if builtins.hasAttr "outPath" spec
150+ then abort
151+ "The values in sources.json should not have an 'outPath' attribute"
152+ else
153+ spec // { outPath = replace name (fetch config.pkgs name spec); }
154+ ) config.sources;
155+
156+ # The "config" used by the fetchers
157+ mkConfig =
158+ { sourcesFile ? if builtins.pathExists ./sources.json then ./sources.json else null
159+ , sources ? if isNull sourcesFile then {} else builtins.fromJSON (builtins.readFile sourcesFile)
160+ , system ? builtins.currentSystem
161+ , pkgs ? mkPkgs sources system
162+ }: rec {
163+ # The sources, i.e. the attribute set of spec name to spec
164+ inherit sources;
165+
166+ # The "pkgs" (evaluated nixpkgs) to use for e.g. non-builtin fetchers
167+ inherit pkgs;
168+ };
169+
170+in
171+mkSources (mkConfig {}) // { __functor = _: settings: mkSources (mkConfig settings); }
benchmarks/oasdiff/gomod2nix.tomlnew file+135
@@ -0,0 +1,135 @@
1+["github.com/davecgh/go-spew"]
2+ sumVersion = "v1.1.1"
3+ ["github.com/davecgh/go-spew".fetch]
4+ type = "git"
5+ url = "https://github.com/davecgh/go-spew"
6+ rev = "8991bc29aa16c548c550c7ff78260e27b9ab7c73"
7+ sha256 = "0hka6hmyvp701adzag2g26cxdj47g21x6jz4sc6jjz1mn59d474y"
8+
9+["github.com/getkin/kin-openapi"]
10+ sumVersion = "v0.66.0"
11+ ["github.com/getkin/kin-openapi".fetch]
12+ type = "git"
13+ url = "https://github.com/getkin/kin-openapi"
14+ rev = "6b4444becdebac4ea5658cbe205bac8c27a7ec41"
15+ sha256 = "08njvg2v14k2p3l1fwrmgg21k0fkli2ajac4893j5zky7a72sbiq"
16+
17+["github.com/ghodss/yaml"]
18+ sumVersion = "v1.0.0"
19+ ["github.com/ghodss/yaml".fetch]
20+ type = "git"
21+ url = "https://github.com/ghodss/yaml"
22+ rev = "0ca9ea5df5451ffdf184b4428c902747c2c11cd7"
23+ sha256 = "0skwmimpy7hlh7pva2slpcplnm912rp3igs98xnqmn859kwa5v8g"
24+
25+["github.com/go-openapi/jsonpointer"]
26+ sumVersion = "v0.19.5"
27+ ["github.com/go-openapi/jsonpointer".fetch]
28+ type = "git"
29+ url = "https://github.com/go-openapi/jsonpointer"
30+ rev = "2446e21cad36eee826e1c2380f0ff747074a2faa"
31+ sha256 = "0azic9nfwywlz4qxvacyi4g668fbbrkcyv15bag02yfcsi8szg5c"
32+
33+["github.com/go-openapi/swag"]
34+ sumVersion = "v0.19.5"
35+ ["github.com/go-openapi/swag".fetch]
36+ type = "git"
37+ url = "https://github.com/go-openapi/swag"
38+ rev = "c3d0f7896d589f3babb99eea24bbc7de98108e72"
39+ sha256 = "1z34vqc5yz6rzvarrvlhkimxx33p74iaxb28l1mv716njvlsmjhg"
40+
41+["github.com/gorilla/mux"]
42+ sumVersion = "v1.8.0"
43+ ["github.com/gorilla/mux".fetch]
44+ type = "git"
45+ url = "https://github.com/gorilla/mux"
46+ rev = "98cb6bf42e086f6af920b965c38cacc07402d51b"
47+ sha256 = "18f0q9qxgq1yh4ji07mqhiydfcwvi56z9d775v7dc7yckj33kpdk"
48+
49+["github.com/kr/pretty"]
50+ sumVersion = "v0.1.0"
51+ ["github.com/kr/pretty".fetch]
52+ type = "git"
53+ url = "https://github.com/kr/pretty"
54+ rev = "73f6ac0b30a98e433b289500d779f50c1a6f0712"
55+ sha256 = "18m4pwg2abd0j9cn5v3k2ksk9ig4vlwxmlw9rrglanziv9l967qp"
56+
57+["github.com/kr/pty"]
58+ sumVersion = "v1.1.1"
59+ ["github.com/kr/pty".fetch]
60+ type = "git"
61+ url = "https://github.com/kr/pty"
62+ rev = "282ce0e5322c82529687d609ee670fac7c7d917c"
63+ sha256 = "0383f0mb9kqjvncqrfpidsf8y6ns5zlrc91c6a74xpyxjwvzl2y6"
64+
65+["github.com/kr/text"]
66+ sumVersion = "v0.1.0"
67+ ["github.com/kr/text".fetch]
68+ type = "git"
69+ url = "https://github.com/kr/text"
70+ rev = "e2ffdb16a802fe2bb95e2e35ff34f0e53aeef34f"
71+ sha256 = "1gm5bsl01apvc84bw06hasawyqm4q84vx1pm32wr9jnd7a8vjgj1"
72+
73+["github.com/mailru/easyjson"]
74+ sumVersion = "v0.0.0-20190626092158-b2ccc519800e"
75+ ["github.com/mailru/easyjson".fetch]
76+ type = "git"
77+ url = "https://github.com/mailru/easyjson"
78+ rev = "b2ccc519800e761ac8000b95e5d57c80a897ff9e"
79+ sha256 = "0q85h383mhbkcjm2vqm72bi8n2252fv3c56q3lclzb8n2crnjcdk"
80+
81+["github.com/pmezard/go-difflib"]
82+ sumVersion = "v1.0.0"
83+ ["github.com/pmezard/go-difflib".fetch]
84+ type = "git"
85+ url = "https://github.com/pmezard/go-difflib"
86+ rev = "792786c7400a136282c1664665ae0a8db921c6c2"
87+ sha256 = "0c1cn55m4rypmscgf0rrb88pn58j3ysvc2d0432dp3c6fqg6cnzw"
88+
89+["github.com/stretchr/objx"]
90+ sumVersion = "v0.1.0"
91+ ["github.com/stretchr/objx".fetch]
92+ type = "git"
93+ url = "https://github.com/stretchr/objx"
94+ rev = "facf9a85c22f48d2f52f2380e4efce1768749a89"
95+ sha256 = "19ynspzjdynbi85xw06mh8ad5j0qa1vryvxjgvbnyrr8rbm4vd8w"
96+
97+["github.com/stretchr/testify"]
98+ sumVersion = "v1.7.0"
99+ ["github.com/stretchr/testify".fetch]
100+ type = "git"
101+ url = "https://github.com/stretchr/testify"
102+ rev = "acba37e5db06f0093b465a7d47822bf13644b66c"
103+ sha256 = "0ixgjsvafr3513pz3r6pmgk074s2dxkll0dadvl25gkf30rkmh10"
104+
105+["github.com/yuin/goldmark"]
106+ sumVersion = "v1.4.0"
107+ ["github.com/yuin/goldmark".fetch]
108+ type = "git"
109+ url = "https://github.com/yuin/goldmark"
110+ rev = "5588d92a56fe1642791cf4aa8e9eae8227cfeecd"
111+ sha256 = "0n3xhna2rnxixjy5d7gfvgjkhddppa8hpzd8i8b68yb2l016g3qk"
112+
113+["gopkg.in/check.v1"]
114+ sumVersion = "v1.0.0-20190902080502-41f04d3bba15"
115+ ["gopkg.in/check.v1".fetch]
116+ type = "git"
117+ url = "https://gopkg.in/check.v1"
118+ rev = "41f04d3bba152ddec2103e299fed053415705330"
119+ sha256 = "0vfk9czmlxmp6wndq8k17rhnjxal764mxfhrccza7nwlia760pjy"
120+
121+["gopkg.in/yaml.v2"]
122+ sumVersion = "v2.3.0"
123+ ["gopkg.in/yaml.v2".fetch]
124+ type = "git"
125+ url = "https://gopkg.in/yaml.v2"
126+ rev = "0b1645d91e851e735d3e23330303ce81f70adbe3"
127+ sha256 = "1md0hlyd9s6myv3663i9l59y74n4xjazifmmyxn43g86fgkc5lzj"
128+
129+["gopkg.in/yaml.v3"]
130+ sumVersion = "v3.0.0-20210107192922-496545a6307b"
131+ ["gopkg.in/yaml.v3".fetch]
132+ type = "git"
133+ url = "https://gopkg.in/yaml.v3"
134+ rev = "496545a6307b2a7d7a710fd516e5e16e8ab62dbc"
135+ sha256 = "06f4lnrp494wqaygv09dggr2dwf3z2bawqhnlnnwiamg5y787k4g"
benchmarks/openapitools/mavenix.locknew file+3511
@@ -0,0 +1,3511 @@
1+{
2+ "artifactId": "openapi-diff-parent",
3+ "deps": [
4+ {
5+ "path": "asm/asm-parent/3.3.1/asm-parent-3.3.1.pom",
6+ "sha1": "72945d9cb6faa5082dcd190da850aa06760e4350"
7+ },
8+ {
9+ "path": "asm/asm/3.3.1/asm-3.3.1.jar",
10+ "sha1": "1d5f20b4ea675e6fab6ab79f1cd60ec268ddc015"
11+ },
12+ {
13+ "path": "asm/asm/3.3.1/asm-3.3.1.pom",
14+ "sha1": "bbcde0189656fa6cc671f27437432ac7e7f95673"
15+ },
16+ {
17+ "path": "backport-util-concurrent/backport-util-concurrent/3.1/backport-util-concurrent-3.1.jar",
18+ "sha1": "682f7ac17fed79e92f8e87d8455192b63376347b"
19+ },
20+ {
21+ "path": "backport-util-concurrent/backport-util-concurrent/3.1/backport-util-concurrent-3.1.pom",
22+ "sha1": "24aa8f29c14d1c63225caa6ad5328f1f7a2497a8"
23+ },
24+ {
25+ "path": "classworlds/classworlds/1.1-alpha-2/classworlds-1.1-alpha-2.jar",
26+ "sha1": "05adf2e681c57d7f48038b602f3ca2254ee82d47"
27+ },
28+ {
29+ "path": "classworlds/classworlds/1.1-alpha-2/classworlds-1.1-alpha-2.pom",
30+ "sha1": "8c8ad6a96a8c1168f8b12ec8a227b8261b160b26"
31+ },
32+ {
33+ "path": "classworlds/classworlds/1.1/classworlds-1.1.jar",
34+ "sha1": "60c708f55deeb7c5dfce8a7886ef09cbc1388eca"
35+ },
36+ {
37+ "path": "classworlds/classworlds/1.1/classworlds-1.1.pom",
38+ "sha1": "4703c4199028094698c222c17afea6dcd9f04999"
39+ },
40+ {
41+ "path": "com/coveo/fmt-maven-plugin/2.9.1/fmt-maven-plugin-2.9.1.jar",
42+ "sha1": "b9e23dcda7579bb2136c75a824954458376fc1f9"
43+ },
44+ {
45+ "path": "com/coveo/fmt-maven-plugin/2.9.1/fmt-maven-plugin-2.9.1.pom",
46+ "sha1": "7dd6d3f3d423d1d91f1fc3bc7899f4a042c7e342"
47+ },
48+ {
49+ "path": "com/fasterxml/jackson/core/jackson-annotations/2.10.1/jackson-annotations-2.10.1.pom",
50+ "sha1": "fdcd151d1804dec2025726f598a230e64a7da4d5"
51+ },
52+ {
53+ "path": "com/fasterxml/jackson/core/jackson-annotations/2.11.0/jackson-annotations-2.11.0.pom",
54+ "sha1": "516a81f560864d215c7680f5a00484ddfa8794b5"
55+ },
56+ {
57+ "path": "com/fasterxml/jackson/core/jackson-annotations/2.11.1/jackson-annotations-2.11.1.pom",
58+ "sha1": "b746e11b97ca52619ade1effdb75a786f495f4f7"
59+ },
60+ {
61+ "path": "com/fasterxml/jackson/core/jackson-annotations/2.12.1/jackson-annotations-2.12.1.jar",
62+ "sha1": "aa079f822ddce5548018286d19ccb15c2fc202d7"
63+ },
64+ {
65+ "path": "com/fasterxml/jackson/core/jackson-annotations/2.12.1/jackson-annotations-2.12.1.pom",
66+ "sha1": "9c38fd86d042ec6c2769fd52f5bfd8a8eae1abed"
67+ },
68+ {
69+ "path": "com/fasterxml/jackson/core/jackson-core/2.10.1/jackson-core-2.10.1.pom",
70+ "sha1": "fb8b025a02a6cf5612ad186402c94367c4b912f8"
71+ },
72+ {
73+ "path": "com/fasterxml/jackson/core/jackson-core/2.11.0/jackson-core-2.11.0.pom",
74+ "sha1": "e996f8033f774ea6d197de0edc84d6f14c2ce57e"
75+ },
76+ {
77+ "path": "com/fasterxml/jackson/core/jackson-core/2.11.1/jackson-core-2.11.1.pom",
78+ "sha1": "0a0d8a4a161004cf6d19eaeef9c95c7682da6152"
79+ },
80+ {
81+ "path": "com/fasterxml/jackson/core/jackson-core/2.12.1/jackson-core-2.12.1.jar",
82+ "sha1": "7c5493930e439be6fcec80a9afd6516b8e5e8760"
83+ },
84+ {
85+ "path": "com/fasterxml/jackson/core/jackson-core/2.12.1/jackson-core-2.12.1.pom",
86+ "sha1": "ac12348abc8bb6661e20975ea395c8c995b32b4c"
87+ },
88+ {
89+ "path": "com/fasterxml/jackson/core/jackson-databind/2.10.1/jackson-databind-2.10.1.pom",
90+ "sha1": "ea136b827ada9aebe65ecb47b8a8dacab76c6a89"
91+ },
92+ {
93+ "path": "com/fasterxml/jackson/core/jackson-databind/2.11.0/jackson-databind-2.11.0.pom",
94+ "sha1": "fffc69b81151915509b96cbc7e80ad832b53301d"
95+ },
96+ {
97+ "path": "com/fasterxml/jackson/core/jackson-databind/2.11.1/jackson-databind-2.11.1.pom",
98+ "sha1": "51a50898a694504b98853f909f068d4aa17dc782"
99+ },
100+ {
101+ "path": "com/fasterxml/jackson/core/jackson-databind/2.12.1/jackson-databind-2.12.1.jar",
102+ "sha1": "8a97e00e429c42f74757b0a8cd1d39dddd41524f"
103+ },
104+ {
105+ "path": "com/fasterxml/jackson/core/jackson-databind/2.12.1/jackson-databind-2.12.1.pom",
106+ "sha1": "6d5c05dec274802de5c58b654ff68f772f13125f"
107+ },
108+ {
109+ "path": "com/fasterxml/jackson/dataformat/jackson-dataformat-yaml/2.10.1/jackson-dataformat-yaml-2.10.1.pom",
110+ "sha1": "d6a8b362e8a7ca52cffe3aeaa30ab85ff88d610f"
111+ },
112+ {
113+ "path": "com/fasterxml/jackson/dataformat/jackson-dataformat-yaml/2.11.1/jackson-dataformat-yaml-2.11.1.pom",
114+ "sha1": "134a6d50bb1c78e667d226a34f3641f3586cf036"
115+ },
116+ {
117+ "path": "com/fasterxml/jackson/dataformat/jackson-dataformat-yaml/2.12.1/jackson-dataformat-yaml-2.12.1.jar",
118+ "sha1": "be6bf31ca69a28218daff18caef923ed6e1643e9"
119+ },
120+ {
121+ "path": "com/fasterxml/jackson/dataformat/jackson-dataformat-yaml/2.12.1/jackson-dataformat-yaml-2.12.1.pom",
122+ "sha1": "776dbfe69bdcc6c3e3a1e020848c65a1fd07cb0c"
123+ },
124+ {
125+ "path": "com/fasterxml/jackson/dataformat/jackson-dataformats-text/2.10.1/jackson-dataformats-text-2.10.1.pom",
126+ "sha1": "3a52b760d354b1203cac90252ff8f82aae7bb043"
127+ },
128+ {
129+ "path": "com/fasterxml/jackson/dataformat/jackson-dataformats-text/2.11.1/jackson-dataformats-text-2.11.1.pom",
130+ "sha1": "7fd5d17a7d147fe4a766d5552c7a5e5bdd874be8"
131+ },
132+ {
133+ "path": "com/fasterxml/jackson/dataformat/jackson-dataformats-text/2.12.1/jackson-dataformats-text-2.12.1.pom",
134+ "sha1": "f03cf5105784f4a4b772802ed718548580c6593f"
135+ },
136+ {
137+ "path": "com/fasterxml/jackson/datatype/jackson-datatype-jsr310/2.12.1/jackson-datatype-jsr310-2.12.1.jar",
138+ "sha1": "a245631c624e9c38dd0563c1100243c2f0be8335"
139+ },
140+ {
141+ "path": "com/fasterxml/jackson/datatype/jackson-datatype-jsr310/2.12.1/jackson-datatype-jsr310-2.12.1.pom",
142+ "sha1": "d4c62c8a033669bb82dde3bd93bbeabd21e0b3e8"
143+ },
144+ {
145+ "path": "com/fasterxml/jackson/jackson-base/2.10.1/jackson-base-2.10.1.pom",
146+ "sha1": "d0ba31a357e4503ca4f0ef8815d51b20c57edb35"
147+ },
148+ {
149+ "path": "com/fasterxml/jackson/jackson-base/2.11.0/jackson-base-2.11.0.pom",
150+ "sha1": "276bbf4e8376ae502fbb778f457ab8c827905735"
151+ },
152+ {
153+ "path": "com/fasterxml/jackson/jackson-base/2.11.1/jackson-base-2.11.1.pom",
154+ "sha1": "3f035aea01d74bae7a0bdb90064095454eca3730"
155+ },
156+ {
157+ "path": "com/fasterxml/jackson/jackson-base/2.12.1/jackson-base-2.12.1.pom",
158+ "sha1": "2dbd59b818a40450167a1ef3cf511e4c5fd19f69"
159+ },
160+ {
161+ "path": "com/fasterxml/jackson/jackson-bom/2.10.1/jackson-bom-2.10.1.pom",
162+ "sha1": "5893082a4078414e9b19ef1a79ad47727c89fed5"
163+ },
164+ {
165+ "path": "com/fasterxml/jackson/jackson-bom/2.11.0/jackson-bom-2.11.0.pom",
166+ "sha1": "33494ae4ec70fa17a153f42f367b36303cff71ff"
167+ },
168+ {
169+ "path": "com/fasterxml/jackson/jackson-bom/2.11.1/jackson-bom-2.11.1.pom",
170+ "sha1": "619e312d377367fcf8d704c2f575fe62922b7426"
171+ },
172+ {
173+ "path": "com/fasterxml/jackson/jackson-bom/2.12.1/jackson-bom-2.12.1.pom",
174+ "sha1": "47003a8d30c4174338dfc4da85e144cd61af13f3"
175+ },
176+ {
177+ "path": "com/fasterxml/jackson/jackson-parent/2.10/jackson-parent-2.10.pom",
178+ "sha1": "c07f59ea3d696225de2aa318a02b33ad0512b151"
179+ },
180+ {
181+ "path": "com/fasterxml/jackson/jackson-parent/2.11/jackson-parent-2.11.pom",
182+ "sha1": "89f0f8a7f21a54125e0ae1f72e6cdd50b51c87f3"
183+ },
184+ {
185+ "path": "com/fasterxml/jackson/jackson-parent/2.12/jackson-parent-2.12.pom",
186+ "sha1": "7675e7641142bc3c583fc3bf2e30ec9cba076ad9"
187+ },
188+ {
189+ "path": "com/fasterxml/jackson/module/jackson-modules-java8/2.12.1/jackson-modules-java8-2.12.1.pom",
190+ "sha1": "ffac85890402bb43f94f65d5ebd64eace3e436af"
191+ },
192+ {
193+ "path": "com/fasterxml/oss-parent/38/oss-parent-38.pom",
194+ "sha1": "ff6b9e9e40c23235f87a44b463995b47adca8dc9"
195+ },
196+ {
197+ "path": "com/fasterxml/oss-parent/41/oss-parent-41.pom",
198+ "sha1": "2b66e40e928eb5f2f9c1c0da54e3c26f6310cbfa"
199+ },
200+ {
201+ "path": "com/github/java-json-tools/btf/1.3/btf-1.3.jar",
202+ "sha1": "6cf5405e214cbc83337a107cdef8401fb6aa6383"
203+ },
204+ {
205+ "path": "com/github/java-json-tools/btf/1.3/btf-1.3.pom",
206+ "sha1": "0c7801904e438441fea6ab25d0e792b70c1f7399"
207+ },
208+ {
209+ "path": "com/github/java-json-tools/jackson-coreutils-equivalence/1.0/jackson-coreutils-equivalence-1.0.jar",
210+ "sha1": "8b928cf1f95dc5fe6b1648f5da93befab031da19"
211+ },
212+ {
213+ "path": "com/github/java-json-tools/jackson-coreutils-equivalence/1.0/jackson-coreutils-equivalence-1.0.pom",
214+ "sha1": "c71f1ce503ab04453666a1d986cca6e33da68d45"
215+ },
216+ {
217+ "path": "com/github/java-json-tools/jackson-coreutils/2.0/jackson-coreutils-2.0.jar",
218+ "sha1": "6374371261b91b829d10f21256b2feefdf8f0a78"
219+ },
220+ {
221+ "path": "com/github/java-json-tools/jackson-coreutils/2.0/jackson-coreutils-2.0.pom",
222+ "sha1": "561bdf0a38d4e16b7546a1551c1aab29855fc45e"
223+ },
224+ {
225+ "path": "com/github/java-json-tools/json-patch/1.13/json-patch-1.13.jar",
226+ "sha1": "c8b72249e50fe778e7df223e5b1fed1931a4a688"
227+ },
228+ {
229+ "path": "com/github/java-json-tools/json-patch/1.13/json-patch-1.13.pom",
230+ "sha1": "98e392a93101908fc7ce4572a9b204e1536b8bef"
231+ },
232+ {
233+ "path": "com/github/java-json-tools/json-schema-core/1.2.14/json-schema-core-1.2.14.jar",
234+ "sha1": "39d4efcf7e538684200fea15e08d47d0198c19fb"
235+ },
236+ {
237+ "path": "com/github/java-json-tools/json-schema-core/1.2.14/json-schema-core-1.2.14.pom",
238+ "sha1": "20d95413c951cbbaff4a9ce13fb98d29f93a2783"
239+ },
240+ {
241+ "path": "com/github/java-json-tools/json-schema-validator/2.2.14/json-schema-validator-2.2.14.jar",
242+ "sha1": "10c42918adc1fd4454e83bb21365f30df497a076"
243+ },
244+ {
245+ "path": "com/github/java-json-tools/json-schema-validator/2.2.14/json-schema-validator-2.2.14.pom",
246+ "sha1": "28a9a765a2f9b479e8843687a987357b5ec56a37"
247+ },
248+ {
249+ "path": "com/github/java-json-tools/msg-simple/1.2/msg-simple-1.2.jar",
250+ "sha1": "a06afa2d5d75c98e54ab370107930978fc3f9937"
251+ },
252+ {
253+ "path": "com/github/java-json-tools/msg-simple/1.2/msg-simple-1.2.pom",
254+ "sha1": "5b94d70f5d2cf151835ffeef57e543213e35879f"
255+ },
256+ {
257+ "path": "com/github/java-json-tools/uri-template/0.10/uri-template-0.10.jar",
258+ "sha1": "6e8cf7b04f5ed679c76f15e0b19918906d84dbc4"
259+ },
260+ {
261+ "path": "com/github/java-json-tools/uri-template/0.10/uri-template-0.10.pom",
262+ "sha1": "bbb4daf2e61908caf0977b484816c41fa322a46b"
263+ },
264+ {
265+ "path": "com/google/code/findbugs/jsr305/2.0.1/jsr305-2.0.1.pom",
266+ "sha1": "95efa8cea662452bb74b34abe09a93ff47625c8f"
267+ },
268+ {
269+ "path": "com/google/code/findbugs/jsr305/3.0.2/jsr305-3.0.2.jar",
270+ "sha1": "25ea2e8b0c338a877313bd4672d3fe056ea78f0d"
271+ },
272+ {
273+ "path": "com/google/code/findbugs/jsr305/3.0.2/jsr305-3.0.2.pom",
274+ "sha1": "8d93cdf4d84d7e1de736df607945c6df0730a10f"
275+ },
276+ {
277+ "path": "com/google/collections/google-collections/1.0/google-collections-1.0.pom",
278+ "sha1": "292197f3cb1ebc0dd03e20897e4250b265177286"
279+ },
280+ {
281+ "path": "com/google/errorprone/error_prone_annotations/2.2.0/error_prone_annotations-2.2.0.jar",
282+ "sha1": "88e3c593e9b3586e1c6177f89267da6fc6986f0c"
283+ },
284+ {
285+ "path": "com/google/errorprone/error_prone_annotations/2.2.0/error_prone_annotations-2.2.0.pom",
286+ "sha1": "e28b5b546020f18ea29e2b4756023f53ee91492b"
287+ },
288+ {
289+ "path": "com/google/errorprone/error_prone_annotations/2.3.2/error_prone_annotations-2.3.2.pom",
290+ "sha1": "f9aadf833282cfd743aa5d330f927489ca9c8734"
291+ },
292+ {
293+ "path": "com/google/errorprone/error_prone_annotations/2.3.4/error_prone_annotations-2.3.4.jar",
294+ "sha1": "dac170e4594de319655ffb62f41cbd6dbb5e601e"
295+ },
296+ {
297+ "path": "com/google/errorprone/error_prone_annotations/2.3.4/error_prone_annotations-2.3.4.pom",
298+ "sha1": "9a23fcb83bc8ed502506a8e6c648bf763dc5bcf9"
299+ },
300+ {
301+ "path": "com/google/errorprone/error_prone_parent/2.2.0/error_prone_parent-2.2.0.pom",
302+ "sha1": "72e2f31cb1952eada003d2ba7e82874cfe4b738c"
303+ },
304+ {
305+ "path": "com/google/errorprone/error_prone_parent/2.3.2/error_prone_parent-2.3.2.pom",
306+ "sha1": "ea30b94538922c99fb231a2c9859790831eb0fb0"
307+ },
308+ {
309+ "path": "com/google/errorprone/error_prone_parent/2.3.4/error_prone_parent-2.3.4.pom",
310+ "sha1": "a9b9dd42d174a5f96d6c195525877fc6d0b2028a"
311+ },
312+ {
313+ "path": "com/google/errorprone/javac-shaded/9+181-r4173-1/javac-shaded-9+181-r4173-1.jar",
314+ "sha1": "a399ee380b6d6b6ea53af1cfbcb086b108d1efb7"
315+ },
316+ {
317+ "path": "com/google/errorprone/javac-shaded/9+181-r4173-1/javac-shaded-9+181-r4173-1.pom",
318+ "sha1": "277b9e653add9e37cb6acf37f2b2330ac02dcda5"
319+ },
320+ {
321+ "path": "com/google/google/1/google-1.pom",
322+ "sha1": "c35a5268151b7a1bbb77f7ee94a950f00e32db61"
323+ },
324+ {
325+ "path": "com/google/googlejavaformat/google-java-format-parent/1.7/google-java-format-parent-1.7.pom",
326+ "sha1": "b320014d90fdda640da53e422c9c11b18e613ffc"
327+ },
328+ {
329+ "path": "com/google/googlejavaformat/google-java-format/1.7/google-java-format-1.7.jar",
330+ "sha1": "97cb6afc835d65682edc248e19170a8e4ecfe4c4"
331+ },
332+ {
333+ "path": "com/google/googlejavaformat/google-java-format/1.7/google-java-format-1.7.pom",
334+ "sha1": "f98d4be9cfef8c8a326c63089805e94248954219"
335+ },
336+ {
337+ "path": "com/google/guava/failureaccess/1.0.1/failureaccess-1.0.1.jar",
338+ "sha1": "1dcf1de382a0bf95a3d8b0849546c88bac1292c9"
339+ },
340+ {
341+ "path": "com/google/guava/failureaccess/1.0.1/failureaccess-1.0.1.pom",
342+ "sha1": "e8160e78fdaaf7088621dc1649d9dd2dfcf8d0e8"
343+ },
344+ {
345+ "path": "com/google/guava/guava-parent/26.0-android/guava-parent-26.0-android.pom",
346+ "sha1": "a2c0df489614352b7e8e503e274bd1dee5c42a64"
347+ },
348+ {
349+ "path": "com/google/guava/guava-parent/27.0.1-android/guava-parent-27.0.1-android.pom",
350+ "sha1": "87eb68456b29567ac831ffc6f487f1897e58fa7c"
351+ },
352+ {
353+ "path": "com/google/guava/guava-parent/27.0.1-jre/guava-parent-27.0.1-jre.pom",
354+ "sha1": "8f7a96c144da567471d3d763a240c25ba374ebb1"
355+ },
356+ {
357+ "path": "com/google/guava/guava-parent/28.1-android/guava-parent-28.1-android.pom",
358+ "sha1": "a35bc2b0d0477bca2e4a88c9b864de91ce705f5b"
359+ },
360+ {
361+ "path": "com/google/guava/guava-parent/28.2-android/guava-parent-28.2-android.pom",
362+ "sha1": "6db9079b12f809e8ab0f589d2e847a7a0bd9f4d2"
363+ },
364+ {
365+ "path": "com/google/guava/guava/27.0.1-android/guava-27.0.1-android.jar",
366+ "sha1": "b7e1c37f66ef193796ccd7ea6e80c2b05426182d"
367+ },
368+ {
369+ "path": "com/google/guava/guava/27.0.1-android/guava-27.0.1-android.pom",
370+ "sha1": "705c4ba035f86e8e883ce4892db3fecbf2a90b16"
371+ },
372+ {
373+ "path": "com/google/guava/guava/27.0.1-jre/guava-27.0.1-jre.jar",
374+ "sha1": "bd41a290787b5301e63929676d792c507bbc00ae"
375+ },
376+ {
377+ "path": "com/google/guava/guava/27.0.1-jre/guava-27.0.1-jre.pom",
378+ "sha1": "a6ccf3af1d34509e5fb1f5bff675b9ae707ad628"
379+ },
380+ {
381+ "path": "com/google/guava/guava/28.1-android/guava-28.1-android.pom",
382+ "sha1": "ad4f915dab2e5fecba3f440f8f77244647b96499"
383+ },
384+ {
385+ "path": "com/google/guava/guava/28.2-android/guava-28.2-android.jar",
386+ "sha1": "e11db6e27f5d1ec19826848a865c496c798398fa"
387+ },
388+ {
389+ "path": "com/google/guava/guava/28.2-android/guava-28.2-android.pom",
390+ "sha1": "8524e3a9ec839c335c75699514bc6dcb5b541778"
391+ },
392+ {
393+ "path": "com/google/guava/listenablefuture/9999.0-empty-to-avoid-conflict-with-guava/listenablefuture-9999.0-empty-to-avoid-conflict-with-guava.jar",
394+ "sha1": "b421526c5f297295adef1c886e5246c39d4ac629"
395+ },
396+ {
397+ "path": "com/google/guava/listenablefuture/9999.0-empty-to-avoid-conflict-with-guava/listenablefuture-9999.0-empty-to-avoid-conflict-with-guava.pom",
398+ "sha1": "1b77ba79f9b2b7dfd4e15ea7bb0d568d5eb9cb8d"
399+ },
400+ {
401+ "path": "com/google/j2objc/j2objc-annotations/1.1/j2objc-annotations-1.1.jar",
402+ "sha1": "ed28ded51a8b1c6b112568def5f4b455e6809019"
403+ },
404+ {
405+ "path": "com/google/j2objc/j2objc-annotations/1.1/j2objc-annotations-1.1.pom",
406+ "sha1": "b964a9414771661bdf35a3f10692a2fb0dd2c866"
407+ },
408+ {
409+ "path": "com/google/j2objc/j2objc-annotations/1.3/j2objc-annotations-1.3.jar",
410+ "sha1": "ba035118bc8bac37d7eff77700720999acd9986d"
411+ },
412+ {
413+ "path": "com/google/j2objc/j2objc-annotations/1.3/j2objc-annotations-1.3.pom",
414+ "sha1": "47e0dd93285dcc6b33181713bc7e8aed66742964"
415+ },
416+ {
417+ "path": "com/googlecode/javaewah/JavaEWAH/1.1.6/JavaEWAH-1.1.6.jar",
418+ "sha1": "94ad16d728b374d65bd897625f3fbb3da223a2b6"
419+ },
420+ {
421+ "path": "com/googlecode/javaewah/JavaEWAH/1.1.6/JavaEWAH-1.1.6.pom",
422+ "sha1": "759dda489d69ebd237d9ee353e67a460274b14f0"
423+ },
424+ {
425+ "path": "com/googlecode/libphonenumber/libphonenumber-parent/8.11.1/libphonenumber-parent-8.11.1.pom",
426+ "sha1": "fe3273c57fc50ef3f6bc4f851cb720e6e2255e4e"
427+ },
428+ {
429+ "path": "com/googlecode/libphonenumber/libphonenumber/8.11.1/libphonenumber-8.11.1.jar",
430+ "sha1": "6bb6115fd5a0bf00964afec358496faea66b7db5"
431+ },
432+ {
433+ "path": "com/googlecode/libphonenumber/libphonenumber/8.11.1/libphonenumber-8.11.1.pom",
434+ "sha1": "394fef7b008490aebe3186ea5dbe546cfb1ee849"
435+ },
436+ {
437+ "path": "com/j2html/j2html/1.5.0/j2html-1.5.0.jar",
438+ "sha1": "4416b2c8735192301711fa54ed97d2361ef90e06"
439+ },
440+ {
441+ "path": "com/j2html/j2html/1.5.0/j2html-1.5.0.pom",
442+ "sha1": "818f0a477f3d3801add2112bf44ba9d6e675c51b"
443+ },
444+ {
445+ "path": "com/jcraft/jsch/0.1.54/jsch-0.1.54.jar",
446+ "sha1": "da3584329a263616e277e15462b387addd1b208d"
447+ },
448+ {
449+ "path": "com/jcraft/jsch/0.1.54/jsch-0.1.54.pom",
450+ "sha1": "8e82e6a2cb5664170faa2a5abdc297e589a37df1"
451+ },
452+ {
453+ "path": "com/jcraft/jzlib/1.1.1/jzlib-1.1.1.jar",
454+ "sha1": "a1551373315ffc2f96130a0e5704f74e151777ba"
455+ },
456+ {
457+ "path": "com/jcraft/jzlib/1.1.1/jzlib-1.1.1.pom",
458+ "sha1": "d990b68017884e9615990c39ef81cf2b5884d464"
459+ },
460+ {
461+ "path": "com/sun/activation/all/1.2.1/all-1.2.1.pom",
462+ "sha1": "efca912f55f71e63ab2eb82552519b66dd123f98"
463+ },
464+ {
465+ "path": "com/sun/mail/all/1.6.2/all-1.6.2.pom",
466+ "sha1": "de5027ae62957f06ba7ff4733a0058871e237121"
467+ },
468+ {
469+ "path": "com/sun/mail/mailapi/1.6.2/mailapi-1.6.2.jar",
470+ "sha1": "208b6439dfbe6713c384ebf54ecd62cd4423cc50"
471+ },
472+ {
473+ "path": "com/sun/mail/mailapi/1.6.2/mailapi-1.6.2.pom",
474+ "sha1": "ab978578ae40ce05d492925a654dcd7154d3bd9a"
475+ },
476+ {
477+ "path": "com/thoughtworks/qdox/qdox/2.0-M8/qdox-2.0-M8.jar",
478+ "sha1": "036dc5cbf2aaf642d9ce7d0338591234ca49fcf0"
479+ },
480+ {
481+ "path": "com/thoughtworks/qdox/qdox/2.0-M8/qdox-2.0-M8.pom",
482+ "sha1": "8fc15cc55411249f3d89973e6ea55a7c4dc8688f"
483+ },
484+ {
485+ "path": "com/thoughtworks/qdox/qdox/2.0-M9/qdox-2.0-M9.jar",
486+ "sha1": "ea940f1cdba9205d03e4f54b9ac0ec988de751dd"
487+ },
488+ {
489+ "path": "com/thoughtworks/qdox/qdox/2.0-M9/qdox-2.0-M9.pom",
490+ "sha1": "5d3e19942fb302f11734b507b1115700b37f2cac"
491+ },
492+ {
493+ "path": "commons-beanutils/commons-beanutils/1.6/commons-beanutils-1.6.pom",
494+ "sha1": "cb6192708aa48ef75e8d04bcde65bc8d5a6ccdbf"
495+ },
496+ {
497+ "path": "commons-beanutils/commons-beanutils/1.7.0/commons-beanutils-1.7.0.jar",
498+ "sha1": "5675fd96b29656504b86029551973d60fb41339b"
499+ },
500+ {
501+ "path": "commons-beanutils/commons-beanutils/1.7.0/commons-beanutils-1.7.0.pom",
502+ "sha1": "19eca029edacc1be30030faf43ea6acb30556d1a"
503+ },
504+ {
505+ "path": "commons-cli/commons-cli/1.0/commons-cli-1.0.jar",
506+ "sha1": "6dac9733315224fc562f6268df58e92d65fd0137"
507+ },
508+ {
509+ "path": "commons-cli/commons-cli/1.0/commons-cli-1.0.pom",
510+ "sha1": "bc51fd74ed7c8ccf75b3abc84b3613d6ba60eb89"
511+ },
512+ {
513+ "path": "commons-cli/commons-cli/1.4/commons-cli-1.4.jar",
514+ "sha1": "c51c00206bb913cd8612b24abd9fa98ae89719b1"
515+ },
516+ {
517+ "path": "commons-cli/commons-cli/1.4/commons-cli-1.4.pom",
518+ "sha1": "c5aed4264ff37247043f6dcb6613d994ea7f8473"
519+ },
520+ {
521+ "path": "commons-codec/commons-codec/1.11/commons-codec-1.11.jar",
522+ "sha1": "3acb4705652e16236558f0f4f2192cc33c3bd189"
523+ },
524+ {
525+ "path": "commons-codec/commons-codec/1.11/commons-codec-1.11.pom",
526+ "sha1": "093ee1760aba62d6896d578bd7d247d0fa52f0e7"
527+ },
528+ {
529+ "path": "commons-codec/commons-codec/1.2/commons-codec-1.2.jar",
530+ "sha1": "397f4731a9f9b6eb1907e224911c77ea3aa27a8b"
531+ },
532+ {
533+ "path": "commons-codec/commons-codec/1.2/commons-codec-1.2.pom",
534+ "sha1": "3924208ea1e84feb88701e9a5000bc65c66fb335"
535+ },
536+ {
537+ "path": "commons-codec/commons-codec/1.9/commons-codec-1.9.pom",
538+ "sha1": "f5357ff0f308600af3660bf00a8be3415a335723"
539+ },
540+ {
541+ "path": "commons-collections/commons-collections/2.0/commons-collections-2.0.pom",
542+ "sha1": "b0d78d06e725d7f8176256eaeceb9d5b3f0a7bca"
543+ },
544+ {
545+ "path": "commons-collections/commons-collections/2.1/commons-collections-2.1.pom",
546+ "sha1": "03ac124c9f50b403afc9819e1f430d6883e77213"
547+ },
548+ {
549+ "path": "commons-collections/commons-collections/3.1/commons-collections-3.1.pom",
550+ "sha1": "f1afb3351823e726793a165ca37dced8f0191370"
551+ },
552+ {
553+ "path": "commons-collections/commons-collections/3.2.1/commons-collections-3.2.1.jar",
554+ "sha1": "761ea405b9b37ced573d2df0d1e3a4e0f9edc668"
555+ },
556+ {
557+ "path": "commons-collections/commons-collections/3.2.1/commons-collections-3.2.1.pom",
558+ "sha1": "c812635cfb96cd2431ee315e73418eed86aeb5e4"
559+ },
560+ {
561+ "path": "commons-collections/commons-collections/3.2/commons-collections-3.2.pom",
562+ "sha1": "0c8e56dc5476c517f1596f0686d72f51ef24d9e3"
563+ },
564+ {
565+ "path": "commons-digester/commons-digester/1.6/commons-digester-1.6.jar",
566+ "sha1": "e2822f655f2c182681c2cf27f224a425ccb2983d"
567+ },
568+ {
569+ "path": "commons-digester/commons-digester/1.6/commons-digester-1.6.pom",
570+ "sha1": "807b7186d68503e8a596c19f9d6ff2c70416967c"
571+ },
572+ {
573+ "path": "commons-httpclient/commons-httpclient/3.1/commons-httpclient-3.1.jar",
574+ "sha1": "964cd74171f427720480efdec40a7c7f6e58426a"
575+ },
576+ {
577+ "path": "commons-httpclient/commons-httpclient/3.1/commons-httpclient-3.1.pom",
578+ "sha1": "7e64d764d7f7ebc75ae3920490fcb58fbaf504a8"
579+ },
580+ {
581+ "path": "commons-io/commons-io/1.4/commons-io-1.4.jar",
582+ "sha1": "a8762d07e76cfde2395257a5da47ba7c1dbd3dce"
583+ },
584+ {
585+ "path": "commons-io/commons-io/1.4/commons-io-1.4.pom",
586+ "sha1": "526f34cad0a113787f3eb8ee1d0fe0abebcba887"
587+ },
588+ {
589+ "path": "commons-io/commons-io/2.4/commons-io-2.4.pom",
590+ "sha1": "9ece23effe8bce3904f3797a76b1ba6ab681e1b9"
591+ },
592+ {
593+ "path": "commons-io/commons-io/2.5/commons-io-2.5.jar",
594+ "sha1": "2852e6e05fbb95076fc091f6d1780f1f8fe35e0f"
595+ },
596+ {
597+ "path": "commons-io/commons-io/2.5/commons-io-2.5.pom",
598+ "sha1": "7e39112810f6096061c43504188d18edc7d7eece"
599+ },
600+ {
601+ "path": "commons-io/commons-io/2.6/commons-io-2.6.jar",
602+ "sha1": "815893df5f31da2ece4040fe0a12fd44b577afaf"
603+ },
604+ {
605+ "path": "commons-io/commons-io/2.6/commons-io-2.6.pom",
606+ "sha1": "5060835593e5b6ed18c82fc2e782f0a3c30a00b1"
607+ },
608+ {
609+ "path": "commons-lang/commons-lang/2.1/commons-lang-2.1.jar",
610+ "sha1": "4763ecc9d78781c915c07eb03e90572c7ff04205"
611+ },
612+ {
613+ "path": "commons-lang/commons-lang/2.1/commons-lang-2.1.pom",
614+ "sha1": "a34d992202615804c534953aba402de55d8ee47c"
615+ },
616+ {
617+ "path": "commons-lang/commons-lang/2.5/commons-lang-2.5.jar",
618+ "sha1": "b0236b252e86419eef20c31a44579d2aee2f0a69"
619+ },
620+ {
621+ "path": "commons-lang/commons-lang/2.6/commons-lang-2.6.jar",
622+ "sha1": "0ce1edb914c94ebc388f086c6827e8bdeec71ac2"
623+ },
624+ {
625+ "path": "commons-lang/commons-lang/2.6/commons-lang-2.6.pom",
626+ "sha1": "347d60b180fa80e5699d8e2cb72c99c93dda5454"
627+ },
628+ {
629+ "path": "commons-logging/commons-logging-api/1.1/commons-logging-api-1.1.pom",
630+ "sha1": "825395875e4a7ac53277f5f746085a3e13a04248"
631+ },
632+ {
633+ "path": "commons-logging/commons-logging/1.0.3/commons-logging-1.0.3.pom",
634+ "sha1": "b7de43bb310eb1dbfd00a34cec30500fa13cb577"
635+ },
636+ {
637+ "path": "commons-logging/commons-logging/1.0.4/commons-logging-1.0.4.jar",
638+ "sha1": "f029a2aefe2b3e1517573c580f948caac31b1056"
639+ },
640+ {
641+ "path": "commons-logging/commons-logging/1.0.4/commons-logging-1.0.4.pom",
642+ "sha1": "7d32e7520b801cabc3dc704d2afe59d020d00c45"
643+ },
644+ {
645+ "path": "commons-logging/commons-logging/1.0/commons-logging-1.0.pom",
646+ "sha1": "4f58df6cca7ad7b863e8186e5dc25a8ef502e374"
647+ },
648+ {
649+ "path": "commons-logging/commons-logging/1.2/commons-logging-1.2.pom",
650+ "sha1": "075c03ba4b01932842a996ef8d3fc1ab61ddeac2"
651+ },
652+ {
653+ "path": "commons-validator/commons-validator/1.2.0/commons-validator-1.2.0.jar",
654+ "sha1": "13dcebc00d206605bea72f6191b80370eb3ca805"
655+ },
656+ {
657+ "path": "commons-validator/commons-validator/1.2.0/commons-validator-1.2.0.pom",
658+ "sha1": "a7992acb52332d17c1bd9f7f774361b68b183c23"
659+ },
660+ {
661+ "path": "io/github/phillipuniverse/githook-maven-plugin/1.0.5/githook-maven-plugin-1.0.5.jar",
662+ "sha1": "79f5d906dbd88c654d2d4aabd4f7f26447782b05"
663+ },
664+ {
665+ "path": "io/github/phillipuniverse/githook-maven-plugin/1.0.5/githook-maven-plugin-1.0.5.pom",
666+ "sha1": "db15a1a8feb7f44a4bcaf3ec3914bd808017473c"
667+ },
668+ {
669+ "path": "io/swagger/core/v3/swagger-annotations/2.1.10/swagger-annotations-2.1.10.jar",
670+ "sha1": "1eec58d3db42dcefac76fa47211812c4782b1342"
671+ },
672+ {
673+ "path": "io/swagger/core/v3/swagger-annotations/2.1.10/swagger-annotations-2.1.10.pom",
674+ "sha1": "22f5429db8b61a40a4adc520062b811d8a474e1b"
675+ },
676+ {
677+ "path": "io/swagger/core/v3/swagger-core/2.1.10/swagger-core-2.1.10.jar",
678+ "sha1": "2400f32e387ade9ca015552d9ac23d1139c9884d"
679+ },
680+ {
681+ "path": "io/swagger/core/v3/swagger-core/2.1.10/swagger-core-2.1.10.pom",
682+ "sha1": "c4a78b843ca77156d6a4282d5a6533214e511b88"
683+ },
684+ {
685+ "path": "io/swagger/core/v3/swagger-models/2.1.10/swagger-models-2.1.10.jar",
686+ "sha1": "e577371a45e67ee22fa3b31675ff8a333054de4b"
687+ },
688+ {
689+ "path": "io/swagger/core/v3/swagger-models/2.1.10/swagger-models-2.1.10.pom",
690+ "sha1": "7a9293f9e8b8be13d4570ea4fac1e727cbc89210"
691+ },
692+ {
693+ "path": "io/swagger/core/v3/swagger-project/2.1.10/swagger-project-2.1.10.pom",
694+ "sha1": "3cb602835c36d643b42f35c21eb82abe0fdf47b4"
695+ },
696+ {
697+ "path": "io/swagger/parser/v3/swagger-parser-core/2.0.27/swagger-parser-core-2.0.27.jar",
698+ "sha1": "06e3a0b827ad5c519540963b61633eb88c4eb2b3"
699+ },
700+ {
701+ "path": "io/swagger/parser/v3/swagger-parser-core/2.0.27/swagger-parser-core-2.0.27.pom",
702+ "sha1": "1991007131f2c9f9ac7cd6c2c599bf41c2cc545f"
703+ },
704+ {
705+ "path": "io/swagger/parser/v3/swagger-parser-project/2.0.27/swagger-parser-project-2.0.27.pom",
706+ "sha1": "4db7dd58f920f974975463bcad388c81a3171470"
707+ },
708+ {
709+ "path": "io/swagger/parser/v3/swagger-parser-v2-converter/2.0.27/swagger-parser-v2-converter-2.0.27.jar",
710+ "sha1": "c827b8e82654f7ab2e575e56b7f9a8ca178e67bd"
711+ },
712+ {
713+ "path": "io/swagger/parser/v3/swagger-parser-v2-converter/2.0.27/swagger-parser-v2-converter-2.0.27.pom",
714+ "sha1": "d9e589a7b6f31cb3f801da0f1b172160108ef3a2"
715+ },
716+ {
717+ "path": "io/swagger/parser/v3/swagger-parser-v3/2.0.27/swagger-parser-v3-2.0.27.jar",
718+ "sha1": "304f736165d05944e3fc3bfa40ec09f65b985a23"
719+ },
720+ {
721+ "path": "io/swagger/parser/v3/swagger-parser-v3/2.0.27/swagger-parser-v3-2.0.27.pom",
722+ "sha1": "1d096d5386f3b519724377b9774c45ff0228826e"
723+ },
724+ {
725+ "path": "io/swagger/parser/v3/swagger-parser/2.0.27/swagger-parser-2.0.27.jar",
726+ "sha1": "63369fb7dda733feed9a2df2c5eb414ac7561a0e"
727+ },
728+ {
729+ "path": "io/swagger/parser/v3/swagger-parser/2.0.27/swagger-parser-2.0.27.pom",
730+ "sha1": "c43ecebd10022c75bad76e8e10956834a7f9973e"
731+ },
732+ {
733+ "path": "io/swagger/swagger-annotations/1.6.1/swagger-annotations-1.6.1.pom",
734+ "sha1": "43769ab44afc59a0b3acc2a05aabb912c406c0c8"
735+ },
736+ {
737+ "path": "io/swagger/swagger-annotations/1.6.2/swagger-annotations-1.6.2.jar",
738+ "sha1": "313913e603eaf3bb2c3b05079046ec07bb61f8c6"
739+ },
740+ {
741+ "path": "io/swagger/swagger-annotations/1.6.2/swagger-annotations-1.6.2.pom",
742+ "sha1": "3f95a7e66c8d71a7b6144d13bb45aca44c27caaf"
743+ },
744+ {
745+ "path": "io/swagger/swagger-compat-spec-parser/1.0.55/swagger-compat-spec-parser-1.0.55.jar",
746+ "sha1": "53347a00aaafa1cfb4b68b41563d6fbb3c1d86a0"
747+ },
748+ {
749+ "path": "io/swagger/swagger-compat-spec-parser/1.0.55/swagger-compat-spec-parser-1.0.55.pom",
750+ "sha1": "e1a68d7d9de27d86765ae3f67526f54ffcfea2f4"
751+ },
752+ {
753+ "path": "io/swagger/swagger-core/1.6.1/swagger-core-1.6.1.pom",
754+ "sha1": "cda5d0b22d090aa4e8d50dd6756044d3c6d87e5c"
755+ },
756+ {
757+ "path": "io/swagger/swagger-core/1.6.2/swagger-core-1.6.2.jar",
758+ "sha1": "4f062ad1aebb1255b84c851d00694cc7949de832"
759+ },
760+ {
761+ "path": "io/swagger/swagger-core/1.6.2/swagger-core-1.6.2.pom",
762+ "sha1": "534fb8fd889f0ab325ee4689971e1f62022b5b39"
763+ },
764+ {
765+ "path": "io/swagger/swagger-models/1.6.1/swagger-models-1.6.1.pom",
766+ "sha1": "dad12b91d115af4a0f224b3513b1049211382a4f"
767+ },
768+ {
769+ "path": "io/swagger/swagger-models/1.6.2/swagger-models-1.6.2.jar",
770+ "sha1": "887697058d8464462e8fd6d23c8461e90aec8c08"
771+ },
772+ {
773+ "path": "io/swagger/swagger-models/1.6.2/swagger-models-1.6.2.pom",
774+ "sha1": "24a8e6dfc8078fb2d26e4859ee6cbe8129fd89c1"
775+ },
776+ {
777+ "path": "io/swagger/swagger-parser-project/1.0.55/swagger-parser-project-1.0.55.pom",
778+ "sha1": "7add46a1d32db32e3dde17445c042599e98ba656"
779+ },
780+ {
781+ "path": "io/swagger/swagger-parser/1.0.55/swagger-parser-1.0.55.jar",
782+ "sha1": "4d1d07b4730e738b1ff11683973c5ddfca7f514e"
783+ },
784+ {
785+ "path": "io/swagger/swagger-parser/1.0.55/swagger-parser-1.0.55.pom",
786+ "sha1": "05f85ea462d75bed8afe91fcc7636a2fb93f0429"
787+ },
788+ {
789+ "path": "io/swagger/swagger-project/1.6.1/swagger-project-1.6.1.pom",
790+ "sha1": "9981865f6e64187bf023d8aac0f25ddcd750662a"
791+ },
792+ {
793+ "path": "io/swagger/swagger-project/1.6.2/swagger-project-1.6.2.pom",
794+ "sha1": "f33f1fd09542c95cd62267202f1596561db845be"
795+ },
796+ {
797+ "path": "jakarta/activation/jakarta.activation-api/1.2.1/jakarta.activation-api-1.2.1.jar",
798+ "sha1": "562a587face36ec7eff2db7f2fc95425c6602bc1"
799+ },
800+ {
801+ "path": "jakarta/activation/jakarta.activation-api/1.2.1/jakarta.activation-api-1.2.1.pom",
802+ "sha1": "b9c1b2502949970360efe8d75ec5268d87d38a82"
803+ },
804+ {
805+ "path": "jakarta/validation/jakarta.validation-api/2.0.2/jakarta.validation-api-2.0.2.jar",
806+ "sha1": "5eacc6522521f7eacb081f95cee1e231648461e7"
807+ },
808+ {
809+ "path": "jakarta/validation/jakarta.validation-api/2.0.2/jakarta.validation-api-2.0.2.pom",
810+ "sha1": "fc029778f5494ed05e5833f8bdb57e36dbda38aa"
811+ },
812+ {
813+ "path": "jakarta/xml/bind/jakarta.xml.bind-api-parent/2.3.2/jakarta.xml.bind-api-parent-2.3.2.pom",
814+ "sha1": "7be72e8345e33f747d5d813e313abd8df25f259e"
815+ },
816+ {
817+ "path": "jakarta/xml/bind/jakarta.xml.bind-api/2.3.2/jakarta.xml.bind-api-2.3.2.jar",
818+ "sha1": "8d49996a4338670764d7ca4b85a1c4ccf7fe665d"
819+ },
820+ {
821+ "path": "jakarta/xml/bind/jakarta.xml.bind-api/2.3.2/jakarta.xml.bind-api-2.3.2.pom",
822+ "sha1": "6142021e7186bf29f5f7639b968cfe250ce086dd"
823+ },
824+ {
825+ "path": "javax/annotation/jsr250-api/1.0/jsr250-api-1.0.jar",
826+ "sha1": "5025422767732a1ab45d93abfea846513d742dcf"
827+ },
828+ {
829+ "path": "javax/annotation/jsr250-api/1.0/jsr250-api-1.0.pom",
830+ "sha1": "828184cb963d953865b5941e416999e376b1c82a"
831+ },
832+ {
833+ "path": "javax/enterprise/cdi-api/1.0/cdi-api-1.0.jar",
834+ "sha1": "44c453f60909dfc223552ace63e05c694215156b"
835+ },
836+ {
837+ "path": "javax/enterprise/cdi-api/1.0/cdi-api-1.0.pom",
838+ "sha1": "b79b64c2b1cd6ddc1663f9f48dbf527262a2c3e5"
839+ },
840+ {
841+ "path": "javax/inject/javax.inject/1/javax.inject-1.jar",
842+ "sha1": "6975da39a7040257bd51d21a231b76c915872d38"
843+ },
844+ {
845+ "path": "javax/inject/javax.inject/1/javax.inject-1.pom",
846+ "sha1": "b8e00a8a0deb0ebef447570e37ff8146ccd92cbe"
847+ },
848+ {
849+ "path": "javax/servlet/servlet-api/2.5/servlet-api-2.5.jar",
850+ "sha1": "5959582d97d8b61f4d154ca9e495aafd16726e34"
851+ },
852+ {
853+ "path": "javax/validation/validation-api/1.1.0.Final/validation-api-1.1.0.Final.jar",
854+ "sha1": "8613ae82954779d518631e05daa73a6a954817d5"
855+ },
856+ {
857+ "path": "javax/validation/validation-api/1.1.0.Final/validation-api-1.1.0.Final.pom",
858+ "sha1": "0d2ad4d1498d1048abc6c6948fd3f835d8fdafb0"
859+ },
860+ {
861+ "path": "joda-time/joda-time/2.10.5/joda-time-2.10.5.jar",
862+ "sha1": "7f1d89817cd20a32444d5ab4160f035ab9b864e7"
863+ },
864+ {
865+ "path": "joda-time/joda-time/2.10.5/joda-time-2.10.5.pom",
866+ "sha1": "2523a5fb9c0b367fc734b33c8da600889472bd46"
867+ },
868+ {
869+ "path": "junit/junit/3.8.1/junit-3.8.1.jar",
870+ "sha1": "99129f16442844f6a4a11ae22fbbee40b14d774f"
871+ },
872+ {
873+ "path": "junit/junit/3.8.1/junit-3.8.1.pom",
874+ "sha1": "16d74791c801c89b0071b1680ea0bc85c93417bb"
875+ },
876+ {
877+ "path": "junit/junit/3.8.2/junit-3.8.2.pom",
878+ "sha1": "c735a15ca8fc2ea77db963c71ade153ffeb8212e"
879+ },
880+ {
881+ "path": "junit/junit/4.12/junit-4.12.jar",
882+ "sha1": "2973d150c0dc1fefe998f834810d68f278ea58ec"
883+ },
884+ {
885+ "path": "junit/junit/4.12/junit-4.12.pom",
886+ "sha1": "35fb238baee3f3af739074d723279ebea2028398"
887+ },
888+ {
889+ "path": "junit/junit/4.13.1/junit-4.13.1.jar",
890+ "sha1": "cdd00374f1fee76b11e2a9d127405aa3f6be5b6a"
891+ },
892+ {
893+ "path": "junit/junit/4.13.1/junit-4.13.1.pom",
894+ "sha1": "643e8b4c40dca9f0b0abd8125d378d9f47d7d69e"
895+ },
896+ {
897+ "path": "log4j/log4j/1.2.12/log4j-1.2.12.pom",
898+ "sha1": "70545179454d298d1ff01335fbec3c2acfd381d5"
899+ },
900+ {
901+ "path": "log4j/log4j/1.2.17/log4j-1.2.17.jar",
902+ "sha1": "5af35056b4d257e4b64b9e8069c0746e8b08629f"
903+ },
904+ {
905+ "path": "log4j/log4j/1.2.17/log4j-1.2.17.pom",
906+ "sha1": "309d3cac016db1a4cd4565ea2b95c0bdf040f8d1"
907+ },
908+ {
909+ "path": "net/java/jvnet-parent/1/jvnet-parent-1.pom",
910+ "sha1": "b55a1b046dbe82acdee8edde7476eebcba1e57d8"
911+ },
912+ {
913+ "path": "net/sf/jopt-simple/jopt-simple/5.0.4/jopt-simple-5.0.4.jar",
914+ "sha1": "4fdac2fbe92dfad86aa6e9301736f6b4342a3f5c"
915+ },
916+ {
917+ "path": "net/sf/jopt-simple/jopt-simple/5.0.4/jopt-simple-5.0.4.pom",
918+ "sha1": "c761a09cd9a4695b242c1fc35322d5b1659df7ed"
919+ },
920+ {
921+ "path": "org/apache/apache/10/apache-10.pom",
922+ "sha1": "48296e511366fa13aad48c58d8e09721774abec6"
923+ },
924+ {
925+ "path": "org/apache/apache/11/apache-11.pom",
926+ "sha1": "cb35e3b8eb7f1adbdc91e015b60d0da3a4e16c4f"
927+ },
928+ {
929+ "path": "org/apache/apache/13/apache-13.pom",
930+ "sha1": "15aff1faaec4963617f07dbe8e603f0adabc3a12"
931+ },
932+ {
933+ "path": "org/apache/apache/14/apache-14.pom",
934+ "sha1": "5c7956a91f3faaa9534cdc2b571c90bde2235157"
935+ },
936+ {
937+ "path": "org/apache/apache/16/apache-16.pom",
938+ "sha1": "8a90e31780e5cd0685ccaf25836c66e3b4e163b7"
939+ },
940+ {
941+ "path": "org/apache/apache/17/apache-17.pom",
942+ "sha1": "c1685ef8de6047fdad5e5fce99a8ccd80fc8b659"
943+ },
944+ {
945+ "path": "org/apache/apache/18/apache-18.pom",
946+ "sha1": "bd408bbea3840f2c7f914b29403e39a90f84fd5f"
947+ },
948+ {
949+ "path": "org/apache/apache/19/apache-19.pom",
950+ "sha1": "db8bb0231dcbda5011926dbaca1a7ce652fd5517"
951+ },
952+ {
953+ "path": "org/apache/apache/21/apache-21.pom",
954+ "sha1": "649b700a1b2b4a1d87e7ae8e3f47bfe101b2a4a5"
955+ },
956+ {
957+ "path": "org/apache/apache/23/apache-23.pom",
958+ "sha1": "0404949e96725e63a10a6d8f9d9b521948d170d5"
959+ },
960+ {
961+ "path": "org/apache/apache/3/apache-3.pom",
962+ "sha1": "1bc0010136a890e2fd38d901a0b7ecdf0e3f9871"
963+ },
964+ {
965+ "path": "org/apache/apache/4/apache-4.pom",
966+ "sha1": "602b647986c1d24301bc3d70e5923696bc7f1401"
967+ },
968+ {
969+ "path": "org/apache/apache/5/apache-5.pom",
970+ "sha1": "a99e211eb2be05af269c489b0f1abb9e8469fbca"
971+ },
972+ {
973+ "path": "org/apache/apache/6/apache-6.pom",
974+ "sha1": "70e78921afc16d914e65611d18ab1b2d6cb20e57"
975+ },
976+ {
977+ "path": "org/apache/apache/7/apache-7.pom",
978+ "sha1": "a5f679b14bb06a3cb3769eb04e228c8b9e12908f"
979+ },
980+ {
981+ "path": "org/apache/apache/9/apache-9.pom",
982+ "sha1": "de55d73a30c7521f3d55e8141d360ffbdfd88caa"
983+ },
984+ {
985+ "path": "org/apache/commons/commons-collections4/4.4/commons-collections4-4.4.jar",
986+ "sha1": "62ebe7544cb7164d87e0637a2a6a2bdc981395e8"
987+ },
988+ {
989+ "path": "org/apache/commons/commons-collections4/4.4/commons-collections4-4.4.pom",
990+ "sha1": "05428d42492ca170947632194080eb9432fbdf6c"
991+ },
992+ {
993+ "path": "org/apache/commons/commons-lang3/3.12.0/commons-lang3-3.12.0.jar",
994+ "sha1": "c6842c86792ff03b9f1d1fe2aab8dc23aa6c6f0e"
995+ },
996+ {
997+ "path": "org/apache/commons/commons-lang3/3.12.0/commons-lang3-3.12.0.pom",
998+ "sha1": "302d01a9279f7a400b1e767be60f12c02a5cf513"
999+ },
1000+ {
1001+ "path": "org/apache/commons/commons-lang3/3.4/commons-lang3-3.4.jar",
1002+ "sha1": "5fe28b9518e58819180a43a850fbc0dd24b7c050"
1003+ },
1004+ {
1005+ "path": "org/apache/commons/commons-lang3/3.4/commons-lang3-3.4.pom",
1006+ "sha1": "fd6eccbd05d55177e2f5e6d9da6f8d120751ab72"
1007+ },
1008+ {
1009+ "path": "org/apache/commons/commons-lang3/3.7/commons-lang3-3.7.jar",
1010+ "sha1": "557edd918fd41f9260963583ebf5a61a43a6b423"
1011+ },
1012+ {
1013+ "path": "org/apache/commons/commons-lang3/3.7/commons-lang3-3.7.pom",
1014+ "sha1": "c445be3b6442b41cbea539d4218be3aea9428a55"
1015+ },
1016+ {
1017+ "path": "org/apache/commons/commons-parent/17/commons-parent-17.pom",
1018+ "sha1": "84bc2f457fac92c947cde9c15c81786ded79b3c1"
1019+ },
1020+ {
1021+ "path": "org/apache/commons/commons-parent/25/commons-parent-25.pom",
1022+ "sha1": "67b84199ca4acf0d8fbc5256d90b80f746737e94"
1023+ },
1024+ {
1025+ "path": "org/apache/commons/commons-parent/32/commons-parent-32.pom",
1026+ "sha1": "0e51c4223003c2c7c63f38d7b8823e40eb06bd1f"
1027+ },
1028+ {
1029+ "path": "org/apache/commons/commons-parent/34/commons-parent-34.pom",
1030+ "sha1": "1f6be162a806d8343e3cd238dd728558532473a5"
1031+ },
1032+ {
1033+ "path": "org/apache/commons/commons-parent/37/commons-parent-37.pom",
1034+ "sha1": "a85dfae7a1295e5aed75bd952e6795832e4abcc5"
1035+ },
1036+ {
1037+ "path": "org/apache/commons/commons-parent/39/commons-parent-39.pom",
1038+ "sha1": "4bc32d3cda9f07814c548492af7bf19b21798d46"
1039+ },
1040+ {
1041+ "path": "org/apache/commons/commons-parent/42/commons-parent-42.pom",
1042+ "sha1": "35d45eda74fe511d3d60b68e1dac29ed55043354"
1043+ },
1044+ {
1045+ "path": "org/apache/commons/commons-parent/48/commons-parent-48.pom",
1046+ "sha1": "1cdeb626cf4f0cec0f171ec838a69922efc6ef95"
1047+ },
1048+ {
1049+ "path": "org/apache/commons/commons-parent/52/commons-parent-52.pom",
1050+ "sha1": "004ee86dedc66d0010ccdc29e5a4ce014c057854"
1051+ },
1052+ {
1053+ "path": "org/apache/commons/commons-parent/7/commons-parent-7.pom",
1054+ "sha1": "95db361d9db1474346b2bde93e5402281909144c"
1055+ },
1056+ {
1057+ "path": "org/apache/commons/commons-parent/9/commons-parent-9.pom",
1058+ "sha1": "217cc375e25b647a61956e1d6a88163f9e3a387c"
1059+ },
1060+ {
1061+ "path": "org/apache/httpcomponents/httpclient/4.5.2/httpclient-4.5.2.jar",
1062+ "sha1": "733db77aa8d9b2d68015189df76ab06304406e50"
1063+ },
1064+ {
1065+ "path": "org/apache/httpcomponents/httpclient/4.5.2/httpclient-4.5.2.pom",
1066+ "sha1": "56f6338b324e438307e1f2c2b33bd02268310fc2"
1067+ },
1068+ {
1069+ "path": "org/apache/httpcomponents/httpcomponents-client/4.5.2/httpcomponents-client-4.5.2.pom",
1070+ "sha1": "55d500e6c1e98ffbb00c35bee72fabc255c22108"
1071+ },
1072+ {
1073+ "path": "org/apache/httpcomponents/httpcomponents-core/4.4.4/httpcomponents-core-4.4.4.pom",
1074+ "sha1": "84c5600018f58510ef3d2c3b5d218bea5d51bbbe"
1075+ },
1076+ {
1077+ "path": "org/apache/httpcomponents/httpcore/4.4.4/httpcore-4.4.4.jar",
1078+ "sha1": "b31526a230871fbe285fbcbe2813f9c0839ae9b0"
1079+ },
1080+ {
1081+ "path": "org/apache/httpcomponents/httpcore/4.4.4/httpcore-4.4.4.pom",
1082+ "sha1": "2feaed055f70af1aafd223137e4bd456decc5995"
1083+ },
1084+ {
1085+ "path": "org/apache/httpcomponents/project/7/project-7.pom",
1086+ "sha1": "c486760d8e0eafe8d4932450e386c2805364f782"
1087+ },
1088+ {
1089+ "path": "org/apache/maven/doxia/doxia-core/1.0/doxia-core-1.0.jar",
1090+ "sha1": "e94c3303b09923f8cd7916a59702ef5972033f5d"
1091+ },
1092+ {
1093+ "path": "org/apache/maven/doxia/doxia-core/1.0/doxia-core-1.0.pom",
1094+ "sha1": "d4f85b43d096d6346af131b9d184847c67d0b405"
1095+ },
1096+ {
1097+ "path": "org/apache/maven/doxia/doxia-core/1.4/doxia-core-1.4.jar",
1098+ "sha1": "1e9ee5aa729da72e9e9884462782c005592d2075"
1099+ },
1100+ {
1101+ "path": "org/apache/maven/doxia/doxia-decoration-model/1.0/doxia-decoration-model-1.0.jar",
1102+ "sha1": "040cc4c68fcc197885c4d98f89588bd0445c7449"
1103+ },
1104+ {
1105+ "path": "org/apache/maven/doxia/doxia-decoration-model/1.0/doxia-decoration-model-1.0.pom",
1106+ "sha1": "ce88deb4d18e5ecd4b23bb3e4c60b6bd842bb27f"
1107+ },
1108+ {
1109+ "path": "org/apache/maven/doxia/doxia-decoration-model/1.4/doxia-decoration-model-1.4.jar",
1110+ "sha1": "ffa7fabafef8ba0accc794d025f9790320220e1e"
1111+ },
1112+ {
1113+ "path": "org/apache/maven/doxia/doxia-integration-tools/1.5/doxia-integration-tools-1.5.jar",
1114+ "sha1": "ee43d4ccb9e5cc4067ac4f4de9b50e89de2f1191"
1115+ },
1116+ {
1117+ "path": "org/apache/maven/doxia/doxia-logging-api/1.4/doxia-logging-api-1.4.jar",
1118+ "sha1": "fd0ab30404ac0fca5f672eee70acf5d17a1ea856"
1119+ },
1120+ {
1121+ "path": "org/apache/maven/doxia/doxia-module-apt/1.0/doxia-module-apt-1.0.jar",
1122+ "sha1": "de385703452b5b9029504df97b763f7f48e8bf42"
1123+ },
1124+ {
1125+ "path": "org/apache/maven/doxia/doxia-module-apt/1.0/doxia-module-apt-1.0.pom",
1126+ "sha1": "4d78dfaba27a352590ea86e6eaa80284c004e603"
1127+ },
1128+ {
1129+ "path": "org/apache/maven/doxia/doxia-module-apt/1.4/doxia-module-apt-1.4.jar",
1130+ "sha1": "2b6fc70f6906e74eee049cc30f8385e49381c16f"
1131+ },
1132+ {
1133+ "path": "org/apache/maven/doxia/doxia-module-fml/1.0/doxia-module-fml-1.0.jar",
1134+ "sha1": "f837b5f530c95b5551d94d792da31737e678eaa1"
1135+ },
1136+ {
1137+ "path": "org/apache/maven/doxia/doxia-module-fml/1.0/doxia-module-fml-1.0.pom",
1138+ "sha1": "dcb9b6d9fbd98857242891f7922e5f032ab56897"
1139+ },
1140+ {
1141+ "path": "org/apache/maven/doxia/doxia-module-fml/1.4/doxia-module-fml-1.4.jar",
1142+ "sha1": "d27851cfa0a355070acdc0482de3e94c0140b5db"
1143+ },
1144+ {
1145+ "path": "org/apache/maven/doxia/doxia-module-markdown/1.4/doxia-module-markdown-1.4.jar",
1146+ "sha1": "90c587acc8b13dea639ffeb43854165a6531a011"
1147+ },
1148+ {
1149+ "path": "org/apache/maven/doxia/doxia-module-xdoc/1.0/doxia-module-xdoc-1.0.jar",
1150+ "sha1": "538dce721987425bae72e55c318863ee4a412154"
1151+ },
1152+ {
1153+ "path": "org/apache/maven/doxia/doxia-module-xdoc/1.0/doxia-module-xdoc-1.0.pom",
1154+ "sha1": "3f97d4af3f734f0c71ce540b1fbf57708e2d76c8"
1155+ },
1156+ {
1157+ "path": "org/apache/maven/doxia/doxia-module-xdoc/1.4/doxia-module-xdoc-1.4.jar",
1158+ "sha1": "cf7d317034a3c8ab170076a4f82f6371ca5e6791"
1159+ },
1160+ {
1161+ "path": "org/apache/maven/doxia/doxia-module-xhtml/1.0/doxia-module-xhtml-1.0.jar",
1162+ "sha1": "237057eb966a49ad5e675f46b783880a0a703e86"
1163+ },
1164+ {
1165+ "path": "org/apache/maven/doxia/doxia-module-xhtml/1.0/doxia-module-xhtml-1.0.pom",
1166+ "sha1": "969aaeb5d46b76183b0bf3eacd3587cc44fd3d9e"
1167+ },
1168+ {
1169+ "path": "org/apache/maven/doxia/doxia-module-xhtml/1.4/doxia-module-xhtml-1.4.jar",
1170+ "sha1": "109b0b6b49fdd166b036c7fce93393fa98002c66"
1171+ },
1172+ {
1173+ "path": "org/apache/maven/doxia/doxia-modules/1.0/doxia-modules-1.0.pom",
1174+ "sha1": "0995eb509c335f35f0170182e9d64a76ddf4b02a"
1175+ },
1176+ {
1177+ "path": "org/apache/maven/doxia/doxia-sink-api/1.0-alpha-10/doxia-sink-api-1.0-alpha-10.pom",
1178+ "sha1": "80e28b4d518236464c97722dd9aa53092af181a7"
1179+ },
1180+ {
1181+ "path": "org/apache/maven/doxia/doxia-sink-api/1.0-alpha-7/doxia-sink-api-1.0-alpha-7.jar",
1182+ "sha1": "68464d54384c35119c70684d5d609b64635d1bbd"
1183+ },
1184+ {
1185+ "path": "org/apache/maven/doxia/doxia-sink-api/1.0-alpha-7/doxia-sink-api-1.0-alpha-7.pom",
1186+ "sha1": "d8e08f33563f684917311978da2ff03a9d0022ab"
1187+ },
1188+ {
1189+ "path": "org/apache/maven/doxia/doxia-sink-api/1.0/doxia-sink-api-1.0.jar",
1190+ "sha1": "13f502f2fb1d4e2db6f19352c85b83277084bb98"
1191+ },
1192+ {
1193+ "path": "org/apache/maven/doxia/doxia-sink-api/1.0/doxia-sink-api-1.0.pom",
1194+ "sha1": "5d842372fdb4c42d78824141f7be4c0d541c983f"
1195+ },
1196+ {
1197+ "path": "org/apache/maven/doxia/doxia-sink-api/1.4/doxia-sink-api-1.4.jar",
1198+ "sha1": "3cfed174cabb086426a9043da49a70526ff40d16"
1199+ },
1200+ {
1201+ "path": "org/apache/maven/doxia/doxia-site-renderer/1.0/doxia-site-renderer-1.0.jar",
1202+ "sha1": "c70e13ad9cb90f7cf88ceeb10eba2a85d0f9045f"
1203+ },
1204+ {
1205+ "path": "org/apache/maven/doxia/doxia-site-renderer/1.0/doxia-site-renderer-1.0.pom",
1206+ "sha1": "f2df20c85431398821cab8b1b65e3228df1f2ae5"
1207+ },
1208+ {
1209+ "path": "org/apache/maven/doxia/doxia-site-renderer/1.4/doxia-site-renderer-1.4.jar",
1210+ "sha1": "91acd32a131407bccefd2971c1103c5d16002da2"
1211+ },
1212+ {
1213+ "path": "org/apache/maven/doxia/doxia-sitetools/1.0/doxia-sitetools-1.0.pom",
1214+ "sha1": "adeed9a4562d79bbf2bbc22af664c4b7888ed49a"
1215+ },
1216+ {
1217+ "path": "org/apache/maven/doxia/doxia/1.0-alpha-10/doxia-1.0-alpha-10.pom",
1218+ "sha1": "219a2deff42bccd82cd3d5775a86b95ce48d3dd4"
1219+ },
1220+ {
1221+ "path": "org/apache/maven/doxia/doxia/1.0-alpha-7/doxia-1.0-alpha-7.pom",
1222+ "sha1": "fff8727b6ff366d624669f4b8dc4d4c7316bbb0c"
1223+ },
1224+ {
1225+ "path": "org/apache/maven/doxia/doxia/1.0/doxia-1.0.pom",
1226+ "sha1": "250d5a027daedc96539e3b3def7da7911feb6aae"
1227+ },
1228+ {
1229+ "path": "org/apache/maven/maven-aether-provider/3.0/maven-aether-provider-3.0.jar",
1230+ "sha1": "419f5eb63cf743a1a0f2a80ea5dde37fd1a4fec0"
1231+ },
1232+ {
1233+ "path": "org/apache/maven/maven-aether-provider/3.0/maven-aether-provider-3.0.pom",
1234+ "sha1": "a3e7fa0d4d0d26f901c919173681bab824c5588c"
1235+ },
1236+ {
1237+ "path": "org/apache/maven/maven-archiver/2.4.2/maven-archiver-2.4.2.jar",
1238+ "sha1": "ddcb393749701eb292a263a3500db69df39aef43"
1239+ },
1240+ {
1241+ "path": "org/apache/maven/maven-archiver/2.5/maven-archiver-2.5.jar",
1242+ "sha1": "c999ae305f22ecfc5a000dca12a39b9491778bd5"
1243+ },
1244+ {
1245+ "path": "org/apache/maven/maven-archiver/2.5/maven-archiver-2.5.pom",
1246+ "sha1": "a46a65782b96c7624c0ff64b50a91ba2935d84f6"
1247+ },
1248+ {
1249+ "path": "org/apache/maven/maven-artifact-manager/2.0.2/maven-artifact-manager-2.0.2.jar",
1250+ "sha1": "982eee8d0feb92587beb60874c731febc6d9ed9d"
1251+ },
1252+ {
1253+ "path": "org/apache/maven/maven-artifact-manager/2.0.2/maven-artifact-manager-2.0.2.pom",
1254+ "sha1": "157c24fb3ec09b9a693f88dc571fc17ed0669cca"
1255+ },
1256+ {
1257+ "path": "org/apache/maven/maven-artifact-manager/2.0.5/maven-artifact-manager-2.0.5.pom",
1258+ "sha1": "cc2c71211f52ada0389f3d2c9de16dd1429eccd7"
1259+ },
1260+ {
1261+ "path": "org/apache/maven/maven-artifact-manager/2.0.6/maven-artifact-manager-2.0.6.jar",
1262+ "sha1": "dc326c3a989c10618e09a7b77cadeff297591942"
1263+ },
1264+ {
1265+ "path": "org/apache/maven/maven-artifact-manager/2.0.6/maven-artifact-manager-2.0.6.pom",
1266+ "sha1": "8cb8b1dc4d9f7fbd90be4e9c8e9a1d353e28666c"
1267+ },
1268+ {
1269+ "path": "org/apache/maven/maven-artifact-manager/2.0.8/maven-artifact-manager-2.0.8.pom",
1270+ "sha1": "5c9b2820e6abe0c070c0dedfdacf642a85abf2e6"
1271+ },
1272+ {
1273+ "path": "org/apache/maven/maven-artifact-manager/2.0.9/maven-artifact-manager-2.0.9.jar",
1274+ "sha1": "53224a5254101fb9b6d561d5a53c6d0817036d94"
1275+ },
1276+ {
1277+ "path": "org/apache/maven/maven-artifact-manager/2.0.9/maven-artifact-manager-2.0.9.pom",
1278+ "sha1": "84c14dcd1d85eebccbba665f95057b5748f51d83"
1279+ },
1280+ {
1281+ "path": "org/apache/maven/maven-artifact-manager/2.2.0/maven-artifact-manager-2.2.0.pom",
1282+ "sha1": "91b2c4b9a4cb63846da595ff15df78ebc7f1b31f"
1283+ },
1284+ {
1285+ "path": "org/apache/maven/maven-artifact-manager/2.2.1/maven-artifact-manager-2.2.1.jar",
1286+ "sha1": "ec355b913c34d37080810f98e3f51abecbe1572b"
1287+ },
1288+ {
1289+ "path": "org/apache/maven/maven-artifact-manager/2.2.1/maven-artifact-manager-2.2.1.pom",
1290+ "sha1": "062f05a1fc0a40a6ea8fc8f0a1e9e2c02057ebaf"
1291+ },
1292+ {
1293+ "path": "org/apache/maven/maven-artifact/2.0.2/maven-artifact-2.0.2.pom",
1294+ "sha1": "a8b0aa4f932e948f979c872326a5ac9d7f4e123c"
1295+ },
1296+ {
1297+ "path": "org/apache/maven/maven-artifact/2.0.5/maven-artifact-2.0.5.pom",
1298+ "sha1": "d4b90628e1e33c3d2319aa3279f6498905fb7bd8"
1299+ },
1300+ {
1301+ "path": "org/apache/maven/maven-artifact/2.0.6/maven-artifact-2.0.6.jar",
1302+ "sha1": "fcbf6e26a6d26ecaa25c199b6f16bf168b2f28dc"
1303+ },
1304+ {
1305+ "path": "org/apache/maven/maven-artifact/2.0.6/maven-artifact-2.0.6.pom",
1306+ "sha1": "973c14299a051daf4e767cc60f15788b50c887f2"
1307+ },
1308+ {
1309+ "path": "org/apache/maven/maven-artifact/2.0.8/maven-artifact-2.0.8.pom",
1310+ "sha1": "351f42403e36c8661e8f0a8489bf537ba31ab17a"
1311+ },
1312+ {
1313+ "path": "org/apache/maven/maven-artifact/2.0.9/maven-artifact-2.0.9.jar",
1314+ "sha1": "66f0c8baa789fffdf54924cf395b26bbc2130435"
1315+ },
1316+ {
1317+ "path": "org/apache/maven/maven-artifact/2.0.9/maven-artifact-2.0.9.pom",
1318+ "sha1": "ffc6bb3eabd75a28d704e0431e7a44e7b4dff9bd"
1319+ },
1320+ {
1321+ "path": "org/apache/maven/maven-artifact/2.2.0/maven-artifact-2.2.0.pom",
1322+ "sha1": "adf024bc80dcc83893fc712b9fff6f8d1f224fc6"
1323+ },
1324+ {
1325+ "path": "org/apache/maven/maven-artifact/2.2.1/maven-artifact-2.2.1.jar",
1326+ "sha1": "23600f790d4dab2cb965419eaa982e3e84c428f8"
1327+ },
1328+ {
1329+ "path": "org/apache/maven/maven-artifact/2.2.1/maven-artifact-2.2.1.pom",
1330+ "sha1": "e37430ef3c3ee1d33817fdb45a0e538f49932c0a"
1331+ },
1332+ {
1333+ "path": "org/apache/maven/maven-artifact/3.0/maven-artifact-3.0.jar",
1334+ "sha1": "c29cfa43ce2ba09975a07c40d7241655d7c2fa29"
1335+ },
1336+ {
1337+ "path": "org/apache/maven/maven-artifact/3.0/maven-artifact-3.0.pom",
1338+ "sha1": "6823c7ad1a5557c2f96bd2fd312948513af8e524"
1339+ },
1340+ {
1341+ "path": "org/apache/maven/maven-artifact/3.3.9/maven-artifact-3.3.9.jar",
1342+ "sha1": "0f43afa184555fbc6e36b3334b17246c39b30f6e"
1343+ },
1344+ {
1345+ "path": "org/apache/maven/maven-artifact/3.3.9/maven-artifact-3.3.9.pom",
1346+ "sha1": "d1d1835d6f9f725841f6e0c8e40e00a19a4a1f9a"
1347+ },
1348+ {
1349+ "path": "org/apache/maven/maven-core/2.0.6/maven-core-2.0.6.jar",
1350+ "sha1": "33b78ed70029bfca9fadee5c8e7c9b27b9a39443"
1351+ },
1352+ {
1353+ "path": "org/apache/maven/maven-core/2.0.6/maven-core-2.0.6.pom",
1354+ "sha1": "b02365ee1822cff5839d9f85bc9b1cbfab9f5674"
1355+ },
1356+ {
1357+ "path": "org/apache/maven/maven-core/2.0.9/maven-core-2.0.9.jar",
1358+ "sha1": "e1003a0a66dae77515259c5e591ea1cfd73c2859"
1359+ },
1360+ {
1361+ "path": "org/apache/maven/maven-core/2.0.9/maven-core-2.0.9.pom",
1362+ "sha1": "25da75e747afa1c361f003aed72de2e48dd190a7"
1363+ },
1364+ {
1365+ "path": "org/apache/maven/maven-core/2.2.1/maven-core-2.2.1.jar",
1366+ "sha1": "6f488e461188496c62e161f32160b3465ce5901e"
1367+ },
1368+ {
1369+ "path": "org/apache/maven/maven-core/2.2.1/maven-core-2.2.1.pom",
1370+ "sha1": "c7312a507d519047be160bab5cbb56c07d0247a1"
1371+ },
1372+ {
1373+ "path": "org/apache/maven/maven-core/3.0/maven-core-3.0.jar",
1374+ "sha1": "73728ce32c9016c8bd05584301fa3ba3a6f5d20a"
1375+ },
1376+ {
1377+ "path": "org/apache/maven/maven-core/3.0/maven-core-3.0.pom",
1378+ "sha1": "3727542038487060064a4a14b74c7590d364c45b"
1379+ },
1380+ {
1381+ "path": "org/apache/maven/maven-error-diagnostics/2.0.6/maven-error-diagnostics-2.0.6.jar",
1382+ "sha1": "49f5380c07a79cd91ee09e0cb9063764f1f6525c"
1383+ },
1384+ {
1385+ "path": "org/apache/maven/maven-error-diagnostics/2.0.6/maven-error-diagnostics-2.0.6.pom",
1386+ "sha1": "31c0ce961dfc5b491e92ad0804dd48840dac7796"
1387+ },
1388+ {
1389+ "path": "org/apache/maven/maven-error-diagnostics/2.0.9/maven-error-diagnostics-2.0.9.jar",
1390+ "sha1": "46cc6b69beebc7bbf59c4f3842f72f2c1942e8e5"
1391+ },
1392+ {
1393+ "path": "org/apache/maven/maven-error-diagnostics/2.0.9/maven-error-diagnostics-2.0.9.pom",
1394+ "sha1": "dd562ddf84fc56b0693b42184a27d86d126ef02b"
1395+ },
1396+ {
1397+ "path": "org/apache/maven/maven-error-diagnostics/2.2.1/maven-error-diagnostics-2.2.1.jar",
1398+ "sha1": "e81bb342d7d172f23d108dc8fa979a1facdcde8e"
1399+ },
1400+ {
1401+ "path": "org/apache/maven/maven-error-diagnostics/2.2.1/maven-error-diagnostics-2.2.1.pom",
1402+ "sha1": "5074991d8d14a88e7c8bff294639a254d7ef387a"
1403+ },
1404+ {
1405+ "path": "org/apache/maven/maven-model-builder/3.0/maven-model-builder-3.0.jar",
1406+ "sha1": "bedc161a3b07a4bcd175b9428cdf18725d292b37"
1407+ },
1408+ {
1409+ "path": "org/apache/maven/maven-model-builder/3.0/maven-model-builder-3.0.pom",
1410+ "sha1": "e4b3e5ffec18728f099d8000e400ac763af2cc20"
1411+ },
1412+ {
1413+ "path": "org/apache/maven/maven-model/2.0.5/maven-model-2.0.5.pom",
1414+ "sha1": "0b5c0e9a116a812ef64831e5be5114bb4f518e58"
1415+ },
1416+ {
1417+ "path": "org/apache/maven/maven-model/2.0.6/maven-model-2.0.6.jar",
1418+ "sha1": "9649253c0e68a453f388e0a308c0653309f87807"
1419+ },
1420+ {
1421+ "path": "org/apache/maven/maven-model/2.0.6/maven-model-2.0.6.pom",
1422+ "sha1": "ea1dd9b8c7b1c3d2f0bdf314390ed7da7e463460"
1423+ },
1424+ {
1425+ "path": "org/apache/maven/maven-model/2.0.8/maven-model-2.0.8.pom",
1426+ "sha1": "6e51285e0830c3f05999ca4f3175ffc81f0be43b"
1427+ },
1428+ {
1429+ "path": "org/apache/maven/maven-model/2.0.9/maven-model-2.0.9.jar",
1430+ "sha1": "9fb844625928dd992842e180853fbb2b197c9a9d"
1431+ },
1432+ {
1433+ "path": "org/apache/maven/maven-model/2.0.9/maven-model-2.0.9.pom",
1434+ "sha1": "0978fe1857f847436fd3c454d25161e26fb2d5ec"
1435+ },
1436+ {
1437+ "path": "org/apache/maven/maven-model/2.2.0/maven-model-2.2.0.pom",
1438+ "sha1": "826351ed94e42205e27410676351e83486ec5bb2"
1439+ },
1440+ {
1441+ "path": "org/apache/maven/maven-model/2.2.1/maven-model-2.2.1.jar",
1442+ "sha1": "c0a1c17436ec3ff5a56207c031d82277b4250a29"
1443+ },
1444+ {
1445+ "path": "org/apache/maven/maven-model/2.2.1/maven-model-2.2.1.pom",
1446+ "sha1": "548a7e6354c1bc4a49dbec6bd17b4f8e9310201b"
1447+ },
1448+ {
1449+ "path": "org/apache/maven/maven-model/3.0/maven-model-3.0.jar",
1450+ "sha1": "24ce598c94a78341c42556fe9192dad6a2822405"
1451+ },
1452+ {
1453+ "path": "org/apache/maven/maven-model/3.0/maven-model-3.0.pom",
1454+ "sha1": "3aa89da7792286192b860c58841b3907364d33a8"
1455+ },
1456+ {
1457+ "path": "org/apache/maven/maven-model/3.3.9/maven-model-3.3.9.jar",
1458+ "sha1": "6efde8cbcb4de4c47f7e9c2a3ab2806022b5c70f"
1459+ },
1460+ {
1461+ "path": "org/apache/maven/maven-model/3.3.9/maven-model-3.3.9.pom",
1462+ "sha1": "4435603380715177bdda01d89c62ee69fd58dfc1"
1463+ },
1464+ {
1465+ "path": "org/apache/maven/maven-monitor/2.0.6/maven-monitor-2.0.6.jar",
1466+ "sha1": "ab682e67281bb025980181c83acbcad19042a342"
1467+ },
1468+ {
1469+ "path": "org/apache/maven/maven-monitor/2.0.6/maven-monitor-2.0.6.pom",
1470+ "sha1": "7ed6529eefa74ca263b65a7c20adf65af5bacdff"
1471+ },
1472+ {
1473+ "path": "org/apache/maven/maven-monitor/2.0.9/maven-monitor-2.0.9.jar",
1474+ "sha1": "ae55264ab9ffbbfdba08c8c7853bbe4a2dd32e8a"
1475+ },
1476+ {
1477+ "path": "org/apache/maven/maven-monitor/2.0.9/maven-monitor-2.0.9.pom",
1478+ "sha1": "872e92b9f9ebed4761ea469c2c385f2ffcd6a589"
1479+ },
1480+ {
1481+ "path": "org/apache/maven/maven-monitor/2.2.1/maven-monitor-2.2.1.jar",
1482+ "sha1": "afc57c3a1368cd34caccb638e00523701f398c20"
1483+ },
1484+ {
1485+ "path": "org/apache/maven/maven-monitor/2.2.1/maven-monitor-2.2.1.pom",
1486+ "sha1": "421fcf473a51d9695d8dfe4f8e977ae38087f2ae"
1487+ },
1488+ {
1489+ "path": "org/apache/maven/maven-parent/10/maven-parent-10.pom",
1490+ "sha1": "281aafa31dfa9544070448ea8f353434f53267e4"
1491+ },
1492+ {
1493+ "path": "org/apache/maven/maven-parent/11/maven-parent-11.pom",
1494+ "sha1": "4bb80173fa4979737840fda012af86f5beabf1bc"
1495+ },
1496+ {
1497+ "path": "org/apache/maven/maven-parent/13/maven-parent-13.pom",
1498+ "sha1": "743843d9973c083b7755e4a26a9c2ac369608ab5"
1499+ },
1500+ {
1501+ "path": "org/apache/maven/maven-parent/15/maven-parent-15.pom",
1502+ "sha1": "63d5a76e7f9d3c6d7870bde13438856ef5300336"
1503+ },
1504+ {
1505+ "path": "org/apache/maven/maven-parent/16/maven-parent-16.pom",
1506+ "sha1": "00fed95187c0c9bfd13c08a858cb6f00245a3fa9"
1507+ },
1508+ {
1509+ "path": "org/apache/maven/maven-parent/21/maven-parent-21.pom",
1510+ "sha1": "0ecebf1043d9c7bdd3d32a4184ad4ef9ad3ea744"
1511+ },
1512+ {
1513+ "path": "org/apache/maven/maven-parent/22/maven-parent-22.pom",
1514+ "sha1": "b8b69066f9f1c388a977669871df9b66782f751a"
1515+ },
1516+ {
1517+ "path": "org/apache/maven/maven-parent/23/maven-parent-23.pom",
1518+ "sha1": "f92ae4baba6616609a29f6287626ee3f50ed7d6e"
1519+ },
1520+ {
1521+ "path": "org/apache/maven/maven-parent/24/maven-parent-24.pom",
1522+ "sha1": "277cf98c25de4d7512aa6403635810c1018e82b0"
1523+ },
1524+ {
1525+ "path": "org/apache/maven/maven-parent/27/maven-parent-27.pom",
1526+ "sha1": "2672c73b6189bb9ff437ba94ac7f62975e1257dd"
1527+ },
1528+ {
1529+ "path": "org/apache/maven/maven-parent/30/maven-parent-30.pom",
1530+ "sha1": "c3b2d24677a5f694e069b8210e9793a88c9d28b5"
1531+ },
1532+ {
1533+ "path": "org/apache/maven/maven-parent/31/maven-parent-31.pom",
1534+ "sha1": "e773af8e851de63461222f3a26d37e4619431e03"
1535+ },
1536+ {
1537+ "path": "org/apache/maven/maven-parent/33/maven-parent-33.pom",
1538+ "sha1": "9dd736089b07fa56da1259c87a825a097ba0278c"
1539+ },
1540+ {
1541+ "path": "org/apache/maven/maven-parent/34/maven-parent-34.pom",
1542+ "sha1": "d03d96b2f4ee06300faa9731b0fa71feeec5a8ef"
1543+ },
1544+ {
1545+ "path": "org/apache/maven/maven-parent/5/maven-parent-5.pom",
1546+ "sha1": "5c1ab38decaca1ccd08294aeab135047ebbae00d"
1547+ },
1548+ {
1549+ "path": "org/apache/maven/maven-parent/6/maven-parent-6.pom",
1550+ "sha1": "e9c3dcf052c26ac7340fbd7a03a751e482855330"
1551+ },
1552+ {
1553+ "path": "org/apache/maven/maven-parent/7/maven-parent-7.pom",
1554+ "sha1": "2426103263cbaf5519433f16bd98cdc31870a10a"
1555+ },
1556+ {
1557+ "path": "org/apache/maven/maven-parent/8/maven-parent-8.pom",
1558+ "sha1": "6f92a85ec401422bfc6572759a0bab2ff5df525e"
1559+ },
1560+ {
1561+ "path": "org/apache/maven/maven-parent/9/maven-parent-9.pom",
1562+ "sha1": "a7d098bde368f683c2b51475a903a1e74b61ba32"
1563+ },
1564+ {
1565+ "path": "org/apache/maven/maven-plugin-api/2.0.6/maven-plugin-api-2.0.6.jar",
1566+ "sha1": "52b32fd980c8ead7a3858d057330bda1ace72d9d"
1567+ },
1568+ {
1569+ "path": "org/apache/maven/maven-plugin-api/2.0.6/maven-plugin-api-2.0.6.pom",
1570+ "sha1": "3af72b052dfefb73ecfae742613012b5396c8863"
1571+ },
1572+ {
1573+ "path": "org/apache/maven/maven-plugin-api/2.0.8/maven-plugin-api-2.0.8.pom",
1574+ "sha1": "df49abd86bcf9fd7a624562a7285049ebdd2f00e"
1575+ },
1576+ {
1577+ "path": "org/apache/maven/maven-plugin-api/2.0.9/maven-plugin-api-2.0.9.jar",
1578+ "sha1": "8b8cae9daa688fdb57995c6835a3e24475d554c0"
1579+ },
1580+ {
1581+ "path": "org/apache/maven/maven-plugin-api/2.0.9/maven-plugin-api-2.0.9.pom",
1582+ "sha1": "4f6c3d5d50d1e22dea74629b3c52e22b30b6cbbd"
1583+ },
1584+ {
1585+ "path": "org/apache/maven/maven-plugin-api/2.2.1/maven-plugin-api-2.2.1.jar",
1586+ "sha1": "d60c36b60f760e0b5b87dd0c6311f93a72dc4585"
1587+ },
1588+ {
1589+ "path": "org/apache/maven/maven-plugin-api/2.2.1/maven-plugin-api-2.2.1.pom",
1590+ "sha1": "29a30b7c8180601523293fd61b00fcb298d32230"
1591+ },
1592+ {
1593+ "path": "org/apache/maven/maven-plugin-api/3.0/maven-plugin-api-3.0.jar",
1594+ "sha1": "98f886f59bb0e69f8e86cdc082e69f2f4c13d648"
1595+ },
1596+ {
1597+ "path": "org/apache/maven/maven-plugin-api/3.0/maven-plugin-api-3.0.pom",
1598+ "sha1": "9627e130b4f516945f0db03119dbafb86f168026"
1599+ },
1600+ {
1601+ "path": "org/apache/maven/maven-plugin-api/3.3.9/maven-plugin-api-3.3.9.jar",
1602+ "sha1": "aa706ea7ca23776861b4eb2cea97cf345e791496"
1603+ },
1604+ {
1605+ "path": "org/apache/maven/maven-plugin-api/3.3.9/maven-plugin-api-3.3.9.pom",
1606+ "sha1": "9a2b35a6e916b9fea2a6afa9cd5238efd3d0c407"
1607+ },
1608+ {
1609+ "path": "org/apache/maven/maven-plugin-descriptor/2.0.6/maven-plugin-descriptor-2.0.6.jar",
1610+ "sha1": "30a00f4ef12d3901c4f842de99e9363e3743245f"
1611+ },
1612+ {
1613+ "path": "org/apache/maven/maven-plugin-descriptor/2.0.6/maven-plugin-descriptor-2.0.6.pom",
1614+ "sha1": "c03fb59f559651730a98907d4acf65e6ffb886d6"
1615+ },
1616+ {
1617+ "path": "org/apache/maven/maven-plugin-descriptor/2.0.9/maven-plugin-descriptor-2.0.9.jar",
1618+ "sha1": "10443d038cd57feb4a027e7dfe09bed0925a1953"
1619+ },
1620+ {
1621+ "path": "org/apache/maven/maven-plugin-descriptor/2.0.9/maven-plugin-descriptor-2.0.9.pom",
1622+ "sha1": "2752f80f21bd62796600c66859406a08a587c2d9"
1623+ },
1624+ {
1625+ "path": "org/apache/maven/maven-plugin-descriptor/2.2.1/maven-plugin-descriptor-2.2.1.jar",
1626+ "sha1": "68d20ae3c40c4664dc52be90338af796db7ffb32"
1627+ },
1628+ {
1629+ "path": "org/apache/maven/maven-plugin-descriptor/2.2.1/maven-plugin-descriptor-2.2.1.pom",
1630+ "sha1": "020c06240db8c2f9bcf8450414ef040becef16e0"
1631+ },
1632+ {
1633+ "path": "org/apache/maven/maven-plugin-parameter-documenter/2.0.6/maven-plugin-parameter-documenter-2.0.6.jar",
1634+ "sha1": "df6fa6c4adb313cb8937ffae96368bec1fd5d13d"
1635+ },
1636+ {
1637+ "path": "org/apache/maven/maven-plugin-parameter-documenter/2.0.6/maven-plugin-parameter-documenter-2.0.6.pom",
1638+ "sha1": "c6403fbdb781a3d47a771656054defe1173ce486"
1639+ },
1640+ {
1641+ "path": "org/apache/maven/maven-plugin-parameter-documenter/2.0.9/maven-plugin-parameter-documenter-2.0.9.jar",
1642+ "sha1": "f481e2677384f6a0ab96633567d736e70657e042"
1643+ },
1644+ {
1645+ "path": "org/apache/maven/maven-plugin-parameter-documenter/2.0.9/maven-plugin-parameter-documenter-2.0.9.pom",
1646+ "sha1": "a575e74bbf8402a2371034d3a128d214c4cee060"
1647+ },
1648+ {
1649+ "path": "org/apache/maven/maven-plugin-parameter-documenter/2.2.1/maven-plugin-parameter-documenter-2.2.1.jar",
1650+ "sha1": "1a117baac49437fc5a6fcd9f18f779e6bad4207e"
1651+ },
1652+ {
1653+ "path": "org/apache/maven/maven-plugin-parameter-documenter/2.2.1/maven-plugin-parameter-documenter-2.2.1.pom",
1654+ "sha1": "8eb54f97405512e83f680f29ef6163f5ef082acb"
1655+ },
1656+ {
1657+ "path": "org/apache/maven/maven-plugin-registry/2.0.6/maven-plugin-registry-2.0.6.jar",
1658+ "sha1": "4242ec8629b4797387751379f57e72cb718aac7a"
1659+ },
1660+ {
1661+ "path": "org/apache/maven/maven-plugin-registry/2.0.6/maven-plugin-registry-2.0.6.pom",
1662+ "sha1": "2e13beea3b3511c6075c60384d9e7fad18efbcdf"
1663+ },
1664+ {
1665+ "path": "org/apache/maven/maven-plugin-registry/2.0.8/maven-plugin-registry-2.0.8.pom",
1666+ "sha1": "8f64ad448251c2c6007e609088bb7aa45ff337c5"
1667+ },
1668+ {
1669+ "path": "org/apache/maven/maven-plugin-registry/2.0.9/maven-plugin-registry-2.0.9.jar",
1670+ "sha1": "a7172a87a7cb901cf6df4df9fd89a3c2d3f8a770"
1671+ },
1672+ {
1673+ "path": "org/apache/maven/maven-plugin-registry/2.0.9/maven-plugin-registry-2.0.9.pom",
1674+ "sha1": "403ed44092f56e1ebab891f37c69d61936c5c4da"
1675+ },
1676+ {
1677+ "path": "org/apache/maven/maven-plugin-registry/2.2.0/maven-plugin-registry-2.2.0.pom",
1678+ "sha1": "a28f479f5a2334f4018fd6812a6da2652a11d858"
1679+ },
1680+ {
1681+ "path": "org/apache/maven/maven-plugin-registry/2.2.1/maven-plugin-registry-2.2.1.jar",
1682+ "sha1": "72a24b7775649af78f3986b5aa7eb354b9674cfd"
1683+ },
1684+ {
1685+ "path": "org/apache/maven/maven-plugin-registry/2.2.1/maven-plugin-registry-2.2.1.pom",
1686+ "sha1": "c3575ac9ad32638af33d88829453bdc902ea8711"
1687+ },
1688+ {
1689+ "path": "org/apache/maven/maven-profile/2.0.5/maven-profile-2.0.5.pom",
1690+ "sha1": "d16b97a0ac60bf526c8a727dfa549a43ac57e519"
1691+ },
1692+ {
1693+ "path": "org/apache/maven/maven-profile/2.0.6/maven-profile-2.0.6.jar",
1694+ "sha1": "f03cd3820d2b4d60b93ccd17a1c14e8eeef63f79"
1695+ },
1696+ {
1697+ "path": "org/apache/maven/maven-profile/2.0.6/maven-profile-2.0.6.pom",
1698+ "sha1": "12d0d8217e613b9cb487c1d1d0db744a4f588528"
1699+ },
1700+ {
1701+ "path": "org/apache/maven/maven-profile/2.0.8/maven-profile-2.0.8.pom",
1702+ "sha1": "34de742e38173bc6b4bc921ad79567c282f880ab"
1703+ },
1704+ {
1705+ "path": "org/apache/maven/maven-profile/2.0.9/maven-profile-2.0.9.jar",
1706+ "sha1": "0b9b02df9134bff9edb4f4e1624243d005895234"
1707+ },
1708+ {
1709+ "path": "org/apache/maven/maven-profile/2.0.9/maven-profile-2.0.9.pom",
1710+ "sha1": "616ca5d9ab345e415c6e3f5f75ea24a952690ac0"
1711+ },
1712+ {
1713+ "path": "org/apache/maven/maven-profile/2.2.0/maven-profile-2.2.0.pom",
1714+ "sha1": "740bce07af0b724e8e79e62493b537e190d14c1f"
1715+ },
1716+ {
1717+ "path": "org/apache/maven/maven-profile/2.2.1/maven-profile-2.2.1.jar",
1718+ "sha1": "3950071587027e5086e9c395574a60650c432738"
1719+ },
1720+ {
1721+ "path": "org/apache/maven/maven-profile/2.2.1/maven-profile-2.2.1.pom",
1722+ "sha1": "075b47a5262cae02c228137399b8247e50a43284"
1723+ },
1724+ {
1725+ "path": "org/apache/maven/maven-project/2.0.5/maven-project-2.0.5.pom",
1726+ "sha1": "f8e28bec122e2092e91660758ede22e1f78744ee"
1727+ },
1728+ {
1729+ "path": "org/apache/maven/maven-project/2.0.6/maven-project-2.0.6.jar",
1730+ "sha1": "c0df764cd8f5bac660bfa53fa97fdd53663ee308"
1731+ },
1732+ {
1733+ "path": "org/apache/maven/maven-project/2.0.6/maven-project-2.0.6.pom",
1734+ "sha1": "28e9f98ae3688d8831052283b2d65bd18295a7f5"
1735+ },
1736+ {
1737+ "path": "org/apache/maven/maven-project/2.0.8/maven-project-2.0.8.pom",
1738+ "sha1": "13398a071f2094acc11add38afc85f75a3faac33"
1739+ },
1740+ {
1741+ "path": "org/apache/maven/maven-project/2.0.9/maven-project-2.0.9.jar",
1742+ "sha1": "30ec37813df5a212888a1f3df0b27497ecef4ad8"
1743+ },
1744+ {
1745+ "path": "org/apache/maven/maven-project/2.0.9/maven-project-2.0.9.pom",
1746+ "sha1": "152cb93838c431848f31cd5a7a7a11b98c57135e"
1747+ },
1748+ {
1749+ "path": "org/apache/maven/maven-project/2.2.0/maven-project-2.2.0.pom",
1750+ "sha1": "bce50c677b7219221db29b87470b6ba605ef0d3f"
1751+ },
1752+ {
1753+ "path": "org/apache/maven/maven-project/2.2.1/maven-project-2.2.1.jar",
1754+ "sha1": "8239e98c16f641d55a4ad0e0bab0aee3aff8933f"
1755+ },
1756+ {
1757+ "path": "org/apache/maven/maven-project/2.2.1/maven-project-2.2.1.pom",
1758+ "sha1": "d96e4545b4700ac177430b5189c3f2aa54f62ca1"
1759+ },
1760+ {
1761+ "path": "org/apache/maven/maven-repository-metadata/2.0.2/maven-repository-metadata-2.0.2.pom",
1762+ "sha1": "f731304626897c68836461f0df5134f26aeddcf1"
1763+ },
1764+ {
1765+ "path": "org/apache/maven/maven-repository-metadata/2.0.5/maven-repository-metadata-2.0.5.pom",
1766+ "sha1": "64b711de2206859a37333e015c24451546278123"
1767+ },
1768+ {
1769+ "path": "org/apache/maven/maven-repository-metadata/2.0.6/maven-repository-metadata-2.0.6.jar",
1770+ "sha1": "ae64379396d2eba33616ce1e0a458c3a744b317b"
1771+ },
1772+ {
1773+ "path": "org/apache/maven/maven-repository-metadata/2.0.6/maven-repository-metadata-2.0.6.pom",
1774+ "sha1": "bdcd11054562df6124286aaf252ae8f256879e26"
1775+ },
1776+ {
1777+ "path": "org/apache/maven/maven-repository-metadata/2.0.8/maven-repository-metadata-2.0.8.pom",
1778+ "sha1": "741cf565a37d838eb7bebbb3d38a8293835b6cd5"
1779+ },
1780+ {
1781+ "path": "org/apache/maven/maven-repository-metadata/2.0.9/maven-repository-metadata-2.0.9.jar",
1782+ "sha1": "dd79022a827b1d577865d5c97f8ad0c7d6b067b7"
1783+ },
1784+ {
1785+ "path": "org/apache/maven/maven-repository-metadata/2.0.9/maven-repository-metadata-2.0.9.pom",
1786+ "sha1": "dc5dac36e8c773d8645a681b71b3d80a3e3b8916"
1787+ },
1788+ {
1789+ "path": "org/apache/maven/maven-repository-metadata/2.2.0/maven-repository-metadata-2.2.0.pom",
1790+ "sha1": "7805801e5b7d9eafeb3baf07e864650a62991192"
1791+ },
1792+ {
1793+ "path": "org/apache/maven/maven-repository-metadata/2.2.1/maven-repository-metadata-2.2.1.jar",
1794+ "sha1": "98f0c07fcf1eeb213bef8d9316a9935184084b06"
1795+ },
1796+ {
1797+ "path": "org/apache/maven/maven-repository-metadata/2.2.1/maven-repository-metadata-2.2.1.pom",
1798+ "sha1": "415f88d96ea04b0fcef38c50123da1ccc2be49d2"
1799+ },
1800+ {
1801+ "path": "org/apache/maven/maven-repository-metadata/3.0/maven-repository-metadata-3.0.jar",
1802+ "sha1": "e3c41f7565b1e189ff7a312796b9d2c470c09a8b"
1803+ },
1804+ {
1805+ "path": "org/apache/maven/maven-repository-metadata/3.0/maven-repository-metadata-3.0.pom",
1806+ "sha1": "5126010cefcb80ed5dc6eb066541b546dbdbc971"
1807+ },
1808+ {
1809+ "path": "org/apache/maven/maven-settings-builder/3.0/maven-settings-builder-3.0.jar",
1810+ "sha1": "08234c1bdf7a9a28c671b0abf11f8adaa66440cd"
1811+ },
1812+ {
1813+ "path": "org/apache/maven/maven-settings-builder/3.0/maven-settings-builder-3.0.pom",
1814+ "sha1": "69a41566b573bda12bd2bb7dcb64d30da834cb9c"
1815+ },
1816+ {
1817+ "path": "org/apache/maven/maven-settings/2.0.5/maven-settings-2.0.5.pom",
1818+ "sha1": "87aabc89ef7581c3e8119acf01280a701f446f37"
1819+ },
1820+ {
1821+ "path": "org/apache/maven/maven-settings/2.0.6/maven-settings-2.0.6.jar",
1822+ "sha1": "5da16cf9def50e3a352cd7e8923a49ebd72003b8"
1823+ },
1824+ {
1825+ "path": "org/apache/maven/maven-settings/2.0.6/maven-settings-2.0.6.pom",
1826+ "sha1": "6e8ca6b7fce58a28d2b73774fe277593af14d82a"
1827+ },
1828+ {
1829+ "path": "org/apache/maven/maven-settings/2.0.8/maven-settings-2.0.8.pom",
1830+ "sha1": "2516e8bf74885aef0561c2132b185d882253cb19"
1831+ },
1832+ {
1833+ "path": "org/apache/maven/maven-settings/2.0.9/maven-settings-2.0.9.jar",
1834+ "sha1": "ab8d338c00fab0db29af358ab0676c3c02d7329f"
1835+ },
1836+ {
1837+ "path": "org/apache/maven/maven-settings/2.0.9/maven-settings-2.0.9.pom",
1838+ "sha1": "f1fde243f26152cc66f7f1d6b4e3bb19d39d6847"
1839+ },
1840+ {
1841+ "path": "org/apache/maven/maven-settings/2.2.0/maven-settings-2.2.0.pom",
1842+ "sha1": "2cd4b74ac9ee7d8213fa8b4bb585c36e3dc1e17c"
1843+ },
1844+ {
1845+ "path": "org/apache/maven/maven-settings/2.2.1/maven-settings-2.2.1.jar",
1846+ "sha1": "2236ffe71fa5f78ce42b0f5fc22c54ed45f14294"
1847+ },
1848+ {
1849+ "path": "org/apache/maven/maven-settings/2.2.1/maven-settings-2.2.1.pom",
1850+ "sha1": "d54135b84370b3b0b70d84ffbb4ddf161c303d56"
1851+ },
1852+ {
1853+ "path": "org/apache/maven/maven-settings/3.0/maven-settings-3.0.jar",
1854+ "sha1": "8ee129adae535dd610f2dc952fddce68ac42fd86"
1855+ },
1856+ {
1857+ "path": "org/apache/maven/maven-settings/3.0/maven-settings-3.0.pom",
1858+ "sha1": "efc9c618ca5b82f76d1894977482069fe0e4565a"
1859+ },
1860+ {
1861+ "path": "org/apache/maven/maven-toolchain/2.2.1/maven-toolchain-2.2.1.jar",
1862+ "sha1": "0be589179cfbbad11e48572bf1a28e3490c7b197"
1863+ },
1864+ {
1865+ "path": "org/apache/maven/maven-toolchain/2.2.1/maven-toolchain-2.2.1.pom",
1866+ "sha1": "ef19c9782d233f4515cf83b4208dd04731ed8989"
1867+ },
1868+ {
1869+ "path": "org/apache/maven/maven/2.0.2/maven-2.0.2.pom",
1870+ "sha1": "816e22beec3ee5c4a344959625a824bb6202daeb"
1871+ },
1872+ {
1873+ "path": "org/apache/maven/maven/2.0.5/maven-2.0.5.pom",
1874+ "sha1": "9801e4423479367099ad4507c51c4f7f5b19bc6f"
1875+ },
1876+ {
1877+ "path": "org/apache/maven/maven/2.0.6/maven-2.0.6.pom",
1878+ "sha1": "1991be0ed3e1820e135201406d5acabf8c08d426"
1879+ },
1880+ {
1881+ "path": "org/apache/maven/maven/2.0.8/maven-2.0.8.pom",
1882+ "sha1": "0b6bdac7d11f0fc5c4c4bb0f336323f7b86cddc0"
1883+ },
1884+ {
1885+ "path": "org/apache/maven/maven/2.0.9/maven-2.0.9.pom",
1886+ "sha1": "696e3d1eaf254c63347613715faa31e5eecb282d"
1887+ },
1888+ {
1889+ "path": "org/apache/maven/maven/2.2.0/maven-2.2.0.pom",
1890+ "sha1": "c5bb0fda80306d0d27b3221d511c5032c95b27fa"
1891+ },
1892+ {
1893+ "path": "org/apache/maven/maven/2.2.1/maven-2.2.1.pom",
1894+ "sha1": "7bc311044fbacb404de025b76feefa3567f0e5d7"
1895+ },
1896+ {
1897+ "path": "org/apache/maven/maven/3.0/maven-3.0.pom",
1898+ "sha1": "30c961aaf964aadcc028102ebe03d1afff324ec0"
1899+ },
1900+ {
1901+ "path": "org/apache/maven/maven/3.3.9/maven-3.3.9.pom",
1902+ "sha1": "6e8c698e365e1a895770db9eec7bd3e544e1464f"
1903+ },
1904+ {
1905+ "path": "org/apache/maven/plugin-tools/maven-plugin-annotations/3.5.2/maven-plugin-annotations-3.5.2.jar",
1906+ "sha1": "958c81789d4cc52e7f83ede3168633c0b03ea2de"
1907+ },
1908+ {
1909+ "path": "org/apache/maven/plugin-tools/maven-plugin-annotations/3.5.2/maven-plugin-annotations-3.5.2.pom",
1910+ "sha1": "263f39d1cb915beaa94497d2b4b6ec94ca5b1291"
1911+ },
1912+ {
1913+ "path": "org/apache/maven/plugin-tools/maven-plugin-tools/3.5.2/maven-plugin-tools-3.5.2.pom",
1914+ "sha1": "7c1b14adca1eef5063248cb8078b160e48c3a969"
1915+ },
1916+ {
1917+ "path": "org/apache/maven/plugins/maven-antrun-plugin/1.3/maven-antrun-plugin-1.3.jar",
1918+ "sha1": "a1481166aa4a16c3a37e65f40847e238cc878709"
1919+ },
1920+ {
1921+ "path": "org/apache/maven/plugins/maven-antrun-plugin/1.3/maven-antrun-plugin-1.3.pom",
1922+ "sha1": "338231886cec6cd6853b3a3628b9fe8fc10c6eb5"
1923+ },
1924+ {
1925+ "path": "org/apache/maven/plugins/maven-assembly-plugin/2.2-beta-5/maven-assembly-plugin-2.2-beta-5.jar",
1926+ "sha1": "b1fd2e4dea47cb9c2858d26ad0aa608b802d34e2"
1927+ },
1928+ {
1929+ "path": "org/apache/maven/plugins/maven-assembly-plugin/2.2-beta-5/maven-assembly-plugin-2.2-beta-5.pom",
1930+ "sha1": "e7faf80b1d8086bd26dc2c67f4e0252b8d47df44"
1931+ },
1932+ {
1933+ "path": "org/apache/maven/plugins/maven-clean-plugin/2.5/maven-clean-plugin-2.5.jar",
1934+ "sha1": "75653decaefa85ca8114ff3a4f869bb2ee6d605d"
1935+ },
1936+ {
1937+ "path": "org/apache/maven/plugins/maven-clean-plugin/2.5/maven-clean-plugin-2.5.pom",
1938+ "sha1": "8571a1cd21bed4fe28656c3303526fa7d1e582ad"
1939+ },
1940+ {
1941+ "path": "org/apache/maven/plugins/maven-compiler-plugin/3.8.1/maven-compiler-plugin-3.8.1.jar",
1942+ "sha1": "be834db00dbace3d7fd08a6e0e96ab5e4af45f99"
1943+ },
1944+ {
1945+ "path": "org/apache/maven/plugins/maven-compiler-plugin/3.8.1/maven-compiler-plugin-3.8.1.pom",
1946+ "sha1": "96021d81e9ecaa27aadb861c681840a768ea502b"
1947+ },
1948+ {
1949+ "path": "org/apache/maven/plugins/maven-dependency-plugin/2.8/maven-dependency-plugin-2.8.jar",
1950+ "sha1": "04c8dedf3d9b2a3f45f3daa93e11ca547d2063ca"
1951+ },
1952+ {
1953+ "path": "org/apache/maven/plugins/maven-dependency-plugin/2.8/maven-dependency-plugin-2.8.pom",
1954+ "sha1": "df6ec1e4d0850f1b58c5432e7eb103e87fa197ec"
1955+ },
1956+ {
1957+ "path": "org/apache/maven/plugins/maven-deploy-plugin/2.8.2/maven-deploy-plugin-2.8.2.jar",
1958+ "sha1": "3c2d83ecd387e9843142ae92a0439792c1500319"
1959+ },
1960+ {
1961+ "path": "org/apache/maven/plugins/maven-deploy-plugin/2.8.2/maven-deploy-plugin-2.8.2.pom",
1962+ "sha1": "7feb36f26137084a8a8654d83efcbd8fb3d8a0a1"
1963+ },
1964+ {
1965+ "path": "org/apache/maven/plugins/maven-install-plugin/2.4/maven-install-plugin-2.4.jar",
1966+ "sha1": "9d1316166fe4c313f56276935e08df11f45267c2"
1967+ },
1968+ {
1969+ "path": "org/apache/maven/plugins/maven-install-plugin/2.4/maven-install-plugin-2.4.pom",
1970+ "sha1": "a94328f3fcee1cebefa3d1224caa0050682da487"
1971+ },
1972+ {
1973+ "path": "org/apache/maven/plugins/maven-jar-plugin/2.4/maven-jar-plugin-2.4.jar",
1974+ "sha1": "e3200bcf357b5c5e26df072d27df160546bb079a"
1975+ },
1976+ {
1977+ "path": "org/apache/maven/plugins/maven-jar-plugin/2.4/maven-jar-plugin-2.4.pom",
1978+ "sha1": "ae9d54d974e163f260f89ecea8ff6d55e4b0963e"
1979+ },
1980+ {
1981+ "path": "org/apache/maven/plugins/maven-plugins/12/maven-plugins-12.pom",
1982+ "sha1": "1adf3bec812d8db9c1f18303aa22325ec2fb61ca"
1983+ },
1984+ {
1985+ "path": "org/apache/maven/plugins/maven-plugins/16/maven-plugins-16.pom",
1986+ "sha1": "b5c0ca0bf4e73800f888cee77741bc1fa9c8ed78"
1987+ },
1988+ {
1989+ "path": "org/apache/maven/plugins/maven-plugins/22/maven-plugins-22.pom",
1990+ "sha1": "beff44ae4eff1e5c79c01972083cd11fa6982462"
1991+ },
1992+ {
1993+ "path": "org/apache/maven/plugins/maven-plugins/23/maven-plugins-23.pom",
1994+ "sha1": "d40d68ba1f88d8e9b0040f175a6ff41928abd5e7"
1995+ },
1996+ {
1997+ "path": "org/apache/maven/plugins/maven-plugins/24/maven-plugins-24.pom",
1998+ "sha1": "91e68408f2d1774c5f39c0c4cd56a8b83e47c67f"
1999+ },
2000+ {
2001+ "path": "org/apache/maven/plugins/maven-plugins/25/maven-plugins-25.pom",
2002+ "sha1": "8f4f05aaf87c858d2323b3a8fcf37d0fe00ecc75"
2003+ },
2004+ {
2005+ "path": "org/apache/maven/plugins/maven-plugins/33/maven-plugins-33.pom",
2006+ "sha1": "1492c1ec367964ea0a088d128d13b1df4529c8ae"
2007+ },
2008+ {
2009+ "path": "org/apache/maven/plugins/maven-plugins/34/maven-plugins-34.pom",
2010+ "sha1": "039027f0abac25deccfc21486550731fa5f55858"
2011+ },
2012+ {
2013+ "path": "org/apache/maven/plugins/maven-release-plugin/2.5.3/maven-release-plugin-2.5.3.jar",
2014+ "sha1": "4a85ece12021a247251b9a28cf4d88b2ee80a17d"
2015+ },
2016+ {
2017+ "path": "org/apache/maven/plugins/maven-release-plugin/2.5.3/maven-release-plugin-2.5.3.pom",
2018+ "sha1": "975a495019c29e2fd12cc81d83aa88b4eb14a0fe"
2019+ },
2020+ {
2021+ "path": "org/apache/maven/plugins/maven-resources-plugin/2.6/maven-resources-plugin-2.6.jar",
2022+ "sha1": "dd093ff6a4b680eae7ae83b5ab04310249fc6590"
2023+ },
2024+ {
2025+ "path": "org/apache/maven/plugins/maven-resources-plugin/2.6/maven-resources-plugin-2.6.pom",
2026+ "sha1": "5db5c3a879f31e8de7b580c79a52b245454c4620"
2027+ },
2028+ {
2029+ "path": "org/apache/maven/plugins/maven-shade-plugin/3.2.4/maven-shade-plugin-3.2.4.jar",
2030+ "sha1": "4cb43b86676649691a3945872998b5514ed40505"
2031+ },
2032+ {
2033+ "path": "org/apache/maven/plugins/maven-shade-plugin/3.2.4/maven-shade-plugin-3.2.4.pom",
2034+ "sha1": "619e08e6eddb99e43a0ae42821ac83571ce9f787"
2035+ },
2036+ {
2037+ "path": "org/apache/maven/plugins/maven-site-plugin/3.3/maven-site-plugin-3.3.jar",
2038+ "sha1": "77ba1752b1ac4c4339d6f11554800960a56a4ae1"
2039+ },
2040+ {
2041+ "path": "org/apache/maven/plugins/maven-site-plugin/3.3/maven-site-plugin-3.3.pom",
2042+ "sha1": "e790e7e93471cf9245706d76747f4653dd58c0e7"
2043+ },
2044+ {
2045+ "path": "org/apache/maven/plugins/maven-surefire-plugin/2.22.2/maven-surefire-plugin-2.22.2.jar",
2046+ "sha1": "63d1dd017bfecc64a7b68b964e39e8d9f8f11a14"
2047+ },
2048+ {
2049+ "path": "org/apache/maven/plugins/maven-surefire-plugin/2.22.2/maven-surefire-plugin-2.22.2.pom",
2050+ "sha1": "f0bfc47221f365d6812e6c4091227f6425268980"
2051+ },
2052+ {
2053+ "path": "org/apache/maven/release/maven-release-manager/2.5.3/maven-release-manager-2.5.3.jar",
2054+ "sha1": "65485d8c11cee5f06ef70615a7e0a516ee055f1a"
2055+ },
2056+ {
2057+ "path": "org/apache/maven/release/maven-release/2.5.3/maven-release-2.5.3.pom",
2058+ "sha1": "43ecfac1cf706ce9e60b8742c3ef36029158e61a"
2059+ },
2060+ {
2061+ "path": "org/apache/maven/reporting/maven-reporting-api/2.0.6/maven-reporting-api-2.0.6.jar",
2062+ "sha1": "29ec352c90968c345b628be6c40ddfb5ec7010a8"
2063+ },
2064+ {
2065+ "path": "org/apache/maven/reporting/maven-reporting-api/2.0.6/maven-reporting-api-2.0.6.pom",
2066+ "sha1": "8d8037467cc092dbaf1ca8b513172e2a893b5b9b"
2067+ },
2068+ {
2069+ "path": "org/apache/maven/reporting/maven-reporting-api/2.0.9/maven-reporting-api-2.0.9.pom",
2070+ "sha1": "bc210876e266e2f3153e96832cbdc5cd3ba53cba"
2071+ },
2072+ {
2073+ "path": "org/apache/maven/reporting/maven-reporting-api/3.0/maven-reporting-api-3.0.jar",
2074+ "sha1": "b2541dd07d08cd5eff9bd4554a2ad6a4198e2dfe"
2075+ },
2076+ {
2077+ "path": "org/apache/maven/reporting/maven-reporting-api/3.0/maven-reporting-api-3.0.pom",
2078+ "sha1": "eca7bd81ad86e6d8a978f37e1d077fee5c59d41e"
2079+ },
2080+ {
2081+ "path": "org/apache/maven/reporting/maven-reporting-exec/1.1/maven-reporting-exec-1.1.jar",
2082+ "sha1": "6e584f7a77d08716e703aae223809e22cbba3af7"
2083+ },
2084+ {
2085+ "path": "org/apache/maven/reporting/maven-reporting-impl/2.0.5/maven-reporting-impl-2.0.5.jar",
2086+ "sha1": "a9830b74eaa96dd67a89d82f13a735252cc1c725"
2087+ },
2088+ {
2089+ "path": "org/apache/maven/reporting/maven-reporting-impl/2.0.5/maven-reporting-impl-2.0.5.pom",
2090+ "sha1": "2308b1d114a8ee45bf4131806c02f26078646a72"
2091+ },
2092+ {
2093+ "path": "org/apache/maven/reporting/maven-reporting/2.0.6/maven-reporting-2.0.6.pom",
2094+ "sha1": "0257fe61312283ef58817edf197e9c90db0bba25"
2095+ },
2096+ {
2097+ "path": "org/apache/maven/reporting/maven-reporting/2.0.9/maven-reporting-2.0.9.pom",
2098+ "sha1": "92fc48457601be497488cc316bc3617326977a24"
2099+ },
2100+ {
2101+ "path": "org/apache/maven/scm/maven-scm-api/1.9.4/maven-scm-api-1.9.4.jar",
2102+ "sha1": "20007a3e71fda6824900856e63e552416de2b59d"
2103+ },
2104+ {
2105+ "path": "org/apache/maven/shared/file-management/1.2.1/file-management-1.2.1.jar",
2106+ "sha1": "8f98bcaa7fd3625a172fd3de10bba8c32b9820ea"
2107+ },
2108+ {
2109+ "path": "org/apache/maven/shared/file-management/1.2.1/file-management-1.2.1.pom",
2110+ "sha1": "9aacc3da37949502b89807f0df2e6529ef33da0c"
2111+ },
2112+ {
2113+ "path": "org/apache/maven/shared/maven-artifact-transfer/0.12.0/maven-artifact-transfer-0.12.0.jar",
2114+ "sha1": "b63d86f97cda1456dcbda78bf57de779c372addd"
2115+ },
2116+ {
2117+ "path": "org/apache/maven/shared/maven-artifact-transfer/0.12.0/maven-artifact-transfer-0.12.0.pom",
2118+ "sha1": "c3dbc60cf87e50311ccf0f7c87ee43681dfb2edc"
2119+ },
2120+ {
2121+ "path": "org/apache/maven/shared/maven-common-artifact-filters/1.4/maven-common-artifact-filters-1.4.jar",
2122+ "sha1": "de97ff2efd804f06c3698a914f2d55205742bcc4"
2123+ },
2124+ {
2125+ "path": "org/apache/maven/shared/maven-common-artifact-filters/1.4/maven-common-artifact-filters-1.4.pom",
2126+ "sha1": "40c60d137280b0583ebff4b80361cd2a28ea9c42"
2127+ },
2128+ {
2129+ "path": "org/apache/maven/shared/maven-common-artifact-filters/3.0.1/maven-common-artifact-filters-3.0.1.jar",
2130+ "sha1": "1a98d8e3d5610bb0abf09a7756195e8b2ed215e5"
2131+ },
2132+ {
2133+ "path": "org/apache/maven/shared/maven-common-artifact-filters/3.0.1/maven-common-artifact-filters-3.0.1.pom",
2134+ "sha1": "c6e96947d07fc8d9d02f60ebccfd6e8080201676"
2135+ },
2136+ {
2137+ "path": "org/apache/maven/shared/maven-dependency-analyzer/1.4/maven-dependency-analyzer-1.4.jar",
2138+ "sha1": "2b20e6f9bb568e37ae952063d41b7a6d935dadb9"
2139+ },
2140+ {
2141+ "path": "org/apache/maven/shared/maven-dependency-analyzer/1.4/maven-dependency-analyzer-1.4.pom",
2142+ "sha1": "c4d24829dcaa5f153f0d3108cfd1fe370a7583f7"
2143+ },
2144+ {
2145+ "path": "org/apache/maven/shared/maven-dependency-tree/2.1/maven-dependency-tree-2.1.jar",
2146+ "sha1": "29c4d6aeae519809b9af0607156bbdd174efb0bb"
2147+ },
2148+ {
2149+ "path": "org/apache/maven/shared/maven-dependency-tree/2.1/maven-dependency-tree-2.1.pom",
2150+ "sha1": "772a49d54d50ffe30dbfc50e86ed8318a188746c"
2151+ },
2152+ {
2153+ "path": "org/apache/maven/shared/maven-dependency-tree/3.0.1/maven-dependency-tree-3.0.1.jar",
2154+ "sha1": "e9ae9966f1d3a238004c8b15ca4fd0e03d405424"
2155+ },
2156+ {
2157+ "path": "org/apache/maven/shared/maven-dependency-tree/3.0.1/maven-dependency-tree-3.0.1.pom",
2158+ "sha1": "836669a016f1abbabc9a4776c4b76fa097f8a7d5"
2159+ },
2160+ {
2161+ "path": "org/apache/maven/shared/maven-doxia-tools/1.0.2/maven-doxia-tools-1.0.2.jar",
2162+ "sha1": "50453155feb184ee951c1b5444555637705cc32b"
2163+ },
2164+ {
2165+ "path": "org/apache/maven/shared/maven-doxia-tools/1.0.2/maven-doxia-tools-1.0.2.pom",
2166+ "sha1": "c6180757919a5a2e6bdd9f55ebb4adb6a6391ca3"
2167+ },
2168+ {
2169+ "path": "org/apache/maven/shared/maven-filtering/1.1/maven-filtering-1.1.jar",
2170+ "sha1": "c223ff4ef9e9b3b51b2c9310dda59527a4b85baf"
2171+ },
2172+ {
2173+ "path": "org/apache/maven/shared/maven-filtering/1.1/maven-filtering-1.1.pom",
2174+ "sha1": "58f9827f70cc29dd6aed2477b6384f14462f9576"
2175+ },
2176+ {
2177+ "path": "org/apache/maven/shared/maven-invoker/2.0.11/maven-invoker-2.0.11.jar",
2178+ "sha1": "9c71535d63b58390e5413218ed66012b18902847"
2179+ },
2180+ {
2181+ "path": "org/apache/maven/shared/maven-invoker/2.0.11/maven-invoker-2.0.11.pom",
2182+ "sha1": "c4a3df6dbe91d3a4303c77cd0ae6f77dc62f357b"
2183+ },
2184+ {
2185+ "path": "org/apache/maven/shared/maven-shared-components/10/maven-shared-components-10.pom",
2186+ "sha1": "a7dabc7cff7b683d810e33a63c85cbc630c3ebf3"
2187+ },
2188+ {
2189+ "path": "org/apache/maven/shared/maven-shared-components/11/maven-shared-components-11.pom",
2190+ "sha1": "f60de1679753378e91acd5e0b35c53ec1d3cdff7"
2191+ },
2192+ {
2193+ "path": "org/apache/maven/shared/maven-shared-components/12/maven-shared-components-12.pom",
2194+ "sha1": "bb93c9f13f4d000affb4425632ad00b2082049a3"
2195+ },
2196+ {
2197+ "path": "org/apache/maven/shared/maven-shared-components/15/maven-shared-components-15.pom",
2198+ "sha1": "ea4cecd1845e61708cd05f20d5d428a3d429e67c"
2199+ },
2200+ {
2201+ "path": "org/apache/maven/shared/maven-shared-components/17/maven-shared-components-17.pom",
2202+ "sha1": "9574bbf041ebae3dcf84c221d552dbeb01fe5b40"
2203+ },
2204+ {
2205+ "path": "org/apache/maven/shared/maven-shared-components/18/maven-shared-components-18.pom",
2206+ "sha1": "b9aa57e02b5452a9b6cc9147e40bb0b53a7c8009"
2207+ },
2208+ {
2209+ "path": "org/apache/maven/shared/maven-shared-components/19/maven-shared-components-19.pom",
2210+ "sha1": "650a49682d4c82f060c7cc8005f8734a5fd86af9"
2211+ },
2212+ {
2213+ "path": "org/apache/maven/shared/maven-shared-components/30/maven-shared-components-30.pom",
2214+ "sha1": "fed1e8496612f1fd3621e686a4cee4ea56d04cf9"
2215+ },
2216+ {
2217+ "path": "org/apache/maven/shared/maven-shared-components/33/maven-shared-components-33.pom",
2218+ "sha1": "3eb04765b707822b0b97eae2648b1054e21cbdb3"
2219+ },
2220+ {
2221+ "path": "org/apache/maven/shared/maven-shared-components/8/maven-shared-components-8.pom",
2222+ "sha1": "a6b88e9b00b5eea13069ce324293a85e427e57c6"
2223+ },
2224+ {
2225+ "path": "org/apache/maven/shared/maven-shared-incremental/1.1/maven-shared-incremental-1.1.jar",
2226+ "sha1": "9d017a7584086755445c0a260dd9a1e9eae161a5"
2227+ },
2228+ {
2229+ "path": "org/apache/maven/shared/maven-shared-incremental/1.1/maven-shared-incremental-1.1.pom",
2230+ "sha1": "c607b2c64c027151c440f27b5ec86e062b9e9953"
2231+ },
2232+ {
2233+ "path": "org/apache/maven/shared/maven-shared-io/1.1/maven-shared-io-1.1.jar",
2234+ "sha1": "02e1d57be05ecac7dbe56a3c73b113e98f22240f"
2235+ },
2236+ {
2237+ "path": "org/apache/maven/shared/maven-shared-io/1.1/maven-shared-io-1.1.pom",
2238+ "sha1": "031970802f3b9937e43a82ff11518e02a51669dc"
2239+ },
2240+ {
2241+ "path": "org/apache/maven/shared/maven-shared-utils/0.1/maven-shared-utils-0.1.pom",
2242+ "sha1": "c638aa76e8eb374e14c4a3d25f66f36454645a54"
2243+ },
2244+ {
2245+ "path": "org/apache/maven/shared/maven-shared-utils/3.1.0/maven-shared-utils-3.1.0.jar",
2246+ "sha1": "78d8798fe84d5e095577221d299e9a3c8e696bca"
2247+ },
2248+ {
2249+ "path": "org/apache/maven/shared/maven-shared-utils/3.1.0/maven-shared-utils-3.1.0.pom",
2250+ "sha1": "96d533d4ae5c8ae5abe3f2e04fea554e2b03fd99"
2251+ },
2252+ {
2253+ "path": "org/apache/maven/shared/maven-shared-utils/3.2.1/maven-shared-utils-3.2.1.jar",
2254+ "sha1": "08dd4dfb1d2d8b6969f6462790f82670bcd35ce2"
2255+ },
2256+ {
2257+ "path": "org/apache/maven/shared/maven-shared-utils/3.2.1/maven-shared-utils-3.2.1.pom",
2258+ "sha1": "9347480fc0b3162e873c3a1f83af76ee1f909924"
2259+ },
2260+ {
2261+ "path": "org/apache/maven/surefire/maven-surefire-common/2.22.2/maven-surefire-common-2.22.2.jar",
2262+ "sha1": "d22aaa69c65e96cd9d87f779e45df76fb5040108"
2263+ },
2264+ {
2265+ "path": "org/apache/maven/surefire/maven-surefire-common/2.22.2/maven-surefire-common-2.22.2.pom",
2266+ "sha1": "7024a6391c6869c06e7b801c9553553884df2fdb"
2267+ },
2268+ {
2269+ "path": "org/apache/maven/surefire/surefire-api/2.22.2/surefire-api-2.22.2.jar",
2270+ "sha1": "273caddf446705ccceada91064e7266eb8517608"
2271+ },
2272+ {
2273+ "path": "org/apache/maven/surefire/surefire-api/2.22.2/surefire-api-2.22.2.pom",
2274+ "sha1": "49b34d166f30020a893551f058148e559779daf2"
2275+ },
2276+ {
2277+ "path": "org/apache/maven/surefire/surefire-booter/2.22.2/surefire-booter-2.22.2.jar",
2278+ "sha1": "84f8a93e76a7991f7f57d0e3905d8cf76176d3f5"
2279+ },
2280+ {
2281+ "path": "org/apache/maven/surefire/surefire-booter/2.22.2/surefire-booter-2.22.2.pom",
2282+ "sha1": "378a14fb78a3ba2d3efbb8cce8370937d65d39e3"
2283+ },
2284+ {
2285+ "path": "org/apache/maven/surefire/surefire-logger-api/2.22.2/surefire-logger-api-2.22.2.jar",
2286+ "sha1": "7c1513509a6f386711cfe21f50127a2641986163"
2287+ },
2288+ {
2289+ "path": "org/apache/maven/surefire/surefire-logger-api/2.22.2/surefire-logger-api-2.22.2.pom",
2290+ "sha1": "8170e8a3cd87c73fb8c97233b57d8ea4000dc8bf"
2291+ },
2292+ {
2293+ "path": "org/apache/maven/surefire/surefire/2.22.2/surefire-2.22.2.pom",
2294+ "sha1": "2bf172bb2ad3375d96a945775254a5d23f82612e"
2295+ },
2296+ {
2297+ "path": "org/apache/maven/wagon/wagon-provider-api/1.0-alpha-6/wagon-provider-api-1.0-alpha-6.jar",
2298+ "sha1": "b3c986c63fc873fbaef75ad4e57cd162fd5c9dd6"
2299+ },
2300+ {
2301+ "path": "org/apache/maven/wagon/wagon-provider-api/1.0-alpha-6/wagon-provider-api-1.0-alpha-6.pom",
2302+ "sha1": "1c1add559b9ed89168c2ae447481cfb63937ce2f"
2303+ },
2304+ {
2305+ "path": "org/apache/maven/wagon/wagon-provider-api/1.0/wagon-provider-api-1.0.jar",
2306+ "sha1": "12bcd211158c0c09b027d06b70371861398fedea"
2307+ },
2308+ {
2309+ "path": "org/apache/maven/wagon/wagon/1.0-alpha-6/wagon-1.0-alpha-6.pom",
2310+ "sha1": "69aa7db6cd9b32c6026dfb3d77d6a6865a2a9fc3"
2311+ },
2312+ {
2313+ "path": "org/apache/velocity/velocity/1.5/velocity-1.5.jar",
2314+ "sha1": "09f306baf7523ffc0e81a6353d08a584d254133b"
2315+ },
2316+ {
2317+ "path": "org/apache/velocity/velocity/1.5/velocity-1.5.pom",
2318+ "sha1": "106262b58f0f2b44cc0dbb3d0fa77105f28f5e38"
2319+ },
2320+ {
2321+ "path": "org/apache/xbean/xbean-reflect/3.4/xbean-reflect-3.4.pom",
2322+ "sha1": "5027123eb872a166f5205a5eb00d3ed186b63277"
2323+ },
2324+ {
2325+ "path": "org/apache/xbean/xbean/3.4/xbean-3.4.pom",
2326+ "sha1": "6b6d0d977f3fb41cfd097a350472baefd82713f5"
2327+ },
2328+ {
2329+ "path": "org/apiguardian/apiguardian-api/1.1.0/apiguardian-api-1.1.0.jar",
2330+ "sha1": "fc9dff4bb36d627bdc553de77e1f17efd790876c"
2331+ },
2332+ {
2333+ "path": "org/apiguardian/apiguardian-api/1.1.0/apiguardian-api-1.1.0.pom",
2334+ "sha1": "41f951c2aff248588037007e8f915467b9971a6f"
2335+ },
2336+ {
2337+ "path": "org/assertj/assertj-core/3.20.2/assertj-core-3.20.2.jar",
2338+ "sha1": "66f1f0ebd6db2b24e4a731979171da16ba919cd5"
2339+ },
2340+ {
2341+ "path": "org/assertj/assertj-core/3.20.2/assertj-core-3.20.2.pom",
2342+ "sha1": "38cead0af72d29e73c923fba590788c2f9a0bffd"
2343+ },
2344+ {
2345+ "path": "org/assertj/assertj-parent-pom/2.2.13/assertj-parent-pom-2.2.13.pom",
2346+ "sha1": "c75c29cf525c7ea9fc104ed740260cba02c7634b"
2347+ },
2348+ {
2349+ "path": "org/checkerframework/checker-compat-qual/2.5.2/checker-compat-qual-2.5.2.jar",
2350+ "sha1": "dc0b20906c9e4b9724af29d11604efa574066892"
2351+ },
2352+ {
2353+ "path": "org/checkerframework/checker-compat-qual/2.5.2/checker-compat-qual-2.5.2.pom",
2354+ "sha1": "055f6817b93fa72267c4a0aa47e06f0e826f0339"
2355+ },
2356+ {
2357+ "path": "org/checkerframework/checker-compat-qual/2.5.5/checker-compat-qual-2.5.5.jar",
2358+ "sha1": "435dc33e3019c9f019e15f01aa111de9d6b2b79c"
2359+ },
2360+ {
2361+ "path": "org/checkerframework/checker-compat-qual/2.5.5/checker-compat-qual-2.5.5.pom",
2362+ "sha1": "493796785b3c508c4c25e539321218511bd1c1ae"
2363+ },
2364+ {
2365+ "path": "org/checkerframework/checker-qual/2.5.2/checker-qual-2.5.2.jar",
2366+ "sha1": "cea74543d5904a30861a61b4643a5f2bb372efc4"
2367+ },
2368+ {
2369+ "path": "org/checkerframework/checker-qual/2.5.2/checker-qual-2.5.2.pom",
2370+ "sha1": "7cee753353b0fc94e0300ad3dbf155069260c4d7"
2371+ },
2372+ {
2373+ "path": "org/codehaus/mojo/animal-sniffer-annotations/1.17/animal-sniffer-annotations-1.17.jar",
2374+ "sha1": "f97ce6decaea32b36101e37979f8b647f00681fb"
2375+ },
2376+ {
2377+ "path": "org/codehaus/mojo/animal-sniffer-annotations/1.17/animal-sniffer-annotations-1.17.pom",
2378+ "sha1": "80948bd07c5db60753d8d5a9164b8b2272e0842a"
2379+ },
2380+ {
2381+ "path": "org/codehaus/mojo/animal-sniffer-annotations/1.18/animal-sniffer-annotations-1.18.pom",
2382+ "sha1": "82452242e8e2d0e058182cb01f29c3c30391dac3"
2383+ },
2384+ {
2385+ "path": "org/codehaus/mojo/animal-sniffer-parent/1.17/animal-sniffer-parent-1.17.pom",
2386+ "sha1": "eea4b805793494ebb025e5a9926ea3cf1ee8b34d"
2387+ },
2388+ {
2389+ "path": "org/codehaus/mojo/animal-sniffer-parent/1.18/animal-sniffer-parent-1.18.pom",
2390+ "sha1": "dd9080d0b2019e3cbb8b97dc7c057787062172f2"
2391+ },
2392+ {
2393+ "path": "org/codehaus/mojo/mojo-parent/40/mojo-parent-40.pom",
2394+ "sha1": "d2fa7c95447827e9bbcb8c60bd9484c51202732e"
2395+ },
2396+ {
2397+ "path": "org/codehaus/mojo/mojo-parent/50/mojo-parent-50.pom",
2398+ "sha1": "8caf7f67d94e762418df68f034c88b6f18433860"
2399+ },
2400+ {
2401+ "path": "org/codehaus/plexus/plexus-archiver/1.0/plexus-archiver-1.0.jar",
2402+ "sha1": "b564a05aeecd4d81d6b81f57a1d495fc8c0f497f"
2403+ },
2404+ {
2405+ "path": "org/codehaus/plexus/plexus-archiver/2.1/plexus-archiver-2.1.jar",
2406+ "sha1": "97853695be4bba3724512226c4d910fed733e608"
2407+ },
2408+ {
2409+ "path": "org/codehaus/plexus/plexus-archiver/2.1/plexus-archiver-2.1.pom",
2410+ "sha1": "8e63c83bf055cf0357669ca934f64c6bf27fc640"
2411+ },
2412+ {
2413+ "path": "org/codehaus/plexus/plexus-archiver/2.3/plexus-archiver-2.3.jar",
2414+ "sha1": "6abb3f7e89a76b9ef95db62f209a8cbb0c03fab2"
2415+ },
2416+ {
2417+ "path": "org/codehaus/plexus/plexus-archiver/2.3/plexus-archiver-2.3.pom",
2418+ "sha1": "a955cd43f140b2717beaf3e9d13bc8468c401eb4"
2419+ },
2420+ {
2421+ "path": "org/codehaus/plexus/plexus-classworlds/1.2-alpha-7/plexus-classworlds-1.2-alpha-7.pom",
2422+ "sha1": "6944ec0d0cab19adf167332f7197e045d64a577c"
2423+ },
2424+ {
2425+ "path": "org/codehaus/plexus/plexus-classworlds/1.2-alpha-9/plexus-classworlds-1.2-alpha-9.pom",
2426+ "sha1": "32be3692644bf86d1226e13e2a60b49a9fa49571"
2427+ },
2428+ {
2429+ "path": "org/codehaus/plexus/plexus-classworlds/2.2.2/plexus-classworlds-2.2.2.pom",
2430+ "sha1": "df1dfb0099c8759b378fe0af3b4a564d2c16aa18"
2431+ },
2432+ {
2433+ "path": "org/codehaus/plexus/plexus-classworlds/2.2.3/plexus-classworlds-2.2.3.jar",
2434+ "sha1": "93b34d7a40ed56fe33274480c5792b656d3697a9"
2435+ },
2436+ {
2437+ "path": "org/codehaus/plexus/plexus-classworlds/2.2.3/plexus-classworlds-2.2.3.pom",
2438+ "sha1": "068f7ac6a425f5e82bbbb5faef91e4b5d3d84f76"
2439+ },
2440+ {
2441+ "path": "org/codehaus/plexus/plexus-classworlds/2.5.2/plexus-classworlds-2.5.2.jar",
2442+ "sha1": "4abb111bfdace5b8167db4c0ef74644f3f88f142"
2443+ },
2444+ {
2445+ "path": "org/codehaus/plexus/plexus-classworlds/2.5.2/plexus-classworlds-2.5.2.pom",
2446+ "sha1": "a39bedbc3fa3652d3606821d7c21d80e900f57a0"
2447+ },
2448+ {
2449+ "path": "org/codehaus/plexus/plexus-compiler-api/2.8.4/plexus-compiler-api-2.8.4.jar",
2450+ "sha1": "ab13f02c237842b1d81b531fafd27f3c13585a37"
2451+ },
2452+ {
2453+ "path": "org/codehaus/plexus/plexus-compiler-api/2.8.4/plexus-compiler-api-2.8.4.pom",
2454+ "sha1": "be4194949f559462e78267207a99360274a58056"
2455+ },
2456+ {
2457+ "path": "org/codehaus/plexus/plexus-compiler-javac/2.8.4/plexus-compiler-javac-2.8.4.jar",
2458+ "sha1": "4a2c03bf7663dff8fd512cc1a7adecacf1a2249b"
2459+ },
2460+ {
2461+ "path": "org/codehaus/plexus/plexus-compiler-javac/2.8.4/plexus-compiler-javac-2.8.4.pom",
2462+ "sha1": "fecd511a1cd70f23ecee2cecc52b4d89124c114c"
2463+ },
2464+ {
2465+ "path": "org/codehaus/plexus/plexus-compiler-manager/2.8.4/plexus-compiler-manager-2.8.4.jar",
2466+ "sha1": "43b09c6b1831e962259634ac9ae2e6ac0467560e"
2467+ },
2468+ {
2469+ "path": "org/codehaus/plexus/plexus-compiler-manager/2.8.4/plexus-compiler-manager-2.8.4.pom",
2470+ "sha1": "578d6fba6c0b8a91884f3e710e051ad466d33425"
2471+ },
2472+ {
2473+ "path": "org/codehaus/plexus/plexus-compiler/2.8.4/plexus-compiler-2.8.4.pom",
2474+ "sha1": "0e54ac334bbea91bcb67325d78871c4082522f28"
2475+ },
2476+ {
2477+ "path": "org/codehaus/plexus/plexus-compilers/2.8.4/plexus-compilers-2.8.4.pom",
2478+ "sha1": "2ee8e7bcc9426c075fa4d0c415fb648ea8a9d701"
2479+ },
2480+ {
2481+ "path": "org/codehaus/plexus/plexus-component-annotations/1.5.4/plexus-component-annotations-1.5.4.pom",
2482+ "sha1": "52093f92fd7f82edf464f86c4f7220f9effc4bf2"
2483+ },
2484+ {
2485+ "path": "org/codehaus/plexus/plexus-component-annotations/1.5.5/plexus-component-annotations-1.5.5.jar",
2486+ "sha1": "c72f2660d0cbed24246ddb55d7fdc4f7374d2078"
2487+ },
2488+ {
2489+ "path": "org/codehaus/plexus/plexus-component-annotations/1.5.5/plexus-component-annotations-1.5.5.pom",
2490+ "sha1": "fd506865d5d083d8cef9fdbf525ad99fcc3416c1"
2491+ },
2492+ {
2493+ "path": "org/codehaus/plexus/plexus-component-annotations/1.7.1/plexus-component-annotations-1.7.1.jar",
2494+ "sha1": "862abca6deff0fff241a835a33d22559e9132069"
2495+ },
2496+ {
2497+ "path": "org/codehaus/plexus/plexus-component-annotations/1.7.1/plexus-component-annotations-1.7.1.pom",
2498+ "sha1": "e265daf1fcf56a67dd9bae3db80531a9717ccee4"
2499+ },
2500+ {
2501+ "path": "org/codehaus/plexus/plexus-component-annotations/2.0.0/plexus-component-annotations-2.0.0.jar",
2502+ "sha1": "6897b9fa8b67c900b52996f845e2d179eea13441"
2503+ },
2504+ {
2505+ "path": "org/codehaus/plexus/plexus-component-annotations/2.0.0/plexus-component-annotations-2.0.0.pom",
2506+ "sha1": "c273519bf9d766461c523facbf530ba18793bbe4"
2507+ },
2508+ {
2509+ "path": "org/codehaus/plexus/plexus-components/1.1.12/plexus-components-1.1.12.pom",
2510+ "sha1": "e7332a35914684bab5dd1718aea0202fa5a2bb0d"
2511+ },
2512+ {
2513+ "path": "org/codehaus/plexus/plexus-components/1.1.14/plexus-components-1.1.14.pom",
2514+ "sha1": "aed78d67ee20a5038741c7cc2a8124ae20c960ad"
2515+ },
2516+ {
2517+ "path": "org/codehaus/plexus/plexus-components/1.1.15/plexus-components-1.1.15.pom",
2518+ "sha1": "44366f11d5b9571c16829ae7f0a7f20e116f6260"
2519+ },
2520+ {
2521+ "path": "org/codehaus/plexus/plexus-components/1.1.18/plexus-components-1.1.18.pom",
2522+ "sha1": "41abf89f075e6b912a2ff728aa002e98591de425"
2523+ },
2524+ {
2525+ "path": "org/codehaus/plexus/plexus-components/1.1.19/plexus-components-1.1.19.pom",
2526+ "sha1": "2c0f4d3bcbcdd8f77521502d886681ed5af38a25"
2527+ },
2528+ {
2529+ "path": "org/codehaus/plexus/plexus-components/1.1.7/plexus-components-1.1.7.pom",
2530+ "sha1": "5fcdd5b77b86b603af118b70281f48539031a9f3"
2531+ },
2532+ {
2533+ "path": "org/codehaus/plexus/plexus-components/1.2/plexus-components-1.2.pom",
2534+ "sha1": "d0371336a8a00aa8ab99b332ac8eaf1665a9a3e5"
2535+ },
2536+ {
2537+ "path": "org/codehaus/plexus/plexus-components/1.3/plexus-components-1.3.pom",
2538+ "sha1": "979daf6b32bf4eb1fc8ff51689bf31731651a0c8"
2539+ },
2540+ {
2541+ "path": "org/codehaus/plexus/plexus-components/4.0/plexus-components-4.0.pom",
2542+ "sha1": "dcad998d9c45ca35212ac7efc49b729efce20395"
2543+ },
2544+ {
2545+ "path": "org/codehaus/plexus/plexus-container-default/1.0-alpha-20/plexus-container-default-1.0-alpha-20.pom",
2546+ "sha1": "911e3b5962b6485fd2fac68fa1af066f36388320"
2547+ },
2548+ {
2549+ "path": "org/codehaus/plexus/plexus-container-default/1.0-alpha-30/plexus-container-default-1.0-alpha-30.pom",
2550+ "sha1": "aa1efeb7ed05a3c5037cc194b9e8fbf97e52268a"
2551+ },
2552+ {
2553+ "path": "org/codehaus/plexus/plexus-container-default/1.0-alpha-8/plexus-container-default-1.0-alpha-8.pom",
2554+ "sha1": "3324c2065311b5cd636d3fe37353fe7558a6ec22"
2555+ },
2556+ {
2557+ "path": "org/codehaus/plexus/plexus-container-default/1.0-alpha-9-stable-1/plexus-container-default-1.0-alpha-9-stable-1.jar",
2558+ "sha1": "94aea3010e250a334d9dab7f591114cd6c767458"
2559+ },
2560+ {
2561+ "path": "org/codehaus/plexus/plexus-container-default/1.0-alpha-9-stable-1/plexus-container-default-1.0-alpha-9-stable-1.pom",
2562+ "sha1": "f557cb47f4594ac941d0edf08093a03ce15b51ba"
2563+ },
2564+ {
2565+ "path": "org/codehaus/plexus/plexus-container-default/1.0-alpha-9/plexus-container-default-1.0-alpha-9.jar",
2566+ "sha1": "50596183cd7b688d9d7b6d868a0193ca1a8a7b3d"
2567+ },
2568+ {
2569+ "path": "org/codehaus/plexus/plexus-container-default/1.0-alpha-9/plexus-container-default-1.0-alpha-9.pom",
2570+ "sha1": "d00c65ec36fb3cc8c755182a7ee52d3d80340179"
2571+ },
2572+ {
2573+ "path": "org/codehaus/plexus/plexus-container-default/1.5.5/plexus-container-default-1.5.5.pom",
2574+ "sha1": "f68a6d3761cfdfdf1e13ce2c18327c514acad611"
2575+ },
2576+ {
2577+ "path": "org/codehaus/plexus/plexus-containers/1.0-alpha-20/plexus-containers-1.0-alpha-20.pom",
2578+ "sha1": "5e436ba5a20b19e6b840f087e12e1c993b427de0"
2579+ },
2580+ {
2581+ "path": "org/codehaus/plexus/plexus-containers/1.0-alpha-30/plexus-containers-1.0-alpha-30.pom",
2582+ "sha1": "8b6330c46076c52825feb050aa27c550b24b4a17"
2583+ },
2584+ {
2585+ "path": "org/codehaus/plexus/plexus-containers/1.0.3/plexus-containers-1.0.3.pom",
2586+ "sha1": "e16f1c9b83cdeb142fc038dd0262c61121d58c4b"
2587+ },
2588+ {
2589+ "path": "org/codehaus/plexus/plexus-containers/1.5.4/plexus-containers-1.5.4.pom",
2590+ "sha1": "b9942b081e9903371eb0c8f5677d1d2564b575ca"
2591+ },
2592+ {
2593+ "path": "org/codehaus/plexus/plexus-containers/1.5.5/plexus-containers-1.5.5.pom",
2594+ "sha1": "cd786b660f8a4c1c520403a5fa04c7be45212b84"
2595+ },
2596+ {
2597+ "path": "org/codehaus/plexus/plexus-containers/1.7.1/plexus-containers-1.7.1.pom",
2598+ "sha1": "7ff4e431b5af8100be6e9fcd946ba7c532d890e2"
2599+ },
2600+ {
2601+ "path": "org/codehaus/plexus/plexus-containers/2.0.0/plexus-containers-2.0.0.pom",
2602+ "sha1": "47ae11db323292909afbcbd817f9cafda054000a"
2603+ },
2604+ {
2605+ "path": "org/codehaus/plexus/plexus-digest/1.0/plexus-digest-1.0.jar",
2606+ "sha1": "5f6a5a5140cd39e8c987cf6c31429d917b31166e"
2607+ },
2608+ {
2609+ "path": "org/codehaus/plexus/plexus-digest/1.0/plexus-digest-1.0.pom",
2610+ "sha1": "df5c2e55c9f30db34972661819437f1802128861"
2611+ },
2612+ {
2613+ "path": "org/codehaus/plexus/plexus-i18n/1.0-beta-7/plexus-i18n-1.0-beta-7.jar",
2614+ "sha1": "3690f10a668b3c7ac2ef563f14cfb6b2ba30ee57"
2615+ },
2616+ {
2617+ "path": "org/codehaus/plexus/plexus-i18n/1.0-beta-7/plexus-i18n-1.0-beta-7.pom",
2618+ "sha1": "5080cbaf0a98e413017ed074c845673c16546500"
2619+ },
2620+ {
2621+ "path": "org/codehaus/plexus/plexus-interactivity-api/1.0-alpha-4/plexus-interactivity-api-1.0-alpha-4.jar",
2622+ "sha1": "0a8f1178664a5457eef3f4531eb62f9505e1295f"
2623+ },
2624+ {
2625+ "path": "org/codehaus/plexus/plexus-interactivity-api/1.0-alpha-4/plexus-interactivity-api-1.0-alpha-4.pom",
2626+ "sha1": "1376ffcc4a8d46dee6c1a9096d0dcad3be01f838"
2627+ },
2628+ {
2629+ "path": "org/codehaus/plexus/plexus-interpolation/1.11/plexus-interpolation-1.11.jar",
2630+ "sha1": "ad9dddff6043194904ad1d2c00ff1d003c3915f7"
2631+ },
2632+ {
2633+ "path": "org/codehaus/plexus/plexus-interpolation/1.11/plexus-interpolation-1.11.pom",
2634+ "sha1": "f03da80999422b6cc4300735789be83e4498a3bc"
2635+ },
2636+ {
2637+ "path": "org/codehaus/plexus/plexus-interpolation/1.12/plexus-interpolation-1.12.pom",
2638+ "sha1": "101dd833f7186103b61a0281da38c95ae440eb63"
2639+ },
2640+ {
2641+ "path": "org/codehaus/plexus/plexus-interpolation/1.13/plexus-interpolation-1.13.jar",
2642+ "sha1": "1740038076cec1946fd28ed5ac5c1688f7cf7630"
2643+ },
2644+ {
2645+ "path": "org/codehaus/plexus/plexus-interpolation/1.13/plexus-interpolation-1.13.pom",
2646+ "sha1": "5003aac564f8ab42ceede81b114c520b48271873"
2647+ },
2648+ {
2649+ "path": "org/codehaus/plexus/plexus-interpolation/1.14/plexus-interpolation-1.14.jar",
2650+ "sha1": "c88dd864fe8b8256c25558ce7cd63be66ba07693"
2651+ },
2652+ {
2653+ "path": "org/codehaus/plexus/plexus-interpolation/1.14/plexus-interpolation-1.14.pom",
2654+ "sha1": "e296d45aff17c16ed268c5b9480214a0d92937ab"
2655+ },
2656+ {
2657+ "path": "org/codehaus/plexus/plexus-interpolation/1.15/plexus-interpolation-1.15.jar",
2658+ "sha1": "d682b4b8c1a92329d5b114a51794ef178168abbe"
2659+ },
2660+ {
2661+ "path": "org/codehaus/plexus/plexus-interpolation/1.15/plexus-interpolation-1.15.pom",
2662+ "sha1": "3dda3be2ada841f5ca3976a48281349a99f27e89"
2663+ },
2664+ {
2665+ "path": "org/codehaus/plexus/plexus-io/2.0.2/plexus-io-2.0.2.jar",
2666+ "sha1": "5d1890f1099242d6a1a6a46640eed931a96ef67f"
2667+ },
2668+ {
2669+ "path": "org/codehaus/plexus/plexus-io/2.0.2/plexus-io-2.0.2.pom",
2670+ "sha1": "d0ad15a280e5bf6c32388cbef26fd7d428fa1623"
2671+ },
2672+ {
2673+ "path": "org/codehaus/plexus/plexus-io/2.0.6/plexus-io-2.0.6.jar",
2674+ "sha1": "ae2ddfcb316ac045cd85792cbfea928b4cfd5b8d"
2675+ },
2676+ {
2677+ "path": "org/codehaus/plexus/plexus-io/2.0.6/plexus-io-2.0.6.pom",
2678+ "sha1": "80663ba325fc5477350b3e27af62b4879d6f5ca8"
2679+ },
2680+ {
2681+ "path": "org/codehaus/plexus/plexus-java/0.9.10/plexus-java-0.9.10.jar",
2682+ "sha1": "269ef3b88d500716f958a8e2b78561f34d50df80"
2683+ },
2684+ {
2685+ "path": "org/codehaus/plexus/plexus-java/0.9.10/plexus-java-0.9.10.pom",
2686+ "sha1": "65d0f66fc4b0adafe01c8b29a8bd692d0d62ba09"
2687+ },
2688+ {
2689+ "path": "org/codehaus/plexus/plexus-languages/0.9.10/plexus-languages-0.9.10.pom",
2690+ "sha1": "f7816d2ab70df6ff670bcfb8376d14238a63be72"
2691+ },
2692+ {
2693+ "path": "org/codehaus/plexus/plexus-utils/1.0.4/plexus-utils-1.0.4.pom",
2694+ "sha1": "a82e1ddd2d795616ac58d73ed246b8ec65326dfa"
2695+ },
2696+ {
2697+ "path": "org/codehaus/plexus/plexus-utils/1.1/plexus-utils-1.1.pom",
2698+ "sha1": "15492ecd00920daca9ec15f6acd695b626621e5b"
2699+ },
2700+ {
2701+ "path": "org/codehaus/plexus/plexus-utils/1.3/plexus-utils-1.3.pom",
2702+ "sha1": "050fadd040060c86cfd5d78ba95dab0cffcbcf5e"
2703+ },
2704+ {
2705+ "path": "org/codehaus/plexus/plexus-utils/1.4.1/plexus-utils-1.4.1.pom",
2706+ "sha1": "0a77530df5e881e55a4ffaea4b6bf33d57bc5b26"
2707+ },
2708+ {
2709+ "path": "org/codehaus/plexus/plexus-utils/1.4.5/plexus-utils-1.4.5.pom",
2710+ "sha1": "0bdc8a7fbce7d9007a93d289a029b43e1196d85c"
2711+ },
2712+ {
2713+ "path": "org/codehaus/plexus/plexus-utils/1.4.6/plexus-utils-1.4.6.pom",
2714+ "sha1": "a734ee9396d2ac09764cef74ebc56ef0339f6bd2"
2715+ },
2716+ {
2717+ "path": "org/codehaus/plexus/plexus-utils/1.5.1/plexus-utils-1.5.1.pom",
2718+ "sha1": "2a0b3470063440066d3b8a084340ce07dbdbfedc"
2719+ },
2720+ {
2721+ "path": "org/codehaus/plexus/plexus-utils/1.5.10/plexus-utils-1.5.10.jar",
2722+ "sha1": "f387a2faa309154d90b90cc049e44b7833a6c282"
2723+ },
2724+ {
2725+ "path": "org/codehaus/plexus/plexus-utils/1.5.15/plexus-utils-1.5.15.jar",
2726+ "sha1": "c689598ce1eb94c304817877ed15911099972526"
2727+ },
2728+ {
2729+ "path": "org/codehaus/plexus/plexus-utils/1.5.15/plexus-utils-1.5.15.pom",
2730+ "sha1": "b1f42bc7ebc5be3c0414f67fe2daf3b183acd74f"
2731+ },
2732+ {
2733+ "path": "org/codehaus/plexus/plexus-utils/1.5.5/plexus-utils-1.5.5.pom",
2734+ "sha1": "6d04eaae6db5f8d879332da294a46df0fd81450f"
2735+ },
2736+ {
2737+ "path": "org/codehaus/plexus/plexus-utils/1.5.6/plexus-utils-1.5.6.pom",
2738+ "sha1": "2df1a6c4e7b1849a10643a37a6f66b21d49bd643"
2739+ },
2740+ {
2741+ "path": "org/codehaus/plexus/plexus-utils/1.5.7/plexus-utils-1.5.7.pom",
2742+ "sha1": "38ae56ab5c035d5ebbfda0d3b418d3c3ea41d83d"
2743+ },
2744+ {
2745+ "path": "org/codehaus/plexus/plexus-utils/1.5.8/plexus-utils-1.5.8.pom",
2746+ "sha1": "7deaa90e5725075c9f9fb5a2cfbef75c86a5e5b5"
2747+ },
2748+ {
2749+ "path": "org/codehaus/plexus/plexus-utils/2.0.4/plexus-utils-2.0.4.jar",
2750+ "sha1": "1a363fa733fba4285967162f9a6ffe6fd356ec24"
2751+ },
2752+ {
2753+ "path": "org/codehaus/plexus/plexus-utils/2.0.4/plexus-utils-2.0.4.pom",
2754+ "sha1": "ffd8cee6475d101a5697091e1c18b0d08e3a8ff8"
2755+ },
2756+ {
2757+ "path": "org/codehaus/plexus/plexus-utils/2.0.5/plexus-utils-2.0.5.jar",
2758+ "sha1": "7841ba10ea46c9611ce702c3833ff9fccc8ae6eb"
2759+ },
2760+ {
2761+ "path": "org/codehaus/plexus/plexus-utils/2.0.5/plexus-utils-2.0.5.pom",
2762+ "sha1": "51785edd83de609389ba142c9516752a4246aefc"
2763+ },
2764+ {
2765+ "path": "org/codehaus/plexus/plexus-utils/2.1/plexus-utils-2.1.pom",
2766+ "sha1": "093c8fac63e60cc811aac811b8d36ffe2aa5401f"
2767+ },
2768+ {
2769+ "path": "org/codehaus/plexus/plexus-utils/3.0.10/plexus-utils-3.0.10.pom",
2770+ "sha1": "c70632156c3f19286424329d71e82b2026b90471"
2771+ },
2772+ {
2773+ "path": "org/codehaus/plexus/plexus-utils/3.0.15/plexus-utils-3.0.15.jar",
2774+ "sha1": "519b3f1fc84d3387c61a8c8e6235daf89aea4168"
2775+ },
2776+ {
2777+ "path": "org/codehaus/plexus/plexus-utils/3.0.17/plexus-utils-3.0.17.pom",
2778+ "sha1": "f2f5fa2f18718b54e0c488e9c40ca68c9e0cd190"
2779+ },
2780+ {
2781+ "path": "org/codehaus/plexus/plexus-utils/3.0.22/plexus-utils-3.0.22.jar",
2782+ "sha1": "764f26e0ab13a87c48fe55f525dfb6a133b7a92f"
2783+ },
2784+ {
2785+ "path": "org/codehaus/plexus/plexus-utils/3.0.22/plexus-utils-3.0.22.pom",
2786+ "sha1": "553c5a129da11f6d56a2599ad0b21649a6d6de08"
2787+ },
2788+ {
2789+ "path": "org/codehaus/plexus/plexus-utils/3.0.5/plexus-utils-3.0.5.jar",
2790+ "sha1": "3da9c286180a66aba197db8ffa7bbdc756c3e31f"
2791+ },
2792+ {
2793+ "path": "org/codehaus/plexus/plexus-utils/3.0.5/plexus-utils-3.0.5.pom",
2794+ "sha1": "880976a01d8f71ced7c8da841e571479bb7b6021"
2795+ },
2796+ {
2797+ "path": "org/codehaus/plexus/plexus-utils/3.0.8/plexus-utils-3.0.8.pom",
2798+ "sha1": "45a8cbe47c297155f2e2ef10c1b7b4707ab55fc6"
2799+ },
2800+ {
2801+ "path": "org/codehaus/plexus/plexus-utils/3.0.9/plexus-utils-3.0.9.jar",
2802+ "sha1": "48362e7b8a6edd68f8ff2e26bfb84ee370a5380b"
2803+ },
2804+ {
2805+ "path": "org/codehaus/plexus/plexus-utils/3.0.9/plexus-utils-3.0.9.pom",
2806+ "sha1": "259d8924d1f827ee49c7c5b3913f76b18d6055ca"
2807+ },
2808+ {
2809+ "path": "org/codehaus/plexus/plexus-utils/3.0/plexus-utils-3.0.jar",
2810+ "sha1": "d63aa0daf60d573bada235e2b4207617dcf24959"
2811+ },
2812+ {
2813+ "path": "org/codehaus/plexus/plexus-utils/3.0/plexus-utils-3.0.pom",
2814+ "sha1": "fe3d8457b0cf4e219fd8e3edad5054b8e38f17b0"
2815+ },
2816+ {
2817+ "path": "org/codehaus/plexus/plexus-utils/3.1.1/plexus-utils-3.1.1.pom",
2818+ "sha1": "9444be6c0e7197eccde066fc5ed8aaba968e9a16"
2819+ },
2820+ {
2821+ "path": "org/codehaus/plexus/plexus-utils/3.3.0/plexus-utils-3.3.0.jar",
2822+ "sha1": "cf43b5391de623b36fe066a21127baef82c64022"
2823+ },
2824+ {
2825+ "path": "org/codehaus/plexus/plexus-utils/3.3.0/plexus-utils-3.3.0.pom",
2826+ "sha1": "de5faec837d872a1712aa89242845216118a9405"
2827+ },
2828+ {
2829+ "path": "org/codehaus/plexus/plexus-velocity/1.1.7/plexus-velocity-1.1.7.jar",
2830+ "sha1": "1440fc2552d1405b1c2d380ef3b96c4d9c6dbd0b"
2831+ },
2832+ {
2833+ "path": "org/codehaus/plexus/plexus-velocity/1.1.7/plexus-velocity-1.1.7.pom",
2834+ "sha1": "659f8ef80ef0cc3d101e63535b9c5a39f7bc4b3e"
2835+ },
2836+ {
2837+ "path": "org/codehaus/plexus/plexus-velocity/1.1.8/plexus-velocity-1.1.8.jar",
2838+ "sha1": "d6b34818c82cd2e2f7bc75a2852d31283d154291"
2839+ },
2840+ {
2841+ "path": "org/codehaus/plexus/plexus/1.0.10/plexus-1.0.10.pom",
2842+ "sha1": "039c3f6a3cbe1f9e7b4a3309d9d7062b6e390fa7"
2843+ },
2844+ {
2845+ "path": "org/codehaus/plexus/plexus/1.0.11/plexus-1.0.11.pom",
2846+ "sha1": "4693d4512d50c5159bef1c49def1d2690a327c30"
2847+ },
2848+ {
2849+ "path": "org/codehaus/plexus/plexus/1.0.12/plexus-1.0.12.pom",
2850+ "sha1": "71d4361c71c7454a2626f3e18c789747256fe0b1"
2851+ },
2852+ {
2853+ "path": "org/codehaus/plexus/plexus/1.0.4/plexus-1.0.4.pom",
2854+ "sha1": "06f66b2f7d2eef1d805c11bca91c89984cda4137"
2855+ },
2856+ {
2857+ "path": "org/codehaus/plexus/plexus/1.0.8/plexus-1.0.8.pom",
2858+ "sha1": "9e7c8432829962afe796b32587c1bfa841a317d5"
2859+ },
2860+ {
2861+ "path": "org/codehaus/plexus/plexus/1.0.9/plexus-1.0.9.pom",
2862+ "sha1": "89d241b1e5ee6a72d3dd95d9eb90f635deebcdb2"
2863+ },
2864+ {
2865+ "path": "org/codehaus/plexus/plexus/2.0.2/plexus-2.0.2.pom",
2866+ "sha1": "b6c97d19090baa51e953fb782e3986b068fb450f"
2867+ },
2868+ {
2869+ "path": "org/codehaus/plexus/plexus/2.0.3/plexus-2.0.3.pom",
2870+ "sha1": "bf472ec56fe823f1b4b997fe5b9396490ae9b1dc"
2871+ },
2872+ {
2873+ "path": "org/codehaus/plexus/plexus/2.0.5/plexus-2.0.5.pom",
2874+ "sha1": "c37b8e9129d8860dfdea27da2c5407de7c6faba7"
2875+ },
2876+ {
2877+ "path": "org/codehaus/plexus/plexus/2.0.6/plexus-2.0.6.pom",
2878+ "sha1": "da193f47e5ce5a2cb85931851b3698e61cde8227"
2879+ },
2880+ {
2881+ "path": "org/codehaus/plexus/plexus/2.0.7/plexus-2.0.7.pom",
2882+ "sha1": "f6ee62f8157f273757b8ffda59714a6a279a174d"
2883+ },
2884+ {
2885+ "path": "org/codehaus/plexus/plexus/3.0.1/plexus-3.0.1.pom",
2886+ "sha1": "9ae573423303ba80844ed564756442d32b97cc33"
2887+ },
2888+ {
2889+ "path": "org/codehaus/plexus/plexus/3.1/plexus-3.1.pom",
2890+ "sha1": "b64de86ceaa4f0e4d8ccc44a26c562c6fb7fb230"
2891+ },
2892+ {
2893+ "path": "org/codehaus/plexus/plexus/3.2/plexus-3.2.pom",
2894+ "sha1": "521733c90c6fb160311e47b51f0471642b69f64f"
2895+ },
2896+ {
2897+ "path": "org/codehaus/plexus/plexus/3.3.1/plexus-3.3.1.pom",
2898+ "sha1": "f081c65405b2d5e403c9d57e791b23f613966322"
2899+ },
2900+ {
2901+ "path": "org/codehaus/plexus/plexus/3.3/plexus-3.3.pom",
2902+ "sha1": "70ab8436286998acce80e63fe75067a70cfe3e43"
2903+ },
2904+ {
2905+ "path": "org/codehaus/plexus/plexus/4.0/plexus-4.0.pom",
2906+ "sha1": "cdbb31ee91973d16e8f8b0bda51ed4211e7a9f57"
2907+ },
2908+ {
2909+ "path": "org/codehaus/plexus/plexus/5.1/plexus-5.1.pom",
2910+ "sha1": "2fca82e2eb5172f6a2909bea7accc733581a8c71"
2911+ },
2912+ {
2913+ "path": "org/eclipse/aether/aether-util/0.9.0.M2/aether-util-0.9.0.M2.jar",
2914+ "sha1": "b957089deb654647da320ad7507b0a4b5ce23813"
2915+ },
2916+ {
2917+ "path": "org/eclipse/aether/aether-util/0.9.0.M2/aether-util-0.9.0.M2.pom",
2918+ "sha1": "938d4a7468d46180927cd14ccec6a5accfc428af"
2919+ },
2920+ {
2921+ "path": "org/eclipse/aether/aether/0.9.0.M2/aether-0.9.0.M2.pom",
2922+ "sha1": "e44bcfab62cbf0ad4f15a47aa9cc48368db2dc6d"
2923+ },
2924+ {
2925+ "path": "org/eclipse/ee4j/project/1.0.2/project-1.0.2.pom",
2926+ "sha1": "5730bedee1faaeeb62b0afc4ed1c4571f87a8eb4"
2927+ },
2928+ {
2929+ "path": "org/eclipse/ee4j/project/1.0.5/project-1.0.5.pom",
2930+ "sha1": "d391c5ed15d8fb1dadba9c5d1017006d56c50332"
2931+ },
2932+ {
2933+ "path": "org/eclipse/jgit/org.eclipse.jgit-parent/5.2.1.201812262042-r/org.eclipse.jgit-parent-5.2.1.201812262042-r.pom",
2934+ "sha1": "71ef80c1389d9c47dfe995e03ad655a7294167a2"
2935+ },
2936+ {
2937+ "path": "org/eclipse/jgit/org.eclipse.jgit/5.2.1.201812262042-r/org.eclipse.jgit-5.2.1.201812262042-r.jar",
2938+ "sha1": "34914e63e1463e40ba40e2e28b0392993ea3b938"
2939+ },
2940+ {
2941+ "path": "org/eclipse/jgit/org.eclipse.jgit/5.2.1.201812262042-r/org.eclipse.jgit-5.2.1.201812262042-r.pom",
2942+ "sha1": "91190a4dd7ea339c080ce5b76221e5fceaab58d6"
2943+ },
2944+ {
2945+ "path": "org/eclipse/sisu/org.eclipse.sisu.inject/0.3.2/org.eclipse.sisu.inject-0.3.2.jar",
2946+ "sha1": "59044b92ec27cc6fda7a2d24b2cd6cec23f31d5b"
2947+ },
2948+ {
2949+ "path": "org/eclipse/sisu/org.eclipse.sisu.inject/0.3.2/org.eclipse.sisu.inject-0.3.2.pom",
2950+ "sha1": "41a7f34260adf84181f7bfaf512e5c0ddde5f417"
2951+ },
2952+ {
2953+ "path": "org/eclipse/sisu/org.eclipse.sisu.plexus/0.3.2/org.eclipse.sisu.plexus-0.3.2.jar",
2954+ "sha1": "cd84cb43788de23847eec2999070f64381bdb495"
2955+ },
2956+ {
2957+ "path": "org/eclipse/sisu/org.eclipse.sisu.plexus/0.3.2/org.eclipse.sisu.plexus-0.3.2.pom",
2958+ "sha1": "2b368076ccdce46590f97214bde1aa0f9413f282"
2959+ },
2960+ {
2961+ "path": "org/eclipse/sisu/sisu-inject/0.3.2/sisu-inject-0.3.2.pom",
2962+ "sha1": "1cfcf623633b3f1d270f38ada2805ec81aec9130"
2963+ },
2964+ {
2965+ "path": "org/eclipse/sisu/sisu-plexus/0.3.2/sisu-plexus-0.3.2.pom",
2966+ "sha1": "cfcccb1005e63760bb7dac857fcfe2bbe9a55414"
2967+ },
2968+ {
2969+ "path": "org/hamcrest/hamcrest-core/1.3/hamcrest-core-1.3.jar",
2970+ "sha1": "42a25dc3219429f0e5d060061f71acb49bf010a0"
2971+ },
2972+ {
2973+ "path": "org/hamcrest/hamcrest-core/1.3/hamcrest-core-1.3.pom",
2974+ "sha1": "872e413497b906e7c9fa85ccc96046c5d1ef7ece"
2975+ },
2976+ {
2977+ "path": "org/hamcrest/hamcrest-parent/1.3/hamcrest-parent-1.3.pom",
2978+ "sha1": "80391bd32bfa4837a15215d5e9f07c60555c379a"
2979+ },
2980+ {
2981+ "path": "org/jacoco/jacoco-maven-plugin/0.8.7/jacoco-maven-plugin-0.8.7.jar",
2982+ "sha1": "3958dec701e6ae1d47c1264d3a74f1a70c35cdad"
2983+ },
2984+ {
2985+ "path": "org/jacoco/jacoco-maven-plugin/0.8.7/jacoco-maven-plugin-0.8.7.pom",
2986+ "sha1": "c742cce4f08c3d70c270fd2113ffccef1b7c8db9"
2987+ },
2988+ {
2989+ "path": "org/jacoco/org.jacoco.agent/0.8.7/org.jacoco.agent-0.8.7-runtime.jar",
2990+ "sha1": "37df187b76888101ecd745282e9cd1ad4ea508d6"
2991+ },
2992+ {
2993+ "path": "org/jacoco/org.jacoco.agent/0.8.7/org.jacoco.agent-0.8.7.pom",
2994+ "sha1": "ea782b5dd63854e0691c3e62a450af8474a907f9"
2995+ },
2996+ {
2997+ "path": "org/jacoco/org.jacoco.build/0.8.7/org.jacoco.build-0.8.7.pom",
2998+ "sha1": "492fd345ea752983327442fe383590995e40a7aa"
2999+ },
3000+ {
3001+ "path": "org/jacoco/org.jacoco.core/0.8.7/org.jacoco.core-0.8.7.jar",
3002+ "sha1": "2c2dc2b720a7fb33afcf4f45b05db2eb5b4ffa10"
3003+ },
3004+ {
3005+ "path": "org/jacoco/org.jacoco.core/0.8.7/org.jacoco.core-0.8.7.pom",
3006+ "sha1": "a26a78c73750f93915a98daac900c5e7a37e4494"
3007+ },
3008+ {
3009+ "path": "org/jacoco/org.jacoco.report/0.8.7/org.jacoco.report-0.8.7.jar",
3010+ "sha1": "be3926576212ef4cbf317fbadd0cc372cc205ab6"
3011+ },
3012+ {
3013+ "path": "org/jacoco/org.jacoco.report/0.8.7/org.jacoco.report-0.8.7.pom",
3014+ "sha1": "e54f4220d1b60811466439dbc463dfa126048d1c"
3015+ },
3016+ {
3017+ "path": "org/jboss/weld/weld-api-bom/1.0/weld-api-bom-1.0.pom",
3018+ "sha1": "efa278108d83f051152fb414e78e231d8ce5b38e"
3019+ },
3020+ {
3021+ "path": "org/jboss/weld/weld-api-parent/1.0/weld-api-parent-1.0.pom",
3022+ "sha1": "508700c6712082eece7e9e29a99286fd70593afa"
3023+ },
3024+ {
3025+ "path": "org/jboss/weld/weld-parent/6/weld-parent-6.pom",
3026+ "sha1": "a6f50e34ff79bc4a5761a35b71d89b07a1d051ec"
3027+ },
3028+ {
3029+ "path": "org/jdom/jdom/1.1/jdom-1.1.jar",
3030+ "sha1": "1d04c0f321ea337f3661cf7ede8f4c6f653a8fdd"
3031+ },
3032+ {
3033+ "path": "org/jdom/jdom2/2.0.6/jdom2-2.0.6.jar",
3034+ "sha1": "6f14738ec2e9dd0011e343717fa624a10f8aab64"
3035+ },
3036+ {
3037+ "path": "org/jdom/jdom2/2.0.6/jdom2-2.0.6.pom",
3038+ "sha1": "11e250d112bc9f2a0e1a595a5f6ecd2802af2691"
3039+ },
3040+ {
3041+ "path": "org/junit/junit-bom/5.7.1/junit-bom-5.7.1.pom",
3042+ "sha1": "ea517dcd1a0692cf193264d3e3ef0cc1a4a7b410"
3043+ },
3044+ {
3045+ "path": "org/junit/junit-bom/5.7.2/junit-bom-5.7.2.pom",
3046+ "sha1": "e8848369738c03e40af5507686216f9b8b44b6a3"
3047+ },
3048+ {
3049+ "path": "org/junit/jupiter/junit-jupiter-api/5.7.2/junit-jupiter-api-5.7.2.jar",
3050+ "sha1": "f4b4079732a9c537983324cfa4e46655f21d2c56"
3051+ },
3052+ {
3053+ "path": "org/junit/jupiter/junit-jupiter-api/5.7.2/junit-jupiter-api-5.7.2.pom",
3054+ "sha1": "e1d9f605ed666ba964fbd02e2a7ca6f8422b529f"
3055+ },
3056+ {
3057+ "path": "org/junit/jupiter/junit-jupiter-engine/5.7.2/junit-jupiter-engine-5.7.2.jar",
3058+ "sha1": "9415680a889f00b8205a094c5c487bc69dc7077d"
3059+ },
3060+ {
3061+ "path": "org/junit/jupiter/junit-jupiter-engine/5.7.2/junit-jupiter-engine-5.7.2.pom",
3062+ "sha1": "840cf93d83c2aa76bb8e70b99824bdc6dfde0220"
3063+ },
3064+ {
3065+ "path": "org/junit/jupiter/junit-jupiter-params/5.7.2/junit-jupiter-params-5.7.2.jar",
3066+ "sha1": "685f832f8c54dd40100f646d61aca88ed9545421"
3067+ },
3068+ {
3069+ "path": "org/junit/jupiter/junit-jupiter-params/5.7.2/junit-jupiter-params-5.7.2.pom",
3070+ "sha1": "80879379707b6c927355922113562afe77b3fcca"
3071+ },
3072+ {
3073+ "path": "org/junit/jupiter/junit-jupiter/5.7.2/junit-jupiter-5.7.2.jar",
3074+ "sha1": "62faa742964a9d8dab8fdb4a0eab7b01441c171f"
3075+ },
3076+ {
3077+ "path": "org/junit/jupiter/junit-jupiter/5.7.2/junit-jupiter-5.7.2.pom",
3078+ "sha1": "88fabd0e43c7d1669c64bb07337bbc3798deb12e"
3079+ },
3080+ {
3081+ "path": "org/junit/platform/junit-platform-commons/1.7.2/junit-platform-commons-1.7.2.jar",
3082+ "sha1": "34adfea6c13fc4a996cf38cdad80800ce850d198"
3083+ },
3084+ {
3085+ "path": "org/junit/platform/junit-platform-commons/1.7.2/junit-platform-commons-1.7.2.pom",
3086+ "sha1": "f3f9908126ecaa774d8d8b015e12612926aaebf3"
3087+ },
3088+ {
3089+ "path": "org/junit/platform/junit-platform-engine/1.7.2/junit-platform-engine-1.7.2.jar",
3090+ "sha1": "2573770b46b8a199ed5f6b0f96fb99e468bfe891"
3091+ },
3092+ {
3093+ "path": "org/junit/platform/junit-platform-engine/1.7.2/junit-platform-engine-1.7.2.pom",
3094+ "sha1": "8c35e134715c567e87b36506e71cd76ef35d2e99"
3095+ },
3096+ {
3097+ "path": "org/mortbay/jetty/jetty-util/6.1.25/jetty-util-6.1.25.jar",
3098+ "sha1": "5527b01ad9c4a12b4101f9ddca31c04ac4fe8614"
3099+ },
3100+ {
3101+ "path": "org/mortbay/jetty/jetty/6.1.25/jetty-6.1.25.jar",
3102+ "sha1": "b242826712e0e5146bf57f07394691cf8cb5f5cd"
3103+ },
3104+ {
3105+ "path": "org/mozilla/rhino/1.7.7.2/rhino-1.7.7.2.jar",
3106+ "sha1": "a7c4a9ba8b6922374580d71060ef71eafa994256"
3107+ },
3108+ {
3109+ "path": "org/mozilla/rhino/1.7.7.2/rhino-1.7.7.2.pom",
3110+ "sha1": "741bec7f31e2980262ebe466970a2a2053369269"
3111+ },
3112+ {
3113+ "path": "org/opentest4j/opentest4j/1.2.0/opentest4j-1.2.0.jar",
3114+ "sha1": "28c11eb91f9b6d8e200631d46e20a7f407f2a046"
3115+ },
3116+ {
3117+ "path": "org/opentest4j/opentest4j/1.2.0/opentest4j-1.2.0.pom",
3118+ "sha1": "b5c66f49b69c36797c1fb7f4ec57776f261303ad"
3119+ },
3120+ {
3121+ "path": "org/ow2/asm/asm-analysis/8.0/asm-analysis-8.0.jar",
3122+ "sha1": "57b12c6a9e14788f63ee3c6c0132fadcce1727d0"
3123+ },
3124+ {
3125+ "path": "org/ow2/asm/asm-analysis/8.0/asm-analysis-8.0.pom",
3126+ "sha1": "e9ef727d5390f9faefafa7bfab2fd4a18e1ebe49"
3127+ },
3128+ {
3129+ "path": "org/ow2/asm/asm-analysis/9.1/asm-analysis-9.1.jar",
3130+ "sha1": "4f61b83b81d8b659958f4bcc48907e93ecea55a0"
3131+ },
3132+ {
3133+ "path": "org/ow2/asm/asm-analysis/9.1/asm-analysis-9.1.pom",
3134+ "sha1": "e30004dc53274dc96d0b9c6a3ac06bdcf6d23d86"
3135+ },
3136+ {
3137+ "path": "org/ow2/asm/asm-commons/8.0/asm-commons-8.0.jar",
3138+ "sha1": "ea2231bdb3394bcca5989db7f7586f743829a9cb"
3139+ },
3140+ {
3141+ "path": "org/ow2/asm/asm-commons/8.0/asm-commons-8.0.pom",
3142+ "sha1": "92946423017f753ede6d4470a763c4eff4a0e2f6"
3143+ },
3144+ {
3145+ "path": "org/ow2/asm/asm-commons/9.1/asm-commons-9.1.jar",
3146+ "sha1": "8b971b182eb5cf100b9e8d4119152d83e00e0fdd"
3147+ },
3148+ {
3149+ "path": "org/ow2/asm/asm-commons/9.1/asm-commons-9.1.pom",
3150+ "sha1": "5914a98fed0e76a0ce92a75704cacaf2454ae90a"
3151+ },
3152+ {
3153+ "path": "org/ow2/asm/asm-tree/8.0/asm-tree-8.0.jar",
3154+ "sha1": "7b31ca94da9f57334a5aed79b40f2b88c5ee9f4f"
3155+ },
3156+ {
3157+ "path": "org/ow2/asm/asm-tree/8.0/asm-tree-8.0.pom",
3158+ "sha1": "e80355a497077d7a16a47c449dfdd83626b0bf9c"
3159+ },
3160+ {
3161+ "path": "org/ow2/asm/asm-tree/9.1/asm-tree-9.1.jar",
3162+ "sha1": "c333f2a855069cb8eb17a40a3eb8b1b67755d0eb"
3163+ },
3164+ {
3165+ "path": "org/ow2/asm/asm-tree/9.1/asm-tree-9.1.pom",
3166+ "sha1": "aeef4f505fe557517394dc29e404fba6ba98c428"
3167+ },
3168+ {
3169+ "path": "org/ow2/asm/asm-util/8.0/asm-util-8.0.jar",
3170+ "sha1": "b21996293fd49851ed9017cfde3191e49f77fbd0"
3171+ },
3172+ {
3173+ "path": "org/ow2/asm/asm-util/8.0/asm-util-8.0.pom",
3174+ "sha1": "83a3d02ed5354a1516e10251f3b3be247c934e87"
3175+ },
3176+ {
3177+ "path": "org/ow2/asm/asm/6.2/asm-6.2.jar",
3178+ "sha1": "1b6c4ff09ce03f3052429139c2a68e295cae6604"
3179+ },
3180+ {
3181+ "path": "org/ow2/asm/asm/6.2/asm-6.2.pom",
3182+ "sha1": "c995a570b9984647aa8557f26691f694c93f76af"
3183+ },
3184+ {
3185+ "path": "org/ow2/asm/asm/8.0/asm-8.0.jar",
3186+ "sha1": "d1a17d07c60e9e82c8b31b1d8f9ca98726418db4"
3187+ },
3188+ {
3189+ "path": "org/ow2/asm/asm/8.0/asm-8.0.pom",
3190+ "sha1": "9498cc1db19c6c8492581795ce3373af0978b105"
3191+ },
3192+ {
3193+ "path": "org/ow2/asm/asm/9.1/asm-9.1.jar",
3194+ "sha1": "a99500cf6eea30535eeac6be73899d048f8d12a8"
3195+ },
3196+ {
3197+ "path": "org/ow2/asm/asm/9.1/asm-9.1.pom",
3198+ "sha1": "927153d04a920d5f06a9a4aefd5f6be60726117d"
3199+ },
3200+ {
3201+ "path": "org/ow2/ow2/1.5/ow2-1.5.pom",
3202+ "sha1": "d8edc69335f4d9f95f511716fb689c86fb0ebaae"
3203+ },
3204+ {
3205+ "path": "org/slf4j/jcl-over-slf4j/1.5.6/jcl-over-slf4j-1.5.6.jar",
3206+ "sha1": "629680940b7dcb02c3904deb85992b462c42e272"
3207+ },
3208+ {
3209+ "path": "org/slf4j/jcl-over-slf4j/1.5.6/jcl-over-slf4j-1.5.6.pom",
3210+ "sha1": "8aa25adef55174f1436073e551953c2f74a5c71b"
3211+ },
3212+ {
3213+ "path": "org/slf4j/slf4j-api/1.5.6/slf4j-api-1.5.6.jar",
3214+ "sha1": "ec9b7142625dfa1dcaf22db99ecb7c555ffa714d"
3215+ },
3216+ {
3217+ "path": "org/slf4j/slf4j-api/1.5.6/slf4j-api-1.5.6.pom",
3218+ "sha1": "b79729ffc12292c0ec755db12360486066f6fd34"
3219+ },
3220+ {
3221+ "path": "org/slf4j/slf4j-api/1.7.2/slf4j-api-1.7.2.jar",
3222+ "sha1": "0081d61b7f33ebeab314e07de0cc596f8e858d97"
3223+ },
3224+ {
3225+ "path": "org/slf4j/slf4j-api/1.7.2/slf4j-api-1.7.2.pom",
3226+ "sha1": "3fceb45ce8f7a6f87f3f2077a24a3833d1ecb4c6"
3227+ },
3228+ {
3229+ "path": "org/slf4j/slf4j-api/1.7.31/slf4j-api-1.7.31.jar",
3230+ "sha1": "9545c9cb71de4c18d97a91e32ef0be6f3f6661b7"
3231+ },
3232+ {
3233+ "path": "org/slf4j/slf4j-api/1.7.31/slf4j-api-1.7.31.pom",
3234+ "sha1": "f81ceb107e2d2a5776c39dcb4064d5f60a25889b"
3235+ },
3236+ {
3237+ "path": "org/slf4j/slf4j-api/1.7.5/slf4j-api-1.7.5.jar",
3238+ "sha1": "6b262da268f8ad9eff941b25503a9198f0a0ac93"
3239+ },
3240+ {
3241+ "path": "org/slf4j/slf4j-api/1.7.5/slf4j-api-1.7.5.pom",
3242+ "sha1": "8bef62de94ecb16f574fadc01dcd3127ddb1a4da"
3243+ },
3244+ {
3245+ "path": "org/slf4j/slf4j-jdk14/1.5.6/slf4j-jdk14-1.5.6.jar",
3246+ "sha1": "cc383fbd07dd1826bbcba1b907bbdc0b5be627f1"
3247+ },
3248+ {
3249+ "path": "org/slf4j/slf4j-jdk14/1.5.6/slf4j-jdk14-1.5.6.pom",
3250+ "sha1": "cbc0f6b542435be20eba2fc698cf209e606ec1b4"
3251+ },
3252+ {
3253+ "path": "org/slf4j/slf4j-log4j12/1.7.31/slf4j-log4j12-1.7.31.jar",
3254+ "sha1": "77f6829fb450ba38bf0cbfdf3706bd180617d1b4"
3255+ },
3256+ {
3257+ "path": "org/slf4j/slf4j-log4j12/1.7.31/slf4j-log4j12-1.7.31.pom",
3258+ "sha1": "56a981ea1aacd2bd69ee5da16ea7c398ffd90520"
3259+ },
3260+ {
3261+ "path": "org/slf4j/slf4j-parent/1.5.6/slf4j-parent-1.5.6.pom",
3262+ "sha1": "7e94cd535680417391d54c1b1a14bcf9ed29a400"
3263+ },
3264+ {
3265+ "path": "org/slf4j/slf4j-parent/1.7.2/slf4j-parent-1.7.2.pom",
3266+ "sha1": "26c68730e36b29249e0c3bb70eba4a5dbaa4f76c"
3267+ },
3268+ {
3269+ "path": "org/slf4j/slf4j-parent/1.7.31/slf4j-parent-1.7.31.pom",
3270+ "sha1": "4ca9e443d3146affc616b84a584fa99c754b1dc8"
3271+ },
3272+ {
3273+ "path": "org/slf4j/slf4j-parent/1.7.5/slf4j-parent-1.7.5.pom",
3274+ "sha1": "2955681f952b108824dfb16ca366f36f3cef7861"
3275+ },
3276+ {
3277+ "path": "org/slf4j/slf4j-simple/1.7.31/slf4j-simple-1.7.31.jar",
3278+ "sha1": "cf5df9007f6fb85f04728eec1dd96de73533fec7"
3279+ },
3280+ {
3281+ "path": "org/slf4j/slf4j-simple/1.7.31/slf4j-simple-1.7.31.pom",
3282+ "sha1": "0149324b7bee90e50da892a4d415f5149ed5e840"
3283+ },
3284+ {
3285+ "path": "org/sonatype/aether/aether-api/1.7/aether-api-1.7.jar",
3286+ "sha1": "0c491a637ee6795143b6708ce5f112e6a9f548f4"
3287+ },
3288+ {
3289+ "path": "org/sonatype/aether/aether-api/1.7/aether-api-1.7.pom",
3290+ "sha1": "07d9331c480f8028c0f009f4b332ff5b18230003"
3291+ },
3292+ {
3293+ "path": "org/sonatype/aether/aether-impl/1.7/aether-impl-1.7.jar",
3294+ "sha1": "5cc1803eb7126f759d34007b74e6dc44e9a9fb08"
3295+ },
3296+ {
3297+ "path": "org/sonatype/aether/aether-impl/1.7/aether-impl-1.7.pom",
3298+ "sha1": "1f6352a67ee0e08fa1cac00e982cdc305d10ce67"
3299+ },
3300+ {
3301+ "path": "org/sonatype/aether/aether-parent/1.7/aether-parent-1.7.pom",
3302+ "sha1": "9272ca55ba8e2a1f03addfd1b698511d5122c646"
3303+ },
3304+ {
3305+ "path": "org/sonatype/aether/aether-spi/1.7/aether-spi-1.7.jar",
3306+ "sha1": "1ea472b28d9d891d353c0311593f5e2a0e73d4be"
3307+ },
3308+ {
3309+ "path": "org/sonatype/aether/aether-spi/1.7/aether-spi-1.7.pom",
3310+ "sha1": "0fdd424fc1f7acd9268c0ceb07fd7aceedb1019f"
3311+ },
3312+ {
3313+ "path": "org/sonatype/aether/aether-util/1.7/aether-util-1.7.jar",
3314+ "sha1": "38485c9c086c3c867c2dd5371909337bd056c492"
3315+ },
3316+ {
3317+ "path": "org/sonatype/aether/aether-util/1.7/aether-util-1.7.pom",
3318+ "sha1": "3bd750dbf22b2effa411117b7230694cc4095f3f"
3319+ },
3320+ {
3321+ "path": "org/sonatype/forge/forge-parent/10/forge-parent-10.pom",
3322+ "sha1": "c24dc843444f348100c19ebd51157e7a5f61bfe7"
3323+ },
3324+ {
3325+ "path": "org/sonatype/forge/forge-parent/3/forge-parent-3.pom",
3326+ "sha1": "fdc1f6eb65f750775acd57ff4371d5657ae2e6d3"
3327+ },
3328+ {
3329+ "path": "org/sonatype/forge/forge-parent/4/forge-parent-4.pom",
3330+ "sha1": "564f266ea9323e57e246f0fca8f04f596663fb86"
3331+ },
3332+ {
3333+ "path": "org/sonatype/forge/forge-parent/5/forge-parent-5.pom",
3334+ "sha1": "a557514263bbd4a6daef8f125ab80e78413292d3"
3335+ },
3336+ {
3337+ "path": "org/sonatype/forge/forge-parent/6/forge-parent-6.pom",
3338+ "sha1": "8726e91194a5442e05472854652602a3b599f27d"
3339+ },
3340+ {
3341+ "path": "org/sonatype/oss/oss-parent/5/oss-parent-5.pom",
3342+ "sha1": "3ae20880ad3d5da6b1caec19e3de7e70dd2dd762"
3343+ },
3344+ {
3345+ "path": "org/sonatype/oss/oss-parent/6/oss-parent-6.pom",
3346+ "sha1": "765c355ec09ad070065d9d12a9245bba5c689d96"
3347+ },
3348+ {
3349+ "path": "org/sonatype/oss/oss-parent/7/oss-parent-7.pom",
3350+ "sha1": "46b8a785b60a2767095b8611613b58577e96d4c9"
3351+ },
3352+ {
3353+ "path": "org/sonatype/oss/oss-parent/9/oss-parent-9.pom",
3354+ "sha1": "e5cdc4d23b86d79c436f16fed20853284e868f65"
3355+ },
3356+ {
3357+ "path": "org/sonatype/plexus/plexus-build-api/0.0.4/plexus-build-api-0.0.4.jar",
3358+ "sha1": "8fdcf45c2fad3052a51385fdfc79753d9124a1a7"
3359+ },
3360+ {
3361+ "path": "org/sonatype/plexus/plexus-build-api/0.0.4/plexus-build-api-0.0.4.pom",
3362+ "sha1": "df389a276b6c493bcea1937339b29145a7ce99bf"
3363+ },
3364+ {
3365+ "path": "org/sonatype/plexus/plexus-cipher/1.4/plexus-cipher-1.4.jar",
3366+ "sha1": "50ade46f23bb38cd984b4ec560c46223432aac38"
3367+ },
3368+ {
3369+ "path": "org/sonatype/plexus/plexus-cipher/1.4/plexus-cipher-1.4.pom",
3370+ "sha1": "8c0bee97c1badb926611bf82358e392fedc07764"
3371+ },
3372+ {
3373+ "path": "org/sonatype/plexus/plexus-sec-dispatcher/1.3/plexus-sec-dispatcher-1.3.jar",
3374+ "sha1": "dedc02034fb8fcd7615d66593228cb71709134b4"
3375+ },
3376+ {
3377+ "path": "org/sonatype/plexus/plexus-sec-dispatcher/1.3/plexus-sec-dispatcher-1.3.pom",
3378+ "sha1": "b953c3a84a7d3f2a7f606e18c07ee38fb6766e3d"
3379+ },
3380+ {
3381+ "path": "org/sonatype/sisu/inject/guice-bean/1.4.2/guice-bean-1.4.2.pom",
3382+ "sha1": "11c2c29c95aa9c9d636ac349b33b49de1190deaf"
3383+ },
3384+ {
3385+ "path": "org/sonatype/sisu/inject/guice-plexus/1.4.2/guice-plexus-1.4.2.pom",
3386+ "sha1": "9b167556a64cb79acea3a8dbf6c2f580e2699d2b"
3387+ },
3388+ {
3389+ "path": "org/sonatype/sisu/sisu-guice/2.1.7/sisu-guice-2.1.7-noaop.jar",
3390+ "sha1": "8cb56e976b8e0e7b23f2969c32bef7b830c6d6ed"
3391+ },
3392+ {
3393+ "path": "org/sonatype/sisu/sisu-guice/2.1.7/sisu-guice-2.1.7.pom",
3394+ "sha1": "f690b118b2c3ca4cf400a558e6d000a971fd8d98"
3395+ },
3396+ {
3397+ "path": "org/sonatype/sisu/sisu-inject-bean/1.4.2/sisu-inject-bean-1.4.2.jar",
3398+ "sha1": "5cf37202afbaae899d63dd51b46d173df650af1b"
3399+ },
3400+ {
3401+ "path": "org/sonatype/sisu/sisu-inject-bean/1.4.2/sisu-inject-bean-1.4.2.pom",
3402+ "sha1": "8b8bd0a19ec8218bb04e27aca13658605c9d7588"
3403+ },
3404+ {
3405+ "path": "org/sonatype/sisu/sisu-inject-plexus/1.4.2/sisu-inject-plexus-1.4.2.jar",
3406+ "sha1": "53d863ed4879d4a43ad7aee7bc63f935cc513353"
3407+ },
3408+ {
3409+ "path": "org/sonatype/sisu/sisu-inject-plexus/1.4.2/sisu-inject-plexus-1.4.2.pom",
3410+ "sha1": "3e27a576e375175ba275f21692d99a386d879405"
3411+ },
3412+ {
3413+ "path": "org/sonatype/sisu/sisu-inject/1.4.2/sisu-inject-1.4.2.pom",
3414+ "sha1": "780340415a1dc940f10ae38a7b32e84db28c95dd"
3415+ },
3416+ {
3417+ "path": "org/sonatype/sisu/sisu-parent/1.4.2/sisu-parent-1.4.2.pom",
3418+ "sha1": "11c9a4a343a22f80cfe4e9677d7b0679850e4196"
3419+ },
3420+ {
3421+ "path": "org/sonatype/spice/spice-parent/10/spice-parent-10.pom",
3422+ "sha1": "8e0e4ba87d63321333c26494698377b1204633a8"
3423+ },
3424+ {
3425+ "path": "org/sonatype/spice/spice-parent/12/spice-parent-12.pom",
3426+ "sha1": "e86b2d826f53093e27dc579bea3becbf1425d9ba"
3427+ },
3428+ {
3429+ "path": "org/sonatype/spice/spice-parent/16/spice-parent-16.pom",
3430+ "sha1": "aefd3135046b7c3f5835283bcc3b670fc46692b9"
3431+ },
3432+ {
3433+ "path": "org/sonatype/spice/spice-parent/17/spice-parent-17.pom",
3434+ "sha1": "7f500699ef371383492a4d6ee799b1a77ffd82cc"
3435+ },
3436+ {
3437+ "path": "org/vafer/jdependency/2.4.0/jdependency-2.4.0.jar",
3438+ "sha1": "78ca0c5e686bf4dede312f53ae2f3bacf9eb7638"
3439+ },
3440+ {
3441+ "path": "org/vafer/jdependency/2.4.0/jdependency-2.4.0.pom",
3442+ "sha1": "a671bc7bf898dd47a3b2df5ce2cffaaed4570e42"
3443+ },
3444+ {
3445+ "path": "org/yaml/snakeyaml/1.24/snakeyaml-1.24.pom",
3446+ "sha1": "605d93a1f7549eb22a18cb85dc8970bd4123e234"
3447+ },
3448+ {
3449+ "path": "org/yaml/snakeyaml/1.26/snakeyaml-1.26.pom",
3450+ "sha1": "ebf6b3e5c0a055d004fe639c22b6831c6e7554e5"
3451+ },
3452+ {
3453+ "path": "org/yaml/snakeyaml/1.27/snakeyaml-1.27.jar",
3454+ "sha1": "359d62567480b07a679dc643f82fc926b100eed5"
3455+ },
3456+ {
3457+ "path": "org/yaml/snakeyaml/1.27/snakeyaml-1.27.pom",
3458+ "sha1": "cedcc7f40ce3aa17b2498344e5e72fc2e9c11acb"
3459+ },
3460+ {
3461+ "path": "oro/oro/2.0.8/oro-2.0.8.jar",
3462+ "sha1": "5592374f834645c4ae250f4c9fbb314c9369d698"
3463+ },
3464+ {
3465+ "path": "oro/oro/2.0.8/oro-2.0.8.pom",
3466+ "sha1": "6d10956ccdb32138560928ba9501648e430c34bb"
3467+ },
3468+ {
3469+ "path": "xml-apis/xml-apis/1.0.b2/xml-apis-1.0.b2.jar",
3470+ "sha1": "3136ca936f64c9d68529f048c2618bd356bf85c9"
3471+ },
3472+ {
3473+ "path": "xml-apis/xml-apis/1.0.b2/xml-apis-1.0.b2.pom",
3474+ "sha1": "2289016f8b8f6a600ce45a199426fe0f6b2be4b0"
3475+ },
3476+ {
3477+ "path": "xml-apis/xml-apis/2.0.2/xml-apis-2.0.2.pom",
3478+ "sha1": "bf2e4baaea312f54f2934c6eb9bbde0a2a4afb07"
3479+ }
3480+ ],
3481+ "groupId": "org.openapitools.openapidiff",
3482+ "metas": [],
3483+ "name": "openapi-diff-parent-2.0.0-SNAPSHOT",
3484+ "remotes": {
3485+ "central": "https://repo.maven.apache.org/maven2"
3486+ },
3487+ "submodules": [
3488+ {
3489+ "artifactId": "openapi-diff-parent",
3490+ "groupId": "org.openapitools.openapidiff",
3491+ "name": "openapi-diff-parent-2.0.0-SNAPSHOT",
3492+ "path": "./",
3493+ "version": "2.0.0-SNAPSHOT"
3494+ },
3495+ {
3496+ "artifactId": "openapi-diff-core",
3497+ "groupId": "org.openapitools.openapidiff",
3498+ "name": "openapi-diff-core-2.0.0-SNAPSHOT",
3499+ "path": "./core",
3500+ "version": "2.0.0-SNAPSHOT"
3501+ },
3502+ {
3503+ "artifactId": "openapi-diff-cli",
3504+ "groupId": "org.openapitools.openapidiff",
3505+ "name": "openapi-diff-cli-2.0.0-SNAPSHOT",
3506+ "path": "./cli",
3507+ "version": "2.0.0-SNAPSHOT"
3508+ }
3509+ ],
3510+ "version": "2.0.0-SNAPSHOT"
3511+}
benchmarks/report.mdnew file+41
@@ -0,0 +1,41 @@
1+| | Typeable | Atlassian | OpenApi Tools | oasdiff | Bump.sh |
2+| -------------------------------------------------------------------------------------------------------------------------- | -------- | --------- | ------------- | ------- | ------- |
3+| [enum-anyof](./enum-anyof) | โœ…โŒ | โœ…โŒ | โœ…โŒ | โœ…โŒ | โœ…โŒ |
4+| [id](./id) | โœ…โŒ | โœ…โŒ | โœ…โŒ | โœ…โŒ | โœ…โŒ |
5+| [json/recursive](./json/recursive) | โœ…โŒ | โœ…โŒ | โœ…โŒ | โœ…โŒ | โœ…โŒ |
6+| [maximum-lowered](./maximum-lowered) | โœ…โŒ | โœ…โŒ | โœ…โŒ | โœ…โŒ | โœ…โŒ |
7+| [pathItem/operation/parameters/allowEmptyValue/reset](./pathItem/operation/parameters/allowEmptyValue/reset) | โœ…โŒ | โœ…โŒ | โœ…โŒ | โœ…โŒ | โœ…โŒ |
8+| [pathItem/operation/parameters/allowEmptyValue/set](./pathItem/operation/parameters/allowEmptyValue/set) | โœ…โŒ | โœ…โŒ | โœ…โŒ | โœ…โŒ | โœ…โŒ |
9+| [pathItem/operation/parameters/change](./pathItem/operation/parameters/change) | โœ…โŒ | โœ…โŒ | โœ…โŒ | โœ…โŒ | โœ…โŒ |
10+| [pathItem/operation/parameters/required/false/add](./pathItem/operation/parameters/required/false/add) | โœ…โŒ | โœ…โŒ | โœ…โŒ | โœ…โŒ | โœ…โŒ |
11+| [pathItem/operation/parameters/required/false/del](./pathItem/operation/parameters/required/false/del) | โœ…โŒ | โœ…โŒ | โœ…โŒ | โœ…โŒ | โœ…โŒ |
12+| [pathItem/operation/parameters/required/reset](./pathItem/operation/parameters/required/reset) | โœ…โŒ | โœ…โŒ | โœ…โŒ | โœ…โŒ | โœ…โŒ |
13+| [pathItem/operation/parameters/required/set](./pathItem/operation/parameters/required/set) | โœ…โŒ | โœ…โŒ | โœ…โŒ | โœ…โŒ | โœ…โŒ |
14+| [pathItem/operation/parameters/required/true/add](./pathItem/operation/parameters/required/true/add) | โœ…โŒ | โœ…โŒ | โœ…โŒ | โœ…โŒ | โœ…โŒ |
15+| [pathItem/operation/parameters/required/true/del](./pathItem/operation/parameters/required/true/del) | โœ…โŒ | โœ…โŒ | โœ…โŒ | โœ…โŒ | โœ…โŒ |
16+| [pathItem/operation/requestBody/mediaTypeObject/add](./pathItem/operation/requestBody/mediaTypeObject/add) | โœ…โŒ | โœ…โŒ | โœ…โŒ | โœ…โŒ | โœ…โŒ |
17+| [pathItem/operation/requestBody/mediaTypeObject/change](./pathItem/operation/requestBody/mediaTypeObject/change) | โœ…โŒ | โœ…โŒ | โœ…โŒ | โœ…โŒ | โœ…โŒ |
18+| [pathItem/operation/requestBody/mediaTypeObject/del](./pathItem/operation/requestBody/mediaTypeObject/del) | โœ…โŒ | โœ…โŒ | โœ…โŒ | โœ…โŒ | โœ…โŒ |
19+| [pathItem/operation/requestBody/required/reset](./pathItem/operation/requestBody/required/reset) | โœ…โŒ | โœ…โŒ | โœ…โŒ | โœ…โŒ | โœ…โŒ |
20+| [pathItem/operation/requestBody/required/set](./pathItem/operation/requestBody/required/set) | โœ…โŒ | โœ…โŒ | โœ…โŒ | โœ…โŒ | โœ…โŒ |
21+| [pathItem/operation/responses/add](./pathItem/operation/responses/add) | โœ…โŒ | โœ…โŒ | โœ…โŒ | โœ…โŒ | โœ…โŒ |
22+| [pathItem/operation/responses/change/headers/mandatory/add](./pathItem/operation/responses/change/headers/mandatory/add) | โœ…โŒ | โœ…โŒ | โœ…โŒ | โœ…โŒ | โœ…โŒ |
23+| [pathItem/operation/responses/change/headers/mandatory/del](./pathItem/operation/responses/change/headers/mandatory/del) | โœ…โŒ | โœ…โŒ | โœ…โŒ | โœ…โŒ | โœ…โŒ |
24+| [pathItem/operation/responses/change/headers/optional/add](./pathItem/operation/responses/change/headers/optional/add) | โœ…โŒ | โœ…โŒ | โœ…โŒ | โœ…โŒ | โœ…โŒ |
25+| [pathItem/operation/responses/change/headers/optional/del](./pathItem/operation/responses/change/headers/optional/del) | โœ…โŒ | โœ…โŒ | โœ…โŒ | โœ…โŒ | โœ…โŒ |
26+| [pathItem/operation/responses/change/mediaTypeObject/add](./pathItem/operation/responses/change/mediaTypeObject/add) | โœ…โŒ | โœ…โŒ | โœ…โŒ | โœ…โŒ | โœ…โŒ |
27+| [pathItem/operation/responses/change/mediaTypeObject/change](./pathItem/operation/responses/change/mediaTypeObject/change) | โœ…โŒ | โœ…โŒ | โœ…โŒ | โœ…โŒ | โœ…โŒ |
28+| [pathItem/operation/responses/change/mediaTypeObject/del](./pathItem/operation/responses/change/mediaTypeObject/del) | โœ…โŒ | โœ…โŒ | โœ…โŒ | โœ…โŒ | โœ…โŒ |
29+| [pathItem/operation/responses/del](./pathItem/operation/responses/del) | โœ…โŒ | โœ…โŒ | โœ…โŒ | โœ…โŒ | โœ…โŒ |
30+| [prod/6159](./prod/6159) | โœ…โŒ | โœ…โŒ | โœ…โŒ | โœ…โŒ | โœ…โŒ |
31+| [prod/enum](./prod/enum) | โœ…โŒ | โœ…โŒ | โœ…โŒ | โœ…โŒ | โœ…โŒ |
32+| [prod/pure](./prod/pure) | โœ…โŒ | โœ…โŒ | โœ…โŒ | โœ…โŒ | โœ…โŒ |
33+| [prod/with-latest](./prod/with-latest) | โœ…โŒ | โœ…โŒ | โœ…โŒ | โœ…โŒ | โœ…โŒ |
34+| [property-removed](./property-removed) | โœ…โŒ | โœ…โŒ | โœ…โŒ | โœ…โŒ | โœ…โŒ |
35+| [property-removed-additional](./property-removed-additional) | โœ…โŒ | โœ…โŒ | โœ…โŒ | โœ…โŒ | โœ…โŒ |
36+| [property-required](./property-required) | โœ…โŒ | โœ…โŒ | โœ…โŒ | โœ…โŒ | โœ…โŒ |
37+| [recursive](./recursive) | โœ…โŒ | โœ…โŒ | โœ…โŒ | โœ…โŒ | โœ…โŒ |
38+| [security-scheme](./security-scheme) | โœ…โŒ | โœ…โŒ | โœ…โŒ | โœ…โŒ | โœ…โŒ |
39+| [servers](./servers) | โœ…โŒ | โœ…โŒ | โœ…โŒ | โœ…โŒ | โœ…โŒ |
40+| [type-changing](./type-changing) | โœ…โŒ | โœ…โŒ | โœ…โŒ | โœ…โŒ | โœ…โŒ |
41+| [unguarded-recursive](./unguarded-recursive) | โœ…โŒ | โœ…โŒ | โœ…โŒ | โœ…โŒ | โœ…โŒ |
ci/policeman.nixnew file+4
@@ -0,0 +1,4 @@
1+{ sources ? import ../nix/sources.nix
2+, pkgs ? import sources.nixpkgs { }
3+}:
4+pkgs.haskellPackages.policeman
openapi-diff.cabal โ†’ compaREST.cabalrenamed+87โˆ’49
@@ -1,28 +1,24 @@
1cabal-version: 2.4
1cabal-version: 2.4
2โˆ’name: openapi-diff
2+name: compaREST
3version: 0.0.0.0
3version: 0.0.0.0
4synopsis: Compatibility checker for OpenAPI
4synopsis: Compatibility checker for OpenAPI
5โˆ’description: Compatibility checker for OpenAPI
5+description: Compatibility checker for OpenAPI.
6license: MIT
6license: MIT
7license-file: LICENSE
7license-file: LICENSE
8โˆ’author: Aleksey Uymanov
8+author: Typeable
9โˆ’maintainer: Aleksey Uymanov <s9gf4ult@gmail.com>
9+maintainer: compaREST@typeable.io
10โˆ’copyright: 2021 Aleksey Uymanov
10+copyright: 2021 Typeable
11category: Web
11category: Web
12build-type: Simple
12build-type: Simple
13extra-doc-files: README.md
13extra-doc-files: README.md
14 CHANGELOG.md
14 CHANGELOG.md
15tested-with: GHC == 8.10.4
15tested-with: GHC == 8.10.4
16โˆ’
16+extra-source-files: awsm-css/dist/awsm.min.css
17โˆ’Flag static
17+data-files:
18โˆ’ Default: False
18+ test/golden/**/*.yaml
19โˆ’ Manual: True
19+ test/golden/**/*.md
20
20
21common common-options
21common common-options
22โˆ’ if flag(static)
23โˆ’ cc-options: -static
24โˆ’ ld-options: -static -pthread
25โˆ’ ghc-options: -static
26 ghc-options:
22 ghc-options:
27 -Weverything
23 -Weverything
28 -Wno-implicit-prelude
24 -Wno-implicit-prelude
@@ -34,11 +30,12 @@ common common-options
34 -Wno-all-missed-specialisations
30 -Wno-all-missed-specialisations
35 -Wno-missing-local-signatures
31 -Wno-missing-local-signatures
36 -Wno-unsafe
32 -Wno-unsafe
33+ -fconstraint-solver-iterations=0
37 default-language: Haskell2010
34 default-language: Haskell2010
38 build-depends: base >= 4.12.0.0 && < 4.16
35 build-depends: base >= 4.12.0.0 && < 4.16
39โˆ’ , bytestring
40 , text
36 , text
41
37
38+
42 default-extensions: ApplicativeDo
39 default-extensions: ApplicativeDo
43 , BangPatterns
40 , BangPatterns
44 , ConstraintKinds
41 , ConstraintKinds
@@ -80,6 +77,7 @@ common common-options
80 , QuantifiedConstraints
77 , QuantifiedConstraints
81 , DefaultSignatures
78 , DefaultSignatures
82
79
80+
83library
81library
84 import: common-options
82 import: common-options
85 build-depends:
83 build-depends:
@@ -107,45 +105,55 @@ library
107 , generic-data
105 , generic-data
108 , doctemplates
106 , doctemplates
109 , file-embed
107 , file-embed
108+ , data-default
109+ , ordered-containers
110+ , bytestring
110 hs-source-dirs: src
111 hs-source-dirs: src
111โˆ’ exposed-modules: Data.HList
112+ exposed-modules: Data.OpenApi.Compare.Behavior
112โˆ’ , OpenAPI.Checker.Behavior
113+ , Data.OpenApi.Compare.Common
113โˆ’ , OpenAPI.Checker.Formula
114+ , Data.OpenApi.Compare.Formula
114โˆ’ , OpenAPI.Checker.Memo
115+ , Data.OpenApi.Compare.Memo
115โˆ’ , OpenAPI.Checker.Orphans
116+ , Data.OpenApi.Compare.Orphans
116โˆ’ , OpenAPI.Checker.Paths
117+ , Data.OpenApi.Compare.Paths
117โˆ’ , OpenAPI.Checker.PathsPrefixTree
118+ , Data.OpenApi.Compare.PathsPrefixTree
118โˆ’ , OpenAPI.Checker.References
119+ , Data.OpenApi.Compare.References
119โˆ’ , OpenAPI.Checker.Subtree
120+ , Data.OpenApi.Compare.Report
121+ , Data.OpenApi.Compare.Report.Html.Template
122+ , Data.OpenApi.Compare.Report.Jet
123+ , Data.OpenApi.Compare.Run
124+ , Data.OpenApi.Compare.Subtree
125+ , Data.OpenApi.Compare.Validate.Header
126+ , Data.OpenApi.Compare.Validate.Link
120โˆ’ , OpenAPI.Checker.Validate.MediaTypeObject
127+ , Data.OpenApi.Compare.Validate.MediaTypeObject
128+ , Data.OpenApi.Compare.Validate.OAuth2Flows
121โˆ’ , OpenAPI.Checker.Validate.OpenApi
129+ , Data.OpenApi.Compare.Validate.OpenApi
122โˆ’ , OpenAPI.Checker.Validate.Operation
130+ , Data.OpenApi.Compare.Validate.Operation
123โˆ’ , OpenAPI.Checker.Validate.Param
131+ , Data.OpenApi.Compare.Validate.Param
124โˆ’ , OpenAPI.Checker.Validate.PathFragment
132+ , Data.OpenApi.Compare.Validate.PathFragment
125โˆ’ , OpenAPI.Checker.Validate.Products
133+ , Data.OpenApi.Compare.Validate.Products
126โˆ’ , OpenAPI.Checker.Validate.RequestBody
134+ , Data.OpenApi.Compare.Validate.RequestBody
127โˆ’ , OpenAPI.Checker.Validate.Responses
135+ , Data.OpenApi.Compare.Validate.Responses
136+ , Data.OpenApi.Compare.Validate.Schema
128โˆ’ , OpenAPI.Checker.Validate.Schema
137+ , Data.OpenApi.Compare.Validate.Schema.DNF
138+ , Data.OpenApi.Compare.Validate.Schema.Issues
139+ , Data.OpenApi.Compare.Validate.Schema.JsonFormula
140+ , Data.OpenApi.Compare.Validate.Schema.Partition
141+ , Data.OpenApi.Compare.Validate.Schema.Process
142+ , Data.OpenApi.Compare.Validate.Schema.Traced
143+ , Data.OpenApi.Compare.Validate.Schema.TypedJson
129โˆ’ , OpenAPI.Checker.Validate.SecurityRequirement
144+ , Data.OpenApi.Compare.Validate.SecurityRequirement
145+ , Data.OpenApi.Compare.Validate.SecurityScheme
130โˆ’ , OpenAPI.Checker.Validate.Server
146+ , Data.OpenApi.Compare.Validate.Server
131โˆ’ , OpenAPI.Checker.Validate.Sums
147+ , Data.OpenApi.Compare.Validate.Sums
132โˆ’ , OpenAPI.Checker.Validate.Header
148+ other-modules: Data.HList
133โˆ’ , OpenAPI.Checker.Validate.Link
134โˆ’ , OpenAPI.Checker.Common
135โˆ’ , OpenAPI.Checker.Validate.SecurityScheme
136โˆ’ , OpenAPI.Checker.Validate.OAuth2Flows
137โˆ’ , OpenAPI.Checker.Report
138 , Data.OpenUnion.Extra
149 , Data.OpenUnion.Extra
139โˆ’ , OpenAPI.Checker.Report.Jet
140โˆ’ , OpenAPI.Checker.Run
141โˆ’ , OpenAPI.Checker.Report.Html.Template
142
150
143โˆ’executable openapi-diff
151+executable compaREST
144 import: common-options
152 import: common-options
145 hs-source-dirs: app
153 hs-source-dirs: app
146 main-is: Main.hs
154 main-is: Main.hs
147 build-depends:
155 build-depends:
148โˆ’ openapi-diff
156+ compaREST
149 , pandoc
157 , pandoc
150 , data-default
158 , data-default
151 , bytestring
159 , bytestring
@@ -156,14 +164,41 @@ executable openapi-diff
156 , aeson
164 , aeson
157 , containers
165 , containers
158 , doctemplates
166 , doctemplates
167+ , pandoc-types
159 ghc-options: -threaded
168 ghc-options: -threaded
160 -rtsopts
169 -rtsopts
161 -with-rtsopts=-N
170 -with-rtsopts=-N
162 other-modules:
171 other-modules:
163 FormatHeuristic
172 FormatHeuristic
164โˆ’ OpenAPI.Checker.Options
173+ Data.OpenApi.Compare.Options
174+
175+executable compaREST-GitHub-Action
176+ import: common-options
177+ hs-source-dirs: github-action
178+ main-is: Main.hs
179+ build-depends:
180+ compaREST
181+ , pandoc
182+ , yaml
183+ , aeson
184+ , github
185+ , freer-simple
186+ , vector
187+ , pandoc-types
188+ , envy
189+ , filepath
190+ , bytestring
191+ ghc-options: -threaded
192+ -rtsopts
193+ -with-rtsopts=-N
194+ other-modules:
195+ Control.Monad.Freer.GitHub
196+ CompaREST.GitHub.API
197+ CompaREST.GitHub.Action.Config
198+ GitHub.Data.Checks
199+ GitHub.Endpoints.Checks
165
200
166โˆ’test-suite openapi-diff-test
201+test-suite compaREST-tests
167 import: common-options
202 import: common-options
168 type: exitcode-stdio-1.0
203 type: exitcode-stdio-1.0
169 hs-source-dirs: test
204 hs-source-dirs: test
@@ -171,8 +206,10 @@ test-suite openapi-diff-test
171 other-modules:
206 other-modules:
172 Spec.Golden.Extra
207 Spec.Golden.Extra
173 Spec.Golden.TraceTree
208 Spec.Golden.TraceTree
209+ Paths_compaREST
210+ autogen-modules: Paths_compaREST
174 build-depends:
211 build-depends:
175โˆ’ , openapi-diff
212+ , compaREST
176 , tasty-golden
213 , tasty-golden
177 , tasty
214 , tasty
178 , bytestring
215 , bytestring
@@ -182,6 +219,7 @@ test-suite openapi-diff-test
182 , pandoc
219 , pandoc
183 , data-default
220 , data-default
184 , lens
221 , lens
222+ , pandoc-types
185 ghc-options: -threaded
223 ghc-options: -threaded
186 -rtsopts
224 -rtsopts
187 -with-rtsopts=-N
225 -with-rtsopts=-N
default.nixnew file+114
@@ -0,0 +1,114 @@
1+{ sources ? import ./nix/sources.nix
2+, haskellNix ? import sources.haskellNix { inherit system; }
3+, pkgs ? import haskellNix.sources.nixpkgs-2105 (haskellNix.nixpkgsArgs // { inherit system; })
4+, system ? builtins.currentSystem
5+, nix-filter ? import sources.nix-filter
6+}:
7+let
8+ masterPkgs = import sources.nixpkgs { inherit system; };
9+
10+ hsPkgs = pkgs.haskell-nix.stackProject {
11+ src = nix-filter {
12+ root = ./.;
13+ name = "compaREST";
14+ include = [
15+ ./stack.yaml
16+ ./stack.yaml.lock
17+ ./compaREST.cabal
18+ ];
19+ };
20+
21+ modules = [
22+ {
23+ dontStrip = false;
24+ dontPatchELF = false;
25+ enableDeadCodeElimination = true;
26+ ghcOptions = [
27+ "-O2"
28+ "-fexpose-all-unfoldings"
29+ "-fspecialise-aggressively"
30+ ];
31+ packages.pandoc.ghcOptions = [ "-O1" ];
32+ packages.compaREST.src = nix-filter {
33+ root = ./.;
34+ name = "compaREST-src";
35+ include = with nix-filter; [
36+ (./compaREST.cabal)
37+ (inDirectory ./test)
38+ (inDirectory ./src)
39+ (inDirectory ./app)
40+ (inDirectory ./github-action)
41+ ./awsm-css/dist/awsm.min.css
42+ ./LICENSE
43+ ];
44+ };
45+ }
46+ ];
47+ };
48+
49+ staticify = name: drv: pkgs.runCommand name { } ''
50+ mkdir -p $out/bin
51+ cp ${drv + "/bin"}/* $out/bin
52+
53+ ${pkgs.nukeReferences}/bin/nuke-refs $out/bin/*
54+ '';
55+
56+ compaRESTBin = hsPkgs.compaREST.components.exes.compaREST;
57+ compaRESTStaticBin = (staticify "compaREST-static" hsPkgs.projectCross.musl64.hsPkgs.compaREST.components.exes.compaREST);
58+
59+
60+ # doesn't work
61+ armDarwinCompaREST = hsPkgs.projectCross.aarch64-darwin.hsPkgs.compaREST.components.exes.compaREST;
62+
63+ compaRESTImage = pkgs.dockerTools.buildImage {
64+ name = "compaREST";
65+ contents = [ compaRESTStaticBin ];
66+ config = {
67+ Entrypoint = [ "/bin/compaREST" ];
68+ };
69+ };
70+
71+ macOSCompaRESTBundle = pkgs.runCommand "compaREST-macOS-bundled"
72+ {
73+ buildInputs = [ masterPkgs.macdylibbundler ];
74+ } ''
75+ mkdir -p $out/lib
76+ cp ${compaRESTBin}/bin/compaREST $out/compaREST
77+ chmod 755 $out/compaREST
78+ dylibbundler -b \
79+ -x $out/compaREST \
80+ -d $out/lib \
81+ -p '@executable_path/lib'
82+ '';
83+
84+
85+ compaRESTGithubAction =
86+ let
87+ action = staticify "compaREST-GitHub-Action-static" hsPkgs.projectCross.musl64.hsPkgs.compaREST.components.exes.compaREST-GitHub-Action;
88+ wrapped = pkgs.runCommand "wrapped-compaREST-GitHub-Action" { buildInputs = [ pkgs.makeWrapper ]; } ''
89+ makeWrapper ${action}/bin/compaREST-GitHub-Action $out/bin/pre --add-flags "pre"
90+ makeWrapper ${action}/bin/compaREST-GitHub-Action $out/bin/run --add-flags "run"
91+ '';
92+ in
93+ pkgs.dockerTools.buildImage {
94+ name = "typeable/compaREST-GitHub-Action";
95+ tag = "latest";
96+ contents = [ wrapped pkgs.cacert ];
97+ };
98+
99+ WindowsCompaRESTBin = hsPkgs.projectCross.mingwW64.hsPkgs.compaREST.components.exes.compaREST;
100+in
101+{
102+ inherit
103+ compaRESTImage
104+ compaRESTGithubAction
105+ compaRESTStaticBin
106+ compaRESTBin
107+ hsPkgs
108+ macOSCompaRESTBundle
109+ WindowsCompaRESTBin;
110+
111+ # We use the static version so that we don't have to rebuild everything on CI.
112+ # The only binaries build on CI are static.
113+ test = hsPkgs.projectCross.musl64.hsPkgs.compaREST.components.tests.compaREST-tests;
114+}
docs/Development_guide.mdnew file+149
@@ -0,0 +1,149 @@
1+CompaREST
2+=========
3+The tool works by simultaneously looking at a pair of nodes in OpenAPI schema
4+trees. At every place we try to understand whether one side (the producer) can
5+produce something that the other side (the consumer) cannot consume. This often
6+involves recursively running the same check on child sub-nodes. The necessary
7+criteria are implemented manually for all types of nodes that appear in the
8+schema. The `Subtree` class in `Data.OpenApi.Compare.Subtree` designates types
9+of nodes for which this compatibility checking is defined. The implementations
10+for various types reside in `Data.OpenApi.Compare.Validate.*`.
11+
12+Producer/Consumer
13+-----------------
14+Rather than looking at which schema is the server's and which is the client's,
15+in terms of compatibility checking it is more useful to track which side is the
16+"producer" and which is the "consumer". At the root of the schema the producer
17+is the client, but as we descend into an HTTP response, the direction flips and
18+the producer becomes the server.
19+
20+We deal with a lot of things in pairs, where one thing belongs to the producer
21+and another belongs to the consumer. The `ProdCons` datatype (in
22+`Data.OpenApi.Compare.Subtree`) is just a pair type that provides an Applicative
23+abstraction for working with two things simultaneously.
24+
25+Trees
26+-----
27+We directly use the datatypes defined in the `openapi3` library. For reasons of
28+identifiability and memoization we tag all nodes in the trees with a path from
29+the root. The tree is heterogeneous (nodes have different types), and every type
30+of node has a different arrangement of children. There is a `Step` data family
31+that defines all the possible children (of a specific type) of a node (of a
32+specific type).
33+
34+A `Trace` is a sequence of steps, except in a path the types of adjacent steps
35+have to agree. The `Paths` datatype achieves this. Together all paths form a
36+`Category`, and we often concatenate them using `>>>`. This is defined in
37+`Data.OpenApi.Compare.Paths`.
38+
39+We often keep a node and a path to it next to each other using an environment
40+comonad. `Traced` is a type alias around `Env` which ensures that the type of
41+the path matches the type of the node.
42+
43+Issues
44+------
45+The output of the tool is a list of compatibility issues that came up during
46+checking. The `Issue` data family describes the kinds of issues that can occur
47+at each type of node. An issue is supposed to characterize a set of interactions
48+(requests or responses) that demonstrate that the schemas are incompatible.
49+
50+Each issue is tagged with a `Behavior` that describes the path to reproducing
51+the issue. While a `Trace` describes a syntactic path down the schema tree, a
52+`Behavior` describes which part of an interaction needs to be focused on for the
53+issue to manifest itself.
54+
55+In most places where we keep multiple issues (e.g. the output), to store them we
56+use a prefix tree map, indexed by both types and values of `Behavior`s. See
57+`Data.OpenApi.Compare.PathsPrefixTree`.
58+
59+Report
60+------
61+The checker ultimately outputs a list of `Issue`s, together with `Behavior`s
62+that cause them. We run the checker twice: forwards and backwards -- to detect
63+non-breaking changes. All of this is then compiled into a report in
64+`Data.OpenApi.Compare.Report`. The tree structure of headings is computed from
65+`Behavior`s, using `Jet`s to collapse particular sequences of behavior steps
66+into a single human-readable header item. The text of each paragraph comes from
67+`describeIssue`.
68+
69+We then use the `pandoc` library to render the report in a variety of formats.
70+
71+Formulas
72+--------
73+The schema has references, so it can end up being recursive. Similarly the
74+process for establishing compatibility can end up being recursive. To keep track
75+of this, the checker actually manipulates *formulas* which can have variables in
76+them, defined in (`Data.OpenApi.Compare.Formula`).
77+
78+A formula represents a set of issues, with the empty set corresponding to a
79+successful compatibility check. A formula can have conjunctions, where we only
80+report success if all parts succeeded, and if not we take the union of all
81+issues. A formula can also have disjunctions, but there it's impossible to
82+guarantee that the issues for the parts also make sense as issues for the whole
83+thing. Due to this if all disjuncted parts have issues we instead return a
84+different issue (usually non-descriptive).
85+
86+The `FormulaF` datatype implements a functor that carries formulaic calculations
87+as well as a result value (a co-Yoneda extension of formulas for the most part).
88+The Applicative interface provides conjunction, and the Alternative interface
89+provides disjunction.
90+
91+When we detect recursion we introduce a variable, compute the compatibility
92+check as a formula with that variable, and then we solve a fixed point equation
93+(`maxFixpoint`) with the variable to obtain the answer.
94+
95+This `FomulaF` is further wrapped in a couple monad transformers
96+(`SemanticCompatFormula`, `StructuralCompatFormula`), and the whole checker is
97+then implemented in the resulting Applicative using ApplicativeDo.
98+
99+Memoization
100+-----------
101+The `Data.OpenApi.Compare.Memo` module contains utilities for stateful
102+memoization and recursion detection. The entire checking process is memoized,
103+and can detect, propagate, and resolve recursion.
104+
105+Structural/Semantic Compatibility
106+---------------------------------
107+When we encounter two nodes we first try to optimistically establish whether
108+they're structurally equal, i.e. the trees are exactly the same modulo reference
109+inlining. This check is also memoized and recursion-aware. If the check succeeds
110+we conclude that the schemas are compatible. Otherwise we fall back to the
111+"normal" semantic compatibility.
112+
113+
114+JSON Schema
115+-----------
116+The language that describes JSON payloads is probably the richest part of
117+OpenAPI schemas, and the checker for it also comes with a lot of moving parts.
118+
119+JSON schema allows arbitrary set arithmetic using `allOf`, `anyOf`, `not` and
120+`oneOf`. To fully check `not` and `oneOf` we would need to compare set
121+subtraction, which involves negating a comparison result. If recursion is
122+involved we would need to be able to solve equations with negation, which we
123+cannot do. So `not` is unsupported altogether, and `oneOf` is only supported
124+when it has disjoint branches and behaves like `anyOf`.
125+
126+With that in mind a JSON schema is first pre-processed into a Disjunctive Normal
127+Form (`DNF` in `Data.OpenApi.Compare.Validate.Schema.DNF`). This pre-processing
128+happens in `Data.OpenApi.Compare.Validate.Schema.Process`.
129+
130+The DNF contains elementary clauses that match on a specific aspect of a JSON
131+object (`Condition`). Most clauses only affect objects of a single type, so JSON
132+values and clauses are segregated by type (`JsonType`, `TypedValue` in
133+`Data.OpenApi.Compare.Validate.Schema.JsonFormula`)
134+
135+Then we reduce the problem of comparing two DNF's to the comparison of a
136+conjunction of clauses in the producer with a single clause in the consumer
137+(`checkFormulas` in `Data.OpenApi.Compare.Validate.Schema`).
138+
139+When we do disjunction in the formula we lose information, so we try to avoid
140+having disjunctions in the consumer DNF. This is done by the means of
141+partitioning. We look for factors that would let us partition the set of all
142+objects into several bins, in a way that hopefully corresponds only a single
143+consumer to each producer. This is implemented in
144+`Data.OpenApi.Compare.Validate.Schema.Partition`. Currently we can only
145+partition by an `enum` value that is accessible via a chain of `required`
146+fields.
147+
148+The same partitioning mechanism is used to test whether the branches of a
149+`oneOf` are disjoint, and emit a warning otherwise.
docs/Integration_guide.mdnew file+51
@@ -0,0 +1,51 @@
1+# Integration guide
2+
3+## Github Actions
4+
5+In cases where your OpenAPI spec can be generated from your code, it can be useful to see how a pull request changes your API. For this very purpose we have a Github Action.
6+
7+### Generating the inputs
8+
9+To use it you need to first get the old (before the pull request) and new (after the pull request) specs.
10+
11+For example:
12+
13+- To get the old spec you can:
14+ - Download from a public "production" server (if your api is public and you provide an OpenAPI spec)
15+ - Checkout the base commit of the pull request and generate is programmatically.
16+
17+ You can checkout the base commit like so in Github Actions:
18+
19+ ```bash
20+ git checkout $(git merge-base ${{ github.event.pull_request.head.sha }} ${{ github.event.pull_request.base.sha }})
21+ ```
22+- To get the new spec you can:
23+ - Build and run the spec generation for the head commit of the pull request
24+
25+### Run the action
26+
27+In our example we have already generated the two OpenAPI specs and placed them in the `old-openapi.yaml` and `new-openapi.yaml` files.
28+
29+We can now run our action:
30+
31+##### NOTE: will only work after public release
32+
33+```yaml
34+- uses: typeable/comparest
35+ with:
36+ old: old-openapi.yaml
37+ new: new-openapi.yaml
38+ project_name: TEST
39+```
40+
41+This will create a check on the pull request displaying the changes (if there are any) similar to this:
42+
43+![](img/github-action-report.png)
44+
45+The check will show success when there are no breaking changes, and be neutral otherwise.
46+
47+## Integrating into something other than Github Actions
48+
49+We have a dedicated implementation only for Github Actions. However, we provide a generic CLI which can be used to integrate compaREST into arbitrary workflows and CI systems.
50+
51+You see an example of CLI usage in our [readme](../README.md#assessing-compatibility-automatically).
docs/User_guide.mdnew file+51
@@ -0,0 +1,51 @@
1+CompaREST User Guide
2+====================
3+
4+Running the Tool
5+----------------
6+The tool accepts two OpenAPI 3.0.0 schema files in either JSON or YAML format.
7+One is assumed to be the client version of the schema, and the other is the
8+server version.
9+
10+The tool will look for changes between the schemas and detect whether they are
11+breaking or not -- that is, if they prevent interoperability between the client
12+and the server.
13+
14+Running:
15+```
16+comparest -c client.json -s server.json
17+```
18+will output a markdown report of the changes to the standard output.
19+
20+Compatibility status can be signaled via the exit code using
21+`--signal-exit-code`. In case no report is needed, output can be suppressed with
22+`--silent`. For example:
23+```
24+comparest -c client.json -s server.json --signal-exit-code --silent
25+echo $?
26+```
27+If there were changes that the tool determined to be breaking, the exit code
28+will be 1. If there were some changes the tool couldn't understand, the exit
29+code will be 2. Otherwise if there were no breaking changes, the exit code will
30+be 0.
31+
32+Controlling the Report
33+----------------------
34+By default the report includes breaking changes, as well as non-breaking:
35+changes that would be considered breaking in the opposite direction. To only
36+include breaking changes in the report use `--only-breaking`. The `--all` option
37+restores the default behavior.
38+
39+The report can be formatted in a variety of ways supported by Pandoc. The `-o`
40+option causes the report to be written to a file. The format of the file is
41+determined from the extension. The supported extensions include:
42+ - `.md` for markdown
43+ - `.html` for an HTML snippet
44+ - `.rst` for restructured text
45+ - no extension for a self-contained HTML document with styles
46+
47+By default the report is split up into parts relating to different paths,
48+requests, responses, etc, using headers of various levels. Alternatively, the
49+report can use indended block-quotes to visualize the tree structure of the
50+report. The header style is enabled with `--header-style`, and the block-quote
51+style is enabled with `--folding-block-quotes-style`.
docs/img/github-action-report.pngnew file

Binary file not shown.

fourmolu.yamlnew file+8
@@ -0,0 +1,8 @@
1+indentation: 2
2+comma-style: leading # for lists, tuples etc. - can also be 'trailing'
3+record-brace-space: true # rec {x = 1} vs. rec{x = 1}
4+indent-wheres: true # 'false' means save space by only half-indenting the 'where' keyword
5+diff-friendly-import-export: false # 'false' uses Ormolu-style lists
6+respectful: true # don't be too opinionated about newlines etc.
7+haddock-style: single-line # '--' vs. '{-'
8+newlines-between-decls: 1 # number of newlines between top-level declarations
github-action/CompaREST/GitHub/API.hsnew file+86
@@ -0,0 +1,86 @@
1+module CompaREST.GitHub.API
2+ ( postStatus,
3+ postStatusProcessing,
4+ )
5+where
6+
7+import CompaREST.GitHub.Action.Config
8+import Control.Monad.Freer
9+import Control.Monad.Freer.GitHub
10+import Control.Monad.Freer.Reader
11+import Control.Monad.IO.Class
12+import Data.Aeson
13+import qualified Data.ByteString.Lazy.Char8 as BSLC
14+import Data.OpenApi.Compare.Report
15+import Data.Proxy
16+import Data.Text (Text)
17+import GitHub
18+import GitHub.Data.Checks
19+import GitHub.Endpoints.Checks
20+
21+postStatusProcessing ::
22+ (Members '[GitHub, Reader Config] effs, MonadIO (Eff effs)) =>
23+ Eff effs ()
24+postStatusProcessing = do
25+ Config {..} <- ask
26+ printJSON $
27+ sendGitHub $
28+ checkR
29+ repoOwner
30+ repoName
31+ Check
32+ { checkName = mkName Proxy $ "compaREST โ€“ " <> projectName
33+ , checkSha = sha
34+ , checkDetailsURL = Nothing
35+ , checkExternalId = Nothing
36+ , checkStatus = Just CheckInProgress
37+ , checkStartedAt = Nothing
38+ , checkConclusion = Nothing
39+ , checkCompletedAt = Nothing
40+ , checkOutput = Nothing
41+ , checkActions = Nothing
42+ }
43+
44+postStatus ::
45+ (Members '[GitHub, Reader Config] effs, MonadIO (Eff effs)) =>
46+ -- | 'Nothing' means that there were no changes at all
47+ Maybe (Text, ReportStatus) ->
48+ Eff effs ()
49+postStatus x = do
50+ let (body, (title, conclusion)) = case x of
51+ Just (b, s) -> (b,) $ case s of
52+ BreakingChanges -> ("โš ๏ธ Breaking changes found!", CheckNeutral)
53+ NoBreakingChanges -> ("No breaking changes found โœจ", CheckSuccess)
54+ OnlyUnsupportedChanges -> ("๐Ÿคท Couldn't determine compatibility", CheckNeutral)
55+ Nothing -> ("", ("โœ… The API did not change", CheckSuccess))
56+ Config {..} <- ask
57+ printJSON $
58+ sendGitHub $
59+ checkR
60+ repoOwner
61+ repoName
62+ Check
63+ { checkName = mkName Proxy $ "compaREST โ€“ " <> projectName
64+ , checkSha = sha
65+ , checkDetailsURL = Nothing
66+ , checkExternalId = Nothing
67+ , checkStatus = Just CheckCompleted
68+ , checkStartedAt = Nothing
69+ , checkConclusion = Just conclusion
70+ , checkCompletedAt = Nothing
71+ , checkOutput =
72+ Just $
73+ CheckOutput
74+ { checkTitle = title
75+ , checkSummary = body
76+ , checkText = Nothing
77+ , checkAnnotations = Nothing
78+ , checkImages = Nothing
79+ }
80+ , checkActions = Nothing
81+ }
82+
83+printJSON :: MonadIO (Eff effs) => Eff effs Value -> Eff effs ()
84+printJSON m = do
85+ x <- m
86+ liftIO . BSLC.putStrLn $ encode x
github-action/CompaREST/GitHub/Action/Config.hsnew file+43
@@ -0,0 +1,43 @@
1+module CompaREST.GitHub.Action.Config
2+ ( Config (..),
3+ )
4+where
5+
6+import Data.Proxy
7+import Data.Text (Text)
8+import qualified Data.Text as T
9+import qualified GitHub as GH
10+
11+import System.Envy
12+
13+data Config = Config
14+ { githubToken :: GH.Auth
15+ , repoOwner :: GH.Name GH.Owner
16+ , repoName :: GH.Name GH.Repo
17+ , projectName :: Text
18+ , footerText :: Text
19+ , root :: FilePath
20+ , sha :: GH.Name GH.Commit
21+ }
22+
23+instance FromEnv Config where
24+ fromEnv _ = do
25+ token <- GH.OAuth <$> env "GITHUB_TOKEN"
26+ (owner, repo) <-
27+ T.split (== '/') <$> env "REPO" >>= \case
28+ [owner, name] -> pure (owner, name)
29+ _ -> fail "malformed repo"
30+ projectName <- env "PROJECT_NAME"
31+ footerText <- env "FOOTER"
32+ root <- envMaybe "ROOT" .!= "."
33+ sha <- env "SHA"
34+ pure $
35+ Config
36+ { githubToken = token
37+ , repoOwner = GH.mkName Proxy owner
38+ , repoName = GH.mkName Proxy repo
39+ , projectName = projectName
40+ , footerText = footerText
41+ , root = root
42+ , sha = GH.mkName Proxy sha
43+ }
github-action/Control/Monad/Freer/GitHub.hsnew file+27
@@ -0,0 +1,27 @@
1+module Control.Monad.Freer.GitHub
2+ ( GitHub (..),
3+ runGitHub,
4+ sendGitHub,
5+ )
6+where
7+
8+import Control.Monad.Freer
9+import Control.Monad.Freer.Error
10+import Control.Monad.IO.Class
11+import Data.Aeson
12+import GitHub hiding (Error)
13+import qualified GitHub as GH
14+
15+data GitHub r where
16+ SendGHRequest :: FromJSON x => Request 'RW x -> GitHub x
17+
18+runGitHub :: (Member (Error GH.Error) effs, MonadIO (Eff effs)) => Auth -> Eff (GitHub ': effs) ~> Eff effs
19+runGitHub auth =
20+ interpret
21+ ( \(SendGHRequest req) ->
22+ liftIO (executeRequest auth req)
23+ >>= either throwError pure
24+ )
25+
26+sendGitHub :: (FromJSON x, Member GitHub effs) => Request 'RW x -> Eff effs x
27+sendGitHub req = send $ SendGHRequest req
github-action/GitHub/Data/Checks.hsnew file+173
@@ -0,0 +1,173 @@
1+module GitHub.Data.Checks
2+ ( Check (..),
3+ CheckStatus (..),
4+ CheckConclusion (..),
5+ CheckOutput (..),
6+ CheckAnnotation (..),
7+ CheckAnnotationLevel (..),
8+ CheckImage (..),
9+ CheckAction (..),
10+ )
11+where
12+
13+import Data.Aeson
14+import Data.Aeson.Types
15+import Data.Text (Text)
16+import Data.Vector (Vector)
17+import GHC.Generics (Generic)
18+import GitHub
19+import GitHub.Internal.Prelude (UTCTime)
20+
21+data Check = Check
22+ { checkName :: !(Name Check)
23+ , checkSha :: !(Name Commit)
24+ , checkDetailsURL :: !(Maybe URL)
25+ , checkExternalId :: !(Maybe (Id Check))
26+ , checkStatus :: !(Maybe CheckStatus)
27+ , checkStartedAt :: !(Maybe UTCTime)
28+ , checkConclusion :: !(Maybe CheckConclusion)
29+ , checkCompletedAt :: !(Maybe UTCTime)
30+ , checkOutput :: !(Maybe CheckOutput)
31+ , checkActions :: !(Maybe (Vector CheckAction))
32+ }
33+ deriving stock (Show, Eq, Ord, Generic)
34+
35+instance ToJSON Check where
36+ toJSON (Check n sha durl eid s sa c ca o a) =
37+ object'
38+ [ "name" .= n
39+ , "head_sha" .= sha
40+ , "details_url" .= durl
41+ , "external_id" .= eid
42+ , "status" .= s
43+ , "started_at" .= sa
44+ , "conclusion" .= c
45+ , "completed_at" .= ca
46+ , "output" .= o
47+ , "actions" .= a
48+ ]
49+
50+data CheckStatus
51+ = CheckQueued
52+ | CheckInProgress
53+ | CheckCompleted
54+ deriving stock (Show, Enum, Bounded, Eq, Ord, Generic)
55+
56+instance ToJSON CheckStatus where
57+ toJSON CheckQueued = String "queued"
58+ toJSON CheckInProgress = String "in_progress"
59+ toJSON CheckCompleted = String "completed"
60+
61+data CheckConclusion
62+ = CheckActionRequired
63+ | CheckCancelled
64+ | CheckFailure
65+ | CheckNeutral
66+ | CheckSuccess
67+ | CheckSkipped
68+ | CheckStale
69+ | CheckTimedOut
70+ deriving stock (Show, Enum, Bounded, Eq, Ord, Generic)
71+
72+instance ToJSON CheckConclusion where
73+ toJSON CheckActionRequired = String "action_required"
74+ toJSON CheckCancelled = String "cancelled"
75+ toJSON CheckFailure = String "failure"
76+ toJSON CheckNeutral = String "neutral"
77+ toJSON CheckSuccess = String "success"
78+ toJSON CheckSkipped = String "skipped"
79+ toJSON CheckStale = String "stale"
80+ toJSON CheckTimedOut = String "timed_out"
81+
82+data CheckOutput = CheckOutput
83+ { checkTitle :: !Text
84+ , checkSummary :: !Text
85+ , checkText :: !(Maybe Text)
86+ , checkAnnotations :: !(Maybe (Vector CheckAnnotation))
87+ , checkImages :: !(Maybe (Vector CheckImage))
88+ }
89+ deriving stock (Show, Eq, Ord, Generic)
90+
91+instance ToJSON CheckOutput where
92+ toJSON (CheckOutput t s txt a i) =
93+ object'
94+ [ "title" .= t
95+ , "summary" .= s
96+ , "text" .= txt
97+ , "annotations" .= a
98+ , "images" .= i
99+ ]
100+
101+data CheckAnnotation = CheckAnnotation
102+ { checkPath :: !Text
103+ , checkStartLine :: !Int
104+ , checkEndLine :: !Int
105+ , checkStartColumn :: !(Maybe Int)
106+ , checkEndColumn :: !(Maybe Int)
107+ , checkAnnotationLevel :: !CheckAnnotationLevel
108+ , checkMessage :: !Text
109+ , checkTitle :: !(Maybe Text)
110+ , checkRawDetails :: !(Maybe Text)
111+ }
112+ deriving stock (Show, Eq, Ord, Generic)
113+
114+instance ToJSON CheckAnnotation where
115+ toJSON (CheckAnnotation p sl el sc ec al m t rd) =
116+ object'
117+ [ "path" .= p
118+ , "start_line" .= sl
119+ , "end_line" .= el
120+ , "start_column" .= sc
121+ , "end_column" .= ec
122+ , "annotation_level" .= al
123+ , "message" .= m
124+ , "title" .= t
125+ , "raw_details" .= rd
126+ ]
127+
128+data CheckAnnotationLevel
129+ = NoticeAnnotation
130+ | WarningAnnotation
131+ | FailureAnnotation
132+ deriving stock (Show, Enum, Bounded, Eq, Ord, Generic)
133+
134+instance ToJSON CheckAnnotationLevel where
135+ toJSON NoticeAnnotation = String "notice"
136+ toJSON WarningAnnotation = String "warning"
137+ toJSON FailureAnnotation = String "failure"
138+
139+data CheckImage = CheckImage
140+ { checkImageAlt :: !Text
141+ , checkImageURL :: !URL
142+ , checkImageCaption :: !(Maybe Text)
143+ }
144+ deriving stock (Show, Eq, Ord, Generic)
145+
146+instance ToJSON CheckImage where
147+ toJSON (CheckImage a url c) =
148+ object'
149+ [ "alt" .= a
150+ , "image_url" .= url
151+ , "caption" .= c
152+ ]
153+
154+data CheckAction = CheckAction
155+ { checkActionLabel :: !Text
156+ , checkActionDescription :: !Text
157+ , checkActionIdentifier :: !Text
158+ }
159+ deriving stock (Show, Eq, Ord, Generic)
160+
161+instance ToJSON CheckAction where
162+ toJSON (CheckAction l d i) =
163+ object'
164+ [ "label" .= l
165+ , "description" .= d
166+ , "identifier" .= i
167+ ]
168+
169+object' :: [Pair] -> Value
170+object' = object . filter notNull
171+ where
172+ notNull (_, Null) = False
173+ notNull (_, _) = True
github-action/GitHub/Endpoints/Checks.hsnew file+12
@@ -0,0 +1,12 @@
1+module GitHub.Endpoints.Checks
2+ ( checkR,
3+ )
4+where
5+
6+import Data.Aeson
7+import GitHub
8+import GitHub.Data.Checks
9+
10+checkR :: Name Owner -> Name Repo -> Check -> Request 'RW Value
11+checkR user repo =
12+ command Post ["repos", toPathPart user, toPathPart repo, "check-runs"] . encode
github-action/Main.hsnew file+66
@@ -0,0 +1,66 @@
1+module Main (main) where
2+
3+import CompaREST.GitHub.API
4+import CompaREST.GitHub.Action.Config
5+import Control.Exception
6+import Control.Monad.Freer
7+import Control.Monad.Freer.Error
8+import Control.Monad.Freer.GitHub
9+import Control.Monad.Freer.Reader
10+import Data.OpenApi.Compare.Run
11+import Data.Text (Text)
12+import qualified Data.Yaml.Aeson as Yaml
13+import qualified GitHub as GH
14+import System.Environment
15+import System.Envy (decodeEnv)
16+import System.FilePath ((</>))
17+import Text.Pandoc (runPure)
18+import Text.Pandoc.Builder
19+import Text.Pandoc.Options
20+import Text.Pandoc.Writers
21+
22+main :: IO ()
23+main = do
24+ cfg <- decodeEnv >>= either error pure
25+ getArgs >>= \case
26+ ["pre"] -> runPre cfg
27+ ["run"] -> do
28+ oldFile <- getEnv "OLD"
29+ newFile <- getEnv "NEW"
30+ runRun cfg (root cfg </> oldFile) (root cfg </> newFile)
31+ _ -> error "Invalid arguments."
32+
33+runner :: Config -> Eff '[GitHub, Error GH.Error, Reader Config, IO] a -> IO a
34+runner cfg =
35+ runM @IO . runReader cfg
36+ . flip (handleError @GH.Error) (error . displayException)
37+ . runGitHub (githubToken cfg)
38+
39+runPre :: Config -> IO ()
40+runPre cfg = runner cfg postStatusProcessing
41+
42+runRun :: Config -> FilePath -> FilePath -> IO ()
43+runRun cfg old' new' = runner cfg $ do
44+ old <- Yaml.decodeFileThrow old'
45+ new <- Yaml.decodeFileThrow new'
46+ let reportConfig =
47+ ReportConfig
48+ { treeStyle = FoldingBlockquotesTreeStyle
49+ , reportMode = All
50+ }
51+ (report, status) = runReport reportConfig (old, new)
52+
53+ body = markdown report <> "\n\n" <> footerText cfg
54+
55+ result =
56+ if old == new
57+ then Nothing
58+ else Just (body, status)
59+ postStatus result
60+
61+markdown :: Blocks -> Text
62+markdown =
63+ either (error . displayException) id
64+ . runPure
65+ . writeHtml5String def
66+ . doc
nix/ci.nixnew file+6
@@ -0,0 +1,6 @@
1+{ sources ? import ./sources.nix
2+, pkgs ? import sources.nixpkgs { }
3+}:
4+pkgs.mkShell {
5+ packages = [ pkgs.haskellPackages.fourmolu ];
6+}
nix/sources.jsonnew file+50
@@ -0,0 +1,50 @@
1+{
2+ "haskellNix": {
3+ "branch": "master",
4+ "description": "Alternative Haskell Infrastructure for Nixpkgs",
5+ "homepage": "https://input-output-hk.github.io/haskell.nix",
6+ "owner": "input-output-hk",
7+ "repo": "haskell.nix",
8+ "rev": "c8a8f57de3c14fcf1c5cda045ed885fb6d06a00e",
9+ "sha256": "0frzmvz8rhb4vgx20qms9xxqbkmg5pwivis4qis63ny5wxclzb34",
10+ "type": "tarball",
11+ "url": "https://github.com/input-output-hk/haskell.nix/archive/c8a8f57de3c14fcf1c5cda045ed885fb6d06a00e.tar.gz",
12+ "url_template": "https://github.com/<owner>/<repo>/archive/<rev>.tar.gz"
13+ },
14+ "niv": {
15+ "branch": "master",
16+ "description": "Easy dependency management for Nix projects",
17+ "homepage": "https://github.com/nmattia/niv",
18+ "owner": "nmattia",
19+ "repo": "niv",
20+ "rev": "5830a4dd348d77e39a0f3c4c762ff2663b602d4c",
21+ "sha256": "1d3lsrqvci4qz2hwjrcnd8h5vfkg8aypq3sjd4g3izbc8frwz5sm",
22+ "type": "tarball",
23+ "url": "https://github.com/nmattia/niv/archive/5830a4dd348d77e39a0f3c4c762ff2663b602d4c.tar.gz",
24+ "url_template": "https://github.com/<owner>/<repo>/archive/<rev>.tar.gz"
25+ },
26+ "nix-filter": {
27+ "branch": "master",
28+ "description": "a small self-container source filtering lib",
29+ "homepage": "",
30+ "owner": "numtide",
31+ "repo": "nix-filter",
32+ "rev": "3c9e33ed627e009428197b07216613206f06ed80",
33+ "sha256": "19w142crrkywxynmyw4rhz4nglrg64yjawfkw3j91qwkwbfjds84",
34+ "type": "tarball",
35+ "url": "https://github.com/numtide/nix-filter/archive/3c9e33ed627e009428197b07216613206f06ed80.tar.gz",
36+ "url_template": "https://github.com/<owner>/<repo>/archive/<rev>.tar.gz"
37+ },
38+ "nixpkgs": {
39+ "branch": "master",
40+ "description": "Nix Packages collection",
41+ "homepage": "",
42+ "owner": "NixOS",
43+ "repo": "nixpkgs",
44+ "rev": "f0fe5e9ba08e658474476317717aca7acacef4d4",
45+ "sha256": "1n5syynwmg3x8lj2kyb2ilbxw5nmw7f2kw6yxsi8qadx91hrvkwm",
46+ "type": "tarball",
47+ "url": "https://github.com/NixOS/nixpkgs/archive/f0fe5e9ba08e658474476317717aca7acacef4d4.tar.gz",
48+ "url_template": "https://github.com/<owner>/<repo>/archive/<rev>.tar.gz"
49+ }
50+}
nix/sources.nixnew file+174
@@ -0,0 +1,174 @@
1+# This file has been generated by Niv.
2+
3+let
4+
5+ #
6+ # The fetchers. fetch_<type> fetches specs of type <type>.
7+ #
8+
9+ fetch_file = pkgs: name: spec:
10+ let
11+ name' = sanitizeName name + "-src";
12+ in
13+ if spec.builtin or true then
14+ builtins_fetchurl { inherit (spec) url sha256; name = name'; }
15+ else
16+ pkgs.fetchurl { inherit (spec) url sha256; name = name'; };
17+
18+ fetch_tarball = pkgs: name: spec:
19+ let
20+ name' = sanitizeName name + "-src";
21+ in
22+ if spec.builtin or true then
23+ builtins_fetchTarball { name = name'; inherit (spec) url sha256; }
24+ else
25+ pkgs.fetchzip { name = name'; inherit (spec) url sha256; };
26+
27+ fetch_git = name: spec:
28+ let
29+ ref =
30+ if spec ? ref then spec.ref else
31+ if spec ? branch then "refs/heads/${spec.branch}" else
32+ if spec ? tag then "refs/tags/${spec.tag}" else
33+ abort "In git source '${name}': Please specify `ref`, `tag` or `branch`!";
34+ in
35+ builtins.fetchGit { url = spec.repo; inherit (spec) rev; inherit ref; };
36+
37+ fetch_local = spec: spec.path;
38+
39+ fetch_builtin-tarball = name: throw
40+ ''[${name}] The niv type "builtin-tarball" is deprecated. You should instead use `builtin = true`.
41+ $ niv modify ${name} -a type=tarball -a builtin=true'';
42+
43+ fetch_builtin-url = name: throw
44+ ''[${name}] The niv type "builtin-url" will soon be deprecated. You should instead use `builtin = true`.
45+ $ niv modify ${name} -a type=file -a builtin=true'';
46+
47+ #
48+ # Various helpers
49+ #
50+
51+ # https://github.com/NixOS/nixpkgs/pull/83241/files#diff-c6f540a4f3bfa4b0e8b6bafd4cd54e8bR695
52+ sanitizeName = name:
53+ (
54+ concatMapStrings (s: if builtins.isList s then "-" else s)
55+ (
56+ builtins.split "[^[:alnum:]+._?=-]+"
57+ ((x: builtins.elemAt (builtins.match "\\.*(.*)" x) 0) name)
58+ )
59+ );
60+
61+ # The set of packages used when specs are fetched using non-builtins.
62+ mkPkgs = sources: system:
63+ let
64+ sourcesNixpkgs =
65+ import (builtins_fetchTarball { inherit (sources.nixpkgs) url sha256; }) { inherit system; };
66+ hasNixpkgsPath = builtins.any (x: x.prefix == "nixpkgs") builtins.nixPath;
67+ hasThisAsNixpkgsPath = <nixpkgs> == ./.;
68+ in
69+ if builtins.hasAttr "nixpkgs" sources
70+ then sourcesNixpkgs
71+ else if hasNixpkgsPath && ! hasThisAsNixpkgsPath then
72+ import <nixpkgs> {}
73+ else
74+ abort
75+ ''
76+ Please specify either <nixpkgs> (through -I or NIX_PATH=nixpkgs=...) or
77+ add a package called "nixpkgs" to your sources.json.
78+ '';
79+
80+ # The actual fetching function.
81+ fetch = pkgs: name: spec:
82+
83+ if ! builtins.hasAttr "type" spec then
84+ abort "ERROR: niv spec ${name} does not have a 'type' attribute"
85+ else if spec.type == "file" then fetch_file pkgs name spec
86+ else if spec.type == "tarball" then fetch_tarball pkgs name spec
87+ else if spec.type == "git" then fetch_git name spec
88+ else if spec.type == "local" then fetch_local spec
89+ else if spec.type == "builtin-tarball" then fetch_builtin-tarball name
90+ else if spec.type == "builtin-url" then fetch_builtin-url name
91+ else
92+ abort "ERROR: niv spec ${name} has unknown type ${builtins.toJSON spec.type}";
93+
94+ # If the environment variable NIV_OVERRIDE_${name} is set, then use
95+ # the path directly as opposed to the fetched source.
96+ replace = name: drv:
97+ let
98+ saneName = stringAsChars (c: if isNull (builtins.match "[a-zA-Z0-9]" c) then "_" else c) name;
99+ ersatz = builtins.getEnv "NIV_OVERRIDE_${saneName}";
100+ in
101+ if ersatz == "" then drv else
102+ # this turns the string into an actual Nix path (for both absolute and
103+ # relative paths)
104+ if builtins.substring 0 1 ersatz == "/" then /. + ersatz else /. + builtins.getEnv "PWD" + "/${ersatz}";
105+
106+ # Ports of functions for older nix versions
107+
108+ # a Nix version of mapAttrs if the built-in doesn't exist
109+ mapAttrs = builtins.mapAttrs or (
110+ f: set: with builtins;
111+ listToAttrs (map (attr: { name = attr; value = f attr set.${attr}; }) (attrNames set))
112+ );
113+
114+ # https://github.com/NixOS/nixpkgs/blob/0258808f5744ca980b9a1f24fe0b1e6f0fecee9c/lib/lists.nix#L295
115+ range = first: last: if first > last then [] else builtins.genList (n: first + n) (last - first + 1);
116+
117+ # https://github.com/NixOS/nixpkgs/blob/0258808f5744ca980b9a1f24fe0b1e6f0fecee9c/lib/strings.nix#L257
118+ stringToCharacters = s: map (p: builtins.substring p 1 s) (range 0 (builtins.stringLength s - 1));
119+
120+ # https://github.com/NixOS/nixpkgs/blob/0258808f5744ca980b9a1f24fe0b1e6f0fecee9c/lib/strings.nix#L269
121+ stringAsChars = f: s: concatStrings (map f (stringToCharacters s));
122+ concatMapStrings = f: list: concatStrings (map f list);
123+ concatStrings = builtins.concatStringsSep "";
124+
125+ # https://github.com/NixOS/nixpkgs/blob/8a9f58a375c401b96da862d969f66429def1d118/lib/attrsets.nix#L331
126+ optionalAttrs = cond: as: if cond then as else {};
127+
128+ # fetchTarball version that is compatible between all the versions of Nix
129+ builtins_fetchTarball = { url, name ? null, sha256 }@attrs:
130+ let
131+ inherit (builtins) lessThan nixVersion fetchTarball;
132+ in
133+ if lessThan nixVersion "1.12" then
134+ fetchTarball ({ inherit url; } // (optionalAttrs (!isNull name) { inherit name; }))
135+ else
136+ fetchTarball attrs;
137+
138+ # fetchurl version that is compatible between all the versions of Nix
139+ builtins_fetchurl = { url, name ? null, sha256 }@attrs:
140+ let
141+ inherit (builtins) lessThan nixVersion fetchurl;
142+ in
143+ if lessThan nixVersion "1.12" then
144+ fetchurl ({ inherit url; } // (optionalAttrs (!isNull name) { inherit name; }))
145+ else
146+ fetchurl attrs;
147+
148+ # Create the final "sources" from the config
149+ mkSources = config:
150+ mapAttrs (
151+ name: spec:
152+ if builtins.hasAttr "outPath" spec
153+ then abort
154+ "The values in sources.json should not have an 'outPath' attribute"
155+ else
156+ spec // { outPath = replace name (fetch config.pkgs name spec); }
157+ ) config.sources;
158+
159+ # The "config" used by the fetchers
160+ mkConfig =
161+ { sourcesFile ? if builtins.pathExists ./sources.json then ./sources.json else null
162+ , sources ? if isNull sourcesFile then {} else builtins.fromJSON (builtins.readFile sourcesFile)
163+ , system ? builtins.currentSystem
164+ , pkgs ? mkPkgs sources system
165+ }: rec {
166+ # The sources, i.e. the attribute set of spec name to spec
167+ inherit sources;
168+
169+ # The "pkgs" (evaluated nixpkgs) to use for e.g. non-builtin fetchers
170+ inherit pkgs;
171+ };
172+
173+in
174+mkSources (mkConfig {}) // { __functor = _: settings: mkSources (mkConfig settings); }
policeman.jsonnew file+6
@@ -0,0 +1,6 @@
1+[{
2+ "file": "compaREST.cabal",
3+ "annotation_level": "notice",
4+ "end_line": 0,
5+ "start_line": 0
6+}]
src/Data/HList.hs+37โˆ’7
@@ -1,9 +1,11 @@
1module Data.HList
1module Data.HList
2โˆ’ ( Has
2+ ( Has,
3โˆ’ , HasAll
3+ HasAll,
4โˆ’ , getH
4+ getH,
5โˆ’ , HList (..)
5+ HList (..),
6โˆ’ , singletonH
6+ singletonH,
7+ ReassembleHList,
8+ reassemble,
7 )
9 )
8where
10where
9
11
@@ -31,21 +33,49 @@ class t ~ HeadEq x xs => Has' (x :: Type) (xs :: [Type]) (t :: Bool) where
31
33
32instance Has' x (x ': xs) 'True where
34instance Has' x (x ': xs) 'True where
33 getH (HCons x _) = x
35 getH (HCons x _) = x
36+ {-# INLINE getH #-}
34
37
35instance (Has' x xs t, HeadEq x (y : xs) ~ 'False) => Has' x (y ': xs) 'False where
38instance (Has' x xs t, HeadEq x (y : xs) ~ 'False) => Has' x (y ': xs) 'False where
36 getH (HCons _ xs) = getH xs
39 getH (HCons _ xs) = getH xs
40+ {-# INLINE getH #-}
37
41
38instance
42instance
39โˆ’ TypeError ('ShowType x ':<>: 'Text " is not a part of the list.")
43+ TypeError ( 'ShowType x ':<>: 'Text " is not a part of the list.") =>
40โˆ’ => Has' x '[] 'False
44+ Has' x '[] 'False
41 where
45 where
42 getH HNil = undefined
46 getH HNil = undefined
47+ {-# INLINE getH #-}
43
48
44singletonH :: a -> HList '[a]
49singletonH :: a -> HList '[a]
45singletonH a = a `HCons` HNil
50singletonH a = a `HCons` HNil
51+{-# INLINE singletonH #-}
46
52
47instance Eq (HList '[]) where
53instance Eq (HList '[]) where
48 HNil == HNil = True
54 HNil == HNil = True
49
55
50instance (Eq x, Eq (HList xs)) => Eq (HList (x ': xs)) where
56instance (Eq x, Eq (HList xs)) => Eq (HList (x ': xs)) where
51 (HCons x xs) == (HCons y ys) = x == y && xs == ys
57 (HCons x xs) == (HCons y ys) = x == y && xs == ys
58+
59+type family (==) a b :: Bool where
60+ a == a = 'True
61+ _ == _ = 'False
62+
63+type ReassembleHList xs ys = ReassembleHList' xs ys (xs == ys)
64+
65+class f ~ (xs == ys) => ReassembleHList' xs ys f where
66+ reassemble :: HList xs -> HList ys
67+
68+instance ReassembleHList' xs xs 'True where
69+ reassemble = id
70+ {-# INLINE reassemble #-}
71+
72+instance ReassembleHList' (x ': xs) '[] 'False where
73+ reassemble _ = HNil
74+ {-# INLINE reassemble #-}
75+
76+instance
77+ (Has y xs, ReassembleHList' xs ys f, (xs == (y ': ys)) ~ 'False) =>
78+ ReassembleHList' xs (y ': ys) 'False
79+ where
80+ reassemble xs = getH @y xs `HCons` reassemble xs
81+ {-# INLINE reassemble #-}
src/Data/OpenApi/Compare/Behavior.hsnew file+124
@@ -0,0 +1,124 @@
1+module Data.OpenApi.Compare.Behavior
2+ ( BehaviorLevel (..),
3+ Behavable (..),
4+ IssueKind (..),
5+ Issuable (..),
6+ Orientation (..),
7+ toggleOrientation,
8+ Behavior,
9+ AnIssue (..),
10+ withClass,
11+ anIssueKind,
12+ relatedAnIssues,
13+ )
14+where
15+
16+import Data.Aeson
17+import Data.Kind
18+import Data.OpenApi.Compare.Paths
19+import Data.Typeable
20+import Text.Pandoc.Builder
21+
22+-- | Kind
23+data BehaviorLevel
24+ = APILevel
25+ | ServerLevel
26+ | SecurityRequirementLevel
27+ | SecuritySchemeLevel
28+ | PathLevel
29+ | OperationLevel
30+ | PathFragmentLevel
31+ | RequestLevel
32+ | ResponseLevel
33+ | HeaderLevel
34+ | -- | either request or response data
35+ PayloadLevel
36+ | SchemaLevel
37+ | TypedSchemaLevel
38+ | LinkLevel
39+ | CallbackLevel
40+
41+class
42+ (Ord (Behave a b), Show (Behave a b)) =>
43+ Behavable (a :: BehaviorLevel) (b :: BehaviorLevel)
44+ where
45+ data Behave a b
46+ describeBehavior :: Behave a b -> Inlines
47+
48+type instance AdditionalQuiverConstraints Behave a b = Behavable a b
49+
50+data IssueKind
51+ = -- | This is certainly an issue, we can demonstrate a "counterexample"
52+ CertainIssue
53+ | -- | Change looks breaking but we don't have a complete comprehension of the problem
54+ ProbablyIssue
55+ | -- | We don't really support this feature at all, outside structural comparison
56+ Unsupported
57+ | -- | This is not an issue in itself, but a clarifying comment providing context for some other issues
58+ Comment
59+ | -- | We detected an issue with one of the input schemata itself
60+ SchemaInvalid
61+ deriving stock (Eq, Ord, Show)
62+
63+class (Typeable l, Ord (Issue l), Show (Issue l)) => Issuable (l :: BehaviorLevel) where
64+ data Issue l :: Type
65+
66+ -- | The same issues can be rendered in multiple places and might
67+ -- require different ways of represnting them to the user.
68+ --
69+ -- In practice each issue requires a maximum of two different representations:
70+ -- based on the context the issue might need to be rendered as "opposite" ('Backward')
71+ -- โ€“ for example when rendering non-breaking changes everything should be
72+ -- reversed (a consequence of the way we generate non-breaking changes).
73+ --
74+ -- If _consumer_ doesn't have something, the element was "removed".
75+ -- If _producer_ doesn't have something, the element was "added".
76+ describeIssue :: Orientation -> Issue l -> Blocks
77+
78+ issueKind :: Issue l -> IssueKind
79+
80+ -- | An equivalence relation designating whether two issues are talking about the aspect of the schema. This is used
81+ -- to remove duplicates from the "reverse" error tree we get when we look for non-breaking changes.
82+ -- Generally if checking X->Y raises issue I, and checking Y->X raises issue J, I and J should be related.
83+ relatedIssues :: Issue l -> Issue l -> Bool
84+ relatedIssues = (==)
85+
86+-- Utility function for 'relatedIssues'. In @withClass eq f@, @f@ attempts to partition inputs into equivalence classes,
87+-- and two items in the same equivalence class are related. If both items aren't assigned to a class by @f@, instead
88+-- @eq@ is used to compare them.
89+withClass :: Eq b => (a -> a -> Bool) -> (a -> Maybe b) -> a -> a -> Bool
90+withClass eq f = \x y -> case (f x, f y) of
91+ (Just fx, Just fy) -> fx == fy
92+ (Nothing, Nothing) -> eq x y
93+ (_, _) -> False
94+
95+data Orientation = Forward | Backward
96+ deriving stock (Eq, Ord, Show)
97+
98+toggleOrientation :: Orientation -> Orientation
99+toggleOrientation Forward = Backward
100+toggleOrientation Backward = Forward
101+
102+-- | A set of interactions having common unifying features
103+type Behavior = Paths Behave 'APILevel
104+
105+instance Issuable l => ToJSON (Issue l) where
106+ toJSON = toJSON . show
107+
108+data AnIssue (l :: BehaviorLevel) where
109+ AnIssue :: Issuable l => Orientation -> Issue l -> AnIssue l
110+
111+deriving stock instance Show (AnIssue l)
112+
113+deriving stock instance Eq (AnIssue l)
114+
115+deriving stock instance Ord (AnIssue l)
116+
117+instance ToJSON (AnIssue l) where
118+ toJSON (AnIssue _ issue) = toJSON issue
119+
120+anIssueKind :: AnIssue l -> IssueKind
121+anIssueKind (AnIssue _ i) = issueKind i
122+
123+relatedAnIssues :: AnIssue l -> AnIssue l -> Bool
124+relatedAnIssues (AnIssue _ x) (AnIssue _ y) = relatedIssues x y
src/OpenAPI/Checker/Common.hs โ†’ src/Data/OpenApi/Compare/Common.hsrenamed+2โˆ’2
@@ -1,5 +1,5 @@
1โˆ’module OpenAPI.Checker.Common
1+module Data.OpenApi.Compare.Common
2โˆ’ ( zipAll
2+ ( zipAll,
3 )
3 )
4where
4where
5
5
src/OpenAPI/Checker/Formula.hs โ†’ src/Data/OpenApi/Compare/Formula.hsrenamed+35โˆ’25
@@ -1,20 +1,21 @@
1โˆ’module OpenAPI.Checker.Formula
1+module Data.OpenApi.Compare.Formula
2โˆ’ ( FormulaF
2+ ( FormulaF,
3โˆ’ , VarRef
3+ VarRef,
4โˆ’ , variable
4+ variable,
5โˆ’ , eitherOf
5+ eitherOf,
6โˆ’ , anError
6+ anError,
7โˆ’ , errors
7+ errors,
8โˆ’ , calculate
8+ calculate,
9โˆ’ , maxFixpoint
9+ maxFixpoint,
10โˆ’ , mapErrors
10+ mapErrors,
11+ )
11โˆ’ ) where
12+where
12
13
13import Data.Kind
14import Data.Kind
14โˆ’import Data.Monoid
15import qualified Data.List.NonEmpty as NE
15import qualified Data.List.NonEmpty as NE
16โˆ’import OpenAPI.Checker.Paths
16+import Data.Monoid
17+import Data.OpenApi.Compare.Paths
17โˆ’import qualified OpenAPI.Checker.PathsPrefixTree as P
18+import qualified Data.OpenApi.Compare.PathsPrefixTree as P
18
19
19type VarRef = Int
20type VarRef = Int
20
21
@@ -24,15 +25,24 @@ type VarRef = Int
24-- fixpoints always exist, i.e. that @x = f x@ has at least one solution.
25-- fixpoints always exist, i.e. that @x = f x@ has at least one solution.
25data FormulaF (q :: k -> k -> Type) (f :: k -> Type) (r :: k) (a :: Type) where
26data FormulaF (q :: k -> k -> Type) (f :: k -> Type) (r :: k) (a :: Type) where
26 Result :: a -> FormulaF q f r a
27 Result :: a -> FormulaF q f r a
28+ Errors ::
27โˆ’ Errors :: !(P.PathsPrefixTree q f r) -> FormulaF q f r a
29+ !(P.PathsPrefixTree q f r) ->
28โˆ’ -- ^ invariant: never empty
30+ -- | invariant: never empty
31+ FormulaF q f r a
32+ Apply ::
29โˆ’ Apply :: FormulaF q f r (b -> c) -> FormulaF q f r b -> (c -> a) -> FormulaF q f r a
33+ FormulaF q f r (b -> c) ->
34+ FormulaF q f r b ->
35+ (c -> a) ->
30โˆ’ -- ^ invariant: at least one of LHS and RHS is not 'Errors', and they are
36+ -- | invariant: at least one of LHS and RHS is not 'Errors', and they are
31 -- both not 'Result'
37 -- both not 'Result'
38+ FormulaF q f r a
39+ SelectFirst ::
32โˆ’ SelectFirst :: NE.NonEmpty (SomeFormulaF b)
40+ NE.NonEmpty (SomeFormulaF b) ->
33โˆ’ -> !(P.PathsPrefixTree q f r) -> (b -> a) -> FormulaF q f r a
41+ !(P.PathsPrefixTree q f r) ->
42+ (b -> a) ->
34โˆ’ -- ^ invariant: the list doesn't contain any 'Result's, 'Errors' or
43+ -- | invariant: the list doesn't contain any 'Result's, 'Errors' or
35 -- 'SelectFirst'
44 -- 'SelectFirst'
45+ FormulaF q f r a
36 Variable :: !VarRef -> a -> FormulaF q f r a
46 Variable :: !VarRef -> a -> FormulaF q f r a
37
47
38mkApply :: FormulaF q f r (b -> c) -> FormulaF q f r b -> (c -> a) -> FormulaF q f r a
48mkApply :: FormulaF q f r (b -> c) -> FormulaF q f r b -> (c -> a) -> FormulaF q f r a
@@ -44,13 +54,13 @@ mkApply f x h = Apply f x h
44mkSelectFirst :: [SomeFormulaF b] -> P.PathsPrefixTree q f r -> (b -> a) -> FormulaF q f r a
54mkSelectFirst :: [SomeFormulaF b] -> P.PathsPrefixTree q f r -> (b -> a) -> FormulaF q f r a
45mkSelectFirst fs allE h = case foldMap check fs of
55mkSelectFirst fs allE h = case foldMap check fs of
46 (First (Just x), _) -> Result (h x)
56 (First (Just x), _) -> Result (h x)
47โˆ’ (First Nothing, x:xs) -> SelectFirst (x NE.:| xs) allE h
57+ (First Nothing, x : xs) -> SelectFirst (x NE.:| xs) allE h
48 (First Nothing, []) -> Errors allE
58 (First Nothing, []) -> Errors allE
49 where
59 where
50 check (SomeFormulaF (Result x)) = (First (Just x), mempty)
60 check (SomeFormulaF (Result x)) = (First (Just x), mempty)
51 check (SomeFormulaF (Errors _)) = (mempty, mempty)
61 check (SomeFormulaF (Errors _)) = (mempty, mempty)
52โˆ’ check (SomeFormulaF (SelectFirst xs _ h'))
62+ check (SomeFormulaF (SelectFirst xs _ h')) =
53โˆ’ = (mempty, NE.toList (fmap (fmap h') xs))
63+ (mempty, NE.toList (fmap (fmap h') xs))
54 check x = (mempty, [x])
64 check x = (mempty, [x])
55
65
56data SomeFormulaF (a :: Type) where
66data SomeFormulaF (a :: Type) where
@@ -96,7 +106,7 @@ calculate (Apply f x h) = case calculate f of
96 Right x' -> Right (h (f' x'))
106 Right x' -> Right (h (f' x'))
97calculate (SelectFirst xs e h) = go (NE.toList xs)
107calculate (SelectFirst xs e h) = go (NE.toList xs)
98 where
108 where
99โˆ’ go (SomeFormulaF r:rs) = case calculate r of
109+ go (SomeFormulaF r : rs) = case calculate r of
100 Left _ -> go rs
110 Left _ -> go rs
101 Right x -> Right (h x)
111 Right x -> Right (h x)
102 go [] = Left e
112 go [] = Left e
src/Data/OpenApi/Compare/Memo.hsnew file+164
@@ -0,0 +1,164 @@
1+{-# LANGUAGE AllowAmbiguousTypes #-}
2+
3+-- | Utilities for effectfully memoizing other, more effectful functions.
4+module Data.OpenApi.Compare.Memo
5+ ( MonadMemo,
6+ MemoState,
7+ runMemo,
8+ modifyMemoNonce,
9+ KnotTier (..),
10+ unknot,
11+ memoWithKnot,
12+ memoTaggedWithKnot,
13+ )
14+where
15+
16+import Control.Monad.State
17+import Data.Dynamic
18+import qualified Data.Map as M
19+import Data.Tagged
20+import qualified Data.TypeRepMap as T
21+import Data.Void
22+import Type.Reflection
23+
24+data Progress a = Finished a | Started | TyingKnot Dynamic
25+
26+data MemoMap a where
27+ MemoMap :: !(M.Map k (Progress v)) -> MemoMap (k, v)
28+
29+data MemoState s = MemoState s (T.TypeRepMap MemoMap)
30+
31+-- | An effectful memoization monad.
32+type MonadMemo s m = MonadState (MemoState s) m
33+
34+memoStateLookup ::
35+ forall k v s.
36+ (Typeable k, Typeable v, Ord k) =>
37+ k ->
38+ MemoState s ->
39+ Maybe (Progress v)
40+memoStateLookup k (MemoState _ t) = case T.lookup @(k, v) t of
41+ Just (MemoMap m) -> M.lookup k m
42+ Nothing -> Nothing
43+
44+memoStateInsert ::
45+ forall k v s.
46+ (Typeable k, Typeable v, Ord k) =>
47+ k ->
48+ Progress v ->
49+ MemoState s ->
50+ MemoState s
51+memoStateInsert k x (MemoState s t) = MemoState s $ T.insert (MemoMap m'') t
52+ where
53+ m'' = M.insert k x m'
54+ m' = case T.lookup @(k, v) t of
55+ Just (MemoMap m) -> m
56+ Nothing -> M.empty
57+
58+modifyMemoNonce :: MonadMemo s m => (s -> s) -> m s
59+modifyMemoNonce f = do
60+ MemoState s t <- get
61+ put $ MemoState (f s) t
62+ pure s
63+
64+-- | Run a memoized computation.
65+runMemo :: Monad m => s -> StateT (MemoState s) m a -> m a
66+runMemo s = (`evalStateT` MemoState s T.empty)
67+
68+-- | A description of how to effectfully tie knots in type @v@, using the @m@
69+-- monad, and by sharing some @d@ data among the recursive instances.
70+data KnotTier v d m = KnotTier
71+ { -- | Create some data that will be connected to this knot
72+ onKnotFound :: m d
73+ , -- | This is what the knot will look like as a value
74+ -- to the inner computations
75+ onKnotUsed :: d -> m v
76+ , -- | Once we're done and we're outside, tie the
77+ -- knot using the datum
78+ tieKnot :: d -> v -> m v
79+ }
80+
81+unknot :: KnotTier v Void m
82+unknot =
83+ KnotTier
84+ { onKnotFound = error "Recursion detected"
85+ , onKnotUsed = absurd
86+ , tieKnot = absurd
87+ }
88+
89+-- | Run a potentially recursive computation. The provided key will be used to
90+-- refer to the result of this computation. If during the computation, another
91+-- attempt to run the computation with the same key is made, we run a
92+-- tying-the-knot procedure.
93+--
94+-- If another attempt to run the computation with the same key is made
95+-- *after we're done*, we will return the memoized value.
96+memoWithKnot ::
97+ forall k v d m s.
98+ (Typeable k, Typeable v, Typeable d, Ord k, MonadMemo s m) =>
99+ KnotTier v d m ->
100+ -- | the computation to memoize
101+ m v ->
102+ -- | key for memoization
103+ k ->
104+ m v
105+memoWithKnot tier f k =
106+ memoStateLookup @k @v k <$> get >>= \case
107+ Just (Finished v) -> pure v
108+ Just Started -> do
109+ d <- onKnotFound tier
110+ modify $ memoStateInsert @k @v k (TyingKnot $ toDyn d)
111+ onKnotUsed tier d
112+ Just (TyingKnot dyn) -> case fromDynamic dyn of
113+ Just d -> onKnotUsed tier d
114+ Nothing ->
115+ error $
116+ "Type mismatch when examining the knot of "
117+ <> show (typeRep @(k -> v))
118+ <> ": expected "
119+ <> show (typeRep @d)
120+ <> ", got "
121+ <> show (dynTypeRep dyn)
122+ Nothing -> do
123+ modify $ memoStateInsert @k @v k Started
124+ v <- f
125+ v' <-
126+ memoStateLookup @k @v k <$> get >>= \case
127+ Just Started -> pure v
128+ Just (TyingKnot dyn) -> case fromDynamic dyn of
129+ Just d -> tieKnot tier d v
130+ Nothing ->
131+ error $
132+ "Type mismatch when tying the knot of "
133+ <> show (typeRep @(k -> v))
134+ <> ": expected "
135+ <> show (typeRep @d)
136+ <> ", got "
137+ <> show (dynTypeRep dyn)
138+ Just (Finished _) ->
139+ error $
140+ "Unexpected Finished when memoizing "
141+ <> show (typeRep @(k -> v))
142+ Nothing -> pure v
143+ -- Normally this would be an error, but the underlying monad can refuse
144+ -- to remember memoization state
145+ modify $ memoStateInsert @k @v k (Finished v')
146+ pure v'
147+
148+-- | Disambiguate memoized computations with an arbitrary tag.
149+memoTaggedWithKnot ::
150+ forall t k v d m s.
151+ ( Typeable t
152+ , Typeable k
153+ , Typeable v
154+ , Typeable d
155+ , Ord k
156+ , MonadMemo s m
157+ ) =>
158+ KnotTier v d m ->
159+ m v ->
160+ k ->
161+ m v
162+memoTaggedWithKnot tier f k =
163+ withTypeable (typeRepKind $ typeRep @t) $
164+ memoWithKnot tier f (Tagged @t k)
src/OpenAPI/Checker/Orphans.hs โ†’ src/Data/OpenApi/Compare/Orphans.hsrenamed+1โˆ’1
@@ -1,6 +1,6 @@
1{-# OPTIONS_GHC -Wno-orphans #-}
1{-# OPTIONS_GHC -Wno-orphans #-}
2
2
3โˆ’module OpenAPI.Checker.Orphans () where
3+module Data.OpenApi.Compare.Orphans () where
4
4
5import Control.Comonad.Env
5import Control.Comonad.Env
6import qualified Data.HashMap.Strict.InsOrd as IOHM
6import qualified Data.HashMap.Strict.InsOrd as IOHM
src/OpenAPI/Checker/Paths.hs โ†’ src/Data/OpenApi/Compare/Paths.hsrenamed+10โˆ’10
@@ -1,18 +1,18 @@
1-- | Utilities for traversing heterogeneous trees. A heterogeneous tree is a
1-- | Utilities for traversing heterogeneous trees. A heterogeneous tree is a
2-- collection of datatypes that "contain" eachother in some form of tree
2-- collection of datatypes that "contain" eachother in some form of tree
3-- structure.
3-- structure.
4โˆ’module OpenAPI.Checker.Paths
4+module Data.OpenApi.Compare.Paths
5โˆ’ ( NiceQuiver
5+ ( NiceQuiver,
6โˆ’ , AdditionalQuiverConstraints
6+ AdditionalQuiverConstraints,
7โˆ’ , Paths (..)
7+ Paths (..),
8โˆ’ , DiffPaths (..)
8+ DiffPaths (..),
9โˆ’ , catDiffPaths
9+ catDiffPaths,
10โˆ’ , AnItem (..)
10+ AnItem (..),
11โˆ’ , step
11+ step,
12
12
13 -- * Reexports
13 -- * Reexports
14โˆ’ , (>>>)
14+ (>>>),
15โˆ’ , (<<<)
15+ (<<<),
16 )
16 )
17where
17where
18
18
src/OpenAPI/Checker/PathsPrefixTree.hs โ†’ src/Data/OpenApi/Compare/PathsPrefixTree.hsrenamed+71โˆ’37
@@ -1,19 +1,22 @@
1{-# LANGUAGE QuantifiedConstraints #-}
1{-# LANGUAGE QuantifiedConstraints #-}
2
2
3โˆ’module OpenAPI.Checker.PathsPrefixTree
3+module Data.OpenApi.Compare.PathsPrefixTree
4โˆ’ ( PathsPrefixTree (PathsPrefixNode)
4+ ( PathsPrefixTree (PathsPrefixNode),
5โˆ’ , AStep (..)
5+ AStep (..),
6โˆ’ , empty
6+ empty,
7โˆ’ , singleton
7+ singleton,
8โˆ’ , fromList
8+ fromList,
9โˆ’ , null
9+ null,
10โˆ’ , foldWith
10+ foldWith,
11โˆ’ , toList
11+ toList,
12โˆ’ , filter
12+ filter,
13+ filterWithKey,
13โˆ’ , takeSubtree
14+ takeSubtree,
15+ lookup,
14โˆ’ , embed
16+ embed,
15โˆ’ , size
17+ size,
16โˆ’ , partition
18+ partition,
19+ map,
17 )
20 )
18where
21where
19
22
@@ -24,15 +27,15 @@ import qualified Data.HashMap.Strict as HM
24import Data.Kind
27import Data.Kind
25import qualified Data.Map as M
28import qualified Data.Map as M
26import Data.Monoid
29import Data.Monoid
30+import Data.OpenApi.Compare.Paths
27import qualified Data.Set as S
31import qualified Data.Set as S
28import qualified Data.Text as T
32import qualified Data.Text as T
29import Data.Type.Equality
33import Data.Type.Equality
30import qualified Data.TypeRepMap as TRM
34import qualified Data.TypeRepMap as TRM
31import qualified Data.Vector as V
35import qualified Data.Vector as V
32import qualified GHC.Exts as Exts
36import qualified GHC.Exts as Exts
33โˆ’import OpenAPI.Checker.Paths
34import Type.Reflection
37import Type.Reflection
35โˆ’import Prelude hiding (filter, null)
38+import Prelude hiding (filter, lookup, map, null)
36
39
37-- | A list of @AnItem r f@, but optimized into a prefix tree.
40-- | A list of @AnItem r f@, but optimized into a prefix tree.
38data PathsPrefixTree (q :: k -> k -> Type) (f :: k -> Type) (r :: k) = PathsPrefixTree
41data PathsPrefixTree (q :: k -> k -> Type) (f :: k -> Type) (r :: k) = PathsPrefixTree
@@ -41,6 +44,10 @@ data PathsPrefixTree (q :: k -> k -> Type) (f :: k -> Type) (r :: k) = PathsPref
41 }
44 }
42 deriving stock (Show)
45 deriving stock (Show)
43
46
47+map :: (forall x. f x -> f x) -> PathsPrefixTree q f r -> PathsPrefixTree q f r
48+map f (PathsPrefixTree roots branches) =
49+ PathsPrefixTree (mapASet f roots) (TRM.hoist (mapAStep f) branches)
50+
44-- TODO: optimize
51-- TODO: optimize
45partition :: (forall a. f a -> Bool) -> PathsPrefixTree q f r -> (PathsPrefixTree q f r, PathsPrefixTree q f r)
52partition :: (forall a. f a -> Bool) -> PathsPrefixTree q f r -> (PathsPrefixTree q f r, PathsPrefixTree q f r)
46partition f x = (filter f x, filter (not . f) x)
53partition f x = (filter f x, filter (not . f) x)
@@ -51,10 +58,27 @@ filter f (PathsPrefixTree roots branches) = PathsPrefixTree roots' branches'
51 roots' = filterASet f roots
58 roots' = filterASet f roots
52 branches' =
59 branches' =
53 Exts.fromList
60 Exts.fromList
54โˆ’ . fmap (\(TRM.WrapTypeable (AStep x)) -> TRM.WrapTypeable . AStep . M.filter (not . null) . fmap (filter f) $ x)
61+ . fmap (\(TRM.WrapTypeable (AStep x)) -> TRM.WrapTypeable . AStep . M.mapMaybe (maybeNonEmpty . filter f) $ x)
55 . Exts.toList
62 . Exts.toList
56 $ branches
63 $ branches
57
64
65+ maybeNonEmpty = mfilter (not . null) . Just
66+
67+filterWithKey :: (forall a. Paths q r a -> f a -> Bool) -> PathsPrefixTree q f r -> PathsPrefixTree q f r
68+filterWithKey = go Root
69+ where
70+ go :: Paths q r b -> (forall a. Paths q r a -> f a -> Bool) -> PathsPrefixTree q f b -> PathsPrefixTree q f b
71+ go xs f (PathsPrefixTree roots branches) = PathsPrefixTree roots' branches'
72+ where
73+ roots' = filterASet (f xs) roots
74+ branches' =
75+ Exts.fromList
76+ . fmap (\(TRM.WrapTypeable (AStep x)) -> TRM.WrapTypeable . AStep . M.mapMaybeWithKey (\k -> maybeNonEmpty . go (xs `Snoc` k) f) $ x)
77+ . Exts.toList
78+ $ branches
79+
80+ maybeNonEmpty = mfilter (not . null) . Just
81+
58-- | The number of leaves.
82-- | The number of leaves.
59size :: PathsPrefixTree q f r -> Int
83size :: PathsPrefixTree q f r -> Int
60size (PathsPrefixTree root branches) =
84size (PathsPrefixTree root branches) =
@@ -78,11 +102,11 @@ deriving stock instance Eq (PathsPrefixTree q f a)
78
102
79-- Kind of orphan. Treat the map as an infinite tuple of @Maybe (f a)@'s, where
103-- Kind of orphan. Treat the map as an infinite tuple of @Maybe (f a)@'s, where
80-- the components are ordered by the @SomeTypeRep@ of the @a@.
104-- the components are ordered by the @SomeTypeRep@ of the @a@.
81โˆ’compareTRM
105+compareTRM ::
82โˆ’ :: (forall a. Typeable a => Ord (f a))
106+ (forall a. Typeable a => Ord (f a)) =>
83โˆ’ => TRM.TypeRepMap f
107+ TRM.TypeRepMap f ->
84โˆ’ -> TRM.TypeRepMap f
108+ TRM.TypeRepMap f ->
85โˆ’ -> Ordering
109+ Ordering
86compareTRM s1 s2 =
110compareTRM s1 s2 =
87 foldMap (\k -> compareMaybe compareW (M.lookup k m1) (M.lookup k m2)) mKeys
111 foldMap (\k -> compareMaybe compareW (M.lookup k m1) (M.lookup k m2)) mKeys
88 where
112 where
@@ -92,11 +116,11 @@ compareTRM s1 s2 =
92 compareMaybe _ Nothing (Just _) = LT
116 compareMaybe _ Nothing (Just _) = LT
93 compareMaybe _ (Just _) Nothing = GT
117 compareMaybe _ (Just _) Nothing = GT
94 compareMaybe cmp (Just x) (Just y) = cmp x y
118 compareMaybe cmp (Just x) (Just y) = cmp x y
95โˆ’ compareW
119+ compareW ::
96โˆ’ :: (forall a. Typeable a => Ord (f a))
120+ (forall a. Typeable a => Ord (f a)) =>
97โˆ’ => TRM.WrapTypeable f
121+ TRM.WrapTypeable f ->
98โˆ’ -> TRM.WrapTypeable f
122+ TRM.WrapTypeable f ->
99โˆ’ -> Ordering
123+ Ordering
100 compareW (TRM.WrapTypeable (x :: f a)) (TRM.WrapTypeable (y :: f b))
124 compareW (TRM.WrapTypeable (x :: f a)) (TRM.WrapTypeable (y :: f b))
101 | Just Refl <- testEquality (typeRep @a) (typeRep @b) = compare x y
125 | Just Refl <- testEquality (typeRep @a) (typeRep @b) = compare x y
102 | otherwise = EQ -- unreachable
126 | otherwise = EQ -- unreachable
@@ -116,6 +140,10 @@ data ASet (a :: Type) where
116 AnEmptySet :: ASet a
140 AnEmptySet :: ASet a
117 ASet :: Ord a => S.Set a -> ASet a
141 ASet :: Ord a => S.Set a -> ASet a
118
142
143+mapASet :: (Ord a => Ord b) => (a -> b) -> ASet a -> ASet b
144+mapASet _ AnEmptySet = AnEmptySet
145+mapASet f (ASet s) = ASet $ S.map f s
146+
119deriving stock instance Show a => Show (ASet a)
147deriving stock instance Show a => Show (ASet a)
120
148
121toSet :: ASet a -> S.Set a
149toSet :: ASet a -> S.Set a
@@ -144,10 +172,13 @@ instance Monoid (ASet a) where
144 mempty = AnEmptySet
172 mempty = AnEmptySet
145
173
146data AStep (q :: k -> k -> Type) (f :: k -> Type) (r :: k) (a :: k) where
174data AStep (q :: k -> k -> Type) (f :: k -> Type) (r :: k) (a :: k) where
147โˆ’ AStep
175+ AStep ::
148โˆ’ :: NiceQuiver q r a =>
176+ NiceQuiver q r a =>
149โˆ’ !(M.Map (q r a) (PathsPrefixTree q f a))
177+ !(M.Map (q r a) (PathsPrefixTree q f a)) ->
150โˆ’ -> AStep q f r a
178+ AStep q f r a
179+
180+mapAStep :: (forall x. f x -> f x) -> AStep q f r a -> AStep q f r a
181+mapAStep f (AStep m) = AStep $ M.map (map f) m
151
182
152deriving stock instance Eq (AStep q f r a)
183deriving stock instance Eq (AStep q f r a)
153
184
@@ -184,12 +215,12 @@ null :: PathsPrefixTree q f r -> Bool
184null (PathsPrefixTree AnEmptySet s) = all (\(TRM.WrapTypeable (AStep x)) -> all null x) (Exts.toList s)
215null (PathsPrefixTree AnEmptySet s) = all (\(TRM.WrapTypeable (AStep x)) -> all null x) (Exts.toList s)
185null _ = False
216null _ = False
186
217
187โˆ’foldWith
218+foldWith ::
188โˆ’ :: forall q f m r.
219+ forall q f m r.
189โˆ’ Monoid m
220+ Monoid m =>
190โˆ’ => (forall a. Ord (f a) => Paths q r a -> f a -> m)
221+ (forall a. Ord (f a) => Paths q r a -> f a -> m) ->
191โˆ’ -> PathsPrefixTree q f r
222+ PathsPrefixTree q f r ->
192โˆ’ -> m
223+ m
193foldWith k = goTPT Root
224foldWith k = goTPT Root
194 where
225 where
195 goTPT :: forall a. Paths q r a -> PathsPrefixTree q f a -> m
226 goTPT :: forall a. Paths q r a -> PathsPrefixTree q f a -> m
@@ -213,6 +244,9 @@ takeSubtree (Snoc xs x) t =
213 foldMap (\(AStep m) -> fold $ M.lookup x m) $
244 foldMap (\(AStep m) -> fold $ M.lookup x m) $
214 TRM.lookup @a $ snocItems $ takeSubtree xs t
245 TRM.lookup @a $ snocItems $ takeSubtree xs t
215
246
247+lookup :: Paths q r a -> PathsPrefixTree q f r -> S.Set (f a)
248+lookup xs = toSet . rootItems . takeSubtree xs
249+
216-- | Embed a subtree in a larger tree with given prefix
250-- | Embed a subtree in a larger tree with given prefix
217embed :: Paths q r a -> PathsPrefixTree q f a -> PathsPrefixTree q f r
251embed :: Paths q r a -> PathsPrefixTree q f a -> PathsPrefixTree q f r
218embed Root t = t
252embed Root t = t
src/OpenAPI/Checker/References.hs โ†’ src/Data/OpenApi/Compare/References.hsrenamed+18โˆ’19
@@ -1,9 +1,9 @@
1{-# OPTIONS_GHC -Wno-orphans #-}
1{-# OPTIONS_GHC -Wno-orphans #-}
2
2
3โˆ’module OpenAPI.Checker.References
3+module Data.OpenApi.Compare.References
4โˆ’ ( Step (..)
4+ ( Step (..),
5โˆ’ , dereference
5+ dereference,
6โˆ’ , Typeable
6+ Typeable,
7 )
7 )
8where
8where
9
9
@@ -11,19 +11,18 @@ import Data.HList
11import qualified Data.HashMap.Strict.InsOrd as IOHM
11import qualified Data.HashMap.Strict.InsOrd as IOHM
12import Data.Maybe
12import Data.Maybe
13import Data.OpenApi
13import Data.OpenApi
14โˆ’import Data.Typeable
14+import Data.OpenApi.Compare.Orphans ()
15โˆ’import OpenAPI.Checker.Orphans ()
16โˆ’import OpenAPI.Checker.Subtree
15+import Data.OpenApi.Compare.Subtree
17
16
18instance Typeable a => Steppable (Referenced a) a where
17instance Typeable a => Steppable (Referenced a) a where
19 data Step (Referenced a) a = InlineStep
18 data Step (Referenced a) a = InlineStep
20 deriving stock (Eq, Ord, Show)
19 deriving stock (Eq, Ord, Show)
21
20
22โˆ’dereference
21+dereference ::
23โˆ’ :: Typeable a
22+ Typeable a =>
24โˆ’ => Traced (Definitions a)
23+ Traced (Definitions a) ->
25โˆ’ -> Traced (Referenced a)
24+ Traced (Referenced a) ->
26โˆ’ -> Traced a
25+ Traced a
27dereference defs x = case extract x of
26dereference defs x = case extract x of
28 Inline a ->
27 Inline a ->
29 traced (ask x >>> step InlineStep) a
28 traced (ask x >>> step InlineStep) a
@@ -34,16 +33,16 @@ instance Subtree a => Subtree (Referenced a) where
34 type CheckEnv (Referenced a) = ProdCons (Traced (Definitions a)) ': CheckEnv a
33 type CheckEnv (Referenced a) = ProdCons (Traced (Definitions a)) ': CheckEnv a
35 type SubtreeLevel (Referenced a) = SubtreeLevel a
34 type SubtreeLevel (Referenced a) = SubtreeLevel a
36
35
37โˆ’ checkStructuralCompatibility env pc' = do
36+ checkStructuralCompatibility (defs `HCons` env) pc' = do
38 let pc = do
37 let pc = do
39 x <- pc'
38 x <- pc'
40โˆ’ defs <- getH @(ProdCons (Traced (Definitions a))) env
39+ defs' <- defs
41โˆ’ pure (dereference defs x)
40+ pure (dereference defs' x)
42 checkSubstructure env pc
41 checkSubstructure env pc
43
42
44โˆ’ checkSemanticCompatibility env bhv pc' = do
43+ checkSemanticCompatibility (defs `HCons` env) bhv pc' = do
45 let pc = do
44 let pc = do
46 x <- pc'
45 x <- pc'
47โˆ’ defs <- getH @(ProdCons (Traced (Definitions a))) env
46+ defs' <- defs
48โˆ’ pure (dereference defs x)
47+ pure (dereference defs' x)
49โˆ’ checkCompatibility env bhv pc
48+ checkCompatibility bhv env pc
src/Data/OpenApi/Compare/Report.hsnew file+399
@@ -0,0 +1,399 @@
1+module Data.OpenApi.Compare.Report
2+ ( generateReport,
3+ CheckerOutput (..),
4+ ReportInput (..),
5+ segregateIssues,
6+ ReportStatus (..),
7+ Pandoc,
8+ ReportConfig (..),
9+ ReportTreeStyle (..),
10+ ReportMode (..),
11+ )
12+where
13+
14+import Control.Monad.Free hiding (unfoldM)
15+import Data.Aeson (ToJSON)
16+import Data.Default
17+import Data.Either
18+import Data.Function
19+import Data.Functor
20+import Data.List.NonEmpty
21+import qualified Data.List.NonEmpty as NE
22+import qualified Data.Map as M
23+import Data.Map.Ordered (OMap)
24+import qualified Data.Map.Ordered as OM
25+import Data.Maybe
26+import Data.OpenApi.Compare.Behavior
27+import Data.OpenApi.Compare.Paths
28+import Data.OpenApi.Compare.PathsPrefixTree hiding (empty)
29+import qualified Data.OpenApi.Compare.PathsPrefixTree as P hiding (empty)
30+import Data.OpenApi.Compare.Report.Jet
31+import Data.OpenApi.Compare.Subtree (invertIssueOrientationP)
32+import Data.OpenApi.Compare.Validate.OpenApi
33+import Data.OpenApi.Compare.Validate.Schema.Issues
34+import Data.OpenApi.Compare.Validate.Schema.TypedJson
35+import Data.OpenUnion
36+import Data.OpenUnion.Extra
37+import Data.Set
38+import qualified Data.Set as S
39+import Data.Text (Text)
40+import qualified Data.Text as T
41+import Data.TypeRepMap hiding (empty)
42+import Data.Typeable
43+import Generic.Data
44+import Text.Pandoc.Builder
45+
46+type Changes = P.PathsPrefixTree Behave AnIssue 'APILevel
47+
48+data CheckerOutput = CheckerOutput
49+ { forwardChanges :: Changes
50+ , backwardChanges :: Changes
51+ }
52+ deriving stock (Generic)
53+ deriving (Semigroup, Monoid) via (Generically CheckerOutput)
54+ deriving anyclass (ToJSON)
55+
56+data ReportInput = ReportInput
57+ { -- | forward 'CertainIssue', 'ProbablyIssue' and 'Comment'
58+ breakingChanges :: Changes
59+ , -- | backward 'CertainIssue', 'ProbablyIssue' and 'Comment', except those shadowed by 'relatedIssues'
60+ nonBreakingChanges :: Changes
61+ , -- | forward and backward 'Unsupported' (assumed to be the same anyway)
62+ unsupportedChanges :: Changes
63+ , -- | forward and backward 'SchemaInvalid' (assumed to be the same anyway)
64+ schemaIssues :: Changes
65+ }
66+ deriving stock (Generic)
67+ deriving (Semigroup, Monoid) via (Generically ReportInput)
68+ deriving anyclass (ToJSON)
69+
70+segregateIssues :: CheckerOutput -> ReportInput
71+segregateIssues CheckerOutput {forwardChanges = fwd, backwardChanges = bck} =
72+ ReportInput
73+ { breakingChanges = P.filter isBreaking fwd
74+ , nonBreakingChanges = invertIssueOrientationP $ P.filterWithKey isNonBreaking bck
75+ , unsupportedChanges = P.filter isUnsupported fwd <> P.filter isUnsupported bck
76+ , schemaIssues = P.filter isSchemaIssue fwd <> P.filter isSchemaIssue bck
77+ }
78+ where
79+ isBreaking i = anIssueKind i `elem` [CertainIssue, ProbablyIssue, Comment]
80+ isNonBreaking :: Paths Behave 'APILevel a -> AnIssue a -> Bool
81+ isNonBreaking xs i = isBreaking i && all (\j -> not $ relatedAnIssues i j) (P.lookup xs fwd)
82+ isUnsupported i = anIssueKind i == Unsupported
83+ isSchemaIssue i = anIssueKind i == SchemaInvalid
84+
85+data ReportStatus
86+ = BreakingChanges
87+ | NoBreakingChanges
88+ | -- | All changes that could be breaking are unsupported โ€“ we don't know if
89+ -- there actually are any breaking changes.
90+ OnlyUnsupportedChanges
91+
92+data ReportMode = OnlyErrors | All
93+ deriving stock (Eq)
94+
95+data ReportConfig = ReportConfig
96+ { treeStyle :: ReportTreeStyle
97+ , reportMode :: ReportMode
98+ }
99+
100+instance Default ReportConfig where
101+ def =
102+ ReportConfig
103+ { treeStyle = HeadersTreeStyle
104+ , reportMode = All
105+ }
106+
107+data ReportTreeStyle = HeadersTreeStyle | FoldingBlockquotesTreeStyle
108+
109+twoRowTable :: [(Inlines, Inlines)] -> Blocks
110+twoRowTable x = simpleTable (para . fst <$> x) [para . snd <$> x]
111+
112+generateReport :: ReportConfig -> ReportInput -> (Blocks, ReportStatus)
113+generateReport cfg inp =
114+ let schemaIssuesPresent = not $ P.null $ schemaIssues inp
115+ breakingChangesPresent = not $ P.null $ breakingChanges inp
116+ nonBreakingChangesPresent = not $ P.null $ nonBreakingChanges inp
117+ unsupportedChangesPresent = not $ P.null $ unsupportedChanges inp
118+ nonBreakingChangesShown = case reportMode cfg of
119+ All -> True
120+ OnlyErrors -> False
121+ builder = buildReport cfg
122+ report =
123+ header 1 "Summary"
124+ <> twoRowTable
125+ ( when'
126+ schemaIssuesPresent
127+ [
128+ ( refOpt schemaIssuesPresent schemaIssuesId "โ€ผ๏ธ Schema issues"
129+ , show' $ P.size $ schemaIssues inp
130+ )
131+ ]
132+ ++ [
133+ ( refOpt breakingChangesPresent breakingChangesId "โŒ Breaking changes"
134+ , show' $ P.size $ breakingChanges inp
135+ )
136+ ]
137+ ++ when'
138+ nonBreakingChangesShown
139+ [
140+ ( refOpt nonBreakingChangesPresent nonBreakingChangesId "โš ๏ธ Non-breaking changes"
141+ , show' $ P.size $ nonBreakingChanges inp
142+ )
143+ ]
144+ ++ when'
145+ unsupportedChangesPresent
146+ [
147+ ( refOpt unsupportedChangesPresent unsupportedChangesId "โ“ Unsupported feature changes"
148+ , show' $ P.size $ unsupportedChanges inp
149+ )
150+ ]
151+ )
152+ <> when'
153+ schemaIssuesPresent
154+ ( header 1 (anchor schemaIssuesId <> "โ€ผ๏ธ Schema issues")
155+ <> builder (showErrs $ schemaIssues inp)
156+ )
157+ <> when'
158+ breakingChangesPresent
159+ ( header 1 (anchor breakingChangesId <> "โŒ Breaking changes")
160+ <> builder (showErrs $ breakingChanges inp)
161+ )
162+ <> when'
163+ (nonBreakingChangesPresent && nonBreakingChangesShown)
164+ ( header 1 (anchor nonBreakingChangesId <> "โš ๏ธ Non-breaking changes")
165+ <> builder (showErrs $ nonBreakingChanges inp)
166+ )
167+ <> when'
168+ unsupportedChangesPresent
169+ ( header 1 (anchor unsupportedChangesId <> "โ“ Unsupported feature changes")
170+ <> builder (showErrs $ unsupportedChanges inp)
171+ )
172+ status =
173+ if
174+ | breakingChangesPresent -> BreakingChanges
175+ | unsupportedChangesPresent -> OnlyUnsupportedChanges
176+ | otherwise -> NoBreakingChanges
177+ in (report, status)
178+ where
179+ anchor :: Text -> Inlines
180+ anchor a = spanWith (a, [], []) mempty
181+
182+ refOpt :: Bool -> Text -> Inlines -> Inlines
183+ refOpt False _ i = i
184+ refOpt True a i = link ("#" <> a) "" i
185+
186+ breakingChangesId, nonBreakingChangesId, unsupportedChangesId, schemaIssuesId :: Text
187+ breakingChangesId = "breaking-changes"
188+ unsupportedChangesId = "unsupported-changes"
189+ nonBreakingChangesId = "non-breaking-changes"
190+ schemaIssuesId = "schema-issues"
191+
192+ when' :: Monoid m => Bool -> m -> m
193+ when' True m = m
194+ when' False _ = mempty
195+
196+showErrs :: forall a. Typeable a => P.PathsPrefixTree Behave AnIssue a -> Report
197+showErrs x@(P.PathsPrefixNode currentIssues _) =
198+ let -- Extract this pattern if more cases like this arise
199+ ( removedPaths :: Maybe (Orientation, [Issue 'APILevel])
200+ , otherIssues :: Set (AnIssue a)
201+ ) = case eqT @a @ 'APILevel of
202+ Just Refl
203+ | (S.toList -> p@((AnIssue ori _) : _), o) <-
204+ S.partition
205+ ( \((AnIssue _ u)) -> case u of
206+ NoPathsMatched {} -> True
207+ AllPathsFailed {} -> True
208+ )
209+ currentIssues ->
210+ let p' = p <&> (\(AnIssue _ i) -> i)
211+ in (Just (ori, p'), o)
212+ _ -> (Nothing, currentIssues)
213+ issues = singletonBody $ case S.toList otherIssues of
214+ [AnIssue ori i] -> describeIssue ori i
215+ ii -> orderedList $ ii <&> (\(AnIssue ori i) -> describeIssue ori i)
216+ paths = case removedPaths of
217+ Just (ori, ps) -> do
218+ singletonHeader
219+ ( case ori of
220+ Forward -> "Removed paths"
221+ Backward -> "Added paths"
222+ )
223+ $ singletonBody $
224+ bulletList $
225+ ps <&> \case
226+ (NoPathsMatched p) -> para . code $ T.pack p
227+ (AllPathsFailed p) -> para . code $ T.pack p
228+ Nothing -> mempty
229+ rest = unfoldFunctions x (observeJetShowErrs <$> jets) $ \(P.PathsPrefixNode _ subIssues) -> do
230+ flip foldMap subIssues $ \(WrapTypeable (AStep m)) ->
231+ flip foldMap (M.toList m) $ \(bhv, subErrors) ->
232+ if P.null subErrors
233+ then mempty
234+ else singletonHeader (describeBehavior bhv) $ showErrs subErrors
235+ in issues <> paths <> rest
236+
237+unfoldFunctions :: forall m a. (Monoid m, Eq a) => a -> [a -> (m, a)] -> (a -> m) -> m
238+unfoldFunctions initA fs g = unfoldFunctions' initA fs
239+ where
240+ unfoldFunctions' :: a -> [a -> (m, a)] -> m
241+ unfoldFunctions' a [] | a == initA = g a
242+ unfoldFunctions' a [] = unfoldFunctions a fs g
243+ unfoldFunctions' a (f : ff) =
244+ let (m, a') = f a
245+ in unfoldFunctions' a' ff <> m
246+
247+jets :: [ReportJet' Behave (Maybe Inlines)]
248+jets =
249+ unwrapReportJetResult
250+ <$> [ constructReportJet $
251+ curry $ \case
252+ (OfType Object, p@(InPartition _)) -> Just $ describeBehavior p :: Maybe Inlines
253+ _ -> Nothing
254+ , constructReportJet jsonPathJet
255+ , constructReportJet $ \p@(AtPath _) op@(InOperation _) ->
256+ strong (describeBehavior op) <> " " <> describeBehavior p :: Inlines
257+ , constructReportJet $ \(WithStatusCode c) ResponsePayload PayloadSchema ->
258+ "โฌ…๏ธโ˜๏ธ JSON Response โ€“ " <> str (T.pack . show $ c) :: Inlines
259+ , constructReportJet $ \InRequest InPayload PayloadSchema -> "โžก๏ธโ˜๏ธ JSON Request" :: Inlines
260+ ]
261+ where
262+ unwrapReportJetResult :: ReportJetResult Behave x -> ReportJet' Behave x
263+ unwrapReportJetResult (Pure _) = error "There really shouldn't be any results here."
264+ unwrapReportJetResult (Free f) = f
265+
266+ jsonPathJet ::
267+ NonEmpty
268+ ( Union
269+ '[ Behave 'SchemaLevel 'TypedSchemaLevel
270+ , Behave 'TypedSchemaLevel 'SchemaLevel
271+ ]
272+ ) ->
273+ Inlines
274+ jsonPathJet x = code $ "$" <> showParts (NE.toList x)
275+ where
276+ showParts ::
277+ [ Union
278+ '[ Behave 'SchemaLevel 'TypedSchemaLevel
279+ , Behave 'TypedSchemaLevel 'SchemaLevel
280+ ]
281+ ] ->
282+ Text
283+ showParts [] = mempty
284+ showParts (SingletonUnion (OfType Object) : xs@((SingletonUnion (InProperty _)) : _)) = showParts xs
285+ showParts (SingletonUnion (OfType Object) : xs@((SingletonUnion InAdditionalProperty) : _)) = showParts xs
286+ showParts (SingletonUnion (OfType Array) : xs@(SingletonUnion InItems : _)) = showParts xs
287+ showParts (SingletonUnion (OfType Array) : xs@(SingletonUnion (InItem _) : _)) = showParts xs
288+ showParts (y : ys) =
289+ ( (\(OfType t) -> "(" <> describeJSONType t <> ")")
290+ @@> ( \case
291+ InItems -> "[*]"
292+ InItem i -> "[" <> T.pack (show i) <> "]"
293+ InProperty p -> "." <> p
294+ InAdditionalProperty -> ".*"
295+ )
296+ @@> typesExhausted
297+ )
298+ y
299+ <> showParts ys
300+
301+observeJetShowErrs ::
302+ ReportJet' Behave (Maybe Inlines) ->
303+ P.PathsPrefixTree Behave AnIssue a ->
304+ (Report, P.PathsPrefixTree Behave AnIssue a)
305+observeJetShowErrs jet p = case observeJetShowErrs' jet p of
306+ Just m -> m
307+ Nothing -> (mempty, p)
308+
309+observeJetShowErrs' ::
310+ forall a.
311+ ReportJet' Behave (Maybe Inlines) ->
312+ P.PathsPrefixTree Behave AnIssue a ->
313+ Maybe (Report, P.PathsPrefixTree Behave AnIssue a)
314+observeJetShowErrs' (ReportJet jet) (P.PathsPrefixNode currentIssues subIssues) =
315+ let results =
316+ subIssues >>= \(WrapTypeable (AStep m)) ->
317+ M.toList m <&> \(bhv, subErrs) ->
318+ maybe (Left $ embed (step bhv) subErrs) Right . listToMaybe $
319+ jet @_ @_ @[] bhv
320+ & mapMaybe
321+ ( \case
322+ Free jet' -> fmap (embed $ step bhv) <$> observeJetShowErrs' jet' subErrs
323+ Pure (Just h) ->
324+ if P.null subErrs
325+ then Just mempty
326+ else Just (singletonHeader h (showErrs subErrs), mempty)
327+ Pure Nothing -> Nothing
328+ )
329+ in (fmap . fmap) (PathsPrefixNode currentIssues mempty <>) $
330+ if any isRight results
331+ then
332+ Just $
333+ foldMap
334+ ( \case
335+ Left e -> (mempty, e)
336+ Right m -> m
337+ )
338+ results
339+ else Nothing
340+
341+data Report = Report {headers :: OMap Inlines Report, body :: Blocks}
342+ deriving stock (Generic)
343+
344+instance Semigroup Report where
345+ (Report headers1 b1) <> (Report headers2 b2) = Report (OM.unionWithL (const (<>)) headers1 headers2) (b1 <> b2)
346+
347+instance Monoid Report where
348+ mempty = Report OM.empty mempty
349+
350+buildReport :: ReportConfig -> Report -> Blocks
351+buildReport cfg = case treeStyle cfg of
352+ HeadersTreeStyle -> headerStyleBuilder 2
353+ FoldingBlockquotesTreeStyle -> foldingStyleBuilder
354+ where
355+ headerStyleBuilder :: HeaderLevel -> Report -> Blocks
356+ headerStyleBuilder level rprt =
357+ body rprt
358+ <> foldOMapWithKey
359+ (headers rprt)
360+ ( \k v ->
361+ header level k <> subBuilder v
362+ )
363+ where
364+ subBuilder = headerStyleBuilder (level + 1)
365+
366+ foldingStyleBuilder :: Report -> Blocks
367+ foldingStyleBuilder rprt =
368+ body rprt
369+ <> foldOMapWithKey
370+ (headers rprt)
371+ ( \k v ->
372+ if (OM.size . headers $ rprt) < 2
373+ then para k <> blockQuote (subBuilder v)
374+ else
375+ rawHtml "<details>"
376+ <> rawHtml "<summary>"
377+ <> plain k
378+ <> rawHtml "</summary>"
379+ <> blockQuote (subBuilder v)
380+ <> rawHtml "</details>"
381+ )
382+ where
383+ subBuilder = foldingStyleBuilder
384+
385+ rawHtml = rawBlock "html"
386+
387+type HeaderLevel = Int
388+
389+singletonHeader :: Inlines -> Report -> Report
390+singletonHeader i b = Report (OM.singleton (i, b)) mempty
391+
392+singletonBody :: Blocks -> Report
393+singletonBody = Report OM.empty
394+
395+show' :: Show x => x -> Inlines
396+show' = str . T.pack . show
397+
398+foldOMapWithKey :: Monoid m => OMap k v -> (k -> v -> m) -> m
399+foldOMapWithKey m f = foldMap (uncurry f) $ OM.assocs m
src/OpenAPI/Checker/Report/Html/Template.hs โ†’ src/Data/OpenApi/Compare/Report/Html/Template.hsrenamed+4โˆ’4
@@ -1,7 +1,7 @@
1{-# LANGUAGE TemplateHaskell #-}
1{-# LANGUAGE TemplateHaskell #-}
2
2
3โˆ’module OpenAPI.Checker.Report.Html.Template
3+module Data.OpenApi.Compare.Report.Html.Template
4โˆ’ ( template
4+ ( template,
5 )
5 )
6where
6where
7
7
@@ -24,11 +24,11 @@ template =
24 \<meta charset=\"utf-8\">\
24 \<meta charset=\"utf-8\">\
25 \<title></title>\
25 \<title></title>\
26 \<meta name=\"description\" content=\"\">\
26 \<meta name=\"description\" content=\"\">\
27โˆ’ \<meta name=\"generator\" content=\"OpenApi Diff\" />\
27+ \<meta name=\"generator\" content=\"CompaREST\" />\
28 \<meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0, user-scalable=yes\" />\
28 \<meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0, user-scalable=yes\" />\
29 \</head>\
29 \</head>\
30 \<body>\
30 \<body>\
31โˆ’ \<header><h1>โ›„ OpenApi Diff</h1></header>\
31+ \<header><h1>CompaREST</h1></header>\
32 \<main>\
32 \<main>\
33 \$body$\
33 \$body$\
34 \</main>\
34 \</main>\
src/OpenAPI/Checker/Report/Jet.hs โ†’ src/Data/OpenApi/Compare/Report/Jet.hsrenamed+11โˆ’8
@@ -1,8 +1,8 @@
1โˆ’module OpenAPI.Checker.Report.Jet
1+module Data.OpenApi.Compare.Report.Jet
2โˆ’ ( ReportJet (..)
2+ ( ReportJet (..),
3โˆ’ , ReportJet'
3+ ReportJet',
4โˆ’ , ConstructReportJet (..)
4+ ConstructReportJet (..),
5โˆ’ , ReportJetResult
5+ ReportJetResult,
6 )
6 )
7where
7where
8
8
@@ -23,16 +23,19 @@ import Text.Pandoc.Builder
23-- The term "jet" in this context was introduced in the Urbit project:
23-- The term "jet" in this context was introduced in the Urbit project:
24-- https://urbit.org/docs/vere/jetting/
24-- https://urbit.org/docs/vere/jetting/
25--
25--
26โˆ’-- The pattern fits well for simplifying 'Behaviour' tree paths.
26+-- The pattern fits well for simplifying 'Behavior' tree paths.
27class ConstructReportJet x f where
27class ConstructReportJet x f where
28โˆ’ constructReportJet :: x -> ReportJetResult f Inlines
28+ constructReportJet :: x -> ReportJetResult f (Maybe Inlines)
29
29
30instance (ConstructReportJet b f, JetArg a) => ConstructReportJet (a -> b) f where
30instance (ConstructReportJet b f, JetArg a) => ConstructReportJet (a -> b) f where
31 constructReportJet f = Free (fmap f <$> consumeJetArg @a) >>= constructReportJet
31 constructReportJet f = Free (fmap f <$> consumeJetArg @a) >>= constructReportJet
32
32
33โˆ’instance ConstructReportJet Inlines f where
33+instance ConstructReportJet (Maybe Inlines) f where
34 constructReportJet x = Pure x
34 constructReportJet x = Pure x
35
35
36+instance ConstructReportJet Inlines f where
37+ constructReportJet x = Pure $ Just x
38+
36class JetArg a where
39class JetArg a where
37 consumeJetArg :: ReportJet' f a
40 consumeJetArg :: ReportJet' f a
38
41
src/Data/OpenApi/Compare/Run.hsnew file+31
@@ -0,0 +1,31 @@
1+module Data.OpenApi.Compare.Run
2+ ( runChecker,
3+ runReport,
4+ module Data.OpenApi.Compare.Report,
5+ )
6+where
7+
8+import Data.HList
9+import Data.OpenApi (OpenApi)
10+import Data.OpenApi.Compare.Paths
11+import Data.OpenApi.Compare.Report
12+import Data.OpenApi.Compare.Subtree
13+import Data.OpenApi.Compare.Validate.OpenApi ()
14+import Text.Pandoc.Builder
15+
16+runChecker :: (OpenApi, OpenApi) -> CheckerOutput
17+runChecker (client, server) =
18+ CheckerOutput
19+ { forwardChanges = run client server
20+ , backwardChanges = run server client
21+ }
22+ where
23+ toPC p c =
24+ ProdCons
25+ { producer = traced (step ClientSchema) p
26+ , consumer = traced (step ServerSchema) c
27+ }
28+ run p c = either id mempty . runCompatFormula . checkCompatibility Root HNil $ toPC p c
29+
30+runReport :: ReportConfig -> (OpenApi, OpenApi) -> (Blocks, ReportStatus)
31+runReport cfg = generateReport cfg . segregateIssues . runChecker
src/Data/OpenApi/Compare/Subtree.hsnew file+364
@@ -0,0 +1,364 @@
1+{-# OPTIONS_GHC -Wno-orphans #-}
2+
3+module Data.OpenApi.Compare.Subtree
4+ ( Steppable (..),
5+ Step (..),
6+ TraceRoot,
7+ Trace,
8+ Traced,
9+ Traced',
10+ pattern Traced,
11+ traced,
12+ retraced,
13+ stepTraced,
14+ Subtree (..),
15+ checkCompatibility,
16+ checkSubstructure,
17+ CompatM (..),
18+ CompatFormula',
19+ SemanticCompatFormula,
20+ ProdCons (..),
21+ orientProdCons,
22+ swapProdCons,
23+ runCompatFormula,
24+ issueAt,
25+ anItem,
26+ anIssue,
27+ invertIssueOrientation,
28+ invertIssueOrientationP,
29+ embedFormula,
30+ anyOfAt,
31+ clarifyIssue,
32+ structuralIssue,
33+
34+ -- * Structural helpers
35+ structuralMaybe,
36+ structuralMaybeWith,
37+ structuralEq,
38+ iohmStructural,
39+ iohmStructuralWith,
40+ structuralList,
41+
42+ -- * Reexports
43+ (>>>),
44+ (<<<),
45+ extract,
46+ ask,
47+ local,
48+ step,
49+ Typeable,
50+ )
51+where
52+
53+import Control.Comonad.Env
54+import Control.Monad.Identity
55+import Control.Monad.State
56+import Data.Foldable
57+import Data.Functor.Compose
58+import Data.HList
59+import qualified Data.HashMap.Strict.InsOrd as IOHM
60+import Data.Hashable
61+import Data.Kind
62+import Data.OpenApi
63+import Data.OpenApi.Compare.Behavior
64+import Data.OpenApi.Compare.Formula
65+import Data.OpenApi.Compare.Memo
66+import Data.OpenApi.Compare.Paths
67+import qualified Data.OpenApi.Compare.PathsPrefixTree as P
68+import qualified Data.Set as S
69+import Data.Typeable
70+
71+class
72+ (Typeable Step, Typeable a, Typeable b, Ord (Step a b), Show (Step a b)) =>
73+ Steppable (a :: Type) (b :: Type)
74+ where
75+ -- | How to get from an @a@ node to a @b@ node
76+ data Step a b :: Type
77+
78+data TraceRoot
79+
80+instance Steppable TraceRoot OpenApi where
81+ data Step TraceRoot OpenApi
82+ = ClientSchema
83+ | ServerSchema
84+ deriving stock (Eq, Ord, Show)
85+
86+type Trace = Paths Step TraceRoot
87+
88+type instance AdditionalQuiverConstraints Step _ _ = ()
89+
90+type Traced' a b = Env (Trace a) b
91+
92+type Traced a = Traced' a a
93+
94+pattern Traced :: Trace a -> b -> Traced' a b
95+pattern Traced t x = EnvT t (Identity x)
96+
97+{-# COMPLETE Traced #-}
98+
99+traced :: Trace a -> a -> Traced a
100+traced = env
101+
102+retraced :: (Trace a -> Trace a') -> Traced' a b -> Traced' a' b
103+retraced f (Traced a b) = Traced (f a) b
104+
105+stepTraced :: Steppable a a' => Step a a' -> Traced' a b -> Traced' a' b
106+stepTraced s = retraced (>>> step s)
107+
108+data ProdCons a = ProdCons
109+ { producer :: a
110+ , consumer :: a
111+ }
112+ deriving stock (Eq, Ord, Show, Functor, Foldable, Traversable)
113+
114+orientProdCons :: Orientation -> ProdCons x -> ProdCons x
115+orientProdCons Forward x = x
116+orientProdCons Backward (ProdCons p c) = ProdCons c p
117+
118+swapProdCons ::
119+ SwapEnvRoles xs =>
120+ (HList xs -> ProdCons x -> CompatFormula' q AnIssue r a) ->
121+ (HList xs -> ProdCons x -> CompatFormula' q AnIssue r a)
122+swapProdCons f e (ProdCons p c) =
123+ invertIssueOrientation $
124+ f (swapEnvRoles e) (ProdCons c p)
125+{-# INLINE swapProdCons #-}
126+
127+type family IsProdCons (x :: Type) :: Bool where
128+ IsProdCons (ProdCons _) = 'True
129+ IsProdCons _ = 'False
130+
131+type SwapEnvElementRoles x = SwapEnvElementRoles' x (IsProdCons x)
132+
133+class IsProdCons x ~ f => SwapEnvElementRoles' (x :: Type) f where
134+ swapEnvElementRoles :: x -> x
135+
136+instance SwapEnvElementRoles' (ProdCons x) 'True where
137+ swapEnvElementRoles (ProdCons p c) = ProdCons c p
138+
139+instance IsProdCons x ~ 'False => SwapEnvElementRoles' x 'False where
140+ swapEnvElementRoles = id
141+
142+class SwapEnvRoles xs where
143+ swapEnvRoles :: HList xs -> HList xs
144+
145+instance SwapEnvRoles '[] where
146+ swapEnvRoles = id
147+
148+instance (SwapEnvElementRoles x, SwapEnvRoles xs) => SwapEnvRoles (x ': xs) where
149+ swapEnvRoles (HCons x xs) = HCons (swapEnvElementRoles x) (swapEnvRoles xs)
150+
151+instance Applicative ProdCons where
152+ pure x = ProdCons x x
153+ ProdCons fp fc <*> ProdCons xp xc = ProdCons (fp xp) (fc xc)
154+
155+newtype CompatM a = CompatM
156+ { unCompatM ::
157+ StateT (MemoState VarRef) Identity a
158+ }
159+ deriving newtype
160+ ( Functor
161+ , Applicative
162+ , Monad
163+ , MonadState (MemoState VarRef)
164+ )
165+
166+type CompatFormula' q f r = Compose CompatM (FormulaF q f r)
167+
168+type SemanticCompatFormula = CompatFormula' Behave AnIssue 'APILevel
169+
170+type StructuralCompatFormula = CompatFormula' VoidQuiver Proxy ()
171+
172+data VoidQuiver a b
173+
174+deriving stock instance Eq (VoidQuiver a b)
175+
176+type instance AdditionalQuiverConstraints VoidQuiver _ _ = ()
177+
178+deriving stock instance Ord (VoidQuiver a b)
179+
180+deriving stock instance Show (VoidQuiver a b)
181+
182+class (Typeable t, Issuable (SubtreeLevel t)) => Subtree (t :: Type) where
183+ type CheckEnv t :: [Type]
184+ type SubtreeLevel t :: BehaviorLevel
185+
186+ checkStructuralCompatibility ::
187+ HList (CheckEnv t) ->
188+ ProdCons (Traced t) ->
189+ StructuralCompatFormula ()
190+
191+ checkSemanticCompatibility ::
192+ HList (CheckEnv t) ->
193+ Behavior (SubtreeLevel t) ->
194+ ProdCons (Traced t) ->
195+ SemanticCompatFormula ()
196+
197+{-# WARNING checkStructuralCompatibility "You should not be calling this directly. Use 'checkSubstructure'" #-}
198+
199+{-# WARNING checkSemanticCompatibility "You should not be calling this directly. Use 'checkCompatibility'" #-}
200+
201+checkCompatibility ::
202+ forall t xs.
203+ (ReassembleHList xs (CheckEnv t), Subtree t) =>
204+ Behavior (SubtreeLevel t) ->
205+ HList xs ->
206+ ProdCons (Traced t) ->
207+ SemanticCompatFormula ()
208+checkCompatibility bhv e = memo bhv SemanticMemoKey $ \pc ->
209+ case runCompatFormula $ checkSubstructure e pc of
210+ Left _ -> checkSemanticCompatibility (reassemble e) bhv pc
211+ Right () -> pure ()
212+{-# INLINE checkCompatibility #-}
213+
214+checkSubstructure ::
215+ (ReassembleHList xs (CheckEnv t), Subtree t) =>
216+ HList xs ->
217+ ProdCons (Traced t) ->
218+ StructuralCompatFormula ()
219+checkSubstructure e = memo Root StructuralMemoKey $ checkStructuralCompatibility (reassemble e)
220+{-# INLINE checkSubstructure #-}
221+
222+structuralMaybe ::
223+ (Subtree a, ReassembleHList xs (CheckEnv a)) =>
224+ HList xs ->
225+ ProdCons (Maybe (Traced a)) ->
226+ StructuralCompatFormula ()
227+structuralMaybe e = structuralMaybeWith (checkSubstructure e)
228+{-# INLINE structuralMaybe #-}
229+
230+structuralMaybeWith ::
231+ (ProdCons a -> StructuralCompatFormula ()) ->
232+ ProdCons (Maybe a) ->
233+ StructuralCompatFormula ()
234+structuralMaybeWith f (ProdCons (Just a) (Just b)) = f $ ProdCons a b
235+structuralMaybeWith _ (ProdCons Nothing Nothing) = pure ()
236+structuralMaybeWith _ _ = structuralIssue
237+{-# INLINE structuralMaybeWith #-}
238+
239+structuralList ::
240+ (Subtree a, ReassembleHList xs (CheckEnv a)) =>
241+ HList xs ->
242+ ProdCons [Traced a] ->
243+ StructuralCompatFormula ()
244+structuralList _ (ProdCons [] []) = pure ()
245+structuralList e (ProdCons (a : aa) (b : bb)) = do
246+ checkSubstructure e $ ProdCons a b
247+ structuralList e $ ProdCons aa bb
248+ pure ()
249+structuralList _ _ = structuralIssue
250+{-# INLINE structuralList #-}
251+
252+structuralEq :: (Eq a, Comonad w) => ProdCons (w a) -> StructuralCompatFormula ()
253+structuralEq (ProdCons a b) = if extract a == extract b then pure () else structuralIssue
254+{-# INLINE structuralEq #-}
255+
256+iohmStructural ::
257+ (ReassembleHList (k ': xs) (CheckEnv v), Ord k, Subtree v, Hashable k, Typeable k, Show k) =>
258+ HList xs ->
259+ ProdCons (Traced (IOHM.InsOrdHashMap k v)) ->
260+ StructuralCompatFormula ()
261+iohmStructural e =
262+ iohmStructuralWith (\k -> checkSubstructure (k `HCons` e))
263+{-# INLINE iohmStructural #-}
264+
265+instance (Typeable k, Typeable v, Ord k, Show k) => Steppable (IOHM.InsOrdHashMap k v) v where
266+ data Step (IOHM.InsOrdHashMap k v) v = InsOrdHashMapKeyStep k
267+ deriving stock (Eq, Ord, Show)
268+
269+iohmStructuralWith ::
270+ (Ord k, Hashable k, Typeable k, Typeable v, Show k) =>
271+ (k -> ProdCons (Traced v) -> StructuralCompatFormula ()) ->
272+ ProdCons (Traced (IOHM.InsOrdHashMap k v)) ->
273+ StructuralCompatFormula ()
274+iohmStructuralWith f pc = do
275+ let ProdCons pEKeys cEKeys = S.fromList . IOHM.keys . extract <$> pc
276+ if pEKeys == cEKeys
277+ then
278+ for_
279+ pEKeys
280+ ( \eKey ->
281+ f eKey $ stepTraced (InsOrdHashMapKeyStep eKey) . fmap (IOHM.lookupDefault (error "impossible") eKey) <$> pc
282+ )
283+ else structuralIssue
284+{-# INLINE iohmStructuralWith #-}
285+
286+runCompatFormula ::
287+ CompatFormula' q f r a ->
288+ Either (P.PathsPrefixTree q f r) a
289+runCompatFormula (Compose f) =
290+ calculate . runIdentity . runMemo 0 . unCompatM $ f
291+{-# INLINE runCompatFormula #-}
292+
293+embedFormula :: Paths q r l -> CompatFormula' q f l a -> CompatFormula' q f r a
294+embedFormula bhv (Compose x) = Compose $ mapErrors (P.embed bhv) <$> x
295+
296+issueAt :: Issuable l => Paths q r l -> Issue l -> CompatFormula' q AnIssue r a
297+issueAt xs issue = Compose $ pure $ anError $ AnItem xs $ anIssue issue
298+{-# INLINE issueAt #-}
299+
300+anIssue :: Issuable l => Issue l -> AnIssue l
301+anIssue = AnIssue Forward
302+{-# INLINE anIssue #-}
303+
304+anItem :: AnItem q AnIssue r -> CompatFormula' q AnIssue r a
305+anItem = Compose . pure . anError
306+{-# INLINE anItem #-}
307+
308+invertIssueOrientation :: CompatFormula' q AnIssue r a -> CompatFormula' q AnIssue r a
309+invertIssueOrientation (Compose x) =
310+ Compose $ mapErrors invertIssueOrientationP <$> x
311+
312+invertIssueOrientationP :: P.PathsPrefixTree q AnIssue r -> P.PathsPrefixTree q AnIssue r
313+invertIssueOrientationP = P.map (\(AnIssue ori i) -> AnIssue (toggleOrientation ori) i)
314+
315+structuralIssue :: StructuralCompatFormula a
316+structuralIssue = Compose $ pure $ anError $ AnItem Root Proxy
317+
318+anyOfAt ::
319+ Issuable l =>
320+ Paths q r l ->
321+ Issue l ->
322+ [CompatFormula' q AnIssue r a] ->
323+ CompatFormula' q AnIssue r a
324+anyOfAt _ _ [x] = x
325+anyOfAt xs issue fs =
326+ Compose $ (`eitherOf` AnItem xs (anIssue issue)) <$> traverse getCompose fs
327+
328+-- | If the given formula contains any issues, add another issue on top. Otherwise succeed.
329+clarifyIssue ::
330+ AnItem q AnIssue r ->
331+ CompatFormula' q AnIssue r a ->
332+ CompatFormula' q AnIssue r a
333+clarifyIssue item f =
334+ Compose ((`eitherOf` item) <$> pure <$> getCompose f) *> f
335+
336+fixpointKnot ::
337+ MonadState (MemoState VarRef) m =>
338+ KnotTier (FormulaF q f r ()) VarRef m
339+fixpointKnot =
340+ KnotTier
341+ { onKnotFound = modifyMemoNonce succ
342+ , onKnotUsed = \i -> pure $ variable i
343+ , tieKnot = \i x -> pure $ maxFixpoint i x
344+ }
345+
346+memo ::
347+ (Typeable (l :: k), Typeable q, Typeable f, Typeable k, Typeable a) =>
348+ Paths q r l ->
349+ MemoKey ->
350+ (ProdCons (Traced a) -> CompatFormula' q f r ()) ->
351+ (ProdCons (Traced a) -> CompatFormula' q f r ())
352+memo bhv k f pc = Compose $ do
353+ formula' <-
354+ memoWithKnot
355+ fixpointKnot
356+ ( do
357+ formula <- getCompose $ f pc
358+ pure $ mapErrors (P.takeSubtree bhv) formula
359+ )
360+ (k, ask <$> pc)
361+ pure $ mapErrors (P.embed bhv) formula'
362+
363+data MemoKey = SemanticMemoKey | StructuralMemoKey
364+ deriving stock (Eq, Ord)
src/OpenAPI/Checker/Validate/Header.hs โ†’ src/Data/OpenApi/Compare/Validate/Header.hsrenamed+10โˆ’8
@@ -1,6 +1,6 @@
1{-# OPTIONS_GHC -Wno-orphans #-}
1{-# OPTIONS_GHC -Wno-orphans #-}
2
2
3โˆ’module OpenAPI.Checker.Validate.Header
3+module Data.OpenApi.Compare.Validate.Header
4 (
4 (
5 )
5 )
6where
6where
@@ -9,10 +9,10 @@ import Data.Foldable
9import Data.Functor
9import Data.Functor
10import Data.Maybe
10import Data.Maybe
11import Data.OpenApi
11import Data.OpenApi
12โˆ’import OpenAPI.Checker.Behavior
12+import Data.OpenApi.Compare.Behavior
13โˆ’import OpenAPI.Checker.References ()
13+import Data.OpenApi.Compare.References ()
14โˆ’import OpenAPI.Checker.Subtree
14+import Data.OpenApi.Compare.Subtree
15โˆ’import OpenAPI.Checker.Validate.Schema ()
15+import Data.OpenApi.Compare.Validate.Schema ()
16import Text.Pandoc.Builder
16import Text.Pandoc.Builder
17
17
18instance Subtree Header where
18instance Subtree Header where
@@ -34,7 +34,7 @@ instance Subtree Header where
34 for_ (tracedSchema c) $ \consRef ->
34 for_ (tracedSchema c) $ \consRef ->
35 case tracedSchema p of
35 case tracedSchema p of
36 Nothing -> issueAt beh HeaderSchemaRequired
36 Nothing -> issueAt beh HeaderSchemaRequired
37โˆ’ Just prodRef -> checkCompatibility env (beh >>> step InSchema) (ProdCons prodRef consRef)
37+ Just prodRef -> checkCompatibility (beh >>> step InSchema) env (ProdCons prodRef consRef)
38 pure ()
38 pure ()
39
39
40instance Steppable Header (Referenced Schema) where
40instance Steppable Header (Referenced Schema) where
@@ -50,7 +50,9 @@ instance Issuable 'HeaderLevel where
50 | NonEmptyHeaderRequired
50 | NonEmptyHeaderRequired
51 | HeaderSchemaRequired
51 | HeaderSchemaRequired
52 deriving stock (Eq, Ord, Show)
52 deriving stock (Eq, Ord, Show)
53โˆ’ issueIsUnsupported _ = False
53+ issueKind = \case
54+ HeaderSchemaRequired -> ProbablyIssue -- catch-all schema?
55+ _ -> CertainIssue
54 describeIssue Forward RequiredHeaderMissing = para "Header has become required."
56 describeIssue Forward RequiredHeaderMissing = para "Header has become required."
55 describeIssue Backward RequiredHeaderMissing = para "Header is no longer required."
57 describeIssue Backward RequiredHeaderMissing = para "Header is no longer required."
56 describeIssue Forward NonEmptyHeaderRequired = para "The header does not allow empty values anymore."
58 describeIssue Forward NonEmptyHeaderRequired = para "The header does not allow empty values anymore."
@@ -61,4 +63,4 @@ instance Behavable 'HeaderLevel 'SchemaLevel where
61 data Behave 'HeaderLevel 'SchemaLevel
63 data Behave 'HeaderLevel 'SchemaLevel
62 = InSchema
64 = InSchema
63 deriving stock (Eq, Ord, Show)
65 deriving stock (Eq, Ord, Show)
64โˆ’ describeBehaviour InSchema = "JSON Schema"
66+ describeBehavior InSchema = "JSON Schema"
src/OpenAPI/Checker/Validate/Link.hs โ†’ src/Data/OpenApi/Compare/Validate/Link.hsrenamed+6โˆ’6
@@ -1,10 +1,10 @@
1{-# OPTIONS_GHC -Wno-orphans #-}
1{-# OPTIONS_GHC -Wno-orphans #-}
2
2
3โˆ’module OpenAPI.Checker.Validate.Link () where
3+module Data.OpenApi.Compare.Validate.Link () where
4
4
5import Data.OpenApi
5import Data.OpenApi
6โˆ’import OpenAPI.Checker.Behavior
6+import Data.OpenApi.Compare.Behavior
7โˆ’import OpenAPI.Checker.Subtree
7+import Data.OpenApi.Compare.Subtree
8import Text.Pandoc.Builder
8import Text.Pandoc.Builder
9
9
10instance Subtree Link where
10instance Subtree Link where
@@ -17,6 +17,6 @@ instance Issuable 'LinkLevel where
17 data Issue 'LinkLevel
17 data Issue 'LinkLevel
18 = LinksUnsupported
18 = LinksUnsupported
19 deriving stock (Eq, Ord, Show)
19 deriving stock (Eq, Ord, Show)
20โˆ’ issueIsUnsupported = \case
20+ issueKind = \case
21โˆ’ LinksUnsupported -> True
21+ LinksUnsupported -> Unsupported
22โˆ’ describeIssue _ LinksUnsupported = para "OpenApi Diff does not currently support Link Objects."
22+ describeIssue _ LinksUnsupported = para "CompaREST does not currently support Link Objects."
src/OpenAPI/Checker/Validate/MediaTypeObject.hs โ†’ src/Data/OpenApi/Compare/Validate/MediaTypeObject.hsrenamed+24โˆ’24
@@ -1,8 +1,8 @@
1{-# OPTIONS_GHC -Wno-orphans #-}
1{-# OPTIONS_GHC -Wno-orphans #-}
2
2
3โˆ’module OpenAPI.Checker.Validate.MediaTypeObject
3+module Data.OpenApi.Compare.Validate.MediaTypeObject
4โˆ’ ( Issue (..)
4+ ( Issue (..),
5โˆ’ , Behave (..)
5+ Behave (..),
6 )
6 )
7where
7where
8
8
@@ -12,15 +12,15 @@ import Data.HList
12import Data.HashMap.Strict.InsOrd as IOHM
12import Data.HashMap.Strict.InsOrd as IOHM
13import Data.Map.Strict as M
13import Data.Map.Strict as M
14import Data.OpenApi
14import Data.OpenApi
15+import Data.OpenApi.Compare.Behavior
16+import Data.OpenApi.Compare.Subtree
17+import Data.OpenApi.Compare.Validate.Header ()
18+import Data.OpenApi.Compare.Validate.Products
19+import Data.OpenApi.Compare.Validate.Schema ()
15import Data.String
20import Data.String
16import Data.Text (Text)
21import Data.Text (Text)
17import qualified Data.Text as T
22import qualified Data.Text as T
18import Network.HTTP.Media (MediaType, mainType, subType)
23import Network.HTTP.Media (MediaType, mainType, subType)
19โˆ’import OpenAPI.Checker.Behavior
20โˆ’import OpenAPI.Checker.Subtree
21โˆ’import OpenAPI.Checker.Validate.Header ()
22โˆ’import OpenAPI.Checker.Validate.Products
23โˆ’import OpenAPI.Checker.Validate.Schema ()
24import Text.Pandoc.Builder
24import Text.Pandoc.Builder
25
25
26tracedSchema :: Traced MediaTypeObject -> Maybe (Traced (Referenced Schema))
26tracedSchema :: Traced MediaTypeObject -> Maybe (Traced (Referenced Schema))
@@ -38,20 +38,20 @@ instance Issuable 'PayloadLevel where
38 | MediaEncodingMissing Text
38 | MediaEncodingMissing Text
39 | EncodingNotSupported
39 | EncodingNotSupported
40 deriving stock (Eq, Ord, Show)
40 deriving stock (Eq, Ord, Show)
41โˆ’ issueIsUnsupported = \case
41+ issueKind = \case
42โˆ’ EncodingNotSupported -> True
42+ EncodingNotSupported -> Unsupported
43โˆ’ _ -> False
43+ _ -> CertainIssue
44
44
45 describeIssue _ MediaTypeSchemaRequired = para "Media type expected, but was not specified."
45 describeIssue _ MediaTypeSchemaRequired = para "Media type expected, but was not specified."
46 describeIssue Forward (MediaEncodingMissing enc) = para $ "Media encoding " <> str enc <> " has been removed."
46 describeIssue Forward (MediaEncodingMissing enc) = para $ "Media encoding " <> str enc <> " has been removed."
47 describeIssue Backward (MediaEncodingMissing enc) = para $ "Media encoding " <> str enc <> " added."
47 describeIssue Backward (MediaEncodingMissing enc) = para $ "Media encoding " <> str enc <> " added."
48โˆ’ describeIssue _ EncodingNotSupported = para "OpenApi Diff does not currently support media encodings other than JSON."
48+ describeIssue _ EncodingNotSupported = para "CompaREST does not currently support media encodings other than JSON."
49
49
50instance Behavable 'PayloadLevel 'SchemaLevel where
50instance Behavable 'PayloadLevel 'SchemaLevel where
51 data Behave 'PayloadLevel 'SchemaLevel
51 data Behave 'PayloadLevel 'SchemaLevel
52 = PayloadSchema
52 = PayloadSchema
53 deriving stock (Eq, Ord, Show)
53 deriving stock (Eq, Ord, Show)
54โˆ’ describeBehaviour PayloadSchema = "JSON Schema"
54+ describeBehavior PayloadSchema = "JSON Schema"
55
55
56instance Subtree MediaTypeObject where
56instance Subtree MediaTypeObject where
57 type SubtreeLevel MediaTypeObject = 'PayloadLevel
57 type SubtreeLevel MediaTypeObject = 'PayloadLevel
@@ -79,7 +79,7 @@ instance Subtree MediaTypeObject where
79 case tracedSchema p of
79 case tracedSchema p of
80 Nothing -> issueAt beh MediaTypeSchemaRequired
80 Nothing -> issueAt beh MediaTypeSchemaRequired
81 Just prodRef ->
81 Just prodRef ->
82โˆ’ checkCompatibility env (beh >>> step PayloadSchema) $
82+ checkCompatibility (beh >>> step PayloadSchema) env $
83 ProdCons prodRef consRef
83 ProdCons prodRef consRef
84 pure ()
84 pure ()
85 where
85 where
@@ -99,7 +99,7 @@ instance Subtree MediaTypeObject where
99 in checkProducts
99 in checkProducts
100 beh
100 beh
101 MediaEncodingMissing
101 MediaEncodingMissing
102โˆ’ (const $ checkCompatibility env beh)
102+ (const $ checkCompatibility beh env)
103 encProdCons
103 encProdCons
104
104
105instance Subtree Encoding where
105instance Subtree Encoding where
@@ -119,7 +119,7 @@ instance Subtree Encoding where
119
119
120 -- FIXME: Support only JSON body for now. Then Encoding is checked only for
120 -- FIXME: Support only JSON body for now. Then Encoding is checked only for
121 -- multipart/form-url-encoded
121 -- multipart/form-url-encoded
122โˆ’ -- https://github.com/typeable/openapi-diff/issues/54
122+ -- #54
123 checkSemanticCompatibility _env beh _pc =
123 checkSemanticCompatibility _env beh _pc =
124 issueAt beh EncodingNotSupported
124 issueAt beh EncodingNotSupported
125
125
@@ -143,21 +143,21 @@ instance Behavable 'OperationLevel 'ResponseLevel where
143 data Behave 'OperationLevel 'ResponseLevel
143 data Behave 'OperationLevel 'ResponseLevel
144 = WithStatusCode HttpStatusCode
144 = WithStatusCode HttpStatusCode
145 deriving stock (Eq, Ord, Show)
145 deriving stock (Eq, Ord, Show)
146โˆ’ describeBehaviour (WithStatusCode c) = "Response code " <> (fromString . show $ c)
146+ describeBehavior (WithStatusCode c) = "Response code " <> (fromString . show $ c)
147
147
148instance Issuable 'OperationLevel where
148instance Issuable 'OperationLevel where
149 data Issue 'OperationLevel
149 data Issue 'OperationLevel
150โˆ’ = ResponseCodeNotFound HttpStatusCode
150+ = ConsumerDoesntHaveResponseCode HttpStatusCode
151 | ParamNotMatched Text
151 | ParamNotMatched Text
152 | PathFragmentNotMatched Int
152 | PathFragmentNotMatched Int
153 | NoRequestBody
153 | NoRequestBody
154 deriving stock (Eq, Ord, Show)
154 deriving stock (Eq, Ord, Show)
155โˆ’ issueIsUnsupported = \case
155+ issueKind = \case
156โˆ’ _ -> False
156+ _ -> CertainIssue
157โˆ’ describeIssue Forward (ResponseCodeNotFound c) =
157+ describeIssue Forward (ConsumerDoesntHaveResponseCode c) =
158+ para $ "Response code " <> (str . T.pack . show $ c) <> " has been removed."
159+ describeIssue Backward (ConsumerDoesntHaveResponseCode c) =
158โˆ’ para $ "Reponse code " <> (str . T.pack . show $ c) <> " has been added."
160+ para $ "Response code " <> (str . T.pack . show $ c) <> " has been added."
159โˆ’ describeIssue Backward (ResponseCodeNotFound c) =
160โˆ’ para $ "Reponse code " <> (str . T.pack . show $ c) <> " has been removed."
161 describeIssue Forward (ParamNotMatched param) =
161 describeIssue Forward (ParamNotMatched param) =
162 para $ "Parameter " <> code param <> " has become required."
162 para $ "Parameter " <> code param <> " has become required."
163 describeIssue Backward (ParamNotMatched param) =
163 describeIssue Backward (ParamNotMatched param) =
src/OpenAPI/Checker/Validate/OAuth2Flows.hs โ†’ src/Data/OpenApi/Compare/Validate/OAuth2Flows.hsrenamed+28โˆ’23
@@ -1,9 +1,9 @@
1{-# OPTIONS_GHC -Wno-orphans #-}
1{-# OPTIONS_GHC -Wno-orphans #-}
2
2
3โˆ’module OpenAPI.Checker.Validate.OAuth2Flows
3+module Data.OpenApi.Compare.Validate.OAuth2Flows
4โˆ’ ( Step (..)
4+ ( Step (..),
5โˆ’ , Issue (..)
5+ Issue (..),
6โˆ’ , Behave (..)
6+ Behave (..),
7 )
7 )
8where
8where
9
9
@@ -12,13 +12,13 @@ import Data.Function
12import Data.Functor
12import Data.Functor
13import qualified Data.HashMap.Strict.InsOrd as IOHM
13import qualified Data.HashMap.Strict.InsOrd as IOHM
14import Data.OpenApi
14import Data.OpenApi
15+import Data.OpenApi.Compare.Behavior
16+import Data.OpenApi.Compare.Orphans ()
17+import Data.OpenApi.Compare.Subtree
15import Data.Proxy
18import Data.Proxy
16import Data.Set (Set)
19import Data.Set (Set)
17import qualified Data.Set as S
20import qualified Data.Set as S
18import Data.Text (Text)
21import Data.Text (Text)
19โˆ’import OpenAPI.Checker.Behavior
20โˆ’import OpenAPI.Checker.Orphans ()
21โˆ’import OpenAPI.Checker.Subtree
22import Text.Pandoc.Builder
22import Text.Pandoc.Builder
23
23
24instance Subtree OAuth2Flows where
24instance Subtree OAuth2Flows where
@@ -26,23 +26,23 @@ instance Subtree OAuth2Flows where
26 type SubtreeLevel OAuth2Flows = 'SecuritySchemeLevel
26 type SubtreeLevel OAuth2Flows = 'SecuritySchemeLevel
27 checkStructuralCompatibility _ = structuralEq
27 checkStructuralCompatibility _ = structuralEq
28 checkSemanticCompatibility env bhv pc = do
28 checkSemanticCompatibility env bhv pc = do
29โˆ’ let supportFlow
29+ let supportFlow ::
30โˆ’ :: (Subtree t, SubtreeLevel t ~ SubtreeLevel OAuth2Flows, CheckEnv OAuth2Flows ~ CheckEnv t)
30+ (Subtree t, SubtreeLevel t ~ SubtreeLevel OAuth2Flows, CheckEnv OAuth2Flows ~ CheckEnv t) =>
31โˆ’ => Issue 'SecuritySchemeLevel
31+ Issue 'SecuritySchemeLevel ->
32โˆ’ -> ProdCons (Maybe (Traced t))
32+ ProdCons (Maybe (Traced t)) ->
33โˆ’ -> SemanticCompatFormula ()
33+ SemanticCompatFormula ()
34 supportFlow i x = case x of
34 supportFlow i x = case x of
35 -- producer will not attempt this flow
35 -- producer will not attempt this flow
36 (ProdCons Nothing _) -> pure ()
36 (ProdCons Nothing _) -> pure ()
37 -- producer can attempt a flow the consumer does not know about
37 -- producer can attempt a flow the consumer does not know about
38 (ProdCons (Just _) Nothing) -> issueAt bhv i
38 (ProdCons (Just _) Nothing) -> issueAt bhv i
39 (ProdCons (Just p) (Just c)) ->
39 (ProdCons (Just p) (Just c)) ->
40โˆ’ checkCompatibility env bhv $ ProdCons p c
40+ checkCompatibility bhv env $ ProdCons p c
41โˆ’ getFlow
41+ getFlow ::
42โˆ’ :: Typeable x
42+ Typeable x =>
43โˆ’ => (OAuth2Flows -> Maybe (OAuth2Flow x))
43+ (OAuth2Flows -> Maybe (OAuth2Flow x)) ->
44โˆ’ -> Traced OAuth2Flows
44+ Traced OAuth2Flows ->
45โˆ’ -> Maybe (Traced (OAuth2Flow x))
45+ Maybe (Traced (OAuth2Flow x))
46 getFlow f (Traced t a) = Traced (t >>> step (OAuth2FlowsFlow Proxy)) <$> f a
46 getFlow f (Traced t a) = Traced (t >>> step (OAuth2FlowsFlow Proxy)) <$> f a
47 supportFlow ConsumerDoesNotSupportImplicitFlow $ getFlow _oAuth2FlowsImplicit <$> pc
47 supportFlow ConsumerDoesNotSupportImplicitFlow $ getFlow _oAuth2FlowsImplicit <$> pc
48 supportFlow ConsumerDoesNotSupportPasswordFlow $ getFlow _oAuth2FlowsPassword <$> pc
48 supportFlow ConsumerDoesNotSupportPasswordFlow $ getFlow _oAuth2FlowsPassword <$> pc
@@ -62,7 +62,7 @@ instance (Typeable t, Subtree t, SubtreeLevel (OAuth2Flow t) ~ SubtreeLevel t) =
62 let ProdCons pScopes cScopes = S.fromList . IOHM.keys . _oAuth2Scopes . extract <$> prodCons
62 let ProdCons pScopes cScopes = S.fromList . IOHM.keys . _oAuth2Scopes . extract <$> prodCons
63 missingScopes = cScopes S.\\ pScopes
63 missingScopes = cScopes S.\\ pScopes
64 unless (S.null missingScopes) (issueAt bhv $ ScopesMissing missingScopes)
64 unless (S.null missingScopes) (issueAt bhv $ ScopesMissing missingScopes)
65โˆ’ checkCompatibility env bhv $ retraced (>>> step (OAuth2FlowParamsStep Proxy)) . fmap _oAuth2Params <$> prodCons
65+ checkCompatibility bhv env $ retraced (>>> step (OAuth2FlowParamsStep Proxy)) . fmap _oAuth2Params <$> prodCons
66 unless (((==) `on` _oAath2RefreshUrl . extract) p c) $ issueAt bhv RefreshUrlsDontMatch
66 unless (((==) `on` _oAath2RefreshUrl . extract) p c) $ issueAt bhv RefreshUrlsDontMatch
67 pure ()
67 pure ()
68
68
@@ -103,7 +103,9 @@ instance Issuable 'SecurityRequirementLevel where
103 = SecurityRequirementNotMet
103 = SecurityRequirementNotMet
104 | UndefinedSecurityScheme Text
104 | UndefinedSecurityScheme Text
105 deriving stock (Eq, Ord, Show)
105 deriving stock (Eq, Ord, Show)
106โˆ’ issueIsUnsupported _ = False
106+ issueKind = \case
107+ SecurityRequirementNotMet -> CertainIssue
108+ UndefinedSecurityScheme _ -> SchemaInvalid
107 describeIssue Forward SecurityRequirementNotMet = para "Security scheme has been removed."
109 describeIssue Forward SecurityRequirementNotMet = para "Security scheme has been removed."
108 describeIssue Backward SecurityRequirementNotMet = para "Security scheme was added."
110 describeIssue Backward SecurityRequirementNotMet = para "Security scheme was added."
109 describeIssue _ (UndefinedSecurityScheme k) = para $ "Security scheme " <> code k <> " is not defined."
111 describeIssue _ (UndefinedSecurityScheme k) = para $ "Security scheme " <> code k <> " is not defined."
@@ -129,11 +131,14 @@ instance Issuable 'SecuritySchemeLevel where
129 | CanNotHaveScopes
131 | CanNotHaveScopes
130 | ScopeNotDefined Text
132 | ScopeNotDefined Text
131 deriving stock (Eq, Ord, Show)
133 deriving stock (Eq, Ord, Show)
132โˆ’ issueIsUnsupported _ = False
134+ issueKind = \case
135+ CanNotHaveScopes -> SchemaInvalid
136+ ScopeNotDefined _ -> SchemaInvalid
137+ _ -> CertainIssue
133 describeIssue _ RefreshUrlsDontMatch = para "Refresh URL changed."
138 describeIssue _ RefreshUrlsDontMatch = para "Refresh URL changed."
134 describeIssue _ (HttpSchemeTypesDontMatch _ _) = para "HTTP scheme type changed."
139 describeIssue _ (HttpSchemeTypesDontMatch _ _) = para "HTTP scheme type changed."
135 describeIssue _ (ApiKeyParamsDontMatch _ _) = para "API Key parameters changed."
140 describeIssue _ (ApiKeyParamsDontMatch _ _) = para "API Key parameters changed."
136โˆ’ describeIssue _ (OpenIdConnectUrlsDontMatch _ _) = para "OpenaId Connect URL changed."
141+ describeIssue _ (OpenIdConnectUrlsDontMatch _ _) = para "OpenID Connect URL changed."
137 describeIssue _ (CustomHttpSchemesDontMatch e a) =
142 describeIssue _ (CustomHttpSchemesDontMatch e a) =
138 para $ "Changed HTTP scheme from " <> code e <> " to " <> code a <> "."
143 para $ "Changed HTTP scheme from " <> code e <> " to " <> code a <> "."
139 describeIssue Forward ConsumerDoesNotSupportImplicitFlow = para "Implicit flow support has been removed."
144 describeIssue Forward ConsumerDoesNotSupportImplicitFlow = para "Implicit flow support has been removed."
@@ -162,4 +167,4 @@ instance Behavable 'SecurityRequirementLevel 'SecuritySchemeLevel where
162 data Behave 'SecurityRequirementLevel 'SecuritySchemeLevel
167 data Behave 'SecurityRequirementLevel 'SecuritySchemeLevel
163 = SecuritySchemeStep Text
168 = SecuritySchemeStep Text
164 deriving stock (Eq, Ord, Show)
169 deriving stock (Eq, Ord, Show)
165โˆ’ describeBehaviour (SecuritySchemeStep s) = text s
170+ describeBehavior (SecuritySchemeStep s) = text s
src/OpenAPI/Checker/Validate/OpenApi.hs โ†’ src/Data/OpenApi/Compare/Validate/OpenApi.hsrenamed+18โˆ’17
@@ -2,19 +2,19 @@
2-- Does not compiles otherwise
2-- Does not compiles otherwise
3{-# OPTIONS_GHC -fconstraint-solver-iterations=0 #-}
3{-# OPTIONS_GHC -fconstraint-solver-iterations=0 #-}
4
4
5โˆ’module OpenAPI.Checker.Validate.OpenApi
5+module Data.OpenApi.Compare.Validate.OpenApi
6โˆ’ ( Behave (..)
6+ ( Behave (..),
7โˆ’ , Issue (..)
7+ Issue (..),
8 )
8 )
9where
9where
10
10
11import Data.HList
11import Data.HList
12import qualified Data.HashMap.Strict.InsOrd as IOHM
12import qualified Data.HashMap.Strict.InsOrd as IOHM
13import Data.OpenApi
13import Data.OpenApi
14โˆ’import OpenAPI.Checker.Behavior
14+import Data.OpenApi.Compare.Behavior
15โˆ’import OpenAPI.Checker.Paths
15+import Data.OpenApi.Compare.Paths
16โˆ’import OpenAPI.Checker.Subtree
16+import Data.OpenApi.Compare.Subtree
17โˆ’import OpenAPI.Checker.Validate.Operation
17+import Data.OpenApi.Compare.Validate.Operation
18
18
19tracedPaths :: Traced OpenApi -> Traced ProcessedPathItems
19tracedPaths :: Traced OpenApi -> Traced ProcessedPathItems
20tracedPaths oa =
20tracedPaths oa =
@@ -78,17 +78,18 @@ instance Subtree OpenApi where
78 checkStructuralCompatibility _ _ = structuralIssue
78 checkStructuralCompatibility _ _ = structuralIssue
79 checkSemanticCompatibility _ beh prodCons = do
79 checkSemanticCompatibility _ beh prodCons = do
80 checkCompatibility @ProcessedPathItems
80 checkCompatibility @ProcessedPathItems
81โˆ’ ((tracedRequestBodies <$> prodCons)
82โˆ’ `HCons` (tracedParameters <$> prodCons)
83โˆ’ `HCons` (tracedSecuritySchemes <$> prodCons)
84โˆ’ `HCons` (tracedResponses <$> prodCons)
85โˆ’ `HCons` (tracedHeaders <$> prodCons)
86โˆ’ `HCons` (tracedSchemas <$> prodCons)
87โˆ’ `HCons` (_openApiServers . extract <$> prodCons)
88โˆ’ `HCons` (tracedLinks <$> prodCons)
89โˆ’ `HCons` (tracedCallbacks <$> prodCons)
90โˆ’ `HCons` HNil)
91 beh
81 beh
82+ ( (tracedRequestBodies <$> prodCons)
83+ `HCons` (tracedParameters <$> prodCons)
84+ `HCons` (tracedSecuritySchemes <$> prodCons)
85+ `HCons` (tracedResponses <$> prodCons)
86+ `HCons` (tracedHeaders <$> prodCons)
87+ `HCons` (tracedSchemas <$> prodCons)
88+ `HCons` (_openApiServers . extract <$> prodCons)
89+ `HCons` (tracedLinks <$> prodCons)
90+ `HCons` (tracedCallbacks <$> prodCons)
91+ `HCons` HNil
92+ )
92 (tracedPaths <$> prodCons)
93 (tracedPaths <$> prodCons)
93
94
94instance Steppable OpenApi ProcessedPathItems where
95instance Steppable OpenApi ProcessedPathItems where
src/OpenAPI/Checker/Validate/Operation.hs โ†’ src/Data/OpenApi/Compare/Validate/Operation.hsrenamed+70โˆ’86
@@ -2,19 +2,19 @@
2{-# OPTIONS_GHC -Wno-orphans #-}
2{-# OPTIONS_GHC -Wno-orphans #-}
3{-# OPTIONS_GHC -fconstraint-solver-iterations=0 #-}
3{-# OPTIONS_GHC -fconstraint-solver-iterations=0 #-}
4
4
5โˆ’module OpenAPI.Checker.Validate.Operation
5+module Data.OpenApi.Compare.Validate.Operation
6 ( -- * Operation
6 ( -- * Operation
7โˆ’ MatchedOperation (..)
7+ MatchedOperation (..),
8โˆ’ , OperationMethod (..)
8+ OperationMethod (..),
9โˆ’ , pathItemMethod
9+ pathItemMethod,
10
10
11 -- * ProcessedPathItem
11 -- * ProcessedPathItem
12โˆ’ , ProcessedPathItem (..)
12+ ProcessedPathItem (..),
13โˆ’ , ProcessedPathItems (..)
13+ ProcessedPathItems (..),
14โˆ’ , processPathItems
14+ processPathItems,
15โˆ’ , Step (..)
15+ Step (..),
16โˆ’ , Behave (..)
16+ Behave (..),
17โˆ’ , Issue (..)
17+ Issue (..),
18 )
18 )
19where
19where
20
20
@@ -29,21 +29,21 @@ import qualified Data.List as L
29import Data.Map.Strict as M
29import Data.Map.Strict as M
30import Data.Maybe
30import Data.Maybe
31import Data.OpenApi
31import Data.OpenApi
32+import Data.OpenApi.Compare.Behavior
33+import Data.OpenApi.Compare.References
34+import Data.OpenApi.Compare.Subtree
35+import Data.OpenApi.Compare.Validate.MediaTypeObject
36+import Data.OpenApi.Compare.Validate.OAuth2Flows
37+import Data.OpenApi.Compare.Validate.PathFragment
38+import Data.OpenApi.Compare.Validate.Products
39+import Data.OpenApi.Compare.Validate.RequestBody
40+import Data.OpenApi.Compare.Validate.Responses
41+import Data.OpenApi.Compare.Validate.SecurityRequirement ()
42+import Data.OpenApi.Compare.Validate.Server ()
43+import Data.OpenApi.Compare.Validate.Sums
32import Data.String
44import Data.String
33import Data.Text (Text)
45import Data.Text (Text)
34import qualified Data.Text as T
46import qualified Data.Text as T
35โˆ’import OpenAPI.Checker.Behavior
36โˆ’import OpenAPI.Checker.References
37โˆ’import OpenAPI.Checker.Subtree
38โˆ’import OpenAPI.Checker.Validate.MediaTypeObject
39โˆ’import OpenAPI.Checker.Validate.OAuth2Flows
40โˆ’import OpenAPI.Checker.Validate.PathFragment
41โˆ’import OpenAPI.Checker.Validate.Products
42โˆ’import OpenAPI.Checker.Validate.RequestBody
43โˆ’import OpenAPI.Checker.Validate.Responses
44โˆ’import OpenAPI.Checker.Validate.SecurityRequirement ()
45โˆ’import OpenAPI.Checker.Validate.Server ()
46โˆ’import OpenAPI.Checker.Validate.Sums
47import Text.Pandoc.Builder
47import Text.Pandoc.Builder
48
48
49data MatchedOperation = MatchedOperation
49data MatchedOperation = MatchedOperation
@@ -86,11 +86,12 @@ tracedCallbacks (Traced t oper) =
86 | (k, v) <- IOHM.toList . _operationCallbacks . operation $ oper
86 | (k, v) <- IOHM.toList . _operationCallbacks . operation $ oper
87 ]
87 ]
88
88
89โˆ’-- FIXME: https://github.com/typeable/openapi-diff/issues/28
89+-- FIXME: #28
90โˆ’getServers
90+getServers ::
91โˆ’ :: [Server] -- ^ Servers from env
91+ -- | Servers from env
92+ [Server] ->
92โˆ’ -> MatchedOperation
93+ MatchedOperation ->
93โˆ’ -> [Server]
94+ [Server]
94getServers env oper =
95getServers env oper =
95 case _operationServers . operation $ oper of
96 case _operationServers . operation $ oper of
96 [] -> env
97 [] -> env
@@ -101,21 +102,21 @@ instance Behavable 'OperationLevel 'PathFragmentLevel where
101 = InParam Text
102 = InParam Text
102 | InFragment (PathFragment Text)
103 | InFragment (PathFragment Text)
103 deriving stock (Eq, Ord, Show)
104 deriving stock (Eq, Ord, Show)
104โˆ’ describeBehaviour (InParam p) = "Parameter " <> text p
105+ describeBehavior (InParam p) = "Parameter " <> text p
105โˆ’ describeBehaviour (InFragment (StaticPath p)) = "Static fragment " <> code p
106+ describeBehavior (InFragment (StaticPath p)) = "Static fragment " <> code p
106โˆ’ describeBehaviour (InFragment (DynamicPath p)) = "Dynamic fragment " <> code p
107+ describeBehavior (InFragment (DynamicPath p)) = "Dynamic fragment " <> code p
107
108
108instance Behavable 'OperationLevel 'RequestLevel where
109instance Behavable 'OperationLevel 'RequestLevel where
109 data Behave 'OperationLevel 'RequestLevel
110 data Behave 'OperationLevel 'RequestLevel
110 = InRequest
111 = InRequest
111 deriving stock (Eq, Ord, Show)
112 deriving stock (Eq, Ord, Show)
112โˆ’ describeBehaviour InRequest = "Request"
113+ describeBehavior InRequest = "Request"
113
114
114instance Behavable 'OperationLevel 'SecurityRequirementLevel where
115instance Behavable 'OperationLevel 'SecurityRequirementLevel where
115 data Behave 'OperationLevel 'SecurityRequirementLevel
116 data Behave 'OperationLevel 'SecurityRequirementLevel
116 = SecurityRequirementStep Int
117 = SecurityRequirementStep Int
117 deriving stock (Eq, Ord, Show)
118 deriving stock (Eq, Ord, Show)
118โˆ’ describeBehaviour (SecurityRequirementStep i) =
119+ describeBehavior (SecurityRequirementStep i) =
119 "Security requirement " <> (text . T.pack . show $ i)
120 "Security requirement " <> (text . T.pack . show $ i)
120
121
121instance Subtree MatchedOperation where
122instance Subtree MatchedOperation where
@@ -203,8 +204,8 @@ instance Subtree MatchedOperation where
203 , required = fromMaybe False . _paramRequired . extract $ p
204 , required = fromMaybe False . _paramRequired . extract $ p
204 }
205 }
205 pure (k, v)
206 pure (k, v)
206โˆ’ check (_, name) param = do
207+ check (_, name) param =
207โˆ’ checkCompatibility @Param (singletonH schemaDefs) (beh >>> step (InParam name)) param
208+ checkCompatibility @Param (beh >>> step (InParam name)) env param
208 checkProducts beh (ParamNotMatched . snd) check elements
209 checkProducts beh (ParamNotMatched . snd) check elements
209 checkPathParams :: ProdCons [Traced Param] -> SemanticCompatFormula ()
210 checkPathParams :: ProdCons [Traced Param] -> SemanticCompatFormula ()
210 checkPathParams pathParams = do
211 checkPathParams pathParams = do
@@ -213,7 +214,7 @@ instance Subtree MatchedOperation where
213 getFragments params mop = getPathFragments (extract mop) params
214 getFragments params mop = getPathFragments (extract mop) params
214 -- Feed path parameters to the fragments getter
215 -- Feed path parameters to the fragments getter
215 check _ frags@(ProdCons (Traced _ p) _) =
216 check _ frags@(ProdCons (Traced _ p) _) =
216โˆ’ checkCompatibility @PathFragmentParam env (beh >>> step (InFragment $ _paramName . extract <$> p)) frags
217+ checkCompatibility @PathFragmentParam (beh >>> step (InFragment $ _paramName . extract <$> p)) env frags
217 elements =
218 elements =
218 fragments <&> \frags -> M.fromList $
219 fragments <&> \frags -> M.fromList $
219 zip [0 :: Int ..] $ do
220 zip [0 :: Int ..] $ do
@@ -225,7 +226,7 @@ instance Subtree MatchedOperation where
225 }
226 }
226 checkProducts beh PathFragmentNotMatched check elements
227 checkProducts beh PathFragmentNotMatched check elements
227 checkRequestBodies = do
228 checkRequestBodies = do
228โˆ’ let check reqBody = checkCompatibility @RequestBody env (beh >>> step InRequest) reqBody
229+ let check reqBody = checkCompatibility @RequestBody (beh >>> step InRequest) env reqBody
229 elements = getReqBody <$> bodyDefs <*> prodCons
230 elements = getReqBody <$> bodyDefs <*> prodCons
230 getReqBody bodyDef mop = M.fromList $ do
231 getReqBody bodyDef mop = M.fromList $ do
231 bodyRef <- F.toList . tracedRequestBody $ mop
232 bodyRef <- F.toList . tracedRequestBody $ mop
@@ -239,55 +240,32 @@ instance Subtree MatchedOperation where
239 }
240 }
240 )
241 )
241 checkProducts beh (const NoRequestBody) (const check) elements
242 checkProducts beh (const NoRequestBody) (const check) elements
242โˆ’ checkResponses = do
243+ checkResponses =
243โˆ’ let respEnv =
244โˆ’ HCons (swapProdCons respDefs) $
245โˆ’ HCons (swapProdCons headerDefs) $
246โˆ’ HCons (swapProdCons schemaDefs) $
247โˆ’ HCons (swapProdCons linkDefs) HNil
248โˆ’ resps = tracedResponses <$> prodCons
244+ swapProdCons (checkCompatibility beh) env $ tracedResponses <$> prodCons
249โˆ’ checkCompatibility respEnv beh $ swapProdCons resps
245+ -- FIXME: #27
250โˆ’ -- FIXME: https://github.com/typeable/openapi-diff/issues/27
251 checkCallbacks = do
246 checkCallbacks = do
252โˆ’ let env' =
253โˆ’ HCons (swapProdCons respDefs) $
254โˆ’ HCons (swapProdCons headerDefs) $
255โˆ’ HCons (swapProdCons schemaDefs) $
256โˆ’ HCons (swapProdCons securitySchemeDefs) $
257โˆ’ HCons (swapProdCons paramDefs) $
258โˆ’ HCons (swapProdCons serversDefs) $
259โˆ’ HCons (swapProdCons callbackDefs) $
260โˆ’ HCons (swapProdCons bodyDefs) $
261โˆ’ HCons (swapProdCons linkDefs) HNil
262โˆ’ let ProdCons pCallbacks cCallbacks = swapProdCons $ tracedCallbacks <$> prodCons
247+ let ProdCons pCallbacks cCallbacks = tracedCallbacks <$> prodCons
263 for_ pCallbacks $ \(k, pCallback) -> do
248 for_ pCallbacks $ \(k, pCallback) -> do
264 let beh' = beh >>> step (OperationCallback k)
249 let beh' = beh >>> step (OperationCallback k)
265 anyOfAt beh' CallbacksUnsupported $
250 anyOfAt beh' CallbacksUnsupported $
266 cCallbacks <&> \(_, cCallback) -> do
251 cCallbacks <&> \(_, cCallback) -> do
267โˆ’ checkCompatibility env' beh' $ ProdCons pCallback cCallback
252+ swapProdCons (checkCompatibility beh') env $ ProdCons pCallback cCallback
268 pure ()
253 pure ()
269โˆ’ -- FIXME: https://github.com/typeable/openapi-diff/issues/28
254+ -- FIXME: #28
270 checkOperationSecurity = do
255 checkOperationSecurity = do
271 let ProdCons pSecs cSecs = tracedSecurity <$> prodCons
256 let ProdCons pSecs cSecs = tracedSecurity <$> prodCons
272 for_ pSecs $ \(i, pSec) -> do
257 for_ pSecs $ \(i, pSec) -> do
273 let beh' = beh >>> step (SecurityRequirementStep i)
258 let beh' = beh >>> step (SecurityRequirementStep i)
274 anyOfAt beh' SecurityRequirementNotMet $
259 anyOfAt beh' SecurityRequirementNotMet $
275 cSecs <&> \(_, cSec) ->
260 cSecs <&> \(_, cSec) ->
276โˆ’ checkCompatibility env beh' $ ProdCons pSec cSec
261+ checkCompatibility beh' env $ ProdCons pSec cSec
277 checkServers =
262 checkServers =
278โˆ’ checkCompatibility env beh $ do
263+ checkCompatibility beh env $ do
279 x <- prodCons
264 x <- prodCons
280 se <- getH @(ProdCons [Server]) env
265 se <- getH @(ProdCons [Server]) env
281 pure $ Traced (ask x >>> step OperationServersStep) (getServers se (extract x))
266 pure $ Traced (ask x >>> step OperationServersStep) (getServers se (extract x))
282 bodyDefs = getH @(ProdCons (Traced (Definitions RequestBody))) env
267 bodyDefs = getH @(ProdCons (Traced (Definitions RequestBody))) env
283โˆ’ respDefs = getH @(ProdCons (Traced (Definitions Response))) env
284โˆ’ headerDefs = getH @(ProdCons (Traced (Definitions Header))) env
285โˆ’ schemaDefs = getH @(ProdCons (Traced (Definitions Schema))) env
286 paramDefs = getH @(ProdCons (Traced (Definitions Param))) env
268 paramDefs = getH @(ProdCons (Traced (Definitions Param))) env
287โˆ’ linkDefs = getH @(ProdCons (Traced (Definitions Link))) env
288โˆ’ callbackDefs = getH @(ProdCons (Traced (Definitions Callback))) env
289โˆ’ securitySchemeDefs = getH @(ProdCons (Traced (Definitions SecurityScheme))) env
290โˆ’ serversDefs = getH @(ProdCons [Server]) env
291
269
292data OperationMethod
270data OperationMethod
293 = GetMethod
271 = GetMethod
@@ -358,7 +336,12 @@ instance Issuable 'APILevel where
358 | AllPathsFailed FilePath
336 | AllPathsFailed FilePath
359 -- When several paths match given but all checks failed
337 -- When several paths match given but all checks failed
360 deriving stock (Eq, Ord, Show)
338 deriving stock (Eq, Ord, Show)
361โˆ’ issueIsUnsupported _ = False
339+ issueKind = \case
340+ _ -> CertainIssue
341+ relatedIssues =
342+ (==) `withClass` \case
343+ NoPathsMatched fp -> Just fp
344+ AllPathsFailed fp -> Just fp
362 describeIssue Forward (NoPathsMatched p) = para $ "The path " <> (code . T.pack) p <> " has been removed."
345 describeIssue Forward (NoPathsMatched p) = para $ "The path " <> (code . T.pack) p <> " has been removed."
363 describeIssue Backward (NoPathsMatched p) = para $ "The path " <> (code . T.pack) p <> " has been added."
346 describeIssue Backward (NoPathsMatched p) = para $ "The path " <> (code . T.pack) p <> " has been added."
364 describeIssue Forward (AllPathsFailed p) = para $ "The path " <> (code . T.pack) p <> " has been removed."
347 describeIssue Forward (AllPathsFailed p) = para $ "The path " <> (code . T.pack) p <> " has been removed."
@@ -369,7 +352,7 @@ instance Behavable 'APILevel 'PathLevel where
369 = AtPath FilePath
352 = AtPath FilePath
370 deriving stock (Eq, Ord, Show)
353 deriving stock (Eq, Ord, Show)
371
354
372โˆ’ describeBehaviour (AtPath p) = str (T.pack p)
355+ describeBehavior (AtPath p) = str (T.pack p)
373
356
374instance Subtree ProcessedPathItems where
357instance Subtree ProcessedPathItems where
375 type SubtreeLevel ProcessedPathItems = 'APILevel
358 type SubtreeLevel ProcessedPathItems = 'APILevel
@@ -399,10 +382,10 @@ instance Subtree ProcessedPathItems where
399 F.toList $ matchingPathItems $ ProdCons prodItem consItem
382 F.toList $ matchingPathItems $ ProdCons prodItem consItem
400 case matchedItems of
383 case matchedItems of
401 [] -> issueAt beh $ NoPathsMatched prodPath
384 [] -> issueAt beh $ NoPathsMatched prodPath
402โˆ’ [match] -> checkCompatibility env beh' (retraced <$> pc <*> match)
385+ [match] -> checkCompatibility beh' env (retraced <$> pc <*> match)
403 matches -> anyOfAt beh (AllPathsFailed prodPath) $ do
386 matches -> anyOfAt beh (AllPathsFailed prodPath) $ do
404 match <- matches
387 match <- matches
405โˆ’ pure $ checkCompatibility env beh' (retraced <$> pc <*> match)
388+ pure $ checkCompatibility beh' env (retraced <$> pc <*> match)
406 where
389 where
407 retraced pc mpi = traced (ask pc >>> step (MatchedPathStep $ matchedPath mpi)) mpi
390 retraced pc mpi = traced (ask pc >>> step (MatchedPathStep $ matchedPath mpi)) mpi
408
391
@@ -453,17 +436,18 @@ tracedFragments mpi =
453 | (i, x) <- L.zip [0 ..] $ pathFragments $ extract mpi
436 | (i, x) <- L.zip [0 ..] $ pathFragments $ extract mpi
454 ]
437 ]
455
438
456โˆ’tracedMethod
439+tracedMethod ::
457โˆ’ :: OperationMethod
440+ OperationMethod ->
458โˆ’ -> Traced MatchedPathItem
441+ Traced MatchedPathItem ->
459โˆ’ -> Maybe (Traced' MatchedOperation Operation)
442+ Maybe (Traced' MatchedOperation Operation)
460tracedMethod s mpi = env (ask mpi >>> step (OperationMethodStep s)) <$> (pathItemMethod s . pathItem . extract $ mpi)
443tracedMethod s mpi = env (ask mpi >>> step (OperationMethodStep s)) <$> (pathItemMethod s . pathItem . extract $ mpi)
461
444
462instance Issuable 'PathLevel where
445instance Issuable 'PathLevel where
463 data Issue 'PathLevel
446 data Issue 'PathLevel
464 = OperationMissing OperationMethod
447 = OperationMissing OperationMethod
465 deriving stock (Eq, Ord, Show)
448 deriving stock (Eq, Ord, Show)
466โˆ’ issueIsUnsupported _ = False
449+ issueKind = \case
450+ OperationMissing _ -> CertainIssue
467 describeIssue Forward (OperationMissing op) = para $ "Method " <> strong (showMethod op) <> " has been removed."
451 describeIssue Forward (OperationMissing op) = para $ "Method " <> strong (showMethod op) <> " has been removed."
468 describeIssue Backward (OperationMissing op) = para $ "Method " <> strong (showMethod op) <> " has been added."
452 describeIssue Backward (OperationMissing op) = para $ "Method " <> strong (showMethod op) <> " has been added."
469
453
@@ -472,7 +456,7 @@ instance Behavable 'PathLevel 'OperationLevel where
472 = InOperation OperationMethod
456 = InOperation OperationMethod
473 deriving stock (Eq, Ord, Show)
457 deriving stock (Eq, Ord, Show)
474
458
475โˆ’ describeBehaviour (InOperation method) = showMethod method
459+ describeBehavior (InOperation method) = showMethod method
476
460
477showMethod :: IsString s => OperationMethod -> s
461showMethod :: IsString s => OperationMethod -> s
478showMethod = \case
462showMethod = \case
@@ -503,10 +487,10 @@ instance Subtree MatchedPathItem where
503 checkSemanticCompatibility env beh prodCons = do
487 checkSemanticCompatibility env beh prodCons = do
504 let paramDefs = getH @(ProdCons (Traced (Definitions Param))) env
488 let paramDefs = getH @(ProdCons (Traced (Definitions Param))) env
505 pathTracedParams = getPathParams <$> paramDefs <*> prodCons
489 pathTracedParams = getPathParams <$> paramDefs <*> prodCons
506โˆ’ getPathParams
490+ getPathParams ::
507โˆ’ :: Traced (Definitions Param)
491+ Traced (Definitions Param) ->
508โˆ’ -> Traced MatchedPathItem
492+ Traced MatchedPathItem ->
509โˆ’ -> [Traced Param]
493+ [Traced Param]
510 getPathParams defs mpi = do
494 getPathParams defs mpi = do
511 paramRef <- tracedMatchedPathItemParameters mpi
495 paramRef <- tracedMatchedPathItemParameters mpi
512 pure $ dereference defs paramRef
496 pure $ dereference defs paramRef
@@ -535,7 +519,7 @@ instance Subtree MatchedPathItem where
535 -- Got only Justs here
519 -- Got only Justs here
536 let retraced = \op -> MatchedOperation {operation = op, pathParams, getPathFragments}
520 let retraced = \op -> MatchedOperation {operation = op, pathParams, getPathFragments}
537 pure (name, retraced <$> operation)
521 pure (name, retraced <$> operation)
538โˆ’ check name pc = checkCompatibility @MatchedOperation env (beh >>> step (InOperation name)) pc
522+ check name pc = checkCompatibility @MatchedOperation (beh >>> step (InOperation name)) env pc
539 -- Operations are sum-like entities. Use step to operation as key because
523 -- Operations are sum-like entities. Use step to operation as key because
540 -- why not
524 -- why not
541 checkSums beh OperationMissing check operations
525 checkSums beh OperationMissing check operations
@@ -580,9 +564,9 @@ instance Issuable 'CallbackLevel where
580 data Issue 'CallbackLevel
564 data Issue 'CallbackLevel
581 = CallbacksUnsupported
565 = CallbacksUnsupported
582 deriving stock (Eq, Ord, Show)
566 deriving stock (Eq, Ord, Show)
583โˆ’ issueIsUnsupported = \case
567+ issueKind = \case
584โˆ’ CallbacksUnsupported -> True
568+ CallbacksUnsupported -> Unsupported
585โˆ’ describeIssue _ CallbacksUnsupported = para "OpenApi Diff does not currently support callbacks."
569+ describeIssue _ CallbacksUnsupported = para "CompaREST does not currently support callbacks."
586
570
587tracedCallbackPathItems :: Traced Callback -> Traced ProcessedPathItems
571tracedCallbackPathItems :: Traced Callback -> Traced ProcessedPathItems
588tracedCallbackPathItems (Traced t (Callback x)) =
572tracedCallbackPathItems (Traced t (Callback x)) =
@@ -596,4 +580,4 @@ instance Behavable 'OperationLevel 'CallbackLevel where
596 data Behave 'OperationLevel 'CallbackLevel = OperationCallback Text
580 data Behave 'OperationLevel 'CallbackLevel = OperationCallback Text
597 deriving stock (Eq, Ord, Show)
581 deriving stock (Eq, Ord, Show)
598
582
599โˆ’ describeBehaviour (OperationCallback key) = "Operation " <> code key
583+ describeBehavior (OperationCallback key) = "Operation " <> code key
src/OpenAPI/Checker/Validate/Param.hs โ†’ src/Data/OpenApi/Compare/Validate/Param.hsrenamed+21โˆ’16
@@ -1,9 +1,9 @@
1{-# OPTIONS_GHC -Wno-orphans #-}
1{-# OPTIONS_GHC -Wno-orphans #-}
2{-# OPTIONS_GHC -fno-warn-name-shadowing #-}
2{-# OPTIONS_GHC -fno-warn-name-shadowing #-}
3
3
4โˆ’module OpenAPI.Checker.Validate.Param
4+module Data.OpenApi.Compare.Validate.Param
5โˆ’ ( Behave (..)
5+ ( Behave (..),
6โˆ’ , Issue (..)
6+ Issue (..),
7 )
7 )
8where
8where
9
9
@@ -11,11 +11,11 @@ import Control.Monad
11import Data.Functor
11import Data.Functor
12import Data.Maybe
12import Data.Maybe
13import Data.OpenApi
13import Data.OpenApi
14+import Data.OpenApi.Compare.Behavior
15+import Data.OpenApi.Compare.Orphans ()
16+import Data.OpenApi.Compare.Subtree
17+import Data.OpenApi.Compare.Validate.Schema ()
14import Data.Text as T
18import Data.Text as T
15โˆ’import OpenAPI.Checker.Behavior
16โˆ’import OpenAPI.Checker.Orphans ()
17โˆ’import OpenAPI.Checker.Subtree
18โˆ’import OpenAPI.Checker.Validate.Schema ()
19import Text.Pandoc.Builder
19import Text.Pandoc.Builder
20
20
21-- | The type is normalized encoding style of the parameter. If two encoding
21-- | The type is normalized encoding style of the parameter. If two encoding
@@ -66,9 +66,11 @@ instance Issuable 'PathFragmentLevel where
66 ParamStyleMismatch
66 ParamStyleMismatch
67 | -- | One of schemas not presented
67 | -- | One of schemas not presented
68 ParamSchemaMismatch
68 ParamSchemaMismatch
69โˆ’ | PathFragmentsDontMatch Text Text
69+ | PathFragmentsDontMatch (ProdCons Text)
70 deriving stock (Eq, Ord, Show)
70 deriving stock (Eq, Ord, Show)
71โˆ’ issueIsUnsupported _ = False
71+ issueKind = \case
72+ ParamSchemaMismatch -> ProbablyIssue -- the schema could be catch-all (?)
73+ _ -> CertainIssue
72 describeIssue _ ParamNameMismatch = para "The path fragments don't match."
74 describeIssue _ ParamNameMismatch = para "The path fragments don't match."
73 describeIssue Forward ParamEmptinessIncompatible = para "The parameter can no longer be empty."
75 describeIssue Forward ParamEmptinessIncompatible = para "The parameter can no longer be empty."
74 describeIssue Backward ParamEmptinessIncompatible = para "The parameter can now be empty."
76 describeIssue Backward ParamEmptinessIncompatible = para "The parameter can now be empty."
@@ -77,14 +79,15 @@ instance Issuable 'PathFragmentLevel where
77 describeIssue _ ParamPlaceIncompatible = para "Parameters in incompatible locations."
79 describeIssue _ ParamPlaceIncompatible = para "Parameters in incompatible locations."
78 describeIssue _ ParamStyleMismatch = para "Different parameter styles (encodings)."
80 describeIssue _ ParamStyleMismatch = para "Different parameter styles (encodings)."
79 describeIssue _ ParamSchemaMismatch = para "Expected a schema, but didn't find one."
81 describeIssue _ ParamSchemaMismatch = para "Expected a schema, but didn't find one."
82+ describeIssue ori (PathFragmentsDontMatch (orientProdCons ori -> ProdCons e a)) =
80โˆ’ describeIssue _ (PathFragmentsDontMatch e a) = para $ "Parameter changed from " <> code e <> " to " <> code a <> "."
83+ para $ "Parameter changed from " <> code e <> " to " <> code a <> "."
81
84
82instance Behavable 'PathFragmentLevel 'SchemaLevel where
85instance Behavable 'PathFragmentLevel 'SchemaLevel where
83 data Behave 'PathFragmentLevel 'SchemaLevel
86 data Behave 'PathFragmentLevel 'SchemaLevel
84 = InParamSchema
87 = InParamSchema
85 deriving stock (Eq, Ord, Show)
88 deriving stock (Eq, Ord, Show)
86
89
87โˆ’ describeBehaviour InParamSchema = "JSON Schema"
90+ describeBehavior InParamSchema = "JSON Schema"
88
91
89instance Subtree Param where
92instance Subtree Param where
90 type SubtreeLevel Param = 'PathFragmentLevel
93 type SubtreeLevel Param = 'PathFragmentLevel
@@ -103,15 +106,17 @@ instance Subtree Param where
103 when (_paramName (extract p) /= _paramName (extract c)) $
106 when (_paramName (extract p) /= _paramName (extract c)) $
104 issueAt beh ParamNameMismatch
107 issueAt beh ParamNameMismatch
105 when
108 when
106โˆ’ ((fromMaybe False . _paramRequired . extract $ c)
109+ ( (fromMaybe False . _paramRequired . extract $ c)
107โˆ’ && not (fromMaybe False . _paramRequired . extract $ p))
110+ && not (fromMaybe False . _paramRequired . extract $ p)
111+ )
108 $ issueAt beh ParamRequired
112 $ issueAt beh ParamRequired
109 case (_paramIn . extract $ p, _paramIn . extract $ c) of
113 case (_paramIn . extract $ p, _paramIn . extract $ c) of
110 (ParamQuery, ParamQuery) -> do
114 (ParamQuery, ParamQuery) -> do
111 -- Emptiness is only for query params
115 -- Emptiness is only for query params
112 when
116 when
113โˆ’ ((fromMaybe False . _paramAllowEmptyValue . extract $ p)
117+ ( (fromMaybe False . _paramAllowEmptyValue . extract $ p)
114โˆ’ && not (fromMaybe False . _paramAllowEmptyValue . extract $ c))
118+ && not (fromMaybe False . _paramAllowEmptyValue . extract $ c)
119+ )
115 $ issueAt beh ParamEmptinessIncompatible
120 $ issueAt beh ParamEmptinessIncompatible
116 (a, b) | a == b -> pure ()
121 (a, b) | a == b -> pure ()
117 _ -> issueAt beh ParamPlaceIncompatible
122 _ -> issueAt beh ParamPlaceIncompatible
@@ -119,7 +124,7 @@ instance Subtree Param where
119 issueAt beh ParamStyleMismatch
124 issueAt beh ParamStyleMismatch
120 case tracedSchema <$> pc of
125 case tracedSchema <$> pc of
121 ProdCons (Just prodSchema) (Just consSchema) -> do
126 ProdCons (Just prodSchema) (Just consSchema) -> do
122โˆ’ checkCompatibility env (beh >>> step InParamSchema) $ ProdCons prodSchema consSchema
127+ checkCompatibility (beh >>> step InParamSchema) env $ ProdCons prodSchema consSchema
123 ProdCons Nothing Nothing -> pure ()
128 ProdCons Nothing Nothing -> pure ()
124 ProdCons Nothing (Just _consSchema) -> issueAt beh ParamSchemaMismatch
129 ProdCons Nothing (Just _consSchema) -> issueAt beh ParamSchemaMismatch
125 ProdCons (Just _prodSchema) Nothing -> pure ()
130 ProdCons (Just _prodSchema) Nothing -> pure ()
src/OpenAPI/Checker/Validate/PathFragment.hs โ†’ src/Data/OpenApi/Compare/Validate/PathFragment.hsrenamed+10โˆ’11
@@ -1,21 +1,20 @@
1โˆ’module OpenAPI.Checker.Validate.PathFragment
1+module Data.OpenApi.Compare.Validate.PathFragment
2โˆ’ ( parsePath
2+ ( parsePath,
3โˆ’ , PathFragment (..)
3+ PathFragment (..),
4โˆ’ , PathFragmentParam
4+ PathFragmentParam,
5 )
5 )
6where
6where
7
7
8import qualified Data.Aeson as A
8import qualified Data.Aeson as A
9import Data.OpenApi
9import Data.OpenApi
10+import Data.OpenApi.Compare.Behavior
11+import Data.OpenApi.Compare.Subtree
12+import Data.OpenApi.Compare.Validate.Param
10import Data.Text (Text)
13import Data.Text (Text)
11import qualified Data.Text as T
14import qualified Data.Text as T
12โˆ’import Data.Typeable
13โˆ’import OpenAPI.Checker.Behavior
14โˆ’import OpenAPI.Checker.Subtree
15โˆ’import OpenAPI.Checker.Validate.Param
16
15
17-- TODO: templates can be only part of the PathFragment. Currently only supports templates as full PathFragment.
16-- TODO: templates can be only part of the PathFragment. Currently only supports templates as full PathFragment.
18โˆ’-- https://github.com/typeable/openapi-diff/issues/23
17+-- #23
19parsePath :: FilePath -> [PathFragment Text]
18parsePath :: FilePath -> [PathFragment Text]
20parsePath = fmap partition . T.splitOn "/" . T.pack
19parsePath = fmap partition . T.splitOn "/" . T.pack
21 where
20 where
@@ -74,6 +73,6 @@ instance Subtree PathFragmentParam where
74 checkSemanticCompatibility _ beh (ProdCons (extract -> StaticPath x) (extract -> StaticPath y)) =
73 checkSemanticCompatibility _ beh (ProdCons (extract -> StaticPath x) (extract -> StaticPath y)) =
75 if x == y
74 if x == y
76 then pure ()
75 then pure ()
77โˆ’ else issueAt beh (PathFragmentsDontMatch x y)
76+ else issueAt beh (PathFragmentsDontMatch (ProdCons x y))
78 checkSemanticCompatibility env beh prodCons = do
77 checkSemanticCompatibility env beh prodCons = do
79โˆ’ checkCompatibility env beh (tracedPathFragmentParam <$> prodCons)
78+ checkCompatibility beh env (tracedPathFragmentParam <$> prodCons)
src/Data/OpenApi/Compare/Validate/Products.hsnew file+48
@@ -0,0 +1,48 @@
1+-- | Checks product-like entities. The key is some identificator for the product
2+--element. Each element may be required or optional.
3+--
4+--One example of product is request parameters. There are optional and required
5+--parameters. The client and server have possibly different set of
6+--parameters. What we must check is if server requires some request parameter,
7+--then this parameter must be presented by client and their schemas must match.
8+--
9+--So when we checking products we are checking from the server's (consumer)
10+--perspective, ensuring that all parameters are provided by the client (producer)
11+--and their schemas match.
12+--
13+--This module abstracts this logic for arbitrary elements
14+module Data.OpenApi.Compare.Validate.Products
15+ ( checkProducts,
16+ ProductLike (..),
17+ )
18+where
19+
20+import Data.Foldable
21+import Data.Map.Strict (Map)
22+import qualified Data.Map.Strict as M
23+import Data.OpenApi.Compare.Behavior
24+import Data.OpenApi.Compare.Paths
25+import Data.OpenApi.Compare.Subtree
26+
27+-- | Some entity which is product-like
28+data ProductLike a = ProductLike
29+ { productValue :: a
30+ , required :: Bool
31+ }
32+
33+checkProducts ::
34+ (Ord k, Issuable l) =>
35+ Paths q r l ->
36+ -- | No required element found
37+ (k -> Issue l) ->
38+ (k -> ProdCons t -> CompatFormula' q AnIssue r ()) ->
39+ ProdCons (Map k (ProductLike t)) ->
40+ CompatFormula' q AnIssue r ()
41+checkProducts xs noElt check (ProdCons p c) = for_ (M.toList c) $ \(key, consElt) ->
42+ case M.lookup key p of
43+ Nothing -> case required consElt of
44+ True -> issueAt xs $ noElt key
45+ False -> pure ()
46+ Just prodElt -> do
47+ let elts = ProdCons prodElt consElt
48+ check key (productValue <$> elts)
src/OpenAPI/Checker/Validate/RequestBody.hs โ†’ src/Data/OpenApi/Compare/Validate/RequestBody.hsrenamed+11โˆ’10
@@ -1,8 +1,8 @@
1{-# OPTIONS_GHC -Wno-orphans #-}
1{-# OPTIONS_GHC -Wno-orphans #-}
2
2
3โˆ’module OpenAPI.Checker.Validate.RequestBody
3+module Data.OpenApi.Compare.Validate.RequestBody
4โˆ’ ( Issue (..)
4+ ( Issue (..),
5โˆ’ , Behave (..)
5+ Behave (..),
6 )
6 )
7where
7where
8
8
@@ -11,12 +11,12 @@ import Data.HashMap.Strict.InsOrd as IOHM
11import Data.Map.Strict as M
11import Data.Map.Strict as M
12import Data.Maybe
12import Data.Maybe
13import Data.OpenApi
13import Data.OpenApi
14+import Data.OpenApi.Compare.Behavior
15+import Data.OpenApi.Compare.Subtree
16+import Data.OpenApi.Compare.Validate.MediaTypeObject
17+import Data.OpenApi.Compare.Validate.Sums
14import qualified Data.Text as T
18import qualified Data.Text as T
15import Network.HTTP.Media (MediaType)
19import Network.HTTP.Media (MediaType)
16โˆ’import OpenAPI.Checker.Behavior
17โˆ’import OpenAPI.Checker.Subtree
18โˆ’import OpenAPI.Checker.Validate.MediaTypeObject
19โˆ’import OpenAPI.Checker.Validate.Sums
20import Text.Pandoc.Builder
20import Text.Pandoc.Builder
21
21
22-- TODO: Use RequestMediaTypeObjectMapping
22-- TODO: Use RequestMediaTypeObjectMapping
@@ -30,7 +30,8 @@ instance Issuable 'RequestLevel where
30 = RequestBodyRequired
30 = RequestBodyRequired
31 | RequestMediaTypeNotFound MediaType
31 | RequestMediaTypeNotFound MediaType
32 deriving stock (Eq, Ord, Show)
32 deriving stock (Eq, Ord, Show)
33โˆ’ issueIsUnsupported _ = False
33+ issueKind = \case
34+ _ -> CertainIssue
34 describeIssue Forward RequestBodyRequired =
35 describeIssue Forward RequestBodyRequired =
35 para "Request body has become required."
36 para "Request body has become required."
36 describeIssue Backward RequestBodyRequired =
37 describeIssue Backward RequestBodyRequired =
@@ -44,7 +45,7 @@ instance Behavable 'RequestLevel 'PayloadLevel where
44 data Behave 'RequestLevel 'PayloadLevel
45 data Behave 'RequestLevel 'PayloadLevel
45 = InPayload
46 = InPayload
46 deriving stock (Eq, Ord, Show)
47 deriving stock (Eq, Ord, Show)
47โˆ’ describeBehaviour InPayload = "Payload"
48+ describeBehavior InPayload = "Payload"
48
49
49instance Subtree RequestBody where
50instance Subtree RequestBody where
50 type SubtreeLevel RequestBody = 'RequestLevel
51 type SubtreeLevel RequestBody = 'RequestLevel
@@ -64,7 +65,7 @@ instance Subtree RequestBody where
64 then issueAt beh RequestBodyRequired
65 then issueAt beh RequestBodyRequired
65 else -- Media type object are sums-like entities.
66 else -- Media type object are sums-like entities.
66
67
67โˆ’ let check mediaType pc = checkCompatibility @MediaTypeObject (HCons mediaType env) (beh >>> step InPayload) pc
68+ let check mediaType pc = checkCompatibility @MediaTypeObject (beh >>> step InPayload) (HCons mediaType env) pc
68 sumElts = getSum <$> prodCons
69 sumElts = getSum <$> prodCons
69 getSum rb = M.fromList . IOHM.toList $ tracedContent rb
70 getSum rb = M.fromList . IOHM.toList $ tracedContent rb
70 in checkSums beh RequestMediaTypeNotFound check sumElts
71 in checkSums beh RequestMediaTypeNotFound check sumElts
src/OpenAPI/Checker/Validate/Responses.hs โ†’ src/Data/OpenApi/Compare/Validate/Responses.hsrenamed+29โˆ’28
@@ -1,8 +1,8 @@
1{-# OPTIONS_GHC -Wno-orphans #-}
1{-# OPTIONS_GHC -Wno-orphans #-}
2{-# OPTIONS_GHC -fno-warn-name-shadowing #-}
2{-# OPTIONS_GHC -fno-warn-name-shadowing #-}
3
3
4โˆ’module OpenAPI.Checker.Validate.Responses
4+module Data.OpenApi.Compare.Validate.Responses
5โˆ’ ( Behave (..)
5+ ( Behave (..),
6 )
6 )
7where
7where
8
8
@@ -11,17 +11,17 @@ import Data.HashMap.Strict.InsOrd as IOHM
11import Data.Map.Strict as M
11import Data.Map.Strict as M
12import Data.Maybe
12import Data.Maybe
13import Data.OpenApi
13import Data.OpenApi
14+import Data.OpenApi.Compare.Behavior
15+import Data.OpenApi.Compare.References
16+import Data.OpenApi.Compare.Subtree
17+import Data.OpenApi.Compare.Validate.Header ()
18+import Data.OpenApi.Compare.Validate.Link ()
19+import Data.OpenApi.Compare.Validate.MediaTypeObject
20+import Data.OpenApi.Compare.Validate.Products
21+import Data.OpenApi.Compare.Validate.Schema ()
22+import Data.OpenApi.Compare.Validate.Sums
14import qualified Data.Text as T
23import qualified Data.Text as T
15import Network.HTTP.Media (MediaType)
24import Network.HTTP.Media (MediaType)
16โˆ’import OpenAPI.Checker.Behavior
17โˆ’import OpenAPI.Checker.References
18โˆ’import OpenAPI.Checker.Subtree
19โˆ’import OpenAPI.Checker.Validate.Header ()
20โˆ’import OpenAPI.Checker.Validate.Link ()
21โˆ’import OpenAPI.Checker.Validate.MediaTypeObject
22โˆ’import OpenAPI.Checker.Validate.Products
23โˆ’import OpenAPI.Checker.Validate.Schema ()
24โˆ’import OpenAPI.Checker.Validate.Sums
25import Text.Pandoc.Builder
25import Text.Pandoc.Builder
26
26
27tracedResponses :: Traced Responses -> IOHM.InsOrdHashMap HttpStatusCode (Traced (Referenced Response))
27tracedResponses :: Traced Responses -> IOHM.InsOrdHashMap HttpStatusCode (Traced (Referenced Response))
@@ -49,12 +49,12 @@ instance Subtree Responses where
49 -- one element
49 -- one element
50 checkSemanticCompatibility env beh prodCons = do
50 checkSemanticCompatibility env beh prodCons = do
51 let defs = getH @(ProdCons (Traced (Definitions Response))) env
51 let defs = getH @(ProdCons (Traced (Definitions Response))) env
52โˆ’ check code resps = checkCompatibility @Response env (beh >>> step (WithStatusCode code)) resps
52+ check code resps = checkCompatibility @Response (beh >>> step (WithStatusCode code)) env resps
53 elements = getEls <$> defs <*> prodCons
53 elements = getEls <$> defs <*> prodCons
54 getEls respDef resps = M.fromList $ do
54 getEls respDef resps = M.fromList $ do
55 (code, respRef) <- IOHM.toList $ tracedResponses resps
55 (code, respRef) <- IOHM.toList $ tracedResponses resps
56 pure (code, dereference respDef respRef)
56 pure (code, dereference respDef respRef)
57โˆ’ checkSums beh ResponseCodeNotFound check elements
57+ checkSums beh ConsumerDoesntHaveResponseCode check elements
58
58
59tracedContent :: Traced Response -> IOHM.InsOrdHashMap MediaType (Traced MediaTypeObject)
59tracedContent :: Traced Response -> IOHM.InsOrdHashMap MediaType (Traced MediaTypeObject)
60tracedContent resp =
60tracedContent resp =
@@ -68,17 +68,18 @@ tracedHeaders resp =
68
68
69instance Issuable 'ResponseLevel where
69instance Issuable 'ResponseLevel where
70 data Issue 'ResponseLevel
70 data Issue 'ResponseLevel
71โˆ’ = ResponseMediaTypeMissing MediaType
71+ = ConsumerDoesntHaveMediaType MediaType
72โˆ’ | ResponseHeaderMissing HeaderName
72+ | ProducerDoesntHaveResponseHeader HeaderName
73 deriving stock (Eq, Ord, Show)
73 deriving stock (Eq, Ord, Show)
74โˆ’ issueIsUnsupported _ = False
74+ issueKind = \case
75+ _ -> CertainIssue
75โˆ’ describeIssue Forward (ResponseMediaTypeMissing t) =
76+ describeIssue Forward (ConsumerDoesntHaveMediaType t) =
76 para $ "Media type was removed: " <> (code . T.pack . show $ t) <> "."
77 para $ "Media type was removed: " <> (code . T.pack . show $ t) <> "."
77โˆ’ describeIssue Backward (ResponseMediaTypeMissing t) =
78+ describeIssue Backward (ConsumerDoesntHaveMediaType t) =
78โˆ’ para $ "New media type was added: " <> (code . T.pack . show $ t) <> "."
79+ para $ "Media type was added: " <> (code . T.pack . show $ t) <> "."
79โˆ’ describeIssue Forward (ResponseHeaderMissing h) =
80+ describeIssue Forward (ProducerDoesntHaveResponseHeader h) =
80 para $ "New header was added " <> code h <> "."
81 para $ "New header was added " <> code h <> "."
81โˆ’ describeIssue Backward (ResponseHeaderMissing h) =
82+ describeIssue Backward (ProducerDoesntHaveResponseHeader h) =
82 para $ "Header was removed " <> code h <> "."
83 para $ "Header was removed " <> code h <> "."
83
84
84instance Behavable 'ResponseLevel 'PayloadLevel where
85instance Behavable 'ResponseLevel 'PayloadLevel where
@@ -86,14 +87,14 @@ instance Behavable 'ResponseLevel 'PayloadLevel where
86 = ResponsePayload
87 = ResponsePayload
87 deriving stock (Eq, Ord, Show)
88 deriving stock (Eq, Ord, Show)
88
89
89โˆ’ describeBehaviour ResponsePayload = "Payload"
90+ describeBehavior ResponsePayload = "Payload"
90
91
91instance Behavable 'ResponseLevel 'HeaderLevel where
92instance Behavable 'ResponseLevel 'HeaderLevel where
92 data Behave 'ResponseLevel 'HeaderLevel
93 data Behave 'ResponseLevel 'HeaderLevel
93 = InHeader HeaderName
94 = InHeader HeaderName
94 deriving stock (Eq, Ord, Show)
95 deriving stock (Eq, Ord, Show)
95
96
96โˆ’ describeBehaviour (InHeader name) = "Header " <> code name
97+ describeBehavior (InHeader name) = "Header " <> code name
97
98
98instance Subtree Response where
99instance Subtree Response where
99 type SubtreeLevel Response = 'ResponseLevel
100 type SubtreeLevel Response = 'ResponseLevel
@@ -117,15 +118,15 @@ instance Subtree Response where
117 checkMediaTypes = do
118 checkMediaTypes = do
118 -- Media types are sum-like entity
119 -- Media types are sum-like entity
119 let check mediaType mtObj =
120 let check mediaType mtObj =
120โˆ’ let mtEnv = HCons mediaType $ env
121+ let mtEnv = HCons mediaType env
121โˆ’ in checkCompatibility @MediaTypeObject mtEnv (beh >>> step ResponsePayload) mtObj
122+ in checkCompatibility @MediaTypeObject (beh >>> step ResponsePayload) mtEnv mtObj
122 elements = getEls <$> prodCons
123 elements = getEls <$> prodCons
123 getEls resp = M.fromList . IOHM.toList $ tracedContent resp
124 getEls resp = M.fromList . IOHM.toList $ tracedContent resp
124โˆ’ checkSums beh ResponseMediaTypeMissing check elements
125+ checkSums beh ConsumerDoesntHaveMediaType check elements
125
126
126 checkHeaders = do
127 checkHeaders = do
127 -- Headers are product-like entities
128 -- Headers are product-like entities
128โˆ’ let check name hdrs = checkCompatibility @Header env (beh >>> step (InHeader name)) hdrs
129+ let check name hdrs = checkCompatibility @Header (beh >>> step (InHeader name)) env hdrs
129 elements = getEls <$> headerDefs <*> prodCons
130 elements = getEls <$> headerDefs <*> prodCons
130 getEls headerDef resp = M.fromList $ do
131 getEls headerDef resp = M.fromList $ do
131 (hname, headerRef) <- IOHM.toList $ tracedHeaders resp
132 (hname, headerRef) <- IOHM.toList $ tracedHeaders resp
@@ -137,7 +138,7 @@ instance Subtree Response where
137 , required = fromMaybe False . _headerRequired . extract $ header
138 , required = fromMaybe False . _headerRequired . extract $ header
138 }
139 }
139 )
140 )
140โˆ’ checkProducts beh ResponseHeaderMissing check elements
141+ checkProducts beh ProducerDoesntHaveResponseHeader check elements
141 headerDefs = getH @(ProdCons (Traced (Definitions Header))) env
142 headerDefs = getH @(ProdCons (Traced (Definitions Header))) env
142
143
143instance Steppable Responses (Referenced Response) where
144instance Steppable Responses (Referenced Response) where
src/Data/OpenApi/Compare/Validate/Schema.hsnew file+398
@@ -0,0 +1,398 @@
1+{-# OPTIONS_GHC -Wno-orphans #-}
2+
3+module Data.OpenApi.Compare.Validate.Schema
4+ (
5+ )
6+where
7+
8+import Control.Monad.Writer
9+import qualified Data.Aeson as A
10+import Data.Coerce
11+import Data.Foldable (for_, toList)
12+import Data.Functor
13+import Data.HList
14+import Data.List (genericIndex, genericLength, group)
15+import qualified Data.List.NonEmpty as NE
16+import qualified Data.Map as M
17+import Data.Maybe
18+import Data.OpenApi
19+import Data.OpenApi.Compare.Behavior
20+import Data.OpenApi.Compare.Paths
21+import qualified Data.OpenApi.Compare.PathsPrefixTree as P
22+import Data.OpenApi.Compare.Subtree
23+import Data.OpenApi.Compare.Validate.Schema.DNF
24+import Data.OpenApi.Compare.Validate.Schema.Issues
25+import Data.OpenApi.Compare.Validate.Schema.JsonFormula
26+import Data.OpenApi.Compare.Validate.Schema.Partition
27+import Data.OpenApi.Compare.Validate.Schema.Process
28+import Data.OpenApi.Compare.Validate.Schema.Traced
29+import Data.OpenApi.Compare.Validate.Schema.TypedJson
30+import Data.Ord
31+import Data.Ratio
32+import Data.Semigroup
33+import qualified Data.Set as S
34+import Data.Text (Text)
35+
36+checkFormulas ::
37+ (ReassembleHList xs (CheckEnv (Referenced Schema))) =>
38+ HList xs ->
39+ Behavior 'SchemaLevel ->
40+ ProdCons (Trace Schema) ->
41+ ProdCons (Traced (Definitions Schema)) ->
42+ ProdCons (ForeachType JsonFormula, P.PathsPrefixTree Behave AnIssue 'SchemaLevel) ->
43+ SemanticCompatFormula ()
44+checkFormulas env beh trs defs (ProdCons (fp, ep) (fc, ec)) =
45+ case P.toList ep ++ P.toList ec of
46+ issues@(_ : _) -> for_ issues $ embedFormula beh . anItem
47+ [] -> do
48+ -- We have the following isomorphisms:
49+ -- (A โŠ‚ X โˆฉ Y) = (A โŠ‚ X) /\ (A โŠ‚ Y)
50+ -- (A โŠ‚ โŠค) = 1
51+ -- (X โˆช Y โŠ‚ B) = (X โŠ‚ B) /\ (Y โŠ‚ B)
52+ -- (โˆ… โŠ‚ B) = 1
53+ -- The remaining cases are, notably, not isomorphisms:
54+ -- 1) (A โŠ‚ X โˆช Y) <= (A โŠ‚ X) \/ (A โŠ‚ Y)
55+ -- 2) (A โŠ‚ โˆ…) <= 0
56+ -- 3) (X โˆฉ Y โŠ‚ B) <= (X โŠ‚ B) \/ (Y โŠ‚ B)
57+ -- 4) (โŠค โŠ‚ B) <= 0
58+ -- Therefore we have the implications with (โˆƒ and โˆ€ being the N-ary
59+ -- versions of \/ and /\ respectively):
60+ -- (โ‹ƒ_i โ‹‚_j A[i,j]) โŠ‚ (โ‹ƒ_k โ‹‚_l B[k,l])
61+ -- <= โˆƒk โˆ€l โˆ€i, (โ‹‚_j A[i,j]) โŠ‚ B[k,l]
62+ -- = โˆ€i โˆƒk โˆ€l, (โ‹‚_j A[i,j]) โŠ‚ B[k,l]
63+ -- with the caveat that the the set over which k ranges is nonempty.
64+ -- (because 2) is not an isomorphism), and that this is a sufficient
65+ -- but not necessary condition (because 1) is not an isomorphism).
66+ -- Our disjunction loses information, so it makes sense to nest it as
67+ -- deeply as possible, hence we choose the latter representation.
68+ --
69+ -- We delegate the verification of (โ‹‚_j A[j]) โŠ‚ B to a separate heuristic
70+ -- function, with the understanding that โˆƒj, A[j] โŠ‚ B is a sufficient,
71+ -- but not necessary condition (because of 3) and 4)).
72+ --
73+ -- If k ranges over an empty set, we have the isomorphism:
74+ -- (โ‹ƒ_i โ‹‚_j A[i,j]) โŠ‚ โˆ… = โˆ€i, (โ‹‚_j A[i,j]) โŠ‚ โˆ…
75+ -- where we again delegate (โ‹‚_j A[j]) โŠ‚ โˆ… to a heuristic, though here the
76+ -- shortcut of โˆƒj, A[j] โŠ‚ โˆ… hardly helps.
77+ --
78+ -- Disjunctions tend to erase informative error messages, so we may want
79+ -- to avoid them. This can be formally done as follows: if we can
80+ -- partition the universal set into a disjoint union of some parts:
81+ -- โŠค = โŠ”_ฮฑ P[ฮฑ]
82+ -- such that the conjuncts in our disjunctive normal form are subordinate
83+ -- to the partition:
84+ -- โˆ€i โˆƒฮฑ, (โ‹‚_j A[i,j]) โŠ‚ P[ฮฑ]
85+ -- โˆ€k โˆƒฮฑ, (โ‹‚_l B[k,l]) โŠ‚ P[ฮฑ]
86+ -- then we can partition the sets over which i and k range into partitions
87+ -- I[ฮฑ] and K[ฮฑ], and then in each "bucket" verify the inclusion in the
88+ -- aforementioned way:
89+ -- โˆ€ฮฑ, (โ‹ƒ_iโˆˆI[ฮฑ] โ‹‚_j A[i,j]) โŠ‚ (โ‹ƒ_kโˆˆK[ฮฑ] โ‹‚_l B[k,l])
90+ -- = โˆ€ฮฑ โˆ€iโˆˆI[ฮฑ] โˆƒkโˆˆK[ฮฑ] โˆ€l, (โ‹‚_j A[i,j]) โŠ‚ B[k,l]
91+ -- We already somewhat do this by partitioning JSON into types, but we can
92+ -- additionally partition e.g. "enum" fields or existence of particular
93+ -- properties. This works especially well if we manage to ensure K[ฮฑ] are
94+ -- 1-element sets.
95+ --
96+ -- Since the set:
97+ -- (โ‹ƒ_iโˆˆI[ฮฑ] โ‹‚_j A[i,j]) = (โ‹ƒ_i โ‹‚_j A[i,j]) โˆฉ P[ฮฑ]
98+ -- does not actually appear in the source schema, we need to construct it
99+ -- ourselves and come up with a name for it.
100+ let typesRestricted = not (anyBottomTypes fp) && anyBottomTypes fc
101+ -- Specifically handle the case when a schema's type has been
102+ -- restricted from "all" to specific types: if all types were allowed
103+ -- in the producer and not all types are allowed in the consumer, it's
104+ -- usually easier to say what's left than what's removed
105+ when typesRestricted $ issueAt beh $ TypesRestricted $ nonBottomTypes fc
106+ forType_ $ \tyName ty -> do
107+ let beh' = beh >>> step (OfType tyName)
108+ case (getJsonFormula $ ty fp, getJsonFormula $ ty fc) of
109+ (DNF pss, BottomDNF) -> unless typesRestricted $ do
110+ -- don't repeat the TypesRestricted issue
111+ for_ pss $ \(Disjunct ps) -> checkContradiction beh' Nothing ps
112+ (DNF pss, SingleDisjunct (Disjunct cs)) -> for_ pss $ \(Disjunct ps) -> do
113+ for_ cs $ checkImplication env beh' trs ps -- avoid disjunction if there's only one conjunct
114+ (TopDNF, DNF css) ->
115+ -- producer is "open" (allows any value), but consumer has restrictions.
116+ -- In this case we want to show which restrictions were added. (instead
117+ -- of showing an empty list restrictions that couldn't be satisfied.)
118+ for_ css $ \(Disjunct cs) -> for_ cs $ checkImplication env beh' trs S.empty
119+ (pss', css') -> for_ (tryPartition defs $ ProdCons (JsonFormula pss') (JsonFormula css')) $ \case
120+ (mPart, ProdCons pf cf) -> do
121+ let beh'' = foldr ((<<<) . step . InPartition) beh' mPart
122+ case (getJsonFormula pf, getJsonFormula cf) of
123+ (DNF pss, BottomDNF) -> for_ pss $ \(Disjunct ps) -> checkContradiction beh' mPart ps
124+ (DNF pss, SingleDisjunct (Disjunct cs)) -> for_ pss $ \(Disjunct ps) -> do
125+ for_ cs $ checkImplication env beh'' trs ps
126+ -- unlucky:
127+ (DNF pss, DNF css) -> for_ pss $ \(Disjunct ps) -> do
128+ anyOfAt
129+ beh'
130+ (issueFromDisjunct Nothing ps)
131+ [for_ cs $ checkImplication env beh' trs ps | Disjunct cs <- S.toList css]
132+ pure ()
133+ where
134+ anyBottomTypes f = getAny $
135+ foldType $ \_ ty -> case getJsonFormula $ ty f of
136+ BottomDNF -> Any True
137+ _ -> mempty
138+ nonBottomTypes f = foldType $ \tyName ty -> case getJsonFormula $ ty f of
139+ BottomDNF -> mempty
140+ _ -> [tyName]
141+ issueFromDisjunct :: Typeable t => Maybe Partition -> S.Set (Condition t) -> Issue 'TypedSchemaLevel
142+ issueFromDisjunct _ ps
143+ | Just e <- findExactly ps
144+ , all (satisfiesTyped e) ps =
145+ EnumDoesntSatisfy $ untypeValue e -- what does this look like when partitioned?
146+ issueFromDisjunct mPart ps = NoMatchingCondition mPart $ SomeCondition <$> S.toList ps
147+
148+checkContradiction ::
149+ Behavior 'TypedSchemaLevel ->
150+ Maybe Partition ->
151+ S.Set (Condition t) ->
152+ SemanticCompatFormula ()
153+checkContradiction beh mPart _ = issueAt beh $ maybe TypeBecomesEmpty PartitionBecomesEmpty mPart -- TODO #70
154+
155+checkImplication ::
156+ (ReassembleHList xs (CheckEnv (Referenced Schema))) =>
157+ HList xs ->
158+ Behavior 'TypedSchemaLevel ->
159+ ProdCons (Trace Schema) -> -- the traces of the root schemas used in this comparison
160+ S.Set (Condition t) ->
161+ Condition t ->
162+ SemanticCompatFormula ()
163+checkImplication env beh trs prods cons = case findExactly prods of
164+ Just e
165+ | all (satisfiesTyped e) prods ->
166+ if satisfiesTyped e cons
167+ then pure ()
168+ else issueAt beh (EnumDoesntSatisfy $ untypeValue e)
169+ | otherwise -> pure () -- vacuously true
170+ Nothing -> case cons of
171+ -- the above code didn't catch it, so there's no Exactly condition on the lhs
172+ Exactly e -> issueAt beh (NoMatchingEnum $ untypeValue e)
173+ Maximum m -> foldCheck min m NoMatchingMaximum MatchingMaximumWeak $ \case
174+ Maximum m' -> Just m'
175+ _ -> Nothing
176+ Minimum m -> foldCheck max m (NoMatchingMinimum . coerce) (MatchingMinimumWeak . coerce) $ \case
177+ Minimum m' -> Just m'
178+ _ -> Nothing
179+ MultipleOf m -> foldCheck lcmScientific m NoMatchingMultipleOf MatchingMultipleOfWeak $ \case
180+ MultipleOf m' -> Just m'
181+ _ -> Nothing
182+ NumberFormat f -> case flip any prods $ \case
183+ NumberFormat f' -> f == f'
184+ _ -> False of
185+ True -> pure ()
186+ False -> issueAt beh (NoMatchingFormat f)
187+ MaxLength m -> foldCheck min m NoMatchingMaxLength MatchingMaxLengthWeak $ \case
188+ MaxLength m' -> Just m'
189+ _ -> Nothing
190+ MinLength m -> foldCheck max m NoMatchingMinLength MatchingMinLengthWeak $ \case
191+ MinLength m' -> Just m'
192+ _ -> Nothing
193+ Pattern p -> case flip any prods $ \case
194+ Pattern p' -> p == p'
195+ _ -> False of
196+ True -> pure ()
197+ False -> issueAt beh (NoMatchingPattern p) -- TODO: regex comparison #32
198+ StringFormat f -> case flip any prods $ \case
199+ StringFormat f' -> f == f'
200+ _ -> False of
201+ True -> pure ()
202+ False -> issueAt beh (NoMatchingFormat f)
203+ Items _ cons' -> case foldSome (<>) prods $ \case
204+ Items _ rs -> Just (Just (rs NE.:| []), mempty)
205+ TupleItems (map snd -> fs) -> Just (mempty, Just (fs NE.:| []))
206+ _ -> Nothing of
207+ Just (mItems, Just pfs)
208+ | not $ allSame (length <$> pfs) -> pure () -- vacuously
209+ | let plen = genericLength (NE.head pfs) ->
210+ clarifyIssue (AnItem beh (anIssue TupleToArray)) $
211+ for_ [0 .. plen - 1] $ \i -> do
212+ let prod' = tracedConjunct $ case mItems of
213+ Just prods' -> ((`genericIndex` i) <$> pfs) <> prods'
214+ Nothing -> (`genericIndex` i) <$> pfs
215+ checkCompatibility (beh >>> step (InItem i)) env $ ProdCons prod' cons'
216+ Just (Just prods', Nothing) -> do
217+ let prod' = tracedConjunct prods'
218+ checkCompatibility (beh >>> step InItems) env $ ProdCons prod' cons'
219+ _ -> clarifyIssue (AnItem beh (anIssue NoMatchingItems)) $ do
220+ checkCompatibility (beh >>> step InItems) env $ ProdCons prodTopSchema cons'
221+ TupleItems (map snd -> fs) -> case foldSome (<>) prods $ \case
222+ TupleItems (map snd -> fs') -> Just (Just $ fs' NE.:| [], Just . Max $ genericLength fs', Just . Min $ genericLength fs', mempty)
223+ MinItems m' -> Just (mempty, Just . Max $ m', mempty, mempty)
224+ MaxItems m' -> Just (mempty, mempty, Just . Min $ m', mempty)
225+ Items _ rs -> Just (mempty, mempty, mempty, Just (rs NE.:| []))
226+ _ -> Nothing of
227+ -- if the length constraints in the producer are contradictory:
228+ Just (_, Just (Max lowest), Just (Min highest), _) | lowest > highest -> pure ()
229+ -- We have an explicit tuple items clause...
230+ Just (Just pfs, Just (Max plen), _, _)
231+ | plen /= genericLength fs -> -- ...of wrong length
232+ issueAt beh (TupleItemsLengthChanged ProdCons {producer = plen, consumer = genericLength fs})
233+ | otherwise ->
234+ for_ [0 .. plen - 1] $ \i -> do
235+ checkCompatibility (beh >>> step (InItem i)) env $ ProdCons (tracedConjunct $ (`genericIndex` i) <$> pfs) (fs `genericIndex` i)
236+ -- We have a fixed length array in the producer...
237+ Just (Nothing, Just (Max plen), Just (Min plen'), mProd)
238+ | plen == plen' ->
239+ clarifyIssue (AnItem beh (anIssue ArrayToTuple)) $ case mProd of
240+ _
241+ | plen /= genericLength fs -> -- ...of wrong length
242+ issueAt beh (TupleItemsLengthChanged ProdCons {producer = plen, consumer = genericLength fs})
243+ Just rs -> for_ [0 .. plen - 1] $ \i -> do
244+ checkCompatibility (beh >>> step (InItem i)) env $ ProdCons (tracedConjunct rs) (fs `genericIndex` i)
245+ -- ...and no "items" schema
246+ Nothing -> clarifyIssue (AnItem beh (anIssue NoMatchingTupleItems)) $ do
247+ for_ [0 .. plen - 1] $ \i -> do
248+ checkCompatibility (beh >>> step (InItem i)) env $ ProdCons prodTopSchema (fs `genericIndex` i)
249+ _ -> issueAt beh NoMatchingTupleItems
250+ MaxItems m -> foldCheck min m NoMatchingMaxItems MatchingMaxItemsWeak $ \case
251+ MaxItems m' -> Just m'
252+ TupleItems fs -> Just $ toInteger $ length fs
253+ _ -> Nothing
254+ MinItems m -> foldCheck max m NoMatchingMinItems MatchingMinItemsWeak $ \case
255+ MinItems m' -> Just m'
256+ TupleItems fs -> Just $ toInteger $ length fs
257+ _ -> Nothing
258+ UniqueItems -> case flip any prods $ \case
259+ UniqueItems -> True
260+ MaxItems 1 -> True
261+ TupleItems fs | length fs == 1 -> True
262+ _ -> False of
263+ True -> pure ()
264+ False -> issueAt beh NoMatchingUniqueItems
265+ Properties props _ madd -> case foldSome (<>) prods $ \case
266+ Properties props' _ madd' -> Just $ (props', madd') NE.:| []
267+ _ -> Nothing of
268+ Just pm ->
269+ anyOfAt beh NoMatchingProperties $ -- TODO: could first "concat" the lists
270+ NE.toList pm <&> \(props', madd') -> do
271+ for_ (S.fromList $ M.keys props <> M.keys props') $ \k -> do
272+ let beh' = beh >>> step (InProperty k)
273+ go sch sch' = checkCompatibility beh' env (ProdCons sch sch')
274+ case (maybe False propRequired $ M.lookup k props', maybe False propRequired $ M.lookup k props) of
275+ -- producer does not require field, but consumer does (can fail)
276+ (False, True) -> issueAt beh' PropertyNowRequired
277+ _ -> pure ()
278+ case (M.lookup k props', madd', M.lookup k props, madd) of
279+ -- (producer, additional producer, consumer, additional consumer)
280+ (Nothing, Nothing, _, _) -> pure () -- vacuously: the producer asserts that this field cannot exist,
281+ -- and the consumer either doesn't require it, or it does and we've already raised an error about it.
282+ (_, _, Nothing, Nothing) -> issueAt beh' UnexpectedProperty
283+ (Just p', _, Just p, _) -> go (propRefSchema p') (propRefSchema p)
284+ (Nothing, Just add', Just p, _) ->
285+ clarifyIssue (AnItem beh' (anIssue AdditionalToProperty)) $
286+ go add' (propRefSchema p)
287+ (Just p', _, Nothing, Just add) ->
288+ clarifyIssue (AnItem beh' (anIssue PropertyToAdditional)) $
289+ go (propRefSchema p') add
290+ (Nothing, Just _, Nothing, Just _) -> pure ()
291+ pure ()
292+ case (madd', madd) of
293+ (Nothing, _) -> pure () -- vacuously
294+ (_, Nothing) -> issueAt beh NoAdditionalProperties
295+ (Just add', Just add) -> checkCompatibility (beh >>> step InAdditionalProperty) env (ProdCons add' add)
296+ pure ()
297+ Nothing -> issueAt beh NoMatchingProperties
298+ MaxProperties m -> foldCheck min m NoMatchingMaxProperties MatchingMaxPropertiesWeak $ \case
299+ MaxProperties m' -> Just m'
300+ _ -> Nothing
301+ MinProperties m -> foldCheck max m NoMatchingMinProperties MatchingMinPropertiesWeak $ \case
302+ MinProperties m' -> Just m'
303+ _ -> Nothing
304+ where
305+ lcmScientific (toRational -> a) (toRational -> b) =
306+ fromRational $ lcm (numerator a) (numerator b) % gcd (denominator a) (denominator b)
307+
308+ foldCheck ::
309+ Eq a =>
310+ (a -> a -> a) ->
311+ a ->
312+ (a -> Issue 'TypedSchemaLevel) ->
313+ (ProdCons a -> Issue 'TypedSchemaLevel) ->
314+ (forall t. Condition t -> Maybe a) ->
315+ SemanticCompatFormula ()
316+ foldCheck f m missing weak extr = case foldSome f prods extr of
317+ Just m'
318+ | f m' m == m' -> pure ()
319+ | otherwise -> issueAt beh (weak ProdCons {producer = m', consumer = m})
320+ Nothing -> issueAt beh (missing m)
321+
322+ prodTopSchema = traced (producer trs >>> step ImplicitTopSchema) $ Inline mempty
323+
324+allSame :: (Foldable f, Eq a) => f a -> Bool
325+allSame xs = case group (toList xs) of
326+ [] -> True
327+ [_] -> True
328+ _ -> False
329+
330+foldSome :: (b -> b -> b) -> S.Set a -> (a -> Maybe b) -> Maybe b
331+foldSome combine xs extr =
332+ fmap (foldr1 combine) . NE.nonEmpty . mapMaybe extr . S.toList $ xs
333+
334+findExactly :: S.Set (Condition t) -> Maybe (TypedValue t)
335+findExactly xs = foldSome const xs $ \case
336+ Exactly x -> Just x
337+ _ -> Nothing
338+
339+instance Subtree Schema where
340+ type SubtreeLevel Schema = 'SchemaLevel
341+ type CheckEnv Schema = '[ProdCons (Traced (Definitions Schema))]
342+ checkStructuralCompatibility env pc = do
343+ structuralEq $ fmap _schemaRequired <$> pc
344+ structuralEq $ fmap _schemaNullable <$> pc
345+ structuralMaybeWith (structuralList env) $ tracedAllOf <$> pc
346+ structuralMaybeWith (structuralList env) $ tracedOneOf <$> pc
347+ structuralMaybe env $ sequence . stepTraced NotStep . fmap _schemaNot <$> pc
348+ structuralMaybeWith (structuralList env) $ tracedAnyOf <$> pc
349+ iohmStructural env $ stepTraced PropertiesStep . fmap _schemaProperties <$> pc
350+ structuralMaybeWith structuralAdditionalProperties $ tracedAdditionalProperties <$> pc
351+ structuralMaybeWith structuralDiscriminator $ tracedDiscriminator <$> pc
352+ structuralEq $ fmap _schemaReadOnly <$> pc
353+ structuralEq $ fmap _schemaWriteOnly <$> pc
354+ structuralEq $ fmap _schemaXml <$> pc
355+ structuralEq $ fmap _schemaMaxProperties <$> pc
356+ structuralEq $ fmap _schemaMinProperties <$> pc
357+ structuralEq $ fmap _schemaDefault <$> pc
358+ structuralEq $ fmap _schemaType <$> pc
359+ structuralEq $ fmap _schemaFormat <$> pc
360+ structuralMaybeWith structuralItems $ tracedItems <$> pc
361+ structuralEq $ fmap _schemaMaximum <$> pc
362+ structuralEq $ fmap _schemaExclusiveMaximum <$> pc
363+ structuralEq $ fmap _schemaMinimum <$> pc
364+ structuralEq $ fmap _schemaExclusiveMinimum <$> pc
365+ structuralEq $ fmap _schemaMaxLength <$> pc
366+ structuralEq $ fmap _schemaMinLength <$> pc
367+ structuralEq $ fmap _schemaPattern <$> pc
368+ structuralEq $ fmap _schemaMaxItems <$> pc
369+ structuralEq $ fmap _schemaMinItems <$> pc
370+ structuralEq $ fmap _schemaUniqueItems <$> pc
371+ structuralEq $ fmap _schemaEnum <$> pc
372+ structuralEq $ fmap _schemaMultipleOf <$> pc
373+ pure ()
374+ where
375+ structuralAdditionalProperties
376+ (ProdCons (Left x) (Left y)) = unless (x == y) structuralIssue
377+ structuralAdditionalProperties
378+ (ProdCons (Right x) (Right y)) =
379+ checkSubstructure env $ ProdCons x y
380+ structuralAdditionalProperties _ = structuralIssue
381+ structuralDiscriminator pc' = do
382+ structuralEq $ fmap _discriminatorPropertyName <$> pc'
383+ iohmStructural env $
384+ stepTraced DiscriminatorMapping . fmap (fmap parseDiscriminatorValue . _discriminatorMapping) <$> pc'
385+ pure ()
386+ structuralItems (ProdCons (Left a) (Left b)) =
387+ checkSubstructure env $ ProdCons a b
388+ structuralItems (ProdCons (Right a) (Right b)) =
389+ structuralList env $ ProdCons a b
390+ structuralItems _ = structuralIssue
391+ checkSemanticCompatibility env beh schs = do
392+ let defs = getH env
393+ checkFormulas env beh (ask <$> schs) defs $ schemaToFormula <$> defs <*> schs
394+
395+parseDiscriminatorValue :: Text -> Referenced Schema
396+parseDiscriminatorValue v = case A.fromJSON @(Referenced Schema) $ A.object ["$ref" A..= v] of
397+ A.Success x -> x
398+ A.Error _ -> Ref $ Reference v
src/Data/OpenApi/Compare/Validate/Schema/DNF.hsnew file+101
@@ -0,0 +1,101 @@
1+module Data.OpenApi.Compare.Validate.Schema.DNF
2+ ( DNF (..),
3+ Disjunct (..),
4+ pattern SingleDisjunct,
5+ pattern TopDNF,
6+ pattern BottomDNF,
7+ pattern LiteralDNF,
8+ foldDNF,
9+ forDNF,
10+ )
11+where
12+
13+import Algebra.Lattice
14+import Control.Applicative
15+import Data.Foldable
16+import qualified Data.Set as S
17+
18+-- | A boolean formula (without "not") represented as a Disjunctive Normal Form:
19+-- the formula is a disjunction of a set of clauses, each of which is a
20+-- conjunction of a set of some elementary formulas.
21+-- Invariant: no two disjuncts imply eachother
22+newtype DNF a = DNF (S.Set (Disjunct a))
23+ deriving stock (Eq, Ord, Show)
24+
25+-- A disjunct is a thing that is to be disjuncted. Itself it is a conjunction of some literals.
26+newtype Disjunct a = Disjunct (S.Set a)
27+ deriving stock (Eq, Ord, Show)
28+
29+disjImplies :: Ord a => Disjunct a -> Disjunct a -> Bool
30+disjImplies (Disjunct xs) (Disjunct ys) = ys `S.isSubsetOf` xs
31+
32+disjConjunction :: Ord a => Disjunct a -> Disjunct a -> Disjunct a
33+disjConjunction (Disjunct xs) (Disjunct ys) = Disjunct $ xs `S.union` ys
34+
35+disjAdd :: Ord a => DNF a -> Disjunct a -> DNF a
36+disjAdd (DNF yss) xs
37+ | any (xs `disjImplies`) yss = DNF yss
38+ | otherwise = DNF $ S.insert xs $ S.filter (not . (`disjImplies` xs)) yss
39+
40+instance Ord a => Lattice (DNF a) where
41+ xss \/ DNF yss = S.foldl' disjAdd xss yss
42+ DNF xss /\ DNF yss =
43+ foldl' disjAdd bottom $
44+ liftA2 disjConjunction (S.toList xss) (S.toList yss)
45+
46+pattern BottomDNF :: DNF a
47+pattern BottomDNF <-
48+ DNF (S.null -> True)
49+ where
50+ BottomDNF = DNF S.empty
51+
52+isSingleton :: S.Set a -> Maybe a
53+isSingleton s
54+ | S.size s == 1 = S.lookupMin s
55+ | otherwise = Nothing
56+
57+pattern SingleDisjunct :: Ord a => Disjunct a -> DNF a
58+pattern SingleDisjunct xs <-
59+ DNF (isSingleton -> Just xs)
60+ where
61+ SingleDisjunct xs = DNF $ S.singleton xs
62+
63+pattern TopDNF :: DNF a
64+pattern TopDNF <-
65+ DNF (isSingleton -> Just (Disjunct (S.null -> True)))
66+ where
67+ TopDNF = DNF $ S.singleton $ Disjunct S.empty
68+
69+pattern LiteralDNF :: Ord a => a -> DNF a
70+pattern LiteralDNF x <-
71+ SingleDisjunct (Disjunct (isSingleton -> Just x))
72+ where
73+ LiteralDNF x = SingleDisjunct $ Disjunct $ S.singleton x
74+
75+instance Ord a => BoundedJoinSemiLattice (DNF a) where
76+ bottom = BottomDNF
77+
78+instance Ord a => BoundedMeetSemiLattice (DNF a) where
79+ top = TopDNF
80+
81+foldDisjunct :: BoundedMeetSemiLattice l => (a -> l) -> Disjunct a -> l
82+foldDisjunct f (Disjunct xs) = S.foldl' (\y l -> y /\ f l) top xs
83+
84+foldDNF :: BoundedLattice l => (a -> l) -> DNF a -> l
85+foldDNF f (DNF xss) = S.foldl' (\y xs -> y \/ foldDisjunct f xs) bottom xss
86+
87+newtype LiftA f a = LiftA {getLiftA :: f a}
88+ deriving newtype (Functor, Applicative)
89+
90+instance (Lattice a, Applicative f) => Lattice (LiftA f a) where
91+ (/\) = liftA2 (/\)
92+ (\/) = liftA2 (\/)
93+
94+instance (BoundedJoinSemiLattice a, Applicative f) => BoundedJoinSemiLattice (LiftA f a) where
95+ bottom = pure bottom
96+
97+instance (BoundedMeetSemiLattice a, Applicative f) => BoundedMeetSemiLattice (LiftA f a) where
98+ top = pure top
99+
100+forDNF :: (BoundedLattice l, Applicative f) => (a -> f l) -> DNF a -> f l
101+forDNF f = getLiftA . foldDNF (LiftA . f)
src/Data/OpenApi/Compare/Validate/Schema/Issues.hsnew file+321
@@ -0,0 +1,321 @@
1+{-# OPTIONS_GHC -Wno-orphans #-}
2+
3+module Data.OpenApi.Compare.Validate.Schema.Issues
4+ ( Issue (..),
5+ Behave (..),
6+ )
7+where
8+
9+import qualified Data.Aeson as A
10+import Data.OpenApi
11+import Data.OpenApi.Compare.Behavior
12+import Data.OpenApi.Compare.Subtree
13+import Data.OpenApi.Compare.Validate.Schema.JsonFormula
14+import Data.OpenApi.Compare.Validate.Schema.Partition
15+import Data.OpenApi.Compare.Validate.Schema.TypedJson
16+import Data.Scientific
17+import Data.Text (Text)
18+import qualified Data.Text as T
19+import Text.Pandoc.Builder hiding (Format, Null)
20+
21+instance Issuable 'TypedSchemaLevel where
22+ data Issue 'TypedSchemaLevel
23+ = -- | producer produces a specific value ($1), consumer has a condition that is not satisfied by said value
24+ EnumDoesntSatisfy A.Value
25+ | -- | consumer only expects a specific value which the producer does not produce.
26+ NoMatchingEnum A.Value
27+ | -- | consumer declares a maximum numeric value ($1), producer doesn't
28+ NoMatchingMaximum (Bound Scientific)
29+ | -- | consumer declares a maximum numeric value ($1), producer declares a weaker (higher) limit ($2)
30+ MatchingMaximumWeak (ProdCons (Bound Scientific))
31+ | -- | consumer declares a minimum numeric value, producer doesn't
32+ NoMatchingMinimum (Bound Scientific)
33+ | -- | consumer declares a minimum numeric value ($1), producer declares a weaker (lower) limit ($2)
34+ MatchingMinimumWeak (ProdCons (Bound Scientific))
35+ | -- | consumer declares that the numeric value must be a multiple of $1, producer doesn't
36+ NoMatchingMultipleOf Scientific
37+ | -- | consumer declares that the numeric value must be a multiple of $1, producer declares a weaker condition (multiple of $2)
38+ MatchingMultipleOfWeak (ProdCons Scientific)
39+ | -- | consumer declares a string/number format, producer declares none or a different format (TODO: improve via regex #32)
40+ NoMatchingFormat Format
41+ | -- | consumer declares a maximum length of the string ($1), producer doesn't.
42+ NoMatchingMaxLength Integer
43+ | -- | consumer declares a maximum length of the string ($1), producer declares a weaker (higher) limit ($2)
44+ MatchingMaxLengthWeak (ProdCons Integer)
45+ | -- | consumer declares a minimum length of the string ($1), producer doesn't.
46+ NoMatchingMinLength Integer
47+ | -- | consumer declares a minimum length of the string ($1), producer declares a weaker (lower) limit ($2)
48+ MatchingMinLengthWeak (ProdCons Integer)
49+ | -- | consumer declares the string value must match a regex ($1), producer doesn't declare or declares different regex (TODO: #32)
50+ NoMatchingPattern Pattern
51+ | -- | consumer declares the items of an array must satisfy some condition, producer doesn't
52+ NoMatchingItems
53+ | -- | producer and consumer declare that an array must be a tuple of a fixed length, but the lengths don't match
54+ TupleItemsLengthChanged (ProdCons Integer)
55+ | -- | consumer declares that the array is a tuple, but the producer doesn't, the length constraints match, but there were issues with the components
56+ ArrayToTuple
57+ | -- | producer declares that the array is a tuple, but the consumer doesn't, and there were issues with the components
58+ TupleToArray
59+ | -- | consumer declares that the array is a tuple, but the producer doesn't, and there aren't sufficient length constraints
60+ NoMatchingTupleItems
61+ | -- | consumer declares a maximum length of the array ($1), producer doesn't.
62+ NoMatchingMaxItems Integer
63+ | -- | consumer declares a maximum length of the array ($1), producer declares a weaker (higher) limit ($2)
64+ MatchingMaxItemsWeak (ProdCons Integer)
65+ | -- | consumer declares a minimum length of the array ($1), producer doesn't.
66+ NoMatchingMinItems Integer
67+ | -- | consumer declares a minimum length of the array ($1), producer declares a weaker (lower) limit ($2)
68+ MatchingMinItemsWeak (ProdCons Integer)
69+ | -- | consumer declares that items must be unique, producer doesn't
70+ NoMatchingUniqueItems
71+ | -- | consumer declares the properties of an object must satisfy some condition, producer doesn't
72+ NoMatchingProperties
73+ | -- | producer allows additional properties, consumer doesn't
74+ NoAdditionalProperties
75+ | -- | consumer declares a maximum number of properties in the object ($1), producer doesn't.
76+ NoMatchingMaxProperties Integer
77+ | -- | consumer declares a maximum number of properties in the object ($1), producer declares a weaker (higher) limit ($2)
78+ MatchingMaxPropertiesWeak (ProdCons Integer)
79+ | -- | consumer declares a minimum number of properties in the object ($1), producer doesn't.
80+ NoMatchingMinProperties Integer
81+ | -- | consumer declares a minimum number of properties in the object ($1), producer declares a weaker (lower) limit ($2)
82+ MatchingMinPropertiesWeak (ProdCons Integer)
83+ | -- | producer declares that the value must satisfy a disjunction of some conditions, but consumer's requirements couldn't be matched against any single one of them (TODO: split heuristic #71)
84+ NoMatchingCondition (Maybe Partition) [SomeCondition]
85+ | -- | consumer indicates that no values of this type are allowed, but we weren't able to conclude that in the producer (currently only immediate contradictions are checked, c.f. #70)
86+ TypeBecomesEmpty
87+ | -- | consumer indicates that no values in a particular partition are allowed, but we weren't able to conclude this in the producer
88+ PartitionBecomesEmpty Partition
89+ deriving stock (Eq, Ord, Show)
90+ issueKind = \case
91+ NoMatchingEnum _ -> ProbablyIssue
92+ MatchingMaximumWeak _ -> ProbablyIssue -- interplay with MultipleOf could make this not an issue
93+ MatchingMinimumWeak _ -> ProbablyIssue -- ditto
94+ MatchingMultipleOfWeak _ -> ProbablyIssue -- ditto
95+ NoMatchingFormat _ -> Unsupported
96+ NoMatchingPattern _ -> Unsupported
97+ ArrayToTuple -> Comment
98+ TupleToArray -> Comment
99+ NoMatchingProperties -> ProbablyIssue -- TODO: #109
100+ TypeBecomesEmpty -> ProbablyIssue -- TODO: #70
101+ PartitionBecomesEmpty _ -> ProbablyIssue -- ditto
102+ _ -> CertainIssue
103+ relatedIssues =
104+ (==) `withClass` \case
105+ EnumDoesntSatisfy v -> Just v
106+ NoMatchingEnum v -> Just v
107+ _ -> Nothing
108+ `withClass` \case
109+ NoMatchingMaximum _ -> Just ()
110+ MatchingMaximumWeak _ -> Just ()
111+ _ -> Nothing
112+ `withClass` \case
113+ NoMatchingMinimum _ -> Just ()
114+ MatchingMinimumWeak _ -> Just ()
115+ _ -> Nothing
116+ `withClass` \case
117+ NoMatchingMultipleOf _ -> Just ()
118+ MatchingMultipleOfWeak _ -> Just ()
119+ _ -> Nothing
120+ `withClass` \case
121+ NoMatchingMaxLength _ -> Just ()
122+ MatchingMaxLengthWeak _ -> Just ()
123+ _ -> Nothing
124+ `withClass` \case
125+ NoMatchingMinLength _ -> Just ()
126+ MatchingMinLengthWeak _ -> Just ()
127+ _ -> Nothing
128+ `withClass` \case
129+ NoMatchingItems -> Just ()
130+ ArrayToTuple -> Just ()
131+ TupleToArray -> Just ()
132+ NoMatchingTupleItems -> Just ()
133+ TupleItemsLengthChanged _ -> Just ()
134+ _ -> Nothing
135+ `withClass` \case
136+ NoMatchingMaxItems _ -> Just ()
137+ MatchingMaxItemsWeak _ -> Just ()
138+ _ -> Nothing
139+ `withClass` \case
140+ NoMatchingMinItems _ -> Just ()
141+ MatchingMinItemsWeak _ -> Just ()
142+ _ -> Nothing
143+ `withClass` \case
144+ NoMatchingMaxProperties _ -> Just ()
145+ MatchingMaxPropertiesWeak _ -> Just ()
146+ _ -> Nothing
147+ `withClass` \case
148+ NoMatchingMinProperties _ -> Just ()
149+ MatchingMinPropertiesWeak _ -> Just ()
150+ _ -> Nothing
151+ describeIssue Forward (EnumDoesntSatisfy v) = para "The following enum value was removed:" <> showJSONValue v
152+ describeIssue Backward (EnumDoesntSatisfy v) = para "The following enum value was added:" <> showJSONValue v
153+ describeIssue Forward (NoMatchingEnum v) = para "The following enum value has been added:" <> showJSONValue v
154+ describeIssue Backward (NoMatchingEnum v) = para "The following enum value has been removed:" <> showJSONValue v
155+ describeIssue Forward (NoMatchingMaximum b) = para $ "Upper bound has been added:" <> showBound b <> "."
156+ describeIssue Backward (NoMatchingMaximum b) = para $ "Upper bound has been removed:" <> showBound b <> "."
157+ describeIssue ori (MatchingMaximumWeak (orientProdCons ori -> ProdCons p c)) =
158+ para $ "Upper bound changed from " <> showBound p <> " to " <> showBound c <> "."
159+ describeIssue Forward (NoMatchingMinimum b) = para $ "Lower bound has been added: " <> showBound b <> "."
160+ describeIssue Backward (NoMatchingMinimum b) = para $ "Lower bound has been removed: " <> showBound b <> "."
161+ describeIssue ori (MatchingMinimumWeak (orientProdCons ori -> ProdCons p c)) =
162+ para $ "Lower bound changed from " <> showBound p <> " to " <> showBound c <> "."
163+ describeIssue Forward (NoMatchingMultipleOf n) = para $ "Value is now a multiple of " <> show' n <> "."
164+ describeIssue Backward (NoMatchingMultipleOf n) = para $ "Value is no longer a multiple of " <> show' n <> "."
165+ describeIssue ori (MatchingMultipleOfWeak (orientProdCons ori -> ProdCons p c)) =
166+ para $ "Value changed from being a multiple of " <> show' p <> " to being a multiple of " <> show' c <> "."
167+ describeIssue Forward (NoMatchingFormat f) = para $ "Format added: " <> code f <> "."
168+ describeIssue Backward (NoMatchingFormat f) = para $ "Format removed: " <> code f <> "."
169+ describeIssue Forward (NoMatchingMaxLength n) = para $ "Maximum length added: " <> show' n <> "."
170+ describeIssue Backward (NoMatchingMaxLength n) = para $ "Maximum length removed: " <> show' n <> "."
171+ describeIssue ori (MatchingMaxLengthWeak (orientProdCons ori -> ProdCons p c)) =
172+ para $ "Maximum length of the string changed from " <> show' p <> " to " <> show' c <> "."
173+ describeIssue Forward (NoMatchingMinLength n) = para $ "Minimum length of the string added: " <> show' n <> "."
174+ describeIssue Backward (NoMatchingMinLength n) = para $ "Minimum length of the string removed: " <> show' n <> "."
175+ describeIssue ori (MatchingMinLengthWeak (orientProdCons ori -> ProdCons p c)) =
176+ para $ "Minimum length of the string changed from " <> show' p <> " to " <> show' c <> "."
177+ describeIssue Forward (NoMatchingPattern p) = para "Pattern (regular expression) added: " <> codeBlock p
178+ describeIssue Backward (NoMatchingPattern p) = para "Pattern (regular expression) removed: " <> codeBlock p
179+ describeIssue Forward NoMatchingItems = para "Array item schema has been added."
180+ describeIssue Backward NoMatchingItems = para "Array item schema has been removed."
181+ describeIssue ori (TupleItemsLengthChanged (orientProdCons ori -> ProdCons p c)) =
182+ para $ "Tuple length changed from " <> show' p <> " to " <> show' c <> "."
183+ describeIssue Forward ArrayToTuple = para "The array is now explicitly defined as a tuple."
184+ describeIssue Backward ArrayToTuple = para "The array is no longer explicitly defined as a tuple."
185+ describeIssue Forward TupleToArray = para "The array is no longer explicitly defined as a tuple."
186+ describeIssue Backward TupleToArray = para "The array is now explicitly defined as a tuple."
187+ describeIssue Forward NoMatchingTupleItems = para "The array is now explicitly defined as a tuple."
188+ describeIssue Backward NoMatchingTupleItems = para "The array is no longer explicitly defined as a tuple."
189+ describeIssue Forward (NoMatchingMaxItems n) = para $ "Maximum length of the array has been added " <> show' n <> "."
190+ describeIssue Backward (NoMatchingMaxItems n) = para $ "Maximum length of the array has been removed " <> show' n <> "."
191+ describeIssue ori (MatchingMaxItemsWeak (orientProdCons ori -> ProdCons p c)) =
192+ para $ "Maximum length of the array changed from " <> show' p <> " to " <> show' c <> "."
193+ describeIssue Forward (NoMatchingMinItems n) = para $ "Minimum length of the array added: " <> show' n <> "."
194+ describeIssue Backward (NoMatchingMinItems n) = para $ "Minimum length of the array removed: " <> show' n <> "."
195+ describeIssue ori (MatchingMinItemsWeak (orientProdCons ori -> ProdCons p c)) =
196+ para $ "Minimum length of the array changed from " <> show' p <> " to " <> show' c <> "."
197+ describeIssue Forward NoMatchingUniqueItems = para "Items are now required to be unique."
198+ describeIssue Backward NoMatchingUniqueItems = para "Items are no longer required to be unique."
199+ describeIssue Forward NoMatchingProperties = para "Property added."
200+ describeIssue Backward NoMatchingProperties = para "Property removed."
201+ describeIssue Forward NoAdditionalProperties = para "Additional properties have been removed."
202+ describeIssue Backward NoAdditionalProperties = para "Additional properties have been added."
203+ describeIssue Forward (NoMatchingMaxProperties n) = para $ "Maximum number of properties has been added: " <> show' n <> "."
204+ describeIssue Backward (NoMatchingMaxProperties n) = para $ "Maximum number of properties has been removed: " <> show' n <> "."
205+ describeIssue ori (MatchingMaxPropertiesWeak (orientProdCons ori -> ProdCons p c)) =
206+ para $ "Maximum number of properties has changed from " <> show' p <> " to " <> show' c <> "."
207+ describeIssue Forward (NoMatchingMinProperties n) = para $ "Minimum number of properties added: " <> show' n <> "."
208+ describeIssue Backward (NoMatchingMinProperties n) = para $ "Minimum number of properties removed: " <> show' n <> "."
209+ describeIssue ori (MatchingMinPropertiesWeak (orientProdCons ori -> ProdCons p c)) =
210+ para $ "Minimum number of properties has changed from " <> show' p <> " to " <> show' c <> "."
211+ describeIssue _ (NoMatchingCondition mPart conds) =
212+ para
213+ ( case mPart of
214+ Nothing -> "Could not verify that the following conditions hold (please file a bug if you see this):"
215+ Just locPart ->
216+ "In cases where " <> showPartition locPart
217+ <> " โ€“ could not verify that the following conditions hold (please file a bug if you see this):"
218+ )
219+ <> bulletList ((\(SomeCondition c) -> showCondition c) <$> conds)
220+ describeIssue Forward TypeBecomesEmpty = para "The type has been removed."
221+ describeIssue Backward TypeBecomesEmpty = para "The type has been added."
222+ describeIssue Forward (PartitionBecomesEmpty part) = para $ "The case where " <> showPartition part <> " โ€“ has been removed."
223+ describeIssue Backward (PartitionBecomesEmpty part) = para $ "The case where " <> showPartition part <> " โ€“ has been added."
224+
225+show' :: Show x => x -> Inlines
226+show' = str . T.pack . show
227+
228+instance Issuable 'SchemaLevel where
229+ data Issue 'SchemaLevel
230+ = -- | Some (openapi-supported) feature that we do not support was encountered in the schema
231+ NotSupported Text
232+ | -- | We couldn't prove that the branches of a oneOf are disjoint, and we will treat it as an anyOf, meaning we don't check whether the overlaps are excluded in a compatible way
233+ OneOfNotDisjoint
234+ | -- | The schema is actually invalid
235+ InvalidSchema Text
236+ | -- | The schema contains a reference loop along "anyOf"/"allOf"/"oneOf".
237+ UnguardedRecursion
238+ | -- | Producer doesn't place any restrictions on the types, but the consumer does. List what types remain available in the consumer.
239+ TypesRestricted [JsonType]
240+ | -- | in the producer this field used to be handled as part of "additionalProperties", and the consumer this is a specific "properties" entry. Only thrown when this change actually causes other issues
241+ AdditionalToProperty
242+ | -- | in the consumer this field used to be handled as part of "additionalProperties", and the producer this is a specific "properties" entry. Only thrown when this change actually causes other issues
243+ PropertyToAdditional
244+ | -- | consumer requires a property that is not required/allowed in the producer
245+ PropertyNowRequired
246+ | -- | producer allows a property that is not allowed in the consumer
247+ UnexpectedProperty
248+ deriving stock (Eq, Ord, Show)
249+ issueKind = \case
250+ NotSupported _ -> Unsupported
251+ OneOfNotDisjoint -> Unsupported
252+ InvalidSchema _ -> SchemaInvalid
253+ UnguardedRecursion -> Unsupported
254+ AdditionalToProperty -> Comment
255+ PropertyToAdditional -> Comment
256+ TypesRestricted _ -> ProbablyIssue -- TODO: #70
257+ _ -> CertainIssue
258+ relatedIssues =
259+ (==) `withClass` \case
260+ AdditionalToProperty -> Just ()
261+ PropertyToAdditional -> Just ()
262+ _ -> Nothing
263+ `withClass` \case
264+ PropertyNowRequired -> Just ()
265+ UnexpectedProperty -> Just ()
266+ _ -> Nothing
267+ describeIssue _ (NotSupported i) =
268+ para (emph "Encountered a feature that CompaREST does not support: " <> text i <> ".")
269+ describeIssue _ OneOfNotDisjoint =
270+ para $
271+ "Could not deduce that " <> code "oneOf"
272+ <> " cases don't overlap. Treating the "
273+ <> code "oneOf"
274+ <> " as an "
275+ <> code "anyOf"
276+ <> ". Reported errors might not be accurate."
277+ describeIssue _ (InvalidSchema i) =
278+ para (emph "The schema is invalid: " <> text i <> ".")
279+ describeIssue _ UnguardedRecursion =
280+ para "Encountered recursion that is too complex for CompaREST to untangle."
281+ describeIssue Forward (TypesRestricted tys) = case tys of
282+ [] -> para "No longer has any valid values." -- weird
283+ _ -> para "Values are now limited to the following types: " <> bulletList (para . describeJSONType <$> tys)
284+ describeIssue Backward (TypesRestricted tys) = case tys of
285+ [] -> para "Any value of any type is now allowed." -- weird
286+ _ -> para "Values are no longer limited to the following types: " <> bulletList (para . describeJSONType <$> tys)
287+ describeIssue Forward AdditionalToProperty = para "The property was previously implicitly described by the catch-all \"additional properties\" case. It is now explicitly defined."
288+ describeIssue Backward AdditionalToProperty = para "The property was previously explicitly defined. It is now implicitly described by the catch-all \"additional properties\" case."
289+ describeIssue Forward PropertyToAdditional = para "The property was previously explicitly defined. It is now implicitly described by the catch-all \"additional properties\" case."
290+ describeIssue Backward PropertyToAdditional = para "The property was previously implicitly described by the catch-all \"additional properties\" case. It is now explicitly defined."
291+ describeIssue Forward PropertyNowRequired = para "The property has become required."
292+ describeIssue Backward PropertyNowRequired = para "The property may not be present."
293+ describeIssue Forward UnexpectedProperty = para "The property has been removed."
294+ describeIssue Backward UnexpectedProperty = para "The property has been added."
295+
296+instance Behavable 'SchemaLevel 'TypedSchemaLevel where
297+ data Behave 'SchemaLevel 'TypedSchemaLevel
298+ = OfType JsonType
299+ deriving stock (Eq, Ord, Show)
300+
301+ describeBehavior (OfType t) = describeJSONType t
302+
303+instance Behavable 'TypedSchemaLevel 'TypedSchemaLevel where
304+ data Behave 'TypedSchemaLevel 'TypedSchemaLevel
305+ = InPartition Partition
306+ deriving stock (Eq, Ord, Show)
307+
308+ describeBehavior (InPartition partition) = "In cases where " <> showPartition partition
309+
310+instance Behavable 'TypedSchemaLevel 'SchemaLevel where
311+ data Behave 'TypedSchemaLevel 'SchemaLevel
312+ = InItems
313+ | InItem Integer
314+ | InProperty Text
315+ | InAdditionalProperty
316+ deriving stock (Eq, Ord, Show)
317+
318+ describeBehavior InItems = "Items"
319+ describeBehavior (InItem i) = "Item " <> show' i
320+ describeBehavior (InProperty p) = "Property " <> code p
321+ describeBehavior InAdditionalProperty = "Additional properties"
src/Data/OpenApi/Compare/Validate/Schema/JsonFormula.hsnew file+236
@@ -0,0 +1,236 @@
1+module Data.OpenApi.Compare.Validate.Schema.JsonFormula
2+ ( Bound (..),
3+ showBound,
4+ Property (..),
5+ Condition (..),
6+ showCondition,
7+ satisfiesTyped,
8+ checkStringFormat,
9+ checkNumberFormat,
10+ SomeCondition (..),
11+ JsonFormula (..),
12+ satisfiesFormula,
13+ satisfies,
14+ showJSONValue,
15+ showJSONValueInline,
16+ )
17+where
18+
19+import Algebra.Lattice
20+import qualified Data.Aeson as A
21+import qualified Data.ByteString.Lazy as BSL
22+import qualified Data.Foldable as F
23+import Data.Functor
24+import qualified Data.HashMap.Strict as HM
25+import Data.Int
26+import Data.Kind
27+import qualified Data.Map as M
28+import Data.Maybe
29+import Data.OpenApi
30+import Data.OpenApi.Compare.Orphans ()
31+import Data.OpenApi.Compare.Subtree
32+import Data.OpenApi.Compare.Validate.Schema.DNF
33+import Data.OpenApi.Compare.Validate.Schema.TypedJson
34+import Data.Ord
35+import Data.Ratio
36+import Data.Scientific
37+import qualified Data.Set as S
38+import Data.Text (Text)
39+import qualified Data.Text as T
40+import qualified Data.Text.Encoding as T
41+import Data.Typeable
42+import Text.Pandoc.Builder hiding (Format, Null)
43+import Text.Regex.Pcre2
44+
45+data Bound a = Exclusive !a | Inclusive !a
46+ deriving stock (Eq, Show, Functor)
47+
48+-- | The order is lexicographical on @a * Bool@.
49+instance Ord a => Ord (Bound a) where
50+ Exclusive a `compare` Exclusive b = compare a b
51+ Exclusive a `compare` Inclusive b = if a <= b then LT else GT
52+ Inclusive a `compare` Exclusive b = if a < b then LT else GT
53+ Inclusive a `compare` Inclusive b = compare a b
54+
55+showBound :: Show a => Bound a -> Inlines
56+showBound (Inclusive x) = show' x <> " inclusive"
57+showBound (Exclusive x) = show' x <> " exclusive"
58+
59+data Property = Property
60+ { propRequired :: Bool
61+ , propFormula :: ForeachType JsonFormula
62+ , propRefSchema :: Traced (Referenced Schema)
63+ }
64+ deriving stock (Eq, Ord, Show)
65+
66+-- | A primitive structural condition for the "top level" of a JSON value (of a specific type)
67+data Condition :: JsonType -> Type where
68+ Exactly :: TypedValue t -> Condition t
69+ Maximum :: !(Bound Scientific) -> Condition 'Number
70+ Minimum ::
71+ !(Down (Bound (Down Scientific))) ->
72+ -- | this has the right Ord
73+ Condition 'Number
74+ MultipleOf :: !Scientific -> Condition 'Number
75+ NumberFormat :: !Format -> Condition 'Number
76+ MaxLength :: !Integer -> Condition 'String
77+ MinLength :: !Integer -> Condition 'String
78+ Pattern :: !Pattern -> Condition 'String
79+ StringFormat :: !Format -> Condition 'String
80+ Items ::
81+ !(ForeachType JsonFormula) ->
82+ !(Traced (Referenced Schema)) ->
83+ Condition 'Array
84+ TupleItems ::
85+ ![(ForeachType JsonFormula, Traced (Referenced Schema))] ->
86+ Condition 'Array
87+ MaxItems :: !Integer -> Condition 'Array
88+ MinItems :: !Integer -> Condition 'Array
89+ UniqueItems :: Condition 'Array
90+ Properties ::
91+ !(M.Map Text Property) ->
92+ -- | formula for additional properties
93+ !(ForeachType JsonFormula) ->
94+ -- | schema for additional properties, Nothing means bottom
95+ !(Maybe (Traced (Referenced Schema))) ->
96+ Condition 'Object
97+ MaxProperties :: !Integer -> Condition 'Object
98+ MinProperties :: !Integer -> Condition 'Object
99+
100+deriving stock instance Eq (Condition t)
101+
102+deriving stock instance Ord (Condition t)
103+
104+deriving stock instance Show (Condition t)
105+
106+showCondition :: Condition a -> Blocks
107+showCondition = \case
108+ (Exactly v) -> para "The value should be:" <> showJSONValue (untypeValue v)
109+ (Maximum b) -> para $ "The value should be less than " <> showBound b <> "."
110+ (Minimum (Down b)) -> para $ "The value should be more than " <> showBound (getDown <$> b) <> "."
111+ (MultipleOf n) -> para $ "The value should be a multiple of " <> show' n <> "."
112+ (NumberFormat p) -> para $ "The number should have the following format:" <> code p <> "."
113+ (Pattern p) -> para "The value should satisfy the following pattern (regular expression):" <> codeBlock p
114+ (StringFormat p) -> para $ "The string should have the following format:" <> code p <> "."
115+ (MaxLength p) -> para $ "The length of the string should be less than or equal to " <> show' p <> "."
116+ (MinLength p) -> para $ "The length of the string should be more than or equal to " <> show' p <> "."
117+ (Items i _) -> para "The items of the array should satisfy:" <> showForEachJsonFormula i
118+ (TupleItems is) -> para ("There should be " <> show' (length is) <> " items in the array:") <> bulletList (showForEachJsonFormula . fst <$> is)
119+ (MaxItems n) -> para $ "The length of the array should be less than or equal to " <> show' n <> "."
120+ (MinItems n) -> para $ "The length of the array should be more than or equal to " <> show' n <> "."
121+ UniqueItems -> para "The elements in the array should be unique."
122+ (Properties props additional _) ->
123+ bulletList $
124+ ( M.toList props
125+ <&> ( \(k, p) ->
126+ para (code k)
127+ <> para (strong $ if propRequired p then "Required" else "Optional")
128+ <> showForEachJsonFormula (propFormula p)
129+ )
130+ )
131+ <> [ para (emph "Additional properties")
132+ <> showForEachJsonFormula additional
133+ ]
134+ (MaxProperties n) -> para $ "The maximum number of fields should be " <> show' n <> "."
135+ (MinProperties n) -> para $ "The minimum number of fields should be " <> show' n <> "."
136+ where
137+ showForEachJsonFormula :: ForeachType JsonFormula -> Blocks
138+ showForEachJsonFormula i =
139+ bulletList $
140+ foldType
141+ ( \t f -> case getJsonFormula $ f i of
142+ BottomDNF -> mempty
143+ (DNF conds) ->
144+ [ para (describeJSONType t)
145+ <> bulletList
146+ ( S.toList conds <&> \case
147+ Disjunct (S.toList -> []) -> para "Empty"
148+ Disjunct (S.toList -> cond) -> bulletList (showCondition <$> cond)
149+ )
150+ ]
151+ )
152+
153+showJSONValue :: A.Value -> Blocks
154+showJSONValue v = codeBlockWith ("", ["json"], mempty) (T.decodeUtf8 . BSL.toStrict . A.encode $ v)
155+
156+showJSONValueInline :: A.Value -> Inlines
157+showJSONValueInline v = code (T.decodeUtf8 . BSL.toStrict . A.encode $ v)
158+
159+show' :: Show x => x -> Inlines
160+show' = str . T.pack . show
161+
162+satisfiesTyped :: TypedValue t -> Condition t -> Bool
163+satisfiesTyped e (Exactly e') = e == e'
164+satisfiesTyped (TNumber n) (Maximum (Exclusive m)) = n < m
165+satisfiesTyped (TNumber n) (Maximum (Inclusive m)) = n <= m
166+satisfiesTyped (TNumber n) (Minimum (Down (Exclusive (Down m)))) = n > m
167+satisfiesTyped (TNumber n) (Minimum (Down (Inclusive (Down m)))) = n >= m
168+satisfiesTyped (TNumber n) (MultipleOf m) = denominator (toRational n / toRational m) == 1 -- TODO: could be better #36
169+satisfiesTyped (TNumber n) (NumberFormat f) = checkNumberFormat f n
170+satisfiesTyped (TString s) (MaxLength m) = fromIntegral (T.length s) <= m
171+satisfiesTyped (TString s) (MinLength m) = fromIntegral (T.length s) >= m
172+satisfiesTyped (TString s) (Pattern p) = isJust $ match p s -- TODO: regex stuff #32
173+satisfiesTyped (TString s) (StringFormat f) = checkStringFormat f s
174+satisfiesTyped (TArray a) (Items f _) = all (`satisfies` f) a
175+satisfiesTyped (TArray a) (TupleItems fs) = length fs == F.length a && and (zipWith satisfies (F.toList a) (fst <$> fs))
176+satisfiesTyped (TArray a) (MaxItems m) = fromIntegral (F.length a) <= m
177+satisfiesTyped (TArray a) (MinItems m) = fromIntegral (F.length a) >= m
178+satisfiesTyped (TArray a) UniqueItems = S.size (S.fromList $ F.toList a) == F.length a -- TODO: could be better #36
179+satisfiesTyped (TObject o) (Properties props additional _) =
180+ all (`HM.member` o) (M.keys (M.filter propRequired props))
181+ && all (\(k, v) -> satisfies v $ maybe additional propFormula $ M.lookup k props) (HM.toList o)
182+satisfiesTyped (TObject o) (MaxProperties m) = fromIntegral (HM.size o) <= m
183+satisfiesTyped (TObject o) (MinProperties m) = fromIntegral (HM.size o) >= m
184+
185+checkNumberFormat :: Format -> Scientific -> Bool
186+checkNumberFormat "int32" (toRational -> n) =
187+ denominator n == 1
188+ && n >= toRational (minBound :: Int32)
189+ && n <= toRational (maxBound :: Int32)
190+checkNumberFormat "int64" (toRational -> n) =
191+ denominator n == 1
192+ && n >= toRational (minBound :: Int64)
193+ && n <= toRational (maxBound :: Int64)
194+checkNumberFormat "float" _n = True
195+checkNumberFormat "double" _n = True
196+checkNumberFormat f _n = error $ "Invalid number format: " <> T.unpack f
197+
198+checkStringFormat :: Format -> Text -> Bool
199+checkStringFormat "byte" _s = True -- TODO: regex stuff #32
200+checkStringFormat "binary" _s = True
201+checkStringFormat "date" _s = True
202+checkStringFormat "date-time" _s = True
203+checkStringFormat "password" _s = True
204+checkStringFormat "uuid" _s = True
205+checkStringFormat f _s = error $ "Invalid string format: " <> T.unpack f
206+
207+data SomeCondition where
208+ SomeCondition :: Typeable t => Condition t -> SomeCondition
209+
210+instance Eq SomeCondition where
211+ SomeCondition x == SomeCondition y = case cast x of
212+ Just x' -> x' == y
213+ Nothing -> False
214+
215+instance Ord SomeCondition where
216+ compare (SomeCondition x) (SomeCondition y) = case cast x of
217+ Just x' -> compare x' y
218+ Nothing -> compare (typeRep x) (typeRep y)
219+
220+deriving stock instance Show SomeCondition
221+
222+newtype JsonFormula t = JsonFormula {getJsonFormula :: DNF (Condition t)}
223+ deriving stock (Eq, Ord, Show)
224+ deriving newtype (Lattice, BoundedJoinSemiLattice, BoundedMeetSemiLattice)
225+
226+satisfiesFormula :: TypedValue t -> JsonFormula t -> Bool
227+satisfiesFormula val = foldDNF (satisfiesTyped val) . getJsonFormula
228+
229+satisfies :: A.Value -> ForeachType JsonFormula -> Bool
230+satisfies val p = case val of
231+ A.Null -> satisfiesFormula TNull $ forNull p
232+ A.Bool b -> satisfiesFormula (TBool b) $ forBoolean p
233+ A.Number n -> satisfiesFormula (TNumber n) $ forNumber p
234+ A.String s -> satisfiesFormula (TString s) $ forString p
235+ A.Array a -> satisfiesFormula (TArray a) $ forArray p
236+ A.Object o -> satisfiesFormula (TObject o) $ forObject p
src/Data/OpenApi/Compare/Validate/Schema/Partition.hsnew file+317
@@ -0,0 +1,317 @@
1+module Data.OpenApi.Compare.Validate.Schema.Partition
2+ ( partitionSchema,
3+ partitionRefSchema,
4+ selectPartition,
5+ runPartitionM,
6+ tryPartition,
7+ showPartition,
8+ intersectSchema,
9+ intersectRefSchema,
10+ IntersectionResult (..),
11+ runIntersectionM,
12+ Partition,
13+ )
14+where
15+
16+import Algebra.Lattice
17+import Algebra.Lattice.Lifted
18+import Control.Applicative
19+import Control.Monad.Reader hiding (ask)
20+import qualified Control.Monad.Reader as R
21+import Control.Monad.State
22+import qualified Control.Monad.Trans.Reader as R (liftCatch)
23+import qualified Control.Monad.Trans.Writer as W (liftCatch)
24+import Control.Monad.Writer
25+import qualified Data.Aeson as A
26+import Data.Foldable
27+import Data.Functor.Identity
28+import qualified Data.HashMap.Strict.InsOrd as IOHM
29+import Data.List (sortBy)
30+import qualified Data.List as L
31+import qualified Data.List.NonEmpty as NE
32+import qualified Data.Map as M
33+import Data.Maybe
34+import Data.OpenApi
35+import Data.OpenApi.Compare.Memo
36+import Data.OpenApi.Compare.References
37+import Data.OpenApi.Compare.Subtree
38+import Data.OpenApi.Compare.Validate.Schema.DNF
39+import Data.OpenApi.Compare.Validate.Schema.JsonFormula
40+import Data.OpenApi.Compare.Validate.Schema.Traced
41+import Data.OpenApi.Compare.Validate.Schema.TypedJson
42+import Data.Ord
43+import qualified Data.Set as S
44+import Data.Text (Text)
45+import qualified Data.Text as T
46+import Text.Pandoc.Builder hiding (Format, Null)
47+
48+data PartitionData
49+ = DByEnumValue (DNF (S.Set A.Value))
50+ | DByProperties (DNF (S.Set Text, S.Set Text)) -- optional, required
51+ deriving stock (Eq, Ord, Show)
52+
53+conjPart :: PartitionData -> PartitionData -> Maybe PartitionData
54+conjPart (DByEnumValue xss) (DByEnumValue yss) = Just . DByEnumValue $ xss /\ yss
55+conjPart (DByProperties xss) (DByProperties yss) = Just . DByProperties $ xss /\ yss
56+conjPart _ _ = Nothing
57+
58+disjPart :: PartitionData -> PartitionData -> Maybe PartitionData
59+disjPart (DByEnumValue xss) (DByEnumValue yss) = Just . DByEnumValue $ xss \/ yss
60+disjPart (DByProperties xss) (DByProperties yss) = Just . DByProperties $ xss \/ yss
61+disjPart _ _ = Nothing
62+
63+newtype Partitions = Partitions (M.Map PartitionLocation (S.Set PartitionData))
64+ deriving stock (Eq, Ord, Show)
65+
66+instance Lattice Partitions where
67+ Partitions xss /\ Partitions yss = Partitions $ M.unionWith conj xss yss
68+ where
69+ conj xs ys = S.fromList . catMaybes $ liftA2 conjPart (S.toList xs) (S.toList ys)
70+ Partitions xss \/ Partitions yss = Partitions $ M.intersectionWith disj xss yss
71+ where
72+ disj xs ys = S.fromList . catMaybes $ liftA2 disjPart (S.toList xs) (S.toList ys)
73+
74+instance BoundedMeetSemiLattice Partitions where
75+ top = Partitions M.empty
76+
77+-- The lattice has no bottom, but we use 'Lifted' to adjoin a free bottom element
78+
79+type PartitionM = ReaderT (Traced (Definitions Schema)) (State (MemoState ()))
80+
81+ignoreKnot :: KnotTier (Lifted Partitions) () PartitionM
82+ignoreKnot =
83+ KnotTier
84+ { onKnotFound = pure ()
85+ , onKnotUsed = \_ -> pure bottom
86+ , tieKnot = \_ -> pure
87+ }
88+
89+singletonPart :: PartitionData -> Lifted Partitions
90+singletonPart = Lift . Partitions . M.singleton PHere . S.singleton
91+
92+partitionSchema :: Traced Schema -> PartitionM (Lifted Partitions)
93+partitionSchema sch = do
94+ allClauses <- case tracedAllOf sch of
95+ Nothing -> pure []
96+ Just xs -> mapM partitionRefSchema xs
97+
98+ anyClause <- case tracedAnyOf sch of
99+ Nothing -> pure top
100+ Just xs -> joins <$> mapM partitionRefSchema xs
101+
102+ oneClause <- case tracedOneOf sch of
103+ Nothing -> pure top
104+ Just xs -> joins <$> mapM partitionRefSchema xs
105+
106+ byEnumClause <- case _schemaEnum $ extract sch of
107+ Nothing -> pure top
108+ Just xs ->
109+ pure . singletonPart $
110+ DByEnumValue $ LiteralDNF (S.fromList xs)
111+
112+ -- We can only partition by presence of a property if additional properties
113+ -- are disallowed, and the property is not optional
114+ let reqd = S.fromList $ _schemaRequired $ extract sch
115+ byPropertiesClause <- case _schemaAdditionalProperties $ extract sch of
116+ Just (AdditionalPropertiesAllowed False) -> do
117+ let props = S.fromList . IOHM.keys . _schemaProperties $ extract sch
118+ pure . singletonPart $
119+ DByProperties $ LiteralDNF (props S.\\ reqd, props `S.intersection` reqd)
120+ _ -> pure top
121+
122+ -- We can partition on something nested in a property only if the property is
123+ -- required
124+ let reqdProps = IOHM.filterWithKey (\k _ -> k `S.member` reqd) $ tracedProperties sch
125+ inPropertiesClauses <- forM (IOHM.toList reqdProps) $ \(k, rs) -> do
126+ f <- partitionRefSchema rs
127+ pure $ fmap (\(Partitions m) -> Partitions $ M.mapKeysMonotonic (PInProperty k) m) f
128+
129+ pure $ meets $ allClauses <> [anyClause, oneClause, byEnumClause, byPropertiesClause] <> inPropertiesClauses
130+
131+partitionRefSchema :: Traced (Referenced Schema) -> PartitionM (Lifted Partitions)
132+partitionRefSchema x = do
133+ defs <- R.ask
134+ memoWithKnot ignoreKnot (partitionSchema $ dereference defs x) (ask x)
135+
136+partitionCondition :: Condition t -> PartitionM (Lifted Partitions)
137+partitionCondition = \case
138+ Exactly x ->
139+ pure . singletonPart $
140+ DByEnumValue $ LiteralDNF (S.singleton $ untypeValue x)
141+ Properties props _ madd -> do
142+ let byProps = case madd of
143+ Just _ -> top
144+ Nothing ->
145+ singletonPart $
146+ DByProperties $
147+ LiteralDNF
148+ ( M.keysSet $ M.filter (not . propRequired) props
149+ , M.keysSet $ M.filter propRequired props
150+ )
151+ inProps <- forM (M.toList $ M.filter propRequired props) $ \(k, prop) -> do
152+ f <- partitionRefSchema $ propRefSchema prop
153+ pure $ fmap (\(Partitions m) -> Partitions $ M.mapKeysMonotonic (PInProperty k) m) f
154+ pure $ byProps /\ meets inProps
155+ _ -> pure top
156+
157+runPartitionM :: Traced (Definitions Schema) -> PartitionM a -> a
158+runPartitionM defs = runIdentity . runMemo () . (`runReaderT` defs)
159+
160+partitionJsonFormulas ::
161+ ProdCons (Traced (Definitions Schema)) ->
162+ ProdCons (JsonFormula t) ->
163+ Lifted Partitions
164+partitionJsonFormulas defs pc = producer pcPart \/ consumer pcPart
165+ where
166+ pcPart = partitionFormula <$> defs <*> pc
167+ partitionFormula def (JsonFormula xss) = runPartitionM def $ forDNF partitionCondition xss
168+
169+selectPartition :: Lifted Partitions -> Maybe (PartitionLocation, S.Set PartitionChoice)
170+selectPartition Bottom = Nothing
171+selectPartition (Lift (Partitions m)) =
172+ go [(loc, part) | (loc, parts) <- sortBy (comparing $ locLength . fst) $ M.toList m, part <- S.toList parts]
173+ where
174+ locLength :: PartitionLocation -> Int
175+ locLength = walk 0
176+ where
177+ walk !n PHere = n
178+ walk !n (PInProperty _ l) = walk (n + 1) l
179+ go [] = Nothing
180+ -- Skip partitioning by property for now
181+ go ((_, DByProperties _) : ps) = go ps
182+ -- Don't partition by enum value at the root (this reports removed enum values as contradictions in their respective partitions)
183+ go ((PHere, DByEnumValue _) : ps) = go ps
184+ go ((loc, DByEnumValue (DNF xss)) : ps)
185+ -- Check that no disjunction branches are unresticted
186+ | Just enums <- traverse (\(Disjunct xs) -> fmap (foldr1 S.intersection) . NE.nonEmpty . S.toList $ xs) . S.toList $ xss =
187+ -- TODO: improve
188+ Just (loc, S.map (CByEnumValue . S.singleton) $ S.unions enums)
189+ | otherwise = go ps
190+
191+-- This essentially has 3 cases:
192+-- Nothing -- we have produced a bottom schema
193+-- Just (False, _) -- there's been no change to the schema
194+-- Just (True, x) -- x is a new schema
195+type IntersectionM = ReaderT (Traced (Definitions Schema)) (WriterT Any Maybe)
196+
197+mBottom :: IntersectionM a
198+mBottom = lift . lift $ Nothing
199+
200+catchBottom :: IntersectionM a -> IntersectionM a -> IntersectionM a
201+catchBottom act handler = R.liftCatch (W.liftCatch (\a h -> a <|> h ())) act (\_ -> handler)
202+
203+mChange :: IntersectionM ()
204+mChange = tell $ Any True
205+
206+data IntersectionResult a = Disjoint | Same a | New a
207+ deriving stock (Eq, Ord, Show)
208+
209+runIntersectionM :: Traced (Definitions Schema) -> IntersectionM a -> IntersectionResult a
210+runIntersectionM defs act = case runWriterT $ runReaderT act defs of
211+ Nothing -> Disjoint
212+ Just (x, Any False) -> Same x
213+ Just (x, Any True) -> New x
214+
215+intersectSchema ::
216+ PartitionLocation ->
217+ PartitionChoice ->
218+ Traced Schema ->
219+ IntersectionM Schema
220+intersectSchema loc part sch = do
221+ allOf' <- forM (tracedAllOf sch) $ \rss ->
222+ -- Assuming i ranges over a nonempty set (checked in processSchema)
223+ -- (โ‹‚_i A[i]) โˆฉ X = โ‹‚_i (A[i] โˆฉ X)
224+ -- If any intersections are empty, the result is empty. If any intersections are a change, the result is a change.
225+ traverse (intersectRefSchema loc part) rss
226+ anyOf' <- forM (tracedAnyOf sch) $ \rss -> do
227+ -- (โ‹ƒ_i A[i]) โˆฉ X = โ‹ƒ_i (A[i] โˆฉ X)
228+ -- Collect only the nonempty A[i] โˆฉ X, unless there are none, in which case the result is empty.
229+ -- If any schema is empty, we remove it from the list which constitutes a change.
230+ mSchemas <- forM rss $ \rs -> catchBottom (Just <$> intersectRefSchema loc part rs) (mChange >> pure Nothing)
231+ case catMaybes mSchemas of
232+ [] -> mBottom
233+ schs -> pure schs
234+ oneOf' <- forM (tracedOneOf sch) $ \rss -> do
235+ -- Same as anyOf'. By intersecting we're only making them more disjoint if anything.
236+ mSchemas <- forM rss $ \rs -> catchBottom (Just <$> intersectRefSchema loc part rs) (mChange >> pure Nothing)
237+ case catMaybes mSchemas of
238+ [] -> mBottom
239+ schs -> pure schs
240+ let sch' = (extract sch) {_schemaAllOf = allOf', _schemaAnyOf = anyOf', _schemaOneOf = oneOf'}
241+ -- Now the local changes:
242+ case loc of
243+ PInProperty k loc' -> case IOHM.lookup k $ tracedProperties sch of
244+ Nothing -> error $ "Partitioning via absent property: " <> T.unpack k
245+ Just prop -> do
246+ prop' <- intersectRefSchema loc' part prop
247+ pure $ sch' {_schemaProperties = IOHM.adjust (const prop') k $ _schemaProperties sch'}
248+ PHere -> case part of
249+ CByEnumValue vals -> do
250+ enum' <- case _schemaEnum sch' of
251+ Nothing -> do
252+ mChange
253+ pure $ S.toList vals
254+ Just xs -> do
255+ when (any (`S.notMember` vals) xs) mChange
256+ case filter (`S.member` vals) xs of
257+ [] -> mBottom
258+ xs' -> pure xs'
259+ pure $ sch' {_schemaEnum = Just enum'}
260+ CByProperties {} -> error "CByProperties not implemented"
261+
262+intersectRefSchema ::
263+ PartitionLocation ->
264+ PartitionChoice ->
265+ Traced (Referenced Schema) ->
266+ IntersectionM (Referenced Schema)
267+intersectRefSchema loc part rs = do
268+ defs <- R.ask
269+ Inline <$> intersectSchema loc part (dereference defs rs)
270+
271+intersectCondition :: Traced (Definitions Schema) -> PartitionLocation -> PartitionChoice -> Condition t -> DNF (Condition t)
272+intersectCondition _defs PHere (CByEnumValue values) cond@(Exactly x) =
273+ if untypeValue x `S.member` values then LiteralDNF cond else bottom
274+intersectCondition defs (PInProperty k loc) part cond@(Properties props add madd) = case M.lookup k props of
275+ Nothing -> LiteralDNF cond -- shouldn't happen
276+ Just prop -> case runIntersectionM defs $ intersectRefSchema loc part $ propRefSchema prop of
277+ New rs' ->
278+ let trs' = traced (ask (propRefSchema prop) >>> step (Partitioned (loc, part))) rs'
279+ in LiteralDNF $ Properties (M.insert k prop {propRefSchema = trs'} props) add madd
280+ Same _ -> LiteralDNF cond
281+ Disjoint -> bottom
282+intersectCondition _defs _loc _part cond = LiteralDNF cond
283+
284+intersectFormula :: Traced (Definitions Schema) -> PartitionLocation -> PartitionChoice -> JsonFormula t -> JsonFormula t
285+intersectFormula defs loc part = JsonFormula . foldDNF (intersectCondition defs loc part) . getJsonFormula
286+
287+tryPartition :: ProdCons (Traced (Definitions Schema)) -> ProdCons (JsonFormula t) -> [(Maybe Partition, ProdCons (JsonFormula t))]
288+tryPartition defs pc = case selectPartition $ partitionJsonFormulas defs pc of
289+ Nothing -> [(Nothing, pc)]
290+ Just (loc, parts) -> [(Just (loc, part), intersectFormula <$> defs <*> pure loc <*> pure part <*> pc) | part <- S.toList parts]
291+
292+showPartition :: Partition -> Inlines
293+showPartition = \case
294+ (partition, CByEnumValue (S.toList -> [v])) ->
295+ renderPartitionLocation partition <> " is " <> showJSONValueInline v
296+ (partition, CByEnumValue (S.toList -> vs)) ->
297+ renderPartitionLocation partition <> " has values: "
298+ <> (fold . L.intersperse ", " . fmap showJSONValueInline $ vs)
299+ (partition, CByProperties (S.toList -> incl) (S.toList -> [])) ->
300+ renderPartitionLocation partition <> " contains the properties: " <> listCodes incl
301+ (partition, CByProperties (S.toList -> []) (S.toList -> excl)) ->
302+ renderPartitionLocation partition <> " does not contain the properties: " <> listCodes excl
303+ (partition, CByProperties (S.toList -> incl) (S.toList -> excl)) ->
304+ renderPartitionLocation partition
305+ <> " contains the properties "
306+ <> listCodes incl
307+ <> " and does not contain the properties "
308+ <> listCodes excl
309+ where
310+ listCodes :: [Text] -> Inlines
311+ listCodes = fold . L.intersperse ", " . fmap code
312+ renderPartitionLocation :: PartitionLocation -> Inlines
313+ renderPartitionLocation p = code $ "$" <> renderPartitionLocation' p
314+ where
315+ renderPartitionLocation' :: PartitionLocation -> Text
316+ renderPartitionLocation' PHere = mempty
317+ renderPartitionLocation' (PInProperty prop rest) = "." <> prop <> renderPartitionLocation' rest
src/Data/OpenApi/Compare/Validate/Schema/Process.hsnew file+377
@@ -0,0 +1,377 @@
1+module Data.OpenApi.Compare.Validate.Schema.Process
2+ ( schemaToFormula,
3+ )
4+where
5+
6+import Algebra.Lattice
7+import Control.Monad.Reader hiding (ask)
8+import qualified Control.Monad.Reader as R
9+import Control.Monad.State
10+import Control.Monad.Writer
11+import qualified Data.Aeson as A
12+import Data.Functor.Identity
13+import qualified Data.HashMap.Strict.InsOrd as IOHM
14+import qualified Data.Map as M
15+import Data.Maybe
16+import Data.OpenApi hiding (get)
17+import Data.OpenApi.Compare.Behavior
18+import Data.OpenApi.Compare.Memo
19+import Data.OpenApi.Compare.Paths
20+import qualified Data.OpenApi.Compare.PathsPrefixTree as P
21+import Data.OpenApi.Compare.References
22+import Data.OpenApi.Compare.Subtree
23+import Data.OpenApi.Compare.Validate.Schema.DNF
24+import Data.OpenApi.Compare.Validate.Schema.Issues
25+import Data.OpenApi.Compare.Validate.Schema.JsonFormula
26+import Data.OpenApi.Compare.Validate.Schema.Partition
27+import Data.OpenApi.Compare.Validate.Schema.Traced
28+import Data.OpenApi.Compare.Validate.Schema.TypedJson
29+import Data.Ord
30+import qualified Data.Set as S
31+
32+-- | A fake writer monad that doesn't actually record anything and allows lazy recursion.
33+newtype Silent w a = Silent {runSilent :: a}
34+ deriving stock (Functor)
35+ deriving (Applicative, Monad) via Identity
36+
37+instance Monoid w => MonadWriter w (Silent w) where
38+ tell _ = Silent ()
39+ listen (Silent x) = Silent (x, mempty)
40+ pass (Silent (x, _)) = Silent x
41+
42+instance MonadState (MemoState ()) (Silent w) where
43+ get = Silent $ runIdentity $ runMemo () get
44+ put _ = pure ()
45+
46+type ProcessM = StateT (MemoState ()) (ReaderT (Traced (Definitions Schema)) (Writer (P.PathsPrefixTree Behave AnIssue 'SchemaLevel)))
47+
48+type SilentM = ReaderT (Traced (Definitions Schema)) (Silent (P.PathsPrefixTree Behave AnIssue 'SchemaLevel))
49+
50+-- Either SilentM or ProcessM
51+type MonadProcess m =
52+ ( MonadReader (Traced (Definitions Schema)) m
53+ , MonadWriter (P.PathsPrefixTree Behave AnIssue 'SchemaLevel) m
54+ , MonadState (MemoState ()) m
55+ )
56+
57+warn :: MonadProcess m => Issue 'SchemaLevel -> m ()
58+warn issue = tell $ P.singleton $ AnItem Root $ anIssue issue
59+
60+-- | Ignore warnings but allow a recursive loop that lazily computes a recursive 'Condition'.
61+silently :: MonadProcess m => SilentM a -> m a
62+silently m = do
63+ defs <- R.ask
64+ pure . runSilent $ runReaderT m defs
65+
66+warnKnot :: MonadProcess m => KnotTier (ForeachType JsonFormula) () m
67+warnKnot =
68+ KnotTier
69+ { onKnotFound = warn UnguardedRecursion
70+ , onKnotUsed = \_ -> pure bottom
71+ , tieKnot = \_ -> pure
72+ }
73+
74+processRefSchema ::
75+ MonadProcess m =>
76+ Traced (Referenced Schema) ->
77+ m (ForeachType JsonFormula)
78+processRefSchema x = do
79+ defs <- R.ask
80+ memoWithKnot warnKnot (processSchema $ dereference defs x) (ask x)
81+
82+-- | Turn a schema into a tuple of 'JsonFormula's that describes the condition
83+-- for every possible type of a JSON value. The conditions are independent, and
84+-- are thus checked independently.
85+processSchema ::
86+ MonadProcess m =>
87+ Traced Schema ->
88+ m (ForeachType JsonFormula)
89+processSchema sch@(extract -> Schema {..}) = do
90+ let singletonFormula :: Condition t -> JsonFormula t
91+ singletonFormula = JsonFormula . LiteralDNF
92+
93+ allClauses <- case tracedAllOf sch of
94+ Nothing -> pure []
95+ Just [] -> [] <$ warn (InvalidSchema "no items in allOf")
96+ Just xs -> mapM processRefSchema xs
97+
98+ anyClause <- case tracedAnyOf sch of
99+ Nothing -> pure top
100+ Just [] -> bottom <$ warn (InvalidSchema "no items in anyOf")
101+ Just xs -> joins <$> mapM processRefSchema xs
102+
103+ oneClause <- case tracedOneOf sch of
104+ Nothing -> pure top
105+ Just [] -> bottom <$ warn (InvalidSchema "no items in oneOf")
106+ Just xs -> do
107+ checkOneOfDisjoint xs >>= \case
108+ True -> pure ()
109+ False -> warn OneOfNotDisjoint
110+ joins <$> mapM processRefSchema xs
111+
112+ case _schemaNot of
113+ Nothing -> pure ()
114+ Just _ -> warn (NotSupported "not clause is unsupported")
115+
116+ let typeClause = case _schemaType of
117+ Nothing -> top
118+ Just OpenApiNull ->
119+ bottom
120+ { forNull = top
121+ }
122+ Just OpenApiBoolean ->
123+ bottom
124+ { forBoolean = top
125+ }
126+ Just OpenApiNumber ->
127+ bottom
128+ { forNumber = top
129+ }
130+ Just OpenApiInteger ->
131+ bottom
132+ { forNumber = singletonFormula $ MultipleOf 1
133+ }
134+ Just OpenApiString ->
135+ bottom
136+ { forString = top
137+ }
138+ Just OpenApiArray ->
139+ bottom
140+ { forArray = top
141+ }
142+ Just OpenApiObject ->
143+ bottom
144+ { forObject = top
145+ }
146+
147+ let valueEnum A.Null =
148+ bottom
149+ { forNull = singletonFormula $ Exactly TNull
150+ }
151+ valueEnum (A.Bool b) =
152+ bottom
153+ { forBoolean = singletonFormula $ Exactly $ TBool b
154+ }
155+ valueEnum (A.Number n) =
156+ bottom
157+ { forNumber = singletonFormula $ Exactly $ TNumber n
158+ }
159+ valueEnum (A.String s) =
160+ bottom
161+ { forString = singletonFormula $ Exactly $ TString s
162+ }
163+ valueEnum (A.Array a) =
164+ bottom
165+ { forArray = singletonFormula $ Exactly $ TArray a
166+ }
167+ valueEnum (A.Object o) =
168+ bottom
169+ { forObject = singletonFormula $ Exactly $ TObject o
170+ }
171+ enumClause <- case _schemaEnum of
172+ Nothing -> pure top
173+ Just [] -> bottom <$ warn (InvalidSchema "no items in enum")
174+ Just xs -> pure $ joins (valueEnum <$> xs)
175+
176+ let maximumClause = case _schemaMaximum of
177+ Nothing -> top
178+ Just n ->
179+ top
180+ { forNumber = singletonFormula $
181+ Maximum $
182+ case _schemaExclusiveMaximum of
183+ Just True -> Exclusive n
184+ _ -> Inclusive n
185+ }
186+
187+ minimumClause = case _schemaMinimum of
188+ Nothing -> top
189+ Just n ->
190+ top
191+ { forNumber = singletonFormula $
192+ Minimum $
193+ Down $
194+ case _schemaExclusiveMinimum of
195+ Just True -> Exclusive $ Down n
196+ _ -> Inclusive $ Down n
197+ }
198+
199+ multipleOfClause = case _schemaMultipleOf of
200+ Nothing -> top
201+ Just n ->
202+ top
203+ { forNumber = singletonFormula $ MultipleOf n
204+ }
205+
206+ formatClause <- case _schemaFormat of
207+ Nothing -> pure top
208+ Just f
209+ | f `elem` ["int32", "int64", "float", "double"] ->
210+ pure
211+ top
212+ { forNumber = singletonFormula $ NumberFormat f
213+ }
214+ Just f
215+ | f `elem` ["byte", "binary", "date", "date-time", "password", "uuid"] ->
216+ pure
217+ top
218+ { forString = singletonFormula $ StringFormat f
219+ }
220+ Just f -> top <$ warn (NotSupported $ "Unknown format: " <> f)
221+
222+ let maxLengthClause = case _schemaMaxLength of
223+ Nothing -> top
224+ Just n ->
225+ top
226+ { forString = singletonFormula $ MaxLength n
227+ }
228+
229+ minLengthClause = case _schemaMinLength of
230+ Nothing -> top
231+ Just n ->
232+ top
233+ { forString = singletonFormula $ MinLength n
234+ }
235+
236+ patternClause = case _schemaPattern of
237+ Nothing -> top
238+ Just p ->
239+ top
240+ { forString = singletonFormula $ Pattern p
241+ }
242+
243+ itemsClause <- case tracedItems sch of
244+ Nothing -> pure top
245+ Just (Left rs) -> do
246+ f <- silently $ processRefSchema rs
247+ pure top {forArray = singletonFormula $ Items f rs}
248+ Just (Right rss) -> do
249+ fsrs <- forM rss $ \rs -> do
250+ f <- silently $ processRefSchema rs
251+ pure (f, rs)
252+ pure top {forArray = singletonFormula $ TupleItems fsrs}
253+
254+ let maxItemsClause = case _schemaMaxItems of
255+ Nothing -> top
256+ Just n ->
257+ top
258+ { forArray = singletonFormula $ MaxItems n
259+ }
260+
261+ minItemsClause = case _schemaMinItems of
262+ Nothing -> top
263+ Just n ->
264+ top
265+ { forArray = singletonFormula $ MinItems n
266+ }
267+
268+ uniqueItemsClause = case _schemaUniqueItems of
269+ Just True ->
270+ top
271+ { forArray = singletonFormula UniqueItems
272+ }
273+ _ -> top
274+
275+ (addProps, addPropSchema) <- case tracedAdditionalProperties sch of
276+ Just (Right rs) -> (,Just rs) <$> silently (processRefSchema rs)
277+ Just (Left False) -> pure (bottom, Nothing)
278+ _ -> pure (top, Just $ traced (ask sch `Snoc` AdditionalPropertiesStep) $ Inline mempty)
279+ propList <- forM (S.toList . S.fromList $ IOHM.keys _schemaProperties <> _schemaRequired) $ \k -> do
280+ (f, psch) <- case IOHM.lookup k $ tracedProperties sch of
281+ Just rs -> (,rs) <$> silently (processRefSchema rs)
282+ Nothing ->
283+ let fakeSchema = traced (ask sch `Snoc` AdditionalPropertiesStep) $ Inline mempty
284+ in -- The mempty here is incorrect, but if addPropSchema was Nothing, then
285+ -- addProps is bottom, and k is in _schemaRequired. We handle this situation
286+ -- below and short-circuit the entire Properties condition to bottom
287+ pure (addProps, fromMaybe fakeSchema addPropSchema)
288+ pure (k, Property (k `elem` _schemaRequired) f psch)
289+ let allBottom f = getAll $
290+ foldType $ \_ ty -> case getJsonFormula $ ty f of
291+ BottomDNF -> All True
292+ _ -> All False
293+ allTop f = getAll $
294+ foldType $ \_ ty -> case getJsonFormula $ ty f of
295+ TopDNF -> All True
296+ _ -> All False
297+ -- remove optional fields whose schemata match that of additional props
298+ propMap = M.filter (\p -> propRequired p || propFormula p /= addProps) $ M.fromList propList
299+ propertiesClause
300+ | any (\p -> propRequired p && allBottom (propFormula p)) propMap =
301+ bottom -- if any required field has unsatisfiable schema
302+ | M.null propMap
303+ , allTop addProps =
304+ top -- if all fields are optional and have trivial schemata
305+ | otherwise =
306+ top
307+ { forObject = singletonFormula $ Properties propMap addProps addPropSchema
308+ }
309+
310+ maxPropertiesClause = case _schemaMaxProperties of
311+ Nothing -> top
312+ Just n ->
313+ top
314+ { forObject = singletonFormula $ MaxProperties n
315+ }
316+
317+ minPropertiesClause = case _schemaMinProperties of
318+ Nothing -> top
319+ Just n ->
320+ top
321+ { forObject = singletonFormula $ MinProperties n
322+ }
323+
324+ nullableClause
325+ | Just True <- _schemaNullable =
326+ bottom
327+ { forNull = singletonFormula $ Exactly TNull
328+ }
329+ | otherwise = bottom
330+
331+ pure $
332+ nullableClause
333+ \/ meets
334+ ( allClauses
335+ <> [ anyClause
336+ , oneClause
337+ , typeClause
338+ , enumClause
339+ , maximumClause
340+ , minimumClause
341+ , multipleOfClause
342+ , formatClause
343+ , maxLengthClause
344+ , minLengthClause
345+ , patternClause
346+ , itemsClause
347+ , maxItemsClause
348+ , minItemsClause
349+ , uniqueItemsClause
350+ , propertiesClause
351+ , maxPropertiesClause
352+ , minPropertiesClause
353+ ]
354+ )
355+
356+{- TODO: ReadOnly/WriteOnly #68 -}
357+
358+checkOneOfDisjoint :: MonadProcess m => [Traced (Referenced Schema)] -> m Bool
359+checkOneOfDisjoint schs = do
360+ defs <- R.ask
361+ pure $ case selectPartition $ joins $ runPartitionM defs $ traverse partitionRefSchema schs of
362+ Nothing -> False
363+ Just (loc, parts) ->
364+ let intersects part sch = case runIntersectionM defs $ intersectRefSchema loc part sch of
365+ Disjoint -> False
366+ _ -> True
367+ in all (\part -> 1 >= length (filter (intersects part) schs)) parts
368+ where
369+
370+runProcessM :: Traced (Definitions Schema) -> ProcessM a -> (a, P.PathsPrefixTree Behave AnIssue 'SchemaLevel)
371+runProcessM defs = runWriter . (`runReaderT` defs) . runMemo ()
372+
373+schemaToFormula ::
374+ Traced (Definitions Schema) ->
375+ Traced Schema ->
376+ (ForeachType JsonFormula, P.PathsPrefixTree Behave AnIssue 'SchemaLevel)
377+schemaToFormula defs rs = runProcessM defs $ processSchema rs
src/Data/OpenApi/Compare/Validate/Schema/Traced.hsnew file+115
@@ -0,0 +1,115 @@
1+{-# OPTIONS_GHC -Wno-orphans #-}
2+
3+module Data.OpenApi.Compare.Validate.Schema.Traced
4+ ( Step (..),
5+ tracedAllOf,
6+ tracedAnyOf,
7+ tracedOneOf,
8+ tracedItems,
9+ tracedAdditionalProperties,
10+ tracedDiscriminator,
11+ tracedProperties,
12+ tracedConjunct,
13+ PartitionLocation (..),
14+ PartitionChoice (..),
15+ Partition,
16+ )
17+where
18+
19+import qualified Data.Aeson as A
20+import Data.Functor
21+import qualified Data.HashMap.Strict.InsOrd as IOHM
22+import qualified Data.List.NonEmpty as NE
23+import Data.OpenApi
24+import Data.OpenApi.Compare.Subtree
25+import qualified Data.Set as S
26+import Data.Text (Text)
27+
28+data PartitionChoice
29+ = CByEnumValue (S.Set A.Value)
30+ | CByProperties (S.Set Text) (S.Set Text) -- included, excluded
31+ deriving stock (Eq, Ord, Show)
32+
33+data PartitionLocation
34+ = PHere
35+ | PInProperty Text PartitionLocation
36+ deriving stock (Eq, Ord, Show)
37+
38+type Partition = (PartitionLocation, PartitionChoice)
39+
40+instance Steppable Schema (Referenced Schema) where
41+ data Step Schema (Referenced Schema)
42+ = AllOfStep Int
43+ | OneOfStep Int
44+ | AnyOfStep Int
45+ | ItemsObjectStep
46+ | ItemsArrayStep Int
47+ | AdditionalPropertiesStep
48+ | NotStep
49+ | ImplicitTopSchema
50+ deriving stock (Eq, Ord, Show)
51+
52+instance Steppable (Referenced Schema) (Referenced Schema) where
53+ data Step (Referenced Schema) (Referenced Schema)
54+ = -- | Invariant (for better memoization only): the "tail" of the trace is
55+ -- the "least" of the traces of the conjuncted schemata
56+ ConjunctedWith (NE.NonEmpty (Trace (Referenced Schema)))
57+ | Partitioned Partition
58+ deriving stock (Eq, Ord, Show)
59+
60+instance Steppable Schema (Definitions (Referenced Schema)) where
61+ data Step Schema (Definitions (Referenced Schema)) = PropertiesStep
62+ deriving stock (Eq, Ord, Show)
63+
64+instance Steppable Schema Discriminator where
65+ data Step Schema Discriminator = DiscriminatorStep
66+ deriving stock (Eq, Ord, Show)
67+
68+instance Steppable Discriminator (Definitions (Referenced Schema)) where
69+ data Step Discriminator (Definitions (Referenced Schema)) = DiscriminatorMapping
70+ deriving stock (Eq, Ord, Show)
71+
72+tracedAllOf :: Traced Schema -> Maybe [Traced (Referenced Schema)]
73+tracedAllOf sch =
74+ _schemaAllOf (extract sch) <&> \xs ->
75+ [traced (ask sch >>> step (AllOfStep i)) x | (i, x) <- zip [0 ..] xs]
76+
77+tracedAnyOf :: Traced Schema -> Maybe [Traced (Referenced Schema)]
78+tracedAnyOf sch =
79+ _schemaAnyOf (extract sch) <&> \xs ->
80+ [traced (ask sch >>> step (AnyOfStep i)) x | (i, x) <- zip [0 ..] xs]
81+
82+tracedOneOf :: Traced Schema -> Maybe [Traced (Referenced Schema)]
83+tracedOneOf sch =
84+ _schemaOneOf (extract sch) <&> \xs ->
85+ [traced (ask sch >>> step (OneOfStep i)) x | (i, x) <- zip [0 ..] xs]
86+
87+tracedItems :: Traced Schema -> Maybe (Either (Traced (Referenced Schema)) [Traced (Referenced Schema)])
88+tracedItems sch =
89+ _schemaItems (extract sch) <&> \case
90+ OpenApiItemsObject x -> Left $ traced (ask sch >>> step ItemsObjectStep) x
91+ OpenApiItemsArray xs ->
92+ Right
93+ [traced (ask sch >>> step (ItemsArrayStep i)) x | (i, x) <- zip [0 ..] xs]
94+
95+tracedAdditionalProperties :: Traced Schema -> Maybe (Either Bool (Traced (Referenced Schema)))
96+tracedAdditionalProperties sch =
97+ _schemaAdditionalProperties (extract sch) <&> \case
98+ AdditionalPropertiesAllowed b -> Left b
99+ AdditionalPropertiesSchema x -> Right $ traced (ask sch >>> step AdditionalPropertiesStep) x
100+
101+tracedDiscriminator :: Traced Schema -> Maybe (Traced Discriminator)
102+tracedDiscriminator = sequence . stepTraced DiscriminatorStep . fmap _schemaDiscriminator
103+
104+tracedProperties :: Traced Schema -> IOHM.InsOrdHashMap Text (Traced (Referenced Schema))
105+tracedProperties sch =
106+ IOHM.mapWithKey
107+ (\k -> traced (ask sch >>> step PropertiesStep >>> step (InsOrdHashMapKeyStep k)))
108+ (_schemaProperties $ extract sch)
109+
110+tracedConjunct :: NE.NonEmpty (Traced (Referenced Schema)) -> Traced (Referenced Schema)
111+tracedConjunct refSchemas = case NE.sortWith ask refSchemas of
112+ (rs NE.:| []) -> rs
113+ (rs1 NE.:| rs2 : rss) ->
114+ traced (ask rs1 >>> step (ConjunctedWith $ ask <$> rs2 NE.:| rss)) $
115+ Inline mempty {_schemaAllOf = Just $ extract <$> rs1 : rs2 : rss}
src/Data/OpenApi/Compare/Validate/Schema/TypedJson.hsnew file+120
@@ -0,0 +1,120 @@
1+module Data.OpenApi.Compare.Validate.Schema.TypedJson
2+ ( JsonType (..),
3+ describeJSONType,
4+ TypedValue (..),
5+ untypeValue,
6+ ForeachType (..),
7+ foldType,
8+ forType_,
9+ )
10+where
11+
12+import Algebra.Lattice
13+import qualified Data.Aeson as A
14+import Data.Kind
15+import Data.Monoid
16+import Data.Scientific
17+import Data.String
18+import Data.Text (Text)
19+import Data.Typeable
20+
21+-- | Type of a JSON value
22+data JsonType
23+ = Null
24+ | Boolean
25+ | Number
26+ | String
27+ | Array
28+ | Object
29+ deriving stock (Eq, Ord, Show)
30+
31+describeJSONType :: IsString s => JsonType -> s
32+describeJSONType = \case
33+ Null -> "Null"
34+ Boolean -> "Boolean"
35+ Number -> "Number"
36+ String -> "String"
37+ Array -> "Array"
38+ Object -> "Object"
39+
40+-- | A 'A.Value' whose type we know
41+data TypedValue :: JsonType -> Type where
42+ TNull :: TypedValue 'Null
43+ TBool :: !Bool -> TypedValue 'Boolean
44+ TNumber :: !Scientific -> TypedValue 'Number
45+ TString :: !Text -> TypedValue 'String
46+ TArray :: !A.Array -> TypedValue 'Array
47+ TObject :: !A.Object -> TypedValue 'Object
48+
49+deriving stock instance Eq (TypedValue t)
50+
51+deriving stock instance Ord (TypedValue t)
52+
53+deriving stock instance Show (TypedValue t)
54+
55+untypeValue :: TypedValue t -> A.Value
56+untypeValue TNull = A.Null
57+untypeValue (TBool b) = A.Bool b
58+untypeValue (TNumber n) = A.Number n
59+untypeValue (TString s) = A.String s
60+untypeValue (TArray a) = A.Array a
61+untypeValue (TObject o) = A.Object o
62+
63+data ForeachType (f :: JsonType -> Type) = ForeachType
64+ { forNull :: f 'Null
65+ , forBoolean :: f 'Boolean
66+ , forNumber :: f 'Number
67+ , forString :: f 'String
68+ , forArray :: f 'Array
69+ , forObject :: f 'Object
70+ }
71+
72+deriving stock instance (forall x. Typeable x => Eq (f x)) => Eq (ForeachType f)
73+
74+deriving stock instance (forall x. Typeable x => Ord (f x)) => Ord (ForeachType f)
75+
76+deriving stock instance (forall x. Typeable x => Show (f x)) => Show (ForeachType f)
77+
78+foldType :: Monoid m => (forall x. Typeable x => JsonType -> (ForeachType f -> f x) -> m) -> m
79+foldType k =
80+ k Null forNull
81+ <> k Boolean forBoolean
82+ <> k Number forNumber
83+ <> k String forString
84+ <> k Array forArray
85+ <> k Object forObject
86+
87+forType_ :: Applicative m => (forall x. Typeable x => JsonType -> (ForeachType f -> f x) -> m ()) -> m ()
88+forType_ k = getAp $ foldType (\ty proj -> Ap $ k ty proj)
89+
90+broadcastType :: (forall x. Typeable x => f x) -> ForeachType f
91+broadcastType k =
92+ ForeachType
93+ { forNull = k
94+ , forBoolean = k
95+ , forNumber = k
96+ , forString = k
97+ , forArray = k
98+ , forObject = k
99+ }
100+
101+zipType :: (forall x. Typeable x => f x -> g x -> h x) -> ForeachType f -> ForeachType g -> ForeachType h
102+zipType k f1 f2 =
103+ ForeachType
104+ { forNull = k (forNull f1) (forNull f2)
105+ , forBoolean = k (forBoolean f1) (forBoolean f2)
106+ , forNumber = k (forNumber f1) (forNumber f2)
107+ , forString = k (forString f1) (forString f2)
108+ , forArray = k (forArray f1) (forArray f2)
109+ , forObject = k (forObject f1) (forObject f2)
110+ }
111+
112+instance (forall x. Lattice (f x)) => Lattice (ForeachType f) where
113+ (\/) = zipType (\/)
114+ (/\) = zipType (/\)
115+
116+instance (forall x. BoundedJoinSemiLattice (f x)) => BoundedJoinSemiLattice (ForeachType f) where
117+ bottom = broadcastType bottom
118+
119+instance (forall x. BoundedMeetSemiLattice (f x)) => BoundedMeetSemiLattice (ForeachType f) where
120+ top = broadcastType top
src/OpenAPI/Checker/Validate/SecurityRequirement.hs โ†’ src/Data/OpenApi/Compare/Validate/SecurityRequirement.hsrenamed+15โˆ’14
@@ -1,8 +1,8 @@
1{-# LANGUAGE PartialTypeSignatures #-}
1{-# LANGUAGE PartialTypeSignatures #-}
2{-# OPTIONS_GHC -Wno-orphans #-}
2{-# OPTIONS_GHC -Wno-orphans #-}
3
3
4โˆ’module OpenAPI.Checker.Validate.SecurityRequirement
4+module Data.OpenApi.Compare.Validate.SecurityRequirement
5โˆ’ ( Issue (..)
5+ ( Issue (..),
6 )
6 )
7where
7where
8
8
@@ -17,14 +17,14 @@ import Data.HList
17import qualified Data.HashMap.Strict.InsOrd as IOHM
17import qualified Data.HashMap.Strict.InsOrd as IOHM
18import qualified Data.List.NonEmpty as NE
18import qualified Data.List.NonEmpty as NE
19import Data.OpenApi
19import Data.OpenApi
20+import Data.OpenApi.Compare.Behavior
21+import Data.OpenApi.Compare.Subtree
22+import Data.OpenApi.Compare.Validate.OAuth2Flows
23+import Data.OpenApi.Compare.Validate.SecurityScheme ()
20import Data.Set (Set)
24import Data.Set (Set)
21import qualified Data.Set as S
25import qualified Data.Set as S
22import Data.Text (Text)
26import Data.Text (Text)
23import Data.Traversable
27import Data.Traversable
24โˆ’import OpenAPI.Checker.Behavior
25โˆ’import OpenAPI.Checker.Subtree
26โˆ’import OpenAPI.Checker.Validate.OAuth2Flows
27โˆ’import OpenAPI.Checker.Validate.SecurityScheme ()
28
28
29instance Subtree SecurityRequirement where
29instance Subtree SecurityRequirement where
30 type SubtreeLevel SecurityRequirement = 'SecurityRequirementLevel
30 type SubtreeLevel SecurityRequirement = 'SecurityRequirementLevel
@@ -41,18 +41,19 @@ instance Subtree SecurityRequirement where
41 for (IOHM.toList $ getSecurityRequirement sec) $ \(key, scopes) ->
41 for (IOHM.toList $ getSecurityRequirement sec) $ \(key, scopes) ->
42 (,scopes) <$> lookupScheme key defs
42 (,scopes) <$> lookupScheme key defs
43 structuralMaybeWith
43 structuralMaybeWith
44โˆ’ (\pc' -> do
44+ ( \pc' -> do
45โˆ’ let ProdCons pScopes cScopes = fmap snd <$> pc'
45+ let ProdCons pScopes cScopes = fmap snd <$> pc'
46โˆ’ unless (pScopes == cScopes) structuralIssue
46+ unless (pScopes == cScopes) structuralIssue
47โˆ’ structuralList env $ fmap fst <$> pc'
47+ structuralList env $ fmap fst <$> pc'
48โˆ’ pure ())
48+ pure ()
49+ )
49 normalized
50 normalized
50 pure ()
51 pure ()
51 checkSemanticCompatibility env bhv' pc = do
52 checkSemanticCompatibility env bhv' pc = do
52 let schemes = getH @(ProdCons (Traced (Definitions SecurityScheme))) env
53 let schemes = getH @(ProdCons (Traced (Definitions SecurityScheme))) env
53 ( ProdCons pErrs cErrs
54 ( ProdCons pErrs cErrs
54โˆ’ , (ProdCons pSchemes cSchemes)
55+ , (ProdCons pSchemes cSchemes) ::
55โˆ’ :: ProdCons [(Behavior 'SecuritySchemeLevel, Traced SecurityScheme, [Text])]
56+ ProdCons [(Behavior 'SecuritySchemeLevel, Traced SecurityScheme, [Text])]
56 ) =
57 ) =
57 NE.unzip $
58 NE.unzip $
58 partitionEithers <$> do
59 partitionEithers <$> do
@@ -102,7 +103,7 @@ instance Subtree SecurityRequirement where
102 (SecuritySchemeOAuth2 {}, SecuritySchemeOAuth2 {}) -> pure ()
103 (SecuritySchemeOAuth2 {}, SecuritySchemeOAuth2 {}) -> pure ()
103 _ -> unless (null pScopes && null cScopes) $ issueAt bhv CanNotHaveScopes
104 _ -> unless (null pScopes && null cScopes) $ issueAt bhv CanNotHaveScopes
104 for_ errs $ issueAt bhv
105 for_ errs $ issueAt bhv
105โˆ’ checkCompatibility env bhv pc'
106+ checkCompatibility bhv env pc'
106 pure ()
107 pure ()
107 pure ()
108 pure ()
108
109
src/OpenAPI/Checker/Validate/SecurityScheme.hs โ†’ src/Data/OpenApi/Compare/Validate/SecurityScheme.hsrenamed+6โˆ’6
@@ -1,16 +1,16 @@
1{-# OPTIONS_GHC -Wno-orphans #-}
1{-# OPTIONS_GHC -Wno-orphans #-}
2
2
3โˆ’module OpenAPI.Checker.Validate.SecurityScheme
3+module Data.OpenApi.Compare.Validate.SecurityScheme
4 (
4 (
5 )
5 )
6where
6where
7
7
8import Control.Monad
8import Control.Monad
9import Data.OpenApi
9import Data.OpenApi
10โˆ’import OpenAPI.Checker.Behavior
10+import Data.OpenApi.Compare.Behavior
11โˆ’import OpenAPI.Checker.Orphans ()
11+import Data.OpenApi.Compare.Orphans ()
12โˆ’import OpenAPI.Checker.Subtree
12+import Data.OpenApi.Compare.Subtree
13โˆ’import OpenAPI.Checker.Validate.OAuth2Flows
13+import Data.OpenApi.Compare.Validate.OAuth2Flows
14
14
15instance Subtree SecurityScheme where
15instance Subtree SecurityScheme where
16 type CheckEnv SecurityScheme = '[]
16 type CheckEnv SecurityScheme = '[]
@@ -26,7 +26,7 @@ instance Subtree SecurityScheme where
26 (ProdCons (Traced _ (SecuritySchemeApiKey pParams)) (Traced _ (SecuritySchemeApiKey cParams))) -> do
26 (ProdCons (Traced _ (SecuritySchemeApiKey pParams)) (Traced _ (SecuritySchemeApiKey cParams))) -> do
27 unless (pParams == cParams) (issueAt bhv $ ApiKeyParamsDontMatch pParams cParams)
27 unless (pParams == cParams) (issueAt bhv $ ApiKeyParamsDontMatch pParams cParams)
28 (ProdCons (Traced pT (SecuritySchemeOAuth2 pFlows)) (Traced cT (SecuritySchemeOAuth2 cFlows))) -> do
28 (ProdCons (Traced pT (SecuritySchemeOAuth2 pFlows)) (Traced cT (SecuritySchemeOAuth2 cFlows))) -> do
29โˆ’ checkCompatibility env bhv . fmap (stepTraced SecurityOAuthFlowsStep) $ ProdCons (Traced pT pFlows) (Traced cT cFlows)
29+ checkCompatibility bhv env . fmap (stepTraced SecurityOAuthFlowsStep) $ ProdCons (Traced pT pFlows) (Traced cT cFlows)
30 (ProdCons (Traced _ (SecuritySchemeOpenIdConnect pUrl)) (Traced _ (SecuritySchemeOpenIdConnect cUrl))) -> do
30 (ProdCons (Traced _ (SecuritySchemeOpenIdConnect pUrl)) (Traced _ (SecuritySchemeOpenIdConnect cUrl))) -> do
31 unless (pUrl == cUrl) (issueAt bhv $ OpenIdConnectUrlsDontMatch pUrl cUrl)
31 unless (pUrl == cUrl) (issueAt bhv $ OpenIdConnectUrlsDontMatch pUrl cUrl)
32 _ -> issueAt bhv DifferentSecuritySchemes
32 _ -> issueAt bhv DifferentSecuritySchemes
src/OpenAPI/Checker/Validate/Server.hs โ†’ src/Data/OpenApi/Compare/Validate/Server.hsrenamed+22โˆ’19
@@ -1,7 +1,7 @@
1{-# OPTIONS_GHC -Wno-orphans #-}
1{-# OPTIONS_GHC -Wno-orphans #-}
2
2
3โˆ’module OpenAPI.Checker.Validate.Server
3+module Data.OpenApi.Compare.Validate.Server
4โˆ’ ( Issue (..)
4+ ( Issue (..),
5 )
5 )
6where
6where
7
7
@@ -19,21 +19,21 @@ import qualified Data.HashSet.InsOrd as IOHM
19import qualified Data.HashSet.InsOrd as IOHS
19import qualified Data.HashSet.InsOrd as IOHS
20import Data.Maybe
20import Data.Maybe
21import Data.OpenApi
21import Data.OpenApi
22+import Data.OpenApi.Compare.Behavior
23+import Data.OpenApi.Compare.Common
24+import Data.OpenApi.Compare.Paths
25+import Data.OpenApi.Compare.Subtree
26+import Data.OpenApi.Compare.Validate.MediaTypeObject
22import qualified Data.Set as S
27import qualified Data.Set as S
23import Data.Text (Text)
28import Data.Text (Text)
24import qualified Data.Text as T
29import qualified Data.Text as T
25import Data.Traversable
30import Data.Traversable
26โˆ’import OpenAPI.Checker.Behavior
27โˆ’import OpenAPI.Checker.Common
28โˆ’import OpenAPI.Checker.Paths
29โˆ’import OpenAPI.Checker.Subtree
30โˆ’import OpenAPI.Checker.Validate.MediaTypeObject
31import Text.Pandoc.Builder
31import Text.Pandoc.Builder
32import Prelude as P
32import Prelude as P
33
33
34โˆ’tracedParsedServerUrlParts
34+tracedParsedServerUrlParts ::
35โˆ’ :: Server
35+ Server ->
36โˆ’ -> Either (Issue 'ServerLevel) ProcessedServer
36+ Either (Issue 'ServerLevel) ProcessedServer
37tracedParsedServerUrlParts s =
37tracedParsedServerUrlParts s =
38 let parsedUrl = parseServerUrl $ _serverUrl s
38 let parsedUrl = parseServerUrl $ _serverUrl s
39 lookupVar var = case IOHM.lookup var (_serverVariables s) of
39 lookupVar var = case IOHM.lookup var (_serverVariables s) of
@@ -46,7 +46,7 @@ instance Behavable 'OperationLevel 'ServerLevel where
46 = InServer Text
46 = InServer Text
47 deriving stock (Eq, Ord, Show)
47 deriving stock (Eq, Ord, Show)
48
48
49โˆ’ describeBehaviour (InServer n) = "Server " <> code n
49+ describeBehavior (InServer n) = "Server " <> code n
50
50
51instance Subtree [Server] where
51instance Subtree [Server] where
52 type SubtreeLevel [Server] = 'OperationLevel
52 type SubtreeLevel [Server] = 'OperationLevel
@@ -63,11 +63,12 @@ instance Subtree [Server] where
63 pcServer
63 pcServer
64 <&> partitionEithers
64 <&> partitionEithers
65 . fmap
65 . fmap
66โˆ’ (\(Traced t s) ->
66+ ( \(Traced t s) ->
67โˆ’ let bhv = beh >>> step (InServer $ _serverUrl s)
67+ let bhv = beh >>> step (InServer $ _serverUrl s)
68โˆ’ in case tracedParsedServerUrlParts s of
68+ in case tracedParsedServerUrlParts s of
69โˆ’ Left e -> Left $ issueAt bhv e
69+ Left e -> Left $ issueAt bhv e
70โˆ’ Right u -> Right (bhv, Traced (t >>> step (ServerStep $ _serverUrl s)) u))
70+ Right u -> Right (bhv, Traced (t >>> step (ServerStep $ _serverUrl s)) u)
71+ )
71 . sequence
72 . sequence
72 sequenceA_ pErrs
73 sequenceA_ pErrs
73 sequenceA_ cErrs
74 sequenceA_ cErrs
@@ -76,7 +77,7 @@ instance Subtree [Server] where
76 anyOfAt
77 anyOfAt
77 bhv
78 bhv
78 ServerNotMatched
79 ServerNotMatched
79โˆ’ [ checkCompatibility env bhv (ProdCons pUrl cUrl)
80+ [ checkCompatibility bhv env (ProdCons pUrl cUrl)
80 | cUrl <- potentiallyCompatible
81 | cUrl <- potentiallyCompatible
81 ]
82 ]
82 pure ()
83 pure ()
@@ -101,7 +102,7 @@ data ServerUrlPart var
101 deriving stock (Eq, Show, Functor, Foldable, Traversable)
102 deriving stock (Eq, Show, Functor, Foldable, Traversable)
102
103
103-- | This is super rough. Things like @{a|b}c@ will not match @ac@.
104-- | This is super rough. Things like @{a|b}c@ will not match @ac@.
104โˆ’-- FIXME: https://github.com/typeable/openapi-diff/issues/46
105+-- FIXME: #46
105--
106--
106-- NOTE: syntax is defined vaguely in the spec.
107-- NOTE: syntax is defined vaguely in the spec.
107parseServerUrl :: Text -> [ServerUrlPart Text]
108parseServerUrl :: Text -> [ServerUrlPart Text]
@@ -133,7 +134,9 @@ instance Issuable 'ServerLevel where
133 | ServerVariableNotDefined Text
134 | ServerVariableNotDefined Text
134 | ServerNotMatched
135 | ServerNotMatched
135 deriving stock (Eq, Ord, Show)
136 deriving stock (Eq, Ord, Show)
136โˆ’ issueIsUnsupported _ = False
137+ issueKind = \case
138+ ServerVariableNotDefined _ -> SchemaInvalid
139+ _ -> CertainIssue
137 describeIssue Forward (EnumValueNotConsumed _ v) =
140 describeIssue Forward (EnumValueNotConsumed _ v) =
138 para $ "Enum value " <> code v <> " has been removed."
141 para $ "Enum value " <> code v <> " has been removed."
139 describeIssue Backward (EnumValueNotConsumed _ v) =
142 describeIssue Backward (EnumValueNotConsumed _ v) =
src/Data/OpenApi/Compare/Validate/Sums.hsnew file+25
@@ -0,0 +1,25 @@
1+module Data.OpenApi.Compare.Validate.Sums
2+ ( checkSums,
3+ )
4+where
5+
6+import Data.Foldable
7+import Data.Map.Strict (Map)
8+import qualified Data.Map.Strict as M
9+import Data.OpenApi.Compare.Behavior
10+import Data.OpenApi.Compare.Paths
11+import Data.OpenApi.Compare.Subtree
12+
13+checkSums ::
14+ (Ord k, Issuable l) =>
15+ Paths q r l ->
16+ (k -> Issue l) ->
17+ (k -> ProdCons t -> CompatFormula' q AnIssue r ()) ->
18+ ProdCons (Map k t) ->
19+ CompatFormula' q AnIssue r ()
20+checkSums xs noElt check (ProdCons p c) = for_ (M.toList p) $ \(key, prodElt) ->
21+ case M.lookup key c of
22+ Nothing -> issueAt xs $ noElt key
23+ Just consElt ->
24+ let sumElts = ProdCons prodElt consElt
25+ in check key sumElts
src/Data/OpenUnion/Extra.hs+5โˆ’5
@@ -1,7 +1,7 @@
1module Data.OpenUnion.Extra
1module Data.OpenUnion.Extra
2โˆ’ ( (@@>)
2+ ( (@@>),
3โˆ’ , TryLiftUnion (..)
3+ TryLiftUnion (..),
4โˆ’ , pattern SingletonUnion
4+ pattern SingletonUnion,
5 )
5 )
6where
6where
7
7
@@ -18,8 +18,8 @@ instance TryLiftUnion '[] where
18 tryLiftUnion _ = empty
18 tryLiftUnion _ = empty
19
19
20instance
20instance
21โˆ’ (Typeable y, SubList ys (y : ys), TryLiftUnion ys)
21+ (Typeable y, SubList ys (y : ys), TryLiftUnion ys) =>
22โˆ’ => TryLiftUnion (y ': ys)
22+ TryLiftUnion (y ': ys)
23 where
23 where
24 tryLiftUnion (x :: x) = case eqT @x @y of
24 tryLiftUnion (x :: x) = case eqT @x @y of
25 Nothing -> reUnion <$> tryLiftUnion @ys x
25 Nothing -> reUnion <$> tryLiftUnion @ys x
src/OpenAPI/Checker/Behavior.hsdeletedโˆ’83
@@ -1,83 +0,0 @@
1โˆ’module OpenAPI.Checker.Behavior
2โˆ’ ( BehaviorLevel (..)
3โˆ’ , Behavable (..)
4โˆ’ , Issuable (..)
5โˆ’ , Orientation (..)
6โˆ’ , toggleOrientation
7โˆ’ , Behavior
8โˆ’ , AnIssue (..)
9โˆ’ )
10โˆ’where
11โˆ’
12โˆ’import Data.Aeson
13โˆ’import Data.Kind
14โˆ’import Data.Typeable
15โˆ’import OpenAPI.Checker.Paths
16โˆ’import Text.Pandoc.Builder
17โˆ’
18โˆ’-- | Kind
19โˆ’data BehaviorLevel
20โˆ’ = APILevel
21โˆ’ | ServerLevel
22โˆ’ | SecurityRequirementLevel
23โˆ’ | SecuritySchemeLevel
24โˆ’ | PathLevel
25โˆ’ | OperationLevel
26โˆ’ | PathFragmentLevel
27โˆ’ | RequestLevel
28โˆ’ | ResponseLevel
29โˆ’ | HeaderLevel
30โˆ’ | -- | either request or response data
31โˆ’ PayloadLevel
32โˆ’ | SchemaLevel
33โˆ’ | TypedSchemaLevel
34โˆ’ | LinkLevel
35โˆ’ | CallbackLevel
36โˆ’
37โˆ’class
38โˆ’ (Ord (Behave a b), Show (Behave a b)) =>
39โˆ’ Behavable (a :: BehaviorLevel) (b :: BehaviorLevel)
40โˆ’ where
41โˆ’ data Behave a b
42โˆ’ describeBehaviour :: Behave a b -> Inlines
43โˆ’
44โˆ’type instance AdditionalQuiverConstraints Behave a b = Behavable a b
45โˆ’
46โˆ’class (Typeable l, Ord (Issue l), Show (Issue l)) => Issuable (l :: BehaviorLevel) where
47โˆ’ data Issue l :: Type
48โˆ’
49โˆ’ -- | The same issues can be rendered in multiple places and might
50โˆ’ -- require different ways of represnting them to the user.
51โˆ’ --
52โˆ’ -- In practice each issue requires a maximum of two different representations:
53โˆ’ -- based on the context the issue might need to be rendered as "opposite" ('Backward')
54โˆ’ -- โ€“ for example when rendering non-breaking changes everything should be
55โˆ’ -- reversed (a consequence of the way we generate non-breaking changes).
56โˆ’ describeIssue :: Orientation -> Issue l -> Blocks
57โˆ’
58โˆ’ issueIsUnsupported :: Issue l -> Bool
59โˆ’
60โˆ’data Orientation = Forward | Backward
61โˆ’ deriving stock (Eq, Ord)
62โˆ’
63โˆ’toggleOrientation :: Orientation -> Orientation
64โˆ’toggleOrientation Forward = Backward
65โˆ’toggleOrientation Backward = Forward
66โˆ’
67โˆ’-- | A set of interactions having common unifying features
68โˆ’type Behavior = Paths Behave 'APILevel
69โˆ’
70โˆ’instance Issuable l => ToJSON (Issue l) where
71โˆ’ toJSON = toJSON . show
72โˆ’
73โˆ’data AnIssue (l :: BehaviorLevel) where
74โˆ’ AnIssue :: Issuable l => Issue l -> AnIssue l
75โˆ’
76โˆ’deriving stock instance Show (AnIssue l)
77โˆ’
78โˆ’deriving stock instance Eq (AnIssue l)
79โˆ’
80โˆ’deriving stock instance Ord (AnIssue l)
81โˆ’
82โˆ’instance ToJSON (AnIssue l) where
83โˆ’ toJSON (AnIssue issue) = toJSON issue
src/OpenAPI/Checker/Memo.hsdeletedโˆ’126
@@ -1,126 +0,0 @@
1โˆ’{-# LANGUAGE AllowAmbiguousTypes #-}
2โˆ’-- | Utilities for effectfully memoizing other, more effectful functions.
3โˆ’module OpenAPI.Checker.Memo
4โˆ’ ( MonadMemo
5โˆ’ , MemoState
6โˆ’ , runMemo
7โˆ’ , modifyMemoNonce
8โˆ’ , KnotTier(..)
9โˆ’ , unknot
10โˆ’ , memoWithKnot
11โˆ’ , memoTaggedWithKnot
12โˆ’ ) where
13โˆ’
14โˆ’import Control.Monad.State
15โˆ’import Data.Dynamic
16โˆ’import qualified Data.Map as M
17โˆ’import Data.Tagged
18โˆ’import Data.Void
19โˆ’import qualified Data.TypeRepMap as T
20โˆ’import Type.Reflection
21โˆ’
22โˆ’data Progress a = Finished a | Started | TyingKnot Dynamic
23โˆ’
24โˆ’data MemoMap a where
25โˆ’ MemoMap :: !(M.Map k (Progress v)) -> MemoMap (k, v)
26โˆ’
27โˆ’data MemoState s = MemoState s (T.TypeRepMap MemoMap)
28โˆ’
29โˆ’-- | An effectful memoization monad.
30โˆ’type MonadMemo s m = MonadState (MemoState s) m
31โˆ’
32โˆ’memoStateLookup
33โˆ’ :: forall k v s. (Typeable k, Typeable v, Ord k)
34โˆ’ => k -> MemoState s -> Maybe (Progress v)
35โˆ’memoStateLookup k (MemoState _ t) = case T.lookup @(k, v) t of
36โˆ’ Just (MemoMap m) -> M.lookup k m
37โˆ’ Nothing -> Nothing
38โˆ’
39โˆ’memoStateInsert
40โˆ’ :: forall k v s. (Typeable k, Typeable v, Ord k)
41โˆ’ => k -> Progress v -> MemoState s -> MemoState s
42โˆ’memoStateInsert k x (MemoState s t) = MemoState s $ T.insert (MemoMap m'') t
43โˆ’ where
44โˆ’ m'' = M.insert k x m'
45โˆ’ m' = case T.lookup @(k, v) t of
46โˆ’ Just (MemoMap m) -> m
47โˆ’ Nothing -> M.empty
48โˆ’
49โˆ’modifyMemoNonce :: MonadMemo s m => (s -> s) -> m s
50โˆ’modifyMemoNonce f = do
51โˆ’ MemoState s t <- get
52โˆ’ put $ MemoState (f s) t
53โˆ’ pure s
54โˆ’
55โˆ’-- | Run a memoized computation.
56โˆ’runMemo :: Monad m => s -> StateT (MemoState s) m a -> m a
57โˆ’runMemo s = (`evalStateT` MemoState s T.empty)
58โˆ’
59โˆ’-- | A description of how to effectfully tie knots in type @v@, using the @m@
60โˆ’-- monad, and by sharing some @d@ data among the recursive instances.
61โˆ’data KnotTier v d m = KnotTier
62โˆ’ { onKnotFound :: m d -- ^ Create some data that will be connected to this knot
63โˆ’ , onKnotUsed :: d -> m v -- ^ This is what the knot will look like as a value
64โˆ’ -- to the inner computations
65โˆ’ , tieKnot :: d -> v -> m v -- ^ Once we're done and we're outside, tie the
66โˆ’ -- knot using the datum
67โˆ’ }
68โˆ’
69โˆ’unknot :: KnotTier v Void m
70โˆ’unknot = KnotTier
71โˆ’ { onKnotFound = error "Recursion detected"
72โˆ’ , onKnotUsed = absurd
73โˆ’ , tieKnot = absurd
74โˆ’ }
75โˆ’
76โˆ’-- | Run a potentially recursive computation. The provided key will be used to
77โˆ’-- refer to the result of this computation. If during the computation, another
78โˆ’-- attempt to run the computation with the same key is made, we run a
79โˆ’-- tying-the-knot procedure.
80โˆ’--
81โˆ’-- If another attempt to run the computation with the same key is made
82โˆ’-- *after we're done*, we will return the memoized value.
83โˆ’memoWithKnot
84โˆ’ :: forall k v d m s.
85โˆ’ (Typeable k, Typeable v, Typeable d, Ord k, MonadMemo s m)
86โˆ’ => KnotTier v d m
87โˆ’ -> m v -- ^ the computation to memoize
88โˆ’ -> k -- ^ key for memoization
89โˆ’ -> m v
90โˆ’memoWithKnot tier f k = memoStateLookup @k @v k <$> get >>= \case
91โˆ’ Just (Finished v) -> pure v
92โˆ’ Just Started -> do
93โˆ’ d <- onKnotFound tier
94โˆ’ modify $ memoStateInsert @k @v k (TyingKnot $ toDyn d)
95โˆ’ onKnotUsed tier d
96โˆ’ Just (TyingKnot dyn) -> case fromDynamic dyn of
97โˆ’ Just d -> onKnotUsed tier d
98โˆ’ Nothing -> error $ "Type mismatch when examining the knot of "
99โˆ’ <> show (typeRep @(k -> v)) <> ": expected " <> show (typeRep @d)
100โˆ’ <> ", got " <> show (dynTypeRep dyn)
101โˆ’ Nothing -> do
102โˆ’ modify $ memoStateInsert @k @v k Started
103โˆ’ v <- f
104โˆ’ v' <- memoStateLookup @k @v k <$> get >>= \case
105โˆ’ Just Started -> pure v
106โˆ’ Just (TyingKnot dyn) -> case fromDynamic dyn of
107โˆ’ Just d -> tieKnot tier d v
108โˆ’ Nothing -> error $ "Type mismatch when tying the knot of "
109โˆ’ <> show (typeRep @(k -> v)) <> ": expected " <> show (typeRep @d)
110โˆ’ <> ", got " <> show (dynTypeRep dyn)
111โˆ’ Just (Finished _) -> error $ "Unexpected Finished when memoizing "
112โˆ’ <> show (typeRep @(k -> v))
113โˆ’ Nothing -> pure v
114โˆ’ -- Normally this would be an error, but the underlying monad can refuse
115โˆ’ -- to remember memoization state
116โˆ’ modify $ memoStateInsert @k @v k (Finished v')
117โˆ’ pure v'
118โˆ’
119โˆ’-- | Disambiguate memoized computations with an arbitrary tag.
120โˆ’memoTaggedWithKnot
121โˆ’ :: forall t k v d m s.
122โˆ’ ( Typeable t, Typeable k, Typeable v, Typeable d
123โˆ’ , Ord k, MonadMemo s m )
124โˆ’ => KnotTier v d m -> m v -> k -> m v
125โˆ’memoTaggedWithKnot tier f k = withTypeable (typeRepKind $ typeRep @t) $
126โˆ’ memoWithKnot tier f (Tagged @t k)
src/OpenAPI/Checker/Report.hsdeletedโˆ’283
@@ -1,283 +0,0 @@
1โˆ’module OpenAPI.Checker.Report
2โˆ’ ( generateReport
3โˆ’ , ReportInput (..)
4โˆ’ , ReportStatus (..)
5โˆ’ , Pandoc
6โˆ’ )
7โˆ’where
8โˆ’
9โˆ’import Control.Monad.Free hiding (unfoldM)
10โˆ’import Control.Monad.Reader
11โˆ’import Control.Monad.Writer
12โˆ’import Data.Aeson (ToJSON)
13โˆ’import Data.Either
14โˆ’import Data.Foldable
15โˆ’import Data.Function
16โˆ’import Data.Functor
17โˆ’import Data.Functor.Const
18โˆ’import Data.List.NonEmpty
19โˆ’import qualified Data.List.NonEmpty as NE
20โˆ’import qualified Data.Map as M
21โˆ’import Data.Maybe
22โˆ’import Data.OpenUnion
23โˆ’import Data.OpenUnion.Extra
24โˆ’import Data.Set
25โˆ’import qualified Data.Set as S
26โˆ’import Data.Text (Text)
27โˆ’import qualified Data.Text as T
28โˆ’import Data.TypeRepMap hiding (empty)
29โˆ’import Data.Typeable
30โˆ’import Generic.Data
31โˆ’import OpenAPI.Checker.Behavior
32โˆ’import OpenAPI.Checker.Paths
33โˆ’import OpenAPI.Checker.PathsPrefixTree hiding (empty)
34โˆ’import qualified OpenAPI.Checker.PathsPrefixTree as P hiding (empty)
35โˆ’import OpenAPI.Checker.Report.Jet
36โˆ’import OpenAPI.Checker.Validate.OpenApi
37โˆ’import OpenAPI.Checker.Validate.Schema
38โˆ’import Text.Pandoc.Builder
39โˆ’
40โˆ’type Changes = P.PathsPrefixTree Behave AnIssue 'APILevel
41โˆ’
42โˆ’type ProcessedChanges a = P.PathsPrefixTree Behave (FunctorTuple (Const Orientation) AnIssue) a
43โˆ’
44โˆ’data FunctorTuple f g a = FunctorTuple (f a) (g a)
45โˆ’ deriving stock (Eq, Ord)
46โˆ’
47โˆ’data ReportInput = ReportInput
48โˆ’ { breakingChanges :: Changes
49โˆ’ , nonBreakingChanges :: Changes
50โˆ’ }
51โˆ’ deriving stock (Generic)
52โˆ’ deriving (Semigroup, Monoid) via (Generically ReportInput)
53โˆ’ deriving anyclass (ToJSON)
54โˆ’
55โˆ’data ReportStatus
56โˆ’ = BreakingChanges
57โˆ’ | NoBreakingChanges
58โˆ’ | -- | All changes that could be breaking are unsupported โ€“ we don't know if
59โˆ’ -- there actually are any breaking changes.
60โˆ’ OnlyUnsupportedChanges
61โˆ’
62โˆ’preprocessChanges :: Orientation -> Changes -> ProcessedChanges 'APILevel
63โˆ’preprocessChanges initialO = P.fromList . fmap process . P.toList
64โˆ’ where
65โˆ’ process :: AnItem Behave AnIssue 'APILevel -> AnItem Behave (FunctorTuple (Const Orientation) AnIssue) 'APILevel
66โˆ’ process (AnItem paths issue) = AnItem paths $ FunctorTuple (Const $ toggle initialO) issue
67โˆ’ where
68โˆ’ (Endo toggle) = togglePaths paths
69โˆ’
70โˆ’ togglePaths :: Paths Behave a c -> Endo Orientation
71โˆ’ togglePaths Root = mempty
72โˆ’ togglePaths (rest `Snoc` (_ :: Behave b c)) = case eqT @c @'ResponseLevel of
73โˆ’ Just Refl -> Endo toggleOrientation <> togglePaths rest
74โˆ’ Nothing -> togglePaths rest
75โˆ’
76โˆ’generateReport :: ReportInput -> (Pandoc, ReportStatus)
77โˆ’generateReport inp =
78โˆ’ let partitionUnsupported = P.partition (\(AnIssue i) -> issueIsUnsupported i)
79โˆ’ (bUnsupported, preprocessChanges Forward -> breaking) =
80โˆ’ partitionUnsupported $ breakingChanges inp
81โˆ’ (nbUnsupported, preprocessChanges Backward -> nonBreaking) =
82โˆ’ partitionUnsupported $ nonBreakingChanges inp
83โˆ’ unsupported = preprocessChanges Forward $ bUnsupported <> nbUnsupported
84โˆ’ breakingChangesPresent = not $ P.null breaking
85โˆ’ nonBreakingChangesPresent = not $ P.null nonBreaking
86โˆ’ unsupportedChangesPresent = not $ P.null unsupported
87โˆ’ report = doc $
88โˆ’ runReportMonad jets $ do
89โˆ’ smartHeader "Summary"
90โˆ’ tell $
91โˆ’ simpleTable
92โˆ’ (para
93โˆ’ <$> [ refOpt breakingChangesPresent breakingChangesId "โš ๏ธ Breaking changes"
94โˆ’ , refOpt nonBreakingChangesPresent nonBreakingChangesId "๐Ÿ™† Non-breaking changes"
95โˆ’ , refOpt unsupportedChangesPresent unsupportedChangesId "๐Ÿคท Unsupported feature changes"
96โˆ’ ])
97โˆ’ [para . show' <$> [P.size breaking, P.size nonBreaking, P.size unsupported]]
98โˆ’ when breakingChangesPresent $ do
99โˆ’ smartHeader $ anchor breakingChangesId <> "โš ๏ธ Breaking changes"
100โˆ’ incrementHeaders $ showErrs breaking
101โˆ’ when nonBreakingChangesPresent $ do
102โˆ’ smartHeader $ anchor nonBreakingChangesId <> "๐Ÿ™† Non-breaking changes"
103โˆ’ incrementHeaders $ showErrs nonBreaking
104โˆ’ when unsupportedChangesPresent $ do
105โˆ’ smartHeader $ anchor unsupportedChangesId <> "๐Ÿคท Unsupported feature changes"
106โˆ’ incrementHeaders $ showErrs unsupported
107โˆ’ status =
108โˆ’ if
109โˆ’ | breakingChangesPresent -> BreakingChanges
110โˆ’ | unsupportedChangesPresent -> OnlyUnsupportedChanges
111โˆ’ | otherwise -> NoBreakingChanges
112โˆ’ in (report, status)
113โˆ’ where
114โˆ’ anchor :: Text -> Inlines
115โˆ’ anchor a = spanWith (a, [], []) mempty
116โˆ’
117โˆ’ refOpt :: Bool -> Text -> Inlines -> Inlines
118โˆ’ refOpt False _ i = i
119โˆ’ refOpt True a i = link ("#" <> a) "" i
120โˆ’
121โˆ’ breakingChangesId, nonBreakingChangesId, unsupportedChangesId :: Text
122โˆ’ breakingChangesId = "breaking-changes"
123โˆ’ unsupportedChangesId = "unsupported-changes"
124โˆ’ nonBreakingChangesId = "non-breaking-changes"
125โˆ’
126โˆ’data ReportState = ReportState
127โˆ’ { sourceJets :: [ReportJet' Behave Inlines]
128โˆ’ , headerLevel :: Int
129โˆ’ }
130โˆ’
131โˆ’type ReportMonad = ReaderT ReportState (Writer Blocks)
132โˆ’
133โˆ’runReportMonad :: [ReportJet' Behave Inlines] -> ReportMonad () -> Blocks
134โˆ’runReportMonad jts =
135โˆ’ execWriter
136โˆ’ . flip
137โˆ’ runReaderT
138โˆ’ ReportState
139โˆ’ { sourceJets = jts
140โˆ’ , headerLevel = 1
141โˆ’ }
142โˆ’
143โˆ’smartHeader :: Inlines -> ReportMonad ()
144โˆ’smartHeader i = do
145โˆ’ h <- asks headerLevel
146โˆ’ tell $ header h i
147โˆ’
148โˆ’showErrs :: forall a. Typeable a => ProcessedChanges a -> ReportMonad ()
149โˆ’showErrs x@(P.PathsPrefixNode currentIssues _) = do
150โˆ’ let -- Extract this pattern if more cases like this arise
151โˆ’ ( removedPaths :: Maybe (Orientation, [Issue 'APILevel])
152โˆ’ , otherIssues :: Set (FunctorTuple (Const Orientation) AnIssue a)
153โˆ’ ) = case eqT @a @'APILevel of
154โˆ’ Just Refl
155โˆ’ | (S.toList -> p@(FunctorTuple (Const ori) _ : _), o) <-
156โˆ’ S.partition
157โˆ’ (\(FunctorTuple _ (AnIssue u)) -> case u of
158โˆ’ NoPathsMatched {} -> True
159โˆ’ AllPathsFailed {} -> True)
160โˆ’ currentIssues ->
161โˆ’ let p' = p <&> (\(FunctorTuple _ (AnIssue i)) -> i)
162โˆ’ in (Just (ori, p'), o)
163โˆ’ _ -> (Nothing, currentIssues)
164โˆ’ jts <- asks sourceJets
165โˆ’ for_ otherIssues $ \(FunctorTuple (Const ori) (AnIssue i)) -> tell . describeIssue ori $ i
166โˆ’ case removedPaths of
167โˆ’ Just (ori, paths) -> do
168โˆ’ smartHeader $ case ori of
169โˆ’ Forward -> "Removed paths"
170โˆ’ Backward -> "Added paths"
171โˆ’ tell $
172โˆ’ bulletList $
173โˆ’ paths <&> \case
174โˆ’ (NoPathsMatched p) -> para . code $ T.pack p
175โˆ’ (AllPathsFailed p) -> para . code $ T.pack p
176โˆ’ Nothing -> pure ()
177โˆ’ unfoldM x (observeJetShowErrs <$> jts) $ \(P.PathsPrefixNode _ subIssues) -> do
178โˆ’ for_ subIssues $ \(WrapTypeable (AStep m)) ->
179โˆ’ for_ (M.toList m) $ \(bhv, subErrors) -> do
180โˆ’ unless (P.null subErrors) $ do
181โˆ’ smartHeader $ describeBehaviour bhv
182โˆ’ incrementHeaders $ showErrs subErrors
183โˆ’
184โˆ’unfoldM :: Monad m => a -> [a -> m a] -> (a -> m ()) -> m ()
185โˆ’unfoldM a [] g = g a
186โˆ’unfoldM a (f : ff) g = do
187โˆ’ a' <- f a
188โˆ’ unfoldM a' ff g
189โˆ’
190โˆ’incrementHeaders :: ReportMonad x -> ReportMonad x
191โˆ’incrementHeaders m = do
192โˆ’ l <- asks headerLevel
193โˆ’ local (\x -> x {headerLevel = l + 1}) m
194โˆ’
195โˆ’jets :: [ReportJet' Behave Inlines]
196โˆ’jets =
197โˆ’ unwrapReportJetResult
198โˆ’ <$> [ constructReportJet jsonPathJet
199โˆ’ , constructReportJet $ \p@(AtPath _) op@(InOperation _) ->
200โˆ’ strong (describeBehaviour op) <> " " <> describeBehaviour p :: Inlines
201โˆ’ , constructReportJet $ \InRequest InPayload PayloadSchema -> "๐Ÿ“ฑโžก๏ธ JSON Request" :: Inlines
202โˆ’ , constructReportJet $ \(WithStatusCode c) ResponsePayload PayloadSchema ->
203โˆ’ "๐Ÿ“ฑโฌ…๏ธ JSON Response โ€“ " <> str (T.pack . show $ c) :: Inlines
204โˆ’ ]
205โˆ’ where
206โˆ’ unwrapReportJetResult :: ReportJetResult Behave x -> ReportJet' Behave x
207โˆ’ unwrapReportJetResult (Pure _) = error "There really shouldn't be any results here."
208โˆ’ unwrapReportJetResult (Free f) = f
209โˆ’
210โˆ’ jsonPathJet
211โˆ’ :: NonEmpty
212โˆ’ ( Union
213โˆ’ '[ Behave 'SchemaLevel 'TypedSchemaLevel
214โˆ’ , Behave 'TypedSchemaLevel 'SchemaLevel
215โˆ’ ]
216โˆ’ )
217โˆ’ -> Inlines
218โˆ’ jsonPathJet x = code $ "$" <> showParts (NE.toList x)
219โˆ’ where
220โˆ’ showParts
221โˆ’ :: [ Union
222โˆ’ '[ Behave 'SchemaLevel 'TypedSchemaLevel
223โˆ’ , Behave 'TypedSchemaLevel 'SchemaLevel
224โˆ’ ]
225โˆ’ ]
226โˆ’ -> Text
227โˆ’ showParts [] = mempty
228โˆ’ showParts (SingletonUnion (OfType Object) : xs@((SingletonUnion (InProperty _)) : _)) = showParts xs
229โˆ’ showParts (SingletonUnion (OfType Object) : xs@((SingletonUnion InAdditionalProperty) : _)) = showParts xs
230โˆ’ showParts (SingletonUnion (OfType Array) : xs@(SingletonUnion InItems : _)) = showParts xs
231โˆ’ showParts (y : ys) =
232โˆ’ ((\(OfType t) -> "(" <> describeJSONType t <> ")")
233โˆ’ @@> (\case
234โˆ’ InItems -> "[*]"
235โˆ’ InProperty p -> "." <> p
236โˆ’ InAdditionalProperty -> ".*")
237โˆ’ @@> typesExhausted)
238โˆ’ y
239โˆ’ <> showParts ys
240โˆ’
241โˆ’observeJetShowErrs
242โˆ’ :: ReportJet' Behave Inlines
243โˆ’ -> ProcessedChanges a
244โˆ’ -> ReportMonad (ProcessedChanges a)
245โˆ’observeJetShowErrs jet p = case observeJetShowErrs' jet p of
246โˆ’ Just m -> m
247โˆ’ Nothing -> pure p
248โˆ’
249โˆ’observeJetShowErrs'
250โˆ’ :: forall a.
251โˆ’ ReportJet' Behave Inlines
252โˆ’ -> ProcessedChanges a
253โˆ’ -> Maybe (ReportMonad (ProcessedChanges a))
254โˆ’observeJetShowErrs' (ReportJet jet) (P.PathsPrefixNode currentIssues subIssues) =
255โˆ’ let results =
256โˆ’ subIssues >>= \(WrapTypeable (AStep m)) ->
257โˆ’ M.toList m <&> \(bhv, subErrs) ->
258โˆ’ maybe (Left $ embed (step bhv) subErrs) Right . listToMaybe $
259โˆ’ jet @_ @_ @[] bhv
260โˆ’ & mapMaybe
261โˆ’ (\case
262โˆ’ Free jet' -> fmap (embed $ step bhv) <$> observeJetShowErrs' jet' subErrs
263โˆ’ Pure h -> Just $ do
264โˆ’ unless (P.null subErrs) $ do
265โˆ’ smartHeader h
266โˆ’ incrementHeaders $ showErrs subErrs
267โˆ’ return mempty)
268โˆ’ in (fmap . fmap) (PathsPrefixNode currentIssues mempty <>) $
269โˆ’ if any isRight results
270โˆ’ then
271โˆ’ Just $
272โˆ’ catMapM
273โˆ’ (\case
274โˆ’ Left e -> pure e
275โˆ’ Right m -> m)
276โˆ’ results
277โˆ’ else Nothing
278โˆ’
279โˆ’catMapM :: (Monad m, Monoid b) => (a -> m b) -> [a] -> m b
280โˆ’catMapM f xs = mconcat <$> mapM f xs
281โˆ’
282โˆ’show' :: Show x => x -> Inlines
283โˆ’show' = str . T.pack . show
src/OpenAPI/Checker/Run.hsdeletedโˆ’30
@@ -1,30 +0,0 @@
1โˆ’module OpenAPI.Checker.Run
2โˆ’ ( runChecker
3โˆ’ , runReport
4โˆ’ , module OpenAPI.Checker.Report
5โˆ’ )
6โˆ’where
7โˆ’
8โˆ’import Data.HList
9โˆ’import Data.OpenApi (OpenApi)
10โˆ’import OpenAPI.Checker.Paths
11โˆ’import OpenAPI.Checker.Report
12โˆ’import OpenAPI.Checker.Subtree
13โˆ’import OpenAPI.Checker.Validate.OpenApi ()
14โˆ’
15โˆ’runChecker :: (OpenApi, OpenApi) -> ReportInput
16โˆ’runChecker (client, server) =
17โˆ’ ReportInput
18โˆ’ { breakingChanges = run client server
19โˆ’ , nonBreakingChanges = run server client
20โˆ’ }
21โˆ’ where
22โˆ’ toPC p c =
23โˆ’ ProdCons
24โˆ’ { producer = traced (step ClientSchema) p
25โˆ’ , consumer = traced (step ServerSchema) c
26โˆ’ }
27โˆ’ run p c = either id mempty . runCompatFormula . checkCompatibility HNil Root $ toPC p c
28โˆ’
29โˆ’runReport :: (OpenApi, OpenApi) -> (Pandoc, ReportStatus)
30โˆ’runReport = generateReport . runChecker
src/OpenAPI/Checker/Subtree.hsdeletedโˆ’314
@@ -1,314 +0,0 @@
1โˆ’{-# OPTIONS_GHC -Wno-orphans #-}
2โˆ’
3โˆ’module OpenAPI.Checker.Subtree
4โˆ’ ( Steppable (..)
5โˆ’ , Step (..)
6โˆ’ , TraceRoot
7โˆ’ , Trace
8โˆ’ , Traced
9โˆ’ , Traced'
10โˆ’ , pattern Traced
11โˆ’ , traced
12โˆ’ , retraced
13โˆ’ , stepTraced
14โˆ’ , Subtree (..)
15โˆ’ , checkCompatibility
16โˆ’ , checkSubstructure
17โˆ’ , CompatM (..)
18โˆ’ , CompatFormula'
19โˆ’ , SemanticCompatFormula
20โˆ’ , ProdCons (..)
21โˆ’ , HasUnsupportedFeature (..)
22โˆ’ , swapProdCons
23โˆ’ , runCompatFormula
24โˆ’ , issueAt
25โˆ’ , anyOfAt
26โˆ’ , structuralIssue
27โˆ’
28โˆ’ -- * Structural helpers
29โˆ’ , structuralMaybe
30โˆ’ , structuralMaybeWith
31โˆ’ , structuralEq
32โˆ’ , iohmStructural
33โˆ’ , iohmStructuralWith
34โˆ’ , structuralList
35โˆ’
36โˆ’ -- * Reexports
37โˆ’ , (>>>)
38โˆ’ , (<<<)
39โˆ’ , extract
40โˆ’ , ask
41โˆ’ , local
42โˆ’ , step
43โˆ’ , Typeable
44โˆ’ )
45โˆ’where
46โˆ’
47โˆ’import Control.Comonad.Env
48โˆ’import Control.Monad.Identity
49โˆ’import Control.Monad.State
50โˆ’import Data.Foldable
51โˆ’import Data.Functor.Compose
52โˆ’import Data.HList
53โˆ’import qualified Data.HashMap.Strict.InsOrd as IOHM
54โˆ’import Data.Hashable
55โˆ’import Data.Kind
56โˆ’import Data.Monoid
57โˆ’import Data.OpenApi
58โˆ’import qualified Data.Set as S
59โˆ’import Data.Typeable
60โˆ’import OpenAPI.Checker.Behavior
61โˆ’import OpenAPI.Checker.Formula
62โˆ’import OpenAPI.Checker.Memo
63โˆ’import OpenAPI.Checker.Paths
64โˆ’import qualified OpenAPI.Checker.PathsPrefixTree as P
65โˆ’
66โˆ’class
67โˆ’ (Typeable Step, Typeable a, Typeable b, Ord (Step a b), Show (Step a b)) =>
68โˆ’ Steppable (a :: Type) (b :: Type)
69โˆ’ where
70โˆ’ -- | How to get from an @a@ node to a @b@ node
71โˆ’ data Step a b :: Type
72โˆ’
73โˆ’data TraceRoot
74โˆ’
75โˆ’instance Steppable TraceRoot OpenApi where
76โˆ’ data Step TraceRoot OpenApi
77โˆ’ = ClientSchema
78โˆ’ | ServerSchema
79โˆ’ deriving stock (Eq, Ord, Show)
80โˆ’
81โˆ’type Trace = Paths Step TraceRoot
82โˆ’
83โˆ’type instance AdditionalQuiverConstraints Step _ _ = ()
84โˆ’
85โˆ’type Traced' a b = Env (Trace a) b
86โˆ’
87โˆ’type Traced a = Traced' a a
88โˆ’
89โˆ’pattern Traced :: Trace a -> b -> Traced' a b
90โˆ’pattern Traced t x = EnvT t (Identity x)
91โˆ’
92โˆ’{-# COMPLETE Traced #-}
93โˆ’
94โˆ’traced :: Trace a -> a -> Traced a
95โˆ’traced = env
96โˆ’
97โˆ’retraced :: (Trace a -> Trace a') -> Traced' a b -> Traced' a' b
98โˆ’retraced f (Traced a b) = Traced (f a) b
99โˆ’
100โˆ’stepTraced :: Steppable a a' => Step a a' -> Traced' a b -> Traced' a' b
101โˆ’stepTraced s = retraced (>>> step s)
102โˆ’
103โˆ’data ProdCons a = ProdCons
104โˆ’ { producer :: a
105โˆ’ , consumer :: a
106โˆ’ }
107โˆ’ deriving stock (Eq, Ord, Show, Functor, Foldable, Traversable)
108โˆ’
109โˆ’swapProdCons :: ProdCons a -> ProdCons a
110โˆ’swapProdCons (ProdCons a b) = ProdCons b a
111โˆ’
112โˆ’instance Applicative ProdCons where
113โˆ’ pure x = ProdCons x x
114โˆ’ ProdCons fp fc <*> ProdCons xp xc = ProdCons (fp xp) (fc xc)
115โˆ’
116โˆ’newtype CompatM a = CompatM
117โˆ’ { unCompatM
118โˆ’ :: StateT (MemoState VarRef) Identity a
119โˆ’ }
120โˆ’ deriving newtype
121โˆ’ ( Functor
122โˆ’ , Applicative
123โˆ’ , Monad
124โˆ’ , MonadState (MemoState VarRef)
125โˆ’ )
126โˆ’
127โˆ’type CompatFormula' q f r = Compose CompatM (FormulaF q f r)
128โˆ’
129โˆ’type SemanticCompatFormula = CompatFormula' Behave AnIssue 'APILevel
130โˆ’
131โˆ’type StructuralCompatFormula = CompatFormula' VoidQuiver Proxy ()
132โˆ’
133โˆ’data VoidQuiver a b
134โˆ’
135โˆ’deriving stock instance Eq (VoidQuiver a b)
136โˆ’
137โˆ’type instance AdditionalQuiverConstraints VoidQuiver _ _ = ()
138โˆ’
139โˆ’deriving stock instance Ord (VoidQuiver a b)
140โˆ’
141โˆ’deriving stock instance Show (VoidQuiver a b)
142โˆ’
143โˆ’class (Typeable t, Issuable (SubtreeLevel t)) => Subtree (t :: Type) where
144โˆ’ type CheckEnv t :: [Type]
145โˆ’ type SubtreeLevel t :: BehaviorLevel
146โˆ’
147โˆ’ checkStructuralCompatibility
148โˆ’ :: (HasAll (CheckEnv t) xs)
149โˆ’ => HList xs
150โˆ’ -> ProdCons (Traced t)
151โˆ’ -> StructuralCompatFormula ()
152โˆ’
153โˆ’ checkSemanticCompatibility
154โˆ’ :: (HasAll (CheckEnv t) xs)
155โˆ’ => HList xs
156โˆ’ -> Behavior (SubtreeLevel t)
157โˆ’ -> ProdCons (Traced t)
158โˆ’ -> SemanticCompatFormula ()
159โˆ’
160โˆ’{-# WARNING checkStructuralCompatibility "You should not be calling this directly. Use 'checkSubstructure'" #-}
161โˆ’
162โˆ’{-# WARNING checkSemanticCompatibility "You should not be calling this directly. Use 'checkCompatibility'" #-}
163โˆ’
164โˆ’checkCompatibility
165โˆ’ :: (HasAll (CheckEnv t) xs, Subtree t)
166โˆ’ => HList xs
167โˆ’ -> Behavior (SubtreeLevel t)
168โˆ’ -> ProdCons (Traced t)
169โˆ’ -> SemanticCompatFormula ()
170โˆ’checkCompatibility e bhv = memo bhv SemanticMemoKey $ \pc ->
171โˆ’ case runCompatFormula $ checkSubstructure e pc of
172โˆ’ Left _ -> checkSemanticCompatibility e bhv pc
173โˆ’ Right () -> pure ()
174โˆ’
175โˆ’checkSubstructure
176โˆ’ :: (HasAll (CheckEnv t) xs, Subtree t)
177โˆ’ => HList xs
178โˆ’ -> ProdCons (Traced t)
179โˆ’ -> StructuralCompatFormula ()
180โˆ’checkSubstructure e = memo Root StructuralMemoKey $ checkStructuralCompatibility e
181โˆ’
182โˆ’structuralMaybe
183โˆ’ :: (Subtree a, HasAll (CheckEnv a) xs)
184โˆ’ => HList xs
185โˆ’ -> ProdCons (Maybe (Traced a))
186โˆ’ -> StructuralCompatFormula ()
187โˆ’structuralMaybe e = structuralMaybeWith (checkSubstructure e)
188โˆ’
189โˆ’structuralMaybeWith
190โˆ’ :: (ProdCons a -> StructuralCompatFormula ())
191โˆ’ -> ProdCons (Maybe a)
192โˆ’ -> StructuralCompatFormula ()
193โˆ’structuralMaybeWith f (ProdCons (Just a) (Just b)) = f $ ProdCons a b
194โˆ’structuralMaybeWith _ (ProdCons Nothing Nothing) = pure ()
195โˆ’structuralMaybeWith _ _ = structuralIssue
196โˆ’
197โˆ’structuralList
198โˆ’ :: (Subtree a, HasAll (CheckEnv a) xs)
199โˆ’ => HList xs
200โˆ’ -> ProdCons [Traced a]
201โˆ’ -> StructuralCompatFormula ()
202โˆ’structuralList _ (ProdCons [] []) = pure ()
203โˆ’structuralList e (ProdCons (a : aa) (b : bb)) = do
204โˆ’ checkSubstructure e $ ProdCons a b
205โˆ’ structuralList e $ ProdCons aa bb
206โˆ’ pure ()
207โˆ’structuralList _ _ = structuralIssue
208โˆ’
209โˆ’structuralEq :: (Eq a, Comonad w) => ProdCons (w a) -> StructuralCompatFormula ()
210โˆ’structuralEq (ProdCons a b) = if extract a == extract b then pure () else structuralIssue
211โˆ’
212โˆ’iohmStructural
213โˆ’ :: (HasAll (CheckEnv v) (k ': xs), Ord k, Subtree v, Hashable k, Typeable k, Show k)
214โˆ’ => HList xs
215โˆ’ -> ProdCons (Traced (IOHM.InsOrdHashMap k v))
216โˆ’ -> StructuralCompatFormula ()
217โˆ’iohmStructural e =
218โˆ’ iohmStructuralWith (\k -> checkSubstructure (k `HCons` e))
219โˆ’
220โˆ’instance (Typeable k, Typeable v, Ord k, Show k) => Steppable (IOHM.InsOrdHashMap k v) v where
221โˆ’ data Step (IOHM.InsOrdHashMap k v) v = InsOrdHashMapKeyStep k
222โˆ’ deriving stock (Eq, Ord, Show)
223โˆ’
224โˆ’iohmStructuralWith
225โˆ’ :: (Ord k, Hashable k, Typeable k, Typeable v, Show k)
226โˆ’ => (k -> ProdCons (Traced v) -> StructuralCompatFormula ())
227โˆ’ -> ProdCons (Traced (IOHM.InsOrdHashMap k v))
228โˆ’ -> StructuralCompatFormula ()
229โˆ’iohmStructuralWith f pc = do
230โˆ’ let ProdCons pEKeys cEKeys = S.fromList . IOHM.keys . extract <$> pc
231โˆ’ if pEKeys == cEKeys
232โˆ’ then
233โˆ’ for_
234โˆ’ pEKeys
235โˆ’ (\eKey ->
236โˆ’ f eKey $ stepTraced (InsOrdHashMapKeyStep eKey) . fmap (IOHM.lookupDefault (error "impossible") eKey) <$> pc)
237โˆ’ else structuralIssue
238โˆ’
239โˆ’class HasUnsupportedFeature x where
240โˆ’ hasUnsupportedFeature :: x -> Bool
241โˆ’
242โˆ’instance HasUnsupportedFeature () where
243โˆ’ hasUnsupportedFeature () = False
244โˆ’
245โˆ’instance
246โˆ’ (HasUnsupportedFeature a, HasUnsupportedFeature b)
247โˆ’ => HasUnsupportedFeature (Either a b)
248โˆ’ where
249โˆ’ hasUnsupportedFeature (Left x) = hasUnsupportedFeature x
250โˆ’ hasUnsupportedFeature (Right x) = hasUnsupportedFeature x
251โˆ’
252โˆ’instance Issuable l => HasUnsupportedFeature (Issue l) where
253โˆ’ hasUnsupportedFeature = issueIsUnsupported
254โˆ’
255โˆ’instance HasUnsupportedFeature (AnIssue l) where
256โˆ’ hasUnsupportedFeature (AnIssue issue) = hasUnsupportedFeature issue
257โˆ’
258โˆ’instance
259โˆ’ (forall x. HasUnsupportedFeature (f x))
260โˆ’ => HasUnsupportedFeature (P.PathsPrefixTree q f r)
261โˆ’ where
262โˆ’ hasUnsupportedFeature =
263โˆ’ getAny . P.foldWith (\_ fa -> Any $ hasUnsupportedFeature fa)
264โˆ’
265โˆ’runCompatFormula
266โˆ’ :: CompatFormula' q f r a
267โˆ’ -> Either (P.PathsPrefixTree q f r) a
268โˆ’runCompatFormula (Compose f) =
269โˆ’ calculate . runIdentity . runMemo 0 . unCompatM $ f
270โˆ’
271โˆ’issueAt :: Issuable l => Paths q r l -> Issue l -> CompatFormula' q AnIssue r a
272โˆ’issueAt xs issue = Compose $ pure $ anError $ AnItem xs $ AnIssue issue
273โˆ’
274โˆ’structuralIssue :: StructuralCompatFormula a
275โˆ’structuralIssue = Compose $ pure $ anError $ AnItem Root Proxy
276โˆ’
277โˆ’anyOfAt
278โˆ’ :: Issuable l
279โˆ’ => Paths q r l
280โˆ’ -> Issue l
281โˆ’ -> [CompatFormula' q AnIssue r a]
282โˆ’ -> CompatFormula' q AnIssue r a
283โˆ’anyOfAt _ _ [x] = x
284โˆ’anyOfAt xs issue fs =
285โˆ’ Compose $ (`eitherOf` AnItem xs (AnIssue issue)) <$> sequenceA (getCompose <$> fs)
286โˆ’
287โˆ’fixpointKnot
288โˆ’ :: MonadState (MemoState VarRef) m
289โˆ’ => KnotTier (FormulaF q f r ()) VarRef m
290โˆ’fixpointKnot =
291โˆ’ KnotTier
292โˆ’ { onKnotFound = modifyMemoNonce succ
293โˆ’ , onKnotUsed = \i -> pure $ variable i
294โˆ’ , tieKnot = \i x -> pure $ maxFixpoint i x
295โˆ’ }
296โˆ’
297โˆ’memo
298โˆ’ :: (Typeable (l :: k), Typeable q, Typeable f, Typeable k, Typeable a)
299โˆ’ => Paths q r l
300โˆ’ -> MemoKey
301โˆ’ -> (ProdCons (Traced a) -> CompatFormula' q f r ())
302โˆ’ -> (ProdCons (Traced a) -> CompatFormula' q f r ())
303โˆ’memo bhv k f pc = Compose $ do
304โˆ’ formula' <-
305โˆ’ memoWithKnot
306โˆ’ fixpointKnot
307โˆ’ (do
308โˆ’ formula <- getCompose $ f pc
309โˆ’ pure $ mapErrors (P.takeSubtree bhv) formula)
310โˆ’ (k, ask <$> pc)
311โˆ’ pure $ mapErrors (P.embed bhv) formula'
312โˆ’
313โˆ’data MemoKey = SemanticMemoKey | StructuralMemoKey
314โˆ’ deriving stock (Eq, Ord)
src/OpenAPI/Checker/Validate/Products.hsdeletedโˆ’49
@@ -1,49 +0,0 @@
1โˆ’{- | Checks product-like entities. The key is some identificator for the product
2โˆ’element. Each element may be required or optional.
3โˆ’
4โˆ’One example of product is request parameters. There are optional and required
5โˆ’parameters. The client and server have possibly different set of
6โˆ’parameters. What we must check is if server requires some request parameter,
7โˆ’then this parameter must be presented by client and their schemas must match.
8โˆ’
9โˆ’So when we checking products we are checking from the server's (consumer)
10โˆ’perspective, ensuring that all parameters are provided by the client (producer)
11โˆ’and their schemas match.
12โˆ’
13โˆ’This module abstracts this logic for arbitrary elements -}
14โˆ’
15โˆ’module OpenAPI.Checker.Validate.Products
16โˆ’ ( checkProducts
17โˆ’ , ProductLike(..)
18โˆ’ ) where
19โˆ’
20โˆ’import Data.Foldable
21โˆ’import Data.Map.Strict (Map)
22โˆ’import qualified Data.Map.Strict as M
23โˆ’import OpenAPI.Checker.Behavior
24โˆ’import OpenAPI.Checker.Paths
25โˆ’import OpenAPI.Checker.Subtree
26โˆ’
27โˆ’-- | Some entity which is product-like
28โˆ’data ProductLike a = ProductLike
29โˆ’ { productValue :: a
30โˆ’ , required :: Bool
31โˆ’ }
32โˆ’
33โˆ’checkProducts
34โˆ’ :: (Ord k, Issuable l)
35โˆ’ => Paths q r l
36โˆ’ -> (k -> Issue l)
37โˆ’ -- ^ No required element found
38โˆ’ -> (k -> ProdCons t -> CompatFormula' q AnIssue r ())
39โˆ’ -> ProdCons (Map k (ProductLike t))
40โˆ’ -> CompatFormula' q AnIssue r ()
41โˆ’checkProducts xs noElt check (ProdCons p c) = for_ (M.toList c) $ \(key, consElt) ->
42โˆ’ case M.lookup key p of
43โˆ’ Nothing -> case required consElt of
44โˆ’ True -> issueAt xs $ noElt key
45โˆ’ False -> pure ()
46โˆ’ Just prodElt -> do
47โˆ’ let
48โˆ’ elts = ProdCons prodElt consElt
49โˆ’ check key (productValue <$> elts)
src/OpenAPI/Checker/Validate/Schema.hsdeletedโˆ’1222
@@ -1,1222 +0,0 @@
1โˆ’{-# OPTIONS_GHC -fno-warn-orphans #-}
2โˆ’
3โˆ’module OpenAPI.Checker.Validate.Schema
4โˆ’ ( JsonType (..)
5โˆ’ , ForeachType (..)
6โˆ’ , foldType
7โˆ’ , forType_
8โˆ’ , TypedValue (..)
9โˆ’ , untypeValue
10โˆ’ , Bound (..)
11โˆ’ , schemaToFormula
12โˆ’ , foldLattice
13โˆ’ , Behave (..)
14โˆ’ , describeJSONType
15โˆ’ )
16โˆ’where
17โˆ’
18โˆ’import Algebra.Lattice
19โˆ’import Control.Applicative
20โˆ’import Control.Arrow
21โˆ’import Control.Comonad.Env hiding (env)
22โˆ’import Control.Monad.Reader hiding (ask)
23โˆ’import qualified Control.Monad.Reader as R
24โˆ’import Control.Monad.State
25โˆ’import Control.Monad.Writer
26โˆ’import qualified Data.Aeson as A
27โˆ’import qualified Data.ByteString.Lazy as BSL
28โˆ’import Data.Coerce
29โˆ’import qualified Data.Foldable as F
30โˆ’import Data.Functor
31โˆ’import Data.Functor.Identity
32โˆ’import Data.HList
33โˆ’import qualified Data.HashMap.Strict as HM
34โˆ’import qualified Data.HashMap.Strict.InsOrd as IOHM
35โˆ’import Data.Int
36โˆ’import Data.Kind
37โˆ’import qualified Data.List.NonEmpty as NE
38โˆ’import qualified Data.Map as M
39โˆ’import Data.Maybe
40โˆ’import Data.OpenApi hiding (get)
41โˆ’import Data.Ord
42โˆ’import Data.Ratio
43โˆ’import Data.Scientific
44โˆ’import qualified Data.Set as S
45โˆ’import Data.String
46โˆ’import Data.Text (Text)
47โˆ’import qualified Data.Text as T hiding (singleton)
48โˆ’import qualified Data.Text.Encoding as T
49โˆ’import Data.Typeable
50โˆ’import OpenAPI.Checker.Behavior
51โˆ’import OpenAPI.Checker.Memo
52โˆ’import OpenAPI.Checker.Orphans ()
53โˆ’import OpenAPI.Checker.Paths
54โˆ’import qualified OpenAPI.Checker.PathsPrefixTree as P
55โˆ’import OpenAPI.Checker.References
56โˆ’import OpenAPI.Checker.Subtree
57โˆ’import Text.Pandoc.Builder hiding (Format, Null)
58โˆ’import Text.Regex.Pcre2
59โˆ’
60โˆ’-- | Type of a JSON value
61โˆ’data JsonType
62โˆ’ = Null
63โˆ’ | Boolean
64โˆ’ | Number
65โˆ’ | String
66โˆ’ | Array
67โˆ’ | Object
68โˆ’ deriving stock (Eq, Ord, Show)
69โˆ’
70โˆ’-- | A 'A.Value' whose type we know
71โˆ’data TypedValue :: JsonType -> Type where
72โˆ’ TNull :: TypedValue 'Null
73โˆ’ TBool :: !Bool -> TypedValue 'Boolean
74โˆ’ TNumber :: !Scientific -> TypedValue 'Number
75โˆ’ TString :: !Text -> TypedValue 'String
76โˆ’ TArray :: !A.Array -> TypedValue 'Array
77โˆ’ TObject :: !A.Object -> TypedValue 'Object
78โˆ’
79โˆ’deriving stock instance Eq (TypedValue t)
80โˆ’
81โˆ’deriving stock instance Ord (TypedValue t)
82โˆ’
83โˆ’deriving stock instance Show (TypedValue t)
84โˆ’
85โˆ’untypeValue :: TypedValue t -> A.Value
86โˆ’untypeValue TNull = A.Null
87โˆ’untypeValue (TBool b) = A.Bool b
88โˆ’untypeValue (TNumber n) = A.Number n
89โˆ’untypeValue (TString s) = A.String s
90โˆ’untypeValue (TArray a) = A.Array a
91โˆ’untypeValue (TObject o) = A.Object o
92โˆ’
93โˆ’data Bound a = Exclusive !a | Inclusive !a
94โˆ’ deriving stock (Eq, Show, Functor)
95โˆ’
96โˆ’-- | The order is lexicographical on @a * Bool@.
97โˆ’instance Ord a => Ord (Bound a) where
98โˆ’ Exclusive a `compare` Exclusive b = compare a b
99โˆ’ Exclusive a `compare` Inclusive b = if a <= b then LT else GT
100โˆ’ Inclusive a `compare` Exclusive b = if a < b then LT else GT
101โˆ’ Inclusive a `compare` Inclusive b = compare a b
102โˆ’
103โˆ’data Property = Property
104โˆ’ { propRequired :: Bool
105โˆ’ , propFormula :: ForeachType JsonFormula
106โˆ’ , propRefSchema :: Traced (Referenced Schema)
107โˆ’ }
108โˆ’ deriving stock (Eq, Ord, Show)
109โˆ’
110โˆ’-- | A primitive structural condition for the "top level" of a JSON value (of a specific type)
111โˆ’data Condition :: JsonType -> Type where
112โˆ’ Exactly :: TypedValue t -> Condition t
113โˆ’ Maximum :: !(Bound Scientific) -> Condition 'Number
114โˆ’ Minimum
115โˆ’ :: !(Down (Bound (Down Scientific)))
116โˆ’ -> Condition 'Number -- ^ this has the right Ord
117โˆ’ MultipleOf :: !Scientific -> Condition 'Number
118โˆ’ NumberFormat :: !Format -> Condition 'Number
119โˆ’ MaxLength :: !Integer -> Condition 'String
120โˆ’ MinLength :: !Integer -> Condition 'String
121โˆ’ Pattern :: !Pattern -> Condition 'String
122โˆ’ StringFormat :: !Format -> Condition 'String
123โˆ’ Items
124โˆ’ :: !(ForeachType JsonFormula)
125โˆ’ -> !(Traced (Referenced Schema))
126โˆ’ -> Condition 'Array
127โˆ’ MaxItems :: !Integer -> Condition 'Array
128โˆ’ MinItems :: !Integer -> Condition 'Array
129โˆ’ UniqueItems :: Condition 'Array
130โˆ’ Properties
131โˆ’ :: !(M.Map Text Property)
132โˆ’ -> !(ForeachType JsonFormula) -- ^ formula for additional properties
133โˆ’ -> !(Maybe (Traced (Referenced Schema))) -- ^ schema for additional properties, Nothing means bottom
134โˆ’ -> Condition 'Object
135โˆ’ MaxProperties :: !Integer -> Condition 'Object
136โˆ’ MinProperties :: !Integer -> Condition 'Object
137โˆ’
138โˆ’showCondition :: Condition a -> Blocks
139โˆ’showCondition = \case
140โˆ’ (Exactly v) -> para "The value should be:" <> showJSONValue (untypeValue v)
141โˆ’ (Maximum b) -> para $ "The value should be less than " <> showBound b <> "."
142โˆ’ (Minimum (Down b)) -> para $ "The value should be more than " <> showBound (getDown <$> b) <> "."
143โˆ’ (MultipleOf n) -> para $ "The value should be a multiple of " <> show' n <> "."
144โˆ’ (NumberFormat p) -> para $ "The number should have the following format:" <> code p <> "."
145โˆ’ (Pattern p) -> para "The value should satisfy the following pattern (regular expression):" <> codeBlock p
146โˆ’ (StringFormat p) -> para $ "The string should have the following format:" <> code p <> "."
147โˆ’ (MaxLength p) -> para $ "The length of the string should be less than or equal to " <> show' p <> "."
148โˆ’ (MinLength p) -> para $ "The length of the string should be more than or equal to " <> show' p <> "."
149โˆ’ (Items i _) -> para "The items of the array should satisfy:" <> showForEachJsonFormula i
150โˆ’ (MaxItems n) -> para $ "The length of the array should be less than or equal to " <> show' n <> "."
151โˆ’ (MinItems n) -> para $ "The length of the array should be more than or equal to " <> show' n <> "."
152โˆ’ UniqueItems -> para "The elements in the array should be unique."
153โˆ’ (Properties props additional _) ->
154โˆ’ bulletList $
155โˆ’ (M.toList props
156โˆ’ <&> (\(k, p) ->
157โˆ’ para (code k)
158โˆ’ <> para (strong $ if propRequired p then "Required" else "Optional")
159โˆ’ <> showForEachJsonFormula (propFormula p)))
160โˆ’ <> [ para (emph "Additional properties")
161โˆ’ <> showForEachJsonFormula additional
162โˆ’ ]
163โˆ’ (MaxProperties n) -> para $ "The maximum number of fields should be " <> show' n <> "."
164โˆ’ (MinProperties n) -> para $ "The minimum number of fields should be " <> show' n <> "."
165โˆ’ where
166โˆ’ showForEachJsonFormula :: ForeachType JsonFormula -> Blocks
167โˆ’ showForEachJsonFormula i =
168โˆ’ bulletList $
169โˆ’ foldType
170โˆ’ (\t f ->
171โˆ’ let (DNF conds') = f i
172โˆ’ conds = S.toList <$> S.toList conds'
173โˆ’ in [ para (describeJSONType t)
174โˆ’ <> bulletList (conds <&> \cond -> bulletList (showCondition <$> cond))
175โˆ’ ])
176โˆ’
177โˆ’satisfiesTyped :: TypedValue t -> Condition t -> Bool
178โˆ’satisfiesTyped e (Exactly e') = e == e'
179โˆ’satisfiesTyped (TNumber n) (Maximum (Exclusive m)) = n < m
180โˆ’satisfiesTyped (TNumber n) (Maximum (Inclusive m)) = n <= m
181โˆ’satisfiesTyped (TNumber n) (Minimum (Down (Exclusive (Down m)))) = n > m
182โˆ’satisfiesTyped (TNumber n) (Minimum (Down (Inclusive (Down m)))) = n >= m
183โˆ’satisfiesTyped (TNumber n) (MultipleOf m) = denominator (toRational n / toRational m) == 1 -- TODO: could be better #36
184โˆ’satisfiesTyped (TNumber n) (NumberFormat f) = checkNumberFormat f n
185โˆ’satisfiesTyped (TString s) (MaxLength m) = fromIntegral (T.length s) <= m
186โˆ’satisfiesTyped (TString s) (MinLength m) = fromIntegral (T.length s) >= m
187โˆ’satisfiesTyped (TString s) (Pattern p) = isJust $ match p s -- TODO: regex stuff #32
188โˆ’satisfiesTyped (TString s) (StringFormat f) = checkStringFormat f s
189โˆ’satisfiesTyped (TArray a) (Items f _) = all (`satisfies` f) a
190โˆ’satisfiesTyped (TArray a) (MaxItems m) = fromIntegral (F.length a) <= m
191โˆ’satisfiesTyped (TArray a) (MinItems m) = fromIntegral (F.length a) >= m
192โˆ’satisfiesTyped (TArray a) UniqueItems = S.size (S.fromList $ F.toList a) == F.length a -- TODO: could be better #36
193โˆ’satisfiesTyped (TObject o) (Properties props additional _) =
194โˆ’ all (`HM.member` o) (M.keys (M.filter propRequired props))
195โˆ’ && all (\(k, v) -> satisfies v $ maybe additional propFormula $ M.lookup k props) (HM.toList o)
196โˆ’satisfiesTyped (TObject o) (MaxProperties m) = fromIntegral (HM.size o) <= m
197โˆ’satisfiesTyped (TObject o) (MinProperties m) = fromIntegral (HM.size o) >= m
198โˆ’
199โˆ’checkNumberFormat :: Format -> Scientific -> Bool
200โˆ’checkNumberFormat "int32" (toRational -> n) =
201โˆ’ denominator n == 1
202โˆ’ && n >= toRational (minBound :: Int32)
203โˆ’ && n <= toRational (maxBound :: Int32)
204โˆ’checkNumberFormat "int64" (toRational -> n) =
205โˆ’ denominator n == 1
206โˆ’ && n >= toRational (minBound :: Int64)
207โˆ’ && n <= toRational (maxBound :: Int64)
208โˆ’checkNumberFormat "float" _n = True
209โˆ’checkNumberFormat "double" _n = True
210โˆ’checkNumberFormat f _n = error $ "Invalid number format: " <> T.unpack f
211โˆ’
212โˆ’checkStringFormat :: Format -> Text -> Bool
213โˆ’checkStringFormat "byte" _s = True -- TODO: regex stuff #32
214โˆ’checkStringFormat "binary" _s = True
215โˆ’checkStringFormat "date" _s = True
216โˆ’checkStringFormat "date-time" _s = True
217โˆ’checkStringFormat "password" _s = True
218โˆ’checkStringFormat "uuid" _s = True
219โˆ’checkStringFormat f _s = error $ "Invalid string format: " <> T.unpack f
220โˆ’
221โˆ’deriving stock instance Eq (Condition t)
222โˆ’
223โˆ’deriving stock instance Ord (Condition t)
224โˆ’
225โˆ’deriving stock instance Show (Condition t)
226โˆ’
227โˆ’data SomeCondition where
228โˆ’ SomeCondition :: Typeable t => Condition t -> SomeCondition
229โˆ’
230โˆ’instance Eq SomeCondition where
231โˆ’ SomeCondition x == SomeCondition y = case cast x of
232โˆ’ Just x' -> x' == y
233โˆ’ Nothing -> False
234โˆ’
235โˆ’instance Ord SomeCondition where
236โˆ’ compare (SomeCondition x) (SomeCondition y) = case cast x of
237โˆ’ Just x' -> compare x' y
238โˆ’ Nothing -> compare (typeRep x) (typeRep y)
239โˆ’
240โˆ’deriving stock instance Show SomeCondition
241โˆ’
242โˆ’-- | A boolean formula (without "not") of 'Condition's. Represented as a
243โˆ’-- Disjunctive Normal Form: the formula is a disjunction of a set of conjuncts,
244โˆ’-- each of which is a conjunction of a set of 'Condition's.
245โˆ’newtype JsonFormula t
246โˆ’ = DNF (S.Set (S.Set (Condition t)))
247โˆ’ deriving stock (Eq, Ord, Show)
248โˆ’
249โˆ’disjAdd
250โˆ’ :: JsonFormula t
251โˆ’ -> S.Set (Condition t)
252โˆ’ -> JsonFormula t
253โˆ’disjAdd (DNF yss) xs
254โˆ’ | any (`S.isSubsetOf` xs) yss = DNF yss
255โˆ’ | otherwise = DNF $ S.insert xs $ S.filter (not . S.isSubsetOf xs) yss
256โˆ’
257โˆ’instance Lattice (JsonFormula t) where
258โˆ’ xss \/ DNF yss = S.foldl' disjAdd xss yss
259โˆ’ DNF xss /\ DNF yss =
260โˆ’ F.foldl' disjAdd bottom $
261โˆ’ liftA2 S.union (S.toList xss) (S.toList yss)
262โˆ’
263โˆ’pattern BottomFormula :: JsonFormula t
264โˆ’pattern BottomFormula <-
265โˆ’ DNF (S.null -> True)
266โˆ’ where
267โˆ’ BottomFormula = DNF S.empty
268โˆ’
269โˆ’isSingleton :: S.Set a -> Maybe a
270โˆ’isSingleton s
271โˆ’ | S.size s == 1 = S.lookupMin s
272โˆ’ | otherwise = Nothing
273โˆ’
274โˆ’pattern Conjunct :: [Condition t] -> S.Set (Condition t)
275โˆ’pattern Conjunct xs <-
276โˆ’ (S.toList -> xs)
277โˆ’ where
278โˆ’ Conjunct = S.fromList
279โˆ’
280โˆ’{-# COMPLETE Conjunct #-}
281โˆ’
282โˆ’pattern SingleConjunct :: [Condition t] -> JsonFormula t
283โˆ’pattern SingleConjunct xs <-
284โˆ’ DNF (isSingleton -> Just (Conjunct xs))
285โˆ’ where
286โˆ’ SingleConjunct xs = DNF $ S.singleton $ Conjunct xs
287โˆ’
288โˆ’pattern TopFormula :: JsonFormula t
289โˆ’pattern TopFormula <-
290โˆ’ DNF (isSingleton -> Just (S.null -> True))
291โˆ’ where
292โˆ’ TopFormula = DNF $ S.singleton S.empty
293โˆ’
294โˆ’instance BoundedJoinSemiLattice (JsonFormula t) where
295โˆ’ bottom = BottomFormula
296โˆ’
297โˆ’instance BoundedMeetSemiLattice (JsonFormula t) where
298โˆ’ top = TopFormula
299โˆ’
300โˆ’foldLattice
301โˆ’ :: BoundedLattice l
302โˆ’ => (Condition t -> l)
303โˆ’ -> JsonFormula t
304โˆ’ -> l
305โˆ’foldLattice f (DNF xss) =
306โˆ’ S.foldl'
307โˆ’ (\z w ->
308โˆ’ z \/ S.foldl' (\x y -> x /\ f y) top w)
309โˆ’ bottom
310โˆ’ xss
311โˆ’
312โˆ’satisfiesFormula :: TypedValue t -> JsonFormula t -> Bool
313โˆ’satisfiesFormula val = foldLattice (satisfiesTyped val)
314โˆ’
315โˆ’data ForeachType (f :: JsonType -> Type) = ForeachType
316โˆ’ { forNull :: f 'Null
317โˆ’ , forBoolean :: f 'Boolean
318โˆ’ , forNumber :: f 'Number
319โˆ’ , forString :: f 'String
320โˆ’ , forArray :: f 'Array
321โˆ’ , forObject :: f 'Object
322โˆ’ }
323โˆ’
324โˆ’satisfies :: A.Value -> ForeachType JsonFormula -> Bool
325โˆ’satisfies val p = case val of
326โˆ’ A.Null -> satisfiesFormula TNull $ forNull p
327โˆ’ A.Bool b -> satisfiesFormula (TBool b) $ forBoolean p
328โˆ’ A.Number n -> satisfiesFormula (TNumber n) $ forNumber p
329โˆ’ A.String s -> satisfiesFormula (TString s) $ forString p
330โˆ’ A.Array a -> satisfiesFormula (TArray a) $ forArray p
331โˆ’ A.Object o -> satisfiesFormula (TObject o) $ forObject p
332โˆ’
333โˆ’deriving stock instance (forall x. Typeable x => Eq (f x)) => Eq (ForeachType f)
334โˆ’
335โˆ’deriving stock instance (forall x. Typeable x => Ord (f x)) => Ord (ForeachType f)
336โˆ’
337โˆ’deriving stock instance (forall x. Typeable x => Show (f x)) => Show (ForeachType f)
338โˆ’
339โˆ’foldType
340โˆ’ :: Monoid m
341โˆ’ => (forall x. Typeable x => JsonType -> (ForeachType f -> f x) -> m)
342โˆ’ -> m
343โˆ’foldType k =
344โˆ’ k Null forNull
345โˆ’ <> k Boolean forBoolean
346โˆ’ <> k Number forNumber
347โˆ’ <> k String forString
348โˆ’ <> k Array forArray
349โˆ’ <> k Object forObject
350โˆ’
351โˆ’forType_
352โˆ’ :: Applicative m
353โˆ’ => (forall x. Typeable x => JsonType -> (ForeachType f -> f x) -> m ())
354โˆ’ -> m ()
355โˆ’forType_ k = do
356โˆ’ k Null forNull
357โˆ’ k Boolean forBoolean
358โˆ’ k Number forNumber
359โˆ’ k String forString
360โˆ’ k Array forArray
361โˆ’ k Object forObject
362โˆ’ pure ()
363โˆ’
364โˆ’instance (forall x. Lattice (f x)) => Lattice (ForeachType f) where
365โˆ’ f1 \/ f2 =
366โˆ’ ForeachType
367โˆ’ { forNull = forNull f1 \/ forNull f2
368โˆ’ , forBoolean = forBoolean f1 \/ forBoolean f2
369โˆ’ , forNumber = forNumber f1 \/ forNumber f2
370โˆ’ , forString = forString f1 \/ forString f2
371โˆ’ , forArray = forArray f1 \/ forArray f2
372โˆ’ , forObject = forObject f1 \/ forObject f2
373โˆ’ }
374โˆ’ f1 /\ f2 =
375โˆ’ ForeachType
376โˆ’ { forNull = forNull f1 /\ forNull f2
377โˆ’ , forBoolean = forBoolean f1 /\ forBoolean f2
378โˆ’ , forNumber = forNumber f1 /\ forNumber f2
379โˆ’ , forString = forString f1 /\ forString f2
380โˆ’ , forArray = forArray f1 /\ forArray f2
381โˆ’ , forObject = forObject f1 /\ forObject f2
382โˆ’ }
383โˆ’
384โˆ’instance
385โˆ’ (forall x. BoundedJoinSemiLattice (f x))
386โˆ’ => BoundedJoinSemiLattice (ForeachType f)
387โˆ’ where
388โˆ’ bottom =
389โˆ’ ForeachType
390โˆ’ { forNull = bottom
391โˆ’ , forBoolean = bottom
392โˆ’ , forNumber = bottom
393โˆ’ , forString = bottom
394โˆ’ , forArray = bottom
395โˆ’ , forObject = bottom
396โˆ’ }
397โˆ’
398โˆ’instance
399โˆ’ (forall x. BoundedMeetSemiLattice (f x))
400โˆ’ => BoundedMeetSemiLattice (ForeachType f)
401โˆ’ where
402โˆ’ top =
403โˆ’ ForeachType
404โˆ’ { forNull = top
405โˆ’ , forBoolean = top
406โˆ’ , forNumber = top
407โˆ’ , forString = top
408โˆ’ , forArray = top
409โˆ’ , forObject = top
410โˆ’ }
411โˆ’
412โˆ’instance Steppable Schema (Referenced Schema) where
413โˆ’ data Step Schema (Referenced Schema)
414โˆ’ = AllOfStep Int
415โˆ’ | OneOfStep Int
416โˆ’ | AnyOfStep Int
417โˆ’ | ItemsObjectStep
418โˆ’ | ItemsArrayStep Int
419โˆ’ | AdditionalPropertiesStep
420โˆ’ | NotStep
421โˆ’ deriving stock (Eq, Ord, Show)
422โˆ’
423โˆ’instance Steppable Schema (Definitions (Referenced Schema)) where
424โˆ’ data Step Schema (Definitions (Referenced Schema)) = PropertiesStep
425โˆ’ deriving stock (Eq, Ord, Show)
426โˆ’
427โˆ’instance Steppable Schema Discriminator where
428โˆ’ data Step Schema Discriminator = DiscriminatorStep
429โˆ’ deriving stock (Eq, Ord, Show)
430โˆ’
431โˆ’instance Steppable Discriminator (Definitions (Referenced Schema)) where
432โˆ’ data Step Discriminator (Definitions (Referenced Schema)) = DiscriminatorMapping
433โˆ’ deriving stock (Eq, Ord, Show)
434โˆ’
435โˆ’parseDiscriminatorValue :: Text -> Referenced Schema
436โˆ’parseDiscriminatorValue v = case A.fromJSON @(Referenced Schema) $ A.object ["$ref" A..= v] of
437โˆ’ A.Success x -> x
438โˆ’ A.Error _ -> Ref $ Reference v
439โˆ’
440โˆ’-- | A fake writer monad that doesn't actually record anything and allows lazy recursion.
441โˆ’newtype Silent q f r a = Silent {runSilent :: a}
442โˆ’ deriving stock (Functor)
443โˆ’ deriving (Applicative, Monad) via Identity
444โˆ’
445โˆ’instance MonadWriter (P.PathsPrefixTree q f r) (Silent q f r) where
446โˆ’ tell _ = Silent ()
447โˆ’ listen (Silent x) = Silent (x, P.empty)
448โˆ’ pass (Silent (x, _)) = Silent x
449โˆ’
450โˆ’instance MonadState (MemoState ()) (Silent q f r) where
451โˆ’ get = Silent $ runIdentity $ runMemo () get
452โˆ’ put _ = pure ()
453โˆ’
454โˆ’type MonadProcess m =
455โˆ’ ( MonadReader (Traced (Definitions Schema)) m
456โˆ’ , MonadWriter (P.PathsPrefixTree Behave AnIssue 'SchemaLevel) m
457โˆ’ , MonadState (MemoState ()) m
458โˆ’ )
459โˆ’
460โˆ’type SilentM = ReaderT (Traced (Definitions Schema)) (Silent Behave AnIssue 'SchemaLevel)
461โˆ’
462โˆ’warn :: MonadProcess m => Issue 'SchemaLevel -> m ()
463โˆ’warn issue = tell $ P.singleton $ AnItem Root $ AnIssue issue
464โˆ’
465โˆ’-- | Ignore warnings but allow a recursive loop that lazily computes a recursive 'Condition'.
466โˆ’silently :: MonadProcess m => SilentM a -> m a
467โˆ’silently m = do
468โˆ’ defs <- R.ask
469โˆ’ pure . runSilent $ runReaderT m defs
470โˆ’
471โˆ’warnKnot :: MonadProcess m => KnotTier (ForeachType JsonFormula) () m
472โˆ’warnKnot =
473โˆ’ KnotTier
474โˆ’ { onKnotFound = warn UnguardedRecursion
475โˆ’ , onKnotUsed = \_ -> pure bottom
476โˆ’ , tieKnot = \_ -> pure
477โˆ’ }
478โˆ’
479โˆ’processRefSchema
480โˆ’ :: MonadProcess m
481โˆ’ => Traced (Referenced Schema)
482โˆ’ -> m (ForeachType JsonFormula)
483โˆ’processRefSchema x = do
484โˆ’ defs <- R.ask
485โˆ’ memoWithKnot warnKnot (processSchema $ dereference defs x) (ask x)
486โˆ’
487โˆ’tracedAllOf :: Traced Schema -> Maybe [Traced (Referenced Schema)]
488โˆ’tracedAllOf sch =
489โˆ’ _schemaAllOf (extract sch) <&> \xs ->
490โˆ’ [traced (ask sch >>> step (AllOfStep i)) x | (i, x) <- zip [0 ..] xs]
491โˆ’
492โˆ’tracedAnyOf :: Traced Schema -> Maybe [Traced (Referenced Schema)]
493โˆ’tracedAnyOf sch =
494โˆ’ _schemaAnyOf (extract sch) <&> \xs ->
495โˆ’ [traced (ask sch >>> step (AnyOfStep i)) x | (i, x) <- zip [0 ..] xs]
496โˆ’
497โˆ’tracedOneOf :: Traced Schema -> Maybe [Traced (Referenced Schema)]
498โˆ’tracedOneOf sch =
499โˆ’ _schemaOneOf (extract sch) <&> \xs ->
500โˆ’ [traced (ask sch >>> step (OneOfStep i)) x | (i, x) <- zip [0 ..] xs]
501โˆ’
502โˆ’tracedItems :: Traced Schema -> Maybe (Either (Traced (Referenced Schema)) [Traced (Referenced Schema)])
503โˆ’tracedItems sch =
504โˆ’ _schemaItems (extract sch) <&> \case
505โˆ’ OpenApiItemsObject x -> Left $ traced (ask sch >>> step ItemsObjectStep) x
506โˆ’ OpenApiItemsArray xs ->
507โˆ’ Right
508โˆ’ [traced (ask sch >>> step (ItemsArrayStep i)) x | (i, x) <- zip [0 ..] xs]
509โˆ’
510โˆ’tracedAdditionalProperties :: Traced Schema -> Maybe (Either Bool (Traced (Referenced Schema)))
511โˆ’tracedAdditionalProperties sch =
512โˆ’ _schemaAdditionalProperties (extract sch) <&> \case
513โˆ’ AdditionalPropertiesAllowed b -> Left b
514โˆ’ AdditionalPropertiesSchema x -> Right $ traced (ask sch >>> step AdditionalPropertiesStep) x
515โˆ’
516โˆ’tracedDiscriminator :: Traced Schema -> Maybe (Traced Discriminator)
517โˆ’tracedDiscriminator = sequence . stepTraced DiscriminatorStep . fmap _schemaDiscriminator
518โˆ’
519โˆ’tracedProperties :: Traced Schema -> IOHM.InsOrdHashMap Text (Traced (Referenced Schema))
520โˆ’tracedProperties sch =
521โˆ’ IOHM.mapWithKey
522โˆ’ (\k -> traced (ask sch >>> step PropertiesStep >>> step (InsOrdHashMapKeyStep k)))
523โˆ’ (_schemaProperties $ extract sch)
524โˆ’
525โˆ’-- | Turn a schema into a tuple of 'JsonFormula's that describes the condition
526โˆ’-- for every possible type of a JSON value. The conditions are independent, and
527โˆ’-- are thus checked independently.
528โˆ’processSchema
529โˆ’ :: MonadProcess m
530โˆ’ => Traced Schema
531โˆ’ -> m (ForeachType JsonFormula)
532โˆ’processSchema sch@(extract -> Schema {..}) = do
533โˆ’ let singletonFormula :: Condition t -> JsonFormula t
534โˆ’ singletonFormula f = SingleConjunct [f]
535โˆ’
536โˆ’ allClauses <- case tracedAllOf sch of
537โˆ’ Nothing -> pure []
538โˆ’ Just [] -> [] <$ warn (InvalidSchema "no items in allOf")
539โˆ’ Just xs -> mapM processRefSchema xs
540โˆ’
541โˆ’ anyClause <- case tracedAnyOf sch of
542โˆ’ Nothing -> pure top
543โˆ’ Just [] -> bottom <$ warn (InvalidSchema "no items in anyOf")
544โˆ’ Just xs -> joins <$> mapM processRefSchema xs
545โˆ’
546โˆ’ oneClause <- case tracedOneOf sch of
547โˆ’ Nothing -> pure top
548โˆ’ Just [] -> bottom <$ warn (InvalidSchema "no items in oneOf")
549โˆ’ Just xs -> do
550โˆ’ checkOneOfDisjoint xs >>= \case
551โˆ’ True -> pure ()
552โˆ’ False -> warn (NotSupported "Could not determine that oneOf branches are disjoint")
553โˆ’ joins <$> mapM processRefSchema xs
554โˆ’
555โˆ’ case _schemaNot of
556โˆ’ Nothing -> pure ()
557โˆ’ Just _ -> warn (NotSupported "not clause is unsupported")
558โˆ’
559โˆ’ let typeClause = case _schemaType of
560โˆ’ Nothing -> top
561โˆ’ Just OpenApiNull ->
562โˆ’ bottom
563โˆ’ { forNull = top
564โˆ’ }
565โˆ’ Just OpenApiBoolean ->
566โˆ’ bottom
567โˆ’ { forBoolean = top
568โˆ’ }
569โˆ’ Just OpenApiNumber ->
570โˆ’ bottom
571โˆ’ { forNumber = top
572โˆ’ }
573โˆ’ Just OpenApiInteger ->
574โˆ’ bottom
575โˆ’ { forNumber = singletonFormula $ MultipleOf 1
576โˆ’ }
577โˆ’ Just OpenApiString ->
578โˆ’ bottom
579โˆ’ { forString = top
580โˆ’ }
581โˆ’ Just OpenApiArray ->
582โˆ’ bottom
583โˆ’ { forArray = top
584โˆ’ }
585โˆ’ Just OpenApiObject ->
586โˆ’ bottom
587โˆ’ { forObject = top
588โˆ’ }
589โˆ’
590โˆ’ let valueEnum A.Null =
591โˆ’ bottom
592โˆ’ { forNull = singletonFormula $ Exactly TNull
593โˆ’ }
594โˆ’ valueEnum (A.Bool b) =
595โˆ’ bottom
596โˆ’ { forBoolean = singletonFormula $ Exactly $ TBool b
597โˆ’ }
598โˆ’ valueEnum (A.Number n) =
599โˆ’ bottom
600โˆ’ { forNumber = singletonFormula $ Exactly $ TNumber n
601โˆ’ }
602โˆ’ valueEnum (A.String s) =
603โˆ’ bottom
604โˆ’ { forString = singletonFormula $ Exactly $ TString s
605โˆ’ }
606โˆ’ valueEnum (A.Array a) =
607โˆ’ bottom
608โˆ’ { forArray = singletonFormula $ Exactly $ TArray a
609โˆ’ }
610โˆ’ valueEnum (A.Object o) =
611โˆ’ bottom
612โˆ’ { forObject = singletonFormula $ Exactly $ TObject o
613โˆ’ }
614โˆ’ enumClause <- case _schemaEnum of
615โˆ’ Nothing -> pure top
616โˆ’ Just [] -> bottom <$ warn (InvalidSchema "no items in enum")
617โˆ’ Just xs -> pure $ joins (valueEnum <$> xs)
618โˆ’
619โˆ’ let maximumClause = case _schemaMaximum of
620โˆ’ Nothing -> top
621โˆ’ Just n ->
622โˆ’ top
623โˆ’ { forNumber = singletonFormula $
624โˆ’ Maximum $
625โˆ’ case _schemaExclusiveMaximum of
626โˆ’ Just True -> Exclusive n
627โˆ’ _ -> Inclusive n
628โˆ’ }
629โˆ’
630โˆ’ minimumClause = case _schemaMinimum of
631โˆ’ Nothing -> top
632โˆ’ Just n ->
633โˆ’ top
634โˆ’ { forNumber = singletonFormula $
635โˆ’ Minimum $
636โˆ’ Down $
637โˆ’ case _schemaExclusiveMinimum of
638โˆ’ Just True -> Exclusive $ Down n
639โˆ’ _ -> Inclusive $ Down n
640โˆ’ }
641โˆ’
642โˆ’ multipleOfClause = case _schemaMultipleOf of
643โˆ’ Nothing -> top
644โˆ’ Just n ->
645โˆ’ top
646โˆ’ { forNumber = singletonFormula $ MultipleOf n
647โˆ’ }
648โˆ’
649โˆ’ formatClause <- case _schemaFormat of
650โˆ’ Nothing -> pure top
651โˆ’ Just f
652โˆ’ | f `elem` ["int32", "int64", "float", "double"] ->
653โˆ’ pure
654โˆ’ top
655โˆ’ { forNumber = singletonFormula $ NumberFormat f
656โˆ’ }
657โˆ’ Just f
658โˆ’ | f `elem` ["byte", "binary", "date", "date-time", "password", "uuid"] ->
659โˆ’ pure
660โˆ’ top
661โˆ’ { forString = singletonFormula $ StringFormat f
662โˆ’ }
663โˆ’ Just f -> top <$ warn (NotSupported $ "Unknown format: " <> f)
664โˆ’
665โˆ’ let maxLengthClause = case _schemaMaxLength of
666โˆ’ Nothing -> top
667โˆ’ Just n ->
668โˆ’ top
669โˆ’ { forString = singletonFormula $ MaxLength n
670โˆ’ }
671โˆ’
672โˆ’ minLengthClause = case _schemaMinLength of
673โˆ’ Nothing -> top
674โˆ’ Just n ->
675โˆ’ top
676โˆ’ { forString = singletonFormula $ MinLength n
677โˆ’ }
678โˆ’
679โˆ’ patternClause = case _schemaPattern of
680โˆ’ Nothing -> top
681โˆ’ Just p ->
682โˆ’ top
683โˆ’ { forString = singletonFormula $ Pattern p
684โˆ’ }
685โˆ’
686โˆ’ itemsClause <- case tracedItems sch of
687โˆ’ Nothing -> pure top
688โˆ’ Just (Left rs) -> do
689โˆ’ f <- silently $ processRefSchema rs
690โˆ’ pure top {forArray = singletonFormula $ Items f rs}
691โˆ’ Just (Right _) -> top <$ warn (NotSupported "array in items is not supported")
692โˆ’
693โˆ’ let maxItemsClause = case _schemaMaxItems of
694โˆ’ Nothing -> top
695โˆ’ Just n ->
696โˆ’ top
697โˆ’ { forArray = singletonFormula $ MaxItems n
698โˆ’ }
699โˆ’
700โˆ’ minItemsClause = case _schemaMinItems of
701โˆ’ Nothing -> top
702โˆ’ Just n ->
703โˆ’ top
704โˆ’ { forArray = singletonFormula $ MinItems n
705โˆ’ }
706โˆ’
707โˆ’ uniqueItemsClause = case _schemaUniqueItems of
708โˆ’ Just True ->
709โˆ’ top
710โˆ’ { forArray = singletonFormula UniqueItems
711โˆ’ }
712โˆ’ _ -> top
713โˆ’
714โˆ’ (addProps, addPropSchema) <- case tracedAdditionalProperties sch of
715โˆ’ Just (Right rs) -> (,Just rs) <$> silently (processRefSchema rs)
716โˆ’ Just (Left False) -> pure (bottom, Nothing)
717โˆ’ _ -> pure (top, Just $ traced (ask sch `Snoc` AdditionalPropertiesStep) $ Inline mempty)
718โˆ’ propList <- forM (S.toList . S.fromList $ IOHM.keys _schemaProperties <> _schemaRequired) $ \k -> do
719โˆ’ (f, psch) <- case IOHM.lookup k $ tracedProperties sch of
720โˆ’ Just rs -> (,rs) <$> silently (processRefSchema rs)
721โˆ’ Nothing ->
722โˆ’ let fakeSchema = traced (ask sch `Snoc` AdditionalPropertiesStep) $ Inline mempty
723โˆ’ in -- The mempty here is incorrect, but if addPropSchema was Nothing, then
724โˆ’ -- addProps is bottom, and k is in _schemaRequired. We handle this situation
725โˆ’ -- below and short-circuit the entire Properties condition to bottom
726โˆ’ pure (addProps, fromMaybe fakeSchema addPropSchema)
727โˆ’ pure (k, Property (k `elem` _schemaRequired) f psch)
728โˆ’ let allBottom f = getAll $
729โˆ’ foldType $ \_ ty -> case ty f of
730โˆ’ BottomFormula -> All True
731โˆ’ _ -> All False
732โˆ’ allTop f = getAll $
733โˆ’ foldType $ \_ ty -> case ty f of
734โˆ’ TopFormula -> All True
735โˆ’ _ -> All False
736โˆ’ -- remove optional fields whose schemata match that of additional props
737โˆ’ propMap = M.filter (\p -> propRequired p || propFormula p /= addProps) $ M.fromList propList
738โˆ’ propertiesClause
739โˆ’ | any (\p -> propRequired p && allBottom (propFormula p)) propMap =
740โˆ’ bottom -- if any required field has unsatisfiable schema
741โˆ’ | M.null propMap
742โˆ’ , allTop addProps =
743โˆ’ top -- if all fields are optional and have trivial schemata
744โˆ’ | otherwise =
745โˆ’ top
746โˆ’ { forObject = singletonFormula $ Properties propMap addProps addPropSchema
747โˆ’ }
748โˆ’
749โˆ’ maxPropertiesClause = case _schemaMaxProperties of
750โˆ’ Nothing -> top
751โˆ’ Just n ->
752โˆ’ top
753โˆ’ { forObject = singletonFormula $ MaxProperties n
754โˆ’ }
755โˆ’
756โˆ’ minPropertiesClause = case _schemaMinProperties of
757โˆ’ Nothing -> top
758โˆ’ Just n ->
759โˆ’ top
760โˆ’ { forObject = singletonFormula $ MinProperties n
761โˆ’ }
762โˆ’
763โˆ’ nullableClause
764โˆ’ | Just True <- _schemaNullable =
765โˆ’ bottom
766โˆ’ { forNull = singletonFormula $ Exactly TNull
767โˆ’ }
768โˆ’ | otherwise = bottom
769โˆ’
770โˆ’ pure $
771โˆ’ nullableClause
772โˆ’ \/ meets
773โˆ’ (allClauses
774โˆ’ <> [ anyClause
775โˆ’ , oneClause
776โˆ’ , typeClause
777โˆ’ , enumClause
778โˆ’ , maximumClause
779โˆ’ , minimumClause
780โˆ’ , multipleOfClause
781โˆ’ , formatClause
782โˆ’ , maxLengthClause
783โˆ’ , minLengthClause
784โˆ’ , patternClause
785โˆ’ , itemsClause
786โˆ’ , maxItemsClause
787โˆ’ , minItemsClause
788โˆ’ , uniqueItemsClause
789โˆ’ , propertiesClause
790โˆ’ , maxPropertiesClause
791โˆ’ , minPropertiesClause
792โˆ’ ])
793โˆ’
794โˆ’{- TODO: ReadOnly/WriteOnly #68 -}
795โˆ’
796โˆ’checkOneOfDisjoint :: MonadProcess m => [Traced (Referenced Schema)] -> m Bool
797โˆ’checkOneOfDisjoint = const $ pure True -- TODO #69
798โˆ’
799โˆ’schemaToFormula
800โˆ’ :: Traced (Definitions Schema)
801โˆ’ -> Traced Schema
802โˆ’ -> (ForeachType JsonFormula, P.PathsPrefixTree Behave AnIssue 'SchemaLevel)
803โˆ’schemaToFormula defs rs = runWriter . (`runReaderT` defs) . runMemo () $ processSchema rs
804โˆ’
805โˆ’checkFormulas
806โˆ’ :: (HasAll (CheckEnv Schema) xs)
807โˆ’ => HList xs
808โˆ’ -> Behavior 'SchemaLevel
809โˆ’ -> ProdCons (ForeachType JsonFormula, P.PathsPrefixTree Behave AnIssue 'SchemaLevel)
810โˆ’ -> SemanticCompatFormula ()
811โˆ’checkFormulas env beh (ProdCons (fp, ep) (fc, ec)) =
812โˆ’ case P.toList ep ++ P.toList ec of
813โˆ’ issues@(_ : _) -> F.for_ issues $ \(AnItem t (AnIssue e)) -> issueAt (beh >>> t) e
814โˆ’ [] -> do
815โˆ’ -- We have the following isomorphisms:
816โˆ’ -- (A โŠ‚ X โˆช Y) = (A โŠ‚ X) \/ (A โŠ‚ Y)
817โˆ’ -- (A โŠ‚ X โˆฉ Y) = (A โŠ‚ X) /\ (A โŠ‚ Y)
818โˆ’ -- (A โŠ‚ โŠค) = 1
819โˆ’ -- (X โˆช Y โŠ‚ B) = (X โŠ‚ B) /\ (Y โŠ‚ B)
820โˆ’ -- (โˆ… โŠ‚ B) = 1
821โˆ’ -- The remaining cases are, notably, not isomorphisms:
822โˆ’ -- 1) (A โŠ‚ โˆ…) <= 0
823โˆ’ -- 2) (X โˆฉ Y โŠ‚ B) <= (X โŠ‚ B) \/ (Y โŠ‚ B)
824โˆ’ -- 3) (โŠค โŠ‚ B) <= 0
825โˆ’ -- Therefore we have the isomorphisms:
826โˆ’ -- (โ‹ƒ_i โ‹‚_j A[i,j]) โŠ‚ (โ‹ƒ_k โ‹‚_l B[k,l])
827โˆ’ -- = \/_k /\_l /\_i (โ‹‚_j A[i,j]) โŠ‚ B[k,l]
828โˆ’ -- = /\_i \/_k /\_l (โ‹‚_j A[i,j]) โŠ‚ B[k,l]
829โˆ’ -- with the caveat that the the set over which k ranges is nonempty.
830โˆ’ -- This is because 1) is not an isomorphism.
831โˆ’ -- Our disjunction loses information, so it makes sense to nest it as
832โˆ’ -- deeply as possible, hence we choose the latter representation.
833โˆ’ --
834โˆ’ -- We delegate the verification of (โ‹‚_j A[j]) โŠ‚ B to a separate heuristic
835โˆ’ -- function, with the understanding that \/_j A[j] โŠ‚ B is a sufficient,
836โˆ’ -- but not necessary condition (because of 2) and 3)).
837โˆ’ --
838โˆ’ -- If k ranges over an empty set, we have the isomorphism:
839โˆ’ -- (โ‹ƒ_i โ‹‚_j A[i,j]) โŠ‚ โˆ… = /\_i (โ‹‚_j A[i,j]) โŠ‚ โˆ…
840โˆ’ -- where we again delegate (โ‹‚_j A[j]) โŠ‚ โˆ… to a heuristic, though here the
841โˆ’ -- shortcut of \/_j A[j] โŠ‚ โˆ… hardly helps.
842โˆ’ forType_ $ \tyName ty -> do
843โˆ’ let beh' = beh >>> step (OfType tyName)
844โˆ’ case (ty fp, ty fc) of
845โˆ’ (DNF pss, BottomFormula) -> F.for_ pss $ \(Conjunct ps) -> checkContradiction beh' ps
846โˆ’ (DNF pss, SingleConjunct cs) -> F.for_ pss $ \(Conjunct ps) -> do
847โˆ’ F.for_ cs $ checkImplication env beh' ps -- avoid disjuntion if there's only one conjunct
848โˆ’ (DNF pss, DNF css) -> F.for_ pss $ \(Conjunct ps) -> do
849โˆ’ anyOfAt
850โˆ’ beh'
851โˆ’ (issueFromConjunct ps)
852โˆ’ [F.for_ cs $ checkImplication env beh' ps | Conjunct cs <- S.toList css]
853โˆ’ where
854โˆ’ issueFromConjunct :: Typeable t => [Condition t] -> Issue 'TypedSchemaLevel
855โˆ’ issueFromConjunct ps
856โˆ’ | Just e <- findExactly ps
857โˆ’ , all (satisfiesTyped e) ps =
858โˆ’ EnumDoesntSatisfy $ untypeValue e
859โˆ’ issueFromConjunct ps = NoMatchingCondition $ SomeCondition <$> ps
860โˆ’
861โˆ’checkContradiction
862โˆ’ :: Behavior 'TypedSchemaLevel
863โˆ’ -> [Condition t]
864โˆ’ -> SemanticCompatFormula ()
865โˆ’checkContradiction beh _ = issueAt beh NoContradiction -- TODO #70
866โˆ’
867โˆ’checkImplication
868โˆ’ :: (HasAll (CheckEnv Schema) xs)
869โˆ’ => HList xs
870โˆ’ -> Behavior 'TypedSchemaLevel
871โˆ’ -> [Condition t]
872โˆ’ -> Condition t
873โˆ’ -> SemanticCompatFormula ()
874โˆ’checkImplication env beh prods cons = case findExactly prods of
875โˆ’ Just e
876โˆ’ | all (satisfiesTyped e) prods ->
877โˆ’ if satisfiesTyped e cons
878โˆ’ then pure ()
879โˆ’ else issueAt beh (EnumDoesntSatisfy $ untypeValue e)
880โˆ’ | otherwise -> pure () -- vacuously true
881โˆ’ Nothing -> case cons of
882โˆ’ -- the above code didn't catch it, so there's no Exactly condition on the lhs
883โˆ’ Exactly e -> issueAt beh (NoMatchingEnum $ untypeValue e)
884โˆ’ Maximum m -> case findRelevant min (\case Maximum m' -> Just m'; _ -> Nothing) prods of
885โˆ’ Just m' ->
886โˆ’ if m' <= m
887โˆ’ then pure ()
888โˆ’ else issueAt beh (MatchingMaximumWeak $ ProdCons {producer = m', consumer = m})
889โˆ’ Nothing -> issueAt beh (NoMatchingMaximum m)
890โˆ’ Minimum m -> case findRelevant max (\case Minimum m' -> Just m'; _ -> Nothing) prods of
891โˆ’ Just m' ->
892โˆ’ if m' >= m
893โˆ’ then pure ()
894โˆ’ else issueAt beh (MatchingMinimumWeak ProdCons {producer = coerce m', consumer = coerce m})
895โˆ’ Nothing -> issueAt beh (NoMatchingMinimum (coerce m))
896โˆ’ MultipleOf m -> case findRelevant lcmScientific (\case MultipleOf m' -> Just m'; _ -> Nothing) prods of
897โˆ’ Just m' ->
898โˆ’ if lcmScientific m m' == m'
899โˆ’ then pure ()
900โˆ’ else issueAt beh (MatchingMultipleOfWeak $ ProdCons {producer = m', consumer = m})
901โˆ’ Nothing -> issueAt beh (NoMatchingMultipleOf m)
902โˆ’ NumberFormat f ->
903โˆ’ if any (\case NumberFormat f' -> f == f'; _ -> False) prods
904โˆ’ then pure ()
905โˆ’ else issueAt beh (NoMatchingFormat f)
906โˆ’ MaxLength m -> case findRelevant min (\case MaxLength m' -> Just m'; _ -> Nothing) prods of
907โˆ’ Just m' ->
908โˆ’ if m' <= m
909โˆ’ then pure ()
910โˆ’ else issueAt beh (MatchingMaxLengthWeak $ ProdCons {producer = m', consumer = m})
911โˆ’ Nothing -> issueAt beh (NoMatchingMaxLength m)
912โˆ’ MinLength m -> case findRelevant max (\case MinLength m' -> Just m'; _ -> Nothing) prods of
913โˆ’ Just m' ->
914โˆ’ if m' >= m
915โˆ’ then pure ()
916โˆ’ else issueAt beh (MatchingMinLengthWeak $ ProdCons {producer = m', consumer = m})
917โˆ’ Nothing -> issueAt beh (NoMatchingMinLength m)
918โˆ’ Pattern p ->
919โˆ’ if any (\case Pattern p' -> p == p'; _ -> False) prods
920โˆ’ then pure ()
921โˆ’ else issueAt beh (NoMatchingPattern p) -- TODO: regex comparison #32
922โˆ’ StringFormat f ->
923โˆ’ if any (\case StringFormat f' -> f == f'; _ -> False) prods
924โˆ’ then pure ()
925โˆ’ else issueAt beh (NoMatchingFormat f)
926โˆ’ Items _ cons' -> case findRelevant (<>) (\case Items _ rs -> Just (rs NE.:| []); _ -> Nothing) prods of
927โˆ’ Just (rs NE.:| []) -> checkCompatibility env (beh >>> step InItems) $ ProdCons rs cons'
928โˆ’ Just rs -> do
929โˆ’ let sch = Inline mempty {_schemaAllOf = Just . NE.toList $ extract <$> rs}
930โˆ’ checkCompatibility env (beh >>> step InItems) $ ProdCons (traced (ask $ NE.head rs) sch) cons' -- TODO: bad trace
931โˆ’ Nothing -> issueAt beh NoMatchingItems
932โˆ’ MaxItems m -> case findRelevant min (\case MaxItems m' -> Just m'; _ -> Nothing) prods of
933โˆ’ Just m' ->
934โˆ’ if m' <= m
935โˆ’ then pure ()
936โˆ’ else issueAt beh (MatchingMaxItemsWeak ProdCons {producer = m', consumer = m})
937โˆ’ Nothing -> issueAt beh (NoMatchingMaxItems m)
938โˆ’ MinItems m -> case findRelevant max (\case MinItems m' -> Just m'; _ -> Nothing) prods of
939โˆ’ Just m' ->
940โˆ’ if m' >= m
941โˆ’ then pure ()
942โˆ’ else issueAt beh (MatchingMinItemsWeak ProdCons {producer = m', consumer = m})
943โˆ’ Nothing -> issueAt beh (NoMatchingMinItems m)
944โˆ’ UniqueItems ->
945โˆ’ if any (== UniqueItems) $ prods
946โˆ’ then pure ()
947โˆ’ else issueAt beh NoMatchingUniqueItems
948โˆ’ Properties props _ madd -> case findRelevant (<>) (\case Properties props' _ madd' -> Just $ (props', madd') NE.:| []; _ -> Nothing) prods of
949โˆ’ Just pm ->
950โˆ’ anyOfAt beh NoMatchingProperties $
951โˆ’ NE.toList pm <&> \(props', madd') -> do
952โˆ’ F.for_ (S.fromList $ M.keys props <> M.keys props') $ \k -> do
953โˆ’ case (maybe False propRequired $ M.lookup k props', maybe False propRequired $ M.lookup k props) of
954โˆ’ -- producer does not require field, but consumer does (can fail)
955โˆ’ (False, True) -> issueAt beh (PropertyNowRequired k)
956โˆ’ _ -> do
957โˆ’ let go sch sch' = checkCompatibility env (beh >>> step (InProperty k)) (ProdCons sch sch')
958โˆ’ case (M.lookup k props', madd', M.lookup k props, madd) of
959โˆ’ -- (producer, additional producer, consumer, additional consumer)
960โˆ’ (Nothing, Nothing, _, _) -> pure () -- vacuously
961โˆ’ -- this ^ seems fishy. Producer does not produce anything, but consumer might expect a field.
962โˆ’ (_, _, Nothing, Nothing) -> issueAt beh (UnexpectedProperty k)
963โˆ’ (Just p', _, Just p, _) -> go (propRefSchema p') (propRefSchema p)
964โˆ’ (Nothing, Just add', Just p, _) -> go add' (propRefSchema p)
965โˆ’ (Just p', _, Nothing, Just add) -> go (propRefSchema p') add
966โˆ’ (Nothing, Just _, Nothing, Just _) -> pure ()
967โˆ’ case (madd', madd) of
968โˆ’ (Nothing, _) -> pure () -- vacuously
969โˆ’ (_, Nothing) -> issueAt beh NoAdditionalProperties
970โˆ’ (Just add', Just add) -> checkCompatibility env (beh >>> step InAdditionalProperty) (ProdCons add' add)
971โˆ’ pure ()
972โˆ’ Nothing -> issueAt beh NoMatchingProperties
973โˆ’ MaxProperties m -> case findRelevant min (\case MaxProperties m' -> Just m'; _ -> Nothing) prods of
974โˆ’ Just m' ->
975โˆ’ if m' <= m
976โˆ’ then pure ()
977โˆ’ else issueAt beh (MatchingMaxPropertiesWeak ProdCons {producer = m', consumer = m})
978โˆ’ Nothing -> issueAt beh (NoMatchingMaxProperties m)
979โˆ’ MinProperties m -> case findRelevant max (\case MinProperties m' -> Just m'; _ -> Nothing) prods of
980โˆ’ Just m' ->
981โˆ’ if m' >= m
982โˆ’ then pure ()
983โˆ’ else issueAt beh (MatchingMinPropertiesWeak ProdCons {producer = m', consumer = m})
984โˆ’ Nothing -> issueAt beh (NoMatchingMinProperties m)
985โˆ’ where
986โˆ’ findRelevant combine extr =
987โˆ’ fmap (foldr1 combine) . NE.nonEmpty . mapMaybe extr
988โˆ’ lcmScientific (toRational -> a) (toRational -> b) =
989โˆ’ fromRational $ lcm (numerator a) (numerator b) % gcd (denominator a) (denominator b)
990โˆ’
991โˆ’findExactly :: [Condition t] -> Maybe (TypedValue t)
992โˆ’findExactly (Exactly x : _) = Just x
993โˆ’findExactly (_ : xs) = findExactly xs
994โˆ’findExactly [] = Nothing
995โˆ’
996โˆ’instance Issuable 'TypedSchemaLevel where
997โˆ’ data Issue 'TypedSchemaLevel
998โˆ’ = -- | producer produces a specific value ($1), consumer has a condition that is not satisfied by said value
999โˆ’ EnumDoesntSatisfy A.Value
1000โˆ’ | -- | consumer only expects a specific value which the producer does not produce.
1001โˆ’ NoMatchingEnum A.Value
1002โˆ’ | -- | consumer declares a maximum numeric value ($1), producer doesn't
1003โˆ’ NoMatchingMaximum (Bound Scientific)
1004โˆ’ | -- | consumer declares a maximum numeric value ($1), producer declares a weaker (higher) limit ($2)
1005โˆ’ MatchingMaximumWeak (ProdCons (Bound Scientific))
1006โˆ’ | -- | consumer declares a minimum numeric value, producer doesn't
1007โˆ’ NoMatchingMinimum (Bound Scientific)
1008โˆ’ | -- | consumer declares a minimum numeric value ($1), producer declares a weaker (lower) limit ($2)
1009โˆ’ MatchingMinimumWeak (ProdCons (Bound Scientific))
1010โˆ’ | -- | consumer declares that the numeric value must be a multiple of $1, producer doesn't
1011โˆ’ NoMatchingMultipleOf Scientific
1012โˆ’ | -- | consumer declares that the numeric value must be a multiple of $1, producer declares a weaker condition (multiple of $2)
1013โˆ’ MatchingMultipleOfWeak (ProdCons Scientific)
1014โˆ’ | -- | consumer declares a string/number format, producer declares none or a different format (TODO: improve via regex #32)
1015โˆ’ NoMatchingFormat Format
1016โˆ’ | -- | consumer declares a maximum length of the string ($1), producer doesn't.
1017โˆ’ NoMatchingMaxLength Integer
1018โˆ’ | -- | consumer declares a maximum length of the string ($1), producer declares a weaker (higher) limit ($2)
1019โˆ’ MatchingMaxLengthWeak (ProdCons Integer)
1020โˆ’ | -- | consumer declares a minimum length of the string ($1), producer doesn't.
1021โˆ’ NoMatchingMinLength Integer
1022โˆ’ | -- | consumer declares a minimum length of the string ($1), producer declares a weaker (lower) limit ($2)
1023โˆ’ MatchingMinLengthWeak (ProdCons Integer)
1024โˆ’ | -- | consumer declares the string value must match a regex ($1), producer doesn't declare or declares different regex (TODO: #32)
1025โˆ’ NoMatchingPattern Pattern
1026โˆ’ | -- | consumer declares the items of an array must satisfy some condition, producer doesn't
1027โˆ’ NoMatchingItems
1028โˆ’ | -- | consumer declares a maximum length of the array ($1), producer doesn't.
1029โˆ’ NoMatchingMaxItems Integer
1030โˆ’ | -- | consumer declares a maximum length of the array ($1), producer declares a weaker (higher) limit ($2)
1031โˆ’ MatchingMaxItemsWeak (ProdCons Integer)
1032โˆ’ | -- | consumer declares a minimum length of the array ($1), producer doesn't.
1033โˆ’ NoMatchingMinItems Integer
1034โˆ’ | -- | consumer declares a minimum length of the array ($1), producer declares a weaker (lower) limit ($2)
1035โˆ’ MatchingMinItemsWeak (ProdCons Integer)
1036โˆ’ | -- | consumer declares that items must be unique, producer doesn't
1037โˆ’ NoMatchingUniqueItems
1038โˆ’ | -- | consumer declares the properties of an object must satisfy some condition, producer doesn't
1039โˆ’ NoMatchingProperties
1040โˆ’ | -- | producer allows a property that is not allowed in the consumer
1041โˆ’ UnexpectedProperty Text
1042โˆ’ | -- | consumer requires a property that is not required/allowed in the producer
1043โˆ’ PropertyNowRequired Text
1044โˆ’ | -- | producer allows additional properties, consumer doesn't
1045โˆ’ NoAdditionalProperties
1046โˆ’ | -- | consumer declares a maximum number of properties in the object ($1), producer doesn't.
1047โˆ’ NoMatchingMaxProperties Integer
1048โˆ’ | -- | consumer declares a maximum number of properties in the object ($1), producer declares a weaker (higher) limit ($2)
1049โˆ’ MatchingMaxPropertiesWeak (ProdCons Integer)
1050โˆ’ | -- | consumer declares a minimum number of properties in the object ($1), producer doesn't.
1051โˆ’ NoMatchingMinProperties Integer
1052โˆ’ | -- | consumer declares a minimum number of properties in the object ($1), producer declares a weaker (lower) limit ($2)
1053โˆ’ MatchingMinPropertiesWeak (ProdCons Integer)
1054โˆ’ | -- | producer declares that the value must satisfy a disjunction of some conditions, but consumer's requirements couldn't be matched against any single one of them (TODO: split heuristic #71)
1055โˆ’ NoMatchingCondition [SomeCondition]
1056โˆ’ | -- | consumer indicates that values of this type are now allowed, but the producer does not do so (currently we only check immediate contradictions, c.f. #70)
1057โˆ’ NoContradiction
1058โˆ’ deriving stock (Eq, Ord, Show)
1059โˆ’ issueIsUnsupported _ = False
1060โˆ’ describeIssue Forward (EnumDoesntSatisfy v) = para "The following enum value was added:" <> showJSONValue v
1061โˆ’ describeIssue Backward (EnumDoesntSatisfy v) = para "The following enum value was removed:" <> showJSONValue v
1062โˆ’ describeIssue Forward (NoMatchingEnum v) = para "The following enum value has been removed:" <> showJSONValue v
1063โˆ’ describeIssue Backward (NoMatchingEnum v) = para "The following enum value has been added:" <> showJSONValue v
1064โˆ’ describeIssue Forward (NoMatchingMaximum b) = para $ "Upper bound has been added:" <> showBound b <> "."
1065โˆ’ describeIssue Backward (NoMatchingMaximum b) = para $ "Upper bound has been removed:" <> showBound b <> "."
1066โˆ’ describeIssue _ (MatchingMaximumWeak (ProdCons p c)) = para $ "Upper bound changed from " <> showBound p <> " to " <> showBound c <> "."
1067โˆ’ describeIssue Forward (NoMatchingMinimum b) = para $ "Lower bound has been added: " <> showBound b <> "."
1068โˆ’ describeIssue Backward (NoMatchingMinimum b) = para $ "Lower bound has been removed: " <> showBound b <> "."
1069โˆ’ describeIssue _ (MatchingMinimumWeak (ProdCons p c)) = para $ "Lower bound changed from " <> showBound p <> " to " <> showBound c <> "."
1070โˆ’ describeIssue Forward (NoMatchingMultipleOf n) = para $ "Value is now a multiple of " <> show' n <> "."
1071โˆ’ describeIssue Backward (NoMatchingMultipleOf n) = para $ "Value is no longer a multiple of " <> show' n <> "."
1072โˆ’ describeIssue _ (MatchingMultipleOfWeak (ProdCons p c)) = para $ "Value changed from being a multiple of " <> show' p <> " to being a multiple of " <> show' c <> "."
1073โˆ’ describeIssue Forward (NoMatchingFormat f) = para $ "Format added: " <> code f <> "."
1074โˆ’ describeIssue Backward (NoMatchingFormat f) = para $ "Format removed: " <> code f <> "."
1075โˆ’ describeIssue Forward (NoMatchingMaxLength n) = para $ "Maximum length added: " <> show' n <> "."
1076โˆ’ describeIssue Backward (NoMatchingMaxLength n) = para $ "Maximum length removed: " <> show' n <> "."
1077โˆ’ describeIssue _ (MatchingMaxLengthWeak (ProdCons p c)) = para $ "Maximum length of the string changed from " <> show' p <> " to " <> show' c <> "."
1078โˆ’ describeIssue Forward (NoMatchingMinLength n) = para $ "Minimum length of the string added: " <> show' n <> "."
1079โˆ’ describeIssue Backward (NoMatchingMinLength n) = para $ "Minimum length of the string removed: " <> show' n <> "."
1080โˆ’ describeIssue _ (MatchingMinLengthWeak (ProdCons p c)) = para $ "Minimum length of the string changed from " <> show' p <> " to " <> show' c <> "."
1081โˆ’ describeIssue Forward (NoMatchingPattern p) = para "Pattern (regular expression) added: " <> codeBlock p
1082โˆ’ describeIssue Backward (NoMatchingPattern p) = para "Pattern (regular expression) removed: " <> codeBlock p
1083โˆ’ describeIssue Forward NoMatchingItems = para "Array item schema has been added."
1084โˆ’ describeIssue Backward NoMatchingItems = para "Array item schema has been removed."
1085โˆ’ describeIssue Forward (NoMatchingMaxItems n) = para $ "Maximum length of the array has been added " <> show' n <> "."
1086โˆ’ describeIssue Backward (NoMatchingMaxItems n) = para $ "Maximum length of the array has been removed " <> show' n <> "."
1087โˆ’ describeIssue _ (MatchingMaxItemsWeak (ProdCons p c)) = para $ "Maximum length of the array changed from " <> show' p <> " to " <> show' c <> "."
1088โˆ’ describeIssue Forward (NoMatchingMinItems n) = para $ "Minimum length of the array added: " <> show' n <> "."
1089โˆ’ describeIssue Backward (NoMatchingMinItems n) = para $ "Minimum length of the array removed: " <> show' n <> "."
1090โˆ’ describeIssue _ (MatchingMinItemsWeak (ProdCons p c)) = para $ "Minimum length of the array changed from " <> show' p <> " to " <> show' c <> "."
1091โˆ’ describeIssue Forward NoMatchingUniqueItems = para "Items are now required to be unique."
1092โˆ’ describeIssue Backward NoMatchingUniqueItems = para "Items are no longer required to be unique."
1093โˆ’ describeIssue Forward NoMatchingProperties = para "Property added."
1094โˆ’ describeIssue Backward NoMatchingProperties = para "Property removed."
1095โˆ’ describeIssue Forward (UnexpectedProperty p) = para $ "Property " <> code p <> " has been removed."
1096โˆ’ describeIssue Backward (UnexpectedProperty p) = para $ "Property " <> code p <> " has been added."
1097โˆ’ describeIssue Forward (PropertyNowRequired p) = para $ "Property " <> code p <> " has become required."
1098โˆ’ describeIssue Backward (PropertyNowRequired p) = para $ "Property " <> code p <> " may not be present."
1099โˆ’ describeIssue Forward NoAdditionalProperties = para "Additional properties have been removed."
1100โˆ’ describeIssue Backward NoAdditionalProperties = para "Additional properties have been added."
1101โˆ’ describeIssue Forward (NoMatchingMaxProperties n) = para $ "Maximum number of properties has been added: " <> show' n <> "."
1102โˆ’ describeIssue Backward (NoMatchingMaxProperties n) = para $ "Maximum number of properties has been removed: " <> show' n <> "."
1103โˆ’ describeIssue _ (MatchingMaxPropertiesWeak (ProdCons p c)) = para $ "Maximum number of properties has changed from " <> show' p <> " to " <> show' c <> "."
1104โˆ’ describeIssue Forward (NoMatchingMinProperties n) = para $ "Minimum number of properties added: " <> show' n <> "."
1105โˆ’ describeIssue Backward (NoMatchingMinProperties n) = para $ "Minimum number of properties removed: " <> show' n <> "."
1106โˆ’ describeIssue _ (MatchingMinPropertiesWeak (ProdCons p c)) = para $ "Minimum number of properties has changed from " <> show' p <> " to " <> show' c <> "."
1107โˆ’ describeIssue _ (NoMatchingCondition conds) =
1108โˆ’ para "Expected the following conditions to hold, but they didn't (please file a bug if you see this):"
1109โˆ’ <> bulletList ((\(SomeCondition c) -> showCondition c) <$> conds)
1110โˆ’ describeIssue Forward NoContradiction = para "The type has been removed."
1111โˆ’ describeIssue Backward NoContradiction = para "The type has been added."
1112โˆ’
1113โˆ’showJSONValue :: A.Value -> Blocks
1114โˆ’showJSONValue v = codeBlockWith ("", ["json"], mempty) (T.decodeUtf8 . BSL.toStrict . A.encode $ v)
1115โˆ’
1116โˆ’showBound :: Show a => Bound a -> Inlines
1117โˆ’showBound (Inclusive x) = show' x <> " inclusive"
1118โˆ’showBound (Exclusive x) = show' x <> " exclusive"
1119โˆ’
1120โˆ’show' :: Show x => x -> Inlines
1121โˆ’show' = str . T.pack . show
1122โˆ’
1123โˆ’instance Issuable 'SchemaLevel where
1124โˆ’ data Issue 'SchemaLevel
1125โˆ’ = -- | Some (openapi-supported) feature that we do not support was encountered in the schema
1126โˆ’ NotSupported Text
1127โˆ’ | -- | The schema is actually invalid
1128โˆ’ InvalidSchema Text
1129โˆ’ | -- | The schema contains a reference loop along "anyOf"/"allOf"/"oneOf".
1130โˆ’ UnguardedRecursion
1131โˆ’ deriving stock (Eq, Ord, Show)
1132โˆ’ issueIsUnsupported _ = True
1133โˆ’
1134โˆ’ describeIssue _ (NotSupported i) =
1135โˆ’ para (emph "Encountered a feature that OpenApi Diff does not support: " <> text i <> ".")
1136โˆ’ describeIssue _ (InvalidSchema i) =
1137โˆ’ para (emph "The schema is invalid: " <> text i <> ".")
1138โˆ’ describeIssue _ UnguardedRecursion =
1139โˆ’ para "Encountered recursion that is too complex for OpenApi Diff to untangle."
1140โˆ’
1141โˆ’instance Behavable 'SchemaLevel 'TypedSchemaLevel where
1142โˆ’ data Behave 'SchemaLevel 'TypedSchemaLevel
1143โˆ’ = OfType JsonType
1144โˆ’ deriving stock (Eq, Ord, Show)
1145โˆ’
1146โˆ’ describeBehaviour (OfType t) = describeJSONType t
1147โˆ’
1148โˆ’describeJSONType :: IsString s => JsonType -> s
1149โˆ’describeJSONType = \case
1150โˆ’ Null -> "Null"
1151โˆ’ Boolean -> "Boolean"
1152โˆ’ Number -> "Number"
1153โˆ’ String -> "String"
1154โˆ’ Array -> "Array"
1155โˆ’ Object -> "Object"
1156โˆ’
1157โˆ’instance Behavable 'TypedSchemaLevel 'SchemaLevel where
1158โˆ’ data Behave 'TypedSchemaLevel 'SchemaLevel
1159โˆ’ = InItems
1160โˆ’ | InProperty Text
1161โˆ’ | InAdditionalProperty
1162โˆ’ deriving stock (Eq, Ord, Show)
1163โˆ’
1164โˆ’ describeBehaviour InItems = "Items"
1165โˆ’ describeBehaviour (InProperty p) = "Property " <> code p
1166โˆ’ describeBehaviour InAdditionalProperty = "Additional properties"
1167โˆ’
1168โˆ’instance Subtree Schema where
1169โˆ’ type SubtreeLevel Schema = 'SchemaLevel
1170โˆ’ type CheckEnv Schema = '[ProdCons (Traced (Definitions Schema))]
1171โˆ’ checkStructuralCompatibility env pc = do
1172โˆ’ structuralEq $ fmap _schemaRequired <$> pc
1173โˆ’ structuralEq $ fmap _schemaNullable <$> pc
1174โˆ’ structuralMaybeWith (structuralList env) $ tracedAllOf <$> pc
1175โˆ’ structuralMaybeWith (structuralList env) $ tracedOneOf <$> pc
1176โˆ’ structuralMaybe env $ sequence . stepTraced NotStep . fmap _schemaNot <$> pc
1177โˆ’ structuralMaybeWith (structuralList env) $ tracedAnyOf <$> pc
1178โˆ’ iohmStructural env $ stepTraced PropertiesStep . fmap _schemaProperties <$> pc
1179โˆ’ structuralMaybeWith structuralAdditionalProperties $ tracedAdditionalProperties <$> pc
1180โˆ’ structuralMaybeWith structuralDiscriminator $ tracedDiscriminator <$> pc
1181โˆ’ structuralEq $ fmap _schemaReadOnly <$> pc
1182โˆ’ structuralEq $ fmap _schemaWriteOnly <$> pc
1183โˆ’ structuralEq $ fmap _schemaXml <$> pc
1184โˆ’ structuralEq $ fmap _schemaMaxProperties <$> pc
1185โˆ’ structuralEq $ fmap _schemaMinProperties <$> pc
1186โˆ’ structuralEq $ fmap _schemaDefault <$> pc
1187โˆ’ structuralEq $ fmap _schemaType <$> pc
1188โˆ’ structuralEq $ fmap _schemaFormat <$> pc
1189โˆ’ structuralMaybeWith structuralItems $ tracedItems <$> pc
1190โˆ’ structuralEq $ fmap _schemaMaximum <$> pc
1191โˆ’ structuralEq $ fmap _schemaExclusiveMaximum <$> pc
1192โˆ’ structuralEq $ fmap _schemaMinimum <$> pc
1193โˆ’ structuralEq $ fmap _schemaExclusiveMinimum <$> pc
1194โˆ’ structuralEq $ fmap _schemaMaxLength <$> pc
1195โˆ’ structuralEq $ fmap _schemaMinLength <$> pc
1196โˆ’ structuralEq $ fmap _schemaPattern <$> pc
1197โˆ’ structuralEq $ fmap _schemaMaxItems <$> pc
1198โˆ’ structuralEq $ fmap _schemaMinItems <$> pc
1199โˆ’ structuralEq $ fmap _schemaUniqueItems <$> pc
1200โˆ’ structuralEq $ fmap _schemaEnum <$> pc
1201โˆ’ structuralEq $ fmap _schemaMultipleOf <$> pc
1202โˆ’ pure ()
1203โˆ’ where
1204โˆ’ structuralAdditionalProperties
1205โˆ’ (ProdCons (Left x) (Left y)) = unless (x == y) structuralIssue
1206โˆ’ structuralAdditionalProperties
1207โˆ’ (ProdCons (Right x) (Right y)) =
1208โˆ’ checkSubstructure env $ ProdCons x y
1209โˆ’ structuralAdditionalProperties _ = structuralIssue
1210โˆ’ structuralDiscriminator pc' = do
1211โˆ’ structuralEq $ fmap _discriminatorPropertyName <$> pc'
1212โˆ’ iohmStructural env $
1213โˆ’ stepTraced DiscriminatorMapping . fmap (fmap parseDiscriminatorValue . _discriminatorMapping) <$> pc'
1214โˆ’ pure ()
1215โˆ’ structuralItems (ProdCons (Left a) (Left b)) =
1216โˆ’ checkSubstructure env $ ProdCons a b
1217โˆ’ structuralItems (ProdCons (Right a) (Right b)) =
1218โˆ’ structuralList env $ ProdCons a b
1219โˆ’ structuralItems _ = structuralIssue
1220โˆ’ checkSemanticCompatibility env beh schs = do
1221โˆ’ let defs = getH env
1222โˆ’ checkFormulas env beh $ schemaToFormula <$> defs <*> schs
src/OpenAPI/Checker/Validate/Sums.hsdeletedโˆ’24
@@ -1,24 +0,0 @@
1โˆ’module OpenAPI.Checker.Validate.Sums
2โˆ’ ( checkSums
3โˆ’ ) where
4โˆ’
5โˆ’import Data.Foldable
6โˆ’import Data.Map.Strict (Map)
7โˆ’import qualified Data.Map.Strict as M
8โˆ’import OpenAPI.Checker.Behavior
9โˆ’import OpenAPI.Checker.Subtree
10โˆ’import OpenAPI.Checker.Paths
11โˆ’
12โˆ’checkSums
13โˆ’ :: (Ord k, Issuable l)
14โˆ’ => Paths q r l
15โˆ’ -> (k -> Issue l)
16โˆ’ -> (k -> ProdCons t -> CompatFormula' q AnIssue r ())
17โˆ’ -> ProdCons (Map k t)
18โˆ’ -> CompatFormula' q AnIssue r ()
19โˆ’checkSums xs noElt check (ProdCons p c) = for_ (M.toList p) $ \(key, prodElt) ->
20โˆ’ case M.lookup key c of
21โˆ’ Nothing -> issueAt xs $ noElt key
22โˆ’ Just consElt ->
23โˆ’ let sumElts = ProdCons prodElt consElt
24โˆ’ in check key sumElts
stack.yaml+7โˆ’4
@@ -1,8 +1,11 @@
1โˆ’resolver: lts-18.0
1+resolver: lts-18.16
2+
3+packages:
4+ - .
2
5
3extra-deps:
6extra-deps:
4 - open-union-0.4.0.0
7 - open-union-0.4.0.0
5 - type-fun-0.1.3
8 - type-fun-0.1.3
6โˆ’
9+ - github-0.26
7โˆ’apply-ghc-options: everything
10+ - base16-bytestring-0.1.1.7
8โˆ’rebuild-ghc-options: true
11+ - http-link-header-1.0.3.1
stack.yaml.lock+25โˆ’4
@@ -18,9 +18,30 @@ packages:
18 sha256: b977d42525f0b4223959918d18e7905085283e937493c395077b608cd19b42c1
18 sha256: b977d42525f0b4223959918d18e7905085283e937493c395077b608cd19b42c1
19 original:
19 original:
20 hackage: type-fun-0.1.3
20 hackage: type-fun-0.1.3
21+- completed:
22+ hackage: github-0.26@sha256:a9d4046325c3eb28cdc7bef2c3f5bb213328caeae0b7dce6f51de655f0bffaa1,7162
23+ pantry-tree:
24+ size: 7511
25+ sha256: b71aab2984b268030c9e2617043575681134c1fe60dffbd5596e659c0a3e9aec
26+ original:
27+ hackage: github-0.26
28+- completed:
29+ hackage: base16-bytestring-0.1.1.7@sha256:0021256a9628971c08da95cb8f4d0d72192f3bb8a7b30b55c080562d17c43dd3,2231
30+ pantry-tree:
31+ size: 454
32+ sha256: 2dc99cd67293b09204098202d0bdcdcf89d2b8c69ce6c8f4e31deadbdab2a7f9
33+ original:
34+ hackage: base16-bytestring-0.1.1.7
35+- completed:
36+ hackage: http-link-header-1.0.3.1@sha256:9917c26635a46eff5d36c5344a4ae42fad2b5de79c0e300363bddd5eec66facd,1937
37+ pantry-tree:
38+ size: 990
39+ sha256: 155feaf856daf5b55491048c8c4726ba765a8fe79263ebdbfc82f6c385a15715
40+ original:
41+ hackage: http-link-header-1.0.3.1
21snapshots:
42snapshots:
22- completed:
43- completed:
23โˆ’ size: 585393
44+ size: 586286
24โˆ’ url: https://raw.githubusercontent.com/commercialhaskell/stackage-snapshots/master/lts/18/0.yaml
45+ url: https://raw.githubusercontent.com/commercialhaskell/stackage-snapshots/master/lts/18/16.yaml
25โˆ’ sha256: c632012da648385b9fa3c29f4e0afd56ead299f1c5528ee789058be410e883c0
46+ sha256: cdead65fca0323144b346c94286186f4969bf85594d649c49c7557295675d8a5
26โˆ’ original: lts-18.0
47+ original: lts-18.16
test/README.md+1โˆ’1
@@ -30,7 +30,7 @@ This test would read the files `a.yaml` and `b.yaml` using the `Yaml.decodeFileT
30
30
31## Supported feature tests
31## Supported feature tests
32
32
33โˆ’If a test starts with either `x ` or `v `, the test is assumed to test the support of some OpenApi functionality. If the test begins `x ` it means that the feature is expected to be not supported, and the result will only be checked to have an "unsupported" flag set. If it starts with `v ` the test is expected to be supported and the result is compared to some file on disk.
33+If a test starts with either `x ` or `v `, the test is assumed to test the support of some OpenAPI functionality. If the test begins `x ` it means that the feature is expected to be not supported, and the result will only be checked to have an "unsupported" flag set. If it starts with `v ` the test is expected to be supported and the result is compared to some file on disk.
34
34
35The result will be reflected in the generated compatibility matrix.
35The result will be reflected in the generated compatibility matrix.
36
36
test/Spec/Golden/Extra.hs+46โˆ’42
@@ -1,8 +1,8 @@
1module Spec.Golden.Extra
1module Spec.Golden.Extra
2โˆ’ ( getGoldenInputs
2+ ( getGoldenInputs,
3โˆ’ , getGoldenInputsUniform
3+ getGoldenInputsUniform,
4โˆ’ , goldenInputsTree
4+ goldenInputsTree,
5โˆ’ , goldenInputsTreeUniform
5+ goldenInputsTreeUniform,
6 )
6 )
7where
7where
8
8
@@ -19,12 +19,12 @@ data TestInput t
19 | TestInputLeaf TestName t FilePath
19 | TestInputLeaf TestName t FilePath
20 deriving stock (Functor)
20 deriving stock (Functor)
21
21
22โˆ’getGoldenInputs
22+getGoldenInputs ::
23โˆ’ :: (Each s t (FilePath, FilePath -> IO a) a)
23+ (Each s t (FilePath, FilePath -> IO a) a) =>
24โˆ’ => TestName
24+ TestName ->
25โˆ’ -> FilePath
25+ FilePath ->
26โˆ’ -> s
26+ s ->
27โˆ’ -> IO (TestInput t)
27+ IO (TestInput t)
28getGoldenInputs name filepath inp = do
28getGoldenInputs name filepath inp = do
29 dirs' <- listDirectory filepath >>= filterM (doesDirectoryExist . (filepath </>))
29 dirs' <- listDirectory filepath >>= filterM (doesDirectoryExist . (filepath </>))
30 case dirs' of
30 case dirs' of
@@ -39,32 +39,34 @@ getGoldenInputs name filepath inp = do
39 TestInputNode name
39 TestInputNode name
40 <$> forM dirs (\dir -> getGoldenInputs dir (filepath </> dir) inp)
40 <$> forM dirs (\dir -> getGoldenInputs dir (filepath </> dir) inp)
41
41
42โˆ’getGoldenInputsUniform
42+getGoldenInputsUniform ::
43โˆ’ :: (Each t h (FilePath, FilePath -> IO a) a)
43+ (Each t h (FilePath, FilePath -> IO a) a) =>
44โˆ’ => (Each s t FilePath (FilePath, FilePath -> IO a))
44+ (Each s t FilePath (FilePath, FilePath -> IO a)) =>
45โˆ’ => TestName
45+ TestName ->
46โˆ’ -> (FilePath -> IO a)
46+ (FilePath -> IO a) ->
47โˆ’ -> FilePath
47+ FilePath ->
48โˆ’ -> s
48+ s ->
49โˆ’ -> IO (TestInput h)
49+ IO (TestInput h)
50getGoldenInputsUniform name f filepath inp = getGoldenInputs name filepath $ inp & each %~ (,f)
50getGoldenInputsUniform name f filepath inp = getGoldenInputs name filepath $ inp & each %~ (,f)
51
51
52โˆ’goldenInputsTree
52+goldenInputsTree ::
53โˆ’ :: (Each s t (FilePath, FilePath -> IO a) a)
53+ (Each s t (FilePath, FilePath -> IO a) a) =>
54โˆ’ => TestName
54+ TestName ->
55โˆ’ -> FilePath -- ^ Root path
55+ -- | Root path
56+ FilePath ->
56โˆ’ -> FilePath -- ^ Name of golden file
57+ -- | Name of golden file
57โˆ’ -> s
58+ FilePath ->
59+ s ->
58โˆ’ -> (t -> IO BSL.ByteString)
60+ (t -> IO BSL.ByteString) ->
59โˆ’ -> IO TestTree
61+ IO TestTree
60goldenInputsTree name filepath golden inp f = do
62goldenInputsTree name filepath golden inp f = do
61 runTestInputTree golden f <$> getGoldenInputs name filepath inp
63 runTestInputTree golden f <$> getGoldenInputs name filepath inp
62
64
63โˆ’runTestInputTree
65+runTestInputTree ::
64โˆ’ :: FilePath
66+ FilePath ->
65โˆ’ -> (t -> IO BSL.ByteString)
67+ (t -> IO BSL.ByteString) ->
66โˆ’ -> TestInput t
68+ TestInput t ->
67โˆ’ -> TestTree
69+ TestTree
68runTestInputTree golden f (TestInputNode name rest) =
70runTestInputTree golden f (TestInputNode name rest) =
69 testGroup name (runTestInputTree golden f <$> rest)
71 testGroup name (runTestInputTree golden f <$> rest)
70runTestInputTree golden f (TestInputLeaf name t path) =
72runTestInputTree golden f (TestInputLeaf name t path) =
@@ -74,16 +76,18 @@ runTestInputTree golden f (TestInputLeaf name t path) =
74 (path </> golden)
76 (path </> golden)
75 (f t)
77 (f t)
76
78
77โˆ’goldenInputsTreeUniform
79+goldenInputsTreeUniform ::
78โˆ’ :: ( Each t h (FilePath, FilePath -> IO a) a
80+ ( Each t h (FilePath, FilePath -> IO a) a
79โˆ’ , Each s t FilePath (FilePath, FilePath -> IO a)
81+ , Each s t FilePath (FilePath, FilePath -> IO a)
80โˆ’ )
82+ ) =>
81โˆ’ => String
83+ String ->
82โˆ’ -> FilePath -- ^ Root path
84+ -- | Root path
85+ FilePath ->
83โˆ’ -> FilePath -- ^ Name of golden file
86+ -- | Name of golden file
84โˆ’ -> s
87+ FilePath ->
88+ s ->
85โˆ’ -> (FilePath -> IO a)
89+ (FilePath -> IO a) ->
86โˆ’ -> (h -> IO BSL.ByteString)
90+ (h -> IO BSL.ByteString) ->
87โˆ’ -> IO TestTree
91+ IO TestTree
88goldenInputsTreeUniform name filepath golden inp h =
92goldenInputsTreeUniform name filepath golden inp h =
89 goldenInputsTree name filepath golden (inp & each %~ (,h))
93 goldenInputsTree name filepath golden (inp & each %~ (,h))
test/Spec/Golden/TraceTree.hs+9โˆ’6
@@ -1,5 +1,5 @@
1module Spec.Golden.TraceTree
1module Spec.Golden.TraceTree
2โˆ’ ( tests
2+ ( tests,
3 )
3 )
4where
4where
5
5
@@ -7,13 +7,15 @@ import Control.Category
7import Control.Exception
7import Control.Exception
8import qualified Data.ByteString.Lazy as BSL
8import qualified Data.ByteString.Lazy as BSL
9import Data.Default
9import Data.Default
10+import Data.OpenApi.Compare.Run
11+import Data.OpenApi.Compare.Validate.OpenApi ()
10import Data.Text (Text)
12import Data.Text (Text)
11import qualified Data.Text.Encoding as T
13import qualified Data.Text.Encoding as T
12import qualified Data.Yaml as Yaml
14import qualified Data.Yaml as Yaml
13โˆ’import OpenAPI.Checker.Run
15+import Paths_compaREST
14โˆ’import OpenAPI.Checker.Validate.OpenApi ()
15import Spec.Golden.Extra
16import Spec.Golden.Extra
16import Test.Tasty (TestTree, testGroup)
17import Test.Tasty (TestTree, testGroup)
18+import Text.Pandoc.Builder
17import Text.Pandoc.Class
19import Text.Pandoc.Class
18import Text.Pandoc.Options
20import Text.Pandoc.Options
19import Text.Pandoc.Writers
21import Text.Pandoc.Writers
@@ -21,10 +23,11 @@ import Prelude hiding (id, (.))
21
23
22tests :: IO TestTree
24tests :: IO TestTree
23tests = do
25tests = do
26+ dir <- getDataDir
24 traceTreeTests <-
27 traceTreeTests <-
25 goldenInputsTreeUniform
28 goldenInputsTreeUniform
26 "TraceTree"
29 "TraceTree"
27โˆ’ "test/golden/common"
30+ dir
28 "trace-tree.yaml"
31 "trace-tree.yaml"
29 ("a.yaml", "b.yaml")
32 ("a.yaml", "b.yaml")
30 Yaml.decodeFileThrow
33 Yaml.decodeFileThrow
@@ -33,11 +36,11 @@ tests = do
33 reportTests <-
36 reportTests <-
34 goldenInputsTreeUniform
37 goldenInputsTreeUniform
35 "Report"
38 "Report"
36โˆ’ "test/golden/common"
39+ dir
37 "report.md"
40 "report.md"
38 ("a.yaml", "b.yaml")
41 ("a.yaml", "b.yaml")
39 Yaml.decodeFileThrow
42 Yaml.decodeFileThrow
40โˆ’ (runPandoc . writeMarkdown def {writerExtensions = githubMarkdownExtensions} . fst . runReport)
43+ (runPandoc . writeMarkdown def {writerExtensions = githubMarkdownExtensions} . doc . fst . runReport def)
41
44
42 return $ testGroup "Golden tests" [traceTreeTests, reportTests]
45 return $ testGroup "Golden tests" [traceTreeTests, reportTests]
43
46
test/golden/common/bad-oneof-unchanged/a.yamlnew file+39
@@ -0,0 +1,39 @@
1+openapi: "3.0.0"
2+info:
3+ version: 1.0.0
4+ title: Test
5+servers:
6+ - url: http://localhost/
7+paths:
8+ /test:
9+ post:
10+ requestBody:
11+ content:
12+ application/json:
13+ schema:
14+ $ref: "#/components/schemas/Test"
15+ responses:
16+ '200':
17+ description: test
18+ content:
19+ application/json:
20+ schema:
21+ $ref: "#/components/schemas/Test"
22+components:
23+ schemas:
24+ Test:
25+ oneOf:
26+ - type: object
27+ required: ["tag", "prop_A"]
28+ properties:
29+ tag:
30+ enum: ["A"]
31+ prop_A:
32+ type: string
33+ - type: object
34+ required: ["tag", "prop_B"]
35+ properties:
36+ tag:
37+ enum: ["A"]
38+ prop_B:
39+ type: number
test/golden/common/bad-oneof-unchanged/b.yamlnew file+39
@@ -0,0 +1,39 @@
1+openapi: "3.0.0"
2+info:
3+ version: 1.0.0
4+ title: Test
5+servers:
6+ - url: http://localhost/
7+paths:
8+ /test:
9+ post:
10+ requestBody:
11+ content:
12+ application/json:
13+ schema:
14+ $ref: "#/components/schemas/Test"
15+ responses:
16+ '200':
17+ description: test
18+ content:
19+ application/json:
20+ schema:
21+ $ref: "#/components/schemas/Test"
22+components:
23+ schemas:
24+ Test:
25+ oneOf:
26+ - type: object
27+ required: ["tag", "prop_B"]
28+ properties:
29+ tag:
30+ enum: ["A"]
31+ prop_B:
32+ type: number
33+ - type: object
34+ required: ["tag", "prop_A"]
35+ properties:
36+ tag:
37+ enum: ["A"]
38+ prop_A:
39+ type: string
test/golden/common/bad-oneof-unchanged/report.mdnew file+19
@@ -0,0 +1,19 @@
1+# Summary
2+
3+| โŒ Breaking changes | โš ๏ธ Non-breaking changes | [โ“ Unsupported feature changes](#unsupported-changes) |
4+|---------------------|-------------------------|--------------------------------------------------------|
5+| 0 | 0 | 2 |
6+
7+# <span id="unsupported-changes"></span>โ“ Unsupported feature changes
8+
9+## **POST** /test
10+
11+### โžก๏ธโ˜๏ธ JSON Request
12+
13+Could not deduce that `oneOf` cases don't overlap. Treating the `oneOf`
14+as an `anyOf`. Reported errors might not be accurate.
15+
16+### โฌ…๏ธโ˜๏ธ JSON Response โ€“ 200
17+
18+Could not deduce that `oneOf` cases don't overlap. Treating the `oneOf`
19+as an `anyOf`. Reported errors might not be accurate.
test/golden/common/bad-oneof-unchanged/trace-tree.yamlnew file+18
@@ -0,0 +1,18 @@
1+forwardChanges:
2+ AtPath "/test":
3+ InOperation PostMethod:
4+ InRequest:
5+ InPayload:
6+ PayloadSchema: OneOfNotDisjoint
7+ WithStatusCode 200:
8+ ResponsePayload:
9+ PayloadSchema: OneOfNotDisjoint
10+backwardChanges:
11+ AtPath "/test":
12+ InOperation PostMethod:
13+ InRequest:
14+ InPayload:
15+ PayloadSchema: OneOfNotDisjoint
16+ WithStatusCode 200:
17+ ResponsePayload:
18+ PayloadSchema: OneOfNotDisjoint
test/golden/common/enum-added/a.yamlnew file+25
@@ -0,0 +1,25 @@
1+openapi: "3.0.0"
2+info:
3+ version: 1.0.0
4+ title: Test
5+servers:
6+ - url: http://localhost/
7+paths:
8+ /test:
9+ post:
10+ requestBody:
11+ content:
12+ application/json:
13+ schema:
14+ $ref: "#/components/schemas/Test"
15+ responses:
16+ '200':
17+ description: test
18+ content:
19+ application/json:
20+ schema:
21+ $ref: "#/components/schemas/Test"
22+components:
23+ schemas:
24+ Test:
25+ enum: ["A", "B"]
test/golden/common/enum-added/b.yamlnew file+25
@@ -0,0 +1,25 @@
1+openapi: "3.0.0"
2+info:
3+ version: 1.0.0
4+ title: Test
5+servers:
6+ - url: http://localhost/
7+paths:
8+ /test:
9+ post:
10+ requestBody:
11+ content:
12+ application/json:
13+ schema:
14+ $ref: "#/components/schemas/Test"
15+ responses:
16+ '200':
17+ description: test
18+ content:
19+ application/json:
20+ schema:
21+ $ref: "#/components/schemas/Test"
22+components:
23+ schemas:
24+ Test:
25+ enum: ["A", "B", "C"]
test/golden/common/enum-added/report.mdnew file+33
@@ -0,0 +1,33 @@
1+# Summary
2+
3+| [โŒ Breaking changes](#breaking-changes) | [โš ๏ธ Non-breaking changes](#non-breaking-changes) |
4+|------------------------------------------|--------------------------------------------------|
5+| 1 | 1 |
6+
7+# <span id="breaking-changes"></span>โŒ Breaking changes
8+
9+## **POST** /test
10+
11+### โฌ…๏ธโ˜๏ธ JSON Response โ€“ 200
12+
13+#### `$(String)`
14+
15+The following enum value was added:
16+
17+``` json
18+"C"
19+```
20+
21+# <span id="non-breaking-changes"></span>โš ๏ธ Non-breaking changes
22+
23+## **POST** /test
24+
25+### โžก๏ธโ˜๏ธ JSON Request
26+
27+#### `$(String)`
28+
29+The following enum value was added:
30+
31+``` json
32+"C"
33+```
test/golden/common/enum-added/trace-tree.yamlnew file+14
@@ -0,0 +1,14 @@
1+forwardChanges:
2+ AtPath "/test":
3+ InOperation PostMethod:
4+ WithStatusCode 200:
5+ ResponsePayload:
6+ PayloadSchema:
7+ OfType String: EnumDoesntSatisfy (String "C")
8+backwardChanges:
9+ AtPath "/test":
10+ InOperation PostMethod:
11+ InRequest:
12+ InPayload:
13+ PayloadSchema:
14+ OfType String: EnumDoesntSatisfy (String "C")
test/golden/common/enum-anyof/report.md+3โˆ’3
@@ -1,5 +1,5 @@
1# Summary
1# Summary
2
2
3โˆ’| โš ๏ธ Breaking changes | ๐Ÿ™† Non-breaking changes | ๐Ÿคท Unsupported feature changes |
3+| โŒ Breaking changes | โš ๏ธ Non-breaking changes |
4โˆ’|---------------------|------------------------|-------------------------------|
4+|---------------------|-------------------------|
5โˆ’| 0 | 0 | 0 |
5+| 0 | 0 |
test/golden/common/enum-anyof/trace-tree.yaml+2โˆ’2
@@ -1,2 +1,2 @@
1โˆ’breakingChanges: {}
1+forwardChanges: {}
2โˆ’nonBreakingChanges: {}
2+backwardChanges: {}
test/golden/common/id/report.md+3โˆ’3
@@ -1,5 +1,5 @@
1# Summary
1# Summary
2
2
3โˆ’| โš ๏ธ Breaking changes | ๐Ÿ™† Non-breaking changes | ๐Ÿคท Unsupported feature changes |
3+| โŒ Breaking changes | โš ๏ธ Non-breaking changes |
4โˆ’|---------------------|------------------------|-------------------------------|
4+|---------------------|-------------------------|
5โˆ’| 0 | 0 | 0 |
5+| 0 | 0 |
test/golden/common/id/trace-tree.yaml+2โˆ’2
@@ -1,2 +1,2 @@
1โˆ’breakingChanges: {}
1+forwardChanges: {}
2โˆ’nonBreakingChanges: {}
2+backwardChanges: {}
test/golden/common/json/recursive/report.md+3โˆ’3
@@ -1,5 +1,5 @@
1# Summary
1# Summary
2
2
3โˆ’| โš ๏ธ Breaking changes | ๐Ÿ™† Non-breaking changes | ๐Ÿคท Unsupported feature changes |
3+| โŒ Breaking changes | โš ๏ธ Non-breaking changes |
4โˆ’|---------------------|------------------------|-------------------------------|
4+|---------------------|-------------------------|
5โˆ’| 0 | 0 | 0 |
5+| 0 | 0 |
test/golden/common/json/recursive/trace-tree.yaml+2โˆ’2
@@ -1,2 +1,2 @@
1โˆ’breakingChanges: {}
1+forwardChanges: {}
2โˆ’nonBreakingChanges: {}
2+backwardChanges: {}
test/golden/common/maximum-lowered/report.md+7โˆ’7
@@ -1,24 +1,24 @@
1# Summary
1# Summary
2
2
3โˆ’| [โš ๏ธ Breaking changes](#breaking-changes) | [๐Ÿ™† Non-breaking changes](#non-breaking-changes) | ๐Ÿคท Unsupported feature changes |
3+| [โŒ Breaking changes](#breaking-changes) | [โš ๏ธ Non-breaking changes](#non-breaking-changes) |
4โˆ’|------------------------------------------|-------------------------------------------------|-------------------------------|
4+|------------------------------------------|--------------------------------------------------|
5โˆ’| 1 | 1 | 0 |
5+| 1 | 1 |
6
6
7โˆ’# <span id="breaking-changes"></span>โš ๏ธ Breaking changes
7+# <span id="breaking-changes"></span>โŒ Breaking changes
8
8
9## **POST** /test
9## **POST** /test
10
10
11โˆ’### ๐Ÿ“ฑโžก๏ธ JSON Request
11+### โžก๏ธโ˜๏ธ JSON Request
12
12
13#### `$(Number)`
13#### `$(Number)`
14
14
15Upper bound changed from 3.0 inclusive to 2.0 inclusive.
15Upper bound changed from 3.0 inclusive to 2.0 inclusive.
16
16
17โˆ’# <span id="non-breaking-changes"></span>๐Ÿ™† Non-breaking changes
17+# <span id="non-breaking-changes"></span>โš ๏ธ Non-breaking changes
18
18
19## **POST** /test
19## **POST** /test
20
20
21โˆ’### ๐Ÿ“ฑโฌ…๏ธ JSON Response โ€“ 200
21+### โฌ…๏ธโ˜๏ธ JSON Response โ€“ 200
22
22
23#### `$(Number)`
23#### `$(Number)`
24
24
test/golden/common/maximum-lowered/trace-tree.yaml+2โˆ’2
@@ -1,4 +1,4 @@
1โˆ’breakingChanges:
1+forwardChanges:
2 AtPath "/test":
2 AtPath "/test":
3 InOperation PostMethod:
3 InOperation PostMethod:
4 InRequest:
4 InRequest:
@@ -6,7 +6,7 @@ breakingChanges:
6 PayloadSchema:
6 PayloadSchema:
7 OfType Number: MatchingMaximumWeak (ProdCons {producer = Inclusive 3.0,
7 OfType Number: MatchingMaximumWeak (ProdCons {producer = Inclusive 3.0,
8 consumer = Inclusive 2.0})
8 consumer = Inclusive 2.0})
9โˆ’nonBreakingChanges:
9+backwardChanges:
10 AtPath "/test":
10 AtPath "/test":
11 InOperation PostMethod:
11 InOperation PostMethod:
12 WithStatusCode 200:
12 WithStatusCode 200:
test/golden/common/pathItem/operation/parameters/allowEmptyValue/reset/report.md+4โˆ’4
@@ -1,10 +1,10 @@
1# Summary
1# Summary
2
2
3โˆ’| [โš ๏ธ Breaking changes](#breaking-changes) | ๐Ÿ™† Non-breaking changes | ๐Ÿคท Unsupported feature changes |
3+| [โŒ Breaking changes](#breaking-changes) | โš ๏ธ Non-breaking changes |
4โˆ’|------------------------------------------|------------------------|-------------------------------|
4+|------------------------------------------|-------------------------|
5โˆ’| 1 | 0 | 0 |
5+| 1 | 0 |
6
6
7โˆ’# <span id="breaking-changes"></span>โš ๏ธ Breaking changes
7+# <span id="breaking-changes"></span>โŒ Breaking changes
8
8
9## **POST** /test
9## **POST** /test
10
10
test/golden/common/pathItem/operation/parameters/allowEmptyValue/reset/trace-tree.yaml+2โˆ’2
@@ -1,5 +1,5 @@
1โˆ’breakingChanges:
1+forwardChanges:
2 AtPath "/test":
2 AtPath "/test":
3 InOperation PostMethod:
3 InOperation PostMethod:
4 InParam "test1": ParamEmptinessIncompatible
4 InParam "test1": ParamEmptinessIncompatible
5โˆ’nonBreakingChanges: {}
5+backwardChanges: {}
test/golden/common/pathItem/operation/parameters/allowEmptyValue/set/report.md+4โˆ’4
@@ -1,10 +1,10 @@
1# Summary
1# Summary
2
2
3โˆ’| โš ๏ธ Breaking changes | [๐Ÿ™† Non-breaking changes](#non-breaking-changes) | ๐Ÿคท Unsupported feature changes |
3+| โŒ Breaking changes | [โš ๏ธ Non-breaking changes](#non-breaking-changes) |
4โˆ’|---------------------|-------------------------------------------------|-------------------------------|
4+|---------------------|--------------------------------------------------|
5โˆ’| 0 | 1 | 0 |
5+| 0 | 1 |
6
6
7โˆ’# <span id="non-breaking-changes"></span>๐Ÿ™† Non-breaking changes
7+# <span id="non-breaking-changes"></span>โš ๏ธ Non-breaking changes
8
8
9## **POST** /test
9## **POST** /test
10
10
test/golden/common/pathItem/operation/parameters/allowEmptyValue/set/trace-tree.yaml+2โˆ’2
@@ -1,5 +1,5 @@
1โˆ’breakingChanges: {}
1+forwardChanges: {}
2โˆ’nonBreakingChanges:
2+backwardChanges:
3 AtPath "/test":
3 AtPath "/test":
4 InOperation PostMethod:
4 InOperation PostMethod:
5 InParam "test1": ParamEmptinessIncompatible
5 InParam "test1": ParamEmptinessIncompatible
test/golden/common/pathItem/operation/parameters/change/report.md+5โˆ’5
@@ -1,10 +1,10 @@
1# Summary
1# Summary
2
2
3โˆ’| [โš ๏ธ Breaking changes](#breaking-changes) | [๐Ÿ™† Non-breaking changes](#non-breaking-changes) | ๐Ÿคท Unsupported feature changes |
3+| [โŒ Breaking changes](#breaking-changes) | [โš ๏ธ Non-breaking changes](#non-breaking-changes) |
4โˆ’|------------------------------------------|-------------------------------------------------|-------------------------------|
4+|------------------------------------------|--------------------------------------------------|
5โˆ’| 1 | 1 | 0 |
5+| 1 | 1 |
6
6
7โˆ’# <span id="breaking-changes"></span>โš ๏ธ Breaking changes
7+# <span id="breaking-changes"></span>โŒ Breaking changes
8
8
9## **POST** /test
9## **POST** /test
10
10
@@ -16,7 +16,7 @@
16
16
17The type has been removed.
17The type has been removed.
18
18
19โˆ’# <span id="non-breaking-changes"></span>๐Ÿ™† Non-breaking changes
19+# <span id="non-breaking-changes"></span>โš ๏ธ Non-breaking changes
20
20
21## **POST** /test
21## **POST** /test
22
22
test/golden/common/pathItem/operation/parameters/change/trace-tree.yaml+4โˆ’4
@@ -1,12 +1,12 @@
1โˆ’breakingChanges:
1+forwardChanges:
2 AtPath "/test":
2 AtPath "/test":
3 InOperation PostMethod:
3 InOperation PostMethod:
4 InParam "test":
4 InParam "test":
5 InParamSchema:
5 InParamSchema:
6โˆ’ OfType String: NoContradiction
6+ OfType String: TypeBecomesEmpty
7โˆ’nonBreakingChanges:
7+backwardChanges:
8 AtPath "/test":
8 AtPath "/test":
9 InOperation PostMethod:
9 InOperation PostMethod:
10 InParam "test":
10 InParam "test":
11 InParamSchema:
11 InParamSchema:
12โˆ’ OfType Number: NoContradiction
12+ OfType Number: TypeBecomesEmpty
test/golden/common/pathItem/operation/parameters/required/false/add/report.md+3โˆ’3
@@ -1,5 +1,5 @@
1# Summary
1# Summary
2
2
3โˆ’| โš ๏ธ Breaking changes | ๐Ÿ™† Non-breaking changes | ๐Ÿคท Unsupported feature changes |
3+| โŒ Breaking changes | โš ๏ธ Non-breaking changes |
4โˆ’|---------------------|------------------------|-------------------------------|
4+|---------------------|-------------------------|
5โˆ’| 0 | 0 | 0 |
5+| 0 | 0 |
test/golden/common/pathItem/operation/parameters/required/false/add/trace-tree.yaml+2โˆ’2
@@ -1,2 +1,2 @@
1โˆ’breakingChanges: {}
1+forwardChanges: {}
2โˆ’nonBreakingChanges: {}
2+backwardChanges: {}
test/golden/common/pathItem/operation/parameters/required/false/del/report.md+3โˆ’3
@@ -1,5 +1,5 @@
1# Summary
1# Summary
2
2
3โˆ’| โš ๏ธ Breaking changes | ๐Ÿ™† Non-breaking changes | ๐Ÿคท Unsupported feature changes |
3+| โŒ Breaking changes | โš ๏ธ Non-breaking changes |
4โˆ’|---------------------|------------------------|-------------------------------|
4+|---------------------|-------------------------|
5โˆ’| 0 | 0 | 0 |
5+| 0 | 0 |
test/golden/common/pathItem/operation/parameters/required/false/del/trace-tree.yaml+2โˆ’2
@@ -1,2 +1,2 @@
1โˆ’breakingChanges: {}
1+forwardChanges: {}
2โˆ’nonBreakingChanges: {}
2+backwardChanges: {}
test/golden/common/pathItem/operation/parameters/required/reset/report.md+4โˆ’4
@@ -1,10 +1,10 @@
1# Summary
1# Summary
2
2
3โˆ’| โš ๏ธ Breaking changes | [๐Ÿ™† Non-breaking changes](#non-breaking-changes) | ๐Ÿคท Unsupported feature changes |
3+| โŒ Breaking changes | [โš ๏ธ Non-breaking changes](#non-breaking-changes) |
4โˆ’|---------------------|-------------------------------------------------|-------------------------------|
4+|---------------------|--------------------------------------------------|
5โˆ’| 0 | 1 | 0 |
5+| 0 | 1 |
6
6
7โˆ’# <span id="non-breaking-changes"></span>๐Ÿ™† Non-breaking changes
7+# <span id="non-breaking-changes"></span>โš ๏ธ Non-breaking changes
8
8
9## **POST** /test
9## **POST** /test
10
10
test/golden/common/pathItem/operation/parameters/required/reset/trace-tree.yaml+2โˆ’2
@@ -1,5 +1,5 @@
1โˆ’breakingChanges: {}
1+forwardChanges: {}
2โˆ’nonBreakingChanges:
2+backwardChanges:
3 AtPath "/test":
3 AtPath "/test":
4 InOperation PostMethod:
4 InOperation PostMethod:
5 InParam "test1": ParamRequired
5 InParam "test1": ParamRequired
test/golden/common/pathItem/operation/parameters/required/set/report.md+4โˆ’4
@@ -1,10 +1,10 @@
1# Summary
1# Summary
2
2
3โˆ’| [โš ๏ธ Breaking changes](#breaking-changes) | ๐Ÿ™† Non-breaking changes | ๐Ÿคท Unsupported feature changes |
3+| [โŒ Breaking changes](#breaking-changes) | โš ๏ธ Non-breaking changes |
4โˆ’|------------------------------------------|------------------------|-------------------------------|
4+|------------------------------------------|-------------------------|
5โˆ’| 1 | 0 | 0 |
5+| 1 | 0 |
6
6
7โˆ’# <span id="breaking-changes"></span>โš ๏ธ Breaking changes
7+# <span id="breaking-changes"></span>โŒ Breaking changes
8
8
9## **POST** /test
9## **POST** /test
10
10
test/golden/common/pathItem/operation/parameters/required/set/trace-tree.yaml+2โˆ’2
@@ -1,5 +1,5 @@
1โˆ’breakingChanges:
1+forwardChanges:
2 AtPath "/test":
2 AtPath "/test":
3 InOperation PostMethod:
3 InOperation PostMethod:
4 InParam "test1": ParamRequired
4 InParam "test1": ParamRequired
5โˆ’nonBreakingChanges: {}
5+backwardChanges: {}
test/golden/common/pathItem/operation/parameters/required/true/add/report.md+4โˆ’4
@@ -1,10 +1,10 @@
1# Summary
1# Summary
2
2
3โˆ’| [โš ๏ธ Breaking changes](#breaking-changes) | ๐Ÿ™† Non-breaking changes | ๐Ÿคท Unsupported feature changes |
3+| [โŒ Breaking changes](#breaking-changes) | โš ๏ธ Non-breaking changes |
4โˆ’|------------------------------------------|------------------------|-------------------------------|
4+|------------------------------------------|-------------------------|
5โˆ’| 1 | 0 | 0 |
5+| 1 | 0 |
6
6
7โˆ’# <span id="breaking-changes"></span>โš ๏ธ Breaking changes
7+# <span id="breaking-changes"></span>โŒ Breaking changes
8
8
9## **POST** /test
9## **POST** /test
10
10
test/golden/common/pathItem/operation/parameters/required/true/add/trace-tree.yaml+2โˆ’2
@@ -1,4 +1,4 @@
1โˆ’breakingChanges:
1+forwardChanges:
2 AtPath "/test":
2 AtPath "/test":
3 InOperation PostMethod: ParamNotMatched "test2"
3 InOperation PostMethod: ParamNotMatched "test2"
4โˆ’nonBreakingChanges: {}
4+backwardChanges: {}
test/golden/common/pathItem/operation/parameters/required/true/del/report.md+4โˆ’4
@@ -1,10 +1,10 @@
1# Summary
1# Summary
2
2
3โˆ’| โš ๏ธ Breaking changes | [๐Ÿ™† Non-breaking changes](#non-breaking-changes) | ๐Ÿคท Unsupported feature changes |
3+| โŒ Breaking changes | [โš ๏ธ Non-breaking changes](#non-breaking-changes) |
4โˆ’|---------------------|-------------------------------------------------|-------------------------------|
4+|---------------------|--------------------------------------------------|
5โˆ’| 0 | 1 | 0 |
5+| 0 | 1 |
6
6
7โˆ’# <span id="non-breaking-changes"></span>๐Ÿ™† Non-breaking changes
7+# <span id="non-breaking-changes"></span>โš ๏ธ Non-breaking changes
8
8
9## **POST** /test
9## **POST** /test
10
10
test/golden/common/pathItem/operation/parameters/required/true/del/trace-tree.yaml+2โˆ’2
@@ -1,4 +1,4 @@
1โˆ’breakingChanges: {}
1+forwardChanges: {}
2โˆ’nonBreakingChanges:
2+backwardChanges:
3 AtPath "/test":
3 AtPath "/test":
4 InOperation PostMethod: ParamNotMatched "test2"
4 InOperation PostMethod: ParamNotMatched "test2"
test/golden/common/pathItem/operation/requestBody/mediaTypeObject/add/report.md+4โˆ’4
@@ -1,10 +1,10 @@
1# Summary
1# Summary
2
2
3โˆ’| โš ๏ธ Breaking changes | [๐Ÿ™† Non-breaking changes](#non-breaking-changes) | ๐Ÿคท Unsupported feature changes |
3+| โŒ Breaking changes | [โš ๏ธ Non-breaking changes](#non-breaking-changes) |
4โˆ’|---------------------|-------------------------------------------------|-------------------------------|
4+|---------------------|--------------------------------------------------|
5โˆ’| 0 | 1 | 0 |
5+| 0 | 1 |
6
6
7โˆ’# <span id="non-breaking-changes"></span>๐Ÿ™† Non-breaking changes
7+# <span id="non-breaking-changes"></span>โš ๏ธ Non-breaking changes
8
8
9## **POST** /test
9## **POST** /test
10
10
test/golden/common/pathItem/operation/requestBody/mediaTypeObject/add/trace-tree.yaml+2โˆ’2
@@ -1,5 +1,5 @@
1โˆ’breakingChanges: {}
1+forwardChanges: {}
2โˆ’nonBreakingChanges:
2+backwardChanges:
3 AtPath "/test":
3 AtPath "/test":
4 InOperation PostMethod:
4 InOperation PostMethod:
5 InRequest: RequestMediaTypeNotFound application/x-www-form-urlencoded
5 InRequest: RequestMediaTypeNotFound application/x-www-form-urlencoded
test/golden/common/pathItem/operation/requestBody/mediaTypeObject/change/report.md+7โˆ’7
@@ -1,24 +1,24 @@
1# Summary
1# Summary
2
2
3โˆ’| [โš ๏ธ Breaking changes](#breaking-changes) | [๐Ÿ™† Non-breaking changes](#non-breaking-changes) | ๐Ÿคท Unsupported feature changes |
3+| [โŒ Breaking changes](#breaking-changes) | [โš ๏ธ Non-breaking changes](#non-breaking-changes) |
4โˆ’|------------------------------------------|-------------------------------------------------|-------------------------------|
4+|------------------------------------------|--------------------------------------------------|
5โˆ’| 1 | 1 | 0 |
5+| 1 | 1 |
6
6
7โˆ’# <span id="breaking-changes"></span>โš ๏ธ Breaking changes
7+# <span id="breaking-changes"></span>โŒ Breaking changes
8
8
9## **POST** /test
9## **POST** /test
10
10
11โˆ’### ๐Ÿ“ฑโžก๏ธ JSON Request
11+### โžก๏ธโ˜๏ธ JSON Request
12
12
13#### `$(String)`
13#### `$(String)`
14
14
15The type has been removed.
15The type has been removed.
16
16
17โˆ’# <span id="non-breaking-changes"></span>๐Ÿ™† Non-breaking changes
17+# <span id="non-breaking-changes"></span>โš ๏ธ Non-breaking changes
18
18
19## **POST** /test
19## **POST** /test
20
20
21โˆ’### ๐Ÿ“ฑโžก๏ธ JSON Request
21+### โžก๏ธโ˜๏ธ JSON Request
22
22
23#### `$(Number)`
23#### `$(Number)`
24
24
test/golden/common/pathItem/operation/requestBody/mediaTypeObject/change/trace-tree.yaml+4โˆ’4
@@ -1,14 +1,14 @@
1โˆ’breakingChanges:
1+forwardChanges:
2 AtPath "/test":
2 AtPath "/test":
3 InOperation PostMethod:
3 InOperation PostMethod:
4 InRequest:
4 InRequest:
5 InPayload:
5 InPayload:
6 PayloadSchema:
6 PayloadSchema:
7โˆ’ OfType String: NoContradiction
7+ OfType String: TypeBecomesEmpty
8โˆ’nonBreakingChanges:
8+backwardChanges:
9 AtPath "/test":
9 AtPath "/test":
10 InOperation PostMethod:
10 InOperation PostMethod:
11 InRequest:
11 InRequest:
12 InPayload:
12 InPayload:
13 PayloadSchema:
13 PayloadSchema:
14โˆ’ OfType Number: NoContradiction
14+ OfType Number: TypeBecomesEmpty
test/golden/common/pathItem/operation/requestBody/mediaTypeObject/del/report.md+4โˆ’4
@@ -1,10 +1,10 @@
1# Summary
1# Summary
2
2
3โˆ’| [โš ๏ธ Breaking changes](#breaking-changes) | ๐Ÿ™† Non-breaking changes | ๐Ÿคท Unsupported feature changes |
3+| [โŒ Breaking changes](#breaking-changes) | โš ๏ธ Non-breaking changes |
4โˆ’|------------------------------------------|------------------------|-------------------------------|
4+|------------------------------------------|-------------------------|
5โˆ’| 1 | 0 | 0 |
5+| 1 | 0 |
6
6
7โˆ’# <span id="breaking-changes"></span>โš ๏ธ Breaking changes
7+# <span id="breaking-changes"></span>โŒ Breaking changes
8
8
9## **POST** /test
9## **POST** /test
10
10
test/golden/common/pathItem/operation/requestBody/mediaTypeObject/del/trace-tree.yaml+2โˆ’2
@@ -1,5 +1,5 @@
1โˆ’breakingChanges:
1+forwardChanges:
2 AtPath "/test":
2 AtPath "/test":
3 InOperation PostMethod:
3 InOperation PostMethod:
4 InRequest: RequestMediaTypeNotFound application/x-www-form-urlencoded
4 InRequest: RequestMediaTypeNotFound application/x-www-form-urlencoded
5โˆ’nonBreakingChanges: {}
5+backwardChanges: {}
test/golden/common/pathItem/operation/requestBody/required/reset/report.md+4โˆ’4
@@ -1,10 +1,10 @@
1# Summary
1# Summary
2
2
3โˆ’| โš ๏ธ Breaking changes | [๐Ÿ™† Non-breaking changes](#non-breaking-changes) | ๐Ÿคท Unsupported feature changes |
3+| โŒ Breaking changes | [โš ๏ธ Non-breaking changes](#non-breaking-changes) |
4โˆ’|---------------------|-------------------------------------------------|-------------------------------|
4+|---------------------|--------------------------------------------------|
5โˆ’| 0 | 1 | 0 |
5+| 0 | 1 |
6
6
7โˆ’# <span id="non-breaking-changes"></span>๐Ÿ™† Non-breaking changes
7+# <span id="non-breaking-changes"></span>โš ๏ธ Non-breaking changes
8
8
9## **POST** /test
9## **POST** /test
10
10
test/golden/common/pathItem/operation/requestBody/required/reset/trace-tree.yaml+2โˆ’2
@@ -1,5 +1,5 @@
1โˆ’breakingChanges: {}
1+forwardChanges: {}
2โˆ’nonBreakingChanges:
2+backwardChanges:
3 AtPath "/test":
3 AtPath "/test":
4 InOperation PostMethod:
4 InOperation PostMethod:
5 InRequest: RequestBodyRequired
5 InRequest: RequestBodyRequired
test/golden/common/pathItem/operation/requestBody/required/set/report.md+4โˆ’4
@@ -1,10 +1,10 @@
1# Summary
1# Summary
2
2
3โˆ’| [โš ๏ธ Breaking changes](#breaking-changes) | ๐Ÿ™† Non-breaking changes | ๐Ÿคท Unsupported feature changes |
3+| [โŒ Breaking changes](#breaking-changes) | โš ๏ธ Non-breaking changes |
4โˆ’|------------------------------------------|------------------------|-------------------------------|
4+|------------------------------------------|-------------------------|
5โˆ’| 1 | 0 | 0 |
5+| 1 | 0 |
6
6
7โˆ’# <span id="breaking-changes"></span>โš ๏ธ Breaking changes
7+# <span id="breaking-changes"></span>โŒ Breaking changes
8
8
9## **POST** /test
9## **POST** /test
10
10
test/golden/common/pathItem/operation/requestBody/required/set/trace-tree.yaml+2โˆ’2
@@ -1,5 +1,5 @@
1โˆ’breakingChanges:
1+forwardChanges:
2 AtPath "/test":
2 AtPath "/test":
3 InOperation PostMethod:
3 InOperation PostMethod:
4 InRequest: RequestBodyRequired
4 InRequest: RequestBodyRequired
5โˆ’nonBreakingChanges: {}
5+backwardChanges: {}
test/golden/common/pathItem/operation/responses/add/report.md+5โˆ’5
@@ -1,11 +1,11 @@
1# Summary
1# Summary
2
2
3โˆ’| [โš ๏ธ Breaking changes](#breaking-changes) | ๐Ÿ™† Non-breaking changes | ๐Ÿคท Unsupported feature changes |
3+| [โŒ Breaking changes](#breaking-changes) | โš ๏ธ Non-breaking changes |
4โˆ’|------------------------------------------|------------------------|-------------------------------|
4+|------------------------------------------|-------------------------|
5โˆ’| 1 | 0 | 0 |
5+| 1 | 0 |
6
6
7โˆ’# <span id="breaking-changes"></span>โš ๏ธ Breaking changes
7+# <span id="breaking-changes"></span>โŒ Breaking changes
8
8
9## **POST** /test
9## **POST** /test
10
10
11โˆ’Reponse code 500 has been added.
11+Response code 500 has been added.
test/golden/common/pathItem/operation/responses/add/trace-tree.yaml+3โˆ’3
@@ -1,4 +1,4 @@
1โˆ’breakingChanges:
1+forwardChanges:
2 AtPath "/test":
2 AtPath "/test":
3โˆ’ InOperation PostMethod: ResponseCodeNotFound 500
3+ InOperation PostMethod: ConsumerDoesntHaveResponseCode 500
4โˆ’nonBreakingChanges: {}
4+backwardChanges: {}
test/golden/common/pathItem/operation/responses/change/headers/mandatory/add/report.md+4โˆ’4
@@ -1,10 +1,10 @@
1# Summary
1# Summary
2
2
3โˆ’| โš ๏ธ Breaking changes | [๐Ÿ™† Non-breaking changes](#non-breaking-changes) | ๐Ÿคท Unsupported feature changes |
3+| โŒ Breaking changes | [โš ๏ธ Non-breaking changes](#non-breaking-changes) |
4โˆ’|---------------------|-------------------------------------------------|-------------------------------|
4+|---------------------|--------------------------------------------------|
5โˆ’| 0 | 1 | 0 |
5+| 0 | 1 |
6
6
7โˆ’# <span id="non-breaking-changes"></span>๐Ÿ™† Non-breaking changes
7+# <span id="non-breaking-changes"></span>โš ๏ธ Non-breaking changes
8
8
9## **POST** /test
9## **POST** /test
10
10
test/golden/common/pathItem/operation/responses/change/headers/mandatory/add/trace-tree.yaml+3โˆ’3
@@ -1,5 +1,5 @@
1โˆ’breakingChanges: {}
1+forwardChanges: {}
2โˆ’nonBreakingChanges:
2+backwardChanges:
3 AtPath "/test":
3 AtPath "/test":
4 InOperation PostMethod:
4 InOperation PostMethod:
5โˆ’ WithStatusCode 200: ResponseHeaderMissing "Test2"
5+ WithStatusCode 200: ProducerDoesntHaveResponseHeader "Test2"
test/golden/common/pathItem/operation/responses/change/headers/mandatory/del/report.md+4โˆ’4
@@ -1,10 +1,10 @@
1# Summary
1# Summary
2
2
3โˆ’| [โš ๏ธ Breaking changes](#breaking-changes) | ๐Ÿ™† Non-breaking changes | ๐Ÿคท Unsupported feature changes |
3+| [โŒ Breaking changes](#breaking-changes) | โš ๏ธ Non-breaking changes |
4โˆ’|------------------------------------------|------------------------|-------------------------------|
4+|------------------------------------------|-------------------------|
5โˆ’| 1 | 0 | 0 |
5+| 1 | 0 |
6
6
7โˆ’# <span id="breaking-changes"></span>โš ๏ธ Breaking changes
7+# <span id="breaking-changes"></span>โŒ Breaking changes
8
8
9## **POST** /test
9## **POST** /test
10
10
test/golden/common/pathItem/operation/responses/change/headers/mandatory/del/trace-tree.yaml+3โˆ’3
@@ -1,5 +1,5 @@
1โˆ’breakingChanges:
1+forwardChanges:
2 AtPath "/test":
2 AtPath "/test":
3 InOperation PostMethod:
3 InOperation PostMethod:
4โˆ’ WithStatusCode 200: ResponseHeaderMissing "Test2"
4+ WithStatusCode 200: ProducerDoesntHaveResponseHeader "Test2"
5โˆ’nonBreakingChanges: {}
5+backwardChanges: {}
test/golden/common/pathItem/operation/responses/change/headers/optional/add/report.md+3โˆ’3
@@ -1,5 +1,5 @@
1# Summary
1# Summary
2
2
3โˆ’| โš ๏ธ Breaking changes | ๐Ÿ™† Non-breaking changes | ๐Ÿคท Unsupported feature changes |
3+| โŒ Breaking changes | โš ๏ธ Non-breaking changes |
4โˆ’|---------------------|------------------------|-------------------------------|
4+|---------------------|-------------------------|
5โˆ’| 0 | 0 | 0 |
5+| 0 | 0 |
test/golden/common/pathItem/operation/responses/change/headers/optional/add/trace-tree.yaml+2โˆ’2
@@ -1,2 +1,2 @@
1โˆ’breakingChanges: {}
1+forwardChanges: {}
2โˆ’nonBreakingChanges: {}
2+backwardChanges: {}
test/golden/common/pathItem/operation/responses/change/headers/optional/del/report.md+3โˆ’3
@@ -1,5 +1,5 @@
1# Summary
1# Summary
2
2
3โˆ’| โš ๏ธ Breaking changes | ๐Ÿ™† Non-breaking changes | ๐Ÿคท Unsupported feature changes |
3+| โŒ Breaking changes | โš ๏ธ Non-breaking changes |
4โˆ’|---------------------|------------------------|-------------------------------|
4+|---------------------|-------------------------|
5โˆ’| 0 | 0 | 0 |
5+| 0 | 0 |
test/golden/common/pathItem/operation/responses/change/headers/optional/del/trace-tree.yaml+2โˆ’2
@@ -1,2 +1,2 @@
1โˆ’breakingChanges: {}
1+forwardChanges: {}
2โˆ’nonBreakingChanges: {}
2+backwardChanges: {}
test/golden/common/pathItem/operation/responses/change/mediaTypeObject/add/report.md+5โˆ’5
@@ -1,13 +1,13 @@
1# Summary
1# Summary
2
2
3โˆ’| [โš ๏ธ Breaking changes](#breaking-changes) | ๐Ÿ™† Non-breaking changes | ๐Ÿคท Unsupported feature changes |
3+| [โŒ Breaking changes](#breaking-changes) | โš ๏ธ Non-breaking changes |
4โˆ’|------------------------------------------|------------------------|-------------------------------|
4+|------------------------------------------|-------------------------|
5โˆ’| 1 | 0 | 0 |
5+| 1 | 0 |
6
6
7โˆ’# <span id="breaking-changes"></span>โš ๏ธ Breaking changes
7+# <span id="breaking-changes"></span>โŒ Breaking changes
8
8
9## **POST** /test
9## **POST** /test
10
10
11### Response code 200
11### Response code 200
12
12
13โˆ’New media type was added: `application/x-www-form-urlencoded`.
13+Media type was added: `application/x-www-form-urlencoded`.
test/golden/common/pathItem/operation/responses/change/mediaTypeObject/add/trace-tree.yaml+3โˆ’3
@@ -1,5 +1,5 @@
1โˆ’breakingChanges:
1+forwardChanges:
2 AtPath "/test":
2 AtPath "/test":
3 InOperation PostMethod:
3 InOperation PostMethod:
4โˆ’ WithStatusCode 200: ResponseMediaTypeMissing application/x-www-form-urlencoded
4+ WithStatusCode 200: ConsumerDoesntHaveMediaType application/x-www-form-urlencoded
5โˆ’nonBreakingChanges: {}
5+backwardChanges: {}
test/golden/common/pathItem/operation/responses/change/mediaTypeObject/change/report.md+7โˆ’7
@@ -1,24 +1,24 @@
1# Summary
1# Summary
2
2
3โˆ’| [โš ๏ธ Breaking changes](#breaking-changes) | [๐Ÿ™† Non-breaking changes](#non-breaking-changes) | ๐Ÿคท Unsupported feature changes |
3+| [โŒ Breaking changes](#breaking-changes) | [โš ๏ธ Non-breaking changes](#non-breaking-changes) |
4โˆ’|------------------------------------------|-------------------------------------------------|-------------------------------|
4+|------------------------------------------|--------------------------------------------------|
5โˆ’| 1 | 1 | 0 |
5+| 1 | 1 |
6
6
7โˆ’# <span id="breaking-changes"></span>โš ๏ธ Breaking changes
7+# <span id="breaking-changes"></span>โŒ Breaking changes
8
8
9## **POST** /test
9## **POST** /test
10
10
11โˆ’### ๐Ÿ“ฑโฌ…๏ธ JSON Response โ€“ 200
11+### โฌ…๏ธโ˜๏ธ JSON Response โ€“ 200
12
12
13#### `$(Number)`
13#### `$(Number)`
14
14
15The type has been added.
15The type has been added.
16
16
17โˆ’# <span id="non-breaking-changes"></span>๐Ÿ™† Non-breaking changes
17+# <span id="non-breaking-changes"></span>โš ๏ธ Non-breaking changes
18
18
19## **POST** /test
19## **POST** /test
20
20
21โˆ’### ๐Ÿ“ฑโฌ…๏ธ JSON Response โ€“ 200
21+### โฌ…๏ธโ˜๏ธ JSON Response โ€“ 200
22
22
23#### `$(String)`
23#### `$(String)`
24
24
test/golden/common/pathItem/operation/responses/change/mediaTypeObject/change/trace-tree.yaml+4โˆ’4
@@ -1,14 +1,14 @@
1โˆ’breakingChanges:
1+forwardChanges:
2 AtPath "/test":
2 AtPath "/test":
3 InOperation PostMethod:
3 InOperation PostMethod:
4 WithStatusCode 200:
4 WithStatusCode 200:
5 ResponsePayload:
5 ResponsePayload:
6 PayloadSchema:
6 PayloadSchema:
7โˆ’ OfType Number: NoContradiction
7+ OfType Number: TypeBecomesEmpty
8โˆ’nonBreakingChanges:
8+backwardChanges:
9 AtPath "/test":
9 AtPath "/test":
10 InOperation PostMethod:
10 InOperation PostMethod:
11 WithStatusCode 200:
11 WithStatusCode 200:
12 ResponsePayload:
12 ResponsePayload:
13 PayloadSchema:
13 PayloadSchema:
14โˆ’ OfType String: NoContradiction
14+ OfType String: TypeBecomesEmpty
test/golden/common/pathItem/operation/responses/change/mediaTypeObject/del/report.md+4โˆ’4
@@ -1,10 +1,10 @@
1# Summary
1# Summary
2
2
3โˆ’| โš ๏ธ Breaking changes | [๐Ÿ™† Non-breaking changes](#non-breaking-changes) | ๐Ÿคท Unsupported feature changes |
3+| โŒ Breaking changes | [โš ๏ธ Non-breaking changes](#non-breaking-changes) |
4โˆ’|---------------------|-------------------------------------------------|-------------------------------|
4+|---------------------|--------------------------------------------------|
5โˆ’| 0 | 1 | 0 |
5+| 0 | 1 |
6
6
7โˆ’# <span id="non-breaking-changes"></span>๐Ÿ™† Non-breaking changes
7+# <span id="non-breaking-changes"></span>โš ๏ธ Non-breaking changes
8
8
9## **POST** /test
9## **POST** /test
10
10
test/golden/common/pathItem/operation/responses/change/mediaTypeObject/del/trace-tree.yaml+3โˆ’3
@@ -1,5 +1,5 @@
1โˆ’breakingChanges: {}
1+forwardChanges: {}
2โˆ’nonBreakingChanges:
2+backwardChanges:
3 AtPath "/test":
3 AtPath "/test":
4 InOperation PostMethod:
4 InOperation PostMethod:
5โˆ’ WithStatusCode 200: ResponseMediaTypeMissing application/x-www-form-urlencoded
5+ WithStatusCode 200: ConsumerDoesntHaveMediaType application/x-www-form-urlencoded
test/golden/common/pathItem/operation/responses/del/report.md+5โˆ’5
@@ -1,11 +1,11 @@
1# Summary
1# Summary
2
2
3โˆ’| โš ๏ธ Breaking changes | [๐Ÿ™† Non-breaking changes](#non-breaking-changes) | ๐Ÿคท Unsupported feature changes |
3+| โŒ Breaking changes | [โš ๏ธ Non-breaking changes](#non-breaking-changes) |
4โˆ’|---------------------|-------------------------------------------------|-------------------------------|
4+|---------------------|--------------------------------------------------|
5โˆ’| 0 | 1 | 0 |
5+| 0 | 1 |
6
6
7โˆ’# <span id="non-breaking-changes"></span>๐Ÿ™† Non-breaking changes
7+# <span id="non-breaking-changes"></span>โš ๏ธ Non-breaking changes
8
8
9## **POST** /test
9## **POST** /test
10
10
11โˆ’Reponse code 500 has been removed.
11+Response code 500 has been removed.
test/golden/common/pathItem/operation/responses/del/trace-tree.yaml+3โˆ’3
@@ -1,4 +1,4 @@
1โˆ’breakingChanges: {}
1+forwardChanges: {}
2โˆ’nonBreakingChanges:
2+backwardChanges:
3 AtPath "/test":
3 AtPath "/test":
4โˆ’ InOperation PostMethod: ResponseCodeNotFound 500
4+ InOperation PostMethod: ConsumerDoesntHaveResponseCode 500
test/golden/common/property-removed-additional/report.md+25โˆ’11
@@ -1,25 +1,39 @@
1# Summary
1# Summary
2
2
3โˆ’| [โš ๏ธ Breaking changes](#breaking-changes) | [๐Ÿ™† Non-breaking changes](#non-breaking-changes) | ๐Ÿคท Unsupported feature changes |
3+| [โŒ Breaking changes](#breaking-changes) | [โš ๏ธ Non-breaking changes](#non-breaking-changes) |
4โˆ’|------------------------------------------|-------------------------------------------------|-------------------------------|
4+|------------------------------------------|--------------------------------------------------|
5โˆ’| 1 | 1 | 0 |
5+| 3 | 3 |
6
6
7โˆ’# <span id="breaking-changes"></span>โš ๏ธ Breaking changes
7+# <span id="breaking-changes"></span>โŒ Breaking changes
8
8
9## **POST** /test
9## **POST** /test
10
10
11โˆ’### ๐Ÿ“ฑโฌ…๏ธ JSON Response โ€“ 200
11+### โฌ…๏ธโ˜๏ธ JSON Response โ€“ 200
12
12
13โˆ’#### `$(Object)`
13+#### `$.property2`
14
14
15โˆ’Property `property2` may not be present.
15+1. Values are no longer limited to the following types:
16
16
17+ - Number
18+
19+2. The property was previously explicitly defined. It is now implicitly
20+ described by the catch-all "additional properties" case.
21+
22+3. The property may not be present.
23+
17โˆ’# <span id="non-breaking-changes"></span>๐Ÿ™† Non-breaking changes
24+# <span id="non-breaking-changes"></span>โš ๏ธ Non-breaking changes
18
25
19## **POST** /test
26## **POST** /test
20
27
21โˆ’### ๐Ÿ“ฑโžก๏ธ JSON Request
28+### โžก๏ธโ˜๏ธ JSON Request
29+
30+#### `$.property2`
31+
32+1. Values are no longer limited to the following types:
33+
34+ - Number
22
35
23โˆ’#### `$(Object)`
36+2. The property was previously explicitly defined. It is now implicitly
37+ described by the catch-all "additional properties" case.
24
38
25โˆ’Property `property2` may not be present.
39+3. The property may not be present.
test/golden/common/property-removed-additional/trace-tree.yaml+12โˆ’4
@@ -1,14 +1,22 @@
1โˆ’breakingChanges:
1+forwardChanges:
2 AtPath "/test":
2 AtPath "/test":
3 InOperation PostMethod:
3 InOperation PostMethod:
4 WithStatusCode 200:
4 WithStatusCode 200:
5 ResponsePayload:
5 ResponsePayload:
6 PayloadSchema:
6 PayloadSchema:
7โˆ’ OfType Object: PropertyNowRequired "property2"
7+ OfType Object:
8โˆ’nonBreakingChanges:
8+ InProperty "property2":
9+ - TypesRestricted [Number]
10+ - AdditionalToProperty
11+ - PropertyNowRequired
12+backwardChanges:
9 AtPath "/test":
13 AtPath "/test":
10 InOperation PostMethod:
14 InOperation PostMethod:
11 InRequest:
15 InRequest:
12 InPayload:
16 InPayload:
13 PayloadSchema:
17 PayloadSchema:
14โˆ’ OfType Object: PropertyNowRequired "property2"
18+ OfType Object:
19+ InProperty "property2":
20+ - TypesRestricted [Number]
21+ - AdditionalToProperty
22+ - PropertyNowRequired
test/golden/common/property-removed/report.md+10โˆ’26
@@ -1,37 +1,21 @@
1# Summary
1# Summary
2
2
3โˆ’| [โš ๏ธ Breaking changes](#breaking-changes) | [๐Ÿ™† Non-breaking changes](#non-breaking-changes) | ๐Ÿคท Unsupported feature changes |
3+| [โŒ Breaking changes](#breaking-changes) | โš ๏ธ Non-breaking changes |
4โˆ’|------------------------------------------|-------------------------------------------------|-------------------------------|
4+|------------------------------------------|-------------------------|
5โˆ’| 2 | 2 | 0 |
5+| 2 | 0 |
6
6
7โˆ’# <span id="breaking-changes"></span>โš ๏ธ Breaking changes
7+# <span id="breaking-changes"></span>โŒ Breaking changes
8
8
9## **POST** /test
9## **POST** /test
10
10
11โˆ’### ๐Ÿ“ฑโžก๏ธ JSON Request
11+### โžก๏ธโ˜๏ธ JSON Request
12
12
13โˆ’#### `$(Object)`
13+#### `$.property2`
14
14
15โˆ’Property `property2` has been removed.
15+The property has been removed.
16
16
17โˆ’### ๐Ÿ“ฑโฌ…๏ธ JSON Response โ€“ 200
17+### โฌ…๏ธโ˜๏ธ JSON Response โ€“ 200
18
18
19โˆ’#### `$(Object)`
19+#### `$.property2`
20
20
21โˆ’Property `property2` may not be present.
22โˆ’
23โˆ’# <span id="non-breaking-changes"></span>๐Ÿ™† Non-breaking changes
24โˆ’
25โˆ’## **POST** /test
26โˆ’
27โˆ’### ๐Ÿ“ฑโžก๏ธ JSON Request
28โˆ’
29โˆ’#### `$(Object)`
30โˆ’
31โˆ’Property `property2` may not be present.
21+The property may not be present.
32โˆ’
33โˆ’### ๐Ÿ“ฑโฌ…๏ธ JSON Response โ€“ 200
34โˆ’
35โˆ’#### `$(Object)`
36โˆ’
37โˆ’Property `property2` has been removed.
test/golden/common/property-removed/trace-tree.yaml+10โˆ’6
@@ -1,22 +1,26 @@
1โˆ’breakingChanges:
1+forwardChanges:
2 AtPath "/test":
2 AtPath "/test":
3 InOperation PostMethod:
3 InOperation PostMethod:
4 InRequest:
4 InRequest:
5 InPayload:
5 InPayload:
6 PayloadSchema:
6 PayloadSchema:
7โˆ’ OfType Object: UnexpectedProperty "property2"
7+ OfType Object:
8+ InProperty "property2": UnexpectedProperty
8 WithStatusCode 200:
9 WithStatusCode 200:
9 ResponsePayload:
10 ResponsePayload:
10 PayloadSchema:
11 PayloadSchema:
11โˆ’ OfType Object: PropertyNowRequired "property2"
12+ OfType Object:
12โˆ’nonBreakingChanges:
13+ InProperty "property2": PropertyNowRequired
14+backwardChanges:
13 AtPath "/test":
15 AtPath "/test":
14 InOperation PostMethod:
16 InOperation PostMethod:
15 InRequest:
17 InRequest:
16 InPayload:
18 InPayload:
17 PayloadSchema:
19 PayloadSchema:
18โˆ’ OfType Object: PropertyNowRequired "property2"
20+ OfType Object:
21+ InProperty "property2": PropertyNowRequired
19 WithStatusCode 200:
22 WithStatusCode 200:
20 ResponsePayload:
23 ResponsePayload:
21 PayloadSchema:
24 PayloadSchema:
22โˆ’ OfType Object: UnexpectedProperty "property2"
25+ OfType Object:
26+ InProperty "property2": UnexpectedProperty
test/golden/common/property-required/report.md+11โˆ’11
@@ -1,25 +1,25 @@
1# Summary
1# Summary
2
2
3โˆ’| [โš ๏ธ Breaking changes](#breaking-changes) | [๐Ÿ™† Non-breaking changes](#non-breaking-changes) | ๐Ÿคท Unsupported feature changes |
3+| [โŒ Breaking changes](#breaking-changes) | [โš ๏ธ Non-breaking changes](#non-breaking-changes) |
4โˆ’|------------------------------------------|-------------------------------------------------|-------------------------------|
4+|------------------------------------------|--------------------------------------------------|
5โˆ’| 1 | 1 | 0 |
5+| 1 | 1 |
6
6
7โˆ’# <span id="breaking-changes"></span>โš ๏ธ Breaking changes
7+# <span id="breaking-changes"></span>โŒ Breaking changes
8
8
9## **POST** /test
9## **POST** /test
10
10
11โˆ’### ๐Ÿ“ฑโžก๏ธ JSON Request
11+### โžก๏ธโ˜๏ธ JSON Request
12
12
13โˆ’#### `$(Object)`
13+#### `$.property2`
14
14
15โˆ’Property `property2` has become required.
15+The property has become required.
16
16
17โˆ’# <span id="non-breaking-changes"></span>๐Ÿ™† Non-breaking changes
17+# <span id="non-breaking-changes"></span>โš ๏ธ Non-breaking changes
18
18
19## **POST** /test
19## **POST** /test
20
20
21โˆ’### ๐Ÿ“ฑโฌ…๏ธ JSON Response โ€“ 200
21+### โฌ…๏ธโ˜๏ธ JSON Response โ€“ 200
22
22
23โˆ’#### `$(Object)`
23+#### `$.property2`
24
24
25โˆ’Property `property2` has become required.
25+The property has become required.
test/golden/common/property-required/trace-tree.yaml+6โˆ’4
@@ -1,14 +1,16 @@
1โˆ’breakingChanges:
1+forwardChanges:
2 AtPath "/test":
2 AtPath "/test":
3 InOperation PostMethod:
3 InOperation PostMethod:
4 InRequest:
4 InRequest:
5 InPayload:
5 InPayload:
6 PayloadSchema:
6 PayloadSchema:
7โˆ’ OfType Object: PropertyNowRequired "property2"
7+ OfType Object:
8โˆ’nonBreakingChanges:
8+ InProperty "property2": PropertyNowRequired
9+backwardChanges:
9 AtPath "/test":
10 AtPath "/test":
10 InOperation PostMethod:
11 InOperation PostMethod:
11 WithStatusCode 200:
12 WithStatusCode 200:
12 ResponsePayload:
13 ResponsePayload:
13 PayloadSchema:
14 PayloadSchema:
14โˆ’ OfType Object: PropertyNowRequired "property2"
15+ OfType Object:
16+ InProperty "property2": PropertyNowRequired
test/golden/common/random-example/a.yamlnew file+56
@@ -0,0 +1,56 @@
1+openapi: "3.0.0"
2+info:
3+ version: 1.0.0
4+ title: Swagger Petstore
5+ license:
6+ name: MIT
7+servers:
8+ - url: https://example.com
9+paths:
10+ /pets:
11+ get:
12+ parameters:
13+ - name: limit
14+ in: query
15+ required: false
16+ schema:
17+ type: integer
18+ maximum: 20
19+ responses:
20+ "200":
21+ description: ""
22+ headers:
23+ x-next:
24+ schema:
25+ type: string
26+ content:
27+ application/json:
28+ schema:
29+ $ref: "#/components/schemas/Pets"
30+ post:
31+ requestBody:
32+ content:
33+ application/json:
34+ schema:
35+ $ref: "#/components/schemas/Pet"
36+ responses:
37+ "201":
38+ description: ""
39+components:
40+ schemas:
41+ Pet:
42+ type: object
43+ required:
44+ - id
45+ - name
46+ properties:
47+ id:
48+ type: integer
49+ name:
50+ type: string
51+ minLength: 3
52+ maxLength: 10
53+ Pets:
54+ type: array
55+ items:
56+ $ref: "#/components/schemas/Pet"
test/golden/common/random-example/b.yamlnew file+58
@@ -0,0 +1,58 @@
1+openapi: "3.0.0"
2+info:
3+ version: 1.1.0
4+ title: Swagger Petstore
5+ license:
6+ name: MIT
7+servers:
8+ - url: https://example.com
9+paths:
10+ /pets:
11+ get:
12+ parameters:
13+ - name: limit
14+ in: query
15+ required: false
16+ schema:
17+ type: integer
18+ maximum: 30
19+ responses:
20+ "200":
21+ description: ""
22+ headers:
23+ x-next:
24+ schema:
25+ type: string
26+ content:
27+ application/json:
28+ schema:
29+ $ref: "#/components/schemas/Pets"
30+ post:
31+ requestBody:
32+ content:
33+ application/json:
34+ schema:
35+ $ref: "#/components/schemas/Pet"
36+ responses:
37+ "201":
38+ description: ""
39+components:
40+ schemas:
41+ Pet:
42+ type: object
43+ required:
44+ - id
45+ - name
46+ properties:
47+ id:
48+ type: integer
49+ name:
50+ type: string
51+ minLength: 1
52+ maxLength: 15
53+ weight:
54+ type: integer
55+ Pets:
56+ type: array
57+ items:
58+ $ref: "#/components/schemas/Pet"
test/golden/common/random-example/report.mdnew file+71
@@ -0,0 +1,71 @@
1+# Summary
2+
3+| [โŒ Breaking changes](#breaking-changes) | [โš ๏ธ Non-breaking changes](#non-breaking-changes) |
4+|------------------------------------------|--------------------------------------------------|
5+| 5 | 6 |
6+
7+# <span id="breaking-changes"></span>โŒ Breaking changes
8+
9+## **GET** /pets
10+
11+### โฌ…๏ธโ˜๏ธ JSON Response โ€“ 200
12+
13+#### `$[*].name(String)`
14+
15+1. Maximum length of the string changed from 10 to 15.
16+
17+2. Minimum length of the string changed from 3 to 1.
18+
19+## **POST** /pets
20+
21+### โžก๏ธโ˜๏ธ JSON Request
22+
23+#### `$.weight`
24+
25+1. Values are now limited to the following types:
26+
27+ - Number
28+
29+2. The property was previously implicitly described by the catch-all
30+ "additional properties" case. It is now explicitly defined.
31+
32+#### `$.weight(Number)`
33+
34+Value is now a multiple of 1.0.
35+
36+# <span id="non-breaking-changes"></span>โš ๏ธ Non-breaking changes
37+
38+## **GET** /pets
39+
40+### Parameter limit
41+
42+#### JSON Schema
43+
44+##### `$(Number)`
45+
46+Upper bound changed from 20.0 inclusive to 30.0 inclusive.
47+
48+### โฌ…๏ธโ˜๏ธ JSON Response โ€“ 200
49+
50+#### `$[*].weight`
51+
52+1. Values are now limited to the following types:
53+
54+ - Number
55+
56+2. The property was previously implicitly described by the catch-all
57+ "additional properties" case. It is now explicitly defined.
58+
59+#### `$[*].weight(Number)`
60+
61+Value is now a multiple of 1.0.
62+
63+## **POST** /pets
64+
65+### โžก๏ธโ˜๏ธ JSON Request
66+
67+#### `$.name(String)`
68+
69+1. Maximum length of the string changed from 10 to 15.
70+
71+2. Minimum length of the string changed from 3 to 1.
test/golden/common/random-example/trace-tree.yamlnew file+48
@@ -0,0 +1,48 @@
1+forwardChanges:
2+ AtPath "/pets":
3+ InOperation GetMethod:
4+ WithStatusCode 200:
5+ ResponsePayload:
6+ PayloadSchema:
7+ OfType Array:
8+ InItems:
9+ OfType Object:
10+ InProperty "name":
11+ OfType String:
12+ - MatchingMaxLengthWeak (ProdCons {producer = 15, consumer = 10})
13+ - MatchingMinLengthWeak (ProdCons {producer = 1, consumer = 3})
14+ InOperation PostMethod:
15+ InRequest:
16+ InPayload:
17+ PayloadSchema:
18+ OfType Object:
19+ InProperty "weight":
20+ - TypesRestricted [Number]
21+ - AdditionalToProperty
22+ - OfType Number: NoMatchingMultipleOf 1.0
23+backwardChanges:
24+ AtPath "/pets":
25+ InOperation GetMethod:
26+ WithStatusCode 200:
27+ ResponsePayload:
28+ PayloadSchema:
29+ OfType Array:
30+ InItems:
31+ OfType Object:
32+ InProperty "weight":
33+ - TypesRestricted [Number]
34+ - AdditionalToProperty
35+ - OfType Number: NoMatchingMultipleOf 1.0
36+ InParam "limit":
37+ InParamSchema:
38+ OfType Number: MatchingMaximumWeak (ProdCons {producer = Inclusive 30.0,
39+ consumer = Inclusive 20.0})
40+ InOperation PostMethod:
41+ InRequest:
42+ InPayload:
43+ PayloadSchema:
44+ OfType Object:
45+ InProperty "name":
46+ OfType String:
47+ - MatchingMaxLengthWeak (ProdCons {producer = 15, consumer = 10})
48+ - MatchingMinLengthWeak (ProdCons {producer = 1, consumer = 3})
test/golden/common/recursive/a.yaml+6
@@ -7,6 +7,12 @@ servers:
7paths:
7paths:
8 /api/foo:
8 /api/foo:
9 get:
9 get:
10+ requestBody:
11+ content:
12+ application/json;charset=utf-8:
13+ schema:
14+ $ref: "#/components/schemas/Tree"
15+
10 responses:
16 responses:
11 200:
17 200:
12 description: ""
18 description: ""
test/golden/common/recursive/b.yaml+6
@@ -7,6 +7,12 @@ servers:
7paths:
7paths:
8 /api/foo:
8 /api/foo:
9 get:
9 get:
10+ requestBody:
11+ content:
12+ application/json;charset=utf-8:
13+ schema:
14+ $ref: "#/components/schemas/Tree"
15+
10 responses:
16 responses:
11 200:
17 200:
12 description: ""
18 description: ""
test/golden/common/recursive/report.md+20โˆ’6
@@ -1,18 +1,32 @@
1# Summary
1# Summary
2
2
3โˆ’| โš ๏ธ Breaking changes | [๐Ÿ™† Non-breaking changes](#non-breaking-changes) | ๐Ÿคท Unsupported feature changes |
3+| [โŒ Breaking changes](#breaking-changes) | [โš ๏ธ Non-breaking changes](#non-breaking-changes) |
4โˆ’|---------------------|-------------------------------------------------|-------------------------------|
4+|------------------------------------------|--------------------------------------------------|
5โˆ’| 0 | 1 | 0 |
5+| 1 | 1 |
6
6
7โˆ’# <span id="non-breaking-changes"></span>๐Ÿ™† Non-breaking changes
7+# <span id="breaking-changes"></span>โŒ Breaking changes
8
8
9## **GET** /api/foo
9## **GET** /api/foo
10
10
11โˆ’### ๐Ÿ“ฑโฌ…๏ธ JSON Response โ€“ 200
11+### โžก๏ธโ˜๏ธ JSON Request
12
12
13#### `$.leaf.value.foo(String)`
13#### `$.leaf.value.foo(String)`
14
14
15โˆ’The following enum value has been removed:
15+The following enum value has been added:
16+
17+``` json
18+"a"
19+```
20+
21+# <span id="non-breaking-changes"></span>โš ๏ธ Non-breaking changes
22+
23+## **GET** /api/foo
24+
25+### โฌ…๏ธโ˜๏ธ JSON Response โ€“ 200
26+
27+#### `$.leaf.value.foo(String)`
28+
29+The following enum value has been added:
16
30
17``` json
31``` json
18"a"
32"a"
test/golden/common/recursive/trace-tree.yaml+14โˆ’2
@@ -1,5 +1,17 @@
1โˆ’breakingChanges: {}
1+forwardChanges:
2โˆ’nonBreakingChanges:
2+ AtPath "/api/foo":
3+ InOperation GetMethod:
4+ InRequest:
5+ InPayload:
6+ PayloadSchema:
7+ OfType Object:
8+ InProperty "leaf":
9+ OfType Object:
10+ InProperty "value":
11+ OfType Object:
12+ InProperty "foo":
13+ OfType String: NoMatchingEnum (String "a")
14+backwardChanges:
3 AtPath "/api/foo":
15 AtPath "/api/foo":
4 InOperation GetMethod:
16 InOperation GetMethod:
5 WithStatusCode 200:
17 WithStatusCode 200:
test/golden/common/security-scheme/report.md+5โˆ’5
@@ -1,10 +1,10 @@
1# Summary
1# Summary
2
2
3โˆ’| [โš ๏ธ Breaking changes](#breaking-changes) | [๐Ÿ™† Non-breaking changes](#non-breaking-changes) | ๐Ÿคท Unsupported feature changes |
3+| [โŒ Breaking changes](#breaking-changes) | [โš ๏ธ Non-breaking changes](#non-breaking-changes) |
4โˆ’|------------------------------------------|-------------------------------------------------|-------------------------------|
4+|------------------------------------------|--------------------------------------------------|
5โˆ’| 2 | 1 | 0 |
5+| 2 | 1 |
6
6
7โˆ’# <span id="breaking-changes"></span>โš ๏ธ Breaking changes
7+# <span id="breaking-changes"></span>โŒ Breaking changes
8
8
9## **POST** /oauth/check
9## **POST** /oauth/check
10
10
@@ -22,7 +22,7 @@ Security scheme has been removed.
22
22
23Security scheme has been removed.
23Security scheme has been removed.
24
24
25โˆ’# <span id="non-breaking-changes"></span>๐Ÿ™† Non-breaking changes
25+# <span id="non-breaking-changes"></span>โš ๏ธ Non-breaking changes
26
26
27## **POST** /oauth/check
27## **POST** /oauth/check
28
28
test/golden/common/security-scheme/trace-tree.yaml+2โˆ’2
@@ -1,4 +1,4 @@
1โˆ’breakingChanges:
1+forwardChanges:
2 AtPath "/oauth/sign_out":
2 AtPath "/oauth/sign_out":
3 InOperation GetMethod:
3 InOperation GetMethod:
4 SecurityRequirementStep 1:
4 SecurityRequirementStep 1:
@@ -7,7 +7,7 @@ breakingChanges:
7 InOperation PostMethod:
7 InOperation PostMethod:
8 SecurityRequirementStep 0:
8 SecurityRequirementStep 0:
9 SecuritySchemeStep "oauth": SecuritySchemeNotMatched
9 SecuritySchemeStep "oauth": SecuritySchemeNotMatched
10โˆ’nonBreakingChanges:
10+backwardChanges:
11 AtPath "/oauth/check":
11 AtPath "/oauth/check":
12 InOperation PostMethod:
12 InOperation PostMethod:
13 SecurityRequirementStep 0:
13 SecurityRequirementStep 0:
test/golden/common/servers/report.md+7โˆ’7

This diff is too big to show here.

test/golden/common/servers/trace-tree.yaml+2โˆ’2

This diff is too big to show here.

test/golden/common/tuple-items/heterogeneous-component-mismatch/a.yamlnew file+28

This diff is too big to show here.

test/golden/common/tuple-items/heterogeneous-component-mismatch/b.yamlnew file+28

This diff is too big to show here.

test/golden/common/tuple-items/heterogeneous-component-mismatch/report.mdnew file+37

This diff is too big to show here.

test/golden/common/tuple-items/heterogeneous-component-mismatch/trace-tree.yamlnew file+30

This diff is too big to show here.

test/golden/common/tuple-items/heterogeneous-length-mismatch/a.yamlnew file+29

This diff is too big to show here.

test/golden/common/tuple-items/heterogeneous-length-mismatch/b.yamlnew file+28

This diff is too big to show here.

test/golden/common/tuple-items/heterogeneous-length-mismatch/report.mdnew file+21

This diff is too big to show here.

test/golden/common/tuple-items/heterogeneous-length-mismatch/trace-tree.yamlnew file+26

This diff is too big to show here.

test/golden/common/tuple-items/homogeneous-component-mismatch/a.yamlnew file+28

This diff is too big to show here.

test/golden/common/tuple-items/homogeneous-component-mismatch/b.yamlnew file+29

This diff is too big to show here.

test/golden/common/tuple-items/homogeneous-component-mismatch/report.mdnew file+45

This diff is too big to show here.

test/golden/common/tuple-items/homogeneous-component-mismatch/trace-tree.yamlnew file+34

This diff is too big to show here.

test/golden/common/tuple-items/homogeneous-length-mismatch/a.yamlnew file+56

This diff is too big to show here.

test/golden/common/tuple-items/homogeneous-length-mismatch/b.yamlnew file+67

This diff is too big to show here.

test/golden/common/tuple-items/homogeneous-length-mismatch/report.mdnew file+73

This diff is too big to show here.

test/golden/common/tuple-items/homogeneous-length-mismatch/trace-tree.yamlnew file+52

This diff is too big to show here.

test/golden/common/tuple-items/homogeneous-vector/a.yamlnew file+28

This diff is too big to show here.

test/golden/common/tuple-items/homogeneous-vector/b.yamlnew file+29

This diff is too big to show here.

test/golden/common/tuple-items/homogeneous-vector/report.mdnew file+5

This diff is too big to show here.

test/golden/common/tuple-items/homogeneous-vector/trace-tree.yamlnew file+2

This diff is too big to show here.

test/golden/common/type-changing/a.yamlnew file+113

This diff is too big to show here.

test/golden/common/type-changing/b.yamlnew file+108

This diff is too big to show here.

test/golden/common/type-changing/report.mdnew file+105

This diff is too big to show here.

test/golden/common/type-changing/trace-tree.yamlnew file+60

This diff is too big to show here.

test/golden/common/unguarded-recursive/report.md+6โˆ’6

This diff is too big to show here.

test/golden/common/unguarded-recursive/trace-tree.yaml+2โˆ’2

This diff is too big to show here.

test/golden/common/variant-added/a.yamlnew file+39

This diff is too big to show here.

test/golden/common/variant-added/b.yamlnew file+46

This diff is too big to show here.

test/golden/common/variant-added/report.mdnew file+25

This diff is too big to show here.

test/golden/common/variant-added/trace-tree.yamlnew file+16

This diff is too big to show here.

test/golden/common/variant-changed/a.yamlnew file+39

This diff is too big to show here.

test/golden/common/variant-changed/b.yamlnew file+39

This diff is too big to show here.

test/golden/common/variant-changed/report.mdnew file+45

This diff is too big to show here.

test/golden/common/variant-changed/trace-tree.yamlnew file+34

This diff is too big to show here.

test/golden/common/variant-deep-changed/a.yamlnew file+47

This diff is too big to show here.

test/golden/common/variant-deep-changed/b.yamlnew file+47

This diff is too big to show here.

test/golden/common/variant-deep-changed/report.mdnew file+45

This diff is too big to show here.

test/golden/common/variant-deep-changed/trace-tree.yamlnew file+34

This diff is too big to show here.