diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml new file mode 100644 index 0000000..2adf676 --- /dev/null +++ b/.github/workflows/ci.yml @@ -0,0 +1,85 @@ +name: CI +on: [push, pull_request] +jobs: + build: + name: Build & test + runs-on: ubuntu-latest + + strategy: + matrix: + node-version: [20.x, 22.x, '*'] + + steps: + - uses: actions/checkout@v4 + + - uses: actions/setup-node@v4 + with: + node-version: ${{ matrix.node-version }} + cache: 'npm' + cache-dependency-path: 'package.json' + + - uses: shivammathur/setup-php@v2 + with: + php-version: '7.0' + + - run: npm ci + - run: npm test + + publish: + name: Publish to npm + needs: build + if: startsWith(github.ref, 'refs/tags/v') + runs-on: ubuntu-latest + environment: + name: npm + url: https://www.npmjs.com/package/@httptoolkit/httpsnippet + permissions: + contents: read + id-token: write + + steps: + - uses: actions/checkout@v4 + + - uses: actions/setup-node@v4 + with: + node-version: '22.x' + registry-url: 'https://registry.npmjs.org' + cache: 'npm' + cache-dependency-path: 'package.json' + + - run: npm ci + + - name: Verify tag matches package.json version + id: version-check + run: | + TAG_VERSION=${GITHUB_REF#refs/tags/v} + PACKAGE_VERSION=$(node -p "require('./package.json').version") + if [ "$TAG_VERSION" != "$PACKAGE_VERSION" ]; then + echo "Error: Tag version (v$TAG_VERSION) does not match package.json version ($PACKAGE_VERSION)" + exit 1 + fi + echo "✓ Tag version matches package.json version: $PACKAGE_VERSION" + + # Check if version matches strict X.Y.Z format (stable release) + if echo "$PACKAGE_VERSION" | grep -Eq '^[0-9]+\.[0-9]+\.[0-9]+$'; then + echo "Stable release version detected: $PACKAGE_VERSION" + echo "is_prerelease=false" >> $GITHUB_OUTPUT + else + echo "Prerelease version detected: $PACKAGE_VERSION" + echo "is_prerelease=true" >> $GITHUB_OUTPUT + fi + + # Make sure we have the latest npm for publishing: + - run: npm install -g npm@latest + + - name: Publish to npm + run: | + if [ "${{ steps.version-check.outputs.is_prerelease }}" == "true" ]; then + echo "Publishing untagged prerelease" + npm publish --provenance --tag test + # We have to publish with a tag (so we use 'test') but we can clean it up: + npm dist-tag rm @httptoolkit/httpsnippet test --silent + else + echo "Publishing stable release with 'latest' tag" + npm publish --provenance + fi \ No newline at end of file diff --git a/.gitignore b/.gitignore index dddca89..a41ca4a 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,4 @@ *.log node_modules coverage* +.vscode \ No newline at end of file diff --git a/.travis.yml b/.travis.yml deleted file mode 100644 index c7e2c8e..0000000 --- a/.travis.yml +++ /dev/null @@ -1,12 +0,0 @@ -language: node_js - -node_js: - - node - - lts/* - -before_install: - - sudo apt-get update -qq - - sudo apt-get install -qq php7.0 php7.0-curl php7.0-cli - -after_script: - - npm run codeclimate diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index c4cae94..ba2b0ba 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -11,7 +11,7 @@ patches and features. ## Using the issue tracker The [issue tracker](/issues) is the preferred channel for [bug reports](#bug-reports), -[features requests](#feature-requests) and [submitting pull requests](#pull-requests), +[features requests](#feature-requests) and [submitting pull requests](#pull-requests), but please respect the following restrictions: * Please **do not** use the issue tracker for personal support requests (use @@ -93,7 +93,7 @@ project: # Navigate to the newly cloned directory cd # Assign the original repo to a remote called "upstream" - git remote add upstream https://github.com/Mashape/httpsnippet.git + git remote add upstream https://github.com/httptoolkit/httpsnippet.git ``` 2. If you cloned a while ago, get the latest changes from upstream: @@ -136,4 +136,291 @@ license your work under the same license as that used by the project. ## Creating New Conversion Targets -For a info on creating new conversion targets, please review this [guideline](https://github.com/Mashape/httpsnippet/wiki/Creating-Targets) +A target is a simple module with a constructor that accepts two parameters: `source` and `options`, where `source` is the HAR Object to process, and `options` is an optional object with any target-specific flags *(used for customizing the output)*. + +###### Example + +```js +module.exports = function (source, opts) { + // optionally process `opts` object for target specific configuration + // + // process `source` object + // + // return processed output as string +}; + +module.exports.info = { + key: 'curl', + title: 'cURL', + link: 'http://curl.haxx.se/', + description: 'curl is a command line tool and library for transferring data with URL syntax', + extname: '.sh' +}; +``` + +### Conversion Rules + +1. Start by reading and understanding the [HAR](http://www.softwareishard.com/blog/har-12-spec/#request) format. +2. Utilize utility properties created for convenience (`source.headersObj`, `source.uriObj` etc ...) *see below for mode details* +3. Follow the guidelines below for best practices and consistency. + +### Guidelines + +Using the following example of a request object, HTTP Snippet will pre-process data and create some additional properties: + +| property | description | +| --------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------- | +| `source.fullUrl` | the full & final url, including all query string values | +| `source.uriObj` | the url parsed with `url.parse()`. compatible with `url.format` | +| `source.queryObj` | a key => value pair, "normalized" version of `source.queryString`, adds additional query string values from the `source.url` | +| `source.headersObj` | a key => value pair, "normalized" version of `source.headers`, header names are lowercased | +| `source.allHeaders` | same as `source.headersObj` but with `cookies` header and populated from `source.cookies` array | +| `source.postData.jsonObj` | the parsed value of `source.postData.text`, only for `source.postData.mimeType` = `application/json` *(or equivalent mimeTypes)* | +| `source.postData.paramsObj` | a key => value pair, "normalized" version of `source.postData.params`, only for `source.postData.mimeType` = `application/x-www-form-urlencoded` | + +###### Sample Incoming Request Object + +```js +{ + method: 'POST', + url: 'http://mockbin.com/har?key=value', + httpVersion: 'HTTP/1.1', + queryString: [ + { name: 'foo', value: 'bar' }, + { name: 'foo', value: 'baz' }, + { name: 'baz', value: 'abc' } + ], + headers: [ + { name: 'Accept', value: 'application/json' }, + { name: 'Content-Type', value: 'application/x-www-form-urlencoded' } + ], + + cookies: [ + { name: 'foo', value: 'bar' }, + { name: 'bar', value: 'baz' } + ], + + postData: { + mimeType: 'application/x-www-form-urlencoded', + params: [ + { name: 'foo', value: 'bar' }, + { name: 'foo', value: 'baz' }, + { name: 'baz', value: 'abc' } + ] + } +} +``` + +###### Processed Source Object + +```js +{ + method: 'POST', + + // the base url value stripped of any the query string + url: 'http://mockbin.com/har', + + // the full & final url, including all query string values + fullUrl: 'http://mockbin.com/har?foo=bar&foo=baz&baz=abc&key=value', + + // the url parsed with url.parse() + // compatible with url.format + uriObj: { + protocol: 'http:', + slashes: true, + auth: null, + host: 'mockbin.com', + port: null, + hostname: 'mockbin.com', + hash: null, + search: 'key=value&baz=abc&foo=bar&foo=baz', + query: { key: 'value', baz: 'abc', foo: [Object] }, + pathname: '/har', + path: '/har?key=value&baz=abc&foo=bar&foo=baz', + href: 'http://mockbin.com/har' + }, + + httpVersion: 'HTTP/1.1', + + // added to pass har-validator + bodySize: 0, + + // added to pass har-validator + headersSize: 0, + + queryString: [ + { name: 'foo', value: 'bar' }, + { name: 'foo', value: 'baz' }, + { name: 'baz', value: 'abc' } + ], + + // "normalized" version of `queryString` + // adds any additional query string values from the url + // compatible with "querystring" node module + queryObj: { + key: 'value', + baz: 'abc', + foo: [ 'bar', 'baz' ] + }, + + headers: [ + { name: 'Accept', value: 'application/json' }, + { name: 'Content-Type', value: 'application/x-www-form-urlencoded' } + ], + + // normalized headers array into a key => value object pair + // header names are lowercased + headersObj: { + 'accept': 'application/json', + 'content-type': 'application/x-www-form-urlencoded' + }, + + // same as headersObj but with Cookies added (if any exist in cookies array) + allHeaders: { + 'accept': 'application/json', + 'content-type': 'application/x-www-form-urlencoded', + 'cookie': 'foo=bar; bar=baz' + }, + + cookies: [ + { name: 'foo', value: 'bar' }, + { name: 'bar', value: 'baz' } + ], + + // see below for different scenarios + postData: [Object] +} +``` + +###### application/x-www-form-urlencoded + +```js +postData: { + // added to pass har-validator + size: 0, + + // original value + mimeType: 'application/x-www-form-urlencoded', + + // original value + params: [ + { name: 'foo', value: 'bar' }, + { name: 'foo', value: 'baz' }, + { name: 'baz', value: 'abc' } + ], + + // "normalized" version of `params` + // compatible with "querystring" node module + paramsObj: { + key: 'value', + baz: 'abc', + foo: [ 'bar', 'baz' ] + } + + // the raw body in plain text + // this value will be always overwritten in this scenario + text: 'baz=abc&foo=bar&foo=baz' + + // see below + jsonObj: false +} +``` + +###### application/json + +- Will match when `postData.mimeType` is one of: `application/json`, `text/json`, `text/x-json`, `application/x-json` +- In case of failure to parse `postData.text` as a JSON object, `postData.mimeType` is set to `text/plain`, `postData.jsonObj` remains as `false`. this is done so that the implementing target, would still attempt to post the raw body as is. +- This also emphasizes not to rely on `postData.mimeType` for the `Content-Type` header! + +```js +postData: { + // added to pass har-validator + size: 0, + + // original value + mimeType: 'application/json', + + // ignored + params: [], + + // default value + paramsObj: false + + // the raw body in plain text + text: '"{\"foo\": \"bar\"}"' + + // the parsed value of postData.text + jsonObj: { + foo: 'bar' + } +} +``` + +###### multipart/form-data + +- Will match when `postData.mimeType` is one of: `multipart/mixed` `multipart/related`, `multipart/form-data`, `multipart/alternative` +- Will force `postData.mimeType` to `multipart/form-data` +- Will create/overwrite the `Content-Type` header if it does not exist, with the appropriate boundary flag. +- When no `params[].value` is present, will default to empty content + +```js +postData: { + // added to pass har-validator + size: 0, + + // original value + mimeType: 'multipart/form-data', + + // parsed into text values + params: [ + { + name: 'foo', + value: 'bar' + } + ] + + // ignored + paramsObj: false + + // the raw body in plain text + // generated based on appropriately parsing the `params` into a multi-boundary content string + // this value will be always overwritten in this scenario + text: '----------------------------591447866569479977899212\r\nContent-Disposition: form-data; name=\"foo\"\r\n\r\nbar\r\n----------------------------591447866569479977899212--' + + // ignored + jsonObj: false +} +``` + +###### multipart/form-data (File Uploads) + +```js +postData: { + // added to pass har-validator + size: 0, + + // original value + mimeType: 'multipart/form-data', + + // parsed into text values + params: [ + { + name: 'foo', + value: 'Hello World', + fileName: 'test/fixtures/files/hello.txt', + contentType: 'text/plain' + } + ] + + // ignored + paramsObj: false + + // the raw body in plain text + // generated based on appropriately parsing the `params` into a multi-boundary content string + // this value will be always overwritten in this scenario + text: '----------------------------771333709043252625002993\r\nContent-Disposition: form-data; name=\"foo\"; filename=\"hello.txt\"\r\nContent-Type: text/plain\r\n\r\nHello World\r\n----------------------------771333709043252625002993--' + + // ignored + jsonObj: false +} +``` diff --git a/README.md b/README.md index cb59c19..9884759 100644 --- a/README.md +++ b/README.md @@ -1,29 +1,28 @@ -# HTTP Snippet [![version][npm-version]][npm-url] [![License][npm-license]][license-url] +# @httptoolkit/HTTPSnippet [![Build Status](https://github.com/httptoolkit/httpsnippet/workflows/CI/badge.svg)](https://github.com/httptoolkit/httpsnippet/actions) [![Available on NPM](https://img.shields.io/npm/v/@httptoolkit/httpsnippet.svg)](https://npmjs.com/package/@httptoolkit/httpsnippet) -> HTTP Request snippet generator for *many* languages & tools including: `cURL`, `HTTPie`, `Javascript`, `Node`, `C`, `Java`, `PHP`, `Objective-C`, `Swift`, `Python`, `Ruby`, `C#`, `Go`, `OCaml` and [more](https://github.com/Mashape/httpsnippet/wiki/Targets)! +> _Part of [HTTP Toolkit](https://httptoolkit.tech): powerful tools for building, testing & debugging HTTP(S)_ -Relies on the popular [HAR](http://www.softwareishard.com/blog/har-12-spec/#request) format to import data and describe HTTP calls. +Httpsnippet is an HTTP request snippet generator for *many* languages & tools including: `cURL`, `HTTPie`, `Javascript`, `Node`, `C`, `Java`, `PHP`, `Objective-C`, `Swift`, `Python`, `Ruby`, `C#`, `Go`, `OCaml` and [more](https://github.com/httptoolkit/httpsnippet/tree/main/src/targets)! -See it in action on companion service: [APIembed](https://apiembed.com/) +This library relies on the popular [HAR](http://www.softwareishard.com/blog/har-12-spec/#request) format to import data and describe HTTP calls. -[![Build Status][travis-image]][travis-url] -[![Downloads][npm-downloads]][npm-url] +_This is a fork of Kong's (previous Mashape's) [httpsnippet](https://github.com/Kong/httpsnippet/) library, which appears to no longer be maintained. This version is in active production use in [HTTP Toolkit](https://httptoolkit.tech)._ ## Install ```shell # to use in cli -npm install --global httpsnippet +npm install --global @httptoolkit/httpsnippet # to use as a module -npm install --save httpsnippet +npm install --save @httptoolkit/httpsnippet ``` ## Usage ``` - Usage: httpsnippet [options] + Usage: httpsnippet [options] Options: @@ -32,6 +31,7 @@ npm install --save httpsnippet -t, --target target output -c, --client [client] target client library -o, --output write output to directory + -x, --extra [{"optionKey": "optionValue"}] provide extra options for the target/client ``` @@ -63,6 +63,13 @@ snippets/ └── endpoint-3.js ``` +provide extra options: + +```shell +httpsnippet example.json --target http --output ./snippets -x '{"autoHost": false, "autoContentLength": false}' +``` + + ## API ### HTTPSnippet(source) @@ -72,7 +79,7 @@ snippets/ *Required* Type: `object` -Name of [conversion target](https://github.com/Mashape/httpsnippet/wiki/Targets) +Name of [conversion target](TARGETS.md) ```js var HTTPSnippet = require('httpsnippet'); @@ -90,13 +97,13 @@ var snippet = new HTTPSnippet({ *Required* Type: `string` -Name of [conversion target](https://github.com/Mashape/httpsnippet/wiki/Targets) +Name of [conversion target](TARGETS.md) #### options Type: `object` -Target options, *see [wiki](https://github.com/Mashape/httpsnippet/wiki/Targets) for details* +Target options, *see [target docs](https://github.com/httptoolkit/httpsnippet/blob/main/TARGETS.md) for details* ```js var HTTPSnippet = require('httpsnippet'); @@ -122,19 +129,19 @@ console.log(snippet.convert('node', { *Required* Type: `string` -Name of [conversion target](https://github.com/Mashape/httpsnippet/wiki/Targets) +Name of [conversion target](TARGETS.md) #### client Type: `string` -Name of conversion target [client library](https://github.com/Mashape/httpsnippet/wiki/Targets) +Name of conversion target [client library](TARGETS.md) #### options Type: `object` -Target options, *see [wiki](https://github.com/Mashape/httpsnippet/wiki/Targets) for details* +Target options, *see [target docs](https://github.com/httptoolkit/httpsnippet/blob/main/TARGETS.md) for details* ```js var HTTPSnippet = require('httpsnippet'); @@ -159,7 +166,7 @@ console.log(snippet.convert('node', 'unirest')); *Required* Type: `object` -Representation of a [conversion target](https://github.com/Kong/httpsnippet/wiki/Creating-Targets). Can use this to use targets that are not officially supported. +Representation of a [conversion target](https://github.com/httptoolkit/httpsnippet/blob/main/CONTRIBUTING.md#creating-new-conversion-targets). Can use this to use targets that are not officially supported. ```js const customLanguageTarget = require('httpsnippet-for-my-lang'); @@ -172,14 +179,14 @@ HTTPSnippet.addTarget(customLanguageTarget); *Required* Type: `string` -Name of [conversion target](https://github.com/Mashape/httpsnippet/wiki/Targets) +Name of [conversion target](TARGETS.md) ### client *Required* Type: `object` -Representation of a [conversion target client](https://github.com/Kong/httpsnippet/wiki/Creating-Targets). Can use this to use target clients that are not officially supported. +Representation of a [conversion target client](https://github.com/httptoolkit/httpsnippet/blob/main/CONTRIBUTING.md#creating-new-conversion-targets). Can use this to use target clients that are not officially supported. ```js const customClient = require('httpsnippet-for-my-node-http-client'); @@ -190,7 +197,7 @@ HTTPSnippet.addTargetClient('node', customClient); At the heart of this module is the [HAR Format](http://www.softwareishard.com/blog/har-12-spec/#request) as the HTTP request description format, please review some of the sample JSON HAR Request objects in [test fixtures](/test/fixtures/requests), or read the [HAR Docs](http://www.softwareishard.com/blog/har-12-spec/#request) for more details. -For detailed information on each target, please review the [wiki](https://github.com/Mashape/httpsnippet/wiki). +For detailed information on each target, please review the [target docs](./TARGETS.md). ## Bugs and feature requests @@ -200,7 +207,7 @@ Have a bug or a feature request? Please first read the [issue guidelines](CONTRI Please read through our [contributing guidelines](CONTRIBUTING.md). Included are directions for opening issues, coding standards, and notes on development. -For info on creating new conversion targets, please review this [guideline](https://github.com/Mashape/httpsnippet/wiki/Creating-Targets) +For info on creating new conversion targets, please review this [guideline](https://github.com/httptoolkit/httpsnippet/blob/main/CONTRIBUTING.md#creating-new-conversion-targets) Moreover, if your pull request contains JavaScript patches or features, you must include relevant unit tests. @@ -221,17 +228,3 @@ And constructed with the following guidelines: - Bug fixes and misc changes **bumps only the patch** For more information on SemVer, please visit . - -## License - -[MIT](LICENSE) © [Kong](https://konghq.com) - -[license-url]: https://github.com/Kong/httpsnippet/blob/master/LICENSE - -[travis-url]: https://travis-ci.org/Kong/httpsnippet -[travis-image]: https://api.travis-ci.org/Kong/httpsnippet.svg?branch=master - -[npm-url]: https://www.npmjs.com/package/httpsnippet -[npm-license]: https://img.shields.io/npm/l/httpsnippet.svg?style=flat-square -[npm-version]: https://img.shields.io/npm/v/httpsnippet.svg?style=flat-square -[npm-downloads]: https://img.shields.io/npm/dm/httpsnippet.svg?style=flat-square diff --git a/TARGETS.md b/TARGETS.md new file mode 100644 index 0000000..e855002 --- /dev/null +++ b/TARGETS.md @@ -0,0 +1,278 @@ +# Targets + +Currently the following output targets are supported: + +## Go + +### [Native](http://golang.org/pkg/net/http/#NewRequest) + +> Golang HTTP client request + +###### Options + +| Option | Default | Description | +| --------------- | ------- | ----------------------------------------------------- | +| `checkErrors` | `false` | add error checking for request, response and body | +| `printBody` | `true` | include code to print the body as a string | +| `timeout` | `-1` | sets a request timeout in seconds (requires go 1.3+) | + +---- + +## Java + +### [Unirest](http://unirest.io/java.html) + +> Lightweight HTTP Request Client Library + +###### Options + +| Option | Default | Description | +| --------- | ------- | -------------------------------- | +| `indent` | ` ` | line break & indent output value | + +### [OkHttp](http://square.github.io/okhttp/) + +> An HTTP Request Client Library + +###### Options + +| Option | Default | Description | +| --------- | ------- | -------------------------------- | +| `indent` | ` ` | line break & indent output value | + +### [RestClient](https://docs.spring.io/spring-framework/docs/current/javadoc-api/org/springframework/web/client/RestClient.html) + +> Spring Framework REST client + +###### Options + +| Option | Default | Description | +| ------------ | -------- | -------------------------------- | +| `indent` | ` ` | line break & indent output value | +| `entityType` | `String` | Java type for the entity | + +---- + +## JavaScript + +### [jQuery.ajax](http://api.jquery.com/jquery.ajax/) + +> Perform an asynchronous HTTP (Ajax) requests with jQuery + +###### Options + +| Option | Default | Description | +| --------- | ------- | -------------------------------- | +| `indent` | ` ` | line break & indent output value | + +### [XMLHttpRequest](https://developer.mozilla.org/en-US/docs/Web/API/XMLHttpRequest) + +> W3C Standard API that provides scripted client functionality + +###### Options + +| Option | Default | Description | +| --------- | ------- | -------------------------------- | +| `cors` | `true` | use `xhr.withCredentials = true` | +| `indent` | ` ` | line break & indent output value | + +###### Options + +---- + +## Node.js + +### [Native](http://nodejs.org/api/http.html#http_http_request_options_callback) + +> Node.js native HTTP interface + +###### Options + +| Option | Default | Description | +| --------- | ------- | -------------------------------- | +| `indent` | ` ` | line break & indent output value | + +### [Request](https://github.com/request/request) + +> Simplified HTTP request client + +###### Options + +| Option | Default | Description | +| --------- | ------- | -------------------------------- | +| `indent` | ` ` | line break & indent output value | + +### [Unirest](http://unirest.io/nodejs.html) + +> Lightweight HTTP Request Client Library + +###### Options + +| Option | Default | Description | +| --------- | ------- | -------------------------------- | +| `indent` | ` ` | line break & indent output value | + +---- + +## Objective-C + +### [NSURLSession](https://developer.apple.com/library/mac/documentation/Foundation/Reference/NSURLSession_class/index.html) + +> Foundation's NSURLSession request + +###### Options + +| Option | Default | Description | +| --------- | ------- | --------------------------------------------------------------- | +| `indent` | ` ` | line break & indent output value | +| `pretty` | `true` | indent extracted headers/parameters in `NSDictionary` literals | +| `timeout` | `10` | NSURLRequest timeout | + +---- + +## OCaml + +### [CoHTTP](https://github.com/mirage/ocaml-cohttp) + +> CoHTTP is a very lightweight HTTP server using Lwt or Async for OCaml + +###### Options + +| Option | Default | Description | +| --------- | ------- | -------------------------------- | +| `indent` | ` ` | line break & indent output value | + +---- + +## PHP + +### [ext-curl](http://php.net/manual/en/book.curl.php) + +> PHP with ext-curl + +###### Options + +| Option | Default | Description | +| --------------- | ------- | ----------------------------------------------- | +| `closingTag` | `false` | add a closing tag `?>` | +| `indent` | ` ` | line break & indent output value | +| `maxRedirects` | `10` | value for `CURLOPT_MAXREDIRS` | +| `namedErrors` | `false` | attempt to display curl error name instead of # | +| `noTags` | `false` | do NOT output start and end tags: `` | +| `shortTags` | `false` | use short opening tag: ` PHP with pecl/http v1 + +###### Options + +| Option | Default | Description | +| --------------- | ------- | ----------------------------------------------- | +| `closingTag` | `false` | add a closing tag `?>` | +| `indent` | ` ` | line break & indent output value | +| `noTags` | `false` | do NOT output start and end tags: `` | +| `shortTags` | `false` | use short opening tag: ` PHP with pecl/http v2 + +###### Options + +| Option | Default | Description | +| --------------- | ------- | ----------------------------------------------- | +| `closingTag` | `false` | add a closing tag `?>` | +| `indent` | ` ` | line break & indent output value | +| `noTags` | `false` | do NOT output start and end tags: `` | +| `shortTags` | `false` | use short opening tag: ` Python3 HTTP Client + +### [Requests](http://docs.python-requests.org/en/latest/api/#requests.request) + +Requests HTTP library + +---- + +## Ruby + +### [Native](http://ruby-doc.org/stdlib-2.2.1/libdoc/net/http/rdoc/Net/HTTP.html) + +> Ruby HTTP client + +---- + +## Shell + +### [cURL](http://curl.haxx.se/) + +> cURL is a command line tool and library for transferring data with URL syntax + +| Option | Default | Description | +| -------- | ------- | ------------------------------------------------------------------------ | +| `indent` | ` ` | line break & indent output value, set to `false` to disable line breaks | +| `short` | `false` | use short form of cURL CLI options | + +### [HTTPie](http://httpie.org) + +> a CLI, cURL-like tool for humans + +| Option | Default | Description | +| ------------- | ------- | --------------------------------------------------------------------------------------------------------------------------------------- | +| `body` | `false` | only the response body is printed | +| `cert` | `false` | use a client side certificate *(see [httpie docs](https://github.com/jakubroztocil/httpie#client-side-ssl-certificate))* | +| `headers` | `false` | only the response headers are printed | +| `indent` | ` ` | line break & indent output value, set to `false` to disable line breaks | +| `pretty` | `false` | syntax highlighting *(see [httpie docs](https://github.com/jakubroztocil/httpie#colors-and-formatting))* | +| `print` | `false` | selects parts of the HTTP exchange, e.g. `--print=Hh` *(see [httpie docs](https://github.com/jakubroztocil/httpie#output-options))* | +| `queryParams` | `false` | use query params as CLI parameters *otherwise, query string is added to URL* | +| `short` | `false` | use short form of cURL CLI options | +| `style` | `false` | syntax highlighting *(see [httpie docs](https://github.com/jakubroztocil/httpie#colors-and-formatting))* | +| `timeout` | `false` | overwrite the default *30s* timeout | +| `verbose` | `false` | print the whole HTTP exchange (request and response) | +| `verify` | `false` | server SSL certificate verification *(see [httpie docs](https://github.com/jakubroztocil/httpie#server-ssl-certificate-verification))* | + +### [Wget](https://www.gnu.org/software/wget/) + +> a free software package for retrieving files using HTTP, HTTPS + +| Option | Default | Description | +| --------- | ------- | ------------------------------------------------------------------------ | +| `indent` | ` ` | line break & indent output value, set to `false` to disable line breaks | +| `short` | `false` | use short form of cURL CLI options | +| `verbose` | `false` | by default, `--quiet` is always used, unless `verbose` is set to `true` | + +---- + +## Swift + +### [NSURLSession](https://developer.apple.com/library/mac/documentation/Foundation/Reference/NSURLSession_class/index.html) + +> Foundation's NSURLSession request + +| Option | Default | Description | +| --------- | ------- | --------------------------------------------------------------- | +| `indent` | ` ` | line break & indent output value | +| `pretty` | `true` | indent extracted headers/parameters in `NSDictionary` literals | +| `timeout` | `10` | NSURLRequest timeout | + + +## C# + +### [RestSharp](http://restsharp.org/) + +> Simple REST and HTTP API Client for .NET + +## C + +### [LibCurl](http://curl.haxx.se/libcurl/) + +> A easy-to-use client-side URL transfer library diff --git a/bin/httpsnippet b/bin/httpsnippet index 3747f66..49410f8 100755 --- a/bin/httpsnippet +++ b/bin/httpsnippet @@ -17,12 +17,23 @@ cmd .option('-t, --target ', 'target output') .option('-c, --client [client]', 'target client library') .option('-o, --output ', 'write output to directory') + .option('-x, --extra [{"optionKey": "optionValue"}]', 'provide extra options for the target/client') .parse(process.argv) if (!cmd.args.length || !cmd.target) { cmd.help() } +let extraOptions +if (cmd.extra) { + try { + extraOptions = JSON.parse(cmd.extra) + } catch (e) { + console.error('%s failed to parse options %s (should be JSON)', chalk.red('✖'), chalk.cyan.bold(cmd.extra)) + process.exit() + } +} + let dir if (cmd.output) { dir = path.resolve(cmd.output) @@ -53,7 +64,7 @@ cmd.args.forEach(function (fileName) { }) .then(function (snippet) { - return snippet.convert(cmd.target, cmd.client) + return snippet.convert(cmd.target, cmd.client, extraOptions) }) .then(function (output) { diff --git a/package-lock.json b/package-lock.json index 66cd5cc..69e2307 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,8 +1,4664 @@ { - "name": "httpsnippet", - "version": "1.25.0", - "lockfileVersion": 1, + "name": "@httptoolkit/httpsnippet", + "version": "3.0.2", + "lockfileVersion": 2, "requires": true, + "packages": { + "": { + "name": "@httptoolkit/httpsnippet", + "version": "3.0.2", + "license": "MIT", + "dependencies": { + "chalk": "^1.1.1", + "commander": "^2.9.0", + "debug": "^2.2.0", + "event-stream": "3.3.4", + "form-data": "3.0.4", + "fs-readfile-promise": "^2.0.1", + "fs-writefile-promise": "^1.0.3", + "har-validator": "^5.0.0" + }, + "bin": { + "httpsnippet": "bin/httpsnippet" + }, + "devDependencies": { + "echint": "^4.0.2", + "glob": "^6.0.1", + "istanbul": "^0.4.0", + "mocha": "^11.7.5", + "require-directory": "^2.1.1", + "should": "^13.2.3", + "standard": "^16.0.3" + }, + "engines": { + "node": ">=22" + } + }, + "node_modules/@babel/code-frame": { + "version": "7.12.11", + "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.12.11.tgz", + "integrity": "sha512-Zt1yodBx1UcyiePMSkWnU4hPqhwq7hGi2nFL1LeA3EUl+q2LQx16MISgJ0+z7dnmgvP9QtIleuETGOiOH1RcIw==", + "dev": true, + "dependencies": { + "@babel/highlight": "^7.10.4" + } + }, + "node_modules/@babel/helper-validator-identifier": { + "version": "7.12.11", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.12.11.tgz", + "integrity": "sha512-np/lG3uARFybkoHokJUmf1QfEvRVCPbmQeUQpKow5cQ3xWrV9i3rUHodKDJPQfTVX61qKi+UdYk8kik84n7XOw==", + "dev": true + }, + "node_modules/@babel/highlight": { + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.10.4.tgz", + "integrity": "sha512-i6rgnR/YgPEQzZZnbTHHuZdlE8qyoBNalD6F+q4vAFlcMEcqmkoG+mPqJYJCo63qPf74+Y1UZsl3l6f7/RIkmA==", + "dev": true, + "dependencies": { + "@babel/helper-validator-identifier": "^7.10.4", + "chalk": "^2.0.0", + "js-tokens": "^4.0.0" + } + }, + "node_modules/@babel/highlight/node_modules/ansi-styles": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", + "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", + "dev": true, + "dependencies": { + "color-convert": "^1.9.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/@babel/highlight/node_modules/chalk": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", + "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", + "dev": true, + "dependencies": { + "ansi-styles": "^3.2.1", + "escape-string-regexp": "^1.0.5", + "supports-color": "^5.3.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/@babel/highlight/node_modules/has-flag": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", + "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/@babel/highlight/node_modules/supports-color": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", + "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "dev": true, + "dependencies": { + "has-flag": "^3.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/@eslint/eslintrc": { + "version": "0.2.2", + "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-0.2.2.tgz", + "integrity": "sha512-EfB5OHNYp1F4px/LI/FEnGylop7nOqkQ1LRzCM0KccA2U8tvV8w01KBv37LbO7nW4H+YhKyo2LcJhRwjjV17QQ==", + "dev": true, + "dependencies": { + "ajv": "^6.12.4", + "debug": "^4.1.1", + "espree": "^7.3.0", + "globals": "^12.1.0", + "ignore": "^4.0.6", + "import-fresh": "^3.2.1", + "js-yaml": "^3.13.1", + "lodash": "^4.17.19", + "minimatch": "^3.0.4", + "strip-json-comments": "^3.1.1" + }, + "engines": { + "node": "^10.12.0 || >=12.0.0" + } + }, + "node_modules/@eslint/eslintrc/node_modules/debug": { + "version": "4.3.1", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.1.tgz", + "integrity": "sha512-doEwdvm4PCeK4K3RQN2ZC2BYUBaxwLARCqZmMjtF8a51J2Rb0xpVloFRnCODwqjpwnAoao4pelN8l3RJdv3gRQ==", + "dev": true, + "dependencies": { + "ms": "2.1.2" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/@eslint/eslintrc/node_modules/ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", + "dev": true + }, + "node_modules/@eslint/eslintrc/node_modules/strip-json-comments": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz", + "integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==", + "dev": true, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/@isaacs/cliui": { + "version": "8.0.2", + "resolved": "https://registry.npmjs.org/@isaacs/cliui/-/cliui-8.0.2.tgz", + "integrity": "sha512-O8jcjabXaleOG9DQ0+ARXWZBTfnP4WNAqzuiJK7ll44AmxGKv/J2M4TPjxjY3znBCfvBXFzucm1twdyFybFqEA==", + "dev": true, + "dependencies": { + "string-width": "^5.1.2", + "string-width-cjs": "npm:string-width@^4.2.0", + "strip-ansi": "^7.0.1", + "strip-ansi-cjs": "npm:strip-ansi@^6.0.1", + "wrap-ansi": "^8.1.0", + "wrap-ansi-cjs": "npm:wrap-ansi@^7.0.0" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/@isaacs/cliui/node_modules/ansi-regex": { + "version": "6.2.2", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.2.2.tgz", + "integrity": "sha512-Bq3SmSpyFHaWjPk8If9yc6svM8c56dB5BAtW4Qbw5jHTwwXXcTLoRMkpDJp6VL0XzlWaCHTXrkFURMYmD0sLqg==", + "dev": true, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/ansi-regex?sponsor=1" + } + }, + "node_modules/@isaacs/cliui/node_modules/ansi-styles": { + "version": "6.2.3", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-6.2.3.tgz", + "integrity": "sha512-4Dj6M28JB+oAH8kFkTLUo+a2jwOFkuqb3yucU0CANcRRUbxS0cP0nZYCGjcc3BNXwRIsUVmDGgzawme7zvJHvg==", + "dev": true, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/@isaacs/cliui/node_modules/emoji-regex": { + "version": "9.2.2", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-9.2.2.tgz", + "integrity": "sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==", + "dev": true + }, + "node_modules/@isaacs/cliui/node_modules/string-width": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-5.1.2.tgz", + "integrity": "sha512-HnLOCR3vjcY8beoNLtcjZ5/nxn2afmME6lhrDrebokqMap+XbeW8n9TXpPDOqdGK5qcI3oT0GKTW6wC7EMiVqA==", + "dev": true, + "dependencies": { + "eastasianwidth": "^0.2.0", + "emoji-regex": "^9.2.2", + "strip-ansi": "^7.0.1" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/@isaacs/cliui/node_modules/strip-ansi": { + "version": "7.1.2", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.1.2.tgz", + "integrity": "sha512-gmBGslpoQJtgnMAvOVqGZpEz9dyoKTCzy2nfz/n8aIFhN/jCE/rCmcxabB6jOOHV+0WNnylOxaxBQPSvcWklhA==", + "dev": true, + "dependencies": { + "ansi-regex": "^6.0.1" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/strip-ansi?sponsor=1" + } + }, + "node_modules/@isaacs/cliui/node_modules/wrap-ansi": { + "version": "8.1.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-8.1.0.tgz", + "integrity": "sha512-si7QWI6zUMq56bESFvagtmzMdGOtoxfR+Sez11Mobfc7tm+VkUckk9bW2UeffTGVUbOksxmSw0AA2gs8g71NCQ==", + "dev": true, + "dependencies": { + "ansi-styles": "^6.1.0", + "string-width": "^5.0.1", + "strip-ansi": "^7.0.1" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/wrap-ansi?sponsor=1" + } + }, + "node_modules/@pkgjs/parseargs": { + "version": "0.11.0", + "resolved": "https://registry.npmjs.org/@pkgjs/parseargs/-/parseargs-0.11.0.tgz", + "integrity": "sha512-+1VkjdD0QBLPodGrJUeqarH8VAIvQODIbwh9XpP5Syisf7YoQgsJKPNFoqqLQlu+VQ/tVSshMR6loPMn8U+dPg==", + "dev": true, + "optional": true, + "engines": { + "node": ">=14" + } + }, + "node_modules/@types/json5": { + "version": "0.0.29", + "resolved": "https://registry.npmjs.org/@types/json5/-/json5-0.0.29.tgz", + "integrity": "sha1-7ihweulOEdK4J7y+UnC86n8+ce4=", + "dev": true + }, + "node_modules/abbrev": { + "version": "1.0.9", + "resolved": "https://registry.npmjs.org/abbrev/-/abbrev-1.0.9.tgz", + "integrity": "sha1-kbR5JYinc4wl813W9jdSovh3YTU=", + "dev": true + }, + "node_modules/acorn": { + "version": "7.4.1", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-7.4.1.tgz", + "integrity": "sha512-nQyp0o1/mNdbTO1PO6kHkwSrmgZ0MT/jCCpNiwbUjGoRN4dlBhqJtoQuCnEOKzgTVwg0ZWiCoQy6SxMebQVh8A==", + "dev": true, + "bin": { + "acorn": "bin/acorn" + }, + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/acorn-jsx": { + "version": "5.3.1", + "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.3.1.tgz", + "integrity": "sha512-K0Ptm/47OKfQRpNQ2J/oIN/3QYiK6FwW+eJbILhsdxh2WTLdl+30o8aGdTbm5JbffpFFAg/g+zi1E+jvJha5ng==", + "dev": true, + "peerDependencies": { + "acorn": "^6.0.0 || ^7.0.0 || ^8.0.0" + } + }, + "node_modules/ajv": { + "version": "6.12.6", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", + "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", + "dependencies": { + "fast-deep-equal": "^3.1.1", + "fast-json-stable-stringify": "^2.0.0", + "json-schema-traverse": "^0.4.1", + "uri-js": "^4.2.2" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/epoberezkin" + } + }, + "node_modules/amdefine": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/amdefine/-/amdefine-1.0.1.tgz", + "integrity": "sha1-SlKCrBZHKek2Gbz9OtFR+BfOkfU=", + "dev": true, + "optional": true, + "engines": { + "node": ">=0.4.2" + } + }, + "node_modules/ansi-colors": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/ansi-colors/-/ansi-colors-4.1.1.tgz", + "integrity": "sha512-JoX0apGbHaUJBNl6yF+p6JAFYZ666/hhCGKN5t9QFjbJQKUU/g8MNbFDbvfrgKXvI1QpZplPOnwIo99lX/AAmA==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/ansi-regex": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", + "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/ansi-styles": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-2.2.1.tgz", + "integrity": "sha1-tDLdM1i2NM914eRmQ2gkBTPB3b4=", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/argparse": { + "version": "1.0.10", + "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz", + "integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==", + "dev": true, + "dependencies": { + "sprintf-js": "~1.0.2" + } + }, + "node_modules/array-includes": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/array-includes/-/array-includes-3.1.2.tgz", + "integrity": "sha512-w2GspexNQpx+PutG3QpT437/BenZBj0M/MZGn5mzv/MofYqo0xmRHzn4lFsoDlWJ+THYsGJmFlW68WlDFx7VRw==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.0", + "define-properties": "^1.1.3", + "es-abstract": "^1.18.0-next.1", + "get-intrinsic": "^1.0.1", + "is-string": "^1.0.5" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/array.prototype.flat": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/array.prototype.flat/-/array.prototype.flat-1.2.4.tgz", + "integrity": "sha512-4470Xi3GAPAjZqFcljX2xzckv1qeKPizoNkiS0+O4IoPR2ZNpcjE0pkhdihlDouK+x6QOast26B4Q/O9DJnwSg==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.0", + "define-properties": "^1.1.3", + "es-abstract": "^1.18.0-next.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/array.prototype.flatmap": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/array.prototype.flatmap/-/array.prototype.flatmap-1.2.4.tgz", + "integrity": "sha512-r9Z0zYoxqHz60vvQbWEdXIEtCwHF0yxaWfno9qzXeNHvfyl3BZqygmGzb84dsubyaXLH4husF+NFgMSdpZhk2Q==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.0", + "define-properties": "^1.1.3", + "es-abstract": "^1.18.0-next.1", + "function-bind": "^1.1.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/astral-regex": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/astral-regex/-/astral-regex-1.0.0.tgz", + "integrity": "sha512-+Ryf6g3BKoRc7jfp7ad8tM4TtMiaWvbF/1/sQcZPkkS7ag3D5nMBCe2UfOTONtAkaG0tO0ij3C5Lwmf1EiyjHg==", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/asynckit": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", + "integrity": "sha1-x57Zf380y48robyXkLzDZkdLS3k=" + }, + "node_modules/balanced-match": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.0.tgz", + "integrity": "sha1-ibTRmasr7kneFk6gK4nORi1xt2c=", + "dev": true + }, + "node_modules/brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "dev": true, + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "node_modules/browser-stdout": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/browser-stdout/-/browser-stdout-1.3.1.tgz", + "integrity": "sha512-qhAVI1+Av2X7qelOfAIYwXONood6XlZE/fXaBSmW/T5SzLAmCgzi+eiWE7fUvbHaeNBQH13UftjpXxsfLkMpgw==", + "dev": true + }, + "node_modules/call-bind": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.2.tgz", + "integrity": "sha512-7O+FbCihrB5WGbFYesctwmTKae6rOiIzmz1icreWJ+0aA7LJfuqhEso2T9ncpcFtzMQtzXf2QGGueWJGTYsqrA==", + "dev": true, + "dependencies": { + "function-bind": "^1.1.1", + "get-intrinsic": "^1.0.2" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/call-bind-apply-helpers": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/call-bind-apply-helpers/-/call-bind-apply-helpers-1.0.2.tgz", + "integrity": "sha512-Sp1ablJ0ivDkSzjcaJdxEunN5/XvksFJ2sMBFfq6x0ryhQV/2b/KwFe21cMpmHtPOSij8K99/wSfoEuTObmuMQ==", + "dependencies": { + "es-errors": "^1.3.0", + "function-bind": "^1.1.2" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/callsites": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz", + "integrity": "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/chalk": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz", + "integrity": "sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg=", + "dependencies": { + "ansi-styles": "^2.2.1", + "escape-string-regexp": "^1.0.2", + "has-ansi": "^2.0.0", + "strip-ansi": "^3.0.0", + "supports-color": "^2.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/chokidar": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-4.0.3.tgz", + "integrity": "sha512-Qgzu8kfBvo+cA4962jnP1KkS6Dop5NS6g7R5LFYJr4b8Ub94PPQXUksCw9PvXoeXPRRddRNC5C1JQUR2SMGtnA==", + "dev": true, + "dependencies": { + "readdirp": "^4.0.1" + }, + "engines": { + "node": ">= 14.16.0" + }, + "funding": { + "url": "https://paulmillr.com/funding/" + } + }, + "node_modules/cliui": { + "version": "8.0.1", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-8.0.1.tgz", + "integrity": "sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ==", + "dev": true, + "dependencies": { + "string-width": "^4.2.0", + "strip-ansi": "^6.0.1", + "wrap-ansi": "^7.0.0" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/cliui/node_modules/ansi-regex": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/cliui/node_modules/strip-ansi": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "dev": true, + "dependencies": { + "ansi-regex": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/color-convert": { + "version": "1.9.3", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", + "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", + "dev": true, + "dependencies": { + "color-name": "1.1.3" + } + }, + "node_modules/color-name": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", + "integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=", + "dev": true + }, + "node_modules/commander": { + "version": "2.20.0", + "resolved": "https://registry.npmjs.org/commander/-/commander-2.20.0.tgz", + "integrity": "sha512-7j2y+40w61zy6YC2iRNpUe/NwhNyoXrYpHMrSunaMG64nRnaf96zO/KMQR4OyN/UnE5KLyEBnKHd4aG3rskjpQ==" + }, + "node_modules/concat-map": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", + "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=", + "dev": true + }, + "node_modules/contains-path": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/contains-path/-/contains-path-0.1.0.tgz", + "integrity": "sha1-/ozxhP9mcLa67wGp1IYaXL7EEgo=", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/cross-spawn": { + "version": "7.0.6", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.6.tgz", + "integrity": "sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA==", + "dev": true, + "dependencies": { + "path-key": "^3.1.0", + "shebang-command": "^2.0.0", + "which": "^2.0.1" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/cross-spawn/node_modules/which": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", + "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", + "dev": true, + "dependencies": { + "isexe": "^2.0.0" + }, + "bin": { + "node-which": "bin/node-which" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha1-XRKFFd8TT/Mn6QpMk/Tgd6U2NB8=", + "dependencies": { + "ms": "2.0.0" + } + }, + "node_modules/debug-log": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/debug-log/-/debug-log-1.0.1.tgz", + "integrity": "sha1-IwdjLUwEOCuN+KMvcLiVBG1SdF8=", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/deep-extend": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/deep-extend/-/deep-extend-0.6.0.tgz", + "integrity": "sha512-LOHxIOaPYdHlJRtCQfDIVZtfw/ufM8+rVj649RIHzcm/vGwQRXFt6OPqIFWsm2XEMrNIEtWR64sY1LEKD2vAOA==", + "dev": true, + "engines": { + "node": ">=4.0.0" + } + }, + "node_modules/deep-is": { + "version": "0.1.3", + "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.3.tgz", + "integrity": "sha1-s2nW+128E+7PUk+RsHD+7cNXzzQ=", + "dev": true + }, + "node_modules/define-properties": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.1.3.tgz", + "integrity": "sha512-3MqfYKj2lLzdMSf8ZIZE/V+Zuy+BgD6f164e8K2w7dgnpKArBDerGYpM46IYYcjnkdPNMjPk9A6VFB8+3SKlXQ==", + "dev": true, + "dependencies": { + "object-keys": "^1.0.12" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/delayed-stream": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", + "integrity": "sha1-3zrhmayt+31ECqrgsp4icrJOxhk=", + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/diff": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/diff/-/diff-7.0.0.tgz", + "integrity": "sha512-PJWHUb1RFevKCwaFA9RlG5tCd+FO5iRh9A8HEtkmBH2Li03iJriB6m6JIN4rGz3K3JLawI7/veA1xzRKP6ISBw==", + "dev": true, + "engines": { + "node": ">=0.3.1" + } + }, + "node_modules/doctrine": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-3.0.0.tgz", + "integrity": "sha512-yS+Q5i3hBf7GBkd4KG8a7eBNNWNGLTaEwwYWUijIYM7zrlYDM0BFXHjjPWlWZ1Rg7UaddZeIDmi9jF3HmqiQ2w==", + "dev": true, + "dependencies": { + "esutils": "^2.0.2" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/dotenv": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-7.0.0.tgz", + "integrity": "sha512-M3NhsLbV1i6HuGzBUH8vXrtxOk+tWmzWKDMbAVSUp3Zsjm7ywFeuwrUXhmhQyRK1q5B5GGy7hcXPbj3bnfZg2g==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/dunder-proto": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/dunder-proto/-/dunder-proto-1.0.1.tgz", + "integrity": "sha512-KIN/nDJBQRcXw0MLVhZE9iQHmG68qAVIBg9CqmUYjmQIhgij9U5MFvrqkUL5FbtyyzZuOeOt0zdeRe4UY7ct+A==", + "dependencies": { + "call-bind-apply-helpers": "^1.0.1", + "es-errors": "^1.3.0", + "gopd": "^1.2.0" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/duplexer": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/duplexer/-/duplexer-0.1.1.tgz", + "integrity": "sha1-rOb/gIwc5mtX0ev5eXessCM0z8E=" + }, + "node_modules/eastasianwidth": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/eastasianwidth/-/eastasianwidth-0.2.0.tgz", + "integrity": "sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA==", + "dev": true + }, + "node_modules/echint": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/echint/-/echint-4.0.2.tgz", + "integrity": "sha512-iUEHrTxUqpZ0V6ayTmjyf9/f3Iz/Pp3EGKhmfFpnZQ4tjTk3ZyO9bO2qGwgr3coSknzXdieYrcCe3JDsiI/Uvw==", + "deprecated": "no longer maintained", + "dev": true, + "dependencies": { + "chalk": "^2.4.2", + "commander": "^2.19.0", + "dotenv": "^7.0.0", + "glob": "^7.1.3", + "lintspaces": "0.6.3", + "minimatch": "^3.0.4", + "pkg-config": "^1.1.1" + }, + "bin": { + "echint": "lib/bin.js" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/echint/node_modules/ansi-styles": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", + "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", + "dev": true, + "dependencies": { + "color-convert": "^1.9.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/echint/node_modules/chalk": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", + "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", + "dev": true, + "dependencies": { + "ansi-styles": "^3.2.1", + "escape-string-regexp": "^1.0.5", + "supports-color": "^5.3.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/echint/node_modules/glob": { + "version": "7.1.3", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.3.tgz", + "integrity": "sha1-OWCDLT8VdBCDQtr9OmezMsCWnfE=", + "dev": true, + "dependencies": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.0.4", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + }, + "engines": { + "node": "*" + } + }, + "node_modules/echint/node_modules/has-flag": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", + "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/echint/node_modules/supports-color": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", + "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "dev": true, + "dependencies": { + "has-flag": "^3.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/editorconfig": { + "version": "0.15.3", + "resolved": "https://registry.npmjs.org/editorconfig/-/editorconfig-0.15.3.tgz", + "integrity": "sha512-M9wIMFx96vq0R4F+gRpY3o2exzb8hEj/n9S8unZtHSvYjibBp/iMufSzvmOcV/laG0ZtuTVGtiJggPOSW2r93g==", + "dev": true, + "dependencies": { + "commander": "^2.19.0", + "lru-cache": "^4.1.5", + "semver": "^5.6.0", + "sigmund": "^1.0.1" + }, + "bin": { + "editorconfig": "bin/editorconfig" + } + }, + "node_modules/editorconfig/node_modules/semver": { + "version": "5.7.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.0.tgz", + "integrity": "sha512-Ya52jSX2u7QKghxeoFGpLwCtGlt7j0oY9DYb5apt9nPlJ42ID+ulTXESnt/qAQcoSERyZ5sl3LDIOw0nAn/5DA==", + "dev": true, + "bin": { + "semver": "bin/semver" + } + }, + "node_modules/emoji-regex": { + "version": "7.0.3", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-7.0.3.tgz", + "integrity": "sha512-CwBLREIQ7LvYFB0WyRvwhq5N5qPhc6PMjD6bYggFlI5YyDgl+0vxq5VHbMOFqLg7hfWzmu8T5Z1QofhmTIhItA==", + "dev": true + }, + "node_modules/enquirer": { + "version": "2.3.6", + "resolved": "https://registry.npmjs.org/enquirer/-/enquirer-2.3.6.tgz", + "integrity": "sha512-yjNnPr315/FjS4zIsUxYguYUPP2e1NK4d7E7ZOLiyYCcbFBiTMyID+2wvm2w6+pZ/odMA7cRkjhsPbltwBOrLg==", + "dev": true, + "dependencies": { + "ansi-colors": "^4.1.1" + }, + "engines": { + "node": ">=8.6" + } + }, + "node_modules/error-ex": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/error-ex/-/error-ex-1.3.2.tgz", + "integrity": "sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g==", + "dev": true, + "dependencies": { + "is-arrayish": "^0.2.1" + } + }, + "node_modules/es-abstract": { + "version": "1.18.0-next.2", + "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.18.0-next.2.tgz", + "integrity": "sha512-Ih4ZMFHEtZupnUh6497zEL4y2+w8+1ljnCyaTa+adcoafI1GOvMwFlDjBLfWR7y9VLfrjRJe9ocuHY1PSR9jjw==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2", + "es-to-primitive": "^1.2.1", + "function-bind": "^1.1.1", + "get-intrinsic": "^1.0.2", + "has": "^1.0.3", + "has-symbols": "^1.0.1", + "is-callable": "^1.2.2", + "is-negative-zero": "^2.0.1", + "is-regex": "^1.1.1", + "object-inspect": "^1.9.0", + "object-keys": "^1.1.1", + "object.assign": "^4.1.2", + "string.prototype.trimend": "^1.0.3", + "string.prototype.trimstart": "^1.0.3" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/es-abstract/node_modules/object-inspect": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.9.0.tgz", + "integrity": "sha512-i3Bp9iTqwhaLZBxGkRfo5ZbE07BQRT7MGu8+nNgwW9ItGp1TzCTw2DLEoWwjClxBjOFI/hWljTAmYGCEwmtnOw==", + "dev": true, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/es-abstract/node_modules/object.assign": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/object.assign/-/object.assign-4.1.2.tgz", + "integrity": "sha512-ixT2L5THXsApyiUPYKmW+2EHpXXe5Ii3M+f4e+aJFAHao5amFRW6J0OO6c/LU8Be47utCx2GL89hxGB6XSmKuQ==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.0", + "define-properties": "^1.1.3", + "has-symbols": "^1.0.1", + "object-keys": "^1.1.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/es-abstract/node_modules/string.prototype.trimend": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/string.prototype.trimend/-/string.prototype.trimend-1.0.3.tgz", + "integrity": "sha512-ayH0pB+uf0U28CtjlLvL7NaohvR1amUvVZk+y3DYb0Ey2PUV5zPkkKy9+U1ndVEIXO8hNg18eIv9Jntbii+dKw==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.0", + "define-properties": "^1.1.3" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/es-abstract/node_modules/string.prototype.trimstart": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/string.prototype.trimstart/-/string.prototype.trimstart-1.0.3.tgz", + "integrity": "sha512-oBIBUy5lea5tt0ovtOFiEQaBkoBBkyJhZXzJYrSmDo5IUUqbOPvVezuRs/agBIdZ2p2Eo1FD6bD9USyBLfl3xg==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.0", + "define-properties": "^1.1.3" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/es-define-property": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/es-define-property/-/es-define-property-1.0.1.tgz", + "integrity": "sha512-e3nRfgfUZ4rNGL232gUgX06QNyyez04KdjFrF+LTRoOXmrOgFKDg4BCdsjW8EnT69eqdYGmRpJwiPVYNrCaW3g==", + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/es-errors": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/es-errors/-/es-errors-1.3.0.tgz", + "integrity": "sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==", + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/es-object-atoms": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/es-object-atoms/-/es-object-atoms-1.1.1.tgz", + "integrity": "sha512-FGgH2h8zKNim9ljj7dankFPcICIK9Cp5bm+c2gQSYePhpaG5+esrLODihIorn+Pe6FGJzWhXQotPv73jTaldXA==", + "dependencies": { + "es-errors": "^1.3.0" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/es-set-tostringtag": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/es-set-tostringtag/-/es-set-tostringtag-2.1.0.tgz", + "integrity": "sha512-j6vWzfrGVfyXxge+O0x5sh6cvxAog0a/4Rdd2K36zCMV5eJ+/+tOAngRO8cODMNWbVRdVlmGZQL2YS3yR8bIUA==", + "dependencies": { + "es-errors": "^1.3.0", + "get-intrinsic": "^1.2.6", + "has-tostringtag": "^1.0.2", + "hasown": "^2.0.2" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/es-to-primitive": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/es-to-primitive/-/es-to-primitive-1.2.1.tgz", + "integrity": "sha512-QCOllgZJtaUo9miYBcLChTUaHNjJF3PYs1VidD7AwiEj1kYxKeQTctLAezAOH5ZKRH0g2IgPn6KwB4IT8iRpvA==", + "dev": true, + "dependencies": { + "is-callable": "^1.1.4", + "is-date-object": "^1.0.1", + "is-symbol": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/escalade": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.2.0.tgz", + "integrity": "sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/escape-string-regexp": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", + "integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=", + "engines": { + "node": ">=0.8.0" + } + }, + "node_modules/escodegen": { + "version": "1.8.1", + "resolved": "https://registry.npmjs.org/escodegen/-/escodegen-1.8.1.tgz", + "integrity": "sha1-WltTr0aTEQvrsIZ6o0MN07cKEBg=", + "dev": true, + "dependencies": { + "esprima": "^2.7.1", + "estraverse": "^1.9.1", + "esutils": "^2.0.2", + "optionator": "^0.8.1" + }, + "bin": { + "escodegen": "bin/escodegen.js", + "esgenerate": "bin/esgenerate.js" + }, + "engines": { + "node": ">=0.12.0" + }, + "optionalDependencies": { + "source-map": "~0.2.0" + } + }, + "node_modules/eslint": { + "version": "7.13.0", + "resolved": "https://registry.npmjs.org/eslint/-/eslint-7.13.0.tgz", + "integrity": "sha512-uCORMuOO8tUzJmsdRtrvcGq5qposf7Rw0LwkTJkoDbOycVQtQjmnhZSuLQnozLE4TmAzlMVV45eCHmQ1OpDKUQ==", + "dev": true, + "dependencies": { + "@babel/code-frame": "^7.0.0", + "@eslint/eslintrc": "^0.2.1", + "ajv": "^6.10.0", + "chalk": "^4.0.0", + "cross-spawn": "^7.0.2", + "debug": "^4.0.1", + "doctrine": "^3.0.0", + "enquirer": "^2.3.5", + "eslint-scope": "^5.1.1", + "eslint-utils": "^2.1.0", + "eslint-visitor-keys": "^2.0.0", + "espree": "^7.3.0", + "esquery": "^1.2.0", + "esutils": "^2.0.2", + "file-entry-cache": "^5.0.1", + "functional-red-black-tree": "^1.0.1", + "glob-parent": "^5.0.0", + "globals": "^12.1.0", + "ignore": "^4.0.6", + "import-fresh": "^3.0.0", + "imurmurhash": "^0.1.4", + "is-glob": "^4.0.0", + "js-yaml": "^3.13.1", + "json-stable-stringify-without-jsonify": "^1.0.1", + "levn": "^0.4.1", + "lodash": "^4.17.19", + "minimatch": "^3.0.4", + "natural-compare": "^1.4.0", + "optionator": "^0.9.1", + "progress": "^2.0.0", + "regexpp": "^3.1.0", + "semver": "^7.2.1", + "strip-ansi": "^6.0.0", + "strip-json-comments": "^3.1.0", + "table": "^5.2.3", + "text-table": "^0.2.0", + "v8-compile-cache": "^2.0.3" + }, + "bin": { + "eslint": "bin/eslint.js" + }, + "engines": { + "node": "^10.12.0 || >=12.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/eslint-config-standard": { + "version": "16.0.2", + "resolved": "https://registry.npmjs.org/eslint-config-standard/-/eslint-config-standard-16.0.2.tgz", + "integrity": "sha512-fx3f1rJDsl9bY7qzyX8SAtP8GBSk6MfXFaTfaGgk12aAYW4gJSyRm7dM790L6cbXv63fvjY4XeSzXnb4WM+SKw==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "peerDependencies": { + "eslint": "^7.12.1", + "eslint-plugin-import": "^2.22.1", + "eslint-plugin-node": "^11.1.0", + "eslint-plugin-promise": "^4.2.1" + } + }, + "node_modules/eslint-config-standard-jsx": { + "version": "10.0.0", + "resolved": "https://registry.npmjs.org/eslint-config-standard-jsx/-/eslint-config-standard-jsx-10.0.0.tgz", + "integrity": "sha512-hLeA2f5e06W1xyr/93/QJulN/rLbUVUmqTlexv9PRKHFwEC9ffJcH2LvJhMoEqYQBEYafedgGZXH2W8NUpt5lA==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "peerDependencies": { + "eslint": "^7.12.1", + "eslint-plugin-react": "^7.21.5" + } + }, + "node_modules/eslint-import-resolver-node": { + "version": "0.3.4", + "resolved": "https://registry.npmjs.org/eslint-import-resolver-node/-/eslint-import-resolver-node-0.3.4.tgz", + "integrity": "sha512-ogtf+5AB/O+nM6DIeBUNr2fuT7ot9Qg/1harBfBtaP13ekEWFQEEMP94BCB7zaNW3gyY+8SHYF00rnqYwXKWOA==", + "dev": true, + "dependencies": { + "debug": "^2.6.9", + "resolve": "^1.13.1" + } + }, + "node_modules/eslint-import-resolver-node/node_modules/resolve": { + "version": "1.19.0", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.19.0.tgz", + "integrity": "sha512-rArEXAgsBG4UgRGcynxWIWKFvh/XZCcS8UJdHhwy91zwAvCZIbcs+vAbflgBnNjYMs/i/i+/Ux6IZhML1yPvxg==", + "dev": true, + "dependencies": { + "is-core-module": "^2.1.0", + "path-parse": "^1.0.6" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/eslint-module-utils": { + "version": "2.6.0", + "resolved": "https://registry.npmjs.org/eslint-module-utils/-/eslint-module-utils-2.6.0.tgz", + "integrity": "sha512-6j9xxegbqe8/kZY8cYpcp0xhbK0EgJlg3g9mib3/miLaExuuwc3n5UEfSnU6hWMbT0FAYVvDbL9RrRgpUeQIvA==", + "dev": true, + "dependencies": { + "debug": "^2.6.9", + "pkg-dir": "^2.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/eslint-plugin-es": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/eslint-plugin-es/-/eslint-plugin-es-3.0.1.tgz", + "integrity": "sha512-GUmAsJaN4Fc7Gbtl8uOBlayo2DqhwWvEzykMHSCZHU3XdJ+NSzzZcVhXh3VxX5icqQ+oQdIEawXX8xkR3mIFmQ==", + "dev": true, + "dependencies": { + "eslint-utils": "^2.0.0", + "regexpp": "^3.0.0" + }, + "engines": { + "node": ">=8.10.0" + }, + "funding": { + "url": "https://github.com/sponsors/mysticatea" + }, + "peerDependencies": { + "eslint": ">=4.19.1" + } + }, + "node_modules/eslint-plugin-import": { + "version": "2.22.1", + "resolved": "https://registry.npmjs.org/eslint-plugin-import/-/eslint-plugin-import-2.22.1.tgz", + "integrity": "sha512-8K7JjINHOpH64ozkAhpT3sd+FswIZTfMZTjdx052pnWrgRCVfp8op9tbjpAk3DdUeI/Ba4C8OjdC0r90erHEOw==", + "dev": true, + "dependencies": { + "array-includes": "^3.1.1", + "array.prototype.flat": "^1.2.3", + "contains-path": "^0.1.0", + "debug": "^2.6.9", + "doctrine": "1.5.0", + "eslint-import-resolver-node": "^0.3.4", + "eslint-module-utils": "^2.6.0", + "has": "^1.0.3", + "minimatch": "^3.0.4", + "object.values": "^1.1.1", + "read-pkg-up": "^2.0.0", + "resolve": "^1.17.0", + "tsconfig-paths": "^3.9.0" + }, + "engines": { + "node": ">=4" + }, + "peerDependencies": { + "eslint": "^2 || ^3 || ^4 || ^5 || ^6 || ^7.2.0" + } + }, + "node_modules/eslint-plugin-import/node_modules/doctrine": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-1.5.0.tgz", + "integrity": "sha1-N53Ocw9hZvds76TmcHoVmwLFpvo=", + "dev": true, + "dependencies": { + "esutils": "^2.0.2", + "isarray": "^1.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/eslint-plugin-import/node_modules/resolve": { + "version": "1.19.0", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.19.0.tgz", + "integrity": "sha512-rArEXAgsBG4UgRGcynxWIWKFvh/XZCcS8UJdHhwy91zwAvCZIbcs+vAbflgBnNjYMs/i/i+/Ux6IZhML1yPvxg==", + "dev": true, + "dependencies": { + "is-core-module": "^2.1.0", + "path-parse": "^1.0.6" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/eslint-plugin-node": { + "version": "11.1.0", + "resolved": "https://registry.npmjs.org/eslint-plugin-node/-/eslint-plugin-node-11.1.0.tgz", + "integrity": "sha512-oUwtPJ1W0SKD0Tr+wqu92c5xuCeQqB3hSCHasn/ZgjFdA9iDGNkNf2Zi9ztY7X+hNuMib23LNGRm6+uN+KLE3g==", + "dev": true, + "dependencies": { + "eslint-plugin-es": "^3.0.0", + "eslint-utils": "^2.0.0", + "ignore": "^5.1.1", + "minimatch": "^3.0.4", + "resolve": "^1.10.1", + "semver": "^6.1.0" + }, + "engines": { + "node": ">=8.10.0" + }, + "peerDependencies": { + "eslint": ">=5.16.0" + } + }, + "node_modules/eslint-plugin-node/node_modules/ignore": { + "version": "5.1.8", + "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.1.8.tgz", + "integrity": "sha512-BMpfD7PpiETpBl/A6S498BaIJ6Y/ABT93ETbby2fP00v4EbvPBXWEoaR1UBPKs3iR53pJY7EtZk5KACI57i1Uw==", + "dev": true, + "engines": { + "node": ">= 4" + } + }, + "node_modules/eslint-plugin-node/node_modules/resolve": { + "version": "1.19.0", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.19.0.tgz", + "integrity": "sha512-rArEXAgsBG4UgRGcynxWIWKFvh/XZCcS8UJdHhwy91zwAvCZIbcs+vAbflgBnNjYMs/i/i+/Ux6IZhML1yPvxg==", + "dev": true, + "dependencies": { + "is-core-module": "^2.1.0", + "path-parse": "^1.0.6" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/eslint-plugin-node/node_modules/semver": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", + "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", + "dev": true, + "bin": { + "semver": "bin/semver.js" + } + }, + "node_modules/eslint-plugin-promise": { + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/eslint-plugin-promise/-/eslint-plugin-promise-4.2.1.tgz", + "integrity": "sha512-VoM09vT7bfA7D+upt+FjeBO5eHIJQBUWki1aPvB+vbNiHS3+oGIJGIeyBtKQTME6UPXXy3vV07OL1tHd3ANuDw==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/eslint-plugin-react": { + "version": "7.21.5", + "resolved": "https://registry.npmjs.org/eslint-plugin-react/-/eslint-plugin-react-7.21.5.tgz", + "integrity": "sha512-8MaEggC2et0wSF6bUeywF7qQ46ER81irOdWS4QWxnnlAEsnzeBevk1sWh7fhpCghPpXb+8Ks7hvaft6L/xsR6g==", + "dev": true, + "dependencies": { + "array-includes": "^3.1.1", + "array.prototype.flatmap": "^1.2.3", + "doctrine": "^2.1.0", + "has": "^1.0.3", + "jsx-ast-utils": "^2.4.1 || ^3.0.0", + "object.entries": "^1.1.2", + "object.fromentries": "^2.0.2", + "object.values": "^1.1.1", + "prop-types": "^15.7.2", + "resolve": "^1.18.1", + "string.prototype.matchall": "^4.0.2" + }, + "engines": { + "node": ">=4" + }, + "peerDependencies": { + "eslint": "^3 || ^4 || ^5 || ^6 || ^7" + } + }, + "node_modules/eslint-plugin-react/node_modules/doctrine": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-2.1.0.tgz", + "integrity": "sha512-35mSku4ZXK0vfCuHEDAwt55dg2jNajHZ1odvF+8SSr82EsZY4QmXfuWso8oEd8zRhVObSN18aM0CjSdoBX7zIw==", + "dev": true, + "dependencies": { + "esutils": "^2.0.2" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/eslint-plugin-react/node_modules/resolve": { + "version": "1.19.0", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.19.0.tgz", + "integrity": "sha512-rArEXAgsBG4UgRGcynxWIWKFvh/XZCcS8UJdHhwy91zwAvCZIbcs+vAbflgBnNjYMs/i/i+/Ux6IZhML1yPvxg==", + "dev": true, + "dependencies": { + "is-core-module": "^2.1.0", + "path-parse": "^1.0.6" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/eslint-scope": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-5.1.1.tgz", + "integrity": "sha512-2NxwbF/hZ0KpepYN0cNbo+FN6XoK7GaHlQhgx/hIZl6Va0bF45RQOOwhLIy8lQDbuCiadSLCBnH2CFYquit5bw==", + "dev": true, + "dependencies": { + "esrecurse": "^4.3.0", + "estraverse": "^4.1.1" + }, + "engines": { + "node": ">=8.0.0" + } + }, + "node_modules/eslint-scope/node_modules/estraverse": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-4.3.0.tgz", + "integrity": "sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw==", + "dev": true, + "engines": { + "node": ">=4.0" + } + }, + "node_modules/eslint-utils": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/eslint-utils/-/eslint-utils-2.1.0.tgz", + "integrity": "sha512-w94dQYoauyvlDc43XnGB8lU3Zt713vNChgt4EWwhXAP2XkBvndfxF0AgIqKOOasjPIPzj9JqgwkwbCYD0/V3Zg==", + "dev": true, + "dependencies": { + "eslint-visitor-keys": "^1.1.0" + }, + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/mysticatea" + } + }, + "node_modules/eslint-utils/node_modules/eslint-visitor-keys": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-1.3.0.tgz", + "integrity": "sha512-6J72N8UNa462wa/KFODt/PJ3IU60SDpC3QXC1Hjc1BXXpfL2C9R5+AU7jhe0F6GREqVMh4Juu+NY7xn+6dipUQ==", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/eslint-visitor-keys": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-2.0.0.tgz", + "integrity": "sha512-QudtT6av5WXels9WjIM7qz1XD1cWGvX4gGXvp/zBn9nXG02D0utdU3Em2m/QjTnrsk6bBjmCygl3rmj118msQQ==", + "dev": true, + "engines": { + "node": ">=10" + } + }, + "node_modules/eslint/node_modules/ansi-regex": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.0.tgz", + "integrity": "sha512-bY6fj56OUQ0hU1KjFNDQuJFezqKdrAyFdIevADiqrWHwSlbmBNMHp5ak2f40Pm8JTFyM2mqxkG6ngkHO11f/lg==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/eslint/node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/eslint/node_modules/chalk": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.0.tgz", + "integrity": "sha512-qwx12AxXe2Q5xQ43Ac//I6v5aXTipYrSESdOgzrN+9XjgEpyjpKuvSGaN4qE93f7TQTlerQQ8S+EQ0EyDoVL1A==", + "dev": true, + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/eslint/node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/eslint/node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true + }, + "node_modules/eslint/node_modules/debug": { + "version": "4.3.1", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.1.tgz", + "integrity": "sha512-doEwdvm4PCeK4K3RQN2ZC2BYUBaxwLARCqZmMjtF8a51J2Rb0xpVloFRnCODwqjpwnAoao4pelN8l3RJdv3gRQ==", + "dev": true, + "dependencies": { + "ms": "2.1.2" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/eslint/node_modules/has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/eslint/node_modules/levn": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/levn/-/levn-0.4.1.tgz", + "integrity": "sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==", + "dev": true, + "dependencies": { + "prelude-ls": "^1.2.1", + "type-check": "~0.4.0" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/eslint/node_modules/ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", + "dev": true + }, + "node_modules/eslint/node_modules/optionator": { + "version": "0.9.1", + "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.9.1.tgz", + "integrity": "sha512-74RlY5FCnhq4jRxVUPKDaRwrVNXMqsGsiW6AJw4XK8hmtm10wC0ypZBLw5IIp85NZMr91+qd1RvvENwg7jjRFw==", + "dev": true, + "dependencies": { + "deep-is": "^0.1.3", + "fast-levenshtein": "^2.0.6", + "levn": "^0.4.1", + "prelude-ls": "^1.2.1", + "type-check": "^0.4.0", + "word-wrap": "^1.2.3" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/eslint/node_modules/prelude-ls": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.2.1.tgz", + "integrity": "sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==", + "dev": true, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/eslint/node_modules/strip-ansi": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.0.tgz", + "integrity": "sha512-AuvKTrTfQNYNIctbR1K/YGTR1756GycPsg7b9bdV9Duqur4gv6aKqHXah67Z8ImS7WEz5QVcOtlfW2rZEugt6w==", + "dev": true, + "dependencies": { + "ansi-regex": "^5.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/eslint/node_modules/strip-json-comments": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz", + "integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==", + "dev": true, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/eslint/node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/eslint/node_modules/type-check": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.4.0.tgz", + "integrity": "sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==", + "dev": true, + "dependencies": { + "prelude-ls": "^1.2.1" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/espree": { + "version": "7.3.1", + "resolved": "https://registry.npmjs.org/espree/-/espree-7.3.1.tgz", + "integrity": "sha512-v3JCNCE64umkFpmkFGqzVKsOT0tN1Zr+ueqLZfpV1Ob8e+CEgPWa+OxCoGH3tnhimMKIaBm4m/vaRpJ/krRz2g==", + "dev": true, + "dependencies": { + "acorn": "^7.4.0", + "acorn-jsx": "^5.3.1", + "eslint-visitor-keys": "^1.3.0" + }, + "engines": { + "node": "^10.12.0 || >=12.0.0" + } + }, + "node_modules/espree/node_modules/eslint-visitor-keys": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-1.3.0.tgz", + "integrity": "sha512-6J72N8UNa462wa/KFODt/PJ3IU60SDpC3QXC1Hjc1BXXpfL2C9R5+AU7jhe0F6GREqVMh4Juu+NY7xn+6dipUQ==", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/esprima": { + "version": "2.7.3", + "resolved": "https://registry.npmjs.org/esprima/-/esprima-2.7.3.tgz", + "integrity": "sha1-luO3DVd59q1JzQMmc9HDEnZ7pYE=", + "dev": true, + "bin": { + "esparse": "bin/esparse.js", + "esvalidate": "bin/esvalidate.js" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/esquery": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.3.1.tgz", + "integrity": "sha512-olpvt9QG0vniUBZspVRN6lwB7hOZoTRtT+jzR+tS4ffYx2mzbw+z0XCOk44aaLYKApNX5nMm+E+P6o25ip/DHQ==", + "dev": true, + "dependencies": { + "estraverse": "^5.1.0" + }, + "engines": { + "node": ">=0.10" + } + }, + "node_modules/esquery/node_modules/estraverse": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.2.0.tgz", + "integrity": "sha512-BxbNGGNm0RyRYvUdHpIwv9IWzeM9XClbOxwoATuFdOE7ZE6wHL+HQ5T8hoPM+zHvmKzzsEqhgy0GrQ5X13afiQ==", + "dev": true, + "engines": { + "node": ">=4.0" + } + }, + "node_modules/esrecurse": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.3.0.tgz", + "integrity": "sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==", + "dev": true, + "dependencies": { + "estraverse": "^5.2.0" + }, + "engines": { + "node": ">=4.0" + } + }, + "node_modules/esrecurse/node_modules/estraverse": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.2.0.tgz", + "integrity": "sha512-BxbNGGNm0RyRYvUdHpIwv9IWzeM9XClbOxwoATuFdOE7ZE6wHL+HQ5T8hoPM+zHvmKzzsEqhgy0GrQ5X13afiQ==", + "dev": true, + "engines": { + "node": ">=4.0" + } + }, + "node_modules/estraverse": { + "version": "1.9.3", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-1.9.3.tgz", + "integrity": "sha1-r2fy3JIlgkFZUJJgkaQAXSnJu0Q=", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/esutils": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.2.tgz", + "integrity": "sha1-Cr9PHKpbyx96nYrMbepPqqBLrJs=", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/event-stream": { + "version": "3.3.4", + "resolved": "https://registry.npmjs.org/event-stream/-/event-stream-3.3.4.tgz", + "integrity": "sha1-SrTJoPWlTbkzi0w02Gv86PSzVXE=", + "dependencies": { + "duplexer": "~0.1.1", + "from": "~0", + "map-stream": "~0.1.0", + "pause-stream": "0.0.11", + "split": "0.3", + "stream-combiner": "~0.0.4", + "through": "~2.3.1" + } + }, + "node_modules/fast-deep-equal": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", + "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==" + }, + "node_modules/fast-json-stable-stringify": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.0.0.tgz", + "integrity": "sha1-1RQsDK7msRifh9OnYREGT4bIu/I=" + }, + "node_modules/fast-levenshtein": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz", + "integrity": "sha1-PYpcZog6FqMMqGQ+hR8Zuqd5eRc=", + "dev": true + }, + "node_modules/file-entry-cache": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-5.0.1.tgz", + "integrity": "sha512-bCg29ictuBaKUwwArK4ouCaqDgLZcysCFLmM/Yn/FDoqndh/9vNuQfXRDvTuXKLxfD/JtZQGKFT8MGcJBK644g==", + "dev": true, + "dependencies": { + "flat-cache": "^2.0.1" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/find-root": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/find-root/-/find-root-1.1.0.tgz", + "integrity": "sha512-NKfW6bec6GfKc0SGx1e07QZY9PE99u0Bft/0rzSD5k3sO/vwkVUpDUKVm5Gpp5Ue3YfShPFTX2070tDs5kB9Ng==", + "dev": true + }, + "node_modules/find-up": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-2.1.0.tgz", + "integrity": "sha1-RdG35QbHF93UgndaK3eSCjwMV6c=", + "dev": true, + "dependencies": { + "locate-path": "^2.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/flat": { + "version": "5.0.2", + "resolved": "https://registry.npmjs.org/flat/-/flat-5.0.2.tgz", + "integrity": "sha512-b6suED+5/3rTpUBdG1gupIl8MPFCAMA0QXwmljLhvCUKcUvdE4gWky9zpuGCcXHOsz4J9wPGNWq6OKpmIzz3hQ==", + "dev": true, + "bin": { + "flat": "cli.js" + } + }, + "node_modules/flat-cache": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-2.0.1.tgz", + "integrity": "sha512-LoQe6yDuUMDzQAEH8sgmh4Md6oZnc/7PjtwjNFSzveXqSHt6ka9fPBuso7IGf9Rz4uqnSnWiFH2B/zj24a5ReA==", + "dev": true, + "dependencies": { + "flatted": "^2.0.0", + "rimraf": "2.6.3", + "write": "1.0.3" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/flatted": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/flatted/-/flatted-2.0.2.tgz", + "integrity": "sha512-r5wGx7YeOwNWNlCA0wQ86zKyDLMQr+/RB8xy74M4hTphfmjlijTSSXGuH8rnvKZnfT9i+75zmd8jcKdMR4O6jA==", + "dev": true + }, + "node_modules/foreground-child": { + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/foreground-child/-/foreground-child-3.3.1.tgz", + "integrity": "sha512-gIXjKqtFuWEgzFRJA9WCQeSJLZDjgJUOMCMzxtvFq/37KojM1BFGufqsCy0r4qSQmYLsZYMeyRqzIWOMup03sw==", + "dev": true, + "dependencies": { + "cross-spawn": "^7.0.6", + "signal-exit": "^4.0.1" + }, + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/form-data": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/form-data/-/form-data-3.0.4.tgz", + "integrity": "sha512-f0cRzm6dkyVYV3nPoooP8XlccPQukegwhAnpoLcXy+X+A8KfpGOoXwDr9FLZd3wzgLaBGQBE3lY93Zm/i1JvIQ==", + "dependencies": { + "asynckit": "^0.4.0", + "combined-stream": "^1.0.8", + "es-set-tostringtag": "^2.1.0", + "hasown": "^2.0.2", + "mime-types": "^2.1.35" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/form-data/node_modules/combined-stream": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz", + "integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==", + "dependencies": { + "delayed-stream": "~1.0.0" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/from": { + "version": "0.1.7", + "resolved": "https://registry.npmjs.org/from/-/from-0.1.7.tgz", + "integrity": "sha1-g8YK/Fi5xWmXAH7Rp2izqzA6RP4=" + }, + "node_modules/fs-readfile-promise": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/fs-readfile-promise/-/fs-readfile-promise-2.0.1.tgz", + "integrity": "sha1-gAI4I5gfn//+AWCei+Zo9prknnA=", + "dependencies": { + "graceful-fs": "^4.1.2" + } + }, + "node_modules/fs-writefile-promise": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/fs-writefile-promise/-/fs-writefile-promise-1.0.3.tgz", + "integrity": "sha1-4C+bWP/CVe2CKtx6ARFPRF1I0GM=", + "dependencies": { + "mkdirp-promise": "^1.0.0", + "pinkie-promise": "^1.0.0" + }, + "engines": { + "node": ">=0.10" + } + }, + "node_modules/fs-writefile-promise/node_modules/pinkie-promise": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/pinkie-promise/-/pinkie-promise-1.0.0.tgz", + "integrity": "sha1-0dpn9UglY7t89X8oauKCLs+/NnA=", + "dependencies": { + "pinkie": "^1.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/fs.realpath": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", + "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=", + "dev": true + }, + "node_modules/function-bind": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz", + "integrity": "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==", + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/functional-red-black-tree": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/functional-red-black-tree/-/functional-red-black-tree-1.0.1.tgz", + "integrity": "sha1-GwqzvVU7Kg1jmdKcDj6gslIHgyc=", + "dev": true + }, + "node_modules/get-caller-file": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz", + "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==", + "dev": true, + "engines": { + "node": "6.* || 8.* || >= 10.*" + } + }, + "node_modules/get-intrinsic": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.3.0.tgz", + "integrity": "sha512-9fSjSaos/fRIVIp+xSJlE6lfwhES7LNtKaCBIamHsjr2na1BiABJPo0mOjjz8GJDURarmCPGqaiVg5mfjb98CQ==", + "dependencies": { + "call-bind-apply-helpers": "^1.0.2", + "es-define-property": "^1.0.1", + "es-errors": "^1.3.0", + "es-object-atoms": "^1.1.1", + "function-bind": "^1.1.2", + "get-proto": "^1.0.1", + "gopd": "^1.2.0", + "has-symbols": "^1.1.0", + "hasown": "^2.0.2", + "math-intrinsics": "^1.1.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/get-proto": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/get-proto/-/get-proto-1.0.1.tgz", + "integrity": "sha512-sTSfBjoXBp89JvIKIefqw7U2CCebsc74kiY6awiGogKtoSGbgjYE/G/+l9sF3MWFPNc9IcoOC4ODfKHfxFmp0g==", + "dependencies": { + "dunder-proto": "^1.0.1", + "es-object-atoms": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/get-stdin": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/get-stdin/-/get-stdin-8.0.0.tgz", + "integrity": "sha512-sY22aA6xchAzprjyqmSEQv4UbAAzRN0L2dQB0NlN5acTTK9Don6nhoc3eAbUnpZiCANAMfd/+40kVdKfFygohg==", + "dev": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/glob": { + "version": "6.0.4", + "resolved": "https://registry.npmjs.org/glob/-/glob-6.0.4.tgz", + "integrity": "sha1-DwiGD2oVUSey+t1PnOJLGqtuTSI=", + "dev": true, + "dependencies": { + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "2 || 3", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + }, + "engines": { + "node": "*" + } + }, + "node_modules/glob-parent": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", + "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", + "dev": true, + "dependencies": { + "is-glob": "^4.0.1" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/globals": { + "version": "12.4.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-12.4.0.tgz", + "integrity": "sha512-BWICuzzDvDoH54NHKCseDanAhE3CeDorgDL5MT6LMXXj2WCnd9UC2szdk4AWLfjdgNBCXLUanXYcpBBKOSWGwg==", + "dev": true, + "dependencies": { + "type-fest": "^0.8.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/gopd": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/gopd/-/gopd-1.2.0.tgz", + "integrity": "sha512-ZUKRh6/kUFoAiTAtTYPZJ3hw9wNxx+BIBOijnlG9PnrJsCcSjs1wyyD6vJpaYtgnzDrKYRSqf3OO6Rfa93xsRg==", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/graceful-fs": { + "version": "4.1.15", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.1.15.tgz", + "integrity": "sha512-6uHUhOPEBgQ24HM+r6b/QwWfZq+yiFcipKFrOFiBEnWdy5sdzYoi+pJeQaPI5qOLRFqWmAXUPQNsielzdLoecA==" + }, + "node_modules/handlebars": { + "version": "4.7.7", + "resolved": "https://registry.npmjs.org/handlebars/-/handlebars-4.7.7.tgz", + "integrity": "sha512-aAcXm5OAfE/8IXkcZvCepKU3VzW1/39Fb5ZuqMtgI/hT8X2YgoMvBY5dLhq/cpOvw7Lk1nK/UF71aLG/ZnVYRA==", + "dev": true, + "dependencies": { + "minimist": "^1.2.5", + "neo-async": "^2.6.0", + "source-map": "^0.6.1", + "wordwrap": "^1.0.0" + }, + "bin": { + "handlebars": "bin/handlebars" + }, + "engines": { + "node": ">=0.4.7" + }, + "optionalDependencies": { + "uglify-js": "^3.1.4" + } + }, + "node_modules/handlebars/node_modules/minimist": { + "version": "1.2.5", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.5.tgz", + "integrity": "sha512-FM9nNUYrRBAELZQT3xeZQ7fmMOBg6nWNmJKTcgsJeaLstP/UODVpGsr5OhXhhXg6f+qtJ8uiZ+PUxkDWcgIXLw==", + "dev": true + }, + "node_modules/handlebars/node_modules/source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/har-schema": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/har-schema/-/har-schema-2.0.0.tgz", + "integrity": "sha1-qUwiJOvKwEeCoNkDVSHyRzW37JI=", + "engines": { + "node": ">=4" + } + }, + "node_modules/har-validator": { + "version": "5.1.3", + "resolved": "https://registry.npmjs.org/har-validator/-/har-validator-5.1.3.tgz", + "integrity": "sha1-HvievT5JllV2de7ZiTEQ3DUPoIA=", + "deprecated": "this library is no longer supported", + "dependencies": { + "ajv": "^6.5.5", + "har-schema": "^2.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/has": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz", + "integrity": "sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==", + "dev": true, + "dependencies": { + "function-bind": "^1.1.1" + }, + "engines": { + "node": ">= 0.4.0" + } + }, + "node_modules/has-ansi": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/has-ansi/-/has-ansi-2.0.0.tgz", + "integrity": "sha1-NPUEnOHs3ysGSa8+8k5F7TVBbZE=", + "dependencies": { + "ansi-regex": "^2.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/has-flag": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-1.0.0.tgz", + "integrity": "sha1-nZ55MWXOAXoA8AQYxD+UKnsdEfo=", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/has-symbols": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.1.0.tgz", + "integrity": "sha512-1cDNdwJ2Jaohmb3sg4OmKaMBwuC48sYni5HUw2DvsC8LjGTLK9h+eb1X6RyuOHe4hT0ULCW68iomhjUoKUqlPQ==", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/has-tostringtag": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/has-tostringtag/-/has-tostringtag-1.0.2.tgz", + "integrity": "sha512-NqADB8VjPFLM2V0VvHUewwwsw0ZWBaIdgo+ieHtK3hasLz4qeCRjYcqfB6AQrBggRKppKF8L52/VqdVsO47Dlw==", + "dependencies": { + "has-symbols": "^1.0.3" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/hasown": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.2.tgz", + "integrity": "sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==", + "dependencies": { + "function-bind": "^1.1.2" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/he": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/he/-/he-1.2.0.tgz", + "integrity": "sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw==", + "dev": true, + "bin": { + "he": "bin/he" + } + }, + "node_modules/hosted-git-info": { + "version": "2.8.9", + "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-2.8.9.tgz", + "integrity": "sha512-mxIDAb9Lsm6DoOJ7xH+5+X4y1LU/4Hi50L9C5sIswK3JzULS4bwk1FvjdBgvYR4bzT4tuUQiC15FE2f5HbLvYw==", + "dev": true + }, + "node_modules/ignore": { + "version": "4.0.6", + "resolved": "https://registry.npmjs.org/ignore/-/ignore-4.0.6.tgz", + "integrity": "sha512-cyFDKrqc/YdcWFniJhzI42+AzS+gNwmUzOSFcRCQYwySuBBBy/KjuxWLZ/FHEH6Moq1NizMOBWyTcv8O4OZIMg==", + "dev": true, + "engines": { + "node": ">= 4" + } + }, + "node_modules/import-fresh": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.0.tgz", + "integrity": "sha512-veYYhQa+D1QBKznvhUHxb8faxlrwUnxseDAbAp457E0wLNio2bOSKnjYDhMj+YiAq61xrMGhQk9iXVk5FzgQMw==", + "dev": true, + "dependencies": { + "parent-module": "^1.0.0", + "resolve-from": "^4.0.0" + }, + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/imurmurhash": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz", + "integrity": "sha1-khi5srkoojixPcT7a21XbyMUU+o=", + "dev": true, + "engines": { + "node": ">=0.8.19" + } + }, + "node_modules/inflight": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", + "integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=", + "dev": true, + "dependencies": { + "once": "^1.3.0", + "wrappy": "1" + } + }, + "node_modules/inherits": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", + "integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=", + "dev": true + }, + "node_modules/ini": { + "version": "1.3.8", + "resolved": "https://registry.npmjs.org/ini/-/ini-1.3.8.tgz", + "integrity": "sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew==", + "dev": true + }, + "node_modules/internal-slot": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/internal-slot/-/internal-slot-1.0.3.tgz", + "integrity": "sha512-O0DB1JC/sPyZl7cIo78n5dR7eUSwwpYPiXRhTzNxZVAMUuB8vlnRFyLxdrVToks6XPLVnFfbzaVd5WLjhgg+vA==", + "dev": true, + "dependencies": { + "get-intrinsic": "^1.1.0", + "has": "^1.0.3", + "side-channel": "^1.0.4" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/is-arrayish": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz", + "integrity": "sha1-d8mYQFJ6qOyxqLppe4BkWnqSap0=", + "dev": true + }, + "node_modules/is-callable": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.2.2.tgz", + "integrity": "sha512-dnMqspv5nU3LoewK2N/y7KLtxtakvTuaCsU9FU50/QDmdbHNy/4/JuRtMHqRU22o3q+W89YQndQEeCVwK+3qrA==", + "dev": true, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-core-module": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.2.0.tgz", + "integrity": "sha512-XRAfAdyyY5F5cOXn7hYQDqh2Xmii+DEfIcQGxK/uNwMHhIkPWO0g8msXcbzLe+MpGoR951MlqM/2iIlU4vKDdQ==", + "dev": true, + "dependencies": { + "has": "^1.0.3" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-date-object": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-date-object/-/is-date-object-1.0.1.tgz", + "integrity": "sha1-mqIOtq7rv/d/vTPnTKAbM1gdOhY=", + "dev": true, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/is-extglob": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", + "integrity": "sha1-qIwCU1eR8C7TfHahueqXc8gz+MI=", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-fullwidth-code-point": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz", + "integrity": "sha1-o7MKXE8ZkYMWeqq5O+764937ZU8=", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/is-glob": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.1.tgz", + "integrity": "sha512-5G0tKtBTFImOqDnLB2hG6Bp2qcKEFduo4tZu9MT/H6NQv/ghhy30o55ufafxJ/LdH79LLs2Kfrn85TLKyA7BUg==", + "dev": true, + "dependencies": { + "is-extglob": "^2.1.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-negative-zero": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/is-negative-zero/-/is-negative-zero-2.0.1.tgz", + "integrity": "sha512-2z6JzQvZRa9A2Y7xC6dQQm4FSTSTNWjKIYYTt4246eMTJmIo0Q+ZyOsU66X8lxK1AbB92dFeglPLrhwpeRKO6w==", + "dev": true, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-path-inside": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/is-path-inside/-/is-path-inside-3.0.3.tgz", + "integrity": "sha512-Fd4gABb+ycGAmKou8eMftCupSir5lRxqf4aD/vd0cD2qc4HL07OjCeuHMr8Ro4CoMaeCKDB0/ECBOVWjTwUvPQ==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/is-plain-obj": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/is-plain-obj/-/is-plain-obj-2.1.0.tgz", + "integrity": "sha512-YWnfyRwxL/+SsrWYfOpUtz5b3YD+nyfkHvjbcanzk8zgyO4ASD67uVMRt8k5bM4lLMDnXfriRhOpemw+NfT1eA==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/is-regex": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.1.1.tgz", + "integrity": "sha512-1+QkEcxiLlB7VEyFtyBg94e08OAsvq7FUBgApTq/w2ymCLyKJgDPsybBENVtA7XCQEgEXxKPonG+mvYRxh/LIg==", + "dev": true, + "dependencies": { + "has-symbols": "^1.0.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-string": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/is-string/-/is-string-1.0.5.tgz", + "integrity": "sha512-buY6VNRjhQMiF1qWDouloZlQbRhDPCebwxSjxMjxgemYT46YMd2NR0/H+fBhEfWX4A/w9TBJ+ol+okqJKFE6vQ==", + "dev": true, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-symbol": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-symbol/-/is-symbol-1.0.2.tgz", + "integrity": "sha512-HS8bZ9ox60yCJLH9snBpIwv9pYUAkcuLhSA1oero1UB5y9aiQpRA8y2ex945AOtCZL1lJDeIk3G5LthswI46Lw==", + "dev": true, + "dependencies": { + "has-symbols": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/is-unicode-supported": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/is-unicode-supported/-/is-unicode-supported-0.1.0.tgz", + "integrity": "sha512-knxG2q4UC3u8stRGyAVJCOdxFmv5DZiRcdlIaAQXAbSfJya+OhopNotLQrstBhququ4ZpuKbDc/8S6mgXgPFPw==", + "dev": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/isarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=", + "dev": true + }, + "node_modules/isexe": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", + "integrity": "sha1-6PvzdNxVb/iUehDcsFctYz8s+hA=", + "dev": true + }, + "node_modules/istanbul": { + "version": "0.4.5", + "resolved": "https://registry.npmjs.org/istanbul/-/istanbul-0.4.5.tgz", + "integrity": "sha1-ZcfXPUxNqE1POsMQuRj7C4Azczs=", + "deprecated": "This module is no longer maintained, try this instead:\n npm i nyc\nVisit https://istanbul.js.org/integrations for other alternatives.", + "dev": true, + "dependencies": { + "abbrev": "1.0.x", + "async": "1.x", + "escodegen": "1.8.x", + "esprima": "2.7.x", + "glob": "^5.0.15", + "handlebars": "^4.0.1", + "js-yaml": "3.x", + "mkdirp": "0.5.x", + "nopt": "3.x", + "once": "1.x", + "resolve": "1.1.x", + "supports-color": "^3.1.0", + "which": "^1.1.1", + "wordwrap": "^1.0.0" + }, + "bin": { + "istanbul": "lib/cli.js" + } + }, + "node_modules/istanbul/node_modules/async": { + "version": "1.5.2", + "resolved": "https://registry.npmjs.org/async/-/async-1.5.2.tgz", + "integrity": "sha1-7GphrlZIDAw8skHJVhjiCJL5Zyo=", + "dev": true + }, + "node_modules/istanbul/node_modules/glob": { + "version": "5.0.15", + "resolved": "https://registry.npmjs.org/glob/-/glob-5.0.15.tgz", + "integrity": "sha1-G8k2ueAvSmA/zCIuz3Yz0wuLk7E=", + "dev": true, + "dependencies": { + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "2 || 3", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + }, + "engines": { + "node": "*" + } + }, + "node_modules/istanbul/node_modules/supports-color": { + "version": "3.2.3", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-3.2.3.tgz", + "integrity": "sha1-ZawFBLOVQXHYpklGsq48u4pfVPY=", + "dev": true, + "dependencies": { + "has-flag": "^1.0.0" + }, + "engines": { + "node": ">=0.8.0" + } + }, + "node_modules/jackspeak": { + "version": "3.4.3", + "resolved": "https://registry.npmjs.org/jackspeak/-/jackspeak-3.4.3.tgz", + "integrity": "sha512-OGlZQpz2yfahA/Rd1Y8Cd9SIEsqvXkLVoSw/cgwhnhFMDbsQFeZYoJJ7bIZBS9BcamUW96asq/npPWugM+RQBw==", + "dev": true, + "dependencies": { + "@isaacs/cliui": "^8.0.2" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + }, + "optionalDependencies": { + "@pkgjs/parseargs": "^0.11.0" + } + }, + "node_modules/js-tokens": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", + "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==", + "dev": true + }, + "node_modules/js-yaml": { + "version": "3.14.2", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.14.2.tgz", + "integrity": "sha512-PMSmkqxr106Xa156c2M265Z+FTrPl+oxd/rgOQy2tijQeK5TxQ43psO1ZCwhVOSdnn+RzkzlRz/eY4BgJBYVpg==", + "dev": true, + "dependencies": { + "argparse": "^1.0.7", + "esprima": "^4.0.0" + }, + "bin": { + "js-yaml": "bin/js-yaml.js" + } + }, + "node_modules/js-yaml/node_modules/esprima": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz", + "integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==", + "dev": true, + "bin": { + "esparse": "bin/esparse.js", + "esvalidate": "bin/esvalidate.js" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/json-parse-better-errors": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/json-parse-better-errors/-/json-parse-better-errors-1.0.2.tgz", + "integrity": "sha512-mrqyZKfX5EhL7hvqcV6WG1yYjnjeuYDzDhhcAAUrq8Po85NBQBJP+ZDUT75qZQ98IkUoBqdkExkukOU7Ts2wrw==", + "dev": true + }, + "node_modules/json-schema-traverse": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", + "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==" + }, + "node_modules/json-stable-stringify-without-jsonify": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz", + "integrity": "sha1-nbe1lJatPzz+8wp1FC0tkwrXJlE=", + "dev": true + }, + "node_modules/json5": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/json5/-/json5-1.0.2.tgz", + "integrity": "sha512-g1MWMLBiz8FKi1e4w0UyVL3w+iJceWAFBAaBnnGKOpNa5f8TLktkbre1+s6oICydWAm+HRUGTmI+//xv2hvXYA==", + "dev": true, + "dependencies": { + "minimist": "^1.2.0" + }, + "bin": { + "json5": "lib/cli.js" + } + }, + "node_modules/jsx-ast-utils": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/jsx-ast-utils/-/jsx-ast-utils-3.2.0.tgz", + "integrity": "sha512-EIsmt3O3ljsU6sot/J4E1zDRxfBNrhjyf/OKjlydwgEimQuznlM4Wv7U+ueONJMyEn1WRE0K8dhi3dVAXYT24Q==", + "dev": true, + "dependencies": { + "array-includes": "^3.1.2", + "object.assign": "^4.1.2" + }, + "engines": { + "node": ">=4.0" + } + }, + "node_modules/jsx-ast-utils/node_modules/object.assign": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/object.assign/-/object.assign-4.1.2.tgz", + "integrity": "sha512-ixT2L5THXsApyiUPYKmW+2EHpXXe5Ii3M+f4e+aJFAHao5amFRW6J0OO6c/LU8Be47utCx2GL89hxGB6XSmKuQ==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.0", + "define-properties": "^1.1.3", + "has-symbols": "^1.0.1", + "object-keys": "^1.1.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/levn": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/levn/-/levn-0.3.0.tgz", + "integrity": "sha1-OwmSTt+fCDwEkP3UwLxEIeBHZO4=", + "dev": true, + "dependencies": { + "prelude-ls": "~1.1.2", + "type-check": "~0.3.2" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/lintspaces": { + "version": "0.6.3", + "resolved": "https://registry.npmjs.org/lintspaces/-/lintspaces-0.6.3.tgz", + "integrity": "sha512-nUwq/jK+gUhpILtV9Ms2cuF16LB9a8nnecowSQD5LRNX3+h1Bl1zIvPZNQgJYeK9xxuoR+HuWnjagQsvyJbS4w==", + "dev": true, + "dependencies": { + "deep-extend": "^0.6.0", + "editorconfig": "^0.15.0", + "rc": "^1.2.8" + }, + "engines": { + "node": ">=5" + } + }, + "node_modules/load-json-file": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/load-json-file/-/load-json-file-2.0.0.tgz", + "integrity": "sha1-eUfkIUmvgNaWy/eXvKq8/h/inKg=", + "dev": true, + "dependencies": { + "graceful-fs": "^4.1.2", + "parse-json": "^2.2.0", + "pify": "^2.0.0", + "strip-bom": "^3.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/locate-path": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-2.0.0.tgz", + "integrity": "sha1-K1aLJl7slExtnA3pw9u7ygNUzY4=", + "dev": true, + "dependencies": { + "p-locate": "^2.0.0", + "path-exists": "^3.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/lodash": { + "version": "4.17.23", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.23.tgz", + "integrity": "sha512-LgVTMpQtIopCi79SJeDiP0TfWi5CNEc/L/aRdTh3yIvmZXTnheWpKjSZhnvMl8iXbC1tFg9gdHHDMLoV7CnG+w==", + "dev": true + }, + "node_modules/log-symbols": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/log-symbols/-/log-symbols-4.1.0.tgz", + "integrity": "sha512-8XPvpAA8uyhfteu8pIvQxpJZ7SYYdpUivZpGy6sFsBuKRY/7rQGavedeB8aK+Zkyq6upMFVL/9AW6vOYzfRyLg==", + "dev": true, + "dependencies": { + "chalk": "^4.1.0", + "is-unicode-supported": "^0.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/log-symbols/node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/log-symbols/node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/log-symbols/node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/log-symbols/node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true + }, + "node_modules/log-symbols/node_modules/has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/log-symbols/node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/loose-envify": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/loose-envify/-/loose-envify-1.4.0.tgz", + "integrity": "sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q==", + "dev": true, + "dependencies": { + "js-tokens": "^3.0.0 || ^4.0.0" + }, + "bin": { + "loose-envify": "cli.js" + } + }, + "node_modules/lru-cache": { + "version": "4.1.5", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-4.1.5.tgz", + "integrity": "sha512-sWZlbEP2OsHNkXrMl5GYk/jKk70MBng6UU4YI/qGDYbgf6YbP4EvmqISbXCoJiRKs+1bSpFHVgQxvJ17F2li5g==", + "dev": true, + "dependencies": { + "pseudomap": "^1.0.2", + "yallist": "^2.1.2" + } + }, + "node_modules/map-stream": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/map-stream/-/map-stream-0.1.0.tgz", + "integrity": "sha1-5WqpTEyAVaFkBKBnS3jyFffI4ZQ=" + }, + "node_modules/math-intrinsics": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/math-intrinsics/-/math-intrinsics-1.1.0.tgz", + "integrity": "sha512-/IXtbwEk5HTPyEwyKX6hGkYXxM9nbj64B+ilVJnC/R6B0pH5G4V3b0pVbL7DBj4tkhBAppbQUlf6F6Xl9LHu1g==", + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/mime-db": { + "version": "1.52.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz", + "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/mime-types": { + "version": "2.1.35", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz", + "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==", + "dependencies": { + "mime-db": "1.52.0" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/minimatch": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz", + "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==", + "dev": true, + "dependencies": { + "brace-expansion": "^1.1.7" + }, + "engines": { + "node": "*" + } + }, + "node_modules/minimist": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz", + "integrity": "sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ=", + "dev": true + }, + "node_modules/minipass": { + "version": "7.1.2", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-7.1.2.tgz", + "integrity": "sha512-qOOzS1cBTWYF4BH8fVePDBOO9iptMnGUEZwNc/cMWnTV2nVLZ7VoNWEPHkYczZA0pdoA7dl6e7FL659nX9S2aw==", + "dev": true, + "engines": { + "node": ">=16 || 14 >=14.17" + } + }, + "node_modules/mkdirp": { + "version": "0.5.1", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.1.tgz", + "integrity": "sha1-MAV0OOrGz3+MR2fzhkjWaX11yQM=", + "deprecated": "Legacy versions of mkdirp are no longer supported. Please update to mkdirp 1.x. (Note that the API surface has changed to use Promises in 1.x.)", + "dependencies": { + "minimist": "0.0.8" + }, + "bin": { + "mkdirp": "bin/cmd.js" + } + }, + "node_modules/mkdirp-promise": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/mkdirp-promise/-/mkdirp-promise-1.1.0.tgz", + "integrity": "sha1-LISJPtZ24NmPsY+5piEv0bK5qBk=", + "deprecated": "This package is broken and no longer maintained. 'mkdirp' itself supports promises now, please switch to that.", + "engines": { + "node": ">=4" + }, + "peerDependencies": { + "mkdirp": ">=0.5.0" + } + }, + "node_modules/mkdirp/node_modules/minimist": { + "version": "0.0.8", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-0.0.8.tgz", + "integrity": "sha1-hX/Kv8M5fSYluCKCYuhqp6ARsF0=" + }, + "node_modules/mocha": { + "version": "11.7.5", + "resolved": "https://registry.npmjs.org/mocha/-/mocha-11.7.5.tgz", + "integrity": "sha512-mTT6RgopEYABzXWFx+GcJ+ZQ32kp4fMf0xvpZIIfSq9Z8lC/++MtcCnQ9t5FP2veYEP95FIYSvW+U9fV4xrlig==", + "dev": true, + "dependencies": { + "browser-stdout": "^1.3.1", + "chokidar": "^4.0.1", + "debug": "^4.3.5", + "diff": "^7.0.0", + "escape-string-regexp": "^4.0.0", + "find-up": "^5.0.0", + "glob": "^10.4.5", + "he": "^1.2.0", + "is-path-inside": "^3.0.3", + "js-yaml": "^4.1.0", + "log-symbols": "^4.1.0", + "minimatch": "^9.0.5", + "ms": "^2.1.3", + "picocolors": "^1.1.1", + "serialize-javascript": "^6.0.2", + "strip-json-comments": "^3.1.1", + "supports-color": "^8.1.1", + "workerpool": "^9.2.0", + "yargs": "^17.7.2", + "yargs-parser": "^21.1.1", + "yargs-unparser": "^2.0.0" + }, + "bin": { + "_mocha": "bin/_mocha", + "mocha": "bin/mocha.js" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + } + }, + "node_modules/mocha/node_modules/argparse": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", + "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==", + "dev": true + }, + "node_modules/mocha/node_modules/brace-expansion": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.2.tgz", + "integrity": "sha512-Jt0vHyM+jmUBqojB7E1NIYadt0vI0Qxjxd2TErW94wDz+E2LAm5vKMXXwg6ZZBTHPuUlDgQHKXvjGBdfcF1ZDQ==", + "dev": true, + "dependencies": { + "balanced-match": "^1.0.0" + } + }, + "node_modules/mocha/node_modules/debug": { + "version": "4.4.3", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.3.tgz", + "integrity": "sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA==", + "dev": true, + "dependencies": { + "ms": "^2.1.3" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/mocha/node_modules/escape-string-regexp": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz", + "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==", + "dev": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/mocha/node_modules/find-up": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz", + "integrity": "sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==", + "dev": true, + "dependencies": { + "locate-path": "^6.0.0", + "path-exists": "^4.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/mocha/node_modules/glob": { + "version": "10.4.5", + "resolved": "https://registry.npmjs.org/glob/-/glob-10.4.5.tgz", + "integrity": "sha512-7Bv8RF0k6xjo7d4A/PxYLbUCfb6c+Vpd2/mB2yRDlew7Jb5hEXiCD9ibfO7wpk8i4sevK6DFny9h7EYbM3/sHg==", + "dev": true, + "dependencies": { + "foreground-child": "^3.1.0", + "jackspeak": "^3.1.2", + "minimatch": "^9.0.4", + "minipass": "^7.1.2", + "package-json-from-dist": "^1.0.0", + "path-scurry": "^1.11.1" + }, + "bin": { + "glob": "dist/esm/bin.mjs" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/mocha/node_modules/has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/mocha/node_modules/js-yaml": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.1.tgz", + "integrity": "sha512-qQKT4zQxXl8lLwBtHMWwaTcGfFOZviOJet3Oy/xmGk2gZH677CJM9EvtfdSkgWcATZhj/55JZ0rmy3myCT5lsA==", + "dev": true, + "dependencies": { + "argparse": "^2.0.1" + }, + "bin": { + "js-yaml": "bin/js-yaml.js" + } + }, + "node_modules/mocha/node_modules/locate-path": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz", + "integrity": "sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==", + "dev": true, + "dependencies": { + "p-locate": "^5.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/mocha/node_modules/minimatch": { + "version": "9.0.5", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.5.tgz", + "integrity": "sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow==", + "dev": true, + "dependencies": { + "brace-expansion": "^2.0.1" + }, + "engines": { + "node": ">=16 || 14 >=14.17" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/mocha/node_modules/ms": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", + "dev": true + }, + "node_modules/mocha/node_modules/p-limit": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz", + "integrity": "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==", + "dev": true, + "dependencies": { + "yocto-queue": "^0.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/mocha/node_modules/p-locate": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-5.0.0.tgz", + "integrity": "sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==", + "dev": true, + "dependencies": { + "p-limit": "^3.0.2" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/mocha/node_modules/path-exists": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", + "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/mocha/node_modules/strip-json-comments": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz", + "integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==", + "dev": true, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/mocha/node_modules/supports-color": { + "version": "8.1.1", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-8.1.1.tgz", + "integrity": "sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==", + "dev": true, + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/supports-color?sponsor=1" + } + }, + "node_modules/ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=" + }, + "node_modules/natural-compare": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz", + "integrity": "sha1-Sr6/7tdUHywnrPspvbvRXI1bpPc=", + "dev": true + }, + "node_modules/neo-async": { + "version": "2.6.0", + "resolved": "https://registry.npmjs.org/neo-async/-/neo-async-2.6.0.tgz", + "integrity": "sha512-MFh0d/Wa7vkKO3Y3LlacqAEeHK0mckVqzDieUKTT+KGxi+zIpeVsFxymkIiRpbpDziHc290Xr9A1O4Om7otoRA==", + "dev": true + }, + "node_modules/nopt": { + "version": "3.0.6", + "resolved": "https://registry.npmjs.org/nopt/-/nopt-3.0.6.tgz", + "integrity": "sha1-xkZdvwirzU2zWTF/eaxopkayj/k=", + "dev": true, + "dependencies": { + "abbrev": "1" + }, + "bin": { + "nopt": "bin/nopt.js" + } + }, + "node_modules/normalize-package-data": { + "version": "2.5.0", + "resolved": "https://registry.npmjs.org/normalize-package-data/-/normalize-package-data-2.5.0.tgz", + "integrity": "sha512-/5CMN3T0R4XTj4DcGaexo+roZSdSFW/0AOOTROrjxzCG1wrWXEsGbRKevjlIL+ZDE4sZlJr5ED4YW0yqmkK+eA==", + "dev": true, + "dependencies": { + "hosted-git-info": "^2.1.4", + "resolve": "^1.10.0", + "semver": "2 || 3 || 4 || 5", + "validate-npm-package-license": "^3.0.1" + } + }, + "node_modules/normalize-package-data/node_modules/resolve": { + "version": "1.19.0", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.19.0.tgz", + "integrity": "sha512-rArEXAgsBG4UgRGcynxWIWKFvh/XZCcS8UJdHhwy91zwAvCZIbcs+vAbflgBnNjYMs/i/i+/Ux6IZhML1yPvxg==", + "dev": true, + "dependencies": { + "is-core-module": "^2.1.0", + "path-parse": "^1.0.6" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/normalize-package-data/node_modules/semver": { + "version": "5.7.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", + "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==", + "dev": true, + "bin": { + "semver": "bin/semver" + } + }, + "node_modules/object-assign": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", + "integrity": "sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM=", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/object-keys": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.1.1.tgz", + "integrity": "sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==", + "dev": true, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/object.entries": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/object.entries/-/object.entries-1.1.3.tgz", + "integrity": "sha512-ym7h7OZebNS96hn5IJeyUmaWhaSM4SVtAPPfNLQEI2MYWCO2egsITb9nab2+i/Pwibx+R0mtn+ltKJXRSeTMGg==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.0", + "define-properties": "^1.1.3", + "es-abstract": "^1.18.0-next.1", + "has": "^1.0.3" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/object.fromentries": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/object.fromentries/-/object.fromentries-2.0.3.tgz", + "integrity": "sha512-IDUSMXs6LOSJBWE++L0lzIbSqHl9KDCfff2x/JSEIDtEUavUnyMYC2ZGay/04Zq4UT8lvd4xNhU4/YHKibAOlw==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.0", + "define-properties": "^1.1.3", + "es-abstract": "^1.18.0-next.1", + "has": "^1.0.3" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/object.values": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/object.values/-/object.values-1.1.2.tgz", + "integrity": "sha512-MYC0jvJopr8EK6dPBiO8Nb9mvjdypOachO5REGk6MXzujbBrAisKo3HmdEI6kZDL6fC31Mwee/5YbtMebixeag==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.0", + "define-properties": "^1.1.3", + "es-abstract": "^1.18.0-next.1", + "has": "^1.0.3" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/once": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", + "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=", + "dev": true, + "dependencies": { + "wrappy": "1" + } + }, + "node_modules/optionator": { + "version": "0.8.2", + "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.8.2.tgz", + "integrity": "sha1-NkxeQJ0/TWMB1sC0wFu6UBgK62Q=", + "dev": true, + "dependencies": { + "deep-is": "~0.1.3", + "fast-levenshtein": "~2.0.4", + "levn": "~0.3.0", + "prelude-ls": "~1.1.2", + "type-check": "~0.3.2", + "wordwrap": "~1.0.0" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/p-limit": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-1.3.0.tgz", + "integrity": "sha512-vvcXsLAJ9Dr5rQOPk7toZQZJApBl2K4J6dANSsEuh6QI41JYcsS/qhTGa9ErIUUgK3WNQoJYvylxvjqmiqEA9Q==", + "dev": true, + "dependencies": { + "p-try": "^1.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/p-locate": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-2.0.0.tgz", + "integrity": "sha1-IKAQOyIqcMj9OcwuWAaA893l7EM=", + "dev": true, + "dependencies": { + "p-limit": "^1.1.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/p-try": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/p-try/-/p-try-1.0.0.tgz", + "integrity": "sha1-y8ec26+P1CKOE/Yh8rGiN8GyB7M=", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/package-json-from-dist": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/package-json-from-dist/-/package-json-from-dist-1.0.1.tgz", + "integrity": "sha512-UEZIS3/by4OC8vL3P2dTXRETpebLI2NiI5vIrjaD/5UtrkFX/tNbwjTSRAGC/+7CAo2pIcBaRgWmcBBHcsaCIw==", + "dev": true + }, + "node_modules/parent-module": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz", + "integrity": "sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==", + "dev": true, + "dependencies": { + "callsites": "^3.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/parse-json": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-2.2.0.tgz", + "integrity": "sha1-9ID0BDTvgHQfhGkJn43qGPVaTck=", + "dev": true, + "dependencies": { + "error-ex": "^1.2.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/path-exists": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-3.0.0.tgz", + "integrity": "sha1-zg6+ql94yxiSXqfYENe1mwEP1RU=", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/path-is-absolute": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", + "integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/path-key": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", + "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/path-parse": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz", + "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==", + "dev": true + }, + "node_modules/path-scurry": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/path-scurry/-/path-scurry-1.11.1.tgz", + "integrity": "sha512-Xa4Nw17FS9ApQFJ9umLiJS4orGjm7ZzwUrwamcGQuHSzDyth9boKDaycYdDcZDuqYATXw4HFXgaqWTctW/v1HA==", + "dev": true, + "dependencies": { + "lru-cache": "^10.2.0", + "minipass": "^5.0.0 || ^6.0.2 || ^7.0.0" + }, + "engines": { + "node": ">=16 || 14 >=14.18" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/path-scurry/node_modules/lru-cache": { + "version": "10.4.3", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-10.4.3.tgz", + "integrity": "sha512-JNAzZcXrCt42VGLuYz0zfAzDfAvJWW6AfYlDBQyDV5DClI2m5sAmK+OIO7s59XfsRsWHp02jAJrRadPRGTt6SQ==", + "dev": true + }, + "node_modules/path-type": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/path-type/-/path-type-2.0.0.tgz", + "integrity": "sha1-8BLMuEFbcJb8LaoQVMPXI4lZTHM=", + "dev": true, + "dependencies": { + "pify": "^2.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/pause-stream": { + "version": "0.0.11", + "resolved": "https://registry.npmjs.org/pause-stream/-/pause-stream-0.0.11.tgz", + "integrity": "sha1-/lo0sMvOErWqaitAPuLnO2AvFEU=", + "dependencies": { + "through": "~2.3" + } + }, + "node_modules/picocolors": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.1.1.tgz", + "integrity": "sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==", + "dev": true + }, + "node_modules/pify": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz", + "integrity": "sha1-7RQaasBDqEnqWISY59yosVMw6Qw=", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/pinkie": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/pinkie/-/pinkie-1.0.0.tgz", + "integrity": "sha1-Wkfyi6EBXQIBvae/DzWOR77Ix+Q=", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/pkg-conf": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/pkg-conf/-/pkg-conf-3.1.0.tgz", + "integrity": "sha512-m0OTbR/5VPNPqO1ph6Fqbj7Hv6QU7gR/tQW40ZqrL1rjgCU85W6C1bJn0BItuJqnR98PWzw7Z8hHeChD1WrgdQ==", + "dev": true, + "dependencies": { + "find-up": "^3.0.0", + "load-json-file": "^5.2.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/pkg-conf/node_modules/find-up": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-3.0.0.tgz", + "integrity": "sha512-1yD6RmLI1XBfxugvORwlck6f75tYL+iR0jqwsOrOxMZyGYqUuDhJ0l4AXdO1iX/FTs9cBAMEk1gWSEx1kSbylg==", + "dev": true, + "dependencies": { + "locate-path": "^3.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/pkg-conf/node_modules/load-json-file": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/load-json-file/-/load-json-file-5.3.0.tgz", + "integrity": "sha512-cJGP40Jc/VXUsp8/OrnyKyTZ1y6v/dphm3bioS+RrKXjK2BB6wHUd6JptZEFDGgGahMT+InnZO5i1Ei9mpC8Bw==", + "dev": true, + "dependencies": { + "graceful-fs": "^4.1.15", + "parse-json": "^4.0.0", + "pify": "^4.0.1", + "strip-bom": "^3.0.0", + "type-fest": "^0.3.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/pkg-conf/node_modules/locate-path": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-3.0.0.tgz", + "integrity": "sha512-7AO748wWnIhNqAuaty2ZWHkQHRSNfPVIsPIfwEOWO22AmaoVrWavlOcMR5nzTLNYvp36X220/maaRsrec1G65A==", + "dev": true, + "dependencies": { + "p-locate": "^3.0.0", + "path-exists": "^3.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/pkg-conf/node_modules/p-limit": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", + "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", + "dev": true, + "dependencies": { + "p-try": "^2.0.0" + }, + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/pkg-conf/node_modules/p-locate": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-3.0.0.tgz", + "integrity": "sha512-x+12w/To+4GFfgJhBEpiDcLozRJGegY+Ei7/z0tSLkMmxGZNybVMSfWj9aJn8Z5Fc7dBUNJOOVgPv2H7IwulSQ==", + "dev": true, + "dependencies": { + "p-limit": "^2.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/pkg-conf/node_modules/p-try": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz", + "integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/pkg-conf/node_modules/parse-json": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-4.0.0.tgz", + "integrity": "sha1-vjX1Qlvh9/bHRxhPmKeIy5lHfuA=", + "dev": true, + "dependencies": { + "error-ex": "^1.3.1", + "json-parse-better-errors": "^1.0.1" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/pkg-conf/node_modules/pify": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/pify/-/pify-4.0.1.tgz", + "integrity": "sha512-uB80kBFb/tfd68bVleG9T5GGsGPjJrLAUpR5PZIrhBnIaRTQRjqdJSsIKkOP6OAIFbj7GOrcudc5pNjZ+geV2g==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/pkg-conf/node_modules/type-fest": { + "version": "0.3.1", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.3.1.tgz", + "integrity": "sha512-cUGJnCdr4STbePCgqNFbpVNCepa+kAVohJs1sLhxzdH+gnEoOd8VhbYa7pD3zZYGiURWM2xzEII3fQcRizDkYQ==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/pkg-config": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/pkg-config/-/pkg-config-1.1.1.tgz", + "integrity": "sha1-VX7yLXPaPIg3EHdmxS6tq94pj+Q=", + "dev": true, + "dependencies": { + "debug-log": "^1.0.0", + "find-root": "^1.0.0", + "xtend": "^4.0.1" + }, + "engines": { + "node": ">=0.10" + } + }, + "node_modules/pkg-dir": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-2.0.0.tgz", + "integrity": "sha1-9tXREJ4Z1j7fQo4L1X4Sd3YVM0s=", + "dev": true, + "dependencies": { + "find-up": "^2.1.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/prelude-ls": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.1.2.tgz", + "integrity": "sha1-IZMqVJ9eUv/ZqCf1cOBL5iqX2lQ=", + "dev": true, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/progress": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/progress/-/progress-2.0.3.tgz", + "integrity": "sha512-7PiHtLll5LdnKIMw100I+8xJXR5gW2QwWYkT6iJva0bXitZKa/XMrSbdmg3r2Xnaidz9Qumd0VPaMrZlF9V9sA==", + "dev": true, + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/prop-types": { + "version": "15.7.2", + "resolved": "https://registry.npmjs.org/prop-types/-/prop-types-15.7.2.tgz", + "integrity": "sha512-8QQikdH7//R2vurIJSutZ1smHYTcLpRWEOlHnzcWHmBYrOGUysKwSsrC89BCiFj3CbrfJ/nXFdJepOVrY1GCHQ==", + "dev": true, + "dependencies": { + "loose-envify": "^1.4.0", + "object-assign": "^4.1.1", + "react-is": "^16.8.1" + } + }, + "node_modules/pseudomap": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/pseudomap/-/pseudomap-1.0.2.tgz", + "integrity": "sha1-8FKijacOYYkX7wqKw0wa5aaChrM=", + "dev": true + }, + "node_modules/punycode": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.1.1.tgz", + "integrity": "sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A==", + "engines": { + "node": ">=6" + } + }, + "node_modules/randombytes": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/randombytes/-/randombytes-2.1.0.tgz", + "integrity": "sha512-vYl3iOX+4CKUWuxGi9Ukhie6fsqXqS9FE2Zaic4tNFD2N2QQaXOMFbuKK4QmDHC0JO6B1Zp41J0LpT0oR68amQ==", + "dev": true, + "dependencies": { + "safe-buffer": "^5.1.0" + } + }, + "node_modules/rc": { + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/rc/-/rc-1.2.8.tgz", + "integrity": "sha512-y3bGgqKj3QBdxLbLkomlohkvsA8gdAiUQlSBJnBhfn+BPxg4bc62d8TcBW15wavDfgexCgccckhcZvywyQYPOw==", + "dev": true, + "dependencies": { + "deep-extend": "^0.6.0", + "ini": "~1.3.0", + "minimist": "^1.2.0", + "strip-json-comments": "~2.0.1" + }, + "bin": { + "rc": "cli.js" + } + }, + "node_modules/react-is": { + "version": "16.13.1", + "resolved": "https://registry.npmjs.org/react-is/-/react-is-16.13.1.tgz", + "integrity": "sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==", + "dev": true + }, + "node_modules/read-pkg": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-2.0.0.tgz", + "integrity": "sha1-jvHAYjxqbbDcZxPEv6xGMysjaPg=", + "dev": true, + "dependencies": { + "load-json-file": "^2.0.0", + "normalize-package-data": "^2.3.2", + "path-type": "^2.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/read-pkg-up": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/read-pkg-up/-/read-pkg-up-2.0.0.tgz", + "integrity": "sha1-a3KoBImE4MQeeVEP1en6mbO1Sb4=", + "dev": true, + "dependencies": { + "find-up": "^2.0.0", + "read-pkg": "^2.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/readdirp": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-4.1.2.tgz", + "integrity": "sha512-GDhwkLfywWL2s6vEjyhri+eXmfH6j1L7JE27WhqLeYzoh/A3DBaYGEj2H/HFZCn/kMfim73FXxEJTw06WtxQwg==", + "dev": true, + "engines": { + "node": ">= 14.18.0" + }, + "funding": { + "type": "individual", + "url": "https://paulmillr.com/funding/" + } + }, + "node_modules/regexp.prototype.flags": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/regexp.prototype.flags/-/regexp.prototype.flags-1.3.1.tgz", + "integrity": "sha512-JiBdRBq91WlY7uRJ0ds7R+dU02i6LKi8r3BuQhNXn+kmeLN+EfHhfjqMRis1zJxnlu88hq/4dx0P2OP3APRTOA==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2", + "define-properties": "^1.1.3" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/regexpp": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/regexpp/-/regexpp-3.1.0.tgz", + "integrity": "sha512-ZOIzd8yVsQQA7j8GCSlPGXwg5PfmA1mrq0JP4nGhh54LaKN3xdai/vHUDu74pKwV8OxseMS65u2NImosQcSD0Q==", + "dev": true, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/mysticatea" + } + }, + "node_modules/require-directory": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz", + "integrity": "sha1-jGStX9MNqxyXbiNE/+f3kqam30I=", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/resolve": { + "version": "1.1.7", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.1.7.tgz", + "integrity": "sha1-IDEU2CrSxe2ejgQRs5ModeiJ6Xs=", + "dev": true + }, + "node_modules/resolve-from": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz", + "integrity": "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/rimraf": { + "version": "2.6.3", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.6.3.tgz", + "integrity": "sha512-mwqeW5XsA2qAejG46gYdENaxXjx9onRNCfn7L0duuP4hCuTIi/QO7PDK07KJfp1d+izWPrzEJDcSqBa0OZQriA==", + "dev": true, + "dependencies": { + "glob": "^7.1.3" + }, + "bin": { + "rimraf": "bin.js" + } + }, + "node_modules/rimraf/node_modules/glob": { + "version": "7.1.6", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.6.tgz", + "integrity": "sha512-LwaxwyZ72Lk7vZINtNNrywX0ZuLyStrdDtabefZKAY5ZGJhVtgdznluResxNmPitE0SAO+O26sWTHeKSI2wMBA==", + "dev": true, + "dependencies": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.0.4", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + }, + "engines": { + "node": "*" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/safe-buffer": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", + "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ] + }, + "node_modules/semver": { + "version": "7.3.4", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.4.tgz", + "integrity": "sha512-tCfb2WLjqFAtXn4KEdxIhalnRtoKFN7nAwj0B3ZXCbQloV2tq5eDbcTmT68JJD3nRJq24/XgxtQKFIpQdtvmVw==", + "dev": true, + "dependencies": { + "lru-cache": "^6.0.0" + }, + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/semver/node_modules/lru-cache": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", + "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", + "dev": true, + "dependencies": { + "yallist": "^4.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/semver/node_modules/yallist": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", + "dev": true + }, + "node_modules/serialize-javascript": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-6.0.2.tgz", + "integrity": "sha512-Saa1xPByTTq2gdeFZYLLo+RFE35NHZkAbqZeWNd3BpzppeVisAqpDjcp8dyf6uIvEqJRd46jemmyA4iFIeVk8g==", + "dev": true, + "dependencies": { + "randombytes": "^2.1.0" + } + }, + "node_modules/shebang-command": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", + "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", + "dev": true, + "dependencies": { + "shebang-regex": "^3.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/shebang-regex": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz", + "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/should": { + "version": "13.2.3", + "resolved": "https://registry.npmjs.org/should/-/should-13.2.3.tgz", + "integrity": "sha512-ggLesLtu2xp+ZxI+ysJTmNjh2U0TsC+rQ/pfED9bUZZ4DKefP27D+7YJVVTvKsmjLpIi9jAa7itwDGkDDmt1GQ==", + "dev": true, + "dependencies": { + "should-equal": "^2.0.0", + "should-format": "^3.0.3", + "should-type": "^1.4.0", + "should-type-adaptors": "^1.0.1", + "should-util": "^1.0.0" + } + }, + "node_modules/should-equal": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/should-equal/-/should-equal-2.0.0.tgz", + "integrity": "sha512-ZP36TMrK9euEuWQYBig9W55WPC7uo37qzAEmbjHz4gfyuXrEUgF8cUvQVO+w+d3OMfPvSRQJ22lSm8MQJ43LTA==", + "dev": true, + "dependencies": { + "should-type": "^1.4.0" + } + }, + "node_modules/should-format": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/should-format/-/should-format-3.0.3.tgz", + "integrity": "sha1-m/yPdPo5IFxT04w01xcwPidxJPE=", + "dev": true, + "dependencies": { + "should-type": "^1.3.0", + "should-type-adaptors": "^1.0.1" + } + }, + "node_modules/should-type": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/should-type/-/should-type-1.4.0.tgz", + "integrity": "sha1-B1bYzoRt/QmEOmlHcZ36DUz/XPM=", + "dev": true + }, + "node_modules/should-type-adaptors": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/should-type-adaptors/-/should-type-adaptors-1.1.0.tgz", + "integrity": "sha512-JA4hdoLnN+kebEp2Vs8eBe9g7uy0zbRo+RMcU0EsNy+R+k049Ki+N5tT5Jagst2g7EAja+euFuoXFCa8vIklfA==", + "dev": true, + "dependencies": { + "should-type": "^1.3.0", + "should-util": "^1.0.0" + } + }, + "node_modules/should-util": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/should-util/-/should-util-1.0.0.tgz", + "integrity": "sha1-yYzaN0qmsZDfi6h8mInCtNtiAGM=", + "dev": true + }, + "node_modules/side-channel": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.0.4.tgz", + "integrity": "sha512-q5XPytqFEIKHkGdiMIrY10mvLRvnQh42/+GoBlFW3b2LXLE2xxJpZFdm94we0BaoV3RwJyGqg5wS7epxTv0Zvw==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.0", + "get-intrinsic": "^1.0.2", + "object-inspect": "^1.9.0" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/side-channel/node_modules/object-inspect": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.9.0.tgz", + "integrity": "sha512-i3Bp9iTqwhaLZBxGkRfo5ZbE07BQRT7MGu8+nNgwW9ItGp1TzCTw2DLEoWwjClxBjOFI/hWljTAmYGCEwmtnOw==", + "dev": true, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/sigmund": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/sigmund/-/sigmund-1.0.1.tgz", + "integrity": "sha1-P/IfGYytIXX587eBhT/ZTQ0ZtZA=", + "dev": true + }, + "node_modules/signal-exit": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-4.1.0.tgz", + "integrity": "sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==", + "dev": true, + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/slice-ansi": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/slice-ansi/-/slice-ansi-2.1.0.tgz", + "integrity": "sha512-Qu+VC3EwYLldKa1fCxuuvULvSJOKEgk9pi8dZeCVK7TqBfUNTH4sFkk4joj8afVSfAYgJoSOetjx9QWOJ5mYoQ==", + "dev": true, + "dependencies": { + "ansi-styles": "^3.2.0", + "astral-regex": "^1.0.0", + "is-fullwidth-code-point": "^2.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/slice-ansi/node_modules/ansi-styles": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", + "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", + "dev": true, + "dependencies": { + "color-convert": "^1.9.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/source-map": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.2.0.tgz", + "integrity": "sha1-2rc/vPwrqBm03gO9b26qSBZLP50=", + "dev": true, + "optional": true, + "dependencies": { + "amdefine": ">=0.0.4" + }, + "engines": { + "node": ">=0.8.0" + } + }, + "node_modules/spdx-correct": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/spdx-correct/-/spdx-correct-3.1.1.tgz", + "integrity": "sha512-cOYcUWwhCuHCXi49RhFRCyJEK3iPj1Ziz9DpViV3tbZOwXD49QzIN3MpOLJNxh2qwq2lJJZaKMVw9qNi4jTC0w==", + "dev": true, + "dependencies": { + "spdx-expression-parse": "^3.0.0", + "spdx-license-ids": "^3.0.0" + } + }, + "node_modules/spdx-exceptions": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/spdx-exceptions/-/spdx-exceptions-2.3.0.tgz", + "integrity": "sha512-/tTrYOC7PPI1nUAgx34hUpqXuyJG+DTHJTnIULG4rDygi4xu/tfgmq1e1cIRwRzwZgo4NLySi+ricLkZkw4i5A==", + "dev": true + }, + "node_modules/spdx-expression-parse": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/spdx-expression-parse/-/spdx-expression-parse-3.0.1.tgz", + "integrity": "sha512-cbqHunsQWnJNE6KhVSMsMeH5H/L9EpymbzqTQ3uLwNCLZ1Q481oWaofqH7nO6V07xlXwY6PhQdQ2IedWx/ZK4Q==", + "dev": true, + "dependencies": { + "spdx-exceptions": "^2.1.0", + "spdx-license-ids": "^3.0.0" + } + }, + "node_modules/spdx-license-ids": { + "version": "3.0.7", + "resolved": "https://registry.npmjs.org/spdx-license-ids/-/spdx-license-ids-3.0.7.tgz", + "integrity": "sha512-U+MTEOO0AiDzxwFvoa4JVnMV6mZlJKk2sBLt90s7G0Gd0Mlknc7kxEn3nuDPNZRta7O2uy8oLcZLVT+4sqNZHQ==", + "dev": true + }, + "node_modules/split": { + "version": "0.3.3", + "resolved": "https://registry.npmjs.org/split/-/split-0.3.3.tgz", + "integrity": "sha1-zQ7qXmOiEd//frDwkcQTPi0N0o8=", + "dependencies": { + "through": "2" + }, + "engines": { + "node": "*" + } + }, + "node_modules/sprintf-js": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz", + "integrity": "sha1-BOaSb2YolTVPPdAVIDYzuFcpfiw=", + "dev": true + }, + "node_modules/standard": { + "version": "16.0.3", + "resolved": "https://registry.npmjs.org/standard/-/standard-16.0.3.tgz", + "integrity": "sha512-70F7NH0hSkNXosXRltjSv6KpTAOkUkSfyu3ynyM5dtRUiLtR+yX9EGZ7RKwuGUqCJiX/cnkceVM6HTZ4JpaqDg==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "dependencies": { + "eslint": "~7.13.0", + "eslint-config-standard": "16.0.2", + "eslint-config-standard-jsx": "10.0.0", + "eslint-plugin-import": "~2.22.1", + "eslint-plugin-node": "~11.1.0", + "eslint-plugin-promise": "~4.2.1", + "eslint-plugin-react": "~7.21.5", + "standard-engine": "^14.0.1" + }, + "bin": { + "standard": "bin/cmd.js" + }, + "engines": { + "node": "^10.12.0 || >=12.0.0" + } + }, + "node_modules/standard-engine": { + "version": "14.0.1", + "resolved": "https://registry.npmjs.org/standard-engine/-/standard-engine-14.0.1.tgz", + "integrity": "sha512-7FEzDwmHDOGva7r9ifOzD3BGdTbA7ujJ50afLVdW/tK14zQEptJjbFuUfn50irqdHDcTbNh0DTIoMPynMCXb0Q==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "dependencies": { + "get-stdin": "^8.0.0", + "minimist": "^1.2.5", + "pkg-conf": "^3.1.0", + "xdg-basedir": "^4.0.0" + }, + "engines": { + "node": ">=8.10" + } + }, + "node_modules/standard-engine/node_modules/minimist": { + "version": "1.2.5", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.5.tgz", + "integrity": "sha512-FM9nNUYrRBAELZQT3xeZQ7fmMOBg6nWNmJKTcgsJeaLstP/UODVpGsr5OhXhhXg6f+qtJ8uiZ+PUxkDWcgIXLw==", + "dev": true + }, + "node_modules/stream-combiner": { + "version": "0.0.4", + "resolved": "https://registry.npmjs.org/stream-combiner/-/stream-combiner-0.0.4.tgz", + "integrity": "sha1-TV5DPBhSYd3mI8o/RMWGvPXErRQ=", + "dependencies": { + "duplexer": "~0.1.1" + } + }, + "node_modules/string-width": { + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "dev": true, + "dependencies": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/string-width-cjs": { + "name": "string-width", + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "dev": true, + "dependencies": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/string-width-cjs/node_modules/ansi-regex": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/string-width-cjs/node_modules/emoji-regex": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", + "dev": true + }, + "node_modules/string-width-cjs/node_modules/is-fullwidth-code-point": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", + "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/string-width-cjs/node_modules/strip-ansi": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "dev": true, + "dependencies": { + "ansi-regex": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/string-width/node_modules/ansi-regex": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/string-width/node_modules/emoji-regex": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", + "dev": true + }, + "node_modules/string-width/node_modules/is-fullwidth-code-point": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", + "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/string-width/node_modules/strip-ansi": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "dev": true, + "dependencies": { + "ansi-regex": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/string.prototype.matchall": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/string.prototype.matchall/-/string.prototype.matchall-4.0.3.tgz", + "integrity": "sha512-OBxYDA2ifZQ2e13cP82dWFMaCV9CGF8GzmN4fljBVw5O5wep0lu4gacm1OL6MjROoUnB8VbkWRThqkV2YFLNxw==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.0", + "define-properties": "^1.1.3", + "es-abstract": "^1.18.0-next.1", + "has-symbols": "^1.0.1", + "internal-slot": "^1.0.2", + "regexp.prototype.flags": "^1.3.0", + "side-channel": "^1.0.3" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/strip-ansi": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", + "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=", + "dependencies": { + "ansi-regex": "^2.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/strip-ansi-cjs": { + "name": "strip-ansi", + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "dev": true, + "dependencies": { + "ansi-regex": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/strip-ansi-cjs/node_modules/ansi-regex": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/strip-bom": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-3.0.0.tgz", + "integrity": "sha1-IzTBjpx1n3vdVv3vfprj1YjmjtM=", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/strip-json-comments": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-2.0.1.tgz", + "integrity": "sha1-PFMZQukIwml8DsNEhYwobHygpgo=", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/supports-color": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-2.0.0.tgz", + "integrity": "sha1-U10EXOa2Nj+kARcIRimZXp3zJMc=", + "engines": { + "node": ">=0.8.0" + } + }, + "node_modules/table": { + "version": "5.4.6", + "resolved": "https://registry.npmjs.org/table/-/table-5.4.6.tgz", + "integrity": "sha512-wmEc8m4fjnob4gt5riFRtTu/6+4rSe12TpAELNSqHMfF3IqnA+CH37USM6/YR3qRZv7e56kAEAtd6nKZaxe0Ug==", + "dev": true, + "dependencies": { + "ajv": "^6.10.2", + "lodash": "^4.17.14", + "slice-ansi": "^2.1.0", + "string-width": "^3.0.0" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/table/node_modules/ansi-regex": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-4.1.0.tgz", + "integrity": "sha512-1apePfXM1UOSqw0o9IiFAovVz9M5S1Dg+4TrDwfMewQ6p/rmMueb7tWZjQ1rx4Loy1ArBggoqGpfqqdI4rondg==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/table/node_modules/string-width": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-3.1.0.tgz", + "integrity": "sha512-vafcv6KjVZKSgz06oM/H6GDBrAtz8vdhQakGjFIvNrHA6y3HCF1CInLy+QLq8dTJPQ1b+KDUqDFctkdRW44e1w==", + "dev": true, + "dependencies": { + "emoji-regex": "^7.0.1", + "is-fullwidth-code-point": "^2.0.0", + "strip-ansi": "^5.1.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/table/node_modules/strip-ansi": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-5.2.0.tgz", + "integrity": "sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA==", + "dev": true, + "dependencies": { + "ansi-regex": "^4.1.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/text-table": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz", + "integrity": "sha1-f17oI66AUgfACvLfSoTsP8+lcLQ=", + "dev": true + }, + "node_modules/through": { + "version": "2.3.8", + "resolved": "https://registry.npmjs.org/through/-/through-2.3.8.tgz", + "integrity": "sha1-DdTJ/6q8NXlgsbckEV1+Doai4fU=" + }, + "node_modules/tsconfig-paths": { + "version": "3.9.0", + "resolved": "https://registry.npmjs.org/tsconfig-paths/-/tsconfig-paths-3.9.0.tgz", + "integrity": "sha512-dRcuzokWhajtZWkQsDVKbWyY+jgcLC5sqJhg2PSgf4ZkH2aHPvaOY8YWGhmjb68b5qqTfasSsDO9k7RUiEmZAw==", + "dev": true, + "dependencies": { + "@types/json5": "^0.0.29", + "json5": "^1.0.1", + "minimist": "^1.2.0", + "strip-bom": "^3.0.0" + } + }, + "node_modules/type-check": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.3.2.tgz", + "integrity": "sha1-WITKtRLPHTVeP7eE8wgEsrUg23I=", + "dev": true, + "dependencies": { + "prelude-ls": "~1.1.2" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/type-fest": { + "version": "0.8.1", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.8.1.tgz", + "integrity": "sha512-4dbzIzqvjtgiM5rw1k5rEHtBANKmdudhGyBEajN01fEyhaAIhsoKNy6y7+IN93IfpFtwY9iqi7kD+xwKhQsNJA==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/uglify-js": { + "version": "3.5.8", + "resolved": "https://registry.npmjs.org/uglify-js/-/uglify-js-3.5.8.tgz", + "integrity": "sha512-GFSjB1nZIzoIq70qvDRtWRORHX3vFkAnyK/rDExc0BN7r9+/S+Voz3t/fwJuVfjppAMz+ceR2poE7tkhvnVwQQ==", + "dev": true, + "optional": true, + "dependencies": { + "commander": "~2.20.0", + "source-map": "~0.6.1" + }, + "bin": { + "uglifyjs": "bin/uglifyjs" + }, + "engines": { + "node": ">=0.8.0" + } + }, + "node_modules/uglify-js/node_modules/source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true, + "optional": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/uri-js": { + "version": "4.2.2", + "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.2.2.tgz", + "integrity": "sha512-KY9Frmirql91X2Qgjry0Wd4Y+YTdrdZheS8TFwvkbLWf/G5KNJDCh6pKL5OZctEW4+0Baa5idK2ZQuELRwPznQ==", + "dependencies": { + "punycode": "^2.1.0" + } + }, + "node_modules/v8-compile-cache": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/v8-compile-cache/-/v8-compile-cache-2.2.0.tgz", + "integrity": "sha512-gTpR5XQNKFwOd4clxfnhaqvfqMpqEwr4tOtCyz4MtYZX2JYhfr1JvBFKdS+7K/9rfpZR3VLX+YWBbKoxCgS43Q==", + "dev": true + }, + "node_modules/validate-npm-package-license": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/validate-npm-package-license/-/validate-npm-package-license-3.0.4.tgz", + "integrity": "sha512-DpKm2Ui/xN7/HQKCtpZxoRWBhZ9Z0kqtygG8XCgNQ8ZlDnxuQmWhj566j8fN4Cu3/JmbhsDo7fcAJq4s9h27Ew==", + "dev": true, + "dependencies": { + "spdx-correct": "^3.0.0", + "spdx-expression-parse": "^3.0.0" + } + }, + "node_modules/which": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/which/-/which-1.3.1.tgz", + "integrity": "sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ==", + "dev": true, + "dependencies": { + "isexe": "^2.0.0" + }, + "bin": { + "which": "bin/which" + } + }, + "node_modules/word-wrap": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/word-wrap/-/word-wrap-1.2.3.tgz", + "integrity": "sha512-Hz/mrNwitNRh/HUAtM/VT/5VH+ygD6DV7mYKZAtHOrbs8U7lvPS6xf7EJKMF0uW1KJCl0H701g3ZGus+muE5vQ==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/wordwrap": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/wordwrap/-/wordwrap-1.0.0.tgz", + "integrity": "sha1-J1hIEIkUVqQXHI0CJkQa3pDLyus=", + "dev": true + }, + "node_modules/workerpool": { + "version": "9.3.4", + "resolved": "https://registry.npmjs.org/workerpool/-/workerpool-9.3.4.tgz", + "integrity": "sha512-TmPRQYYSAnnDiEB0P/Ytip7bFGvqnSU6I2BcuSw7Hx+JSg/DsUi5ebYfc8GYaSdpuvOcEs6dXxPurOYpe9QFwg==", + "dev": true + }, + "node_modules/wrap-ansi": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", + "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", + "dev": true, + "dependencies": { + "ansi-styles": "^4.0.0", + "string-width": "^4.1.0", + "strip-ansi": "^6.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/wrap-ansi?sponsor=1" + } + }, + "node_modules/wrap-ansi-cjs": { + "name": "wrap-ansi", + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", + "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", + "dev": true, + "dependencies": { + "ansi-styles": "^4.0.0", + "string-width": "^4.1.0", + "strip-ansi": "^6.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/wrap-ansi?sponsor=1" + } + }, + "node_modules/wrap-ansi-cjs/node_modules/ansi-regex": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/wrap-ansi-cjs/node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/wrap-ansi-cjs/node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/wrap-ansi-cjs/node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true + }, + "node_modules/wrap-ansi-cjs/node_modules/strip-ansi": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "dev": true, + "dependencies": { + "ansi-regex": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/wrap-ansi/node_modules/ansi-regex": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/wrap-ansi/node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/wrap-ansi/node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/wrap-ansi/node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true + }, + "node_modules/wrap-ansi/node_modules/strip-ansi": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "dev": true, + "dependencies": { + "ansi-regex": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/wrappy": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", + "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=", + "dev": true + }, + "node_modules/write": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/write/-/write-1.0.3.tgz", + "integrity": "sha512-/lg70HAjtkUgWPVZhZcm+T4hkL8Zbtp1nFNOn3lRrxnlv50SRBv7cR7RqR+GMsd3hUXy9hWBo4CHTbFTcOYwig==", + "dev": true, + "dependencies": { + "mkdirp": "^0.5.1" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/xdg-basedir": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/xdg-basedir/-/xdg-basedir-4.0.0.tgz", + "integrity": "sha512-PSNhEJDejZYV7h50BohL09Er9VaIefr2LMAf3OEmpCkjOi34eYyQYAXUTjEQtZJTKcF0E2UKTh+osDLsgNim9Q==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/xtend": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.1.tgz", + "integrity": "sha1-pcbVMr5lbiPbgg77lDofBJmNY68=", + "dev": true, + "engines": { + "node": ">=0.4" + } + }, + "node_modules/y18n": { + "version": "5.0.8", + "resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz", + "integrity": "sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==", + "dev": true, + "engines": { + "node": ">=10" + } + }, + "node_modules/yallist": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-2.1.2.tgz", + "integrity": "sha1-HBH5IY8HYImkfdUS+TxmmaaoHVI=", + "dev": true + }, + "node_modules/yargs": { + "version": "17.7.2", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-17.7.2.tgz", + "integrity": "sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w==", + "dev": true, + "dependencies": { + "cliui": "^8.0.1", + "escalade": "^3.1.1", + "get-caller-file": "^2.0.5", + "require-directory": "^2.1.1", + "string-width": "^4.2.3", + "y18n": "^5.0.5", + "yargs-parser": "^21.1.1" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/yargs-parser": { + "version": "21.1.1", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-21.1.1.tgz", + "integrity": "sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw==", + "dev": true, + "engines": { + "node": ">=12" + } + }, + "node_modules/yargs-unparser": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/yargs-unparser/-/yargs-unparser-2.0.0.tgz", + "integrity": "sha512-7pRTIA9Qc1caZ0bZ6RYRGbHJthJWuakf+WmHK0rVeLkNrrGhfoabBNdue6kdINI6r4if7ocq9aD/n7xwKOdzOA==", + "dev": true, + "dependencies": { + "camelcase": "^6.0.0", + "decamelize": "^4.0.0", + "flat": "^5.0.2", + "is-plain-obj": "^2.1.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/yargs-unparser/node_modules/camelcase": { + "version": "6.2.0", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-6.2.0.tgz", + "integrity": "sha512-c7wVvbw3f37nuobQNtgsgG9POC9qMbNuMQmTCqZv23b6MIz0fcYpBiOlv9gEN/hdLdnZTDQhg6e9Dq5M1vKvfg==", + "dev": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/yargs-unparser/node_modules/decamelize": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-4.0.0.tgz", + "integrity": "sha512-9iE1PgSik9HeIIw2JO94IidnE3eBoQrFJ3w7sFuzSX4DpmZ3v5sZpUiV5Swcf6mQEF+Y0ru8Neo+p+nyh2J+hQ==", + "dev": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/yocto-queue": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz", + "integrity": "sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==", + "dev": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + } + }, "dependencies": { "@babel/code-frame": { "version": "7.12.11", @@ -85,18 +4741,6 @@ "strip-json-comments": "^3.1.1" }, "dependencies": { - "ajv": { - "version": "6.12.6", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", - "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", - "dev": true, - "requires": { - "fast-deep-equal": "^3.1.1", - "fast-json-stable-stringify": "^2.0.0", - "json-schema-traverse": "^0.4.1", - "uri-js": "^4.2.2" - } - }, "debug": { "version": "4.3.1", "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.1.tgz", @@ -106,12 +4750,6 @@ "ms": "2.1.2" } }, - "fast-deep-equal": { - "version": "3.1.3", - "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", - "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==", - "dev": true - }, "ms": { "version": "2.1.2", "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", @@ -126,18 +4764,84 @@ } } }, + "@isaacs/cliui": { + "version": "8.0.2", + "resolved": "https://registry.npmjs.org/@isaacs/cliui/-/cliui-8.0.2.tgz", + "integrity": "sha512-O8jcjabXaleOG9DQ0+ARXWZBTfnP4WNAqzuiJK7ll44AmxGKv/J2M4TPjxjY3znBCfvBXFzucm1twdyFybFqEA==", + "dev": true, + "requires": { + "string-width": "^5.1.2", + "string-width-cjs": "npm:string-width@^4.2.0", + "strip-ansi": "^7.0.1", + "strip-ansi-cjs": "npm:strip-ansi@^6.0.1", + "wrap-ansi": "^8.1.0", + "wrap-ansi-cjs": "npm:wrap-ansi@^7.0.0" + }, + "dependencies": { + "ansi-regex": { + "version": "6.2.2", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.2.2.tgz", + "integrity": "sha512-Bq3SmSpyFHaWjPk8If9yc6svM8c56dB5BAtW4Qbw5jHTwwXXcTLoRMkpDJp6VL0XzlWaCHTXrkFURMYmD0sLqg==", + "dev": true + }, + "ansi-styles": { + "version": "6.2.3", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-6.2.3.tgz", + "integrity": "sha512-4Dj6M28JB+oAH8kFkTLUo+a2jwOFkuqb3yucU0CANcRRUbxS0cP0nZYCGjcc3BNXwRIsUVmDGgzawme7zvJHvg==", + "dev": true + }, + "emoji-regex": { + "version": "9.2.2", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-9.2.2.tgz", + "integrity": "sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==", + "dev": true + }, + "string-width": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-5.1.2.tgz", + "integrity": "sha512-HnLOCR3vjcY8beoNLtcjZ5/nxn2afmME6lhrDrebokqMap+XbeW8n9TXpPDOqdGK5qcI3oT0GKTW6wC7EMiVqA==", + "dev": true, + "requires": { + "eastasianwidth": "^0.2.0", + "emoji-regex": "^9.2.2", + "strip-ansi": "^7.0.1" + } + }, + "strip-ansi": { + "version": "7.1.2", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.1.2.tgz", + "integrity": "sha512-gmBGslpoQJtgnMAvOVqGZpEz9dyoKTCzy2nfz/n8aIFhN/jCE/rCmcxabB6jOOHV+0WNnylOxaxBQPSvcWklhA==", + "dev": true, + "requires": { + "ansi-regex": "^6.0.1" + } + }, + "wrap-ansi": { + "version": "8.1.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-8.1.0.tgz", + "integrity": "sha512-si7QWI6zUMq56bESFvagtmzMdGOtoxfR+Sez11Mobfc7tm+VkUckk9bW2UeffTGVUbOksxmSw0AA2gs8g71NCQ==", + "dev": true, + "requires": { + "ansi-styles": "^6.1.0", + "string-width": "^5.0.1", + "strip-ansi": "^7.0.1" + } + } + } + }, + "@pkgjs/parseargs": { + "version": "0.11.0", + "resolved": "https://registry.npmjs.org/@pkgjs/parseargs/-/parseargs-0.11.0.tgz", + "integrity": "sha512-+1VkjdD0QBLPodGrJUeqarH8VAIvQODIbwh9XpP5Syisf7YoQgsJKPNFoqqLQlu+VQ/tVSshMR6loPMn8U+dPg==", + "dev": true, + "optional": true + }, "@types/json5": { "version": "0.0.29", "resolved": "https://registry.npmjs.org/@types/json5/-/json5-0.0.29.tgz", "integrity": "sha1-7ihweulOEdK4J7y+UnC86n8+ce4=", "dev": true }, - "@ungap/promise-all-settled": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/@ungap/promise-all-settled/-/promise-all-settled-1.1.2.tgz", - "integrity": "sha512-sL/cEvJWAnClXw0wHk85/2L0G6Sj8UB0Ctc1TEMbKSsmpRosqhwj9gWgFRZSrBr2f9tiXISwNhCPmlfqUqyb9Q==", - "dev": true - }, "abbrev": { "version": "1.0.9", "resolved": "https://registry.npmjs.org/abbrev/-/abbrev-1.0.9.tgz", @@ -154,14 +4858,15 @@ "version": "5.3.1", "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.3.1.tgz", "integrity": "sha512-K0Ptm/47OKfQRpNQ2J/oIN/3QYiK6FwW+eJbILhsdxh2WTLdl+30o8aGdTbm5JbffpFFAg/g+zi1E+jvJha5ng==", - "dev": true + "dev": true, + "requires": {} }, "ajv": { - "version": "6.10.0", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.10.0.tgz", - "integrity": "sha512-nffhOpkymDECQyR0mnsUtoCE8RlX38G0rYP+wgLWFyZuUyuuojSSvi/+euOiQBIn63whYwYVIIH1TvE3tu4OEg==", + "version": "6.12.6", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", + "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", "requires": { - "fast-deep-equal": "^2.0.1", + "fast-deep-equal": "^3.1.1", "fast-json-stable-stringify": "^2.0.0", "json-schema-traverse": "^0.4.1", "uri-js": "^4.2.2" @@ -190,16 +4895,6 @@ "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-2.2.1.tgz", "integrity": "sha1-tDLdM1i2NM914eRmQ2gkBTPB3b4=" }, - "anymatch": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.1.tgz", - "integrity": "sha512-mM8522psRCqzV+6LhomX5wgp25YVibjh8Wj23I5RPkPppSVSjyKD2A2mBJmWGa+KN7f2D6LNh9jkBCeyLktzjg==", - "dev": true, - "requires": { - "normalize-path": "^3.0.0", - "picomatch": "^2.0.4" - } - }, "argparse": { "version": "1.0.10", "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz", @@ -245,21 +4940,6 @@ "function-bind": "^1.1.1" } }, - "asn1": { - "version": "0.2.4", - "resolved": "https://registry.npmjs.org/asn1/-/asn1-0.2.4.tgz", - "integrity": "sha512-jxwzQpLQjSmWXgwaCZE9Nz+glAG01yF1QnWgbhGwHI5A6FRIEY6IVqtHhIepHqI7/kyEyQEagBC5mBEFlIYvdg==", - "dev": true, - "requires": { - "safer-buffer": "~2.1.0" - } - }, - "assert-plus": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz", - "integrity": "sha1-8S4PPF13sLHN2RRpQuTpbB5N1SU=", - "dev": true - }, "astral-regex": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/astral-regex/-/astral-regex-1.0.0.tgz", @@ -271,39 +4951,12 @@ "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", "integrity": "sha1-x57Zf380y48robyXkLzDZkdLS3k=" }, - "aws-sign2": { - "version": "0.7.0", - "resolved": "https://registry.npmjs.org/aws-sign2/-/aws-sign2-0.7.0.tgz", - "integrity": "sha1-tG6JCTSpWR8tL2+G1+ap8bP+dqg=", - "dev": true - }, - "aws4": { - "version": "1.8.0", - "resolved": "https://registry.npmjs.org/aws4/-/aws4-1.8.0.tgz", - "integrity": "sha512-ReZxvNHIOv88FlT7rxcXIIC0fPt4KZqZbOlivyWtXLt8ESx84zd3kMC6iK5jVeS2qt+g7ftS7ye4fi06X5rtRQ==", - "dev": true - }, "balanced-match": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.0.tgz", "integrity": "sha1-ibTRmasr7kneFk6gK4nORi1xt2c=", "dev": true }, - "bcrypt-pbkdf": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/bcrypt-pbkdf/-/bcrypt-pbkdf-1.0.2.tgz", - "integrity": "sha1-pDAdOJtqQ/m2f/PKEaP2Y342Dp4=", - "dev": true, - "requires": { - "tweetnacl": "^0.14.3" - } - }, - "binary-extensions": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.2.0.tgz", - "integrity": "sha512-jDctJ/IVQbZoJykoeHbhXpOlNBqGNcwXJKJog42E5HDPUwQTSdjCHdihjj0DlnheQ7blbT6dHOafNAiS8ooQKA==", - "dev": true - }, "brace-expansion": { "version": "1.1.11", "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", @@ -314,15 +4967,6 @@ "concat-map": "0.0.1" } }, - "braces": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz", - "integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==", - "dev": true, - "requires": { - "fill-range": "^7.0.1" - } - }, "browser-stdout": { "version": "1.3.1", "resolved": "https://registry.npmjs.org/browser-stdout/-/browser-stdout-1.3.1.tgz", @@ -339,24 +4983,21 @@ "get-intrinsic": "^1.0.2" } }, + "call-bind-apply-helpers": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/call-bind-apply-helpers/-/call-bind-apply-helpers-1.0.2.tgz", + "integrity": "sha512-Sp1ablJ0ivDkSzjcaJdxEunN5/XvksFJ2sMBFfq6x0ryhQV/2b/KwFe21cMpmHtPOSij8K99/wSfoEuTObmuMQ==", + "requires": { + "es-errors": "^1.3.0", + "function-bind": "^1.1.2" + } + }, "callsites": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz", "integrity": "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==", "dev": true }, - "camelcase": { - "version": "5.3.1", - "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-5.3.1.tgz", - "integrity": "sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==", - "dev": true - }, - "caseless": { - "version": "0.12.0", - "resolved": "https://registry.npmjs.org/caseless/-/caseless-0.12.0.tgz", - "integrity": "sha1-G2gcIf+EAzyCZUMJBolCDRhxUdw=", - "dev": true - }, "chalk": { "version": "1.1.3", "resolved": "https://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz", @@ -370,85 +5011,38 @@ } }, "chokidar": { - "version": "3.4.3", - "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.4.3.tgz", - "integrity": "sha512-DtM3g7juCXQxFVSNPNByEC2+NImtBuxQQvWlHunpJIS5Ocr0lG306cC7FCi7cEA0fzmybPUIl4txBIobk1gGOQ==", + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-4.0.3.tgz", + "integrity": "sha512-Qgzu8kfBvo+cA4962jnP1KkS6Dop5NS6g7R5LFYJr4b8Ub94PPQXUksCw9PvXoeXPRRddRNC5C1JQUR2SMGtnA==", "dev": true, "requires": { - "anymatch": "~3.1.1", - "braces": "~3.0.2", - "fsevents": "~2.1.2", - "glob-parent": "~5.1.0", - "is-binary-path": "~2.1.0", - "is-glob": "~4.0.1", - "normalize-path": "~3.0.0", - "readdirp": "~3.5.0" + "readdirp": "^4.0.1" } }, "cliui": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/cliui/-/cliui-5.0.0.tgz", - "integrity": "sha512-PYeGSEmmHM6zvoef2w8TPzlrnNpXIjTipYK780YswmIP9vjxmd6Y2a3CB2Ks6/AU8NHjZugXvo8w3oWM2qnwXA==", + "version": "8.0.1", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-8.0.1.tgz", + "integrity": "sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ==", "dev": true, "requires": { - "string-width": "^3.1.0", - "strip-ansi": "^5.2.0", - "wrap-ansi": "^5.1.0" + "string-width": "^4.2.0", + "strip-ansi": "^6.0.1", + "wrap-ansi": "^7.0.0" }, "dependencies": { "ansi-regex": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-4.1.0.tgz", - "integrity": "sha512-1apePfXM1UOSqw0o9IiFAovVz9M5S1Dg+4TrDwfMewQ6p/rmMueb7tWZjQ1rx4Loy1ArBggoqGpfqqdI4rondg==", + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", "dev": true }, - "string-width": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-3.1.0.tgz", - "integrity": "sha512-vafcv6KjVZKSgz06oM/H6GDBrAtz8vdhQakGjFIvNrHA6y3HCF1CInLy+QLq8dTJPQ1b+KDUqDFctkdRW44e1w==", - "dev": true, - "requires": { - "emoji-regex": "^7.0.1", - "is-fullwidth-code-point": "^2.0.0", - "strip-ansi": "^5.1.0" - } - }, "strip-ansi": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-5.2.0.tgz", - "integrity": "sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA==", - "dev": true, - "requires": { - "ansi-regex": "^4.1.0" - } - } - } - }, - "codeclimate-test-reporter": { - "version": "0.5.1", - "resolved": "https://registry.npmjs.org/codeclimate-test-reporter/-/codeclimate-test-reporter-0.5.1.tgz", - "integrity": "sha512-XCzmc8dH+R4orK11BCg5pBbXc35abxq9sept4YvUFRkFl9zb9MIVRrCKENe6U1TKAMTgvGJmrYyHn0y2lerpmg==", - "dev": true, - "requires": { - "async": "~1.5.2", - "commander": "2.9.0", - "lcov-parse": "0.0.10", - "request": "~2.88.0" - }, - "dependencies": { - "async": { - "version": "1.5.2", - "resolved": "https://registry.npmjs.org/async/-/async-1.5.2.tgz", - "integrity": "sha1-7GphrlZIDAw8skHJVhjiCJL5Zyo=", - "dev": true - }, - "commander": { - "version": "2.9.0", - "resolved": "https://registry.npmjs.org/commander/-/commander-2.9.0.tgz", - "integrity": "sha1-nJkJQXbhIkDLItbFFGCYQA/g99Q=", + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", "dev": true, "requires": { - "graceful-readlink": ">= 1.0.0" + "ansi-regex": "^5.0.1" } } } @@ -468,15 +5062,6 @@ "integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=", "dev": true }, - "combined-stream": { - "version": "1.0.7", - "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.7.tgz", - "integrity": "sha512-brWl9y6vOB1xYPZcpZde3N9zDByXTosAeMDo4p1wzo6UMOX4vumB+TP1RZ76sfE6Md68Q0NJSrE/gbezd4Ul+w==", - "dev": true, - "requires": { - "delayed-stream": "~1.0.0" - } - }, "commander": { "version": "2.20.0", "resolved": "https://registry.npmjs.org/commander/-/commander-2.20.0.tgz", @@ -491,19 +5076,13 @@ "contains-path": { "version": "0.1.0", "resolved": "https://registry.npmjs.org/contains-path/-/contains-path-0.1.0.tgz", - "integrity": "sha1-/ozxhP9mcLa67wGp1IYaXL7EEgo=", - "dev": true - }, - "core-util-is": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz", - "integrity": "sha1-tf1UIgqivFq1eqtxQMlAdUUDwac=", + "integrity": "sha1-/ozxhP9mcLa67wGp1IYaXL7EEgo=", "dev": true }, "cross-spawn": { - "version": "7.0.3", - "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz", - "integrity": "sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==", + "version": "7.0.6", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.6.tgz", + "integrity": "sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA==", "dev": true, "requires": { "path-key": "^3.1.0", @@ -522,15 +5101,6 @@ } } }, - "dashdash": { - "version": "1.14.1", - "resolved": "https://registry.npmjs.org/dashdash/-/dashdash-1.14.1.tgz", - "integrity": "sha1-hTz6D3y+L+1d4gMmuN1YEDX24vA=", - "dev": true, - "requires": { - "assert-plus": "^1.0.0" - } - }, "debug": { "version": "2.6.9", "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", @@ -545,12 +5115,6 @@ "integrity": "sha1-IwdjLUwEOCuN+KMvcLiVBG1SdF8=", "dev": true }, - "decamelize": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-1.2.0.tgz", - "integrity": "sha1-9lNNFRSCabIDUue+4m9QH5oZEpA=", - "dev": true - }, "deep-extend": { "version": "0.6.0", "resolved": "https://registry.npmjs.org/deep-extend/-/deep-extend-0.6.0.tgz", @@ -578,9 +5142,9 @@ "integrity": "sha1-3zrhmayt+31ECqrgsp4icrJOxhk=" }, "diff": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/diff/-/diff-4.0.2.tgz", - "integrity": "sha512-58lmxKSA4BNyLz+HHMUzlOEpg09FV+ev6ZMe3vJihgdxzgcwZ8VoEEPmALCZG9LmqfVoNMMKpttIYTVG6uDY7A==", + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/diff/-/diff-7.0.0.tgz", + "integrity": "sha512-PJWHUb1RFevKCwaFA9RlG5tCd+FO5iRh9A8HEtkmBH2Li03iJriB6m6JIN4rGz3K3JLawI7/veA1xzRKP6ISBw==", "dev": true }, "doctrine": { @@ -598,20 +5162,26 @@ "integrity": "sha512-M3NhsLbV1i6HuGzBUH8vXrtxOk+tWmzWKDMbAVSUp3Zsjm7ywFeuwrUXhmhQyRK1q5B5GGy7hcXPbj3bnfZg2g==", "dev": true }, + "dunder-proto": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/dunder-proto/-/dunder-proto-1.0.1.tgz", + "integrity": "sha512-KIN/nDJBQRcXw0MLVhZE9iQHmG68qAVIBg9CqmUYjmQIhgij9U5MFvrqkUL5FbtyyzZuOeOt0zdeRe4UY7ct+A==", + "requires": { + "call-bind-apply-helpers": "^1.0.1", + "es-errors": "^1.3.0", + "gopd": "^1.2.0" + } + }, "duplexer": { "version": "0.1.1", "resolved": "https://registry.npmjs.org/duplexer/-/duplexer-0.1.1.tgz", "integrity": "sha1-rOb/gIwc5mtX0ev5eXessCM0z8E=" }, - "ecc-jsbn": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/ecc-jsbn/-/ecc-jsbn-0.1.2.tgz", - "integrity": "sha1-OoOpBOVDUyh4dMVkt1SThoSamMk=", - "dev": true, - "requires": { - "jsbn": "~0.1.0", - "safer-buffer": "^2.1.0" - } + "eastasianwidth": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/eastasianwidth/-/eastasianwidth-0.2.0.tgz", + "integrity": "sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA==", + "dev": true }, "echint": { "version": "4.0.2", @@ -712,14 +5282,6 @@ "dev": true, "requires": { "ansi-colors": "^4.1.1" - }, - "dependencies": { - "ansi-colors": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/ansi-colors/-/ansi-colors-4.1.1.tgz", - "integrity": "sha512-JoX0apGbHaUJBNl6yF+p6JAFYZ666/hhCGKN5t9QFjbJQKUU/g8MNbFDbvfrgKXvI1QpZplPOnwIo99lX/AAmA==", - "dev": true - } } }, "error-ex": { @@ -753,12 +5315,6 @@ "string.prototype.trimstart": "^1.0.3" }, "dependencies": { - "has-symbols": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.1.tgz", - "integrity": "sha512-PLcsoqu++dmEIZB+6totNFKq/7Do+Z0u4oT0zKOJNl3lYK6vGwwu2hjHs+68OEZbTjiUE9bgOABXbP/GvrS0Kg==", - "dev": true - }, "object-inspect": { "version": "1.9.0", "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.9.0.tgz", @@ -799,6 +5355,35 @@ } } }, + "es-define-property": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/es-define-property/-/es-define-property-1.0.1.tgz", + "integrity": "sha512-e3nRfgfUZ4rNGL232gUgX06QNyyez04KdjFrF+LTRoOXmrOgFKDg4BCdsjW8EnT69eqdYGmRpJwiPVYNrCaW3g==" + }, + "es-errors": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/es-errors/-/es-errors-1.3.0.tgz", + "integrity": "sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==" + }, + "es-object-atoms": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/es-object-atoms/-/es-object-atoms-1.1.1.tgz", + "integrity": "sha512-FGgH2h8zKNim9ljj7dankFPcICIK9Cp5bm+c2gQSYePhpaG5+esrLODihIorn+Pe6FGJzWhXQotPv73jTaldXA==", + "requires": { + "es-errors": "^1.3.0" + } + }, + "es-set-tostringtag": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/es-set-tostringtag/-/es-set-tostringtag-2.1.0.tgz", + "integrity": "sha512-j6vWzfrGVfyXxge+O0x5sh6cvxAog0a/4Rdd2K36zCMV5eJ+/+tOAngRO8cODMNWbVRdVlmGZQL2YS3yR8bIUA==", + "requires": { + "es-errors": "^1.3.0", + "get-intrinsic": "^1.2.6", + "has-tostringtag": "^1.0.2", + "hasown": "^2.0.2" + } + }, "es-to-primitive": { "version": "1.2.1", "resolved": "https://registry.npmjs.org/es-to-primitive/-/es-to-primitive-1.2.1.tgz", @@ -810,6 +5395,12 @@ "is-symbol": "^1.0.2" } }, + "escalade": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.2.0.tgz", + "integrity": "sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA==", + "dev": true + }, "escape-string-regexp": { "version": "1.0.5", "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", @@ -1003,13 +5594,15 @@ "version": "16.0.2", "resolved": "https://registry.npmjs.org/eslint-config-standard/-/eslint-config-standard-16.0.2.tgz", "integrity": "sha512-fx3f1rJDsl9bY7qzyX8SAtP8GBSk6MfXFaTfaGgk12aAYW4gJSyRm7dM790L6cbXv63fvjY4XeSzXnb4WM+SKw==", - "dev": true + "dev": true, + "requires": {} }, "eslint-config-standard-jsx": { "version": "10.0.0", "resolved": "https://registry.npmjs.org/eslint-config-standard-jsx/-/eslint-config-standard-jsx-10.0.0.tgz", "integrity": "sha512-hLeA2f5e06W1xyr/93/QJulN/rLbUVUmqTlexv9PRKHFwEC9ffJcH2LvJhMoEqYQBEYafedgGZXH2W8NUpt5lA==", - "dev": true + "dev": true, + "requires": {} }, "eslint-import-resolver-node": { "version": "0.3.4", @@ -1306,22 +5899,10 @@ "through": "~2.3.1" } }, - "extend": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/extend/-/extend-3.0.2.tgz", - "integrity": "sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g==", - "dev": true - }, - "extsprintf": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/extsprintf/-/extsprintf-1.3.0.tgz", - "integrity": "sha1-lpGEQOMEGnpBT4xS48V06zw+HgU=", - "dev": true - }, "fast-deep-equal": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-2.0.1.tgz", - "integrity": "sha1-ewUhjd+WZ79/Nwv3/bLLFf3Qqkk=" + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", + "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==" }, "fast-json-stable-stringify": { "version": "2.0.0", @@ -1343,15 +5924,6 @@ "flat-cache": "^2.0.1" } }, - "fill-range": { - "version": "7.0.1", - "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz", - "integrity": "sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==", - "dev": true, - "requires": { - "to-regex-range": "^5.0.1" - } - }, "find-root": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/find-root/-/find-root-1.1.0.tgz", @@ -1390,20 +5962,26 @@ "integrity": "sha512-r5wGx7YeOwNWNlCA0wQ86zKyDLMQr+/RB8xy74M4hTphfmjlijTSSXGuH8rnvKZnfT9i+75zmd8jcKdMR4O6jA==", "dev": true }, - "forever-agent": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/forever-agent/-/forever-agent-0.6.1.tgz", - "integrity": "sha1-+8cfDEGt6zf5bFd60e1C2P2sypE=", - "dev": true + "foreground-child": { + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/foreground-child/-/foreground-child-3.3.1.tgz", + "integrity": "sha512-gIXjKqtFuWEgzFRJA9WCQeSJLZDjgJUOMCMzxtvFq/37KojM1BFGufqsCy0r4qSQmYLsZYMeyRqzIWOMup03sw==", + "dev": true, + "requires": { + "cross-spawn": "^7.0.6", + "signal-exit": "^4.0.1" + } }, "form-data": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/form-data/-/form-data-3.0.0.tgz", - "integrity": "sha512-CKMFDglpbMi6PyN+brwB9Q/GOw0eAnsrEZDgcsH5Krhz5Od/haKHAX0NmQfha2zPPz0JpWzA7GJHGSnvCRLWsg==", + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/form-data/-/form-data-3.0.4.tgz", + "integrity": "sha512-f0cRzm6dkyVYV3nPoooP8XlccPQukegwhAnpoLcXy+X+A8KfpGOoXwDr9FLZd3wzgLaBGQBE3lY93Zm/i1JvIQ==", "requires": { "asynckit": "^0.4.0", "combined-stream": "^1.0.8", - "mime-types": "^2.1.12" + "es-set-tostringtag": "^2.1.0", + "hasown": "^2.0.2", + "mime-types": "^2.1.35" }, "dependencies": { "combined-stream": { @@ -1454,18 +6032,10 @@ "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=", "dev": true }, - "fsevents": { - "version": "2.1.3", - "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.1.3.tgz", - "integrity": "sha512-Auw9a4AxqWpa9GUfj370BMPzzyncfBABW8Mab7BGWBYDj4Isgq+cDKtx0i6u9jcX9pQDnswsaaOTgTmA5pEjuQ==", - "dev": true, - "optional": true - }, "function-bind": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz", - "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==", - "dev": true + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz", + "integrity": "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==" }, "functional-red-black-tree": { "version": "1.0.1", @@ -1480,44 +6050,37 @@ "dev": true }, "get-intrinsic": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.1.0.tgz", - "integrity": "sha512-M11rgtQp5GZMZzDL7jLTNxbDfurpzuau5uqRWDPvlHjfvg3TdScAZo96GLvhMjImrmR8uAt0FS2RLoMrfWGKlg==", - "dev": true, + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.3.0.tgz", + "integrity": "sha512-9fSjSaos/fRIVIp+xSJlE6lfwhES7LNtKaCBIamHsjr2na1BiABJPo0mOjjz8GJDURarmCPGqaiVg5mfjb98CQ==", + "requires": { + "call-bind-apply-helpers": "^1.0.2", + "es-define-property": "^1.0.1", + "es-errors": "^1.3.0", + "es-object-atoms": "^1.1.1", + "function-bind": "^1.1.2", + "get-proto": "^1.0.1", + "gopd": "^1.2.0", + "has-symbols": "^1.1.0", + "hasown": "^2.0.2", + "math-intrinsics": "^1.1.0" + } + }, + "get-proto": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/get-proto/-/get-proto-1.0.1.tgz", + "integrity": "sha512-sTSfBjoXBp89JvIKIefqw7U2CCebsc74kiY6awiGogKtoSGbgjYE/G/+l9sF3MWFPNc9IcoOC4ODfKHfxFmp0g==", "requires": { - "function-bind": "^1.1.1", - "has": "^1.0.3", - "has-symbols": "^1.0.1" - }, - "dependencies": { - "has-symbols": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.1.tgz", - "integrity": "sha512-PLcsoqu++dmEIZB+6totNFKq/7Do+Z0u4oT0zKOJNl3lYK6vGwwu2hjHs+68OEZbTjiUE9bgOABXbP/GvrS0Kg==", - "dev": true - } + "dunder-proto": "^1.0.1", + "es-object-atoms": "^1.0.0" } }, - "get-own-enumerable-property-symbols": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/get-own-enumerable-property-symbols/-/get-own-enumerable-property-symbols-3.0.0.tgz", - "integrity": "sha512-CIJYJC4GGF06TakLg8z4GQKvDsx9EMspVxOYih7LerEL/WosUnFIww45CGfxfeKHqlg3twgUrYRT1O3WQqjGCg==" - }, "get-stdin": { "version": "8.0.0", "resolved": "https://registry.npmjs.org/get-stdin/-/get-stdin-8.0.0.tgz", "integrity": "sha512-sY22aA6xchAzprjyqmSEQv4UbAAzRN0L2dQB0NlN5acTTK9Don6nhoc3eAbUnpZiCANAMfd/+40kVdKfFygohg==", "dev": true }, - "getpass": { - "version": "0.1.7", - "resolved": "https://registry.npmjs.org/getpass/-/getpass-0.1.7.tgz", - "integrity": "sha1-Xv+OPmhNVprkyysSgmBOi6YhSfo=", - "dev": true, - "requires": { - "assert-plus": "^1.0.0" - } - }, "glob": { "version": "6.0.4", "resolved": "https://registry.npmjs.org/glob/-/glob-6.0.4.tgz", @@ -1532,9 +6095,9 @@ } }, "glob-parent": { - "version": "5.1.1", - "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.1.tgz", - "integrity": "sha512-FnI+VGOpnlGHWZxthPGR+QhR78fuiK0sNLkHQv+bL9fQi57lNNdquIbna/WrfROrolq8GK5Ek6BiMwqL/voRYQ==", + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", + "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", "dev": true, "requires": { "is-glob": "^4.0.1" @@ -1549,27 +6112,20 @@ "type-fest": "^0.8.1" } }, + "gopd": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/gopd/-/gopd-1.2.0.tgz", + "integrity": "sha512-ZUKRh6/kUFoAiTAtTYPZJ3hw9wNxx+BIBOijnlG9PnrJsCcSjs1wyyD6vJpaYtgnzDrKYRSqf3OO6Rfa93xsRg==" + }, "graceful-fs": { "version": "4.1.15", "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.1.15.tgz", "integrity": "sha512-6uHUhOPEBgQ24HM+r6b/QwWfZq+yiFcipKFrOFiBEnWdy5sdzYoi+pJeQaPI5qOLRFqWmAXUPQNsielzdLoecA==" }, - "graceful-readlink": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/graceful-readlink/-/graceful-readlink-1.0.1.tgz", - "integrity": "sha1-TK+tdrxi8C+gObL5Tpo906ORpyU=", - "dev": true - }, - "growl": { - "version": "1.10.5", - "resolved": "https://registry.npmjs.org/growl/-/growl-1.10.5.tgz", - "integrity": "sha512-qBr4OuELkhPenW6goKVXiv47US3clb3/IbuWF9KNKEijAy9oeHxU9IgzjvJhHkUzhaj7rOUD7+YGWqUjLp5oSA==", - "dev": true - }, "handlebars": { - "version": "4.7.6", - "resolved": "https://registry.npmjs.org/handlebars/-/handlebars-4.7.6.tgz", - "integrity": "sha512-1f2BACcBfiwAfStCKZNrUCgqNZkGsAT7UM3kkYtXuLo0KnaVfjKOyf7PRzB6++aK9STyT1Pd2ZCPe3EGOXleXA==", + "version": "4.7.7", + "resolved": "https://registry.npmjs.org/handlebars/-/handlebars-4.7.7.tgz", + "integrity": "sha512-aAcXm5OAfE/8IXkcZvCepKU3VzW1/39Fb5ZuqMtgI/hT8X2YgoMvBY5dLhq/cpOvw7Lk1nK/UF71aLG/ZnVYRA==", "dev": true, "requires": { "minimist": "^1.2.5", @@ -1631,10 +6187,25 @@ "dev": true }, "has-symbols": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.0.tgz", - "integrity": "sha1-uhqPGvKg/DllD1yFA2dwQSIGO0Q=", - "dev": true + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.1.0.tgz", + "integrity": "sha512-1cDNdwJ2Jaohmb3sg4OmKaMBwuC48sYni5HUw2DvsC8LjGTLK9h+eb1X6RyuOHe4hT0ULCW68iomhjUoKUqlPQ==" + }, + "has-tostringtag": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/has-tostringtag/-/has-tostringtag-1.0.2.tgz", + "integrity": "sha512-NqADB8VjPFLM2V0VvHUewwwsw0ZWBaIdgo+ieHtK3hasLz4qeCRjYcqfB6AQrBggRKppKF8L52/VqdVsO47Dlw==", + "requires": { + "has-symbols": "^1.0.3" + } + }, + "hasown": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.2.tgz", + "integrity": "sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==", + "requires": { + "function-bind": "^1.1.2" + } }, "he": { "version": "1.2.0", @@ -1643,22 +6214,11 @@ "dev": true }, "hosted-git-info": { - "version": "2.8.8", - "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-2.8.8.tgz", - "integrity": "sha512-f/wzC2QaWBs7t9IYqB4T3sR1xviIViXJRJTWBlx2Gf3g0Xi5vI7Yy4koXQ1c9OYDGHN9sBy1DQ2AB8fqZBWhUg==", + "version": "2.8.9", + "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-2.8.9.tgz", + "integrity": "sha512-mxIDAb9Lsm6DoOJ7xH+5+X4y1LU/4Hi50L9C5sIswK3JzULS4bwk1FvjdBgvYR4bzT4tuUQiC15FE2f5HbLvYw==", "dev": true }, - "http-signature": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/http-signature/-/http-signature-1.2.0.tgz", - "integrity": "sha1-muzZJRFHcvPZW2WmCruPfBj7rOE=", - "dev": true, - "requires": { - "assert-plus": "^1.0.0", - "jsprim": "^1.2.2", - "sshpk": "^1.7.0" - } - }, "ignore": { "version": "4.0.6", "resolved": "https://registry.npmjs.org/ignore/-/ignore-4.0.6.tgz", @@ -1720,15 +6280,6 @@ "integrity": "sha1-d8mYQFJ6qOyxqLppe4BkWnqSap0=", "dev": true }, - "is-binary-path": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz", - "integrity": "sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==", - "dev": true, - "requires": { - "binary-extensions": "^2.0.0" - } - }, "is-callable": { "version": "1.2.2", "resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.2.2.tgz", @@ -1777,17 +6328,12 @@ "integrity": "sha512-2z6JzQvZRa9A2Y7xC6dQQm4FSTSTNWjKIYYTt4246eMTJmIo0Q+ZyOsU66X8lxK1AbB92dFeglPLrhwpeRKO6w==", "dev": true }, - "is-number": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", - "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", + "is-path-inside": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/is-path-inside/-/is-path-inside-3.0.3.tgz", + "integrity": "sha512-Fd4gABb+ycGAmKou8eMftCupSir5lRxqf4aD/vd0cD2qc4HL07OjCeuHMr8Ro4CoMaeCKDB0/ECBOVWjTwUvPQ==", "dev": true }, - "is-obj": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/is-obj/-/is-obj-1.0.1.tgz", - "integrity": "sha1-PkcprB9f3gJc19g6iW2rn09n2w8=" - }, "is-plain-obj": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/is-plain-obj/-/is-plain-obj-2.1.0.tgz", @@ -1801,21 +6347,8 @@ "dev": true, "requires": { "has-symbols": "^1.0.1" - }, - "dependencies": { - "has-symbols": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.1.tgz", - "integrity": "sha512-PLcsoqu++dmEIZB+6totNFKq/7Do+Z0u4oT0zKOJNl3lYK6vGwwu2hjHs+68OEZbTjiUE9bgOABXbP/GvrS0Kg==", - "dev": true - } } }, - "is-regexp": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-regexp/-/is-regexp-1.0.0.tgz", - "integrity": "sha1-/S2INUXEa6xaYz57mgnof6LLUGk=" - }, "is-string": { "version": "1.0.5", "resolved": "https://registry.npmjs.org/is-string/-/is-string-1.0.5.tgz", @@ -1831,10 +6364,10 @@ "has-symbols": "^1.0.0" } }, - "is-typedarray": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-typedarray/-/is-typedarray-1.0.0.tgz", - "integrity": "sha1-5HnICFjfDBsR3dppQPlgEfzaSpo=", + "is-unicode-supported": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/is-unicode-supported/-/is-unicode-supported-0.1.0.tgz", + "integrity": "sha512-knxG2q4UC3u8stRGyAVJCOdxFmv5DZiRcdlIaAQXAbSfJya+OhopNotLQrstBhququ4ZpuKbDc/8S6mgXgPFPw==", "dev": true }, "isarray": { @@ -1849,12 +6382,6 @@ "integrity": "sha1-6PvzdNxVb/iUehDcsFctYz8s+hA=", "dev": true }, - "isstream": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/isstream/-/isstream-0.1.2.tgz", - "integrity": "sha1-R+Y/evVa+m+S4VAOaQ64uFKcCZo=", - "dev": true - }, "istanbul": { "version": "0.4.5", "resolved": "https://registry.npmjs.org/istanbul/-/istanbul-0.4.5.tgz", @@ -1907,6 +6434,16 @@ } } }, + "jackspeak": { + "version": "3.4.3", + "resolved": "https://registry.npmjs.org/jackspeak/-/jackspeak-3.4.3.tgz", + "integrity": "sha512-OGlZQpz2yfahA/Rd1Y8Cd9SIEsqvXkLVoSw/cgwhnhFMDbsQFeZYoJJ7bIZBS9BcamUW96asq/npPWugM+RQBw==", + "dev": true, + "requires": { + "@isaacs/cliui": "^8.0.2", + "@pkgjs/parseargs": "^0.11.0" + } + }, "js-tokens": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", @@ -1914,9 +6451,9 @@ "dev": true }, "js-yaml": { - "version": "3.13.1", - "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.13.1.tgz", - "integrity": "sha512-YfbcO7jXDdyj0DGxYVSlSeQNHbD7XPWvrVWeVUujrQEoZzWJIRrCPoyk6kL6IAjAG2IolMK4T0hNUe0HOUs5Jw==", + "version": "3.14.2", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.14.2.tgz", + "integrity": "sha512-PMSmkqxr106Xa156c2M265Z+FTrPl+oxd/rgOQy2tijQeK5TxQ43psO1ZCwhVOSdnn+RzkzlRz/eY4BgJBYVpg==", "dev": true, "requires": { "argparse": "^1.0.7", @@ -1931,24 +6468,12 @@ } } }, - "jsbn": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/jsbn/-/jsbn-0.1.1.tgz", - "integrity": "sha1-peZUwuWi3rXyAdls77yoDA7y9RM=", - "dev": true - }, "json-parse-better-errors": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/json-parse-better-errors/-/json-parse-better-errors-1.0.2.tgz", "integrity": "sha512-mrqyZKfX5EhL7hvqcV6WG1yYjnjeuYDzDhhcAAUrq8Po85NBQBJP+ZDUT75qZQ98IkUoBqdkExkukOU7Ts2wrw==", "dev": true }, - "json-schema": { - "version": "0.2.3", - "resolved": "https://registry.npmjs.org/json-schema/-/json-schema-0.2.3.tgz", - "integrity": "sha1-tIDIkuWaLwWVTOcnvT8qTogvnhM=", - "dev": true - }, "json-schema-traverse": { "version": "0.4.1", "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", @@ -1960,33 +6485,15 @@ "integrity": "sha1-nbe1lJatPzz+8wp1FC0tkwrXJlE=", "dev": true }, - "json-stringify-safe": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz", - "integrity": "sha1-Epai1Y/UXxmg9s4B1lcB4sc1tus=", - "dev": true - }, "json5": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/json5/-/json5-1.0.1.tgz", - "integrity": "sha512-aKS4WQjPenRxiQsC93MNfjx+nbF4PAdYzmd/1JIj8HYzqfbu86beTuNgXDzPknWk0n0uARlyewZo4s++ES36Ow==", + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/json5/-/json5-1.0.2.tgz", + "integrity": "sha512-g1MWMLBiz8FKi1e4w0UyVL3w+iJceWAFBAaBnnGKOpNa5f8TLktkbre1+s6oICydWAm+HRUGTmI+//xv2hvXYA==", "dev": true, "requires": { "minimist": "^1.2.0" } }, - "jsprim": { - "version": "1.4.1", - "resolved": "https://registry.npmjs.org/jsprim/-/jsprim-1.4.1.tgz", - "integrity": "sha1-MT5mvB5cwG5Di8G3SZwuXFastqI=", - "dev": true, - "requires": { - "assert-plus": "1.0.0", - "extsprintf": "1.3.0", - "json-schema": "0.2.3", - "verror": "1.10.0" - } - }, "jsx-ast-utils": { "version": "3.2.0", "resolved": "https://registry.npmjs.org/jsx-ast-utils/-/jsx-ast-utils-3.2.0.tgz", @@ -1997,12 +6504,6 @@ "object.assign": "^4.1.2" }, "dependencies": { - "has-symbols": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.1.tgz", - "integrity": "sha512-PLcsoqu++dmEIZB+6totNFKq/7Do+Z0u4oT0zKOJNl3lYK6vGwwu2hjHs+68OEZbTjiUE9bgOABXbP/GvrS0Kg==", - "dev": true - }, "object.assign": { "version": "4.1.2", "resolved": "https://registry.npmjs.org/object.assign/-/object.assign-4.1.2.tgz", @@ -2017,12 +6518,6 @@ } } }, - "lcov-parse": { - "version": "0.0.10", - "resolved": "https://registry.npmjs.org/lcov-parse/-/lcov-parse-0.0.10.tgz", - "integrity": "sha1-GwuP+ayceIklBYK3C3ExXZ2m2aM=", - "dev": true - }, "levn": { "version": "0.3.0", "resolved": "https://registry.npmjs.org/levn/-/levn-0.3.0.tgz", @@ -2067,18 +6562,19 @@ } }, "lodash": { - "version": "4.17.19", - "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.19.tgz", - "integrity": "sha512-JNvd8XER9GQX0v2qJgsaN/mzFCNA5BRe/j8JN9d+tWyGLSodKQHKFicdwNYzWwI3wjRnaKPsGj1XkBjx/F96DQ==", + "version": "4.17.23", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.23.tgz", + "integrity": "sha512-LgVTMpQtIopCi79SJeDiP0TfWi5CNEc/L/aRdTh3yIvmZXTnheWpKjSZhnvMl8iXbC1tFg9gdHHDMLoV7CnG+w==", "dev": true }, "log-symbols": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/log-symbols/-/log-symbols-4.0.0.tgz", - "integrity": "sha512-FN8JBzLx6CzeMrB0tg6pqlGU1wCrXW+ZXGH481kfsBqer0hToTIiHdjH4Mq8xJUbvATujKCvaREGWpGUionraA==", + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/log-symbols/-/log-symbols-4.1.0.tgz", + "integrity": "sha512-8XPvpAA8uyhfteu8pIvQxpJZ7SYYdpUivZpGy6sFsBuKRY/7rQGavedeB8aK+Zkyq6upMFVL/9AW6vOYzfRyLg==", "dev": true, "requires": { - "chalk": "^4.0.0" + "chalk": "^4.1.0", + "is-unicode-supported": "^0.1.0" }, "dependencies": { "ansi-styles": { @@ -2091,9 +6587,9 @@ } }, "chalk": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.0.tgz", - "integrity": "sha512-qwx12AxXe2Q5xQ43Ac//I6v5aXTipYrSESdOgzrN+9XjgEpyjpKuvSGaN4qE93f7TQTlerQQ8S+EQ0EyDoVL1A==", + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", "dev": true, "requires": { "ansi-styles": "^4.1.0", @@ -2156,17 +6652,22 @@ "resolved": "https://registry.npmjs.org/map-stream/-/map-stream-0.1.0.tgz", "integrity": "sha1-5WqpTEyAVaFkBKBnS3jyFffI4ZQ=" }, + "math-intrinsics": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/math-intrinsics/-/math-intrinsics-1.1.0.tgz", + "integrity": "sha512-/IXtbwEk5HTPyEwyKX6hGkYXxM9nbj64B+ilVJnC/R6B0pH5G4V3b0pVbL7DBj4tkhBAppbQUlf6F6Xl9LHu1g==" + }, "mime-db": { - "version": "1.40.0", - "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.40.0.tgz", - "integrity": "sha512-jYdeOMPy9vnxEqFRRo6ZvTZ8d9oPb+k18PKoYNYUe2stVEBPPwsln/qWzdbmaIvnhZ9v2P+CuecK+fpUfsV2mA==" + "version": "1.52.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz", + "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==" }, "mime-types": { - "version": "2.1.24", - "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.24.tgz", - "integrity": "sha512-WaFHS3MCl5fapm3oLxU4eYDw77IQM2ACcxQ9RIxfaC3ooc6PFuBMGZZsYpvoXS5D5QTWPieo1jjLdAm3TBP3cQ==", + "version": "2.1.35", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz", + "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==", "requires": { - "mime-db": "1.40.0" + "mime-db": "1.52.0" } }, "minimatch": { @@ -2184,11 +6685,16 @@ "integrity": "sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ=", "dev": true }, + "minipass": { + "version": "7.1.2", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-7.1.2.tgz", + "integrity": "sha512-qOOzS1cBTWYF4BH8fVePDBOO9iptMnGUEZwNc/cMWnTV2nVLZ7VoNWEPHkYczZA0pdoA7dl6e7FL659nX9S2aw==", + "dev": true + }, "mkdirp": { "version": "0.5.1", "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.1.tgz", "integrity": "sha1-MAV0OOrGz3+MR2fzhkjWaX11yQM=", - "dev": true, "requires": { "minimist": "0.0.8" }, @@ -2196,56 +6702,67 @@ "minimist": { "version": "0.0.8", "resolved": "https://registry.npmjs.org/minimist/-/minimist-0.0.8.tgz", - "integrity": "sha1-hX/Kv8M5fSYluCKCYuhqp6ARsF0=", - "dev": true + "integrity": "sha1-hX/Kv8M5fSYluCKCYuhqp6ARsF0=" } } }, "mkdirp-promise": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/mkdirp-promise/-/mkdirp-promise-1.1.0.tgz", - "integrity": "sha1-LISJPtZ24NmPsY+5piEv0bK5qBk=" + "integrity": "sha1-LISJPtZ24NmPsY+5piEv0bK5qBk=", + "requires": {} }, "mocha": { - "version": "8.2.1", - "resolved": "https://registry.npmjs.org/mocha/-/mocha-8.2.1.tgz", - "integrity": "sha512-cuLBVfyFfFqbNR0uUKbDGXKGk+UDFe6aR4os78XIrMQpZl/nv7JYHcvP5MFIAb374b2zFXsdgEGwmzMtP0Xg8w==", - "dev": true, - "requires": { - "@ungap/promise-all-settled": "1.1.2", - "ansi-colors": "4.1.1", - "browser-stdout": "1.3.1", - "chokidar": "3.4.3", - "debug": "4.2.0", - "diff": "4.0.2", - "escape-string-regexp": "4.0.0", - "find-up": "5.0.0", - "glob": "7.1.6", - "growl": "1.10.5", - "he": "1.2.0", - "js-yaml": "3.14.0", - "log-symbols": "4.0.0", - "minimatch": "3.0.4", - "ms": "2.1.2", - "nanoid": "3.1.12", - "serialize-javascript": "5.0.1", - "strip-json-comments": "3.1.1", - "supports-color": "7.2.0", - "which": "2.0.2", - "wide-align": "1.1.3", - "workerpool": "6.0.2", - "yargs": "13.3.2", - "yargs-parser": "13.1.2", - "yargs-unparser": "2.0.0" + "version": "11.7.5", + "resolved": "https://registry.npmjs.org/mocha/-/mocha-11.7.5.tgz", + "integrity": "sha512-mTT6RgopEYABzXWFx+GcJ+ZQ32kp4fMf0xvpZIIfSq9Z8lC/++MtcCnQ9t5FP2veYEP95FIYSvW+U9fV4xrlig==", + "dev": true, + "requires": { + "browser-stdout": "^1.3.1", + "chokidar": "^4.0.1", + "debug": "^4.3.5", + "diff": "^7.0.0", + "escape-string-regexp": "^4.0.0", + "find-up": "^5.0.0", + "glob": "^10.4.5", + "he": "^1.2.0", + "is-path-inside": "^3.0.3", + "js-yaml": "^4.1.0", + "log-symbols": "^4.1.0", + "minimatch": "^9.0.5", + "ms": "^2.1.3", + "picocolors": "^1.1.1", + "serialize-javascript": "^6.0.2", + "strip-json-comments": "^3.1.1", + "supports-color": "^8.1.1", + "workerpool": "^9.2.0", + "yargs": "^17.7.2", + "yargs-parser": "^21.1.1", + "yargs-unparser": "^2.0.0" }, "dependencies": { + "argparse": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", + "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==", + "dev": true + }, + "brace-expansion": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.2.tgz", + "integrity": "sha512-Jt0vHyM+jmUBqojB7E1NIYadt0vI0Qxjxd2TErW94wDz+E2LAm5vKMXXwg6ZZBTHPuUlDgQHKXvjGBdfcF1ZDQ==", + "dev": true, + "requires": { + "balanced-match": "^1.0.0" + } + }, "debug": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.2.0.tgz", - "integrity": "sha512-IX2ncY78vDTjZMFUdmsvIRFY2Cf4FnD0wRs+nQwJU8Lu99/tPFdb0VybiiMTPe3I6rQmwsqQqRBvxU+bZ/I8sg==", + "version": "4.4.3", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.3.tgz", + "integrity": "sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA==", "dev": true, "requires": { - "ms": "2.1.2" + "ms": "^2.1.3" } }, "escape-string-regexp": { @@ -2254,12 +6771,6 @@ "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==", "dev": true }, - "esprima": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz", - "integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==", - "dev": true - }, "find-up": { "version": "5.0.0", "resolved": "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz", @@ -2271,17 +6782,17 @@ } }, "glob": { - "version": "7.1.6", - "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.6.tgz", - "integrity": "sha512-LwaxwyZ72Lk7vZINtNNrywX0ZuLyStrdDtabefZKAY5ZGJhVtgdznluResxNmPitE0SAO+O26sWTHeKSI2wMBA==", + "version": "10.4.5", + "resolved": "https://registry.npmjs.org/glob/-/glob-10.4.5.tgz", + "integrity": "sha512-7Bv8RF0k6xjo7d4A/PxYLbUCfb6c+Vpd2/mB2yRDlew7Jb5hEXiCD9ibfO7wpk8i4sevK6DFny9h7EYbM3/sHg==", "dev": true, "requires": { - "fs.realpath": "^1.0.0", - "inflight": "^1.0.4", - "inherits": "2", - "minimatch": "^3.0.4", - "once": "^1.3.0", - "path-is-absolute": "^1.0.0" + "foreground-child": "^3.1.0", + "jackspeak": "^3.1.2", + "minimatch": "^9.0.4", + "minipass": "^7.1.2", + "package-json-from-dist": "^1.0.0", + "path-scurry": "^1.11.1" } }, "has-flag": { @@ -2291,13 +6802,12 @@ "dev": true }, "js-yaml": { - "version": "3.14.0", - "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.14.0.tgz", - "integrity": "sha512-/4IbIeHcD9VMHFqDR/gQ7EdZdLimOvW2DdcxFjdyyZ9NsbS+ccrXqVWDtab/lRl5AlUqmpBx8EhPaWR+OtY17A==", + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.1.tgz", + "integrity": "sha512-qQKT4zQxXl8lLwBtHMWwaTcGfFOZviOJet3Oy/xmGk2gZH677CJM9EvtfdSkgWcATZhj/55JZ0rmy3myCT5lsA==", "dev": true, "requires": { - "argparse": "^1.0.7", - "esprima": "^4.0.0" + "argparse": "^2.0.1" } }, "locate-path": { @@ -2309,10 +6819,19 @@ "p-locate": "^5.0.0" } }, + "minimatch": { + "version": "9.0.5", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.5.tgz", + "integrity": "sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow==", + "dev": true, + "requires": { + "brace-expansion": "^2.0.1" + } + }, "ms": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", - "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", "dev": true }, "p-limit": { @@ -2346,22 +6865,13 @@ "dev": true }, "supports-color": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", - "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "version": "8.1.1", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-8.1.1.tgz", + "integrity": "sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==", "dev": true, "requires": { "has-flag": "^4.0.0" } - }, - "which": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", - "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", - "dev": true, - "requires": { - "isexe": "^2.0.0" - } } } }, @@ -2370,12 +6880,6 @@ "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=" }, - "nanoid": { - "version": "3.1.12", - "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.1.12.tgz", - "integrity": "sha512-1qstj9z5+x491jfiC4Nelk+f8XBad7LN20PmyWINJEMRSf3wcAjAWysw1qaA8z6NSKe2sjq1hRSDpBH5paCb6A==", - "dev": true - }, "natural-compare": { "version": "1.4.0", "resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz", @@ -2427,18 +6931,6 @@ } } }, - "normalize-path": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz", - "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==", - "dev": true - }, - "oauth-sign": { - "version": "0.9.0", - "resolved": "https://registry.npmjs.org/oauth-sign/-/oauth-sign-0.9.0.tgz", - "integrity": "sha512-fexhUFFPTGV8ybAtSIGbV6gOkSv8UtRbDBnAyLQw4QPKkgNlsH2ByPGtMUqdWkos6YCRmAqViwgZrJc/mRDzZQ==", - "dev": true - }, "object-assign": { "version": "4.1.1", "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", @@ -2534,6 +7026,12 @@ "integrity": "sha1-y8ec26+P1CKOE/Yh8rGiN8GyB7M=", "dev": true }, + "package-json-from-dist": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/package-json-from-dist/-/package-json-from-dist-1.0.1.tgz", + "integrity": "sha512-UEZIS3/by4OC8vL3P2dTXRETpebLI2NiI5vIrjaD/5UtrkFX/tNbwjTSRAGC/+7CAo2pIcBaRgWmcBBHcsaCIw==", + "dev": true + }, "parent-module": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz", @@ -2571,11 +7069,29 @@ "dev": true }, "path-parse": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.6.tgz", - "integrity": "sha512-GSmOT2EbHrINBf9SR7CDELwlJ8AENk3Qn7OikK4nFYAu3Ote2+JYNVvkpAEQm3/TLNEJFD/xZJjzyxg3KBWOzw==", + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz", + "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==", "dev": true }, + "path-scurry": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/path-scurry/-/path-scurry-1.11.1.tgz", + "integrity": "sha512-Xa4Nw17FS9ApQFJ9umLiJS4orGjm7ZzwUrwamcGQuHSzDyth9boKDaycYdDcZDuqYATXw4HFXgaqWTctW/v1HA==", + "dev": true, + "requires": { + "lru-cache": "^10.2.0", + "minipass": "^5.0.0 || ^6.0.2 || ^7.0.0" + }, + "dependencies": { + "lru-cache": { + "version": "10.4.3", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-10.4.3.tgz", + "integrity": "sha512-JNAzZcXrCt42VGLuYz0zfAzDfAvJWW6AfYlDBQyDV5DClI2m5sAmK+OIO7s59XfsRsWHp02jAJrRadPRGTt6SQ==", + "dev": true + } + } + }, "path-type": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/path-type/-/path-type-2.0.0.tgz", @@ -2593,16 +7109,10 @@ "through": "~2.3" } }, - "performance-now": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/performance-now/-/performance-now-2.1.0.tgz", - "integrity": "sha1-Ywn04OX6kT7BxpMHrjZLSzd8nns=", - "dev": true - }, - "picomatch": { - "version": "2.2.2", - "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.2.2.tgz", - "integrity": "sha512-q0M/9eZHzmr0AulXyPwNfZjtwZ/RBZlbN3K3CErVrk50T2ASYI7Bye0EvekFY3IP1Nt2DHu0re+V2ZHIpMkuWg==", + "picocolors": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.1.1.tgz", + "integrity": "sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==", "dev": true }, "pify": { @@ -2755,23 +7265,11 @@ "integrity": "sha1-8FKijacOYYkX7wqKw0wa5aaChrM=", "dev": true }, - "psl": { - "version": "1.1.31", - "resolved": "https://registry.npmjs.org/psl/-/psl-1.1.31.tgz", - "integrity": "sha512-/6pt4+C+T+wZUieKR620OpzN/LlnNKuWjy1iFLQ/UG35JqHlR/89MP1d96dUfkf6Dne3TuLQzOYEYshJ+Hx8mw==", - "dev": true - }, "punycode": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.1.1.tgz", "integrity": "sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A==" }, - "qs": { - "version": "6.5.2", - "resolved": "https://registry.npmjs.org/qs/-/qs-6.5.2.tgz", - "integrity": "sha512-N5ZAX4/LxJmF+7wN74pUD6qAh9/wnvdQcjq9TZjevvXzSUo7bfmw91saqMjzGS2xq91/odN2dW/WOl7qQHNDGA==", - "dev": true - }, "randombytes": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/randombytes/-/randombytes-2.1.0.tgz", @@ -2821,13 +7319,10 @@ } }, "readdirp": { - "version": "3.5.0", - "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.5.0.tgz", - "integrity": "sha512-cMhu7c/8rdhkHXWsY+osBhfSy0JikwpHK/5+imo+LpeasTF8ouErHrlYkwT0++njiyuDvc7OFY5T3ukvZ8qmFQ==", - "dev": true, - "requires": { - "picomatch": "^2.2.1" - } + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-4.1.2.tgz", + "integrity": "sha512-GDhwkLfywWL2s6vEjyhri+eXmfH6j1L7JE27WhqLeYzoh/A3DBaYGEj2H/HFZCn/kMfim73FXxEJTw06WtxQwg==", + "dev": true }, "regexp.prototype.flags": { "version": "1.3.1", @@ -2845,59 +7340,12 @@ "integrity": "sha512-ZOIzd8yVsQQA7j8GCSlPGXwg5PfmA1mrq0JP4nGhh54LaKN3xdai/vHUDu74pKwV8OxseMS65u2NImosQcSD0Q==", "dev": true }, - "request": { - "version": "2.88.0", - "resolved": "https://registry.npmjs.org/request/-/request-2.88.0.tgz", - "integrity": "sha512-NAqBSrijGLZdM0WZNsInLJpkJokL72XYjUpnB0iwsRgxh7dB6COrHnTBNwN0E+lHDAJzu7kLAkDeY08z2/A0hg==", - "dev": true, - "requires": { - "aws-sign2": "~0.7.0", - "aws4": "^1.8.0", - "caseless": "~0.12.0", - "combined-stream": "~1.0.6", - "extend": "~3.0.2", - "forever-agent": "~0.6.1", - "form-data": "~2.3.2", - "har-validator": "~5.1.0", - "http-signature": "~1.2.0", - "is-typedarray": "~1.0.0", - "isstream": "~0.1.2", - "json-stringify-safe": "~5.0.1", - "mime-types": "~2.1.19", - "oauth-sign": "~0.9.0", - "performance-now": "^2.1.0", - "qs": "~6.5.2", - "safe-buffer": "^5.1.2", - "tough-cookie": "~2.4.3", - "tunnel-agent": "^0.6.0", - "uuid": "^3.3.2" - }, - "dependencies": { - "form-data": { - "version": "2.3.3", - "resolved": "https://registry.npmjs.org/form-data/-/form-data-2.3.3.tgz", - "integrity": "sha512-1lLKB2Mu3aGP1Q/2eCOx0fNbRMe7XdwktwOruhfqqd0rIJWwN4Dh+E3hrPSlDCXnSR7UtZ1N38rVXm+6+MEhJQ==", - "dev": true, - "requires": { - "asynckit": "^0.4.0", - "combined-stream": "^1.0.6", - "mime-types": "^2.1.12" - } - } - } - }, "require-directory": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz", "integrity": "sha1-jGStX9MNqxyXbiNE/+f3kqam30I=", "dev": true }, - "require-main-filename": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/require-main-filename/-/require-main-filename-2.0.0.tgz", - "integrity": "sha512-NKN5kMDylKuldxYLSUfrbo5Tuzh4hd+2E8NPPX02mZtn1VuREQToYe/ZdlJy+J3uCpfaiGF05e7B8W0iXbQHmg==", - "dev": true - }, "resolve": { "version": "1.1.7", "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.1.7.tgz", @@ -2933,18 +7381,12 @@ "path-is-absolute": "^1.0.0" } } - } - }, - "safe-buffer": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", - "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", - "dev": true + } }, - "safer-buffer": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", - "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==", + "safe-buffer": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", + "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==", "dev": true }, "semver": { @@ -2974,20 +7416,14 @@ } }, "serialize-javascript": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-5.0.1.tgz", - "integrity": "sha512-SaaNal9imEO737H2c05Og0/8LUXG7EnsZyMa8MzkmuHoELfT6txuj0cMqRj6zfPKnmQ1yasR4PCJc8x+M4JSPA==", + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-6.0.2.tgz", + "integrity": "sha512-Saa1xPByTTq2gdeFZYLLo+RFE35NHZkAbqZeWNd3BpzppeVisAqpDjcp8dyf6uIvEqJRd46jemmyA4iFIeVk8g==", "dev": true, "requires": { "randombytes": "^2.1.0" } }, - "set-blocking": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/set-blocking/-/set-blocking-2.0.0.tgz", - "integrity": "sha1-BF+XgtARrppoA93TgrJDkrPYkPc=", - "dev": true - }, "shebang-command": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", @@ -3082,6 +7518,12 @@ "integrity": "sha1-P/IfGYytIXX587eBhT/ZTQ0ZtZA=", "dev": true }, + "signal-exit": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-4.1.0.tgz", + "integrity": "sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==", + "dev": true + }, "slice-ansi": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/slice-ansi/-/slice-ansi-2.1.0.tgz", @@ -3101,12 +7543,6 @@ "requires": { "color-convert": "^1.9.0" } - }, - "is-fullwidth-code-point": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz", - "integrity": "sha1-o7MKXE8ZkYMWeqq5O+764937ZU8=", - "dev": true } } }, @@ -3166,23 +7602,6 @@ "integrity": "sha1-BOaSb2YolTVPPdAVIDYzuFcpfiw=", "dev": true }, - "sshpk": { - "version": "1.16.1", - "resolved": "https://registry.npmjs.org/sshpk/-/sshpk-1.16.1.tgz", - "integrity": "sha512-HXXqVUq7+pcKeLqqZj6mHFUMvXtOJt1uoUx09pFW6011inTMxqI8BA8PM95myrIyyKwdnzjdFjLiE6KBPVtJIg==", - "dev": true, - "requires": { - "asn1": "~0.2.3", - "assert-plus": "^1.0.0", - "bcrypt-pbkdf": "^1.0.0", - "dashdash": "^1.12.0", - "ecc-jsbn": "~0.1.1", - "getpass": "^0.1.1", - "jsbn": "~0.1.0", - "safer-buffer": "^2.0.2", - "tweetnacl": "~0.14.0" - } - }, "standard": { "version": "16.0.3", "resolved": "https://registry.npmjs.org/standard/-/standard-16.0.3.tgz", @@ -3228,28 +7647,81 @@ } }, "string-width": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-2.1.1.tgz", - "integrity": "sha512-nOqH59deCq9SRHlxq1Aw85Jnt4w6KvLKqWVik6oA9ZklXLNIOlqg4F2yrT1MVaTjAqvVwdfeZ7w7aCvJD7ugkw==", + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", "dev": true, "requires": { - "is-fullwidth-code-point": "^2.0.0", - "strip-ansi": "^4.0.0" + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" }, "dependencies": { "ansi-regex": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", + "dev": true + }, + "emoji-regex": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", + "dev": true + }, + "is-fullwidth-code-point": { "version": "3.0.0", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-3.0.0.tgz", - "integrity": "sha1-7QMXwyIGT3lGbAKWa922Bas32Zg=", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", + "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", "dev": true }, "strip-ansi": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-4.0.0.tgz", - "integrity": "sha1-qEeQIusaw2iocTibY1JixQXuNo8=", + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "dev": true, + "requires": { + "ansi-regex": "^5.0.1" + } + } + } + }, + "string-width-cjs": { + "version": "npm:string-width@4.2.3", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "dev": true, + "requires": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + }, + "dependencies": { + "ansi-regex": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", + "dev": true + }, + "emoji-regex": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", + "dev": true + }, + "is-fullwidth-code-point": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", + "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", + "dev": true + }, + "strip-ansi": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", "dev": true, "requires": { - "ansi-regex": "^3.0.0" + "ansi-regex": "^5.0.1" } } } @@ -3267,24 +7739,6 @@ "internal-slot": "^1.0.2", "regexp.prototype.flags": "^1.3.0", "side-channel": "^1.0.3" - }, - "dependencies": { - "has-symbols": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.1.tgz", - "integrity": "sha512-PLcsoqu++dmEIZB+6totNFKq/7Do+Z0u4oT0zKOJNl3lYK6vGwwu2hjHs+68OEZbTjiUE9bgOABXbP/GvrS0Kg==", - "dev": true - } - } - }, - "stringify-object": { - "version": "3.3.0", - "resolved": "https://registry.npmjs.org/stringify-object/-/stringify-object-3.3.0.tgz", - "integrity": "sha512-rHqiFh1elqCQ9WPLIC8I0Q/g/wj5J1eMkyoiD6eoQApWHP0FtlK7rqnhmabL5VUY9JQCcqwwvlOaSuutekgyrw==", - "requires": { - "get-own-enumerable-property-symbols": "^3.0.0", - "is-obj": "^1.0.1", - "is-regexp": "^1.0.0" } }, "strip-ansi": { @@ -3295,6 +7749,23 @@ "ansi-regex": "^2.0.0" } }, + "strip-ansi-cjs": { + "version": "npm:strip-ansi@6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "dev": true, + "requires": { + "ansi-regex": "^5.0.1" + }, + "dependencies": { + "ansi-regex": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", + "dev": true + } + } + }, "strip-bom": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-3.0.0.tgz", @@ -3324,36 +7795,12 @@ "string-width": "^3.0.0" }, "dependencies": { - "ajv": { - "version": "6.12.6", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", - "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", - "dev": true, - "requires": { - "fast-deep-equal": "^3.1.1", - "fast-json-stable-stringify": "^2.0.0", - "json-schema-traverse": "^0.4.1", - "uri-js": "^4.2.2" - } - }, "ansi-regex": { "version": "4.1.0", "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-4.1.0.tgz", "integrity": "sha512-1apePfXM1UOSqw0o9IiFAovVz9M5S1Dg+4TrDwfMewQ6p/rmMueb7tWZjQ1rx4Loy1ArBggoqGpfqqdI4rondg==", "dev": true }, - "fast-deep-equal": { - "version": "3.1.3", - "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", - "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==", - "dev": true - }, - "is-fullwidth-code-point": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz", - "integrity": "sha1-o7MKXE8ZkYMWeqq5O+764937ZU8=", - "dev": true - }, "string-width": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/string-width/-/string-width-3.1.0.tgz", @@ -3387,33 +7834,6 @@ "resolved": "https://registry.npmjs.org/through/-/through-2.3.8.tgz", "integrity": "sha1-DdTJ/6q8NXlgsbckEV1+Doai4fU=" }, - "to-regex-range": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", - "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", - "dev": true, - "requires": { - "is-number": "^7.0.0" - } - }, - "tough-cookie": { - "version": "2.4.3", - "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-2.4.3.tgz", - "integrity": "sha512-Q5srk/4vDM54WJsJio3XNn6K2sCG+CQ8G5Wz6bZhRZoAe/+TxjWB/GlFAnYEbkYVlON9FMk/fE3h2RLpPXo4lQ==", - "dev": true, - "requires": { - "psl": "^1.1.24", - "punycode": "^1.4.1" - }, - "dependencies": { - "punycode": { - "version": "1.4.1", - "resolved": "https://registry.npmjs.org/punycode/-/punycode-1.4.1.tgz", - "integrity": "sha1-wNWmOycYgArY4esPpSachN1BhF4=", - "dev": true - } - } - }, "tsconfig-paths": { "version": "3.9.0", "resolved": "https://registry.npmjs.org/tsconfig-paths/-/tsconfig-paths-3.9.0.tgz", @@ -3426,21 +7846,6 @@ "strip-bom": "^3.0.0" } }, - "tunnel-agent": { - "version": "0.6.0", - "resolved": "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.6.0.tgz", - "integrity": "sha1-J6XeoGs2sEoKmWZ3SykIaPD8QP0=", - "dev": true, - "requires": { - "safe-buffer": "^5.0.1" - } - }, - "tweetnacl": { - "version": "0.14.5", - "resolved": "https://registry.npmjs.org/tweetnacl/-/tweetnacl-0.14.5.tgz", - "integrity": "sha1-WuaBd/GS1EViadEIr6k/+HQ/T2Q=", - "dev": true - }, "type-check": { "version": "0.3.2", "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.3.2.tgz", @@ -3484,12 +7889,6 @@ "punycode": "^2.1.0" } }, - "uuid": { - "version": "3.3.2", - "resolved": "https://registry.npmjs.org/uuid/-/uuid-3.3.2.tgz", - "integrity": "sha512-yXJmeNaw3DnnKAOKJE51sL/ZaYfWJRl1pK9dr19YFCu0ObS231AB1/LbqTKRAQ5kw8A90rA6fr4riOUpTZvQZA==", - "dev": true - }, "v8-compile-cache": { "version": "2.2.0", "resolved": "https://registry.npmjs.org/v8-compile-cache/-/v8-compile-cache-2.2.0.tgz", @@ -3506,17 +7905,6 @@ "spdx-expression-parse": "^3.0.0" } }, - "verror": { - "version": "1.10.0", - "resolved": "https://registry.npmjs.org/verror/-/verror-1.10.0.tgz", - "integrity": "sha1-OhBcoXBTr1XW4nDB+CiGguGNpAA=", - "dev": true, - "requires": { - "assert-plus": "^1.0.0", - "core-util-is": "1.0.2", - "extsprintf": "^1.2.0" - } - }, "which": { "version": "1.3.1", "resolved": "https://registry.npmjs.org/which/-/which-1.3.1.tgz", @@ -3526,21 +7914,6 @@ "isexe": "^2.0.0" } }, - "which-module": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/which-module/-/which-module-2.0.0.tgz", - "integrity": "sha1-2e8H3Od7mQK4o6j6SzHD4/fm6Ho=", - "dev": true - }, - "wide-align": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/wide-align/-/wide-align-1.1.3.tgz", - "integrity": "sha512-QGkOQc8XL6Bt5PwnsExKBPuMKBxnGxWWW3fU55Xt4feHozMUhdUMaBCk290qpm/wG5u/RSKzwdAC4i51YigihA==", - "dev": true, - "requires": { - "string-width": "^1.0.2 || 2" - } - }, "word-wrap": { "version": "1.2.3", "resolved": "https://registry.npmjs.org/word-wrap/-/word-wrap-1.2.3.tgz", @@ -3554,55 +7927,111 @@ "dev": true }, "workerpool": { - "version": "6.0.2", - "resolved": "https://registry.npmjs.org/workerpool/-/workerpool-6.0.2.tgz", - "integrity": "sha512-DSNyvOpFKrNusaaUwk+ej6cBj1bmhLcBfj80elGk+ZIo5JSkq+unB1dLKEOcNfJDZgjGICfhQ0Q5TbP0PvF4+Q==", + "version": "9.3.4", + "resolved": "https://registry.npmjs.org/workerpool/-/workerpool-9.3.4.tgz", + "integrity": "sha512-TmPRQYYSAnnDiEB0P/Ytip7bFGvqnSU6I2BcuSw7Hx+JSg/DsUi5ebYfc8GYaSdpuvOcEs6dXxPurOYpe9QFwg==", "dev": true }, "wrap-ansi": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-5.1.0.tgz", - "integrity": "sha512-QC1/iN/2/RPVJ5jYK8BGttj5z83LmSKmvbvrXPNCLZSEb32KKVDJDl/MOt2N01qU2H/FkzEa9PKto1BqDjtd7Q==", + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", + "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", "dev": true, "requires": { - "ansi-styles": "^3.2.0", - "string-width": "^3.0.0", - "strip-ansi": "^5.0.0" + "ansi-styles": "^4.0.0", + "string-width": "^4.1.0", + "strip-ansi": "^6.0.0" }, "dependencies": { "ansi-regex": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-4.1.0.tgz", - "integrity": "sha512-1apePfXM1UOSqw0o9IiFAovVz9M5S1Dg+4TrDwfMewQ6p/rmMueb7tWZjQ1rx4Loy1ArBggoqGpfqqdI4rondg==", + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", "dev": true }, "ansi-styles": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", - "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", "dev": true, "requires": { - "color-convert": "^1.9.0" + "color-convert": "^2.0.1" } }, - "string-width": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-3.1.0.tgz", - "integrity": "sha512-vafcv6KjVZKSgz06oM/H6GDBrAtz8vdhQakGjFIvNrHA6y3HCF1CInLy+QLq8dTJPQ1b+KDUqDFctkdRW44e1w==", + "color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", "dev": true, "requires": { - "emoji-regex": "^7.0.1", - "is-fullwidth-code-point": "^2.0.0", - "strip-ansi": "^5.1.0" + "color-name": "~1.1.4" } }, + "color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true + }, "strip-ansi": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-5.2.0.tgz", - "integrity": "sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA==", + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", "dev": true, "requires": { - "ansi-regex": "^4.1.0" + "ansi-regex": "^5.0.1" + } + } + } + }, + "wrap-ansi-cjs": { + "version": "npm:wrap-ansi@7.0.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", + "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", + "dev": true, + "requires": { + "ansi-styles": "^4.0.0", + "string-width": "^4.1.0", + "strip-ansi": "^6.0.0" + }, + "dependencies": { + "ansi-regex": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", + "dev": true + }, + "ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "requires": { + "color-convert": "^2.0.1" + } + }, + "color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "requires": { + "color-name": "~1.1.4" + } + }, + "color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true + }, + "strip-ansi": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "dev": true, + "requires": { + "ansi-regex": "^5.0.1" } } } @@ -3635,9 +8064,9 @@ "dev": true }, "y18n": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/y18n/-/y18n-4.0.1.tgz", - "integrity": "sha512-wNcy4NvjMYL8gogWWYAO7ZFWFfHcbdbE57tZO8e4cbpj8tfUcwrwqSl3ad8HxpYWCdXcJUCeKKZS62Av1affwQ==", + "version": "5.0.8", + "resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz", + "integrity": "sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==", "dev": true }, "yallist": { @@ -3647,103 +8076,25 @@ "dev": true }, "yargs": { - "version": "13.3.2", - "resolved": "https://registry.npmjs.org/yargs/-/yargs-13.3.2.tgz", - "integrity": "sha512-AX3Zw5iPruN5ie6xGRIDgqkT+ZhnRlZMLMHAs8tg7nRruy2Nb+i5o9bwghAogtM08q1dpr2LVoS8KSTMYpWXUw==", + "version": "17.7.2", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-17.7.2.tgz", + "integrity": "sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w==", "dev": true, "requires": { - "cliui": "^5.0.0", - "find-up": "^3.0.0", - "get-caller-file": "^2.0.1", + "cliui": "^8.0.1", + "escalade": "^3.1.1", + "get-caller-file": "^2.0.5", "require-directory": "^2.1.1", - "require-main-filename": "^2.0.0", - "set-blocking": "^2.0.0", - "string-width": "^3.0.0", - "which-module": "^2.0.0", - "y18n": "^4.0.0", - "yargs-parser": "^13.1.2" - }, - "dependencies": { - "ansi-regex": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-4.1.0.tgz", - "integrity": "sha512-1apePfXM1UOSqw0o9IiFAovVz9M5S1Dg+4TrDwfMewQ6p/rmMueb7tWZjQ1rx4Loy1ArBggoqGpfqqdI4rondg==", - "dev": true - }, - "find-up": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/find-up/-/find-up-3.0.0.tgz", - "integrity": "sha512-1yD6RmLI1XBfxugvORwlck6f75tYL+iR0jqwsOrOxMZyGYqUuDhJ0l4AXdO1iX/FTs9cBAMEk1gWSEx1kSbylg==", - "dev": true, - "requires": { - "locate-path": "^3.0.0" - } - }, - "locate-path": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-3.0.0.tgz", - "integrity": "sha512-7AO748wWnIhNqAuaty2ZWHkQHRSNfPVIsPIfwEOWO22AmaoVrWavlOcMR5nzTLNYvp36X220/maaRsrec1G65A==", - "dev": true, - "requires": { - "p-locate": "^3.0.0", - "path-exists": "^3.0.0" - } - }, - "p-limit": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", - "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", - "dev": true, - "requires": { - "p-try": "^2.0.0" - } - }, - "p-locate": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-3.0.0.tgz", - "integrity": "sha512-x+12w/To+4GFfgJhBEpiDcLozRJGegY+Ei7/z0tSLkMmxGZNybVMSfWj9aJn8Z5Fc7dBUNJOOVgPv2H7IwulSQ==", - "dev": true, - "requires": { - "p-limit": "^2.0.0" - } - }, - "p-try": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz", - "integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==", - "dev": true - }, - "string-width": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-3.1.0.tgz", - "integrity": "sha512-vafcv6KjVZKSgz06oM/H6GDBrAtz8vdhQakGjFIvNrHA6y3HCF1CInLy+QLq8dTJPQ1b+KDUqDFctkdRW44e1w==", - "dev": true, - "requires": { - "emoji-regex": "^7.0.1", - "is-fullwidth-code-point": "^2.0.0", - "strip-ansi": "^5.1.0" - } - }, - "strip-ansi": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-5.2.0.tgz", - "integrity": "sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA==", - "dev": true, - "requires": { - "ansi-regex": "^4.1.0" - } - } + "string-width": "^4.2.3", + "y18n": "^5.0.5", + "yargs-parser": "^21.1.1" } }, "yargs-parser": { - "version": "13.1.2", - "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-13.1.2.tgz", - "integrity": "sha512-3lbsNRf/j+A4QuSZfDRA7HRSfWrzO0YjqTJd5kjAq37Zep1CEgaYmrH9Q3GwPiB9cHyd1Y1UwggGhJGoxipbzg==", - "dev": true, - "requires": { - "camelcase": "^5.0.0", - "decamelize": "^1.2.0" - } + "version": "21.1.1", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-21.1.1.tgz", + "integrity": "sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw==", + "dev": true }, "yargs-unparser": { "version": "2.0.0", diff --git a/package.json b/package.json index aa7fd35..a9a9247 100644 --- a/package.json +++ b/package.json @@ -1,9 +1,9 @@ { - "version": "1.25.0", - "name": "httpsnippet", - "description": "HTTP Request snippet generator for *most* languages", - "author": "Ahmad Nassri (https://www.mashape.com/)", - "homepage": "https://github.com/Mashape/httpsnippet", + "version": "3.0.2", + "name": "@httptoolkit/httpsnippet", + "description": "HTTP request snippet generator for *most* languages", + "author": "Tim Perry ", + "homepage": "https://github.com/httptoolkit/httpsnippet", "license": "MIT", "main": "src/index.js", "bin": "bin/httpsnippet", @@ -38,23 +38,22 @@ "xmlhttprequest" ], "engines": { - "node": ">=10" + "node": ">=22" }, "files": [ "bin", "src" ], - "repository": "Mashape/httpsnippet", + "repository": "httptoolkit/httpsnippet", "bugs": { - "url": "https://github.com/Mashape/httpsnippet/issues" + "url": "https://github.com/httptoolkit/httpsnippet/issues" }, "scripts": { "quick": "mocha --no-timeouts --fgrep 'Request Validation' --invert", "pretest": "standard && echint", "test": "mocha --no-timeouts", - "posttest": "exit 0 && npm run coverage", - "coverage": "istanbul cover --dir coverage _mocha -- --fgrep 'Request Validation' --invert -R dot", - "codeclimate": "codeclimate < coverage/lcov.info" + "posttest": "npm run coverage", + "coverage": "istanbul cover --dir coverage _mocha -- --fgrep 'Request Validation' --invert -R dot" }, "standard": { "env": "mocha", @@ -70,11 +69,10 @@ ] }, "devDependencies": { - "codeclimate-test-reporter": "^0.5.1", "echint": "^4.0.2", "glob": "^6.0.1", "istanbul": "^0.4.0", - "mocha": "^8.2.1", + "mocha": "^11.7.5", "require-directory": "^2.1.1", "should": "^13.2.3", "standard": "^16.0.3" @@ -84,10 +82,9 @@ "commander": "^2.9.0", "debug": "^2.2.0", "event-stream": "3.3.4", - "form-data": "3.0.0", + "form-data": "3.0.4", "fs-readfile-promise": "^2.0.1", "fs-writefile-promise": "^1.0.3", - "har-validator": "^5.0.0", - "stringify-object": "^3.3.0" + "har-validator": "^5.0.0" } } diff --git a/src/helpers/code-builder.js b/src/helpers/code-builder.js index c1a75e8..245f3d7 100644 --- a/src/helpers/code-builder.js +++ b/src/helpers/code-builder.js @@ -1,6 +1,6 @@ 'use strict' -const util = require('util') +const { format: formatString } = require('./format') /** * Helper object to format and aggragate lines of code. @@ -13,6 +13,7 @@ const util = require('util') */ const CodeBuilder = function (indentation, join) { this.code = [] + this.indentLevel = 0 this.indentation = indentation this.lineJoin = join || '\n' } @@ -42,7 +43,7 @@ CodeBuilder.prototype.buildLine = function (indentationLevel, line) { if (Object.prototype.toString.call(indentationLevel) === '[object String]') { slice = 1 line = indentationLevel - indentationLevel = 0 + indentationLevel = this.indentLevel } else if (indentationLevel === null) { return null } @@ -55,7 +56,7 @@ CodeBuilder.prototype.buildLine = function (indentationLevel, line) { const format = Array.prototype.slice.call(arguments, slice, arguments.length) format.unshift(lineIndentation + line) - return util.format.apply(this, format) + return formatString.apply(this, format) } /** @@ -92,6 +93,18 @@ CodeBuilder.prototype.blank = function () { return this } +/** + * Add the line to the end of the last line. Creates a new line + * if no lines exist yet. + */ +CodeBuilder.prototype.pushToLast = function (line) { + if (!this.code) { + this.push(line) + } + const updatedLine = `${this.code[this.code.length - 1]}${line}` + this.code[this.code.length - 1] = updatedLine +} + /** * Concatenate all current lines using the given lineJoin * @return {string} @@ -100,4 +113,31 @@ CodeBuilder.prototype.join = function () { return this.code.join(this.lineJoin) } +/** + * Increase indentation level + * @returns {this} + */ +CodeBuilder.prototype.indent = function () { + this.indentLevel++ + return this +} + +/** + * Decrease indentation level + * @returns {this} + */ +CodeBuilder.prototype.unindent = function () { + this.indentLevel-- + return this +} + +/** + * Reset indentation level + * @returns {this} + */ +CodeBuilder.prototype.reindent = function () { + this.indentLevel = 0 + return this +} + module.exports = CodeBuilder diff --git a/src/helpers/format.js b/src/helpers/format.js new file mode 100644 index 0000000..fad620c --- /dev/null +++ b/src/helpers/format.js @@ -0,0 +1,92 @@ +const util = require('util') + +exports.escape = function escape (value, options) { + // The JSON-stringify string serialization algorithm, but generalized for string delimiters + // (e.g. " or ') and different escape characters (e.g. Powershell uses `) + // https://tc39.es/ecma262/multipage/structured-data.html#sec-quotejsonstring + const { + delimiter = '"', + escapeChar = '\\', + escapeNewlines = true + } = options || {} + + return [...value].map((c) => { + if (c === '\b') { + return escapeChar + 'b' + } else if (c === '\t') { + return escapeChar + 't' + } else if (c === '\n') { + if (escapeNewlines) { + return escapeChar + 'n' + } else { + return c // Don't just continue, or this is caught by < \u0020 + } + } else if (c === '\f') { + return escapeChar + 'f' + } else if (c === '\r') { + if (escapeNewlines) { + return escapeChar + 'r' + } else { + return c // Don't just continue, or this is caught by < \u0020 + } + } else if (c === escapeChar) { + return escapeChar + escapeChar + } else if (c === delimiter) { + return escapeChar + delimiter + } else if (c < '\u0020' || c > '\u007E') { + // Delegate the trickier non-ASCII cases to the normal algorithm. Some of these are escaped as + // \uXXXX, whilst others are represented literally. Since we're using this primarily for header + // values that are generally (though not strictly?) ASCII-only, this should almost never happen. + return JSON.stringify(c).slice(1, -1) + } else { + return c + } + }).join('') +} + +function doubleQuoteEscape (value) { + return exports.escape(value, { delimiter: '"' }) +} + +function singleQuoteEscape (value) { + return exports.escape(value, { delimiter: "'" }) +} + +/** + * Wraps the `util.format` function and adds the %qd, %qs and %v format options, + * where `%qd` escapes characters for a single-line double-quoted string, `%qs` + * escapes characters for a single-line single-quoted string, and `%v` + * JSON-stringifies the value. + * + * @param {string} value + * @param {...string} format + * + * @returns {string} Formatted string + */ +exports.format = function format (value, ...formatVariables) { + if (typeof value !== 'string') return '' + + let i = 0 + value = value.replace(/(? { + // JSON-stringify + if (m === '%v') { + const [elem] = formatVariables.splice(i, 1) + return JSON.stringify(elem) + } + // Escape for double-quoted string + if (m === '%qd') { + const [elem] = formatVariables.splice(i, 1) + return doubleQuoteEscape(elem) + } + // Escape for single-quoted string + if (m === '%qs') { + const [elem] = formatVariables.splice(i, 1) + return singleQuoteEscape(elem) + } + i += 1 + return m + }) + + const ret = util.format(value, ...formatVariables) + return ret +} diff --git a/src/helpers/stringify-js-object.js b/src/helpers/stringify-js-object.js new file mode 100644 index 0000000..186b351 --- /dev/null +++ b/src/helpers/stringify-js-object.js @@ -0,0 +1,134 @@ +// Closely based on v5.0.0 of stringify-object (BSD-2-Clause licensed), with +// modifications to simplify it for our use case (simpler obj & regex checks +// + object key retrieval) and no awkwardly incompatible ESM. + +module.exports = (input, options, pad) => { + const seen = [] + + return (function stringify (input, options = {}, pad = '') { + const indent = options.indent || '\t' + + let tokens + if (options.inlineCharacterLimit === undefined) { + tokens = { + newline: '\n', + newlineOrSpace: '\n', + pad, + indent: pad + indent + } + } else { + tokens = { + newline: '@@__STRINGIFY_OBJECT_NEW_LINE__@@', + newlineOrSpace: '@@__STRINGIFY_OBJECT_NEW_LINE_OR_SPACE__@@', + pad: '@@__STRINGIFY_OBJECT_PAD__@@', + indent: '@@__STRINGIFY_OBJECT_INDENT__@@' + } + } + + const expandWhiteSpace = string => { + if (options.inlineCharacterLimit === undefined) { + return string + } + + const oneLined = string + .replace(new RegExp(tokens.newline, 'g'), '') + .replace(new RegExp(tokens.newlineOrSpace, 'g'), ' ') + .replace(new RegExp(tokens.pad + '|' + tokens.indent, 'g'), '') + + if (oneLined.length <= options.inlineCharacterLimit) { + return oneLined + } + + return string + .replace(new RegExp(tokens.newline + '|' + tokens.newlineOrSpace, 'g'), '\n') + .replace(new RegExp(tokens.pad, 'g'), pad) + .replace(new RegExp(tokens.indent, 'g'), pad + indent) + } + + if (seen.includes(input)) { + return '"[Circular]"' + } + + if ( + input === null || + input === undefined || + typeof input === 'number' || + typeof input === 'boolean' || + typeof input === 'function' || + typeof input === 'symbol' || + input instanceof RegExp + ) { + return String(input) + } + + if (input instanceof Date) { + return `new Date('${input.toISOString()}')` + } + + if (Array.isArray(input)) { + if (input.length === 0) { + return '[]' + } + + seen.push(input) + + const returnValue = '[' + tokens.newline + input.map((element, i) => { + const eol = input.length - 1 === i ? tokens.newline : ',' + tokens.newlineOrSpace + + let value = stringify(element, options, pad + indent) + if (options.transform) { + value = options.transform(input, i, value) + } + + return tokens.indent + value + eol + }).join('') + tokens.pad + ']' + + seen.pop() + + return expandWhiteSpace(returnValue) + } + + if (typeof input === 'object') { + let objectKeys = Object.keys(input) + + if (options.filter) { + objectKeys = objectKeys.filter(element => options.filter(input, element)) + } + + if (objectKeys.length === 0) { + return '{}' + } + + seen.push(input) + + const returnValue = '{' + tokens.newline + objectKeys.map((element, index) => { + const eol = objectKeys.length - 1 === index ? tokens.newline : ',' + tokens.newlineOrSpace + const isSymbol = typeof element === 'symbol' + const isClassic = !isSymbol && /^[a-z$_][$\w]*$/i.test(element) + const key = isSymbol || isClassic ? element : stringify(element, options) + + let value = stringify(input[element], options, pad + indent) + if (options.transform) { + value = options.transform(input, element, value) + } + + return tokens.indent + String(key) + ': ' + value + eol + }).join('') + tokens.pad + '}' + + seen.pop() + + return expandWhiteSpace(returnValue) + } + + input = input.replace(/\\/g, '\\\\') + input = String(input).replace(/[\r\n]/g, x => x === '\n' ? '\\n' : '\\r') + + if (options.singleQuotes === false) { + input = input.replace(/"/g, '\\"') + return `"${input}"` + } + + input = input.replace(/'/g, '\\\'') + return `'${input}'` + })(input, options, pad) +} diff --git a/src/index.js b/src/index.js index c8ebfc8..0801c78 100644 --- a/src/index.js +++ b/src/index.js @@ -34,12 +34,12 @@ const HTTPSnippet = function (data) { entries.forEach(function (entry) { // add optional properties to make validation successful - entry.request.httpVersion = entry.request.httpVersion || 'HTTP/1.1' - entry.request.queryString = entry.request.queryString || [] - entry.request.headers = entry.request.headers || [] - entry.request.cookies = entry.request.cookies || [] - entry.request.postData = entry.request.postData || {} - entry.request.postData.mimeType = entry.request.postData.mimeType || 'application/octet-stream' + entry.request.httpVersion ||= 'HTTP/1.1' + entry.request.queryString ||= [] + entry.request.headers ||= [] + entry.request.cookies ||= [] + entry.request.postData ||= {} + entry.request.postData.mimeType ||= 'application/octet-stream' entry.request.bodySize = 0 entry.request.headersSize = 0 @@ -168,13 +168,21 @@ HTTPSnippet.prototype.prepare = function (request) { request.postData.boundary = boundary - // Since headers are case-sensitive we need to see if there's an existing `Content-Type` header that we can - // override. - const contentTypeHeader = helpers.hasHeader(request.headersObj, 'content-type') - ? helpers.getHeaderName(request.headersObj, 'content-type') - : 'content-type' + const multipartContentType = 'multipart/form-data; boundary=' + boundary - request.headersObj[contentTypeHeader] = 'multipart/form-data; boundary=' + boundary + // We need to update the various header states to match the CT to our boundary: + if (helpers.hasHeader(request.headersObj, 'content-type')) { + // Since headers are case-sensitive we need to see if there's an existing `Content-Type` + // header that we can override. + const contentTypeHeader = helpers.getHeaderName(request.headersObj, 'content-type') + request.headersObj[contentTypeHeader] = multipartContentType + + const headerEntry = request.headers.findLast(h => h.name.toLowerCase() === 'content-type') + headerEntry.value = multipartContentType + } else { + request.headersObj['Content-Type'] = multipartContentType + request.headers.push({ name: 'Content-Type', value: multipartContentType }) + } } break @@ -216,23 +224,37 @@ HTTPSnippet.prototype.prepare = function (request) { // eslint-disable-next-line node/no-deprecated-api request.uriObj = url.parse(request.url, true, true) - // merge all possible queryString values - request.queryObj = Object.assign(request.queryObj, request.uriObj.query) + // In some cases (unparseable/partially parseable query string) we want to fully preserve the + // original string (as it may not follow qs conventions at all). We assume any scenario where + // qs cannot reproduce the original value is this case. + const simpleQueryString = !request.uriObj.search || + (qs.stringify(request.uriObj.query) === request.uriObj.search.slice(1)) - // reset uriObj values for a clean url - request.uriObj.query = null - request.uriObj.search = null - request.uriObj.path = request.uriObj.pathname + if (simpleQueryString) { + // merge all possible queryString values + request.queryObj = Object.assign(request.queryObj, request.uriObj.query) - // keep the base url clean of queryString - request.url = url.format(request.uriObj) + // reset uriObj values for a clean url + request.uriObj.query = null + request.uriObj.search = null + request.uriObj.path = request.uriObj.pathname - // update the uri object - request.uriObj.query = request.queryObj - request.uriObj.search = qs.stringify(request.queryObj) + // keep the base url clean of queryString + request.url = url.format(request.uriObj) - if (request.uriObj.search) { - request.uriObj.path = request.uriObj.pathname + '?' + request.uriObj.search + // update the uri object + request.uriObj.query = request.queryObj + request.uriObj.search = qs.stringify(request.queryObj) + + if (request.uriObj.search) { + request.uriObj.path = request.uriObj.pathname + '?' + request.uriObj.search + } + } else { + // We keep the queryString in request.url (so it's sent raw everywhere) but disable it + // elsewhere, so it's omitted from automatic code generation cases. + // request.fullUrl is recreated below (maybe mild fixed?) but preserves raw search etc + request.queryString = [] + request.queryObj = {} } // construct a full url diff --git a/src/targets/c/libcurl.js b/src/targets/c/libcurl.js index 1609074..729bbec 100644 --- a/src/targets/c/libcurl.js +++ b/src/targets/c/libcurl.js @@ -1,6 +1,7 @@ 'use strict' const CodeBuilder = require('../../helpers/code-builder') +const helpers = require('../../helpers/headers') module.exports = function (source, options) { const code = new CodeBuilder() @@ -19,16 +20,16 @@ module.exports = function (source, options) { .push('struct curl_slist *headers = NULL;') headers.forEach(function (key) { - code.push('headers = curl_slist_append(headers, "%s: %s");', key, source.headersObj[key]) + code.push('headers = curl_slist_append(headers, "%s: %qd");', key, source.headersObj[key]) }) code.push('curl_easy_setopt(hnd, CURLOPT_HTTPHEADER, headers);') } // construct cookies - if (source.allHeaders.cookie) { + if (helpers.hasHeader(source.allHeaders, 'cookie')) { code.blank() - .push('curl_easy_setopt(hnd, CURLOPT_COOKIE, "%s");', source.allHeaders.cookie) + .push('curl_easy_setopt(hnd, CURLOPT_COOKIE, "%s");', helpers.getHeader(source.allHeaders, 'cookie')) } if (source.postData.text) { @@ -36,6 +37,11 @@ module.exports = function (source, options) { .push('curl_easy_setopt(hnd, CURLOPT_POSTFIELDS, %s);', JSON.stringify(source.postData.text)) } + if (helpers.hasHeader(source.allHeaders, 'accept-encoding')) { + code.blank() + .push('curl_easy_setopt(hnd, CURLOPT_ACCEPT_ENCODING, "");') + } + code.blank() .push('CURLcode ret = curl_easy_perform(hnd);') diff --git a/src/targets/clojure/clj_http.js b/src/targets/clojure/clj_http.js index dd92864..82dc069 100644 --- a/src/targets/clojure/clj_http.js +++ b/src/targets/clojure/clj_http.js @@ -12,6 +12,7 @@ const CodeBuilder = require('../../helpers/code-builder') const helpers = require('../../helpers/headers') +const { escape } = require('../../helpers/format') const Keyword = function (name) { this.name = name @@ -60,7 +61,7 @@ const padBlock = function (x, s) { const jsToEdn = function (js) { switch (jsType(js)) { case 'string': - return '"' + js.replace(/"/g, '\\"') + '"' + return '"' + escape(js, { delimiter: '"' }) + '"' case 'file': return js.toString() case 'keyword': @@ -73,7 +74,14 @@ const jsToEdn = function (js) { const obj = Object.keys(js) .reduce(function (acc, key) { const val = padBlock(key.length + 2, jsToEdn(js[key])) - return acc + ':' + key + ' ' + val + '\n ' + + // This check is overly strict, but good enough for us for + // all typical HTTP values we care about + const safeKey = key.match(/^[a-zA-Z_][\w-]*$/) + ? ':' + key + : jsToEdn(key) + + return acc + safeKey + ' ' + val + '\n ' }, '') .trim() return '{' + padBlock(1, obj) + '}' diff --git a/src/targets/crystal/index.js b/src/targets/crystal/index.js new file mode 100644 index 0000000..b1f84a2 --- /dev/null +++ b/src/targets/crystal/index.js @@ -0,0 +1,12 @@ +'use strict' + +module.exports = { + info: { + key: 'crystal', + title: 'Crystal', + extname: '.cr', + default: 'native' + }, + + native: require('./native') +} diff --git a/src/targets/crystal/native.js b/src/targets/crystal/native.js new file mode 100644 index 0000000..c284baa --- /dev/null +++ b/src/targets/crystal/native.js @@ -0,0 +1,68 @@ +/** + * @description + * HTTP code snippet generator for native Crystal + * + * @author + * @yanecc + * + * for any questions or issues regarding the generated code snippet, please open an issue mentioning the author. + */ + +const CodeBuilder = require('../../helpers/code-builder') + +const { escape } = require('../../helpers/format') + +module.exports = function ({ method: rawMethod, fullUrl, postData, allHeaders }, options = {}) { + const { insecureSkipVerify = false } = options + + const code = new CodeBuilder() + + code.push('require "http/client"') + + code.blank() + + code.push(`url = "${fullUrl}"`) + + const headers = Object.keys(allHeaders) + if (headers.length) { + code.push('headers = HTTP::Headers{') + headers.forEach(key => { + code.push(` "${key}" => "${escape(allHeaders[key])}"`) + }) + code.push('}') + } + + if (postData.text) { + code.push(`reqBody = ${JSON.stringify(postData.text)}`) + } + + code.blank() + + const method = rawMethod.toUpperCase() + const methods = ['GET', 'POST', 'HEAD', 'DELETE', 'PATCH', 'PUT', 'OPTIONS'] + + const headersContext = headers.length ? ', headers: headers' : '' + const bodyContext = postData.text ? ', body: reqBody' : '' + const sslContext = insecureSkipVerify ? ', tls: OpenSSL::SSL::Context::Client.insecure' : '' + + if (methods.includes(method)) { + code.push( + `response = HTTP::Client.${method.toLowerCase()} url${headersContext}${bodyContext}${sslContext}` + ) + } else { + code.push( + `response = HTTP::Client.exec "${method}", url${headersContext}${bodyContext}${sslContext}` + ) + } + + code.push('puts response.body') + + return code.join() +} + +module.exports.info = { + key: 'native', + title: 'http::client', + link: 'https://crystal-lang.org/api/master/HTTP/Client.html', + description: 'Crystal HTTP client' +} diff --git a/src/targets/csharp/httpclient.js b/src/targets/csharp/httpclient.js index 8523a00..1df3e0b 100644 --- a/src/targets/csharp/httpclient.js +++ b/src/targets/csharp/httpclient.js @@ -85,7 +85,7 @@ module.exports = function (source, options) { code.push(1, 'Headers =') code.push(1, '{') headers.forEach(function (key) { - code.push(2, '{ "%s", "%s" },', key, source.allHeaders[key]) + code.push(2, '{ "%s", "%qd" },', key, source.allHeaders[key]) }) code.push(1, '},') } diff --git a/src/targets/csharp/restsharp.js b/src/targets/csharp/restsharp.js index d724c36..63a4df1 100644 --- a/src/targets/csharp/restsharp.js +++ b/src/targets/csharp/restsharp.js @@ -1,17 +1,25 @@ 'use strict' const CodeBuilder = require('../../helpers/code-builder') +const { escape } = require('../../helpers/format') const helpers = require('../../helpers/headers') module.exports = function (source, options) { const code = new CodeBuilder() const methods = ['GET', 'POST', 'PUT', 'DELETE', 'PATCH', 'HEAD', 'OPTIONS'] + function toPascalCase (str) { + return str.replace( + /\w+/g, + word => word.charAt(0).toUpperCase() + word.slice(1).toLowerCase() + ) + } + if (methods.indexOf(source.method.toUpperCase()) === -1) { return 'Method not supported' } else { - code.push('var client = new RestClient("%s");', source.fullUrl) - code.push('var request = new RestRequest(Method.%s);', source.method.toUpperCase()) + code.push('var client = new RestClient("%s//%s");', source.uriObj.protocol, source.uriObj.host) + code.push('var request = new RestRequest("%s", Method.%s);', escape(source.uriObj.path), toPascalCase(source.method)) } // Add headers, including the cookies @@ -20,7 +28,7 @@ module.exports = function (source, options) { // construct headers if (headers.length) { headers.forEach(function (key) { - code.push('request.AddHeader("%s", "%s");', key, source.headersObj[key]) + code.push('request.AddHeader("%s", "%qd");', key, source.headersObj[key]) }) } @@ -32,14 +40,16 @@ module.exports = function (source, options) { } if (source.postData.text) { + const contentTypeHeader = helpers.getHeader(source.allHeaders, 'content-type') + code.push( - 'request.AddParameter("%s", %s, ParameterType.RequestBody);', - helpers.getHeader(source.allHeaders, 'content-type'), + 'request.AddParameter(%s, %s, ParameterType.RequestBody);', + contentTypeHeader ? `"${escape(contentTypeHeader)}"` : 'null', JSON.stringify(source.postData.text) ) } - code.push('IRestResponse response = client.Execute(request);') + code.push('var response = client.Execute(request);') return code.join() } diff --git a/src/targets/go/native.js b/src/targets/go/native.js index fe36c93..af038d5 100644 --- a/src/targets/go/native.js +++ b/src/targets/go/native.js @@ -11,6 +11,7 @@ 'use strict' const CodeBuilder = require('../../helpers/code-builder') +const helpers = require('../../helpers/headers') module.exports = function (source, options) { // Let's Go! @@ -47,6 +48,10 @@ module.exports = function (source, options) { code.push(indent, '"time"') } + if (opts.insecureSkipVerify) { + code.push(indent, '"crypto/tls"') + } + if (source.postData.text) { code.push(indent, '"strings"') } @@ -54,7 +59,7 @@ module.exports = function (source, options) { code.push(indent, '"net/http"') if (opts.printBody) { - code.push(indent, '"io/ioutil"') + code.push(indent, '"io"') } code.push(')') @@ -63,14 +68,28 @@ module.exports = function (source, options) { .blank() } + // Create an insecure transport for the client + if (opts.insecureSkipVerify) { + code.push(indent, 'insecureTransport := http.DefaultTransport.(*http.Transport).Clone()') + code.push(indent, 'insecureTransport.TLSClientConfig = &tls.Config{InsecureSkipVerify: true}') + } + // Create client let client - if (opts.timeout > 0) { + if (opts.timeout > 0 || opts.insecureSkipVerify) { client = 'client' code.push(indent, 'client := http.Client{') - .push(indent + 1, 'Timeout: time.Duration(%s * time.Second),', opts.timeout) - .push(indent, '}') - .blank() + + if (opts.timeout > 0) { + code.push(indent + 1, 'Timeout: time.Duration(%s * time.Second),', opts.timeout) + } + + if (opts.insecureSkipVerify) { + code.push(indent + 1, 'Transport: insecureTransport,') + } + + code.push(indent, '}') + code.blank() } else { client = 'http.DefaultClient' } @@ -92,9 +111,14 @@ module.exports = function (source, options) { errorCheck() // Add headers + + // Go automatically adds this and handles decompression, as long as we don't try to + // manually add it ourselves: + delete source.allHeaders[helpers.getHeaderName(source.allHeaders, 'accept-encoding')] + if (Object.keys(source.allHeaders).length) { Object.keys(source.allHeaders).forEach(function (key) { - code.push(indent, 'req.Header.Add("%s", "%s")', key, source.allHeaders[key]) + code.push(indent, 'req.Header.Add("%s", "%qd")', key, source.allHeaders[key]) }) code.blank() @@ -108,7 +132,7 @@ module.exports = function (source, options) { if (opts.printBody) { code.blank() .push(indent, 'defer res.Body.Close()') - .push(indent, 'body, %s := ioutil.ReadAll(res.Body)', errorPlaceholder) + .push(indent, 'body, %s := io.ReadAll(res.Body)', errorPlaceholder) errorCheck() } diff --git a/src/targets/http/http1.1.js b/src/targets/http/http1.1.js index 58b5918..4a391c2 100644 --- a/src/targets/http/http1.1.js +++ b/src/targets/http/http1.1.js @@ -43,21 +43,27 @@ module.exports = function (source, options) { code.push('%s %s %s', source.method, requestUrl, source.httpVersion) // RFC 7231 Section 5. Header Fields - Object.keys(source.allHeaders).forEach(function (key) { - // Capitalize header keys, even though it's not required by the spec. - const keyCapitalized = key.toLowerCase().replace(/(^|-)(\w)/g, function (x) { - return x.toUpperCase() - }) - + source.headers.forEach((header) => { code.push( '%s', - util.format('%s: %s', keyCapitalized, source.allHeaders[key]) + util.format('%s: %s', header.name, header.value) ) }) + // Unlike most other snippets, we use the fully raw input here (not headerObj/allHeaders) + // so we need to hook into the prepare() cookie injection logic: + if (source.allHeaders.cookie && !source.headers.find(h => h.name.toLowerCase() === 'cookie')) { + code.push( + '%s', + util.format('%s: %s', 'Cookie', source.allHeaders.cookie) + ) + } + + const headerKeys = Object.keys(source.allHeaders).map(k => k.toLowerCase()) + // RFC 7230 Section 5.4. Host // Automatically set Host header if option is on and on header already exists. - if (opts.autoHost && Object.keys(source.allHeaders).indexOf('host') === -1) { + if (opts.autoHost && headerKeys.indexOf('host') === -1) { code.push('Host: %s', source.uriObj.host) } @@ -66,7 +72,7 @@ module.exports = function (source, options) { if ( opts.autoContentLength && source.postData.text && - Object.keys(source.allHeaders).indexOf('content-length') === -1 + headerKeys.indexOf('conteTnt-length') === -1 ) { code.push( 'Content-Length: %d', diff --git a/src/targets/index.js b/src/targets/index.js index dd90b48..9687e9d 100644 --- a/src/targets/index.js +++ b/src/targets/index.js @@ -3,6 +3,7 @@ module.exports = { c: require('./c'), clojure: require('./clojure'), + crystal: require('./crystal'), csharp: require('./csharp'), go: require('./go'), http: require('./http'), @@ -17,6 +18,7 @@ module.exports = { python: require('./python'), r: require('./r'), ruby: require('./ruby'), + rust: require('./rust'), shell: require('./shell'), swift: require('./swift') } diff --git a/src/targets/java/asynchttp.js b/src/targets/java/asynchttp.js index ce3db5d..fd0957b 100644 --- a/src/targets/java/asynchttp.js +++ b/src/targets/java/asynchttp.js @@ -29,7 +29,7 @@ module.exports = function (source, options) { // construct headers if (headers.length) { headers.forEach(function (key) { - code.push(1, '.setHeader("%s", "%s")', key, source.allHeaders[key]) + code.push(1, '.setHeader("%s", "%qd")', key, source.allHeaders[key]) }) } diff --git a/src/targets/java/index.js b/src/targets/java/index.js index 37b0db7..ca0b259 100644 --- a/src/targets/java/index.js +++ b/src/targets/java/index.js @@ -11,5 +11,6 @@ module.exports = { okhttp: require('./okhttp'), unirest: require('./unirest'), asynchttp: require('./asynchttp'), - nethttp: require('./nethttp') + nethttp: require('./nethttp'), + restclient: require('./restclient') } diff --git a/src/targets/java/nethttp.js b/src/targets/java/nethttp.js index 328eeaa..5a81181 100644 --- a/src/targets/java/nethttp.js +++ b/src/targets/java/nethttp.js @@ -30,7 +30,7 @@ module.exports = function (source, options) { // construct headers if (headers.length) { headers.forEach(function (key) { - code.push(2, '.header("%s", "%s")', key, source.allHeaders[key]) + code.push(2, '.header("%s", "%qd")', key, source.allHeaders[key]) }) } diff --git a/src/targets/java/okhttp.js b/src/targets/java/okhttp.js index 3dc7564..b5c8d62 100644 --- a/src/targets/java/okhttp.js +++ b/src/targets/java/okhttp.js @@ -59,7 +59,7 @@ module.exports = function (source, options) { // construct headers if (headers.length) { headers.forEach(function (key) { - code.push(1, '.addHeader("%s", "%s")', key, source.allHeaders[key]) + code.push(1, '.addHeader("%s", "%qd")', key, source.allHeaders[key]) }) } diff --git a/src/targets/java/restclient.js b/src/targets/java/restclient.js new file mode 100644 index 0000000..a4fbeb5 --- /dev/null +++ b/src/targets/java/restclient.js @@ -0,0 +1,184 @@ +/** + * @description + * HTTP code snippet generator for Java using Spring RestClient. + * + * @author + * @jamezrin + * + * for any questions or issues regarding the generated code snippet, please open an issue mentioning the author. + */ + +'use strict' + +const CodeBuilder = require('../../helpers/code-builder') + +const standardMethods = ['GET', 'HEAD', 'POST', 'PUT', 'PATCH', 'DELETE', 'OPTIONS', 'TRACE'] + +const standardMediaTypes = { + 'application/atom+xml': 'APPLICATION_ATOM_XML', + 'application/cbor': 'APPLICATION_CBOR', + 'application/x-www-form-urlencoded': 'APPLICATION_FORM_URLENCODED', + 'application/graphql-response+json': 'APPLICATION_GRAPHQL_RESPONSE', + 'application/json': 'APPLICATION_JSON', + 'application/x-ndjson': 'APPLICATION_NDJSON', + 'application/octet-stream': 'APPLICATION_OCTET_STREAM', + 'application/pdf': 'APPLICATION_PDF', + 'application/problem+json': 'APPLICATION_PROBLEM_JSON', + 'application/problem+xml': 'APPLICATION_PROBLEM_XML', + 'application/x-protobuf': 'APPLICATION_PROTOBUF', + 'application/rss+xml': 'APPLICATION_RSS_XML', + 'application/xhtml+xml': 'APPLICATION_XHTML_XML', + 'application/xml': 'APPLICATION_XML', + 'application/yaml': 'APPLICATION_YAML', + 'image/gif': 'IMAGE_GIF', + 'image/jpeg': 'IMAGE_JPEG', + 'image/png': 'IMAGE_PNG', + 'multipart/form-data': 'MULTIPART_FORM_DATA', + 'multipart/mixed': 'MULTIPART_MIXED', + 'multipart/related': 'MULTIPART_RELATED', + 'text/event-stream': 'TEXT_EVENT_STREAM', + 'text/html': 'TEXT_HTML', + 'text/markdown': 'TEXT_MARKDOWN', + 'text/plain': 'TEXT_PLAIN', + 'text/xml': 'TEXT_XML' +} + +const multipartMimeTypes = [ + 'multipart/form-data', + 'multipart/mixed', + 'multipart/related', + 'multipart/alternative' +] + +module.exports = function (source, options) { + const opts = Object.assign({ + indent: ' ', + entityType: 'String' + }, options) + + const state = { + bodyType: null + } + + const code = new CodeBuilder(opts.indent) + + code.push('RestClient restClient = RestClient.create();') + .blank() + + if (source.postData) { + if (source.postData.params && source.postData.mimeType === 'application/x-www-form-urlencoded') { + state.bodyType = 'form' + + code.push('MultiValueMap formDataMap = new LinkedMultiValueMap<>();') + + source.postData.params.forEach(function (param) { + code.push('formDataMap.add("%qd", "%qd");', param.name, param.value) + }) + + code.blank() + } else if (source.postData.params && multipartMimeTypes.includes(source.postData.mimeType)) { + state.bodyType = 'multipart' + + code.push('MultipartBodyBuilder multipartBuilder = new MultipartBodyBuilder();') + + source.postData.params.forEach(function (param) { + if (param.fileName) { + if (param.value) { + code.push('multipartBuilder.part("%s", "%qd")', param.name, param.value) + code.push(1, '.filename("%s")', param.fileName) + } else { + code.push('multipartBuilder.part("%s", new FileSystemResource("%s"))', param.name, param.fileName) + } + + if (param.contentType) { + const mediaTypeConstant = standardMediaTypes[param.contentType] + if (mediaTypeConstant) { + code.push(1, '.contentType(MediaType.%s);', mediaTypeConstant) + } else { + code.push(1, '.contentType(MediaType.parseMediaType("%s"));', param.contentType) + } + } else { + code.push(1, ';') + } + } else { + code.push('multipartBuilder.part("%s", "%qd");', param.name, param.value || '') + } + }) + + code.blank() + } else if (source.postData.text) { + state.bodyType = 'plaintext' + } + } + + code.push('ResponseEntity<%s> response = restClient', opts.entityType) + + if (standardMethods.includes(source.method.toUpperCase())) { + code.push(1, '.method(HttpMethod.%s)', source.method.toUpperCase()) + } else { + code.push(1, '.method(HttpMethod.valueOf("%s"))', source.method.toUpperCase()) + } + + if (Object.keys(source.queryObj).length) { + code.push(1, '.uri("%s", uriBuilder -> {', source.url) + + Object.keys(source.queryObj).forEach(function (key) { + const value = source.queryObj[key] + const iterable = Array.isArray(value) ? value : [value] + iterable.forEach(function (val) { + code.push(2, 'uriBuilder.queryParam("%qd", "%qd");', key, val) + }) + }) + + code.push(2, 'return uriBuilder.build();') + code.push(1, '})') + } else { + code.push(1, '.uri("%s")', source.url) + } + + if (source.cookies && source.cookies.length) { + source.cookies.forEach(function (cookie) { + code.push(1, '.cookie("%qd", "%qd")', cookie.name, cookie.value) + }) + } + + const headers = Object.keys(source.headersObj) + if (headers.length) { + headers.forEach(function (key) { + if (key.toLowerCase() !== 'content-type') { + code.push(1, '.header("%s", "%qd")', key, source.headersObj[key]) + } + }) + } + + if (source.postData && state.bodyType) { + if (source.postData.mimeType) { + const mediaTypeEnumConstant = standardMediaTypes[source.postData.mimeType] + if (mediaTypeEnumConstant) { + code.push(1, '.contentType(MediaType.%s)', mediaTypeEnumConstant) + } else { + code.push(1, '.contentType(MediaType.parseMediaType("%s"))', source.postData.mimeType) + } + } + + if (state.bodyType === 'form') { + code.push(1, '.body(formDataMap)') + } else if (state.bodyType === 'multipart') { + code.push(1, '.body(multipartBuilder.build())') + } else if (state.bodyType === 'plaintext') { + code.push(1, '.body("%qd")', source.postData.text) + } + } + + code.push(1, '.retrieve()') + code.push(1, '.toEntity(%s.class);', opts.entityType) + + return code.join() +} + +module.exports.info = { + key: 'restclient', + title: 'Spring RestClient', + link: 'https://docs.spring.io/spring-framework/docs/current/javadoc-api/org/springframework/web/client/RestClient.html', + description: 'Spring Framework REST client' +} diff --git a/src/targets/java/unirest.js b/src/targets/java/unirest.js index 7def78e..e449b52 100644 --- a/src/targets/java/unirest.js +++ b/src/targets/java/unirest.js @@ -33,7 +33,7 @@ module.exports = function (source, options) { // construct headers if (headers.length) { headers.forEach(function (key) { - code.push(1, '.header("%s", "%s")', key, source.allHeaders[key]) + code.push(1, '.header("%s", "%qd")', key, source.allHeaders[key]) }) } diff --git a/src/targets/javascript/axios.js b/src/targets/javascript/axios.js index 838eb0d..3b3db45 100644 --- a/src/targets/javascript/axios.js +++ b/src/targets/javascript/axios.js @@ -10,7 +10,7 @@ 'use strict' const util = require('util') -const stringifyObject = require('stringify-object') +const stringifyObject = require('../../helpers/stringify-js-object') const CodeBuilder = require('../../helpers/code-builder') module.exports = function (source, options) { diff --git a/src/targets/javascript/fetch.js b/src/targets/javascript/fetch.js index 2bf213f..aacebc1 100644 --- a/src/targets/javascript/fetch.js +++ b/src/targets/javascript/fetch.js @@ -21,7 +21,7 @@ module.exports = function (source, options) { options ) - const stringifyObject = require('stringify-object') + const stringifyObject = require('../../helpers/stringify-js-object') const code = new CodeBuilder(opts.indent) options = { @@ -67,7 +67,17 @@ module.exports = function (source, options) { } } - code.push('const options = %s;', stringifyObject(options, { indent: opts.indent, inlineCharacterLimit: 80 })) + code.push('const options = %s;', stringifyObject(options, { + indent: opts.indent, + inlineCharacterLimit: 80, + transform: (object, property, originalResult) => { + if (property === 'body' && source.postData.mimeType === 'application/x-www-form-urlencoded') { + return `new URLSearchParams(${originalResult})` + } + + return originalResult + } + })) .blank() if (source.postData.mimeType === 'multipart/form-data') { @@ -75,7 +85,7 @@ module.exports = function (source, options) { .blank() } - code.push("fetch('%s', options)", source.fullUrl) + code.push('fetch(%s, options)', stringifyObject(source.fullUrl)) .push(1, '.then(response => response.json())') .push(1, '.then(response => console.log(response))') .push(1, '.catch(err => console.error(err));') diff --git a/src/targets/kotlin/okhttp.js b/src/targets/kotlin/okhttp.js index 8c13905..8be95db 100644 --- a/src/targets/kotlin/okhttp.js +++ b/src/targets/kotlin/okhttp.js @@ -59,7 +59,7 @@ module.exports = function (source, options) { // construct headers if (headers.length) { headers.forEach(function (key) { - code.push(1, '.addHeader("%s", "%s")', key, source.allHeaders[key]) + code.push(1, '.addHeader("%s", "%qd")', key, source.allHeaders[key]) }) } diff --git a/src/targets/node/axios.js b/src/targets/node/axios.js index 92387de..8bf49e4 100644 --- a/src/targets/node/axios.js +++ b/src/targets/node/axios.js @@ -10,7 +10,7 @@ 'use strict' const util = require('util') -const stringifyObject = require('stringify-object') +const stringifyObject = require('../../helpers/stringify-js-object') const CodeBuilder = require('../../helpers/code-builder') module.exports = function (source, options) { diff --git a/src/targets/node/fetch.js b/src/targets/node/fetch.js index 971d817..3ed4a43 100644 --- a/src/targets/node/fetch.js +++ b/src/targets/node/fetch.js @@ -10,7 +10,7 @@ 'use strict' -const stringifyObject = require('stringify-object') +const stringifyObject = require('../../helpers/stringify-js-object') const CodeBuilder = require('../../helpers/code-builder') module.exports = function (source, options) { @@ -88,7 +88,7 @@ module.exports = function (source, options) { } } code.blank() - code.push('let url = \'' + url + '\';') + code.push('let url = ' + stringifyObject(url) + ';') .blank() code.push('let options = %s;', stringifyObject(reqOpts, { indent: ' ', inlineCharacterLimit: 80 })) .blank() diff --git a/src/targets/node/native.js b/src/targets/node/native.js index a61e63c..bb6e3fb 100644 --- a/src/targets/node/native.js +++ b/src/targets/node/native.js @@ -10,7 +10,7 @@ 'use strict' -const stringifyObject = require('stringify-object') +const stringifyObject = require('../../helpers/stringify-js-object') const CodeBuilder = require('../../helpers/code-builder') module.exports = function (source, options) { @@ -28,6 +28,10 @@ module.exports = function (source, options) { headers: source.allHeaders } + if (options && options.insecureSkipVerify) { + reqOpts.rejectUnauthorized = false + } + code.push('const http = require("%s");', source.uriObj.protocol.replace(':', '')) code.blank() diff --git a/src/targets/node/request.js b/src/targets/node/request.js index 258c736..b47e9f5 100644 --- a/src/targets/node/request.js +++ b/src/targets/node/request.js @@ -11,7 +11,7 @@ 'use strict' const util = require('util') -const stringifyObject = require('stringify-object') +const stringifyObject = require('../../helpers/stringify-js-object') const CodeBuilder = require('../../helpers/code-builder') module.exports = function (source, options) { diff --git a/src/targets/objc/helpers.js b/src/targets/objc/helpers.js index 14d136e..18ded19 100644 --- a/src/targets/objc/helpers.js +++ b/src/targets/objc/helpers.js @@ -2,6 +2,8 @@ const util = require('util') +const { escape } = require('../../helpers/format') + module.exports = { /** * Create an string of given length filled with blank spaces @@ -73,7 +75,7 @@ module.exports = { if (value === null || value === undefined) { return '' } - return '@"' + value.toString().replace(/"/g, '\\"') + '"' + return '@"' + escape(value.toString(), { delimiter: '"' }) + '"' } } } diff --git a/src/targets/objc/nsurlsession.js b/src/targets/objc/nsurlsession.js index 1f17600..b3f7173 100644 --- a/src/targets/objc/nsurlsession.js +++ b/src/targets/objc/nsurlsession.js @@ -91,7 +91,9 @@ module.exports = function (source, options) { default: code.blank() - .push('NSData *postData = [[NSData alloc] initWithData:[@"' + source.postData.text + '" dataUsingEncoding:NSUTF8StringEncoding]];') + .push('NSData *postData = [[NSData alloc] initWithData:[' + + helpers.literalRepresentation(source.postData.text) + + ' dataUsingEncoding:NSUTF8StringEncoding]];') } } diff --git a/src/targets/ocaml/cohttp.js b/src/targets/ocaml/cohttp.js index 76e2335..6abbcb0 100644 --- a/src/targets/ocaml/cohttp.js +++ b/src/targets/ocaml/cohttp.js @@ -30,12 +30,12 @@ module.exports = function (source, options) { const headers = Object.keys(source.allHeaders) if (headers.length === 1) { - code.push('let headers = Header.add (Header.init ()) "%s" "%s" in', headers[0], source.allHeaders[headers[0]]) + code.push('let headers = Header.add (Header.init ()) "%s" "%qd" in', headers[0], source.allHeaders[headers[0]]) } else if (headers.length > 1) { code.push('let headers = Header.add_list (Header.init ()) [') headers.forEach(function (key) { - code.push(1, '("%s", "%s");', key, source.allHeaders[key]) + code.push(1, '("%s", "%qd");', key, source.allHeaders[key]) }) code.push('] in') diff --git a/src/targets/php/curl.js b/src/targets/php/curl.js index 1a7b6a8..37a5d82 100644 --- a/src/targets/php/curl.js +++ b/src/targets/php/curl.js @@ -10,8 +10,9 @@ 'use strict' -const util = require('util') +const { format } = require('../../helpers/format') const CodeBuilder = require('../../helpers/code-builder') +const { phpSqEscape } = require('./helpers') module.exports = function (source, options) { const opts = Object.assign({ @@ -78,7 +79,16 @@ module.exports = function (source, options) { curlOptions.forEach(function (option) { if (!~[null, undefined].indexOf(option.value)) { - curlopts.push(util.format('%s => %s,', option.name, option.escape ? JSON.stringify(option.value) : option.value)) + curlopts.push( + format('%s => %s,', + option.name, + option.escape && typeof option.value === 'string' + ? `'${phpSqEscape(option.value)}'` + : option.escape + ? JSON.stringify(option.value) + : option.value + ) + ) } }) @@ -88,12 +98,12 @@ module.exports = function (source, options) { }) if (cookies.length) { - curlopts.push(util.format('CURLOPT_COOKIE => "%s",', cookies.join('; '))) + curlopts.push(format("CURLOPT_COOKIE => '%s'", phpSqEscape(cookies.join('; ')))) } // construct cookies const headers = Object.keys(source.headersObj).sort().map(function (key) { - return util.format('"%s: %s"', key, source.headersObj[key]) + return format("'%s: %s'", phpSqEscape(key), phpSqEscape(source.headersObj[key])) }) if (headers.length) { @@ -113,9 +123,9 @@ module.exports = function (source, options) { .push('if ($err) {') if (opts.namedErrors) { - code.push(1, 'echo array_flip(get_defined_constants(true)["curl"])[$err];') + code.push(1, "echo array_flip(get_defined_constants(true)['curl'])[$err];") } else { - code.push(1, 'echo "cURL Error #:" . $err;') + code.push(1, "echo 'cURL Error #:' . $err;") } code.push('} else {') diff --git a/src/targets/php/helpers.js b/src/targets/php/helpers.js index 266d72b..c1dffd0 100644 --- a/src/targets/php/helpers.js +++ b/src/targets/php/helpers.js @@ -1,5 +1,8 @@ 'use strict' +// PHP single quotes are super simple - all escapes ignored except sq & slash +const phpSqEscape = val => val.replace(/\\/g, '\\\\').replace(/'/g, "\\'") + const convert = function (obj, indent, lastIndent) { let i, result @@ -17,7 +20,7 @@ const convert = function (obj, indent, lastIndent) { break case '[object String]': - result = "'" + obj.replace(/\\/g, '\\\\').replace(/'/g, "'") + "'" + result = "'" + phpSqEscape(obj) + "'" break case '[object Number]': @@ -53,6 +56,7 @@ const convert = function (obj, indent, lastIndent) { } module.exports = { + phpSqEscape: phpSqEscape, convert: convert, methods: [ 'ACL', diff --git a/src/targets/powershell/common.js b/src/targets/powershell/common.js index e6c53a5..9254300 100644 --- a/src/targets/powershell/common.js +++ b/src/targets/powershell/common.js @@ -3,14 +3,30 @@ const CodeBuilder = require('../../helpers/code-builder') const helpers = require('../../helpers/headers') +// Within a single quote, the ONLY character to worry about is the single quote +// itself (escaped by doubling). Newlines, backticks, slashes etc are all treated +// as literal characters. +const psSqEscape = function (input) { + return input + .replace(/'/g, "''") +} + module.exports = function (command) { return function (source, options) { const code = new CodeBuilder() - const methods = ['GET', 'POST', 'PUT', 'DELETE', 'PATCH', 'HEAD', 'OPTIONS'] - - if (methods.indexOf(source.method.toUpperCase()) === -1) { - return 'Method not supported' - } + const methods = [ + 'DEFAULT', + 'DELETE', + 'GET', + 'HEAD', + 'MERGE', + 'OPTIONS', + 'PATCH', + 'POST', + 'PUT', + 'TRACE' + ] + const methodArg = methods.includes(source.method.toUpperCase()) ? '-Method' : '-CustomMethod' const commandOptions = [] @@ -22,7 +38,10 @@ module.exports = function (command) { code.push('$headers=@{}') headers.forEach(function (key) { if (key !== 'connection') { // Not allowed - code.push('$headers.Add("%s", "%s")', key, source.headersObj[key]) + code.push("$headers.Add('%s', '%s')", + psSqEscape(key), + psSqEscape(source.headersObj[key]) + ) } }) commandOptions.push('-Headers $headers') @@ -35,9 +54,9 @@ module.exports = function (command) { source.cookies.forEach(function (cookie) { code.push('$cookie = New-Object System.Net.Cookie') - code.push("$cookie.Name = '%s'", cookie.name) - code.push("$cookie.Value = '%s'", cookie.value) - code.push("$cookie.Domain = '%s'", source.uriObj.host) + code.push("$cookie.Name = '%s'", psSqEscape(cookie.name)) + code.push("$cookie.Value = '%s'", psSqEscape(cookie.value)) + code.push("$cookie.Domain = '%s'", psSqEscape(source.uriObj.host)) code.push('$session.Cookies.Add($cookie)') }) @@ -45,11 +64,23 @@ module.exports = function (command) { } if (source.postData.text) { - commandOptions.push("-ContentType '" + helpers.getHeader(source.allHeaders, 'content-type') + "'") - commandOptions.push("-Body '" + source.postData.text + "'") + const contentType = helpers.getHeader(source.allHeaders, 'content-type') + if (contentType) { + commandOptions.push("-ContentType '" + psSqEscape(contentType) + "'") + } + + commandOptions.push( + "-Body '" + psSqEscape(source.postData.text) + "'" + ) } - code.push("$response = %s -Uri '%s' -Method %s %s", command, source.fullUrl, source.method, commandOptions.join(' ')) + code.push("$response = %s -Uri '%s' %s %s %s", + command, + psSqEscape(source.fullUrl), + methodArg, + source.method, + commandOptions.join(' ') + ) return code.join() } } diff --git a/src/targets/python/helpers.js b/src/targets/python/helpers.js index 46f72d8..cdec9ca 100644 --- a/src/targets/python/helpers.js +++ b/src/targets/python/helpers.js @@ -62,7 +62,12 @@ module.exports = { case '[object Object]': { const keyValuePairs = [] for (const k in value) { - keyValuePairs.push(util.format('"%s": %s', k, this.literalRepresentation(value[k], opts, indentLevel))) + keyValuePairs.push( + util.format('%s: %s', + this.literalRepresentation(k, opts, indentLevel), + this.literalRepresentation(value[k], opts, indentLevel) + ) + ) } return concatValues('object', keyValuePairs, opts.pretty && keyValuePairs.length > 1, opts.indent, indentLevel) } @@ -77,7 +82,7 @@ module.exports = { if (value === null || value === undefined) { return '' } - return '"' + value.toString().replace(/"/g, '\\"') + '"' + return JSON.stringify(value) } } } diff --git a/src/targets/python/python3.js b/src/targets/python/python3.js index ab24559..fd0d121 100644 --- a/src/targets/python/python3.js +++ b/src/targets/python/python3.js @@ -11,18 +11,39 @@ 'use strict' const CodeBuilder = require('../../helpers/code-builder') +const helpers = require('../../helpers/headers') module.exports = function (source, options) { const code = new CodeBuilder() + // Start Request code.push('import http.client') - .blank() + + if (options.insecureSkipVerify) { + code.push('import ssl') + } + + const mayBeGzipped = helpers.hasHeader(source.allHeaders, 'accept-encoding') && + helpers.getHeader(source.allHeaders, 'accept-encoding').includes('gzip') + + if (mayBeGzipped) { + code.push('import gzip') + } + + code.blank() // Check which protocol to be used for the client connection const protocol = source.uriObj.protocol if (protocol === 'https:') { - code.push('conn = http.client.HTTPSConnection("%s")', source.uriObj.host) - .blank() + if (options.insecureSkipVerify) { + code.push( + 'conn = http.client.HTTPSConnection("%s", context = ssl._create_unverified_context())', + source.uriObj.host + ).blank() + } else { + code.push('conn = http.client.HTTPSConnection("%s")', source.uriObj.host) + .blank() + } } else { code.push('conn = http.client.HTTPConnection("%s")', source.uriObj.host) .blank() @@ -40,7 +61,7 @@ module.exports = function (source, options) { const headerCount = Object.keys(headers).length if (headerCount === 1) { for (const header in headers) { - code.push('headers = { "%s": "%s" }', header, headers[header]) + code.push('headers = { "%s": "%qd" }', header, headers[header]) .blank() } } else if (headerCount > 1) { @@ -50,13 +71,13 @@ module.exports = function (source, options) { for (const header in headers) { if (count++ !== headerCount) { - code.push(' "%s": "%s",', header, headers[header]) + code.push(' "%s": "%qd",', header, headers[header]) } else { - code.push(' "%s": "%s"', header, headers[header]) + code.push(' "%s": "%qd"', header, headers[header]) } } - code.push(' }') + code.push('}') .blank() } @@ -78,7 +99,16 @@ module.exports = function (source, options) { .push('res = conn.getresponse()') .push('data = res.read()') .blank() - .push('print(data.decode("utf-8"))') + + // Decode response + if (mayBeGzipped) { + code.push("if res.headers['content-encoding'] == 'gzip':") + code.push(' print(gzip.decompress(data).decode("utf-8"))') + code.push('else:') + code.push(' print(data.decode("utf-8"))') + } else { + code.push('print(data.decode("utf-8"))') + } return code.join() } diff --git a/src/targets/python/requests.js b/src/targets/python/requests.js index 394656f..1938f97 100644 --- a/src/targets/python/requests.js +++ b/src/targets/python/requests.js @@ -85,7 +85,7 @@ module.exports = function (source, options) { if (headerCount === 1) { for (const header in headers) { - code.push('headers = { "%s": "%s" }', header, headers[header]) + code.push('headers = { "%s": "%qd" }', header, headers[header]) .blank() } } else if (headerCount > 1) { @@ -95,9 +95,9 @@ module.exports = function (source, options) { for (const header in headers) { if (count++ !== headerCount) { - code.push(1, '"%s": "%s",', header, headers[header]) + code.push(1, '"%s": "%qd",', header, headers[header]) } else { - code.push(1, '"%s": "%s"', header, headers[header]) + code.push(1, '"%s": "%qd"', header, headers[header]) } } diff --git a/src/targets/r/httr.js b/src/targets/r/httr.js index db68df2..0b815a6 100644 --- a/src/targets/r/httr.js +++ b/src/targets/r/httr.js @@ -11,6 +11,8 @@ 'use strict' const util = require('util') +const { escape } = require('../../helpers/format') +const { getHeader } = require('../../helpers/headers') const CodeBuilder = require('../../helpers/code-builder') module.exports = function (source, options) { @@ -39,10 +41,14 @@ module.exports = function (source, options) { code.push('queryString <- list(') for (const query in qs) { + const safeKey = query.match(/^[a-zA-Z][\w._]*$/) + ? query + : '"' + escape(query) + '"' + if (count++ !== queryCount - 1) { - code.push(' %s = "%s",', query, qs[query].toString()) + code.push(' %s = "%qd",', safeKey, qs[query].toString()) } else { - code.push(' %s = "%s"', query, qs[query].toString()) + code.push(' %s = "%qd"', safeKey, qs[query].toString()) } } @@ -84,24 +90,33 @@ module.exports = function (source, options) { } // Construct headers - const headers = source.allHeaders - let headerCount = Object.keys(headers).length - let header = '' - let cookies - let accept - - for (const head in headers) { - if (head.toLowerCase() === 'accept') { - accept = ', accept("' + headers[head] + '")' - headerCount = headerCount - 1 - } else if (head.toLowerCase() === 'cookie') { - cookies = ', set_cookies(`' + headers[head].replace(/;/g, '", `').replace(/` /g, '`').replace(/=/g, '` = "') + '")' - headerCount = headerCount - 1 - } else if (head.toLowerCase() !== 'content-type') { - header = header + head.replace('-', '_') + " = '" + headers[head] - if (headerCount > 1) { header = header + "', " } - } - } + const cookieHeader = getHeader(source.allHeaders, 'cookie') + const acceptHeader = getHeader(source.allHeaders, 'accept') + + const setCookies = cookieHeader + ? 'set_cookies(`' + cookieHeader.replace(/;/g, '", `').replace(/` /g, '`').replace(/=/g, '` = "') + '")' + : undefined + + const setAccept = acceptHeader + ? `accept("${escape(acceptHeader)}")` + : undefined + + const setContentType = 'content_type("' + source.postData.mimeType + '")' + + const otherHeaders = Object.entries(source.allHeaders) + // These headers are all handled separately: + .filter(([key]) => !['cookie', 'accept', 'content-type'].includes(key.toLowerCase())) + .map(([key, value]) => { + const safeKey = key.match(/^[a-zA-Z][a-zA-Z0-9_.-]*$/) + ? key.replace(/-/g, '_') + : '"' + escape(key) + '"' + return `${safeKey} = '${escape(value, { delimiter: "'" })}'` + }) + .join(', ') + + const setHeaders = otherHeaders + ? `add_headers(${otherHeaders})` + : undefined // Construct request const method = source.method @@ -111,22 +126,14 @@ module.exports = function (source, options) { request += ', body = payload' } - if (header !== '') { - request += ', add_headers(' + header + "')" - } - if (source.queryString.length) { request += ', query = queryString' } - request += ', content_type("' + source.postData.mimeType + '")' - - if (typeof accept !== 'undefined') { - request += accept - } + const headerAdditions = [setHeaders, setContentType, setAccept, setCookies].filter(x => !!x).join(', ') - if (typeof cookies !== 'undefined') { - request += cookies + if (headerAdditions) { + request += ', ' + headerAdditions } if (source.postData.text || source.postData.jsonObj || source.postData.params) { diff --git a/src/targets/ruby/faraday.js b/src/targets/ruby/faraday.js new file mode 100644 index 0000000..87657ea --- /dev/null +++ b/src/targets/ruby/faraday.js @@ -0,0 +1,104 @@ +const CodeBuilder = require('../../helpers/code-builder') + +module.exports = ({ uriObj, queryObj, method: rawMethod, postData, allHeaders }) => { + const code = new CodeBuilder() + + // To support custom methods we check for the supported methods + // and if doesn't exist then we build a custom class for it + const method = rawMethod.toUpperCase() + const methods = [ + 'GET', + 'POST', + 'HEAD', + 'DELETE', + 'PATCH', + 'PUT', + 'OPTIONS', + 'COPY', + 'LOCK', + 'UNLOCK', + 'MOVE', + 'TRACE' + ] + + if (!methods.includes(method)) { + code.push(`# Faraday cannot currently run ${method} requests. Please use another client.`) + return code.join() + } + + code.push("require 'faraday'") + code.blank() + + // Write body to beginning of script + if (postData.mimeType === 'application/x-www-form-urlencoded') { + if (postData.params) { + code.push('data = {') + postData.params.forEach(param => { + code.push(` :${param.name} => ${JSON.stringify(param.value)},`) + }) + code.push('}') + code.blank() + } + } + + code.push('conn = Faraday.new(') + code.push(` url: '${uriObj.protocol}//${uriObj.host}',`) + if (allHeaders['content-type'] || allHeaders['Content-Type']) { + code.push(` headers: {'Content-Type' => '${allHeaders['content-type'] || allHeaders['Content-Type']}'}`) + } + code.push(')') + + code.blank() + code.push(`response = conn.${method.toLowerCase()}('${uriObj.pathname}') do |req|`) + + const headers = Object.keys(allHeaders) + if (headers.length) { + headers.forEach(key => { + if (key.toLowerCase() !== 'content-type') { + code.push(" req.headers['%qs'] = '%qs'", key, allHeaders[key]) + } + }) + } + + Object.keys(queryObj).forEach(name => { + const value = queryObj[name] + if (Array.isArray(value)) { + code.push(` req.params['%qs'] = ${JSON.stringify(value)}`, name) + } else { + code.push(" req.params['%qs'] = '%qs'", name, value) + } + }) + + switch (postData.mimeType) { + case 'application/x-www-form-urlencoded': + if (postData.params) { + code.push(' req.body = URI.encode_www_form(data)') + } + break + + case 'application/json': + if (postData.jsonObj) { + code.push(` req.body = ${JSON.stringify(postData.text)}`) + } + break + + default: + if (postData.text) { + code.push(` req.body = ${JSON.stringify(postData.text)}`) + } + } + + code.push('end') + code.blank() + code.push('puts response.status') + code.push('puts response.body') + + return code.join() +} + +module.exports.info = { + key: 'faraday', + title: 'faraday', + link: 'https://github.com/lostisland/faraday', + description: 'Faraday HTTP client' +} diff --git a/src/targets/ruby/index.js b/src/targets/ruby/index.js index 1118a1b..184399b 100644 --- a/src/targets/ruby/index.js +++ b/src/targets/ruby/index.js @@ -8,5 +8,6 @@ module.exports = { default: 'native' }, - native: require('./native') + native: require('./native'), + faraday: require('./faraday') } diff --git a/src/targets/ruby/native.js b/src/targets/ruby/native.js index df96b9e..ba9cebc 100644 --- a/src/targets/ruby/native.js +++ b/src/targets/ruby/native.js @@ -7,11 +7,6 @@ module.exports = function (source, options) { code.push('require \'uri\'') .push('require \'net/http\'') - - if (source.uriObj.protocol === 'https:') { - code.push('require \'openssl\'') - } - code.blank() // To support custom methods we check for the supported methods @@ -34,7 +29,10 @@ module.exports = function (source, options) { if (source.uriObj.protocol === 'https:') { code.push('http.use_ssl = true') - .push('http.verify_mode = OpenSSL::SSL::VERIFY_NONE') + + if (options.insecureSkipVerify) { + code.push('http.verify_mode = OpenSSL::SSL::VERIFY_NONE') + } } code.blank() @@ -43,7 +41,7 @@ module.exports = function (source, options) { const headers = Object.keys(source.allHeaders) if (headers.length) { headers.forEach(function (key) { - code.push('request["%s"] = \'%s\'', key, source.allHeaders[key]) + code.push('request["%s"] = \'%qs\'', key, source.allHeaders[key]) }) } diff --git a/src/targets/rust/helpers.js b/src/targets/rust/helpers.js new file mode 100644 index 0000000..bddf6c1 --- /dev/null +++ b/src/targets/rust/helpers.js @@ -0,0 +1,93 @@ +'use strict' + +const util = require('util') + +function concatValues ( + concatType, + values, + pretty, + indentation, + indentLevel +) { + const currentIndent = indentation.repeat(indentLevel) + const closingBraceIndent = indentation.repeat(indentLevel - 1) + const join = pretty ? `,\n${currentIndent}` : ', ' + const openingBrace = concatType === 'object' ? 'json!({' : '(' + const closingBrace = concatType === 'object' ? '})' : ')' + + if (pretty) { + return `${openingBrace}\n${currentIndent}${values.join( + join + )}\n${closingBraceIndent}${closingBrace}` + } + + return `${openingBrace}${values.join(join)}${closingBrace}` +} + +/** + * Create a valid Rust string of a literal value using serde_json according to its type. + * + * @param {*} value Any Javascript literal + * @param {Object} opts Target options + * @return {string} + */ +exports.literalRepresentation = ( + value, + opts, + indentLevel +) => { + /* + * Note: this version is almost entirely borrowed from the Python client helper. The + * only real modification involves the braces and the types. The helper + * could potentially be parameterised for reuse. + */ + indentLevel = indentLevel === undefined ? 1 : indentLevel + 1 + + switch (Object.prototype.toString.call(value)) { + case '[object Number]': + return value + + case '[object Array]': { + let pretty = false + const valuesRep = value.map(v => { + // Switch to prettify if the value is a dict with more than one key. + if (Object.prototype.toString.call(v) === '[object Object]') { + pretty = Object.keys(v).length > 1 + } + return exports.literalRepresentation(v, opts, indentLevel) + }) + return concatValues('array', valuesRep, pretty, opts.indent, indentLevel) + } + + case '[object Object]': { + const keyValuePairs = [] + for (const k in value) { + keyValuePairs.push( + util.format('%s: %s', + exports.literalRepresentation(k, opts, indentLevel), + exports.literalRepresentation(value[k], opts, indentLevel) + ) + ) + } + return concatValues( + 'object', + keyValuePairs, + opts.pretty && keyValuePairs.length > 1, + opts.indent, + indentLevel + ) + } + + case '[object Null]': + return 'json!(null)' + + case '[object Boolean]': + return value ? 'true' : 'false' + + default: + if (value === null || value === undefined) { + return '' + } + return JSON.stringify(value) + } +} diff --git a/src/targets/rust/index.js b/src/targets/rust/index.js new file mode 100644 index 0000000..011dadf --- /dev/null +++ b/src/targets/rust/index.js @@ -0,0 +1,12 @@ +'use strict' + +module.exports = { + info: { + key: 'rust', + title: 'Rust', + extname: '.rs', + default: 'reqwest' + }, + + reqwest: require('./reqwest') +} diff --git a/src/targets/rust/reqwest.js b/src/targets/rust/reqwest.js new file mode 100644 index 0000000..e381015 --- /dev/null +++ b/src/targets/rust/reqwest.js @@ -0,0 +1,238 @@ +/** + * @description + * HTTP code snippet generator for Rust using reqwest + * + * @author + * @Benjscho + * + * for any questions or issues regarding the generated code snippet, please open an issue mentioning the author. + */ + +const CodeBuilder = require('../../helpers/code-builder') +const { escape } = require('../../helpers/format') +const { literalRepresentation } = require('./helpers') + +module.exports = ({ queryObj, url, postData, allHeaders, method }, options) => { + const opts = { + indent: ' ', + pretty: true, + ...options + } + + let indentLevel = 0 + + // start snippet + const code = new CodeBuilder(opts.indent) + + // import reqwest + code.push(indentLevel, 'use reqwest;') + code.blank() + + // start async main for tokio + code.push(indentLevel, '#[tokio::main]') + code.push(indentLevel, 'pub async fn main() {') + indentLevel += 1 + + // add url + code.push(indentLevel, `let url = "${url}";`) + code.blank() + + let hasQuery = false + // construct query string + if (Object.keys(queryObj).length) { + hasQuery = true + code.push(indentLevel, 'let querystring = [') + indentLevel += 1 + for (const [key, value] of Object.entries(queryObj)) { + code.push(indentLevel, `("${escape(key)}", "${escape(value)}"),`) + } + indentLevel -= 1 + code.push(indentLevel, '];') + code.blank() + } + + // construct payload + let payload = {} + const files = {} + + let hasFiles = false + let hasForm = false + let hasBody = false + let jsonPayload = false + let isMultipart = false + switch (postData.mimeType) { + case 'application/json': + if (postData.jsonObj) { + code.push( + indentLevel, + `let payload = ${literalRepresentation(postData.jsonObj, opts, indentLevel)};` + ) + } + jsonPayload = true + break + + case 'multipart/form-data': + isMultipart = true + + if (!postData.params) { + code.push(indentLevel, 'let form = reqwest::multipart::Form::new()') + code.push(indentLevel + 1, '.text("", "");') + break + } + + payload = {} + postData.params.forEach(p => { + if (p.fileName) { + files[p.name] = p.fileName + hasFiles = true + } else { + payload[p.name] = p.value + } + }) + + if (hasFiles) { + for (const line of fileToPartString) { + code.push(indentLevel, line) + } + code.blank() + } + code.push(indentLevel, 'let form = reqwest::multipart::Form::new()') + + for (const [name, fileName] of Object.entries(files)) { + code.push(indentLevel + 1, `.part("${name}", file_to_part("${fileName}").await)`) + } + for (const [name, value] of Object.entries(payload)) { + code.push(indentLevel + 1, `.text("${name}", "${value}")`) + } + code.pushToLast(';') + + break + + default: { + if (postData.mimeType === 'application/x-www-form-urlencoded' && postData.paramsObj) { + code.push( + indentLevel, + `let payload = ${literalRepresentation(postData.paramsObj, opts, indentLevel)};` + ) + hasForm = true + break + } + + if (postData.text) { + code.push( + indentLevel, + `let payload = ${literalRepresentation(postData.text, opts, indentLevel)};` + ) + hasBody = true + break + } + } + } + + if (hasForm || jsonPayload || hasBody) { + code.unshift('use serde_json::json;') + code.blank() + } + + let hasHeaders = false + // construct headers + if (Object.keys(allHeaders).length) { + hasHeaders = true + code.push(indentLevel, 'let mut headers = reqwest::header::HeaderMap::new();') + for (const [key, value] of Object.entries(allHeaders)) { + // Skip setting content-type if there is a file, as this header will + // cause the request to hang, and reqwest will set it for us. + if (key.toLowerCase() === 'content-type' && isMultipart) { + continue + } + code.push( + indentLevel, + `headers.insert("${escape(key)}", ${literalRepresentation(value, opts)}.parse().unwrap());` + ) + } + code.blank() + } + + // construct client + code.push(indentLevel, 'let client = reqwest::Client::new();') + + // construct query + switch (method) { + case 'POST': + code.push(indentLevel, 'let response = client.post(url)') + break + + case 'GET': + code.push(indentLevel, 'let response = client.get(url)') + break + + default: { + code.push( + indentLevel, + `let response = client.request(reqwest::Method::from_str("${method}").unwrap(), url)` + ) + code.unshift('use std::str::FromStr;') + break + } + } + + if (hasQuery) { + code.push(indentLevel + 1, '.query(&querystring)') + } + + if (isMultipart) { + code.push(indentLevel + 1, '.multipart(form)') + } + + if (hasHeaders) { + code.push(indentLevel + 1, '.headers(headers)') + } + + if (jsonPayload) { + code.push(indentLevel + 1, '.json(&payload)') + } + + if (hasForm) { + code.push(indentLevel + 1, '.form(&payload)') + } + + if (hasBody) { + code.push(indentLevel + 1, '.body(payload)') + } + + // send query + code.push(indentLevel + 1, '.send()') + code.push(indentLevel + 1, '.await;') + code.blank() + + // Print response + code.push(indentLevel, 'let results = response.unwrap()') + code.push(indentLevel + 1, '.json::()') + code.push(indentLevel + 1, '.await') + code.push(indentLevel + 1, '.unwrap();') + code.blank() + + code.push(indentLevel, 'dbg!(results);') + + code.push('}\n') + + return code.join() +} + +const fileToPartString = [ + 'async fn file_to_part(file_name: &\'static str) -> reqwest::multipart::Part {', + ' let file = tokio::fs::File::open(file_name).await.unwrap();', + ' let stream = tokio_util::codec::FramedRead::new(file, tokio_util::codec::BytesCodec::new());', + ' let body = reqwest::Body::wrap_stream(stream);', + ' reqwest::multipart::Part::stream(body)', + ' .file_name(file_name)', + ' .mime_str("text/plain").unwrap()', + '}' +] + +module.exports.info = { + key: 'reqwest', + title: 'reqwest', + link: 'https://docs.rs/reqwest/latest/reqwest/', + description: 'reqwest HTTP library' +} diff --git a/src/targets/shell/curl.js b/src/targets/shell/curl.js index f097f5a..d32e05e 100644 --- a/src/targets/shell/curl.js +++ b/src/targets/shell/curl.js @@ -12,6 +12,7 @@ const util = require('util') const helpers = require('../../helpers/shell') +const headerHelpers = require('../../helpers/headers') const CodeBuilder = require('../../helpers/code-builder') module.exports = function (source, options) { @@ -35,10 +36,34 @@ module.exports = function (source, options) { } code.push(util.format('%s%s', opts.short ? '' : '--url ', formattedUrl)) + if (opts.insecureSkipVerify) { + code.push(opts.short ? '-k' : '--insecure') + } + if (source.httpVersion === 'HTTP/1.0') { code.push(opts.short ? '-0' : '--http1.0') } + if (headerHelpers.getHeader(source.allHeaders, 'accept-encoding')) { + code.push('--compressed') + } + + // if multipart form data, we want to remove the boundary + if (source.postData.mimeType === 'multipart/form-data') { + const contentTypeHeaderName = headerHelpers.getHeaderName(source.headersObj, 'content-type') + const contentTypeHeader = source.headersObj[contentTypeHeaderName] + + if (contentTypeHeaderName && contentTypeHeader) { + // remove the leading semi colon and boundary + // up to the next semi colon or the end of string + const noBoundary = contentTypeHeader.replace(/; boundary.+?(?=(;|$))/, '') + + // replace the content-type header with no boundary in both headersObj and allHeaders + source.headersObj[contentTypeHeaderName] = noBoundary + source.allHeaders[contentTypeHeaderName] = noBoundary + } + } + // construct headers Object.keys(source.headersObj).sort().forEach(function (key) { const header = util.format('%s: %s', key, source.headersObj[key]) diff --git a/src/targets/shell/httpie.js b/src/targets/shell/httpie.js index 40b0338..0836ff2 100644 --- a/src/targets/shell/httpie.js +++ b/src/targets/shell/httpie.js @@ -90,7 +90,7 @@ module.exports = function (source, options) { // construct headers Object.keys(source.allHeaders).sort().forEach(function (key) { - code.push('%s:%s', key, shell.quote(source.allHeaders[key])) + code.push('%s:%s', shell.quote(key), shell.quote(source.allHeaders[key])) }) if (source.postData.mimeType === 'application/x-www-form-urlencoded') { @@ -109,7 +109,12 @@ module.exports = function (source, options) { code.unshift('http %s%s %s', flags.length ? flags.join(' ') + ' ' : '', source.method, shell.quote(opts.queryParams ? source.url : source.fullUrl)) if (raw && source.postData.text) { - code.unshift('echo %s | ', shell.quote(source.postData.text)) + if (source.postData.text.includes('\\')) { + // Printf handles escape characters more clearly & portably than echo + code.unshift("printf '%%s' %s | ", shell.quote(source.postData.text)) + } else { + code.unshift('echo %s | ', shell.quote(source.postData.text)) + } } return code.join() diff --git a/src/targets/swift/helpers.js b/src/targets/swift/helpers.js index 62a2121..1a609fc 100644 --- a/src/targets/swift/helpers.js +++ b/src/targets/swift/helpers.js @@ -1,6 +1,7 @@ 'use strict' const util = require('util') +const { escape } = require('../../helpers/format') /** * Create an string of given length filled with blank spaces @@ -72,7 +73,12 @@ module.exports = { case '[object Object]': { const keyValuePairs = [] for (const k in value) { - keyValuePairs.push(util.format('"%s": %s', k, this.literalRepresentation(value[k], opts, indentLevel))) + keyValuePairs.push( + util.format('%s: %s', + this.literalRepresentation(k, opts, indentLevel), + this.literalRepresentation(value[k], opts, indentLevel) + ) + ) } return concatArray(keyValuePairs, opts.pretty && keyValuePairs.length > 1, opts.indent, indentLevel) } @@ -84,7 +90,7 @@ module.exports = { if (value === null || value === undefined) { return '' } - return '"' + value.toString().replace(/"/g, '\\"') + '"' + return '"' + escape(value.toString()) + '"' } } } diff --git a/src/targets/swift/nsurlsession.js b/src/targets/swift/nsurlsession.js index d3b48a7..d57548c 100644 --- a/src/targets/swift/nsurlsession.js +++ b/src/targets/swift/nsurlsession.js @@ -46,9 +46,9 @@ module.exports = function (source, options) { // we make it easier for the user to edit it according to his or her needs after pasting. // The user can just add/remove lines adding/removing body parameters. code.blank() - .push('let postData = NSMutableData(data: "%s=%s".data(using: String.Encoding.utf8)!)', source.postData.params[0].name, source.postData.params[0].value) + .push('let postData = NSMutableData(data: "%qd=%qd".data(using: String.Encoding.utf8)!)', source.postData.params[0].name, source.postData.params[0].value) for (let i = 1, len = source.postData.params.length; i < len; i++) { - code.push('postData.append("&%s=%s".data(using: String.Encoding.utf8)!)', source.postData.params[i].name, source.postData.params[i].value) + code.push('postData.append("&%qd=%qd".data(using: String.Encoding.utf8)!)', source.postData.params[i].name, source.postData.params[i].value) } break @@ -68,7 +68,7 @@ module.exports = function (source, options) { */ code.push(helpers.literalDeclaration('parameters', source.postData.params, opts)) .blank() - .push('let boundary = "%s"', source.postData.boundary) + .push('let boundary = "%qd"', source.postData.boundary) .blank() .push('var body = ""') .push('var error: NSError? = nil') @@ -93,13 +93,13 @@ module.exports = function (source, options) { default: code.blank() - .push('let postData = NSData(data: "%s".data(using: String.Encoding.utf8)!)', source.postData.text) + .push('let postData = NSData(data: "%qd".data(using: String.Encoding.utf8)!)', source.postData.text) } } code.blank() // NSURLRequestUseProtocolCachePolicy is the default policy, let's just always set it to avoid confusion. - .push('let request = NSMutableURLRequest(url: NSURL(string: "%s")! as URL,', source.fullUrl) + .push('let request = NSMutableURLRequest(url: NSURL(string: "%qd")! as URL,', source.fullUrl) .push(' cachePolicy: .useProtocolCachePolicy,') .push(' timeoutInterval: %s)', parseInt(opts.timeout, 10).toFixed(1)) .push('request.httpMethod = "%s"', source.method) diff --git a/test/fixtures/available-targets.json b/test/fixtures/available-targets.json index 7ad7857..b8b2618 100644 --- a/test/fixtures/available-targets.json +++ b/test/fixtures/available-targets.json @@ -1,65 +1,129 @@ [ { - "key": "shell", - "title": "Shell", - "extname": ".sh", - "default": "curl", + "key": "c", + "title": "C", + "extname": ".c", + "default": "libcurl", "clients": [ { - "key": "curl", - "title": "cURL", - "link": "http://curl.haxx.se/", - "description": "cURL is a command line tool and library for transferring data with URL syntax" - }, + "key": "libcurl", + "title": "Libcurl", + "link": "http://curl.haxx.se/libcurl/", + "description": "Simple REST and HTTP API Client for C" + } + ] + }, + { + "key": "clojure", + "title": "Clojure", + "extname": ".clj", + "default": "clj_http", + "clients": [ { - "key": "httpie", - "title": "HTTPie", - "link": "http://httpie.org/", - "description": "a CLI, cURL-like tool for humans" + "key": "clj_http", + "title": "clj-http", + "link": "https://github.com/dakrone/clj-http", + "description": "An idiomatic clojure http client wrapping the apache client." + } + ] + }, + { + "key": "crystal", + "title": "Crystal", + "extname": ".cr", + "default": "native", + "clients": [ + { + "key": "native", + "title": "http::client", + "link": "https://crystal-lang.org/api/master/HTTP/Client.html", + "description": "Crystal HTTP client" + } + ] + }, + { + "key": "csharp", + "title": "C#", + "extname": ".cs", + "default": "restsharp", + "clients": [ + { + "key": "restsharp", + "title": "RestSharp", + "link": "http://restsharp.org/", + "description": "Simple REST and HTTP API Client for .NET" }, { - "key": "wget", - "title": "Wget", - "link": "https://www.gnu.org/software/wget/", - "description": "a free software package for retrieving files using HTTP, HTTPS" + "key": "httpclient", + "title": "HttpClient", + "link": "https://docs.microsoft.com/en-us/dotnet/api/system.net.http.httpclient", + "description": ".NET Standard HTTP Client" } ] }, { - "key": "node", - "title": "Node.js", - "extname": ".js", + "key": "go", + "title": "Go", + "extname": ".go", "default": "native", "clients": [ { "key": "native", - "title": "HTTP", - "link": "http://nodejs.org/api/http.html#http_http_request_options_callback", - "description": "Node.js native HTTP interface" - }, + "title": "NewRequest", + "link": "http://golang.org/pkg/net/http/#NewRequest", + "description": "Golang HTTP client request" + } + ] + }, + { + "key": "http", + "title": "HTTP", + "extname": "", + "default": "1.1", + "clients": [ { - "key": "request", - "title": "Request", - "link": "https://github.com/request/request", - "description": "Simplified HTTP request client" + "key": "1.1", + "title": "HTTP/1.1", + "link": "https://tools.ietf.org/html/rfc7230", + "description": "HTTP/1.1 request string in accordance with RFC 7230" + } + ] + }, + { + "key": "java", + "title": "Java", + "extname": ".java", + "default": "unirest", + "clients": [ + { + "key": "okhttp", + "title": "OkHttp", + "link": "http://square.github.io/okhttp/", + "description": "An HTTP Request Client Library" }, { "key": "unirest", "title": "Unirest", - "link": "http://unirest.io/nodejs.html", + "link": "http://unirest.io/java.html", "description": "Lightweight HTTP Request Client Library" }, { - "key": "axios", - "title": "Axios", - "link": "https://github.com/axios/axios", - "description": "Promise based HTTP client for the browser and node.js" + "key": "asynchttp", + "title": "AsyncHttp", + "link": "https://github.com/AsyncHttpClient/async-http-client", + "description": "Asynchronous Http and WebSocket Client library for Java" }, { - "key": "fetch", - "title": "Fetch", - "link": "https://github.com/bitinn/node-fetch", - "description": "Simplified HTTP node-fetch client" + "key": "nethttp", + "title": "java.net.http", + "link": "https://openjdk.java.net/groups/net/httpclient/intro.html", + "description": "Java Standardized HTTP Client API" + }, + { + "key": "restclient", + "title": "Spring RestClient", + "link": "https://docs.spring.io/spring-framework/docs/current/javadoc-api/org/springframework/web/client/RestClient.html", + "description": "Spring Framework REST client" } ] }, @@ -95,6 +159,72 @@ } ] }, + { + "key": "kotlin", + "title": "Kotlin", + "extname": ".kt", + "default": "okhttp", + "clients": [ + { + "key": "okhttp", + "title": "OkHttp", + "link": "http://square.github.io/okhttp/", + "description": "An HTTP Request Client Library" + } + ] + }, + { + "key": "node", + "title": "Node.js", + "extname": ".js", + "default": "native", + "clients": [ + { + "key": "native", + "title": "HTTP", + "link": "http://nodejs.org/api/http.html#http_http_request_options_callback", + "description": "Node.js native HTTP interface" + }, + { + "key": "request", + "title": "Request", + "link": "https://github.com/request/request", + "description": "Simplified HTTP request client" + }, + { + "key": "unirest", + "title": "Unirest", + "link": "http://unirest.io/nodejs.html", + "description": "Lightweight HTTP Request Client Library" + }, + { + "key": "axios", + "title": "Axios", + "link": "https://github.com/axios/axios", + "description": "Promise based HTTP client for the browser and node.js" + }, + { + "key": "fetch", + "title": "Fetch", + "link": "https://github.com/bitinn/node-fetch", + "description": "Simplified HTTP node-fetch client" + } + ] + }, + { + "key": "objc", + "title": "Objective-C", + "extname": ".m", + "default": "nsurlsession", + "clients": [ + { + "key": "nsurlsession", + "title": "NSURLSession", + "link": "https://developer.apple.com/library/mac/documentation/Foundation/Reference/NSURLSession_class/index.html", + "description": "Foundation's NSURLSession request" + } + ] + }, { "key": "ocaml", "title": "OCaml", @@ -135,6 +265,26 @@ } ] }, + { + "key": "powershell", + "title": "Powershell", + "extname": ".ps1", + "default": "webrequest", + "clients": [ + { + "key": "webrequest", + "title": "Invoke-WebRequest", + "link": "https://docs.microsoft.com/en-us/powershell/module/Microsoft.PowerShell.Utility/Invoke-WebRequest", + "description": "Powershell Invoke-WebRequest client" + }, + { + "key": "restmethod", + "title": "Invoke-RestMethod", + "link": "https://docs.microsoft.com/en-us/powershell/module/Microsoft.PowerShell.Utility/Invoke-RestMethod", + "description": "Powershell Invoke-RestMethod client" + } + ] + }, { "key": "python", "title": "Python", @@ -156,76 +306,16 @@ ] }, { - "key": "objc", - "title": "Objective-C", - "extname": ".m", - "default": "nsurlsession", - "clients": [ - { - "key": "nsurlsession", - "title": "NSURLSession", - "link": "https://developer.apple.com/library/mac/documentation/Foundation/Reference/NSURLSession_class/index.html", - "description": "Foundation's NSURLSession request" - } - ] - }, - { - "key": "swift", - "title": "Swift", - "extname": ".swift", - "default": "nsurlsession", - "clients": [ - { - "key": "nsurlsession", - "title": "NSURLSession", - "link": "https://developer.apple.com/library/mac/documentation/Foundation/Reference/NSURLSession_class/index.html", - "description": "Foundation's NSURLSession request" - } - ] - }, - { - "key": "go", - "title": "Go", - "extname": ".go", - "default": "native", - "clients": [ - { - "key": "native", - "title": "NewRequest", - "link": "http://golang.org/pkg/net/http/#NewRequest", - "description": "Golang HTTP client request" - } - ] - }, - { - "key": "java", - "title": "Java", - "extname": ".java", - "default": "unirest", + "key": "r", + "title": "R", + "extname": ".r", + "default": "httr", "clients": [ { - "key": "okhttp", - "title": "OkHttp", - "link": "http://square.github.io/okhttp/", - "description": "An HTTP Request Client Library" - }, - { - "key": "unirest", - "title": "Unirest", - "link": "http://unirest.io/java.html", - "description": "Lightweight HTTP Request Client Library" - }, - { - "key": "asynchttp", - "title": "AsyncHttp", - "link": "https://github.com/AsyncHttpClient/async-http-client", - "description": "Asynchronous Http and WebSocket Client library for Java" - }, - { - "key": "nethttp", - "title": "java.net.http", - "link": "https://openjdk.java.net/groups/net/httpclient/intro.html", - "description": "Java Standardized HTTP Client API" + "key": "httr", + "title": "httr", + "link": "https://cran.r-project.org/web/packages/httr/vignettes/quickstart.html", + "description": "httr: Tools for Working with URLs and HTTP" } ] }, @@ -240,116 +330,66 @@ "title": "net::http", "link": "http://ruby-doc.org/stdlib-2.2.1/libdoc/net/http/rdoc/Net/HTTP.html", "description": "Ruby HTTP client" - } - ] - }, - { - "key": "csharp", - "title": "C#", - "extname": ".cs", - "default": "restsharp", - "clients": [ - { - "key": "restsharp", - "title": "RestSharp", - "link": "http://restsharp.org/", - "description": "Simple REST and HTTP API Client for .NET" }, { - "key": "httpclient", - "title": "HttpClient", - "link": "https://docs.microsoft.com/en-us/dotnet/api/system.net.http.httpclient", - "description": ".NET Standard HTTP Client" + "key": "faraday", + "title": "faraday", + "link": "https://github.com/lostisland/faraday", + "description": "Faraday HTTP client" } ] }, { - "key": "clojure", - "title": "Clojure", - "extname": ".clj", - "default": "clj_http", + "key": "rust", + "title": "Rust", + "extname": ".rs", + "default": "reqwest", "clients": [ { - "key": "clj_http", - "title": "clj-http", - "link": "https://github.com/dakrone/clj-http", - "description": "An idiomatic clojure http client wrapping the apache client." + "key": "reqwest", + "title": "reqwest", + "link": "https://docs.rs/reqwest/latest/reqwest/", + "description": "reqwest HTTP library" } ] }, { - "key": "c", - "title": "C", - "extname": ".c", - "default": "libcurl", - "clients": [ - { - "key": "libcurl", - "title": "Libcurl", - "link": "http://curl.haxx.se/libcurl/", - "description": "Simple REST and HTTP API Client for C" - } - ] - }, - { - "key": "r", - "title": "R", - "extname": ".r", - "default": "httr", - "clients": [ - { - "key": "httr", - "title": "httr", - "link": "https://cran.r-project.org/web/packages/httr/vignettes/quickstart.html", - "description": "httr: Tools for Working with URLs and HTTP" - } - ] - }, - { - "default": "webrequest", - "extname": ".ps1", - "key": "powershell", - "title": "Powershell", + "key": "shell", + "title": "Shell", + "extname": ".sh", + "default": "curl", "clients": [ { - "description": "Powershell Invoke-WebRequest client", - "key": "webrequest", - "link": "https://docs.microsoft.com/en-us/powershell/module/Microsoft.PowerShell.Utility/Invoke-WebRequest", - "title": "Invoke-WebRequest" + "key": "curl", + "title": "cURL", + "link": "http://curl.haxx.se/", + "description": "cURL is a command line tool and library for transferring data with URL syntax" }, { - "description": "Powershell Invoke-RestMethod client", - "key": "restmethod", - "link": "https://docs.microsoft.com/en-us/powershell/module/Microsoft.PowerShell.Utility/Invoke-RestMethod", - "title": "Invoke-RestMethod" - } - ] - }, - { - "default": "1.1", - "extname": "", - "key": "http", - "title": "HTTP", - "clients": [ + "key": "httpie", + "title": "HTTPie", + "link": "http://httpie.org/", + "description": "a CLI, cURL-like tool for humans" + }, { - "description": "HTTP/1.1 request string in accordance with RFC 7230", - "key": "1.1", - "link": "https://tools.ietf.org/html/rfc7230", - "title": "HTTP/1.1" + "key": "wget", + "title": "Wget", + "link": "https://www.gnu.org/software/wget/", + "description": "a free software package for retrieving files using HTTP, HTTPS" } ] }, { - "key": "kotlin", - "title": "Kotlin", - "extname": ".kt", - "default": "okhttp", + "key": "swift", + "title": "Swift", + "extname": ".swift", + "default": "nsurlsession", "clients": [ { - "key": "okhttp", - "title": "OkHttp", - "link": "http://square.github.io/okhttp/", - "description": "An HTTP Request Client Library" + "key": "nsurlsession", + "title": "NSURLSession", + "link": "https://developer.apple.com/library/mac/documentation/Foundation/Reference/NSURLSession_class/index.html", + "description": "Foundation's NSURLSession request" } ] } diff --git a/test/fixtures/output/c/libcurl/compression.c b/test/fixtures/output/c/libcurl/compression.c new file mode 100644 index 0000000..c008a40 --- /dev/null +++ b/test/fixtures/output/c/libcurl/compression.c @@ -0,0 +1,12 @@ +CURL *hnd = curl_easy_init(); + +curl_easy_setopt(hnd, CURLOPT_CUSTOMREQUEST, "GET"); +curl_easy_setopt(hnd, CURLOPT_URL, "http://mockbin.com/har"); + +struct curl_slist *headers = NULL; +headers = curl_slist_append(headers, "accept-encoding: deflate, gzip, br"); +curl_easy_setopt(hnd, CURLOPT_HTTPHEADER, headers); + +curl_easy_setopt(hnd, CURLOPT_ACCEPT_ENCODING, ""); + +CURLcode ret = curl_easy_perform(hnd); \ No newline at end of file diff --git a/test/fixtures/output/c/libcurl/headers.c b/test/fixtures/output/c/libcurl/headers.c index 54ed7a8..d4cb770 100644 --- a/test/fixtures/output/c/libcurl/headers.c +++ b/test/fixtures/output/c/libcurl/headers.c @@ -6,6 +6,7 @@ curl_easy_setopt(hnd, CURLOPT_URL, "http://mockbin.com/har"); struct curl_slist *headers = NULL; headers = curl_slist_append(headers, "accept: application/json"); headers = curl_slist_append(headers, "x-foo: Bar"); +headers = curl_slist_append(headers, "quoted-value: \"quoted\" 'string'"); curl_easy_setopt(hnd, CURLOPT_HTTPHEADER, headers); CURLcode ret = curl_easy_perform(hnd); diff --git a/test/fixtures/output/c/libcurl/malicious.c b/test/fixtures/output/c/libcurl/malicious.c new file mode 100644 index 0000000..b521db5 --- /dev/null +++ b/test/fixtures/output/c/libcurl/malicious.c @@ -0,0 +1,27 @@ +CURL *hnd = curl_easy_init(); + +curl_easy_setopt(hnd, CURLOPT_CUSTOMREQUEST, "POST"); +curl_easy_setopt(hnd, CURLOPT_URL, "http://example.test/%27%22%60$(%(%%7B%7B%7B/0%s//?'=squote-key-test&squote-value-test='&%22=dquote-key-test&dquote-value-test=%22&%60=backtick-key-test&backtick-value-test=%60&%24(=dollar-parenthesis-key-test&dollar-parenthesis-value-test=%24(&%23%7B=hash-brace-key-test&hash-brace-value-test=%23%7B&%25(=percent-parenthesis-key-test&percent-parenthesis-value-test=%25(&%25%7B=percent-brace-key-test&percent-brace-value-test=%25%7B&%7B%7B=double-brace-key-test&double-brace-value-test=%7B%7B&%5C0=null-key-test&null-value-test=%5C0&%25s=string-fmt-key-test&string-fmt-value-test=%25s&%5C=slash-key-test&slash-value-test=%5C"); + +struct curl_slist *headers = NULL; +headers = curl_slist_append(headers, "': squote-key-test"); +headers = curl_slist_append(headers, "squote-value-test: '"); +headers = curl_slist_append(headers, "dquote-value-test: \""); +headers = curl_slist_append(headers, "`: backtick-key-test"); +headers = curl_slist_append(headers, "backtick-value-test: `"); +headers = curl_slist_append(headers, "$: dollar-key-test"); +headers = curl_slist_append(headers, "dollar-parenthesis-value-test: $("); +headers = curl_slist_append(headers, "#: hash-key-test"); +headers = curl_slist_append(headers, "hash-brace-value-test: #{"); +headers = curl_slist_append(headers, "%: percent-key-test"); +headers = curl_slist_append(headers, "percent-parenthesis-value-test: %("); +headers = curl_slist_append(headers, "percent-brace-value-test: %{"); +headers = curl_slist_append(headers, "double-brace-value-test: {{"); +headers = curl_slist_append(headers, "null-value-test: \\0"); +headers = curl_slist_append(headers, "string-fmt-value-test: %s"); +headers = curl_slist_append(headers, "slash-value-test: \\"); +curl_easy_setopt(hnd, CURLOPT_HTTPHEADER, headers); + +curl_easy_setopt(hnd, CURLOPT_POSTFIELDS, "' \" ` $( #{ %( %{ {{ \\0 %s \\"); + +CURLcode ret = curl_easy_perform(hnd); \ No newline at end of file diff --git a/test/fixtures/output/c/libcurl/unparseable-query.c b/test/fixtures/output/c/libcurl/unparseable-query.c new file mode 100644 index 0000000..dfb694d --- /dev/null +++ b/test/fixtures/output/c/libcurl/unparseable-query.c @@ -0,0 +1,6 @@ +CURL *hnd = curl_easy_init(); + +curl_easy_setopt(hnd, CURLOPT_CUSTOMREQUEST, "GET"); +curl_easy_setopt(hnd, CURLOPT_URL, "http://mockbin.com/har?&&a=b&&"); + +CURLcode ret = curl_easy_perform(hnd); \ No newline at end of file diff --git a/test/fixtures/output/clojure/clj_http/compression.clj b/test/fixtures/output/clojure/clj_http/compression.clj new file mode 100644 index 0000000..e81ae9d --- /dev/null +++ b/test/fixtures/output/clojure/clj_http/compression.clj @@ -0,0 +1,3 @@ +(require '[clj-http.client :as client]) + +(client/get "http://mockbin.com/har" {:headers {:accept-encoding "deflate, gzip, br"}}) \ No newline at end of file diff --git a/test/fixtures/output/clojure/clj_http/headers.clj b/test/fixtures/output/clojure/clj_http/headers.clj index d2816fb..ebe5d7f 100644 --- a/test/fixtures/output/clojure/clj_http/headers.clj +++ b/test/fixtures/output/clojure/clj_http/headers.clj @@ -1,4 +1,5 @@ (require '[clj-http.client :as client]) -(client/get "http://mockbin.com/har" {:headers {:x-foo "Bar"} +(client/get "http://mockbin.com/har" {:headers {:x-foo "Bar" + :quoted-value "\"quoted\" 'string'"} :accept :json}) diff --git a/test/fixtures/output/clojure/clj_http/malicious.clj b/test/fixtures/output/clojure/clj_http/malicious.clj new file mode 100644 index 0000000..9f74137 --- /dev/null +++ b/test/fixtures/output/clojure/clj_http/malicious.clj @@ -0,0 +1,41 @@ +(require '[clj-http.client :as client]) + +(client/post "http://example.test/%27%22%60$(%(%%7B%7B%7B/0%s//" {:headers {"'" "squote-key-test" + :squote-value-test "'" + :dquote-value-test "\"" + "`" "backtick-key-test" + :backtick-value-test "`" + "$" "dollar-key-test" + :dollar-parenthesis-value-test "$(" + "#" "hash-key-test" + :hash-brace-value-test "#{" + "%" "percent-key-test" + :percent-parenthesis-value-test "%(" + :percent-brace-value-test "%{" + :double-brace-value-test "{{" + :null-value-test "\\0" + :string-fmt-value-test "%s" + :slash-value-test "\\"} + :query-params {"'" "squote-key-test" + :squote-value-test "'" + "\"" "dquote-key-test" + :dquote-value-test "\"" + "`" "backtick-key-test" + :backtick-value-test "`" + "$(" "dollar-parenthesis-key-test" + :dollar-parenthesis-value-test "$(" + "#{" "hash-brace-key-test" + :hash-brace-value-test "#{" + "%(" "percent-parenthesis-key-test" + :percent-parenthesis-value-test "%(" + "%{" "percent-brace-key-test" + :percent-brace-value-test "%{" + "{{" "double-brace-key-test" + :double-brace-value-test "{{" + "\\0" "null-key-test" + :null-value-test "\\0" + "%s" "string-fmt-key-test" + :string-fmt-value-test "%s" + "\\" "slash-key-test" + :slash-value-test "\\"} + :body "' \" ` $( #{ %( %{ {{ \\0 %s \\"}) \ No newline at end of file diff --git a/test/fixtures/output/clojure/clj_http/nested.clj b/test/fixtures/output/clojure/clj_http/nested.clj index 73016ab..24a7dd6 100644 --- a/test/fixtures/output/clojure/clj_http/nested.clj +++ b/test/fixtures/output/clojure/clj_http/nested.clj @@ -1,5 +1,5 @@ (require '[clj-http.client :as client]) -(client/get "http://mockbin.com/har" {:query-params {:foo[bar] "baz,zap" +(client/get "http://mockbin.com/har" {:query-params {"foo[bar]" "baz,zap" :fiz "buz" :key "value"}}) diff --git a/test/fixtures/output/clojure/clj_http/unparseable-query.clj b/test/fixtures/output/clojure/clj_http/unparseable-query.clj new file mode 100644 index 0000000..36fc53a --- /dev/null +++ b/test/fixtures/output/clojure/clj_http/unparseable-query.clj @@ -0,0 +1,3 @@ +(require '[clj-http.client :as client]) + +(client/get "http://mockbin.com/har?&&a=b&&") \ No newline at end of file diff --git a/test/fixtures/output/crystal/native/application-form-encoded.cr b/test/fixtures/output/crystal/native/application-form-encoded.cr new file mode 100644 index 0000000..1a88422 --- /dev/null +++ b/test/fixtures/output/crystal/native/application-form-encoded.cr @@ -0,0 +1,10 @@ +require "http/client" + +url = "http://mockbin.com/har" +headers = HTTP::Headers{ + "content-type" => "application/x-www-form-urlencoded" +} +reqBody = "foo=bar&hello=world" + +response = HTTP::Client.post url, headers: headers, body: reqBody +puts response.body \ No newline at end of file diff --git a/test/fixtures/output/crystal/native/application-json.cr b/test/fixtures/output/crystal/native/application-json.cr new file mode 100644 index 0000000..1389c2f --- /dev/null +++ b/test/fixtures/output/crystal/native/application-json.cr @@ -0,0 +1,10 @@ +require "http/client" + +url = "http://mockbin.com/har" +headers = HTTP::Headers{ + "content-type" => "application/json" +} +reqBody = "{\"number\":1,\"string\":\"f\\\"oo\",\"arr\":[1,2,3],\"nested\":{\"a\":\"b\"},\"arr_mix\":[1,\"a\",{\"arr_mix_nested\":{}}],\"boolean\":false}" + +response = HTTP::Client.post url, headers: headers, body: reqBody +puts response.body \ No newline at end of file diff --git a/test/fixtures/output/crystal/native/compression.cr b/test/fixtures/output/crystal/native/compression.cr new file mode 100644 index 0000000..7658836 --- /dev/null +++ b/test/fixtures/output/crystal/native/compression.cr @@ -0,0 +1,9 @@ +require "http/client" + +url = "http://mockbin.com/har" +headers = HTTP::Headers{ + "accept-encoding" => "deflate, gzip, br" +} + +response = HTTP::Client.get url, headers: headers +puts response.body \ No newline at end of file diff --git a/test/fixtures/output/crystal/native/cookies.cr b/test/fixtures/output/crystal/native/cookies.cr new file mode 100644 index 0000000..70d45c1 --- /dev/null +++ b/test/fixtures/output/crystal/native/cookies.cr @@ -0,0 +1,9 @@ +require "http/client" + +url = "http://mockbin.com/har" +headers = HTTP::Headers{ + "cookie" => "foo=bar; bar=baz" +} + +response = HTTP::Client.post url, headers: headers +puts response.body \ No newline at end of file diff --git a/test/fixtures/output/crystal/native/custom-method.cr b/test/fixtures/output/crystal/native/custom-method.cr new file mode 100644 index 0000000..ee1852b --- /dev/null +++ b/test/fixtures/output/crystal/native/custom-method.cr @@ -0,0 +1,6 @@ +require "http/client" + +url = "http://mockbin.com/har" + +response = HTTP::Client.exec "PROPFIND", url +puts response.body \ No newline at end of file diff --git a/test/fixtures/output/crystal/native/full.cr b/test/fixtures/output/crystal/native/full.cr new file mode 100644 index 0000000..edd8f4c --- /dev/null +++ b/test/fixtures/output/crystal/native/full.cr @@ -0,0 +1,12 @@ +require "http/client" + +url = "http://mockbin.com/har?foo=bar&foo=baz&baz=abc&key=value" +headers = HTTP::Headers{ + "cookie" => "foo=bar; bar=baz" + "accept" => "application/json" + "content-type" => "application/x-www-form-urlencoded" +} +reqBody = "foo=bar" + +response = HTTP::Client.post url, headers: headers, body: reqBody +puts response.body \ No newline at end of file diff --git a/test/fixtures/output/crystal/native/headers.cr b/test/fixtures/output/crystal/native/headers.cr new file mode 100644 index 0000000..1061d33 --- /dev/null +++ b/test/fixtures/output/crystal/native/headers.cr @@ -0,0 +1,11 @@ +require "http/client" + +url = "http://mockbin.com/har" +headers = HTTP::Headers{ + "accept" => "application/json" + "x-foo" => "Bar" + "quoted-value" => "\"quoted\" 'string'" +} + +response = HTTP::Client.get url, headers: headers +puts response.body \ No newline at end of file diff --git a/test/fixtures/output/crystal/native/https.cr b/test/fixtures/output/crystal/native/https.cr new file mode 100644 index 0000000..c9fa4fd --- /dev/null +++ b/test/fixtures/output/crystal/native/https.cr @@ -0,0 +1,6 @@ +require "http/client" + +url = "https://mockbin.com/har" + +response = HTTP::Client.get url +puts response.body \ No newline at end of file diff --git a/test/fixtures/output/crystal/native/jsonObj-multiline.cr b/test/fixtures/output/crystal/native/jsonObj-multiline.cr new file mode 100644 index 0000000..12ce719 --- /dev/null +++ b/test/fixtures/output/crystal/native/jsonObj-multiline.cr @@ -0,0 +1,10 @@ +require "http/client" + +url = "http://mockbin.com/har" +headers = HTTP::Headers{ + "content-type" => "application/json" +} +reqBody = "{\n \"foo\": \"bar\"\n}" + +response = HTTP::Client.post url, headers: headers, body: reqBody +puts response.body \ No newline at end of file diff --git a/test/fixtures/output/crystal/native/jsonObj-null-value.cr b/test/fixtures/output/crystal/native/jsonObj-null-value.cr new file mode 100644 index 0000000..053961c --- /dev/null +++ b/test/fixtures/output/crystal/native/jsonObj-null-value.cr @@ -0,0 +1,10 @@ +require "http/client" + +url = "http://mockbin.com/har" +headers = HTTP::Headers{ + "content-type" => "application/json" +} +reqBody = "{\"foo\":null}" + +response = HTTP::Client.post url, headers: headers, body: reqBody +puts response.body \ No newline at end of file diff --git a/test/fixtures/output/crystal/native/malicious.cr b/test/fixtures/output/crystal/native/malicious.cr new file mode 100644 index 0000000..e8374f3 --- /dev/null +++ b/test/fixtures/output/crystal/native/malicious.cr @@ -0,0 +1,25 @@ +require "http/client" + +url = "http://example.test/%27%22%60$(%(%%7B%7B%7B/0%s//?'=squote-key-test&squote-value-test='&%22=dquote-key-test&dquote-value-test=%22&%60=backtick-key-test&backtick-value-test=%60&%24(=dollar-parenthesis-key-test&dollar-parenthesis-value-test=%24(&%23%7B=hash-brace-key-test&hash-brace-value-test=%23%7B&%25(=percent-parenthesis-key-test&percent-parenthesis-value-test=%25(&%25%7B=percent-brace-key-test&percent-brace-value-test=%25%7B&%7B%7B=double-brace-key-test&double-brace-value-test=%7B%7B&%5C0=null-key-test&null-value-test=%5C0&%25s=string-fmt-key-test&string-fmt-value-test=%25s&%5C=slash-key-test&slash-value-test=%5C" +headers = HTTP::Headers{ + "'" => "squote-key-test" + "squote-value-test" => "'" + "dquote-value-test" => "\"" + "`" => "backtick-key-test" + "backtick-value-test" => "`" + "$" => "dollar-key-test" + "dollar-parenthesis-value-test" => "$(" + "#" => "hash-key-test" + "hash-brace-value-test" => "#{" + "%" => "percent-key-test" + "percent-parenthesis-value-test" => "%(" + "percent-brace-value-test" => "%{" + "double-brace-value-test" => "{{" + "null-value-test" => "\\0" + "string-fmt-value-test" => "%s" + "slash-value-test" => "\\" +} +reqBody = "' \" ` $( #{ %( %{ {{ \\0 %s \\" + +response = HTTP::Client.post url, headers: headers, body: reqBody +puts response.body \ No newline at end of file diff --git a/test/fixtures/output/crystal/native/multipart-data.cr b/test/fixtures/output/crystal/native/multipart-data.cr new file mode 100644 index 0000000..96f265a --- /dev/null +++ b/test/fixtures/output/crystal/native/multipart-data.cr @@ -0,0 +1,10 @@ +require "http/client" + +url = "http://mockbin.com/har" +headers = HTTP::Headers{ + "content-type" => "multipart/form-data; boundary=---011000010111000001101001" +} +reqBody = "-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"foo\"; filename=\"hello.txt\"\r\nContent-Type: text/plain\r\n\r\nHello World\r\n-----011000010111000001101001--\r\n" + +response = HTTP::Client.post url, headers: headers, body: reqBody +puts response.body \ No newline at end of file diff --git a/test/fixtures/output/crystal/native/multipart-file.cr b/test/fixtures/output/crystal/native/multipart-file.cr new file mode 100644 index 0000000..1555da8 --- /dev/null +++ b/test/fixtures/output/crystal/native/multipart-file.cr @@ -0,0 +1,10 @@ +require "http/client" + +url = "http://mockbin.com/har" +headers = HTTP::Headers{ + "content-type" => "multipart/form-data; boundary=---011000010111000001101001" +} +reqBody = "-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"foo\"; filename=\"hello.txt\"\r\nContent-Type: text/plain\r\n\r\n\r\n-----011000010111000001101001--\r\n" + +response = HTTP::Client.post url, headers: headers, body: reqBody +puts response.body \ No newline at end of file diff --git a/test/fixtures/output/crystal/native/multipart-form-data.cr b/test/fixtures/output/crystal/native/multipart-form-data.cr new file mode 100644 index 0000000..d5216d7 --- /dev/null +++ b/test/fixtures/output/crystal/native/multipart-form-data.cr @@ -0,0 +1,10 @@ +require "http/client" + +url = "http://mockbin.com/har" +headers = HTTP::Headers{ + "Content-Type" => "multipart/form-data; boundary=---011000010111000001101001" +} +reqBody = "-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"foo\"\r\n\r\nbar\r\n-----011000010111000001101001--\r\n" + +response = HTTP::Client.post url, headers: headers, body: reqBody +puts response.body \ No newline at end of file diff --git a/test/fixtures/output/crystal/native/nested.cr b/test/fixtures/output/crystal/native/nested.cr new file mode 100644 index 0000000..f6fbf4b --- /dev/null +++ b/test/fixtures/output/crystal/native/nested.cr @@ -0,0 +1,6 @@ +require "http/client" + +url = "http://mockbin.com/har?foo%5Bbar%5D=baz%2Czap&fiz=buz&key=value" + +response = HTTP::Client.get url +puts response.body \ No newline at end of file diff --git a/test/fixtures/output/crystal/native/query.cr b/test/fixtures/output/crystal/native/query.cr new file mode 100644 index 0000000..cacc2b3 --- /dev/null +++ b/test/fixtures/output/crystal/native/query.cr @@ -0,0 +1,6 @@ +require "http/client" + +url = "http://mockbin.com/har?foo=bar&foo=baz&baz=abc&key=value" + +response = HTTP::Client.get url +puts response.body \ No newline at end of file diff --git a/test/fixtures/output/crystal/native/short.cr b/test/fixtures/output/crystal/native/short.cr new file mode 100644 index 0000000..0715616 --- /dev/null +++ b/test/fixtures/output/crystal/native/short.cr @@ -0,0 +1,6 @@ +require "http/client" + +url = "http://mockbin.com/har" + +response = HTTP::Client.get url +puts response.body \ No newline at end of file diff --git a/test/fixtures/output/crystal/native/text-plain.cr b/test/fixtures/output/crystal/native/text-plain.cr new file mode 100644 index 0000000..8890116 --- /dev/null +++ b/test/fixtures/output/crystal/native/text-plain.cr @@ -0,0 +1,10 @@ +require "http/client" + +url = "http://mockbin.com/har" +headers = HTTP::Headers{ + "content-type" => "text/plain" +} +reqBody = "Hello World" + +response = HTTP::Client.post url, headers: headers, body: reqBody +puts response.body \ No newline at end of file diff --git a/test/fixtures/output/crystal/native/unparseable-query.cr b/test/fixtures/output/crystal/native/unparseable-query.cr new file mode 100644 index 0000000..83b1dd7 --- /dev/null +++ b/test/fixtures/output/crystal/native/unparseable-query.cr @@ -0,0 +1,6 @@ +require "http/client" + +url = "http://mockbin.com/har?&&a=b&&" + +response = HTTP::Client.get url +puts response.body \ No newline at end of file diff --git a/test/fixtures/output/csharp/httpclient/compression.cs b/test/fixtures/output/csharp/httpclient/compression.cs new file mode 100644 index 0000000..52fba9a --- /dev/null +++ b/test/fixtures/output/csharp/httpclient/compression.cs @@ -0,0 +1,16 @@ +var clientHandler = new HttpClientHandler +{ + AutomaticDecompression = DecompressionMethods.Deflate | DecompressionMethods.GZip, +}; +var client = new HttpClient(clientHandler); +var request = new HttpRequestMessage +{ + Method = HttpMethod.Get, + RequestUri = new Uri("http://mockbin.com/har"), +}; +using (var response = await client.SendAsync(request)) +{ + response.EnsureSuccessStatusCode(); + var body = await response.Content.ReadAsStringAsync(); + Console.WriteLine(body); +} \ No newline at end of file diff --git a/test/fixtures/output/csharp/httpclient/headers.cs b/test/fixtures/output/csharp/httpclient/headers.cs index ad317d7..e63b8de 100644 --- a/test/fixtures/output/csharp/httpclient/headers.cs +++ b/test/fixtures/output/csharp/httpclient/headers.cs @@ -7,6 +7,7 @@ { { "accept", "application/json" }, { "x-foo", "Bar" }, + { "quoted-value", "\"quoted\" 'string'" }, }, }; using (var response = await client.SendAsync(request)) diff --git a/test/fixtures/output/csharp/httpclient/malicious.cs b/test/fixtures/output/csharp/httpclient/malicious.cs new file mode 100644 index 0000000..7524b59 --- /dev/null +++ b/test/fixtures/output/csharp/httpclient/malicious.cs @@ -0,0 +1,38 @@ +var client = new HttpClient(); +var request = new HttpRequestMessage +{ + Method = HttpMethod.Post, + RequestUri = new Uri("http://example.test/%27%22%60$(%(%%7B%7B%7B/0%s//?'=squote-key-test&squote-value-test='&%22=dquote-key-test&dquote-value-test=%22&%60=backtick-key-test&backtick-value-test=%60&%24(=dollar-parenthesis-key-test&dollar-parenthesis-value-test=%24(&%23%7B=hash-brace-key-test&hash-brace-value-test=%23%7B&%25(=percent-parenthesis-key-test&percent-parenthesis-value-test=%25(&%25%7B=percent-brace-key-test&percent-brace-value-test=%25%7B&%7B%7B=double-brace-key-test&double-brace-value-test=%7B%7B&%5C0=null-key-test&null-value-test=%5C0&%25s=string-fmt-key-test&string-fmt-value-test=%25s&%5C=slash-key-test&slash-value-test=%5C"), + Headers = + { + { "'", "squote-key-test" }, + { "squote-value-test", "'" }, + { "dquote-value-test", "\"" }, + { "`", "backtick-key-test" }, + { "backtick-value-test", "`" }, + { "$", "dollar-key-test" }, + { "dollar-parenthesis-value-test", "$(" }, + { "#", "hash-key-test" }, + { "hash-brace-value-test", "#{" }, + { "%", "percent-key-test" }, + { "percent-parenthesis-value-test", "%(" }, + { "percent-brace-value-test", "%{" }, + { "double-brace-value-test", "{{" }, + { "null-value-test", "\\0" }, + { "string-fmt-value-test", "%s" }, + { "slash-value-test", "\\" }, + }, + Content = new StringContent("' \" ` $( #{ %( %{ {{ \\0 %s \\") + { + Headers = + { + ContentType = new MediaTypeHeaderValue("text/plain") + } + } +}; +using (var response = await client.SendAsync(request)) +{ + response.EnsureSuccessStatusCode(); + var body = await response.Content.ReadAsStringAsync(); + Console.WriteLine(body); +} \ No newline at end of file diff --git a/test/fixtures/output/csharp/httpclient/unparseable-query.cs b/test/fixtures/output/csharp/httpclient/unparseable-query.cs new file mode 100644 index 0000000..c0659b0 --- /dev/null +++ b/test/fixtures/output/csharp/httpclient/unparseable-query.cs @@ -0,0 +1,12 @@ +var client = new HttpClient(); +var request = new HttpRequestMessage +{ + Method = HttpMethod.Get, + RequestUri = new Uri("http://mockbin.com/har?&&a=b&&"), +}; +using (var response = await client.SendAsync(request)) +{ + response.EnsureSuccessStatusCode(); + var body = await response.Content.ReadAsStringAsync(); + Console.WriteLine(body); +} \ No newline at end of file diff --git a/test/fixtures/output/csharp/restsharp/application-form-encoded.cs b/test/fixtures/output/csharp/restsharp/application-form-encoded.cs index 96f3f8b..2959968 100644 --- a/test/fixtures/output/csharp/restsharp/application-form-encoded.cs +++ b/test/fixtures/output/csharp/restsharp/application-form-encoded.cs @@ -1,5 +1,5 @@ -var client = new RestClient("http://mockbin.com/har"); -var request = new RestRequest(Method.POST); +var client = new RestClient("http://mockbin.com"); +var request = new RestRequest("/har", Method.Post); request.AddHeader("content-type", "application/x-www-form-urlencoded"); request.AddParameter("application/x-www-form-urlencoded", "foo=bar&hello=world", ParameterType.RequestBody); -IRestResponse response = client.Execute(request); +var response = client.Execute(request); \ No newline at end of file diff --git a/test/fixtures/output/csharp/restsharp/application-json.cs b/test/fixtures/output/csharp/restsharp/application-json.cs index 30a977b..5f1559b 100644 --- a/test/fixtures/output/csharp/restsharp/application-json.cs +++ b/test/fixtures/output/csharp/restsharp/application-json.cs @@ -1,5 +1,5 @@ -var client = new RestClient("http://mockbin.com/har"); -var request = new RestRequest(Method.POST); +var client = new RestClient("http://mockbin.com"); +var request = new RestRequest("/har", Method.Post); request.AddHeader("content-type", "application/json"); request.AddParameter("application/json", "{\"number\":1,\"string\":\"f\\\"oo\",\"arr\":[1,2,3],\"nested\":{\"a\":\"b\"},\"arr_mix\":[1,\"a\",{\"arr_mix_nested\":{}}],\"boolean\":false}", ParameterType.RequestBody); -IRestResponse response = client.Execute(request); +var response = client.Execute(request); \ No newline at end of file diff --git a/test/fixtures/output/csharp/restsharp/compression.cs b/test/fixtures/output/csharp/restsharp/compression.cs new file mode 100644 index 0000000..f7bab10 --- /dev/null +++ b/test/fixtures/output/csharp/restsharp/compression.cs @@ -0,0 +1,4 @@ +var client = new RestClient("http://mockbin.com"); +var request = new RestRequest("/har", Method.Get); +request.AddHeader("accept-encoding", "deflate, gzip, br"); +var response = client.Execute(request); \ No newline at end of file diff --git a/test/fixtures/output/csharp/restsharp/cookies.cs b/test/fixtures/output/csharp/restsharp/cookies.cs index 910b4f5..6e4d410 100644 --- a/test/fixtures/output/csharp/restsharp/cookies.cs +++ b/test/fixtures/output/csharp/restsharp/cookies.cs @@ -1,5 +1,5 @@ -var client = new RestClient("http://mockbin.com/har"); -var request = new RestRequest(Method.POST); +var client = new RestClient("http://mockbin.com"); +var request = new RestRequest("/har", Method.Post); request.AddCookie("foo", "bar"); request.AddCookie("bar", "baz"); -IRestResponse response = client.Execute(request); +var response = client.Execute(request); \ No newline at end of file diff --git a/test/fixtures/output/csharp/restsharp/custom-method.cs b/test/fixtures/output/csharp/restsharp/custom-method.cs index 5e5237a..8eb41a6 100644 --- a/test/fixtures/output/csharp/restsharp/custom-method.cs +++ b/test/fixtures/output/csharp/restsharp/custom-method.cs @@ -1 +1 @@ -Method not supported +Method not supported \ No newline at end of file diff --git a/test/fixtures/output/csharp/restsharp/full.cs b/test/fixtures/output/csharp/restsharp/full.cs index 2a326cc..6642d48 100644 --- a/test/fixtures/output/csharp/restsharp/full.cs +++ b/test/fixtures/output/csharp/restsharp/full.cs @@ -1,8 +1,8 @@ -var client = new RestClient("http://mockbin.com/har?foo=bar&foo=baz&baz=abc&key=value"); -var request = new RestRequest(Method.POST); +var client = new RestClient("http://mockbin.com"); +var request = new RestRequest("/har?foo=bar&foo=baz&baz=abc&key=value", Method.Post); request.AddHeader("accept", "application/json"); request.AddHeader("content-type", "application/x-www-form-urlencoded"); request.AddCookie("foo", "bar"); request.AddCookie("bar", "baz"); request.AddParameter("application/x-www-form-urlencoded", "foo=bar", ParameterType.RequestBody); -IRestResponse response = client.Execute(request); +var response = client.Execute(request); \ No newline at end of file diff --git a/test/fixtures/output/csharp/restsharp/headers.cs b/test/fixtures/output/csharp/restsharp/headers.cs index e338bb1..345f140 100644 --- a/test/fixtures/output/csharp/restsharp/headers.cs +++ b/test/fixtures/output/csharp/restsharp/headers.cs @@ -1,5 +1,6 @@ -var client = new RestClient("http://mockbin.com/har"); -var request = new RestRequest(Method.GET); +var client = new RestClient("http://mockbin.com"); +var request = new RestRequest("/har", Method.Get); request.AddHeader("accept", "application/json"); request.AddHeader("x-foo", "Bar"); -IRestResponse response = client.Execute(request); +request.AddHeader("quoted-value", "\"quoted\" 'string'"); +var response = client.Execute(request); \ No newline at end of file diff --git a/test/fixtures/output/csharp/restsharp/https.cs b/test/fixtures/output/csharp/restsharp/https.cs index 8be49d7..97355f7 100644 --- a/test/fixtures/output/csharp/restsharp/https.cs +++ b/test/fixtures/output/csharp/restsharp/https.cs @@ -1,3 +1,3 @@ -var client = new RestClient("https://mockbin.com/har"); -var request = new RestRequest(Method.GET); -IRestResponse response = client.Execute(request); +var client = new RestClient("https://mockbin.com"); +var request = new RestRequest("/har", Method.Get); +var response = client.Execute(request); \ No newline at end of file diff --git a/test/fixtures/output/csharp/restsharp/jsonObj-multiline.cs b/test/fixtures/output/csharp/restsharp/jsonObj-multiline.cs index 20a7577..b3062e3 100644 --- a/test/fixtures/output/csharp/restsharp/jsonObj-multiline.cs +++ b/test/fixtures/output/csharp/restsharp/jsonObj-multiline.cs @@ -1,5 +1,5 @@ -var client = new RestClient("http://mockbin.com/har"); -var request = new RestRequest(Method.POST); +var client = new RestClient("http://mockbin.com"); +var request = new RestRequest("/har", Method.Post); request.AddHeader("content-type", "application/json"); request.AddParameter("application/json", "{\n \"foo\": \"bar\"\n}", ParameterType.RequestBody); -IRestResponse response = client.Execute(request); +var response = client.Execute(request); \ No newline at end of file diff --git a/test/fixtures/output/csharp/restsharp/jsonObj-null-value.cs b/test/fixtures/output/csharp/restsharp/jsonObj-null-value.cs index fda9215..1eb3388 100644 --- a/test/fixtures/output/csharp/restsharp/jsonObj-null-value.cs +++ b/test/fixtures/output/csharp/restsharp/jsonObj-null-value.cs @@ -1,5 +1,5 @@ -var client = new RestClient("http://mockbin.com/har"); -var request = new RestRequest(Method.POST); +var client = new RestClient("http://mockbin.com"); +var request = new RestRequest("/har", Method.Post); request.AddHeader("content-type", "application/json"); request.AddParameter("application/json", "{\"foo\":null}", ParameterType.RequestBody); -IRestResponse response = client.Execute(request); +var response = client.Execute(request); \ No newline at end of file diff --git a/test/fixtures/output/csharp/restsharp/malicious.cs b/test/fixtures/output/csharp/restsharp/malicious.cs new file mode 100644 index 0000000..0c80d86 --- /dev/null +++ b/test/fixtures/output/csharp/restsharp/malicious.cs @@ -0,0 +1,20 @@ +var client = new RestClient("http://example.test"); +var request = new RestRequest("/%27%22%60$(%(%%7B%7B%7B/0%s//?'=squote-key-test&squote-value-test='&%22=dquote-key-test&dquote-value-test=%22&%60=backtick-key-test&backtick-value-test=%60&%24(=dollar-parenthesis-key-test&dollar-parenthesis-value-test=%24(&%23%7B=hash-brace-key-test&hash-brace-value-test=%23%7B&%25(=percent-parenthesis-key-test&percent-parenthesis-value-test=%25(&%25%7B=percent-brace-key-test&percent-brace-value-test=%25%7B&%7B%7B=double-brace-key-test&double-brace-value-test=%7B%7B&%5C0=null-key-test&null-value-test=%5C0&%25s=string-fmt-key-test&string-fmt-value-test=%25s&%5C=slash-key-test&slash-value-test=%5C", Method.Post); +request.AddHeader("'", "squote-key-test"); +request.AddHeader("squote-value-test", "'"); +request.AddHeader("dquote-value-test", "\""); +request.AddHeader("`", "backtick-key-test"); +request.AddHeader("backtick-value-test", "`"); +request.AddHeader("$", "dollar-key-test"); +request.AddHeader("dollar-parenthesis-value-test", "$("); +request.AddHeader("#", "hash-key-test"); +request.AddHeader("hash-brace-value-test", "#{"); +request.AddHeader("%", "percent-key-test"); +request.AddHeader("percent-parenthesis-value-test", "%("); +request.AddHeader("percent-brace-value-test", "%{"); +request.AddHeader("double-brace-value-test", "{{"); +request.AddHeader("null-value-test", "\\0"); +request.AddHeader("string-fmt-value-test", "%s"); +request.AddHeader("slash-value-test", "\\"); +request.AddParameter(null, "' \" ` $( #{ %( %{ {{ \\0 %s \\", ParameterType.RequestBody); +var response = client.Execute(request); \ No newline at end of file diff --git a/test/fixtures/output/csharp/restsharp/multipart-data.cs b/test/fixtures/output/csharp/restsharp/multipart-data.cs index 9db5bec..4d48b37 100644 --- a/test/fixtures/output/csharp/restsharp/multipart-data.cs +++ b/test/fixtures/output/csharp/restsharp/multipart-data.cs @@ -1,5 +1,5 @@ -var client = new RestClient("http://mockbin.com/har"); -var request = new RestRequest(Method.POST); +var client = new RestClient("http://mockbin.com"); +var request = new RestRequest("/har", Method.Post); request.AddHeader("content-type", "multipart/form-data; boundary=---011000010111000001101001"); request.AddParameter("multipart/form-data; boundary=---011000010111000001101001", "-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"foo\"; filename=\"hello.txt\"\r\nContent-Type: text/plain\r\n\r\nHello World\r\n-----011000010111000001101001--\r\n", ParameterType.RequestBody); -IRestResponse response = client.Execute(request); +var response = client.Execute(request); \ No newline at end of file diff --git a/test/fixtures/output/csharp/restsharp/multipart-file.cs b/test/fixtures/output/csharp/restsharp/multipart-file.cs index d91e66b..d449324 100644 --- a/test/fixtures/output/csharp/restsharp/multipart-file.cs +++ b/test/fixtures/output/csharp/restsharp/multipart-file.cs @@ -1,5 +1,5 @@ -var client = new RestClient("http://mockbin.com/har"); -var request = new RestRequest(Method.POST); +var client = new RestClient("http://mockbin.com"); +var request = new RestRequest("/har", Method.Post); request.AddHeader("content-type", "multipart/form-data; boundary=---011000010111000001101001"); request.AddParameter("multipart/form-data; boundary=---011000010111000001101001", "-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"foo\"; filename=\"hello.txt\"\r\nContent-Type: text/plain\r\n\r\n\r\n-----011000010111000001101001--\r\n", ParameterType.RequestBody); -IRestResponse response = client.Execute(request); +var response = client.Execute(request); \ No newline at end of file diff --git a/test/fixtures/output/csharp/restsharp/multipart-form-data.cs b/test/fixtures/output/csharp/restsharp/multipart-form-data.cs index aae6aa5..bae66ae 100644 --- a/test/fixtures/output/csharp/restsharp/multipart-form-data.cs +++ b/test/fixtures/output/csharp/restsharp/multipart-form-data.cs @@ -1,5 +1,5 @@ -var client = new RestClient("http://mockbin.com/har"); -var request = new RestRequest(Method.POST); +var client = new RestClient("http://mockbin.com"); +var request = new RestRequest("/har", Method.Post); request.AddHeader("Content-Type", "multipart/form-data; boundary=---011000010111000001101001"); request.AddParameter("multipart/form-data; boundary=---011000010111000001101001", "-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"foo\"\r\n\r\nbar\r\n-----011000010111000001101001--\r\n", ParameterType.RequestBody); -IRestResponse response = client.Execute(request); +var response = client.Execute(request); \ No newline at end of file diff --git a/test/fixtures/output/csharp/restsharp/nested.cs b/test/fixtures/output/csharp/restsharp/nested.cs index fbc0fd7..ba3dc6e 100644 --- a/test/fixtures/output/csharp/restsharp/nested.cs +++ b/test/fixtures/output/csharp/restsharp/nested.cs @@ -1,3 +1,3 @@ -var client = new RestClient("http://mockbin.com/har?foo%5Bbar%5D=baz%2Czap&fiz=buz&key=value"); -var request = new RestRequest(Method.GET); -IRestResponse response = client.Execute(request); +var client = new RestClient("http://mockbin.com"); +var request = new RestRequest("/har?foo%5Bbar%5D=baz%2Czap&fiz=buz&key=value", Method.Get); +var response = client.Execute(request); \ No newline at end of file diff --git a/test/fixtures/output/csharp/restsharp/query.cs b/test/fixtures/output/csharp/restsharp/query.cs index 9384530..36fdee0 100644 --- a/test/fixtures/output/csharp/restsharp/query.cs +++ b/test/fixtures/output/csharp/restsharp/query.cs @@ -1,3 +1,3 @@ -var client = new RestClient("http://mockbin.com/har?foo=bar&foo=baz&baz=abc&key=value"); -var request = new RestRequest(Method.GET); -IRestResponse response = client.Execute(request); +var client = new RestClient("http://mockbin.com"); +var request = new RestRequest("/har?foo=bar&foo=baz&baz=abc&key=value", Method.Get); +var response = client.Execute(request); \ No newline at end of file diff --git a/test/fixtures/output/csharp/restsharp/short.cs b/test/fixtures/output/csharp/restsharp/short.cs index eb5c9f5..1312efe 100644 --- a/test/fixtures/output/csharp/restsharp/short.cs +++ b/test/fixtures/output/csharp/restsharp/short.cs @@ -1,3 +1,3 @@ -var client = new RestClient("http://mockbin.com/har"); -var request = new RestRequest(Method.GET); -IRestResponse response = client.Execute(request); +var client = new RestClient("http://mockbin.com"); +var request = new RestRequest("/har", Method.Get); +var response = client.Execute(request); \ No newline at end of file diff --git a/test/fixtures/output/csharp/restsharp/text-plain.cs b/test/fixtures/output/csharp/restsharp/text-plain.cs index 958eb97..5789fa7 100644 --- a/test/fixtures/output/csharp/restsharp/text-plain.cs +++ b/test/fixtures/output/csharp/restsharp/text-plain.cs @@ -1,5 +1,5 @@ -var client = new RestClient("http://mockbin.com/har"); -var request = new RestRequest(Method.POST); +var client = new RestClient("http://mockbin.com"); +var request = new RestRequest("/har", Method.Post); request.AddHeader("content-type", "text/plain"); request.AddParameter("text/plain", "Hello World", ParameterType.RequestBody); -IRestResponse response = client.Execute(request); +var response = client.Execute(request); \ No newline at end of file diff --git a/test/fixtures/output/csharp/restsharp/unparseable-query.cs b/test/fixtures/output/csharp/restsharp/unparseable-query.cs new file mode 100644 index 0000000..2089b1b --- /dev/null +++ b/test/fixtures/output/csharp/restsharp/unparseable-query.cs @@ -0,0 +1,3 @@ +var client = new RestClient("http://mockbin.com"); +var request = new RestRequest("/har?&&a=b&&", Method.Get); +var response = client.Execute(request); \ No newline at end of file diff --git a/test/fixtures/output/go/native/application-form-encoded.go b/test/fixtures/output/go/native/application-form-encoded.go index 5344b4e..18b5cda 100644 --- a/test/fixtures/output/go/native/application-form-encoded.go +++ b/test/fixtures/output/go/native/application-form-encoded.go @@ -4,7 +4,7 @@ import ( "fmt" "strings" "net/http" - "io/ioutil" + "io" ) func main() { @@ -20,7 +20,7 @@ func main() { res, _ := http.DefaultClient.Do(req) defer res.Body.Close() - body, _ := ioutil.ReadAll(res.Body) + body, _ := io.ReadAll(res.Body) fmt.Println(res) fmt.Println(string(body)) diff --git a/test/fixtures/output/go/native/application-json.go b/test/fixtures/output/go/native/application-json.go index c9dba6a..e2cdb35 100644 --- a/test/fixtures/output/go/native/application-json.go +++ b/test/fixtures/output/go/native/application-json.go @@ -4,7 +4,7 @@ import ( "fmt" "strings" "net/http" - "io/ioutil" + "io" ) func main() { @@ -20,7 +20,7 @@ func main() { res, _ := http.DefaultClient.Do(req) defer res.Body.Close() - body, _ := ioutil.ReadAll(res.Body) + body, _ := io.ReadAll(res.Body) fmt.Println(res) fmt.Println(string(body)) diff --git a/test/fixtures/output/go/native/compression.go b/test/fixtures/output/go/native/compression.go new file mode 100644 index 0000000..fae06af --- /dev/null +++ b/test/fixtures/output/go/native/compression.go @@ -0,0 +1,23 @@ +package main + +import ( + "fmt" + "net/http" + "io" +) + +func main() { + + url := "http://mockbin.com/har" + + req, _ := http.NewRequest("GET", url, nil) + + res, _ := http.DefaultClient.Do(req) + + defer res.Body.Close() + body, _ := io.ReadAll(res.Body) + + fmt.Println(res) + fmt.Println(string(body)) + +} \ No newline at end of file diff --git a/test/fixtures/output/go/native/cookies.go b/test/fixtures/output/go/native/cookies.go index cd70638..ff804f8 100644 --- a/test/fixtures/output/go/native/cookies.go +++ b/test/fixtures/output/go/native/cookies.go @@ -3,7 +3,7 @@ package main import ( "fmt" "net/http" - "io/ioutil" + "io" ) func main() { @@ -17,7 +17,7 @@ func main() { res, _ := http.DefaultClient.Do(req) defer res.Body.Close() - body, _ := ioutil.ReadAll(res.Body) + body, _ := io.ReadAll(res.Body) fmt.Println(res) fmt.Println(string(body)) diff --git a/test/fixtures/output/go/native/custom-method.go b/test/fixtures/output/go/native/custom-method.go index 00c86ae..a94b6c2 100644 --- a/test/fixtures/output/go/native/custom-method.go +++ b/test/fixtures/output/go/native/custom-method.go @@ -3,7 +3,7 @@ package main import ( "fmt" "net/http" - "io/ioutil" + "io" ) func main() { @@ -15,7 +15,7 @@ func main() { res, _ := http.DefaultClient.Do(req) defer res.Body.Close() - body, _ := ioutil.ReadAll(res.Body) + body, _ := io.ReadAll(res.Body) fmt.Println(res) fmt.Println(string(body)) diff --git a/test/fixtures/output/go/native/full.go b/test/fixtures/output/go/native/full.go index 7166a6a..7992b37 100644 --- a/test/fixtures/output/go/native/full.go +++ b/test/fixtures/output/go/native/full.go @@ -4,7 +4,7 @@ import ( "fmt" "strings" "net/http" - "io/ioutil" + "io" ) func main() { @@ -22,7 +22,7 @@ func main() { res, _ := http.DefaultClient.Do(req) defer res.Body.Close() - body, _ := ioutil.ReadAll(res.Body) + body, _ := io.ReadAll(res.Body) fmt.Println(res) fmt.Println(string(body)) diff --git a/test/fixtures/output/go/native/headers.go b/test/fixtures/output/go/native/headers.go index 0d09039..57bbca5 100644 --- a/test/fixtures/output/go/native/headers.go +++ b/test/fixtures/output/go/native/headers.go @@ -3,7 +3,7 @@ package main import ( "fmt" "net/http" - "io/ioutil" + "io" ) func main() { @@ -14,11 +14,12 @@ func main() { req.Header.Add("accept", "application/json") req.Header.Add("x-foo", "Bar") + req.Header.Add("quoted-value", "\"quoted\" 'string'") res, _ := http.DefaultClient.Do(req) defer res.Body.Close() - body, _ := ioutil.ReadAll(res.Body) + body, _ := io.ReadAll(res.Body) fmt.Println(res) fmt.Println(string(body)) diff --git a/test/fixtures/output/go/native/https.go b/test/fixtures/output/go/native/https.go index 40e7723..3737fc1 100644 --- a/test/fixtures/output/go/native/https.go +++ b/test/fixtures/output/go/native/https.go @@ -3,7 +3,7 @@ package main import ( "fmt" "net/http" - "io/ioutil" + "io" ) func main() { @@ -15,7 +15,7 @@ func main() { res, _ := http.DefaultClient.Do(req) defer res.Body.Close() - body, _ := ioutil.ReadAll(res.Body) + body, _ := io.ReadAll(res.Body) fmt.Println(res) fmt.Println(string(body)) diff --git a/test/fixtures/output/go/native/jsonObj-multiline.go b/test/fixtures/output/go/native/jsonObj-multiline.go index 9f80486..8d1ee53 100644 --- a/test/fixtures/output/go/native/jsonObj-multiline.go +++ b/test/fixtures/output/go/native/jsonObj-multiline.go @@ -4,7 +4,7 @@ import ( "fmt" "strings" "net/http" - "io/ioutil" + "io" ) func main() { @@ -20,7 +20,7 @@ func main() { res, _ := http.DefaultClient.Do(req) defer res.Body.Close() - body, _ := ioutil.ReadAll(res.Body) + body, _ := io.ReadAll(res.Body) fmt.Println(res) fmt.Println(string(body)) diff --git a/test/fixtures/output/go/native/jsonObj-null-value.go b/test/fixtures/output/go/native/jsonObj-null-value.go index 8d920d7..15a9bb2 100644 --- a/test/fixtures/output/go/native/jsonObj-null-value.go +++ b/test/fixtures/output/go/native/jsonObj-null-value.go @@ -4,7 +4,7 @@ import ( "fmt" "strings" "net/http" - "io/ioutil" + "io" ) func main() { @@ -20,7 +20,7 @@ func main() { res, _ := http.DefaultClient.Do(req) defer res.Body.Close() - body, _ := ioutil.ReadAll(res.Body) + body, _ := io.ReadAll(res.Body) fmt.Println(res) fmt.Println(string(body)) diff --git a/test/fixtures/output/go/native/malicious.go b/test/fixtures/output/go/native/malicious.go new file mode 100644 index 0000000..0e89205 --- /dev/null +++ b/test/fixtures/output/go/native/malicious.go @@ -0,0 +1,43 @@ +package main + +import ( + "fmt" + "strings" + "net/http" + "io" +) + +func main() { + + url := "http://example.test/%27%22%60$(%(%%7B%7B%7B/0%s//?'=squote-key-test&squote-value-test='&%22=dquote-key-test&dquote-value-test=%22&%60=backtick-key-test&backtick-value-test=%60&%24(=dollar-parenthesis-key-test&dollar-parenthesis-value-test=%24(&%23%7B=hash-brace-key-test&hash-brace-value-test=%23%7B&%25(=percent-parenthesis-key-test&percent-parenthesis-value-test=%25(&%25%7B=percent-brace-key-test&percent-brace-value-test=%25%7B&%7B%7B=double-brace-key-test&double-brace-value-test=%7B%7B&%5C0=null-key-test&null-value-test=%5C0&%25s=string-fmt-key-test&string-fmt-value-test=%25s&%5C=slash-key-test&slash-value-test=%5C" + + payload := strings.NewReader("' \" ` $( #{ %( %{ {{ \\0 %s \\") + + req, _ := http.NewRequest("POST", url, payload) + + req.Header.Add("'", "squote-key-test") + req.Header.Add("squote-value-test", "'") + req.Header.Add("dquote-value-test", "\"") + req.Header.Add("`", "backtick-key-test") + req.Header.Add("backtick-value-test", "`") + req.Header.Add("$", "dollar-key-test") + req.Header.Add("dollar-parenthesis-value-test", "$(") + req.Header.Add("#", "hash-key-test") + req.Header.Add("hash-brace-value-test", "#{") + req.Header.Add("%", "percent-key-test") + req.Header.Add("percent-parenthesis-value-test", "%(") + req.Header.Add("percent-brace-value-test", "%{") + req.Header.Add("double-brace-value-test", "{{") + req.Header.Add("null-value-test", "\\0") + req.Header.Add("string-fmt-value-test", "%s") + req.Header.Add("slash-value-test", "\\") + + res, _ := http.DefaultClient.Do(req) + + defer res.Body.Close() + body, _ := io.ReadAll(res.Body) + + fmt.Println(res) + fmt.Println(string(body)) + +} \ No newline at end of file diff --git a/test/fixtures/output/go/native/multipart-data.go b/test/fixtures/output/go/native/multipart-data.go index 3bc875a..f607877 100644 --- a/test/fixtures/output/go/native/multipart-data.go +++ b/test/fixtures/output/go/native/multipart-data.go @@ -4,7 +4,7 @@ import ( "fmt" "strings" "net/http" - "io/ioutil" + "io" ) func main() { @@ -20,7 +20,7 @@ func main() { res, _ := http.DefaultClient.Do(req) defer res.Body.Close() - body, _ := ioutil.ReadAll(res.Body) + body, _ := io.ReadAll(res.Body) fmt.Println(res) fmt.Println(string(body)) diff --git a/test/fixtures/output/go/native/multipart-file.go b/test/fixtures/output/go/native/multipart-file.go index 931cd28..0355970 100644 --- a/test/fixtures/output/go/native/multipart-file.go +++ b/test/fixtures/output/go/native/multipart-file.go @@ -4,7 +4,7 @@ import ( "fmt" "strings" "net/http" - "io/ioutil" + "io" ) func main() { @@ -20,7 +20,7 @@ func main() { res, _ := http.DefaultClient.Do(req) defer res.Body.Close() - body, _ := ioutil.ReadAll(res.Body) + body, _ := io.ReadAll(res.Body) fmt.Println(res) fmt.Println(string(body)) diff --git a/test/fixtures/output/go/native/multipart-form-data.go b/test/fixtures/output/go/native/multipart-form-data.go index cf31548..2d46d6a 100644 --- a/test/fixtures/output/go/native/multipart-form-data.go +++ b/test/fixtures/output/go/native/multipart-form-data.go @@ -4,7 +4,7 @@ import ( "fmt" "strings" "net/http" - "io/ioutil" + "io" ) func main() { @@ -20,7 +20,7 @@ func main() { res, _ := http.DefaultClient.Do(req) defer res.Body.Close() - body, _ := ioutil.ReadAll(res.Body) + body, _ := io.ReadAll(res.Body) fmt.Println(res) fmt.Println(string(body)) diff --git a/test/fixtures/output/go/native/nested.go b/test/fixtures/output/go/native/nested.go index f392179..2089b7d 100644 --- a/test/fixtures/output/go/native/nested.go +++ b/test/fixtures/output/go/native/nested.go @@ -3,7 +3,7 @@ package main import ( "fmt" "net/http" - "io/ioutil" + "io" ) func main() { @@ -15,7 +15,7 @@ func main() { res, _ := http.DefaultClient.Do(req) defer res.Body.Close() - body, _ := ioutil.ReadAll(res.Body) + body, _ := io.ReadAll(res.Body) fmt.Println(res) fmt.Println(string(body)) diff --git a/test/fixtures/output/go/native/query.go b/test/fixtures/output/go/native/query.go index e2e47ac..6f2ab48 100644 --- a/test/fixtures/output/go/native/query.go +++ b/test/fixtures/output/go/native/query.go @@ -3,7 +3,7 @@ package main import ( "fmt" "net/http" - "io/ioutil" + "io" ) func main() { @@ -15,7 +15,7 @@ func main() { res, _ := http.DefaultClient.Do(req) defer res.Body.Close() - body, _ := ioutil.ReadAll(res.Body) + body, _ := io.ReadAll(res.Body) fmt.Println(res) fmt.Println(string(body)) diff --git a/test/fixtures/output/go/native/short.go b/test/fixtures/output/go/native/short.go index 441f2a0..7384b12 100644 --- a/test/fixtures/output/go/native/short.go +++ b/test/fixtures/output/go/native/short.go @@ -3,7 +3,7 @@ package main import ( "fmt" "net/http" - "io/ioutil" + "io" ) func main() { @@ -15,7 +15,7 @@ func main() { res, _ := http.DefaultClient.Do(req) defer res.Body.Close() - body, _ := ioutil.ReadAll(res.Body) + body, _ := io.ReadAll(res.Body) fmt.Println(res) fmt.Println(string(body)) diff --git a/test/fixtures/output/go/native/text-plain.go b/test/fixtures/output/go/native/text-plain.go index ccf1c7a..6f72891 100644 --- a/test/fixtures/output/go/native/text-plain.go +++ b/test/fixtures/output/go/native/text-plain.go @@ -4,7 +4,7 @@ import ( "fmt" "strings" "net/http" - "io/ioutil" + "io" ) func main() { @@ -20,7 +20,7 @@ func main() { res, _ := http.DefaultClient.Do(req) defer res.Body.Close() - body, _ := ioutil.ReadAll(res.Body) + body, _ := io.ReadAll(res.Body) fmt.Println(res) fmt.Println(string(body)) diff --git a/test/fixtures/output/go/native/unparseable-query.go b/test/fixtures/output/go/native/unparseable-query.go new file mode 100644 index 0000000..655601e --- /dev/null +++ b/test/fixtures/output/go/native/unparseable-query.go @@ -0,0 +1,23 @@ +package main + +import ( + "fmt" + "net/http" + "io" +) + +func main() { + + url := "http://mockbin.com/har?&&a=b&&" + + req, _ := http.NewRequest("GET", url, nil) + + res, _ := http.DefaultClient.Do(req) + + defer res.Body.Close() + body, _ := io.ReadAll(res.Body) + + fmt.Println(res) + fmt.Println(string(body)) + +} \ No newline at end of file diff --git a/test/fixtures/output/http/1.1/application-form-encoded b/test/fixtures/output/http/1.1/application-form-encoded index 723d94a..a979905 100644 --- a/test/fixtures/output/http/1.1/application-form-encoded +++ b/test/fixtures/output/http/1.1/application-form-encoded @@ -1,5 +1,5 @@ POST /har HTTP/1.1 -Content-Type: application/x-www-form-urlencoded +content-type: application/x-www-form-urlencoded Host: mockbin.com Content-Length: 19 diff --git a/test/fixtures/output/http/1.1/application-json b/test/fixtures/output/http/1.1/application-json index ee65b54..ac5f1b3 100644 --- a/test/fixtures/output/http/1.1/application-json +++ b/test/fixtures/output/http/1.1/application-json @@ -1,5 +1,5 @@ POST /har HTTP/1.1 -Content-Type: application/json +content-type: application/json Host: mockbin.com Content-Length: 118 diff --git a/test/fixtures/output/http/1.1/compression b/test/fixtures/output/http/1.1/compression new file mode 100644 index 0000000..9a99d1b --- /dev/null +++ b/test/fixtures/output/http/1.1/compression @@ -0,0 +1,3 @@ +GET /har HTTP/1.1 +accept-encoding: deflate, gzip, br +Host: mockbin.com \ No newline at end of file diff --git a/test/fixtures/output/http/1.1/full b/test/fixtures/output/http/1.1/full index d4d41ec..530af73 100644 --- a/test/fixtures/output/http/1.1/full +++ b/test/fixtures/output/http/1.1/full @@ -1,7 +1,7 @@ POST /har?foo=bar&foo=baz&baz=abc&key=value HTTP/1.1 +accept: application/json +content-type: application/x-www-form-urlencoded Cookie: foo=bar; bar=baz -Accept: application/json -Content-Type: application/x-www-form-urlencoded Host: mockbin.com Content-Length: 7 diff --git a/test/fixtures/output/http/1.1/headers b/test/fixtures/output/http/1.1/headers index 7bde2bc..171dbda 100644 --- a/test/fixtures/output/http/1.1/headers +++ b/test/fixtures/output/http/1.1/headers @@ -1,6 +1,7 @@ GET /har HTTP/1.1 -Accept: application/json -X-Foo: Bar +accept: application/json +x-foo: Bar +quoted-value: "quoted" 'string' Host: mockbin.com diff --git a/test/fixtures/output/http/1.1/jsonObj-multiline b/test/fixtures/output/http/1.1/jsonObj-multiline index ebc26ad..9c19277 100644 --- a/test/fixtures/output/http/1.1/jsonObj-multiline +++ b/test/fixtures/output/http/1.1/jsonObj-multiline @@ -1,5 +1,5 @@ POST /har HTTP/1.1 -Content-Type: application/json +content-type: application/json Host: mockbin.com Content-Length: 18 diff --git a/test/fixtures/output/http/1.1/jsonObj-null-value b/test/fixtures/output/http/1.1/jsonObj-null-value index 240a57b..e4c7e14 100644 --- a/test/fixtures/output/http/1.1/jsonObj-null-value +++ b/test/fixtures/output/http/1.1/jsonObj-null-value @@ -1,5 +1,5 @@ POST /har HTTP/1.1 -Content-Type: application/json +content-type: application/json Host: mockbin.com Content-Length: 12 diff --git a/test/fixtures/output/http/1.1/malicious b/test/fixtures/output/http/1.1/malicious new file mode 100644 index 0000000..8f7cbe3 --- /dev/null +++ b/test/fixtures/output/http/1.1/malicious @@ -0,0 +1,21 @@ +POST /%27%22%60$(%(%%7B%7B%7B/0%s//?'=squote-key-test&squote-value-test='&%22=dquote-key-test&dquote-value-test=%22&%60=backtick-key-test&backtick-value-test=%60&%24(=dollar-parenthesis-key-test&dollar-parenthesis-value-test=%24(&%23%7B=hash-brace-key-test&hash-brace-value-test=%23%7B&%25(=percent-parenthesis-key-test&percent-parenthesis-value-test=%25(&%25%7B=percent-brace-key-test&percent-brace-value-test=%25%7B&%7B%7B=double-brace-key-test&double-brace-value-test=%7B%7B&%5C0=null-key-test&null-value-test=%5C0&%25s=string-fmt-key-test&string-fmt-value-test=%25s&%5C=slash-key-test&slash-value-test=%5C HTTP/1.1 +': squote-key-test +squote-value-test: ' +dquote-value-test: " +`: backtick-key-test +backtick-value-test: ` +$: dollar-key-test +dollar-parenthesis-value-test: $( +#: hash-key-test +hash-brace-value-test: #{ +%: percent-key-test +percent-parenthesis-value-test: %( +percent-brace-value-test: %{ +double-brace-value-test: {{ +null-value-test: \0 +string-fmt-value-test: %s +slash-value-test: \ +Host: example.test +Content-Length: 28 + +' " ` $( #{ %( %{ {{ \0 %s \ \ No newline at end of file diff --git a/test/fixtures/output/http/1.1/multipart-data b/test/fixtures/output/http/1.1/multipart-data index cbe1c5f..d0306c7 100644 --- a/test/fixtures/output/http/1.1/multipart-data +++ b/test/fixtures/output/http/1.1/multipart-data @@ -1,5 +1,5 @@ POST /har HTTP/1.1 -Content-Type: multipart/form-data; boundary=---011000010111000001101001 +content-type: multipart/form-data; boundary=---011000010111000001101001 Host: mockbin.com Content-Length: 171 diff --git a/test/fixtures/output/http/1.1/multipart-file b/test/fixtures/output/http/1.1/multipart-file index be0776f..0f8d0e0 100644 --- a/test/fixtures/output/http/1.1/multipart-file +++ b/test/fixtures/output/http/1.1/multipart-file @@ -1,5 +1,5 @@ POST /har HTTP/1.1 -Content-Type: multipart/form-data; boundary=---011000010111000001101001 +content-type: multipart/form-data; boundary=---011000010111000001101001 Host: mockbin.com Content-Length: 160 diff --git a/test/fixtures/output/http/1.1/text-plain b/test/fixtures/output/http/1.1/text-plain index c341a43..6ba9edf 100644 --- a/test/fixtures/output/http/1.1/text-plain +++ b/test/fixtures/output/http/1.1/text-plain @@ -1,5 +1,5 @@ POST /har HTTP/1.1 -Content-Type: text/plain +content-type: text/plain Host: mockbin.com Content-Length: 11 diff --git a/test/fixtures/output/http/1.1/unparseable-query b/test/fixtures/output/http/1.1/unparseable-query new file mode 100644 index 0000000..d4e4f28 --- /dev/null +++ b/test/fixtures/output/http/1.1/unparseable-query @@ -0,0 +1,2 @@ +GET /har?&&a=b&& HTTP/1.1 +Host: mockbin.com \ No newline at end of file diff --git a/test/fixtures/output/java/asynchttp/compression.java b/test/fixtures/output/java/asynchttp/compression.java new file mode 100644 index 0000000..ecadc31 --- /dev/null +++ b/test/fixtures/output/java/asynchttp/compression.java @@ -0,0 +1,9 @@ +AsyncHttpClient client = new DefaultAsyncHttpClient(); +client.prepare("GET", "http://mockbin.com/har") + .setHeader("accept-encoding", "deflate, gzip, br") + .execute() + .toCompletableFuture() + .thenAccept(System.out::println) + .join(); + +client.close(); \ No newline at end of file diff --git a/test/fixtures/output/java/asynchttp/headers.java b/test/fixtures/output/java/asynchttp/headers.java index 472fe09..69a96ed 100644 --- a/test/fixtures/output/java/asynchttp/headers.java +++ b/test/fixtures/output/java/asynchttp/headers.java @@ -2,6 +2,7 @@ client.prepare("GET", "http://mockbin.com/har") .setHeader("accept", "application/json") .setHeader("x-foo", "Bar") + .setHeader("quoted-value", "\"quoted\" 'string'") .execute() .toCompletableFuture() .thenAccept(System.out::println) diff --git a/test/fixtures/output/java/asynchttp/malicious.java b/test/fixtures/output/java/asynchttp/malicious.java new file mode 100644 index 0000000..763dab9 --- /dev/null +++ b/test/fixtures/output/java/asynchttp/malicious.java @@ -0,0 +1,25 @@ +AsyncHttpClient client = new DefaultAsyncHttpClient(); +client.prepare("POST", "http://example.test/%27%22%60$(%(%%7B%7B%7B/0%s//?'=squote-key-test&squote-value-test='&%22=dquote-key-test&dquote-value-test=%22&%60=backtick-key-test&backtick-value-test=%60&%24(=dollar-parenthesis-key-test&dollar-parenthesis-value-test=%24(&%23%7B=hash-brace-key-test&hash-brace-value-test=%23%7B&%25(=percent-parenthesis-key-test&percent-parenthesis-value-test=%25(&%25%7B=percent-brace-key-test&percent-brace-value-test=%25%7B&%7B%7B=double-brace-key-test&double-brace-value-test=%7B%7B&%5C0=null-key-test&null-value-test=%5C0&%25s=string-fmt-key-test&string-fmt-value-test=%25s&%5C=slash-key-test&slash-value-test=%5C") + .setHeader("'", "squote-key-test") + .setHeader("squote-value-test", "'") + .setHeader("dquote-value-test", "\"") + .setHeader("`", "backtick-key-test") + .setHeader("backtick-value-test", "`") + .setHeader("$", "dollar-key-test") + .setHeader("dollar-parenthesis-value-test", "$(") + .setHeader("#", "hash-key-test") + .setHeader("hash-brace-value-test", "#{") + .setHeader("%", "percent-key-test") + .setHeader("percent-parenthesis-value-test", "%(") + .setHeader("percent-brace-value-test", "%{") + .setHeader("double-brace-value-test", "{{") + .setHeader("null-value-test", "\\0") + .setHeader("string-fmt-value-test", "%s") + .setHeader("slash-value-test", "\\") + .setBody("' \" ` $( #{ %( %{ {{ \\0 %s \\") + .execute() + .toCompletableFuture() + .thenAccept(System.out::println) + .join(); + +client.close(); \ No newline at end of file diff --git a/test/fixtures/output/java/asynchttp/unparseable-query.java b/test/fixtures/output/java/asynchttp/unparseable-query.java new file mode 100644 index 0000000..c6a63b3 --- /dev/null +++ b/test/fixtures/output/java/asynchttp/unparseable-query.java @@ -0,0 +1,8 @@ +AsyncHttpClient client = new DefaultAsyncHttpClient(); +client.prepare("GET", "http://mockbin.com/har?&&a=b&&") + .execute() + .toCompletableFuture() + .thenAccept(System.out::println) + .join(); + +client.close(); \ No newline at end of file diff --git a/test/fixtures/output/java/nethttp/compression.java b/test/fixtures/output/java/nethttp/compression.java new file mode 100644 index 0000000..569ab05 --- /dev/null +++ b/test/fixtures/output/java/nethttp/compression.java @@ -0,0 +1,7 @@ +HttpRequest request = HttpRequest.newBuilder() + .uri(URI.create("http://mockbin.com/har")) + .header("accept-encoding", "deflate, gzip, br") + .method("GET", HttpRequest.BodyPublishers.noBody()) + .build(); +HttpResponse response = HttpClient.newHttpClient().send(request, HttpResponse.BodyHandlers.ofString()); +System.out.println(response.body()); \ No newline at end of file diff --git a/test/fixtures/output/java/nethttp/headers.java b/test/fixtures/output/java/nethttp/headers.java index 2e8a09f..db666ed 100644 --- a/test/fixtures/output/java/nethttp/headers.java +++ b/test/fixtures/output/java/nethttp/headers.java @@ -2,6 +2,7 @@ .uri(URI.create("http://mockbin.com/har")) .header("accept", "application/json") .header("x-foo", "Bar") + .header("quoted-value", "\"quoted\" 'string'") .method("GET", HttpRequest.BodyPublishers.noBody()) .build(); HttpResponse response = HttpClient.newHttpClient().send(request, HttpResponse.BodyHandlers.ofString()); diff --git a/test/fixtures/output/java/nethttp/malicious.java b/test/fixtures/output/java/nethttp/malicious.java new file mode 100644 index 0000000..e227616 --- /dev/null +++ b/test/fixtures/output/java/nethttp/malicious.java @@ -0,0 +1,22 @@ +HttpRequest request = HttpRequest.newBuilder() + .uri(URI.create("http://example.test/%27%22%60$(%(%%7B%7B%7B/0%s//?'=squote-key-test&squote-value-test='&%22=dquote-key-test&dquote-value-test=%22&%60=backtick-key-test&backtick-value-test=%60&%24(=dollar-parenthesis-key-test&dollar-parenthesis-value-test=%24(&%23%7B=hash-brace-key-test&hash-brace-value-test=%23%7B&%25(=percent-parenthesis-key-test&percent-parenthesis-value-test=%25(&%25%7B=percent-brace-key-test&percent-brace-value-test=%25%7B&%7B%7B=double-brace-key-test&double-brace-value-test=%7B%7B&%5C0=null-key-test&null-value-test=%5C0&%25s=string-fmt-key-test&string-fmt-value-test=%25s&%5C=slash-key-test&slash-value-test=%5C")) + .header("'", "squote-key-test") + .header("squote-value-test", "'") + .header("dquote-value-test", "\"") + .header("`", "backtick-key-test") + .header("backtick-value-test", "`") + .header("$", "dollar-key-test") + .header("dollar-parenthesis-value-test", "$(") + .header("#", "hash-key-test") + .header("hash-brace-value-test", "#{") + .header("%", "percent-key-test") + .header("percent-parenthesis-value-test", "%(") + .header("percent-brace-value-test", "%{") + .header("double-brace-value-test", "{{") + .header("null-value-test", "\\0") + .header("string-fmt-value-test", "%s") + .header("slash-value-test", "\\") + .method("POST", HttpRequest.BodyPublishers.ofString("' \" ` $( #{ %( %{ {{ \\0 %s \\")) + .build(); +HttpResponse response = HttpClient.newHttpClient().send(request, HttpResponse.BodyHandlers.ofString()); +System.out.println(response.body()); \ No newline at end of file diff --git a/test/fixtures/output/java/nethttp/unparseable-query.java b/test/fixtures/output/java/nethttp/unparseable-query.java new file mode 100644 index 0000000..9df4b62 --- /dev/null +++ b/test/fixtures/output/java/nethttp/unparseable-query.java @@ -0,0 +1,6 @@ +HttpRequest request = HttpRequest.newBuilder() + .uri(URI.create("http://mockbin.com/har?&&a=b&&")) + .method("GET", HttpRequest.BodyPublishers.noBody()) + .build(); +HttpResponse response = HttpClient.newHttpClient().send(request, HttpResponse.BodyHandlers.ofString()); +System.out.println(response.body()); \ No newline at end of file diff --git a/test/fixtures/output/java/okhttp/compression.java b/test/fixtures/output/java/okhttp/compression.java new file mode 100644 index 0000000..2503e18 --- /dev/null +++ b/test/fixtures/output/java/okhttp/compression.java @@ -0,0 +1,9 @@ +OkHttpClient client = new OkHttpClient(); + +Request request = new Request.Builder() + .url("http://mockbin.com/har") + .get() + .addHeader("accept-encoding", "deflate, gzip, br") + .build(); + +Response response = client.newCall(request).execute(); \ No newline at end of file diff --git a/test/fixtures/output/java/okhttp/headers.java b/test/fixtures/output/java/okhttp/headers.java index 081a33a..c2182bd 100644 --- a/test/fixtures/output/java/okhttp/headers.java +++ b/test/fixtures/output/java/okhttp/headers.java @@ -5,6 +5,7 @@ .get() .addHeader("accept", "application/json") .addHeader("x-foo", "Bar") + .addHeader("quoted-value", "\"quoted\" 'string'") .build(); Response response = client.newCall(request).execute(); diff --git a/test/fixtures/output/java/okhttp/malicious.java b/test/fixtures/output/java/okhttp/malicious.java new file mode 100644 index 0000000..008bb7c --- /dev/null +++ b/test/fixtures/output/java/okhttp/malicious.java @@ -0,0 +1,26 @@ +OkHttpClient client = new OkHttpClient(); + +MediaType mediaType = MediaType.parse("text/plain"); +RequestBody body = RequestBody.create(mediaType, "' \" ` $( #{ %( %{ {{ \\0 %s \\"); +Request request = new Request.Builder() + .url("http://example.test/%27%22%60$(%(%%7B%7B%7B/0%s//?'=squote-key-test&squote-value-test='&%22=dquote-key-test&dquote-value-test=%22&%60=backtick-key-test&backtick-value-test=%60&%24(=dollar-parenthesis-key-test&dollar-parenthesis-value-test=%24(&%23%7B=hash-brace-key-test&hash-brace-value-test=%23%7B&%25(=percent-parenthesis-key-test&percent-parenthesis-value-test=%25(&%25%7B=percent-brace-key-test&percent-brace-value-test=%25%7B&%7B%7B=double-brace-key-test&double-brace-value-test=%7B%7B&%5C0=null-key-test&null-value-test=%5C0&%25s=string-fmt-key-test&string-fmt-value-test=%25s&%5C=slash-key-test&slash-value-test=%5C") + .post(body) + .addHeader("'", "squote-key-test") + .addHeader("squote-value-test", "'") + .addHeader("dquote-value-test", "\"") + .addHeader("`", "backtick-key-test") + .addHeader("backtick-value-test", "`") + .addHeader("$", "dollar-key-test") + .addHeader("dollar-parenthesis-value-test", "$(") + .addHeader("#", "hash-key-test") + .addHeader("hash-brace-value-test", "#{") + .addHeader("%", "percent-key-test") + .addHeader("percent-parenthesis-value-test", "%(") + .addHeader("percent-brace-value-test", "%{") + .addHeader("double-brace-value-test", "{{") + .addHeader("null-value-test", "\\0") + .addHeader("string-fmt-value-test", "%s") + .addHeader("slash-value-test", "\\") + .build(); + +Response response = client.newCall(request).execute(); \ No newline at end of file diff --git a/test/fixtures/output/java/okhttp/unparseable-query.java b/test/fixtures/output/java/okhttp/unparseable-query.java new file mode 100644 index 0000000..b08a7d6 --- /dev/null +++ b/test/fixtures/output/java/okhttp/unparseable-query.java @@ -0,0 +1,8 @@ +OkHttpClient client = new OkHttpClient(); + +Request request = new Request.Builder() + .url("http://mockbin.com/har?&&a=b&&") + .get() + .build(); + +Response response = client.newCall(request).execute(); \ No newline at end of file diff --git a/test/fixtures/output/java/restclient/application-form-encoded.java b/test/fixtures/output/java/restclient/application-form-encoded.java new file mode 100644 index 0000000..63b17ff --- /dev/null +++ b/test/fixtures/output/java/restclient/application-form-encoded.java @@ -0,0 +1,13 @@ +RestClient restClient = RestClient.create(); + +MultiValueMap formDataMap = new LinkedMultiValueMap<>(); +formDataMap.add("foo", "bar"); +formDataMap.add("hello", "world"); + +ResponseEntity response = restClient + .method(HttpMethod.POST) + .uri("http://mockbin.com/har") + .contentType(MediaType.APPLICATION_FORM_URLENCODED) + .body(formDataMap) + .retrieve() + .toEntity(String.class); diff --git a/test/fixtures/output/java/restclient/application-json.java b/test/fixtures/output/java/restclient/application-json.java new file mode 100644 index 0000000..5d12031 --- /dev/null +++ b/test/fixtures/output/java/restclient/application-json.java @@ -0,0 +1,9 @@ +RestClient restClient = RestClient.create(); + +ResponseEntity response = restClient + .method(HttpMethod.POST) + .uri("http://mockbin.com/har") + .contentType(MediaType.APPLICATION_JSON) + .body("{\"number\":1,\"string\":\"f\\\"oo\",\"arr\":[1,2,3],\"nested\":{\"a\":\"b\"},\"arr_mix\":[1,\"a\",{\"arr_mix_nested\":{}}],\"boolean\":false}") + .retrieve() + .toEntity(String.class); diff --git a/test/fixtures/output/java/restclient/compression.java b/test/fixtures/output/java/restclient/compression.java new file mode 100644 index 0000000..056a80b --- /dev/null +++ b/test/fixtures/output/java/restclient/compression.java @@ -0,0 +1,8 @@ +RestClient restClient = RestClient.create(); + +ResponseEntity response = restClient + .method(HttpMethod.GET) + .uri("http://mockbin.com/har") + .header("accept-encoding", "deflate, gzip, br") + .retrieve() + .toEntity(String.class); \ No newline at end of file diff --git a/test/fixtures/output/java/restclient/cookies.java b/test/fixtures/output/java/restclient/cookies.java new file mode 100644 index 0000000..624d1fd --- /dev/null +++ b/test/fixtures/output/java/restclient/cookies.java @@ -0,0 +1,9 @@ +RestClient restClient = RestClient.create(); + +ResponseEntity response = restClient + .method(HttpMethod.POST) + .uri("http://mockbin.com/har") + .cookie("foo", "bar") + .cookie("bar", "baz") + .retrieve() + .toEntity(String.class); diff --git a/test/fixtures/output/java/restclient/custom-method.java b/test/fixtures/output/java/restclient/custom-method.java new file mode 100644 index 0000000..70eafc5 --- /dev/null +++ b/test/fixtures/output/java/restclient/custom-method.java @@ -0,0 +1,7 @@ +RestClient restClient = RestClient.create(); + +ResponseEntity response = restClient + .method(HttpMethod.valueOf("PROPFIND")) + .uri("http://mockbin.com/har") + .retrieve() + .toEntity(String.class); diff --git a/test/fixtures/output/java/restclient/full.java b/test/fixtures/output/java/restclient/full.java new file mode 100644 index 0000000..8126f6d --- /dev/null +++ b/test/fixtures/output/java/restclient/full.java @@ -0,0 +1,21 @@ +RestClient restClient = RestClient.create(); + +MultiValueMap formDataMap = new LinkedMultiValueMap<>(); +formDataMap.add("foo", "bar"); + +ResponseEntity response = restClient + .method(HttpMethod.POST) + .uri("http://mockbin.com/har", uriBuilder -> { + uriBuilder.queryParam("foo", "bar"); + uriBuilder.queryParam("foo", "baz"); + uriBuilder.queryParam("baz", "abc"); + uriBuilder.queryParam("key", "value"); + return uriBuilder.build(); + }) + .cookie("foo", "bar") + .cookie("bar", "baz") + .header("accept", "application/json") + .contentType(MediaType.APPLICATION_FORM_URLENCODED) + .body(formDataMap) + .retrieve() + .toEntity(String.class); diff --git a/test/fixtures/output/java/restclient/headers.java b/test/fixtures/output/java/restclient/headers.java new file mode 100644 index 0000000..229d844 --- /dev/null +++ b/test/fixtures/output/java/restclient/headers.java @@ -0,0 +1,10 @@ +RestClient restClient = RestClient.create(); + +ResponseEntity response = restClient + .method(HttpMethod.GET) + .uri("http://mockbin.com/har") + .header("accept", "application/json") + .header("x-foo", "Bar") + .header("quoted-value", "\"quoted\" 'string'") + .retrieve() + .toEntity(String.class); \ No newline at end of file diff --git a/test/fixtures/output/java/restclient/https.java b/test/fixtures/output/java/restclient/https.java new file mode 100644 index 0000000..0946263 --- /dev/null +++ b/test/fixtures/output/java/restclient/https.java @@ -0,0 +1,7 @@ +RestClient restClient = RestClient.create(); + +ResponseEntity response = restClient + .method(HttpMethod.GET) + .uri("https://mockbin.com/har") + .retrieve() + .toEntity(String.class); \ No newline at end of file diff --git a/test/fixtures/output/java/restclient/jsonObj-multiline.java b/test/fixtures/output/java/restclient/jsonObj-multiline.java new file mode 100644 index 0000000..71a2fbe --- /dev/null +++ b/test/fixtures/output/java/restclient/jsonObj-multiline.java @@ -0,0 +1,9 @@ +RestClient restClient = RestClient.create(); + +ResponseEntity response = restClient + .method(HttpMethod.POST) + .uri("http://mockbin.com/har") + .contentType(MediaType.APPLICATION_JSON) + .body("{\n \"foo\": \"bar\"\n}") + .retrieve() + .toEntity(String.class); diff --git a/test/fixtures/output/java/restclient/jsonObj-null-value.java b/test/fixtures/output/java/restclient/jsonObj-null-value.java new file mode 100644 index 0000000..8b3f17b --- /dev/null +++ b/test/fixtures/output/java/restclient/jsonObj-null-value.java @@ -0,0 +1,9 @@ +RestClient restClient = RestClient.create(); + +ResponseEntity response = restClient + .method(HttpMethod.POST) + .uri("http://mockbin.com/har") + .contentType(MediaType.APPLICATION_JSON) + .body("{\"foo\":null}") + .retrieve() + .toEntity(String.class); diff --git a/test/fixtures/output/java/restclient/malicious.java b/test/fixtures/output/java/restclient/malicious.java new file mode 100644 index 0000000..9919ca1 --- /dev/null +++ b/test/fixtures/output/java/restclient/malicious.java @@ -0,0 +1,49 @@ +RestClient restClient = RestClient.create(); + +ResponseEntity response = restClient + .method(HttpMethod.POST) + .uri("http://example.test/%27%22%60$(%(%%7B%7B%7B/0%s//", uriBuilder -> { + uriBuilder.queryParam("'", "squote-key-test"); + uriBuilder.queryParam("squote-value-test", "'"); + uriBuilder.queryParam("\"", "dquote-key-test"); + uriBuilder.queryParam("dquote-value-test", "\""); + uriBuilder.queryParam("`", "backtick-key-test"); + uriBuilder.queryParam("backtick-value-test", "`"); + uriBuilder.queryParam("$(", "dollar-parenthesis-key-test"); + uriBuilder.queryParam("dollar-parenthesis-value-test", "$("); + uriBuilder.queryParam("#{", "hash-brace-key-test"); + uriBuilder.queryParam("hash-brace-value-test", "#{"); + uriBuilder.queryParam("%(", "percent-parenthesis-key-test"); + uriBuilder.queryParam("percent-parenthesis-value-test", "%("); + uriBuilder.queryParam("%{", "percent-brace-key-test"); + uriBuilder.queryParam("percent-brace-value-test", "%{"); + uriBuilder.queryParam("{{", "double-brace-key-test"); + uriBuilder.queryParam("double-brace-value-test", "{{"); + uriBuilder.queryParam("\\0", "null-key-test"); + uriBuilder.queryParam("null-value-test", "\\0"); + uriBuilder.queryParam("%s", "string-fmt-key-test"); + uriBuilder.queryParam("string-fmt-value-test", "%s"); + uriBuilder.queryParam("\\", "slash-key-test"); + uriBuilder.queryParam("slash-value-test", "\\"); + return uriBuilder.build(); + }) + .header("'", "squote-key-test") + .header("squote-value-test", "'") + .header("dquote-value-test", "\"") + .header("`", "backtick-key-test") + .header("backtick-value-test", "`") + .header("$", "dollar-key-test") + .header("dollar-parenthesis-value-test", "$(") + .header("#", "hash-key-test") + .header("hash-brace-value-test", "#{") + .header("%", "percent-key-test") + .header("percent-parenthesis-value-test", "%(") + .header("percent-brace-value-test", "%{") + .header("double-brace-value-test", "{{") + .header("null-value-test", "\\0") + .header("string-fmt-value-test", "%s") + .header("slash-value-test", "\\") + .contentType(MediaType.TEXT_PLAIN) + .body("' \" ` $( #{ %( %{ {{ \\0 %s \\") + .retrieve() + .toEntity(String.class); diff --git a/test/fixtures/output/java/restclient/multipart-data.java b/test/fixtures/output/java/restclient/multipart-data.java new file mode 100644 index 0000000..ef5d723 --- /dev/null +++ b/test/fixtures/output/java/restclient/multipart-data.java @@ -0,0 +1,14 @@ +RestClient restClient = RestClient.create(); + +MultipartBodyBuilder multipartBuilder = new MultipartBodyBuilder(); +multipartBuilder.part("foo", "Hello World") + .filename("hello.txt") + .contentType(MediaType.TEXT_PLAIN); + +ResponseEntity response = restClient + .method(HttpMethod.POST) + .uri("http://mockbin.com/har") + .contentType(MediaType.MULTIPART_FORM_DATA) + .body(multipartBuilder.build()) + .retrieve() + .toEntity(String.class); diff --git a/test/fixtures/output/java/restclient/multipart-file.java b/test/fixtures/output/java/restclient/multipart-file.java new file mode 100644 index 0000000..1144288 --- /dev/null +++ b/test/fixtures/output/java/restclient/multipart-file.java @@ -0,0 +1,13 @@ +RestClient restClient = RestClient.create(); + +MultipartBodyBuilder multipartBuilder = new MultipartBodyBuilder(); +multipartBuilder.part("foo", new FileSystemResource("test/fixtures/files/hello.txt")) + .contentType(MediaType.TEXT_PLAIN); + +ResponseEntity response = restClient + .method(HttpMethod.POST) + .uri("http://mockbin.com/har") + .contentType(MediaType.MULTIPART_FORM_DATA) + .body(multipartBuilder.build()) + .retrieve() + .toEntity(String.class); diff --git a/test/fixtures/output/java/restclient/multipart-form-data.java b/test/fixtures/output/java/restclient/multipart-form-data.java new file mode 100644 index 0000000..604d426 --- /dev/null +++ b/test/fixtures/output/java/restclient/multipart-form-data.java @@ -0,0 +1,12 @@ +RestClient restClient = RestClient.create(); + +MultipartBodyBuilder multipartBuilder = new MultipartBodyBuilder(); +multipartBuilder.part("foo", "bar"); + +ResponseEntity response = restClient + .method(HttpMethod.POST) + .uri("http://mockbin.com/har") + .contentType(MediaType.MULTIPART_FORM_DATA) + .body(multipartBuilder.build()) + .retrieve() + .toEntity(String.class); diff --git a/test/fixtures/output/java/restclient/nested.java b/test/fixtures/output/java/restclient/nested.java new file mode 100644 index 0000000..53b6846 --- /dev/null +++ b/test/fixtures/output/java/restclient/nested.java @@ -0,0 +1,12 @@ +RestClient restClient = RestClient.create(); + +ResponseEntity response = restClient + .method(HttpMethod.GET) + .uri("http://mockbin.com/har", uriBuilder -> { + uriBuilder.queryParam("foo[bar]", "baz,zap"); + uriBuilder.queryParam("fiz", "buz"); + uriBuilder.queryParam("key", "value"); + return uriBuilder.build(); + }) + .retrieve() + .toEntity(String.class); diff --git a/test/fixtures/output/java/restclient/query.java b/test/fixtures/output/java/restclient/query.java new file mode 100644 index 0000000..7979608 --- /dev/null +++ b/test/fixtures/output/java/restclient/query.java @@ -0,0 +1,13 @@ +RestClient restClient = RestClient.create(); + +ResponseEntity response = restClient + .method(HttpMethod.GET) + .uri("http://mockbin.com/har", uriBuilder -> { + uriBuilder.queryParam("foo", "bar"); + uriBuilder.queryParam("foo", "baz"); + uriBuilder.queryParam("baz", "abc"); + uriBuilder.queryParam("key", "value"); + return uriBuilder.build(); + }) + .retrieve() + .toEntity(String.class); diff --git a/test/fixtures/output/java/restclient/short.java b/test/fixtures/output/java/restclient/short.java new file mode 100644 index 0000000..b100f40 --- /dev/null +++ b/test/fixtures/output/java/restclient/short.java @@ -0,0 +1,7 @@ +RestClient restClient = RestClient.create(); + +ResponseEntity response = restClient + .method(HttpMethod.GET) + .uri("http://mockbin.com/har") + .retrieve() + .toEntity(String.class); \ No newline at end of file diff --git a/test/fixtures/output/java/restclient/text-plain.java b/test/fixtures/output/java/restclient/text-plain.java new file mode 100644 index 0000000..8aef2bf --- /dev/null +++ b/test/fixtures/output/java/restclient/text-plain.java @@ -0,0 +1,9 @@ +RestClient restClient = RestClient.create(); + +ResponseEntity response = restClient + .method(HttpMethod.POST) + .uri("http://mockbin.com/har") + .contentType(MediaType.TEXT_PLAIN) + .body("Hello World") + .retrieve() + .toEntity(String.class); diff --git a/test/fixtures/output/java/restclient/unparseable-query.java b/test/fixtures/output/java/restclient/unparseable-query.java new file mode 100644 index 0000000..6d64f6c --- /dev/null +++ b/test/fixtures/output/java/restclient/unparseable-query.java @@ -0,0 +1,7 @@ +RestClient restClient = RestClient.create(); + +ResponseEntity response = restClient + .method(HttpMethod.GET) + .uri("http://mockbin.com/har?&&a=b&&") + .retrieve() + .toEntity(String.class); \ No newline at end of file diff --git a/test/fixtures/output/java/unirest/compression.java b/test/fixtures/output/java/unirest/compression.java new file mode 100644 index 0000000..d006f9e --- /dev/null +++ b/test/fixtures/output/java/unirest/compression.java @@ -0,0 +1,3 @@ +HttpResponse response = Unirest.get("http://mockbin.com/har") + .header("accept-encoding", "deflate, gzip, br") + .asString(); \ No newline at end of file diff --git a/test/fixtures/output/java/unirest/headers.java b/test/fixtures/output/java/unirest/headers.java index 142cf4e..6ab80f8 100644 --- a/test/fixtures/output/java/unirest/headers.java +++ b/test/fixtures/output/java/unirest/headers.java @@ -1,4 +1,5 @@ HttpResponse response = Unirest.get("http://mockbin.com/har") .header("accept", "application/json") .header("x-foo", "Bar") + .header("quoted-value", "\"quoted\" 'string'") .asString(); diff --git a/test/fixtures/output/java/unirest/malicious.java b/test/fixtures/output/java/unirest/malicious.java new file mode 100644 index 0000000..85f1906 --- /dev/null +++ b/test/fixtures/output/java/unirest/malicious.java @@ -0,0 +1,19 @@ +HttpResponse response = Unirest.post("http://example.test/%27%22%60$(%(%%7B%7B%7B/0%s//?'=squote-key-test&squote-value-test='&%22=dquote-key-test&dquote-value-test=%22&%60=backtick-key-test&backtick-value-test=%60&%24(=dollar-parenthesis-key-test&dollar-parenthesis-value-test=%24(&%23%7B=hash-brace-key-test&hash-brace-value-test=%23%7B&%25(=percent-parenthesis-key-test&percent-parenthesis-value-test=%25(&%25%7B=percent-brace-key-test&percent-brace-value-test=%25%7B&%7B%7B=double-brace-key-test&double-brace-value-test=%7B%7B&%5C0=null-key-test&null-value-test=%5C0&%25s=string-fmt-key-test&string-fmt-value-test=%25s&%5C=slash-key-test&slash-value-test=%5C") + .header("'", "squote-key-test") + .header("squote-value-test", "'") + .header("dquote-value-test", "\"") + .header("`", "backtick-key-test") + .header("backtick-value-test", "`") + .header("$", "dollar-key-test") + .header("dollar-parenthesis-value-test", "$(") + .header("#", "hash-key-test") + .header("hash-brace-value-test", "#{") + .header("%", "percent-key-test") + .header("percent-parenthesis-value-test", "%(") + .header("percent-brace-value-test", "%{") + .header("double-brace-value-test", "{{") + .header("null-value-test", "\\0") + .header("string-fmt-value-test", "%s") + .header("slash-value-test", "\\") + .body("' \" ` $( #{ %( %{ {{ \\0 %s \\") + .asString(); \ No newline at end of file diff --git a/test/fixtures/output/java/unirest/unparseable-query.java b/test/fixtures/output/java/unirest/unparseable-query.java new file mode 100644 index 0000000..21aad1f --- /dev/null +++ b/test/fixtures/output/java/unirest/unparseable-query.java @@ -0,0 +1,2 @@ +HttpResponse response = Unirest.get("http://mockbin.com/har?&&a=b&&") + .asString(); \ No newline at end of file diff --git a/test/fixtures/output/javascript/axios/compression.js b/test/fixtures/output/javascript/axios/compression.js new file mode 100644 index 0000000..02f2a93 --- /dev/null +++ b/test/fixtures/output/javascript/axios/compression.js @@ -0,0 +1,13 @@ +import axios from "axios"; + +const options = { + method: 'GET', + url: 'http://mockbin.com/har', + headers: {'accept-encoding': 'deflate, gzip, br'} +}; + +axios.request(options).then(function (response) { + console.log(response.data); +}).catch(function (error) { + console.error(error); +}); \ No newline at end of file diff --git a/test/fixtures/output/javascript/axios/headers.js b/test/fixtures/output/javascript/axios/headers.js index 1db8b5b..3270a35 100644 --- a/test/fixtures/output/javascript/axios/headers.js +++ b/test/fixtures/output/javascript/axios/headers.js @@ -3,7 +3,11 @@ import axios from "axios"; const options = { method: 'GET', url: 'http://mockbin.com/har', - headers: {accept: 'application/json', 'x-foo': 'Bar'} + headers: { + accept: 'application/json', + 'x-foo': 'Bar', + 'quoted-value': '"quoted" \'string\'' + } }; axios.request(options).then(function (response) { diff --git a/test/fixtures/output/javascript/axios/malicious.js b/test/fixtures/output/javascript/axios/malicious.js new file mode 100644 index 0000000..c0435b0 --- /dev/null +++ b/test/fixtures/output/javascript/axios/malicious.js @@ -0,0 +1,55 @@ +import axios from "axios"; + +const options = { + method: 'POST', + url: 'http://example.test/%27%22%60$(%(%%7B%7B%7B/0%s//', + params: { + '\'': 'squote-key-test', + 'squote-value-test': '\'', + '"': 'dquote-key-test', + 'dquote-value-test': '"', + '`': 'backtick-key-test', + 'backtick-value-test': '`', + '$(': 'dollar-parenthesis-key-test', + 'dollar-parenthesis-value-test': '$(', + '#{': 'hash-brace-key-test', + 'hash-brace-value-test': '#{', + '%(': 'percent-parenthesis-key-test', + 'percent-parenthesis-value-test': '%(', + '%{': 'percent-brace-key-test', + 'percent-brace-value-test': '%{', + '{{': 'double-brace-key-test', + 'double-brace-value-test': '{{', + '\\0': 'null-key-test', + 'null-value-test': '\\0', + '%s': 'string-fmt-key-test', + 'string-fmt-value-test': '%s', + '\\': 'slash-key-test', + 'slash-value-test': '\\' + }, + headers: { + '\'': 'squote-key-test', + 'squote-value-test': '\'', + 'dquote-value-test': '"', + '`': 'backtick-key-test', + 'backtick-value-test': '`', + $: 'dollar-key-test', + 'dollar-parenthesis-value-test': '$(', + '#': 'hash-key-test', + 'hash-brace-value-test': '#{', + '%': 'percent-key-test', + 'percent-parenthesis-value-test': '%(', + 'percent-brace-value-test': '%{', + 'double-brace-value-test': '{{', + 'null-value-test': '\\0', + 'string-fmt-value-test': '%s', + 'slash-value-test': '\\' + }, + data: '\' " ` $( #{ %( %{ {{ \\0 %s \\' +}; + +axios.request(options).then(function (response) { + console.log(response.data); +}).catch(function (error) { + console.error(error); +}); \ No newline at end of file diff --git a/test/fixtures/output/javascript/axios/unparseable-query.js b/test/fixtures/output/javascript/axios/unparseable-query.js new file mode 100644 index 0000000..a74bf9f --- /dev/null +++ b/test/fixtures/output/javascript/axios/unparseable-query.js @@ -0,0 +1,9 @@ +import axios from "axios"; + +const options = {method: 'GET', url: 'http://mockbin.com/har?&&a=b&&'}; + +axios.request(options).then(function (response) { + console.log(response.data); +}).catch(function (error) { + console.error(error); +}); \ No newline at end of file diff --git a/test/fixtures/output/javascript/fetch/application-form-encoded.js b/test/fixtures/output/javascript/fetch/application-form-encoded.js index 186c1db..a710c45 100644 --- a/test/fixtures/output/javascript/fetch/application-form-encoded.js +++ b/test/fixtures/output/javascript/fetch/application-form-encoded.js @@ -1,7 +1,7 @@ const options = { method: 'POST', headers: {'content-type': 'application/x-www-form-urlencoded'}, - body: {foo: 'bar', hello: 'world'} + body: new URLSearchParams({foo: 'bar', hello: 'world'}) }; fetch('http://mockbin.com/har', options) diff --git a/test/fixtures/output/javascript/fetch/application-json.js b/test/fixtures/output/javascript/fetch/application-json.js index 7aeb551..d1ef8ff 100644 --- a/test/fixtures/output/javascript/fetch/application-json.js +++ b/test/fixtures/output/javascript/fetch/application-json.js @@ -1,7 +1,7 @@ const options = { method: 'POST', headers: {'content-type': 'application/json'}, - body: '{"number":1,"string":"f\"oo","arr":[1,2,3],"nested":{"a":"b"},"arr_mix":[1,"a",{"arr_mix_nested":{}}],"boolean":false}' + body: '{"number":1,"string":"f\\"oo","arr":[1,2,3],"nested":{"a":"b"},"arr_mix":[1,"a",{"arr_mix_nested":{}}],"boolean":false}' }; fetch('http://mockbin.com/har', options) diff --git a/test/fixtures/output/javascript/fetch/compression.js b/test/fixtures/output/javascript/fetch/compression.js new file mode 100644 index 0000000..4215429 --- /dev/null +++ b/test/fixtures/output/javascript/fetch/compression.js @@ -0,0 +1,6 @@ +const options = {method: 'GET', headers: {'accept-encoding': 'deflate, gzip, br'}}; + +fetch('http://mockbin.com/har', options) + .then(response => response.json()) + .then(response => console.log(response)) + .catch(err => console.error(err)); \ No newline at end of file diff --git a/test/fixtures/output/javascript/fetch/full.js b/test/fixtures/output/javascript/fetch/full.js index 4c7d08f..99298d4 100644 --- a/test/fixtures/output/javascript/fetch/full.js +++ b/test/fixtures/output/javascript/fetch/full.js @@ -5,7 +5,7 @@ const options = { accept: 'application/json', 'content-type': 'application/x-www-form-urlencoded' }, - body: {foo: 'bar'} + body: new URLSearchParams({foo: 'bar'}) }; fetch('http://mockbin.com/har?foo=bar&foo=baz&baz=abc&key=value', options) diff --git a/test/fixtures/output/javascript/fetch/headers.js b/test/fixtures/output/javascript/fetch/headers.js index 583e54c..7948289 100644 --- a/test/fixtures/output/javascript/fetch/headers.js +++ b/test/fixtures/output/javascript/fetch/headers.js @@ -1,4 +1,11 @@ -const options = {method: 'GET', headers: {accept: 'application/json', 'x-foo': 'Bar'}}; +const options = { + method: 'GET', + headers: { + accept: 'application/json', + 'x-foo': 'Bar', + 'quoted-value': '"quoted" \'string\'' + } +}; fetch('http://mockbin.com/har', options) .then(response => response.json()) diff --git a/test/fixtures/output/javascript/fetch/malicious.js b/test/fixtures/output/javascript/fetch/malicious.js new file mode 100644 index 0000000..4fd3ce1 --- /dev/null +++ b/test/fixtures/output/javascript/fetch/malicious.js @@ -0,0 +1,27 @@ +const options = { + method: 'POST', + headers: { + '\'': 'squote-key-test', + 'squote-value-test': '\'', + 'dquote-value-test': '"', + '`': 'backtick-key-test', + 'backtick-value-test': '`', + $: 'dollar-key-test', + 'dollar-parenthesis-value-test': '$(', + '#': 'hash-key-test', + 'hash-brace-value-test': '#{', + '%': 'percent-key-test', + 'percent-parenthesis-value-test': '%(', + 'percent-brace-value-test': '%{', + 'double-brace-value-test': '{{', + 'null-value-test': '\\0', + 'string-fmt-value-test': '%s', + 'slash-value-test': '\\' + }, + body: '\' " ` $( #{ %( %{ {{ \\0 %s \\' +}; + +fetch('http://example.test/%27%22%60$(%(%%7B%7B%7B/0%s//?\'=squote-key-test&squote-value-test=\'&%22=dquote-key-test&dquote-value-test=%22&%60=backtick-key-test&backtick-value-test=%60&%24(=dollar-parenthesis-key-test&dollar-parenthesis-value-test=%24(&%23%7B=hash-brace-key-test&hash-brace-value-test=%23%7B&%25(=percent-parenthesis-key-test&percent-parenthesis-value-test=%25(&%25%7B=percent-brace-key-test&percent-brace-value-test=%25%7B&%7B%7B=double-brace-key-test&double-brace-value-test=%7B%7B&%5C0=null-key-test&null-value-test=%5C0&%25s=string-fmt-key-test&string-fmt-value-test=%25s&%5C=slash-key-test&slash-value-test=%5C', options) + .then(response => response.json()) + .then(response => console.log(response)) + .catch(err => console.error(err)); \ No newline at end of file diff --git a/test/fixtures/output/javascript/fetch/unparseable-query.js b/test/fixtures/output/javascript/fetch/unparseable-query.js new file mode 100644 index 0000000..5e0d126 --- /dev/null +++ b/test/fixtures/output/javascript/fetch/unparseable-query.js @@ -0,0 +1,6 @@ +const options = {method: 'GET'}; + +fetch('http://mockbin.com/har?&&a=b&&', options) + .then(response => response.json()) + .then(response => console.log(response)) + .catch(err => console.error(err)); \ No newline at end of file diff --git a/test/fixtures/output/javascript/jquery/compression.js b/test/fixtures/output/javascript/jquery/compression.js new file mode 100644 index 0000000..6d60dd9 --- /dev/null +++ b/test/fixtures/output/javascript/jquery/compression.js @@ -0,0 +1,13 @@ +const settings = { + "async": true, + "crossDomain": true, + "url": "http://mockbin.com/har", + "method": "GET", + "headers": { + "accept-encoding": "deflate, gzip, br" + } +}; + +$.ajax(settings).done(function (response) { + console.log(response); +}); \ No newline at end of file diff --git a/test/fixtures/output/javascript/jquery/headers.js b/test/fixtures/output/javascript/jquery/headers.js index 17652fa..fd6840a 100644 --- a/test/fixtures/output/javascript/jquery/headers.js +++ b/test/fixtures/output/javascript/jquery/headers.js @@ -5,7 +5,8 @@ const settings = { "method": "GET", "headers": { "accept": "application/json", - "x-foo": "Bar" + "x-foo": "Bar", + "quoted-value": "\"quoted\" 'string'" } }; diff --git a/test/fixtures/output/javascript/jquery/malicious.js b/test/fixtures/output/javascript/jquery/malicious.js new file mode 100644 index 0000000..b6ccbb6 --- /dev/null +++ b/test/fixtures/output/javascript/jquery/malicious.js @@ -0,0 +1,29 @@ +const settings = { + "async": true, + "crossDomain": true, + "url": "http://example.test/%27%22%60$(%(%%7B%7B%7B/0%s//?'=squote-key-test&squote-value-test='&%22=dquote-key-test&dquote-value-test=%22&%60=backtick-key-test&backtick-value-test=%60&%24(=dollar-parenthesis-key-test&dollar-parenthesis-value-test=%24(&%23%7B=hash-brace-key-test&hash-brace-value-test=%23%7B&%25(=percent-parenthesis-key-test&percent-parenthesis-value-test=%25(&%25%7B=percent-brace-key-test&percent-brace-value-test=%25%7B&%7B%7B=double-brace-key-test&double-brace-value-test=%7B%7B&%5C0=null-key-test&null-value-test=%5C0&%25s=string-fmt-key-test&string-fmt-value-test=%25s&%5C=slash-key-test&slash-value-test=%5C", + "method": "POST", + "headers": { + "'": "squote-key-test", + "squote-value-test": "'", + "dquote-value-test": "\"", + "`": "backtick-key-test", + "backtick-value-test": "`", + "$": "dollar-key-test", + "dollar-parenthesis-value-test": "$(", + "#": "hash-key-test", + "hash-brace-value-test": "#{", + "%": "percent-key-test", + "percent-parenthesis-value-test": "%(", + "percent-brace-value-test": "%{", + "double-brace-value-test": "{{", + "null-value-test": "\\0", + "string-fmt-value-test": "%s", + "slash-value-test": "\\" + }, + "data": "' \" ` $( #{ %( %{ {{ \\0 %s \\" +}; + +$.ajax(settings).done(function (response) { + console.log(response); +}); \ No newline at end of file diff --git a/test/fixtures/output/javascript/jquery/unparseable-query.js b/test/fixtures/output/javascript/jquery/unparseable-query.js new file mode 100644 index 0000000..3a59c9e --- /dev/null +++ b/test/fixtures/output/javascript/jquery/unparseable-query.js @@ -0,0 +1,11 @@ +const settings = { + "async": true, + "crossDomain": true, + "url": "http://mockbin.com/har?&&a=b&&", + "method": "GET", + "headers": {} +}; + +$.ajax(settings).done(function (response) { + console.log(response); +}); \ No newline at end of file diff --git a/test/fixtures/output/javascript/xhr/compression.js b/test/fixtures/output/javascript/xhr/compression.js new file mode 100644 index 0000000..eca54e4 --- /dev/null +++ b/test/fixtures/output/javascript/xhr/compression.js @@ -0,0 +1,15 @@ +const data = null; + +const xhr = new XMLHttpRequest(); +xhr.withCredentials = true; + +xhr.addEventListener("readystatechange", function () { + if (this.readyState === this.DONE) { + console.log(this.responseText); + } +}); + +xhr.open("GET", "http://mockbin.com/har"); +xhr.setRequestHeader("accept-encoding", "deflate, gzip, br"); + +xhr.send(data); \ No newline at end of file diff --git a/test/fixtures/output/javascript/xhr/headers.js b/test/fixtures/output/javascript/xhr/headers.js index 511c4ab..2ceeb6d 100644 --- a/test/fixtures/output/javascript/xhr/headers.js +++ b/test/fixtures/output/javascript/xhr/headers.js @@ -12,5 +12,6 @@ xhr.addEventListener("readystatechange", function () { xhr.open("GET", "http://mockbin.com/har"); xhr.setRequestHeader("accept", "application/json"); xhr.setRequestHeader("x-foo", "Bar"); +xhr.setRequestHeader("quoted-value", "\"quoted\" 'string'"); xhr.send(data); diff --git a/test/fixtures/output/javascript/xhr/malicious.js b/test/fixtures/output/javascript/xhr/malicious.js new file mode 100644 index 0000000..08c9797 --- /dev/null +++ b/test/fixtures/output/javascript/xhr/malicious.js @@ -0,0 +1,30 @@ +const data = "' \" ` $( #{ %( %{ {{ \\0 %s \\"; + +const xhr = new XMLHttpRequest(); +xhr.withCredentials = true; + +xhr.addEventListener("readystatechange", function () { + if (this.readyState === this.DONE) { + console.log(this.responseText); + } +}); + +xhr.open("POST", "http://example.test/%27%22%60$(%(%%7B%7B%7B/0%s//?'=squote-key-test&squote-value-test='&%22=dquote-key-test&dquote-value-test=%22&%60=backtick-key-test&backtick-value-test=%60&%24(=dollar-parenthesis-key-test&dollar-parenthesis-value-test=%24(&%23%7B=hash-brace-key-test&hash-brace-value-test=%23%7B&%25(=percent-parenthesis-key-test&percent-parenthesis-value-test=%25(&%25%7B=percent-brace-key-test&percent-brace-value-test=%25%7B&%7B%7B=double-brace-key-test&double-brace-value-test=%7B%7B&%5C0=null-key-test&null-value-test=%5C0&%25s=string-fmt-key-test&string-fmt-value-test=%25s&%5C=slash-key-test&slash-value-test=%5C"); +xhr.setRequestHeader("'", "squote-key-test"); +xhr.setRequestHeader("squote-value-test", "'"); +xhr.setRequestHeader("dquote-value-test", "\""); +xhr.setRequestHeader("`", "backtick-key-test"); +xhr.setRequestHeader("backtick-value-test", "`"); +xhr.setRequestHeader("$", "dollar-key-test"); +xhr.setRequestHeader("dollar-parenthesis-value-test", "$("); +xhr.setRequestHeader("#", "hash-key-test"); +xhr.setRequestHeader("hash-brace-value-test", "#{"); +xhr.setRequestHeader("%", "percent-key-test"); +xhr.setRequestHeader("percent-parenthesis-value-test", "%("); +xhr.setRequestHeader("percent-brace-value-test", "%{"); +xhr.setRequestHeader("double-brace-value-test", "{{"); +xhr.setRequestHeader("null-value-test", "\\0"); +xhr.setRequestHeader("string-fmt-value-test", "%s"); +xhr.setRequestHeader("slash-value-test", "\\"); + +xhr.send(data); \ No newline at end of file diff --git a/test/fixtures/output/javascript/xhr/unparseable-query.js b/test/fixtures/output/javascript/xhr/unparseable-query.js new file mode 100644 index 0000000..d955e0a --- /dev/null +++ b/test/fixtures/output/javascript/xhr/unparseable-query.js @@ -0,0 +1,14 @@ +const data = null; + +const xhr = new XMLHttpRequest(); +xhr.withCredentials = true; + +xhr.addEventListener("readystatechange", function () { + if (this.readyState === this.DONE) { + console.log(this.responseText); + } +}); + +xhr.open("GET", "http://mockbin.com/har?&&a=b&&"); + +xhr.send(data); \ No newline at end of file diff --git a/test/fixtures/output/kotlin/okhttp/compression.kt b/test/fixtures/output/kotlin/okhttp/compression.kt new file mode 100644 index 0000000..7b1ab0c --- /dev/null +++ b/test/fixtures/output/kotlin/okhttp/compression.kt @@ -0,0 +1,9 @@ +val client = OkHttpClient() + +val request = Request.Builder() + .url("http://mockbin.com/har") + .get() + .addHeader("accept-encoding", "deflate, gzip, br") + .build() + +val response = client.newCall(request).execute() \ No newline at end of file diff --git a/test/fixtures/output/kotlin/okhttp/headers.kt b/test/fixtures/output/kotlin/okhttp/headers.kt index 780e580..e404958 100644 --- a/test/fixtures/output/kotlin/okhttp/headers.kt +++ b/test/fixtures/output/kotlin/okhttp/headers.kt @@ -5,6 +5,7 @@ val request = Request.Builder() .get() .addHeader("accept", "application/json") .addHeader("x-foo", "Bar") + .addHeader("quoted-value", "\"quoted\" 'string'") .build() val response = client.newCall(request).execute() diff --git a/test/fixtures/output/kotlin/okhttp/malicious.kt b/test/fixtures/output/kotlin/okhttp/malicious.kt new file mode 100644 index 0000000..95d5e9f --- /dev/null +++ b/test/fixtures/output/kotlin/okhttp/malicious.kt @@ -0,0 +1,26 @@ +val client = OkHttpClient() + +val mediaType = MediaType.parse("text/plain") +val body = RequestBody.create(mediaType, "' \" ` $( #{ %( %{ {{ \\0 %s \\") +val request = Request.Builder() + .url("http://example.test/%27%22%60$(%(%%7B%7B%7B/0%s//?'=squote-key-test&squote-value-test='&%22=dquote-key-test&dquote-value-test=%22&%60=backtick-key-test&backtick-value-test=%60&%24(=dollar-parenthesis-key-test&dollar-parenthesis-value-test=%24(&%23%7B=hash-brace-key-test&hash-brace-value-test=%23%7B&%25(=percent-parenthesis-key-test&percent-parenthesis-value-test=%25(&%25%7B=percent-brace-key-test&percent-brace-value-test=%25%7B&%7B%7B=double-brace-key-test&double-brace-value-test=%7B%7B&%5C0=null-key-test&null-value-test=%5C0&%25s=string-fmt-key-test&string-fmt-value-test=%25s&%5C=slash-key-test&slash-value-test=%5C") + .post(body) + .addHeader("'", "squote-key-test") + .addHeader("squote-value-test", "'") + .addHeader("dquote-value-test", "\"") + .addHeader("`", "backtick-key-test") + .addHeader("backtick-value-test", "`") + .addHeader("$", "dollar-key-test") + .addHeader("dollar-parenthesis-value-test", "$(") + .addHeader("#", "hash-key-test") + .addHeader("hash-brace-value-test", "#{") + .addHeader("%", "percent-key-test") + .addHeader("percent-parenthesis-value-test", "%(") + .addHeader("percent-brace-value-test", "%{") + .addHeader("double-brace-value-test", "{{") + .addHeader("null-value-test", "\\0") + .addHeader("string-fmt-value-test", "%s") + .addHeader("slash-value-test", "\\") + .build() + +val response = client.newCall(request).execute() \ No newline at end of file diff --git a/test/fixtures/output/kotlin/okhttp/unparseable-query.kt b/test/fixtures/output/kotlin/okhttp/unparseable-query.kt new file mode 100644 index 0000000..208e62d --- /dev/null +++ b/test/fixtures/output/kotlin/okhttp/unparseable-query.kt @@ -0,0 +1,8 @@ +val client = OkHttpClient() + +val request = Request.Builder() + .url("http://mockbin.com/har?&&a=b&&") + .get() + .build() + +val response = client.newCall(request).execute() \ No newline at end of file diff --git a/test/fixtures/output/node/axios/compression.js b/test/fixtures/output/node/axios/compression.js new file mode 100644 index 0000000..6d4ba84 --- /dev/null +++ b/test/fixtures/output/node/axios/compression.js @@ -0,0 +1,13 @@ +var axios = require("axios").default; + +var options = { + method: 'GET', + url: 'http://mockbin.com/har', + headers: {'accept-encoding': 'deflate, gzip, br'} +}; + +axios.request(options).then(function (response) { + console.log(response.data); +}).catch(function (error) { + console.error(error); +}); \ No newline at end of file diff --git a/test/fixtures/output/node/axios/headers.js b/test/fixtures/output/node/axios/headers.js index 2dbe470..0955cbd 100644 --- a/test/fixtures/output/node/axios/headers.js +++ b/test/fixtures/output/node/axios/headers.js @@ -3,7 +3,11 @@ var axios = require("axios").default; var options = { method: 'GET', url: 'http://mockbin.com/har', - headers: {accept: 'application/json', 'x-foo': 'Bar'} + headers: { + accept: 'application/json', + 'x-foo': 'Bar', + 'quoted-value': '"quoted" \'string\'' + } }; axios.request(options).then(function (response) { diff --git a/test/fixtures/output/node/axios/malicious.js b/test/fixtures/output/node/axios/malicious.js new file mode 100644 index 0000000..0c3bc7c --- /dev/null +++ b/test/fixtures/output/node/axios/malicious.js @@ -0,0 +1,55 @@ +var axios = require("axios").default; + +var options = { + method: 'POST', + url: 'http://example.test/%27%22%60$(%(%%7B%7B%7B/0%s//', + params: { + '\'': 'squote-key-test', + 'squote-value-test': '\'', + '"': 'dquote-key-test', + 'dquote-value-test': '"', + '`': 'backtick-key-test', + 'backtick-value-test': '`', + '$(': 'dollar-parenthesis-key-test', + 'dollar-parenthesis-value-test': '$(', + '#{': 'hash-brace-key-test', + 'hash-brace-value-test': '#{', + '%(': 'percent-parenthesis-key-test', + 'percent-parenthesis-value-test': '%(', + '%{': 'percent-brace-key-test', + 'percent-brace-value-test': '%{', + '{{': 'double-brace-key-test', + 'double-brace-value-test': '{{', + '\\0': 'null-key-test', + 'null-value-test': '\\0', + '%s': 'string-fmt-key-test', + 'string-fmt-value-test': '%s', + '\\': 'slash-key-test', + 'slash-value-test': '\\' + }, + headers: { + '\'': 'squote-key-test', + 'squote-value-test': '\'', + 'dquote-value-test': '"', + '`': 'backtick-key-test', + 'backtick-value-test': '`', + $: 'dollar-key-test', + 'dollar-parenthesis-value-test': '$(', + '#': 'hash-key-test', + 'hash-brace-value-test': '#{', + '%': 'percent-key-test', + 'percent-parenthesis-value-test': '%(', + 'percent-brace-value-test': '%{', + 'double-brace-value-test': '{{', + 'null-value-test': '\\0', + 'string-fmt-value-test': '%s', + 'slash-value-test': '\\' + }, + data: '\' " ` $( #{ %( %{ {{ \\0 %s \\' +}; + +axios.request(options).then(function (response) { + console.log(response.data); +}).catch(function (error) { + console.error(error); +}); \ No newline at end of file diff --git a/test/fixtures/output/node/axios/unparseable-query.js b/test/fixtures/output/node/axios/unparseable-query.js new file mode 100644 index 0000000..dac5faa --- /dev/null +++ b/test/fixtures/output/node/axios/unparseable-query.js @@ -0,0 +1,9 @@ +var axios = require("axios").default; + +var options = {method: 'GET', url: 'http://mockbin.com/har?&&a=b&&'}; + +axios.request(options).then(function (response) { + console.log(response.data); +}).catch(function (error) { + console.error(error); +}); \ No newline at end of file diff --git a/test/fixtures/output/node/fetch/application-json.js b/test/fixtures/output/node/fetch/application-json.js index 618d55e..a21a86b 100644 --- a/test/fixtures/output/node/fetch/application-json.js +++ b/test/fixtures/output/node/fetch/application-json.js @@ -5,7 +5,7 @@ let url = 'http://mockbin.com/har'; let options = { method: 'POST', headers: {'content-type': 'application/json'}, - body: '{"number":1,"string":"f\"oo","arr":[1,2,3],"nested":{"a":"b"},"arr_mix":[1,"a",{"arr_mix_nested":{}}],"boolean":false}' + body: '{"number":1,"string":"f\\"oo","arr":[1,2,3],"nested":{"a":"b"},"arr_mix":[1,"a",{"arr_mix_nested":{}}],"boolean":false}' }; fetch(url, options) diff --git a/test/fixtures/output/node/fetch/compression.js b/test/fixtures/output/node/fetch/compression.js new file mode 100644 index 0000000..2eee5e8 --- /dev/null +++ b/test/fixtures/output/node/fetch/compression.js @@ -0,0 +1,10 @@ +const fetch = require('node-fetch'); + +let url = 'http://mockbin.com/har'; + +let options = {method: 'GET', headers: {'accept-encoding': 'deflate, gzip, br'}}; + +fetch(url, options) + .then(res => res.json()) + .then(json => console.log(json)) + .catch(err => console.error('error:' + err)); \ No newline at end of file diff --git a/test/fixtures/output/node/fetch/headers.js b/test/fixtures/output/node/fetch/headers.js index 7fa2948..09f7fd2 100644 --- a/test/fixtures/output/node/fetch/headers.js +++ b/test/fixtures/output/node/fetch/headers.js @@ -2,7 +2,14 @@ const fetch = require('node-fetch'); let url = 'http://mockbin.com/har'; -let options = {method: 'GET', headers: {accept: 'application/json', 'x-foo': 'Bar'}}; +let options = { + method: 'GET', + headers: { + accept: 'application/json', + 'x-foo': 'Bar', + 'quoted-value': '"quoted" \'string\'' + } +}; fetch(url, options) .then(res => res.json()) diff --git a/test/fixtures/output/node/fetch/malicious.js b/test/fixtures/output/node/fetch/malicious.js new file mode 100644 index 0000000..a50f8e9 --- /dev/null +++ b/test/fixtures/output/node/fetch/malicious.js @@ -0,0 +1,31 @@ +const fetch = require('node-fetch'); + +let url = 'http://example.test/%27%22%60$(%(%%7B%7B%7B/0%s//?\'=squote-key-test&squote-value-test=\'&%22=dquote-key-test&dquote-value-test=%22&%60=backtick-key-test&backtick-value-test=%60&%24(=dollar-parenthesis-key-test&dollar-parenthesis-value-test=%24(&%23%7B=hash-brace-key-test&hash-brace-value-test=%23%7B&%25(=percent-parenthesis-key-test&percent-parenthesis-value-test=%25(&%25%7B=percent-brace-key-test&percent-brace-value-test=%25%7B&%7B%7B=double-brace-key-test&double-brace-value-test=%7B%7B&%5C0=null-key-test&null-value-test=%5C0&%25s=string-fmt-key-test&string-fmt-value-test=%25s&%5C=slash-key-test&slash-value-test=%5C'; + +let options = { + method: 'POST', + headers: { + '\'': 'squote-key-test', + 'squote-value-test': '\'', + 'dquote-value-test': '"', + '`': 'backtick-key-test', + 'backtick-value-test': '`', + $: 'dollar-key-test', + 'dollar-parenthesis-value-test': '$(', + '#': 'hash-key-test', + 'hash-brace-value-test': '#{', + '%': 'percent-key-test', + 'percent-parenthesis-value-test': '%(', + 'percent-brace-value-test': '%{', + 'double-brace-value-test': '{{', + 'null-value-test': '\\0', + 'string-fmt-value-test': '%s', + 'slash-value-test': '\\' + }, + body: '\' " ` $( #{ %( %{ {{ \\0 %s \\' +}; + +fetch(url, options) + .then(res => res.json()) + .then(json => console.log(json)) + .catch(err => console.error('error:' + err)); \ No newline at end of file diff --git a/test/fixtures/output/node/fetch/unparseable-query.js b/test/fixtures/output/node/fetch/unparseable-query.js new file mode 100644 index 0000000..7064d64 --- /dev/null +++ b/test/fixtures/output/node/fetch/unparseable-query.js @@ -0,0 +1,10 @@ +const fetch = require('node-fetch'); + +let url = 'http://mockbin.com/har?&&a=b&&'; + +let options = {method: 'GET'}; + +fetch(url, options) + .then(res => res.json()) + .then(json => console.log(json)) + .catch(err => console.error('error:' + err)); \ No newline at end of file diff --git a/test/fixtures/output/node/native/compression.js b/test/fixtures/output/node/native/compression.js new file mode 100644 index 0000000..1433ebc --- /dev/null +++ b/test/fixtures/output/node/native/compression.js @@ -0,0 +1,26 @@ +const http = require("http"); + +const options = { + "method": "GET", + "hostname": "mockbin.com", + "port": null, + "path": "/har", + "headers": { + "accept-encoding": "deflate, gzip, br" + } +}; + +const req = http.request(options, function (res) { + const chunks = []; + + res.on("data", function (chunk) { + chunks.push(chunk); + }); + + res.on("end", function () { + const body = Buffer.concat(chunks); + console.log(body.toString()); + }); +}); + +req.end(); \ No newline at end of file diff --git a/test/fixtures/output/node/native/headers.js b/test/fixtures/output/node/native/headers.js index a36dfc9..940deb5 100644 --- a/test/fixtures/output/node/native/headers.js +++ b/test/fixtures/output/node/native/headers.js @@ -7,7 +7,8 @@ const options = { "path": "/har", "headers": { "accept": "application/json", - "x-foo": "Bar" + "x-foo": "Bar", + "quoted-value": "\"quoted\" 'string'" } }; diff --git a/test/fixtures/output/node/native/malicious.js b/test/fixtures/output/node/native/malicious.js new file mode 100644 index 0000000..13db86e --- /dev/null +++ b/test/fixtures/output/node/native/malicious.js @@ -0,0 +1,42 @@ +const http = require("http"); + +const options = { + "method": "POST", + "hostname": "example.test", + "port": null, + "path": "/%27%22%60$(%(%%7B%7B%7B/0%s//?'=squote-key-test&squote-value-test='&%22=dquote-key-test&dquote-value-test=%22&%60=backtick-key-test&backtick-value-test=%60&%24(=dollar-parenthesis-key-test&dollar-parenthesis-value-test=%24(&%23%7B=hash-brace-key-test&hash-brace-value-test=%23%7B&%25(=percent-parenthesis-key-test&percent-parenthesis-value-test=%25(&%25%7B=percent-brace-key-test&percent-brace-value-test=%25%7B&%7B%7B=double-brace-key-test&double-brace-value-test=%7B%7B&%5C0=null-key-test&null-value-test=%5C0&%25s=string-fmt-key-test&string-fmt-value-test=%25s&%5C=slash-key-test&slash-value-test=%5C", + "headers": { + "'": "squote-key-test", + "squote-value-test": "'", + "dquote-value-test": "\"", + "`": "backtick-key-test", + "backtick-value-test": "`", + "$": "dollar-key-test", + "dollar-parenthesis-value-test": "$(", + "#": "hash-key-test", + "hash-brace-value-test": "#{", + "%": "percent-key-test", + "percent-parenthesis-value-test": "%(", + "percent-brace-value-test": "%{", + "double-brace-value-test": "{{", + "null-value-test": "\\0", + "string-fmt-value-test": "%s", + "slash-value-test": "\\" + } +}; + +const req = http.request(options, function (res) { + const chunks = []; + + res.on("data", function (chunk) { + chunks.push(chunk); + }); + + res.on("end", function () { + const body = Buffer.concat(chunks); + console.log(body.toString()); + }); +}); + +req.write("' \" ` $( #{ %( %{ {{ \\0 %s \\"); +req.end(); \ No newline at end of file diff --git a/test/fixtures/output/node/native/unparseable-query.js b/test/fixtures/output/node/native/unparseable-query.js new file mode 100644 index 0000000..b991ed0 --- /dev/null +++ b/test/fixtures/output/node/native/unparseable-query.js @@ -0,0 +1,24 @@ +const http = require("http"); + +const options = { + "method": "GET", + "hostname": "mockbin.com", + "port": null, + "path": "/har?&&a=b&&", + "headers": {} +}; + +const req = http.request(options, function (res) { + const chunks = []; + + res.on("data", function (chunk) { + chunks.push(chunk); + }); + + res.on("end", function () { + const body = Buffer.concat(chunks); + console.log(body.toString()); + }); +}); + +req.end(); \ No newline at end of file diff --git a/test/fixtures/output/node/request/compression.js b/test/fixtures/output/node/request/compression.js new file mode 100644 index 0000000..b034830 --- /dev/null +++ b/test/fixtures/output/node/request/compression.js @@ -0,0 +1,13 @@ +const request = require('request'); + +const options = { + method: 'GET', + url: 'http://mockbin.com/har', + headers: {'accept-encoding': 'deflate, gzip, br'} +}; + +request(options, function (error, response, body) { + if (error) throw new Error(error); + + console.log(body); +}); \ No newline at end of file diff --git a/test/fixtures/output/node/request/headers.js b/test/fixtures/output/node/request/headers.js index a30e3fb..b33229b 100644 --- a/test/fixtures/output/node/request/headers.js +++ b/test/fixtures/output/node/request/headers.js @@ -3,7 +3,11 @@ const request = require('request'); const options = { method: 'GET', url: 'http://mockbin.com/har', - headers: {accept: 'application/json', 'x-foo': 'Bar'} + headers: { + accept: 'application/json', + 'x-foo': 'Bar', + 'quoted-value': '"quoted" \'string\'' + } }; request(options, function (error, response, body) { diff --git a/test/fixtures/output/node/request/malicious.js b/test/fixtures/output/node/request/malicious.js new file mode 100644 index 0000000..e289ee6 --- /dev/null +++ b/test/fixtures/output/node/request/malicious.js @@ -0,0 +1,55 @@ +const request = require('request'); + +const options = { + method: 'POST', + url: 'http://example.test/%27%22%60$(%(%%7B%7B%7B/0%s//', + qs: { + '\'': 'squote-key-test', + 'squote-value-test': '\'', + '"': 'dquote-key-test', + 'dquote-value-test': '"', + '`': 'backtick-key-test', + 'backtick-value-test': '`', + '$(': 'dollar-parenthesis-key-test', + 'dollar-parenthesis-value-test': '$(', + '#{': 'hash-brace-key-test', + 'hash-brace-value-test': '#{', + '%(': 'percent-parenthesis-key-test', + 'percent-parenthesis-value-test': '%(', + '%{': 'percent-brace-key-test', + 'percent-brace-value-test': '%{', + '{{': 'double-brace-key-test', + 'double-brace-value-test': '{{', + '\\0': 'null-key-test', + 'null-value-test': '\\0', + '%s': 'string-fmt-key-test', + 'string-fmt-value-test': '%s', + '\\': 'slash-key-test', + 'slash-value-test': '\\' + }, + headers: { + '\'': 'squote-key-test', + 'squote-value-test': '\'', + 'dquote-value-test': '"', + '`': 'backtick-key-test', + 'backtick-value-test': '`', + $: 'dollar-key-test', + 'dollar-parenthesis-value-test': '$(', + '#': 'hash-key-test', + 'hash-brace-value-test': '#{', + '%': 'percent-key-test', + 'percent-parenthesis-value-test': '%(', + 'percent-brace-value-test': '%{', + 'double-brace-value-test': '{{', + 'null-value-test': '\\0', + 'string-fmt-value-test': '%s', + 'slash-value-test': '\\' + }, + body: '\' " ` $( #{ %( %{ {{ \\0 %s \\' +}; + +request(options, function (error, response, body) { + if (error) throw new Error(error); + + console.log(body); +}); \ No newline at end of file diff --git a/test/fixtures/output/node/request/unparseable-query.js b/test/fixtures/output/node/request/unparseable-query.js new file mode 100644 index 0000000..c10a732 --- /dev/null +++ b/test/fixtures/output/node/request/unparseable-query.js @@ -0,0 +1,9 @@ +const request = require('request'); + +const options = {method: 'GET', url: 'http://mockbin.com/har?&&a=b&&'}; + +request(options, function (error, response, body) { + if (error) throw new Error(error); + + console.log(body); +}); \ No newline at end of file diff --git a/test/fixtures/output/node/unirest/compression.js b/test/fixtures/output/node/unirest/compression.js new file mode 100644 index 0000000..da60aa6 --- /dev/null +++ b/test/fixtures/output/node/unirest/compression.js @@ -0,0 +1,13 @@ +const unirest = require("unirest"); + +const req = unirest("GET", "http://mockbin.com/har"); + +req.headers({ + "accept-encoding": "deflate, gzip, br" +}); + +req.end(function (res) { + if (res.error) throw new Error(res.error); + + console.log(res.body); +}); \ No newline at end of file diff --git a/test/fixtures/output/node/unirest/headers.js b/test/fixtures/output/node/unirest/headers.js index a9e1939..0808629 100644 --- a/test/fixtures/output/node/unirest/headers.js +++ b/test/fixtures/output/node/unirest/headers.js @@ -4,7 +4,8 @@ const req = unirest("GET", "http://mockbin.com/har"); req.headers({ "accept": "application/json", - "x-foo": "Bar" + "x-foo": "Bar", + "quoted-value": "\"quoted\" 'string'" }); req.end(function (res) { diff --git a/test/fixtures/output/node/unirest/malicious.js b/test/fixtures/output/node/unirest/malicious.js new file mode 100644 index 0000000..d082c42 --- /dev/null +++ b/test/fixtures/output/node/unirest/malicious.js @@ -0,0 +1,55 @@ +const unirest = require("unirest"); + +const req = unirest("POST", "http://example.test/%27%22%60$(%(%%7B%7B%7B/0%s//"); + +req.query({ + "'": "squote-key-test", + "squote-value-test": "'", + "\"": "dquote-key-test", + "dquote-value-test": "\"", + "`": "backtick-key-test", + "backtick-value-test": "`", + "$(": "dollar-parenthesis-key-test", + "dollar-parenthesis-value-test": "$(", + "#{": "hash-brace-key-test", + "hash-brace-value-test": "#{", + "%(": "percent-parenthesis-key-test", + "percent-parenthesis-value-test": "%(", + "%{": "percent-brace-key-test", + "percent-brace-value-test": "%{", + "{{": "double-brace-key-test", + "double-brace-value-test": "{{", + "\\0": "null-key-test", + "null-value-test": "\\0", + "%s": "string-fmt-key-test", + "string-fmt-value-test": "%s", + "\\": "slash-key-test", + "slash-value-test": "\\" +}); + +req.headers({ + "'": "squote-key-test", + "squote-value-test": "'", + "dquote-value-test": "\"", + "`": "backtick-key-test", + "backtick-value-test": "`", + "$": "dollar-key-test", + "dollar-parenthesis-value-test": "$(", + "#": "hash-key-test", + "hash-brace-value-test": "#{", + "%": "percent-key-test", + "percent-parenthesis-value-test": "%(", + "percent-brace-value-test": "%{", + "double-brace-value-test": "{{", + "null-value-test": "\\0", + "string-fmt-value-test": "%s", + "slash-value-test": "\\" +}); + +req.send("' \" ` $( #{ %( %{ {{ \\0 %s \\"); + +req.end(function (res) { + if (res.error) throw new Error(res.error); + + console.log(res.body); +}); \ No newline at end of file diff --git a/test/fixtures/output/node/unirest/unparseable-query.js b/test/fixtures/output/node/unirest/unparseable-query.js new file mode 100644 index 0000000..f0f961e --- /dev/null +++ b/test/fixtures/output/node/unirest/unparseable-query.js @@ -0,0 +1,9 @@ +const unirest = require("unirest"); + +const req = unirest("GET", "http://mockbin.com/har?&&a=b&&"); + +req.end(function (res) { + if (res.error) throw new Error(res.error); + + console.log(res.body); +}); \ No newline at end of file diff --git a/test/fixtures/output/objc/nsurlsession/compression.m b/test/fixtures/output/objc/nsurlsession/compression.m new file mode 100644 index 0000000..533bd79 --- /dev/null +++ b/test/fixtures/output/objc/nsurlsession/compression.m @@ -0,0 +1,21 @@ +#import + +NSDictionary *headers = @{ @"accept-encoding": @"deflate, gzip, br" }; + +NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:[NSURL URLWithString:@"http://mockbin.com/har"] + cachePolicy:NSURLRequestUseProtocolCachePolicy + timeoutInterval:10.0]; +[request setHTTPMethod:@"GET"]; +[request setAllHTTPHeaderFields:headers]; + +NSURLSession *session = [NSURLSession sharedSession]; +NSURLSessionDataTask *dataTask = [session dataTaskWithRequest:request + completionHandler:^(NSData *data, NSURLResponse *response, NSError *error) { + if (error) { + NSLog(@"%@", error); + } else { + NSHTTPURLResponse *httpResponse = (NSHTTPURLResponse *) response; + NSLog(@"%@", httpResponse); + } + }]; +[dataTask resume]; \ No newline at end of file diff --git a/test/fixtures/output/objc/nsurlsession/headers.m b/test/fixtures/output/objc/nsurlsession/headers.m index 1d226ff..aec7198 100644 --- a/test/fixtures/output/objc/nsurlsession/headers.m +++ b/test/fixtures/output/objc/nsurlsession/headers.m @@ -1,7 +1,8 @@ #import NSDictionary *headers = @{ @"accept": @"application/json", - @"x-foo": @"Bar" }; + @"x-foo": @"Bar", + @"quoted-value": @"\"quoted\" 'string'" }; NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:[NSURL URLWithString:@"http://mockbin.com/har"] cachePolicy:NSURLRequestUseProtocolCachePolicy diff --git a/test/fixtures/output/objc/nsurlsession/malicious.m b/test/fixtures/output/objc/nsurlsession/malicious.m new file mode 100644 index 0000000..66f2cc5 --- /dev/null +++ b/test/fixtures/output/objc/nsurlsession/malicious.m @@ -0,0 +1,39 @@ +#import + +NSDictionary *headers = @{ @"'": @"squote-key-test", + @"squote-value-test": @"'", + @"dquote-value-test": @"\"", + @"`": @"backtick-key-test", + @"backtick-value-test": @"`", + @"$": @"dollar-key-test", + @"dollar-parenthesis-value-test": @"$(", + @"#": @"hash-key-test", + @"hash-brace-value-test": @"#{", + @"%": @"percent-key-test", + @"percent-parenthesis-value-test": @"%(", + @"percent-brace-value-test": @"%{", + @"double-brace-value-test": @"{{", + @"null-value-test": @"\\0", + @"string-fmt-value-test": @"%s", + @"slash-value-test": @"\\" }; + +NSData *postData = [[NSData alloc] initWithData:[@"' \" ` $( #{ %( %{ {{ \\0 %s \\" dataUsingEncoding:NSUTF8StringEncoding]]; + +NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:[NSURL URLWithString:@"http://example.test/%27%22%60$(%(%%7B%7B%7B/0%s//?'=squote-key-test&squote-value-test='&%22=dquote-key-test&dquote-value-test=%22&%60=backtick-key-test&backtick-value-test=%60&%24(=dollar-parenthesis-key-test&dollar-parenthesis-value-test=%24(&%23%7B=hash-brace-key-test&hash-brace-value-test=%23%7B&%25(=percent-parenthesis-key-test&percent-parenthesis-value-test=%25(&%25%7B=percent-brace-key-test&percent-brace-value-test=%25%7B&%7B%7B=double-brace-key-test&double-brace-value-test=%7B%7B&%5C0=null-key-test&null-value-test=%5C0&%25s=string-fmt-key-test&string-fmt-value-test=%25s&%5C=slash-key-test&slash-value-test=%5C"] + cachePolicy:NSURLRequestUseProtocolCachePolicy + timeoutInterval:10.0]; +[request setHTTPMethod:@"POST"]; +[request setAllHTTPHeaderFields:headers]; +[request setHTTPBody:postData]; + +NSURLSession *session = [NSURLSession sharedSession]; +NSURLSessionDataTask *dataTask = [session dataTaskWithRequest:request + completionHandler:^(NSData *data, NSURLResponse *response, NSError *error) { + if (error) { + NSLog(@"%@", error); + } else { + NSHTTPURLResponse *httpResponse = (NSHTTPURLResponse *) response; + NSLog(@"%@", httpResponse); + } + }]; +[dataTask resume]; \ No newline at end of file diff --git a/test/fixtures/output/objc/nsurlsession/unparseable-query.m b/test/fixtures/output/objc/nsurlsession/unparseable-query.m new file mode 100644 index 0000000..b201540 --- /dev/null +++ b/test/fixtures/output/objc/nsurlsession/unparseable-query.m @@ -0,0 +1,18 @@ +#import + +NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:[NSURL URLWithString:@"http://mockbin.com/har?&&a=b&&"] + cachePolicy:NSURLRequestUseProtocolCachePolicy + timeoutInterval:10.0]; +[request setHTTPMethod:@"GET"]; + +NSURLSession *session = [NSURLSession sharedSession]; +NSURLSessionDataTask *dataTask = [session dataTaskWithRequest:request + completionHandler:^(NSData *data, NSURLResponse *response, NSError *error) { + if (error) { + NSLog(@"%@", error); + } else { + NSHTTPURLResponse *httpResponse = (NSHTTPURLResponse *) response; + NSLog(@"%@", httpResponse); + } + }]; +[dataTask resume]; \ No newline at end of file diff --git a/test/fixtures/output/ocaml/cohttp/compression.ml b/test/fixtures/output/ocaml/cohttp/compression.ml new file mode 100644 index 0000000..e5703bd --- /dev/null +++ b/test/fixtures/output/ocaml/cohttp/compression.ml @@ -0,0 +1,10 @@ +open Cohttp_lwt_unix +open Cohttp +open Lwt + +let uri = Uri.of_string "http://mockbin.com/har" in +let headers = Header.add (Header.init ()) "accept-encoding" "deflate, gzip, br" in + +Client.call ~headers `GET uri +>>= fun (res, body_stream) -> + (* Do stuff with the result *) \ No newline at end of file diff --git a/test/fixtures/output/ocaml/cohttp/headers.ml b/test/fixtures/output/ocaml/cohttp/headers.ml index 6755d5a..05f86ee 100644 --- a/test/fixtures/output/ocaml/cohttp/headers.ml +++ b/test/fixtures/output/ocaml/cohttp/headers.ml @@ -6,6 +6,7 @@ let uri = Uri.of_string "http://mockbin.com/har" in let headers = Header.add_list (Header.init ()) [ ("accept", "application/json"); ("x-foo", "Bar"); + ("quoted-value", "\"quoted\" 'string'"); ] in Client.call ~headers `GET uri diff --git a/test/fixtures/output/ocaml/cohttp/malicious.ml b/test/fixtures/output/ocaml/cohttp/malicious.ml new file mode 100644 index 0000000..ada920e --- /dev/null +++ b/test/fixtures/output/ocaml/cohttp/malicious.ml @@ -0,0 +1,28 @@ +open Cohttp_lwt_unix +open Cohttp +open Lwt + +let uri = Uri.of_string "http://example.test/%27%22%60$(%(%%7B%7B%7B/0%s//?'=squote-key-test&squote-value-test='&%22=dquote-key-test&dquote-value-test=%22&%60=backtick-key-test&backtick-value-test=%60&%24(=dollar-parenthesis-key-test&dollar-parenthesis-value-test=%24(&%23%7B=hash-brace-key-test&hash-brace-value-test=%23%7B&%25(=percent-parenthesis-key-test&percent-parenthesis-value-test=%25(&%25%7B=percent-brace-key-test&percent-brace-value-test=%25%7B&%7B%7B=double-brace-key-test&double-brace-value-test=%7B%7B&%5C0=null-key-test&null-value-test=%5C0&%25s=string-fmt-key-test&string-fmt-value-test=%25s&%5C=slash-key-test&slash-value-test=%5C" in +let headers = Header.add_list (Header.init ()) [ + ("'", "squote-key-test"); + ("squote-value-test", "'"); + ("dquote-value-test", "\""); + ("`", "backtick-key-test"); + ("backtick-value-test", "`"); + ("$", "dollar-key-test"); + ("dollar-parenthesis-value-test", "$("); + ("#", "hash-key-test"); + ("hash-brace-value-test", "#{"); + ("%", "percent-key-test"); + ("percent-parenthesis-value-test", "%("); + ("percent-brace-value-test", "%{"); + ("double-brace-value-test", "{{"); + ("null-value-test", "\\0"); + ("string-fmt-value-test", "%s"); + ("slash-value-test", "\\"); +] in +let body = Cohttp_lwt_body.of_string "' \" ` $( #{ %( %{ {{ \\0 %s \\" in + +Client.call ~headers ~body `POST uri +>>= fun (res, body_stream) -> + (* Do stuff with the result *) \ No newline at end of file diff --git a/test/fixtures/output/ocaml/cohttp/unparseable-query.ml b/test/fixtures/output/ocaml/cohttp/unparseable-query.ml new file mode 100644 index 0000000..f601513 --- /dev/null +++ b/test/fixtures/output/ocaml/cohttp/unparseable-query.ml @@ -0,0 +1,9 @@ +open Cohttp_lwt_unix +open Cohttp +open Lwt + +let uri = Uri.of_string "http://mockbin.com/har?&&a=b&&" in + +Client.call `GET uri +>>= fun (res, body_stream) -> + (* Do stuff with the result *) \ No newline at end of file diff --git a/test/fixtures/output/php/curl/application-form-encoded.php b/test/fixtures/output/php/curl/application-form-encoded.php index 0892dd3..47114c3 100644 --- a/test/fixtures/output/php/curl/application-form-encoded.php +++ b/test/fixtures/output/php/curl/application-form-encoded.php @@ -3,16 +3,16 @@ $curl = curl_init(); curl_setopt_array($curl, [ - CURLOPT_URL => "http://mockbin.com/har", + CURLOPT_URL => 'http://mockbin.com/har', CURLOPT_RETURNTRANSFER => true, - CURLOPT_ENCODING => "", + CURLOPT_ENCODING => '', CURLOPT_MAXREDIRS => 10, CURLOPT_TIMEOUT => 30, CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1, - CURLOPT_CUSTOMREQUEST => "POST", - CURLOPT_POSTFIELDS => "foo=bar&hello=world", + CURLOPT_CUSTOMREQUEST => 'POST', + CURLOPT_POSTFIELDS => 'foo=bar&hello=world', CURLOPT_HTTPHEADER => [ - "content-type: application/x-www-form-urlencoded" + 'content-type: application/x-www-form-urlencoded' ], ]); @@ -22,7 +22,7 @@ curl_close($curl); if ($err) { - echo "cURL Error #:" . $err; + echo 'cURL Error #:' . $err; } else { echo $response; } diff --git a/test/fixtures/output/php/curl/application-json.php b/test/fixtures/output/php/curl/application-json.php index 8a0f0c1..e80ff42 100644 --- a/test/fixtures/output/php/curl/application-json.php +++ b/test/fixtures/output/php/curl/application-json.php @@ -3,16 +3,16 @@ $curl = curl_init(); curl_setopt_array($curl, [ - CURLOPT_URL => "http://mockbin.com/har", + CURLOPT_URL => 'http://mockbin.com/har', CURLOPT_RETURNTRANSFER => true, - CURLOPT_ENCODING => "", + CURLOPT_ENCODING => '', CURLOPT_MAXREDIRS => 10, CURLOPT_TIMEOUT => 30, CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1, - CURLOPT_CUSTOMREQUEST => "POST", - CURLOPT_POSTFIELDS => "{\"number\":1,\"string\":\"f\\\"oo\",\"arr\":[1,2,3],\"nested\":{\"a\":\"b\"},\"arr_mix\":[1,\"a\",{\"arr_mix_nested\":{}}],\"boolean\":false}", + CURLOPT_CUSTOMREQUEST => 'POST', + CURLOPT_POSTFIELDS => '{"number":1,"string":"f\\"oo","arr":[1,2,3],"nested":{"a":"b"},"arr_mix":[1,"a",{"arr_mix_nested":{}}],"boolean":false}', CURLOPT_HTTPHEADER => [ - "content-type: application/json" + 'content-type: application/json' ], ]); @@ -22,7 +22,7 @@ curl_close($curl); if ($err) { - echo "cURL Error #:" . $err; + echo 'cURL Error #:' . $err; } else { echo $response; } diff --git a/test/fixtures/output/php/curl/compression.php b/test/fixtures/output/php/curl/compression.php new file mode 100644 index 0000000..bfc0378 --- /dev/null +++ b/test/fixtures/output/php/curl/compression.php @@ -0,0 +1,27 @@ + 'http://mockbin.com/har', + CURLOPT_RETURNTRANSFER => true, + CURLOPT_ENCODING => '', + CURLOPT_MAXREDIRS => 10, + CURLOPT_TIMEOUT => 30, + CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1, + CURLOPT_CUSTOMREQUEST => 'GET', + CURLOPT_HTTPHEADER => [ + 'accept-encoding: deflate, gzip, br' + ], +]); + +$response = curl_exec($curl); +$err = curl_error($curl); + +curl_close($curl); + +if ($err) { + echo 'cURL Error #:' . $err; +} else { + echo $response; +} \ No newline at end of file diff --git a/test/fixtures/output/php/curl/cookies.php b/test/fixtures/output/php/curl/cookies.php index 2810430..c604973 100644 --- a/test/fixtures/output/php/curl/cookies.php +++ b/test/fixtures/output/php/curl/cookies.php @@ -3,14 +3,14 @@ $curl = curl_init(); curl_setopt_array($curl, [ - CURLOPT_URL => "http://mockbin.com/har", + CURLOPT_URL => 'http://mockbin.com/har', CURLOPT_RETURNTRANSFER => true, - CURLOPT_ENCODING => "", + CURLOPT_ENCODING => '', CURLOPT_MAXREDIRS => 10, CURLOPT_TIMEOUT => 30, CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1, - CURLOPT_CUSTOMREQUEST => "POST", - CURLOPT_COOKIE => "foo=bar; bar=baz", + CURLOPT_CUSTOMREQUEST => 'POST', + CURLOPT_COOKIE => 'foo=bar; bar=baz' ]); $response = curl_exec($curl); @@ -19,7 +19,7 @@ curl_close($curl); if ($err) { - echo "cURL Error #:" . $err; + echo 'cURL Error #:' . $err; } else { echo $response; } diff --git a/test/fixtures/output/php/curl/custom-method.php b/test/fixtures/output/php/curl/custom-method.php index 08aa597..16e6d57 100644 --- a/test/fixtures/output/php/curl/custom-method.php +++ b/test/fixtures/output/php/curl/custom-method.php @@ -3,13 +3,13 @@ $curl = curl_init(); curl_setopt_array($curl, [ - CURLOPT_URL => "http://mockbin.com/har", + CURLOPT_URL => 'http://mockbin.com/har', CURLOPT_RETURNTRANSFER => true, - CURLOPT_ENCODING => "", + CURLOPT_ENCODING => '', CURLOPT_MAXREDIRS => 10, CURLOPT_TIMEOUT => 30, CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1, - CURLOPT_CUSTOMREQUEST => "PROPFIND", + CURLOPT_CUSTOMREQUEST => 'PROPFIND', ]); $response = curl_exec($curl); @@ -18,7 +18,7 @@ curl_close($curl); if ($err) { - echo "cURL Error #:" . $err; + echo 'cURL Error #:' . $err; } else { echo $response; } diff --git a/test/fixtures/output/php/curl/full.php b/test/fixtures/output/php/curl/full.php index 6f342b6..ee1aaee 100644 --- a/test/fixtures/output/php/curl/full.php +++ b/test/fixtures/output/php/curl/full.php @@ -3,18 +3,18 @@ $curl = curl_init(); curl_setopt_array($curl, [ - CURLOPT_URL => "http://mockbin.com/har?foo=bar&foo=baz&baz=abc&key=value", + CURLOPT_URL => 'http://mockbin.com/har?foo=bar&foo=baz&baz=abc&key=value', CURLOPT_RETURNTRANSFER => true, - CURLOPT_ENCODING => "", + CURLOPT_ENCODING => '', CURLOPT_MAXREDIRS => 10, CURLOPT_TIMEOUT => 30, CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1, - CURLOPT_CUSTOMREQUEST => "POST", - CURLOPT_POSTFIELDS => "foo=bar", - CURLOPT_COOKIE => "foo=bar; bar=baz", + CURLOPT_CUSTOMREQUEST => 'POST', + CURLOPT_POSTFIELDS => 'foo=bar', + CURLOPT_COOKIE => 'foo=bar; bar=baz' CURLOPT_HTTPHEADER => [ - "accept: application/json", - "content-type: application/x-www-form-urlencoded" + 'accept: application/json', + 'content-type: application/x-www-form-urlencoded' ], ]); @@ -24,7 +24,7 @@ curl_close($curl); if ($err) { - echo "cURL Error #:" . $err; + echo 'cURL Error #:' . $err; } else { echo $response; } diff --git a/test/fixtures/output/php/curl/headers.php b/test/fixtures/output/php/curl/headers.php index 4e8be5a..42dfe33 100644 --- a/test/fixtures/output/php/curl/headers.php +++ b/test/fixtures/output/php/curl/headers.php @@ -3,16 +3,17 @@ $curl = curl_init(); curl_setopt_array($curl, [ - CURLOPT_URL => "http://mockbin.com/har", + CURLOPT_URL => 'http://mockbin.com/har', CURLOPT_RETURNTRANSFER => true, - CURLOPT_ENCODING => "", + CURLOPT_ENCODING => '', CURLOPT_MAXREDIRS => 10, CURLOPT_TIMEOUT => 30, CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1, - CURLOPT_CUSTOMREQUEST => "GET", + CURLOPT_CUSTOMREQUEST => 'GET', CURLOPT_HTTPHEADER => [ - "accept: application/json", - "x-foo: Bar" + 'accept: application/json', + 'quoted-value: "quoted" \'string\'', + 'x-foo: Bar' ], ]); @@ -22,7 +23,7 @@ curl_close($curl); if ($err) { - echo "cURL Error #:" . $err; + echo 'cURL Error #:' . $err; } else { echo $response; } diff --git a/test/fixtures/output/php/curl/https.php b/test/fixtures/output/php/curl/https.php index 7d97476..bef4757 100644 --- a/test/fixtures/output/php/curl/https.php +++ b/test/fixtures/output/php/curl/https.php @@ -3,13 +3,13 @@ $curl = curl_init(); curl_setopt_array($curl, [ - CURLOPT_URL => "https://mockbin.com/har", + CURLOPT_URL => 'https://mockbin.com/har', CURLOPT_RETURNTRANSFER => true, - CURLOPT_ENCODING => "", + CURLOPT_ENCODING => '', CURLOPT_MAXREDIRS => 10, CURLOPT_TIMEOUT => 30, CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1, - CURLOPT_CUSTOMREQUEST => "GET", + CURLOPT_CUSTOMREQUEST => 'GET', ]); $response = curl_exec($curl); @@ -18,7 +18,7 @@ curl_close($curl); if ($err) { - echo "cURL Error #:" . $err; + echo 'cURL Error #:' . $err; } else { echo $response; } diff --git a/test/fixtures/output/php/curl/jsonObj-multiline.php b/test/fixtures/output/php/curl/jsonObj-multiline.php index 19f7727..2c5d836 100644 --- a/test/fixtures/output/php/curl/jsonObj-multiline.php +++ b/test/fixtures/output/php/curl/jsonObj-multiline.php @@ -3,16 +3,18 @@ $curl = curl_init(); curl_setopt_array($curl, [ - CURLOPT_URL => "http://mockbin.com/har", + CURLOPT_URL => 'http://mockbin.com/har', CURLOPT_RETURNTRANSFER => true, - CURLOPT_ENCODING => "", + CURLOPT_ENCODING => '', CURLOPT_MAXREDIRS => 10, CURLOPT_TIMEOUT => 30, CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1, - CURLOPT_CUSTOMREQUEST => "POST", - CURLOPT_POSTFIELDS => "{\n \"foo\": \"bar\"\n}", + CURLOPT_CUSTOMREQUEST => 'POST', + CURLOPT_POSTFIELDS => '{ + "foo": "bar" +}', CURLOPT_HTTPHEADER => [ - "content-type: application/json" + 'content-type: application/json' ], ]); @@ -22,7 +24,7 @@ curl_close($curl); if ($err) { - echo "cURL Error #:" . $err; + echo 'cURL Error #:' . $err; } else { echo $response; } diff --git a/test/fixtures/output/php/curl/jsonObj-null-value.php b/test/fixtures/output/php/curl/jsonObj-null-value.php index 99a2289..68fee65 100644 --- a/test/fixtures/output/php/curl/jsonObj-null-value.php +++ b/test/fixtures/output/php/curl/jsonObj-null-value.php @@ -3,16 +3,16 @@ $curl = curl_init(); curl_setopt_array($curl, [ - CURLOPT_URL => "http://mockbin.com/har", + CURLOPT_URL => 'http://mockbin.com/har', CURLOPT_RETURNTRANSFER => true, - CURLOPT_ENCODING => "", + CURLOPT_ENCODING => '', CURLOPT_MAXREDIRS => 10, CURLOPT_TIMEOUT => 30, CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1, - CURLOPT_CUSTOMREQUEST => "POST", - CURLOPT_POSTFIELDS => "{\"foo\":null}", + CURLOPT_CUSTOMREQUEST => 'POST', + CURLOPT_POSTFIELDS => '{"foo":null}', CURLOPT_HTTPHEADER => [ - "content-type: application/json" + 'content-type: application/json' ], ]); @@ -22,7 +22,7 @@ curl_close($curl); if ($err) { - echo "cURL Error #:" . $err; + echo 'cURL Error #:' . $err; } else { echo $response; } diff --git a/test/fixtures/output/php/curl/malicious.php b/test/fixtures/output/php/curl/malicious.php new file mode 100644 index 0000000..6418f5c --- /dev/null +++ b/test/fixtures/output/php/curl/malicious.php @@ -0,0 +1,43 @@ + 'http://example.test/%27%22%60$(%(%%7B%7B%7B/0%s//?\'=squote-key-test&squote-value-test=\'&%22=dquote-key-test&dquote-value-test=%22&%60=backtick-key-test&backtick-value-test=%60&%24(=dollar-parenthesis-key-test&dollar-parenthesis-value-test=%24(&%23%7B=hash-brace-key-test&hash-brace-value-test=%23%7B&%25(=percent-parenthesis-key-test&percent-parenthesis-value-test=%25(&%25%7B=percent-brace-key-test&percent-brace-value-test=%25%7B&%7B%7B=double-brace-key-test&double-brace-value-test=%7B%7B&%5C0=null-key-test&null-value-test=%5C0&%25s=string-fmt-key-test&string-fmt-value-test=%25s&%5C=slash-key-test&slash-value-test=%5C', + CURLOPT_RETURNTRANSFER => true, + CURLOPT_ENCODING => '', + CURLOPT_MAXREDIRS => 10, + CURLOPT_TIMEOUT => 30, + CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1, + CURLOPT_CUSTOMREQUEST => 'POST', + CURLOPT_POSTFIELDS => '\' " ` $( #{ %( %{ {{ \\0 %s \\', + CURLOPT_HTTPHEADER => [ + '#: hash-key-test', + '$: dollar-key-test', + '%: percent-key-test', + '\': squote-key-test', + '`: backtick-key-test', + 'backtick-value-test: `', + 'dollar-parenthesis-value-test: $(', + 'double-brace-value-test: {{', + 'dquote-value-test: "', + 'hash-brace-value-test: #{', + 'null-value-test: \\0', + 'percent-brace-value-test: %{', + 'percent-parenthesis-value-test: %(', + 'slash-value-test: \\', + 'squote-value-test: \'', + 'string-fmt-value-test: %s' + ], +]); + +$response = curl_exec($curl); +$err = curl_error($curl); + +curl_close($curl); + +if ($err) { + echo 'cURL Error #:' . $err; +} else { + echo $response; +} \ No newline at end of file diff --git a/test/fixtures/output/php/curl/multipart-data.php b/test/fixtures/output/php/curl/multipart-data.php index d6ce07f..4f91074 100644 --- a/test/fixtures/output/php/curl/multipart-data.php +++ b/test/fixtures/output/php/curl/multipart-data.php @@ -3,16 +3,22 @@ $curl = curl_init(); curl_setopt_array($curl, [ - CURLOPT_URL => "http://mockbin.com/har", + CURLOPT_URL => 'http://mockbin.com/har', CURLOPT_RETURNTRANSFER => true, - CURLOPT_ENCODING => "", + CURLOPT_ENCODING => '', CURLOPT_MAXREDIRS => 10, CURLOPT_TIMEOUT => 30, CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1, - CURLOPT_CUSTOMREQUEST => "POST", - CURLOPT_POSTFIELDS => "-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"foo\"; filename=\"hello.txt\"\r\nContent-Type: text/plain\r\n\r\nHello World\r\n-----011000010111000001101001--\r\n", + CURLOPT_CUSTOMREQUEST => 'POST', + CURLOPT_POSTFIELDS => '-----011000010111000001101001 +Content-Disposition: form-data; name="foo"; filename="hello.txt" +Content-Type: text/plain + +Hello World +-----011000010111000001101001-- +', CURLOPT_HTTPHEADER => [ - "content-type: multipart/form-data; boundary=---011000010111000001101001" + 'content-type: multipart/form-data; boundary=---011000010111000001101001' ], ]); @@ -22,7 +28,7 @@ curl_close($curl); if ($err) { - echo "cURL Error #:" . $err; + echo 'cURL Error #:' . $err; } else { echo $response; } diff --git a/test/fixtures/output/php/curl/multipart-file.php b/test/fixtures/output/php/curl/multipart-file.php index e238b8e..129b9d2 100644 --- a/test/fixtures/output/php/curl/multipart-file.php +++ b/test/fixtures/output/php/curl/multipart-file.php @@ -3,16 +3,22 @@ $curl = curl_init(); curl_setopt_array($curl, [ - CURLOPT_URL => "http://mockbin.com/har", + CURLOPT_URL => 'http://mockbin.com/har', CURLOPT_RETURNTRANSFER => true, - CURLOPT_ENCODING => "", + CURLOPT_ENCODING => '', CURLOPT_MAXREDIRS => 10, CURLOPT_TIMEOUT => 30, CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1, - CURLOPT_CUSTOMREQUEST => "POST", - CURLOPT_POSTFIELDS => "-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"foo\"; filename=\"hello.txt\"\r\nContent-Type: text/plain\r\n\r\n\r\n-----011000010111000001101001--\r\n", + CURLOPT_CUSTOMREQUEST => 'POST', + CURLOPT_POSTFIELDS => '-----011000010111000001101001 +Content-Disposition: form-data; name="foo"; filename="hello.txt" +Content-Type: text/plain + + +-----011000010111000001101001-- +', CURLOPT_HTTPHEADER => [ - "content-type: multipart/form-data; boundary=---011000010111000001101001" + 'content-type: multipart/form-data; boundary=---011000010111000001101001' ], ]); @@ -22,7 +28,7 @@ curl_close($curl); if ($err) { - echo "cURL Error #:" . $err; + echo 'cURL Error #:' . $err; } else { echo $response; } diff --git a/test/fixtures/output/php/curl/multipart-form-data.php b/test/fixtures/output/php/curl/multipart-form-data.php index 038aa49..17e5a9d 100644 --- a/test/fixtures/output/php/curl/multipart-form-data.php +++ b/test/fixtures/output/php/curl/multipart-form-data.php @@ -3,16 +3,21 @@ $curl = curl_init(); curl_setopt_array($curl, [ - CURLOPT_URL => "http://mockbin.com/har", + CURLOPT_URL => 'http://mockbin.com/har', CURLOPT_RETURNTRANSFER => true, - CURLOPT_ENCODING => "", + CURLOPT_ENCODING => '', CURLOPT_MAXREDIRS => 10, CURLOPT_TIMEOUT => 30, CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1, - CURLOPT_CUSTOMREQUEST => "POST", - CURLOPT_POSTFIELDS => "-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"foo\"\r\n\r\nbar\r\n-----011000010111000001101001--\r\n", + CURLOPT_CUSTOMREQUEST => 'POST', + CURLOPT_POSTFIELDS => '-----011000010111000001101001 +Content-Disposition: form-data; name="foo" + +bar +-----011000010111000001101001-- +', CURLOPT_HTTPHEADER => [ - "Content-Type: multipart/form-data; boundary=---011000010111000001101001" + 'Content-Type: multipart/form-data; boundary=---011000010111000001101001' ], ]); @@ -22,7 +27,7 @@ curl_close($curl); if ($err) { - echo "cURL Error #:" . $err; + echo 'cURL Error #:' . $err; } else { echo $response; } diff --git a/test/fixtures/output/php/curl/nested.php b/test/fixtures/output/php/curl/nested.php index 9b345ab..28161a8 100644 --- a/test/fixtures/output/php/curl/nested.php +++ b/test/fixtures/output/php/curl/nested.php @@ -3,13 +3,13 @@ $curl = curl_init(); curl_setopt_array($curl, [ - CURLOPT_URL => "http://mockbin.com/har?foo%5Bbar%5D=baz%2Czap&fiz=buz&key=value", + CURLOPT_URL => 'http://mockbin.com/har?foo%5Bbar%5D=baz%2Czap&fiz=buz&key=value', CURLOPT_RETURNTRANSFER => true, - CURLOPT_ENCODING => "", + CURLOPT_ENCODING => '', CURLOPT_MAXREDIRS => 10, CURLOPT_TIMEOUT => 30, CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1, - CURLOPT_CUSTOMREQUEST => "GET", + CURLOPT_CUSTOMREQUEST => 'GET', ]); $response = curl_exec($curl); @@ -18,7 +18,7 @@ curl_close($curl); if ($err) { - echo "cURL Error #:" . $err; + echo 'cURL Error #:' . $err; } else { echo $response; } diff --git a/test/fixtures/output/php/curl/query.php b/test/fixtures/output/php/curl/query.php index 158e851..a799eb8 100644 --- a/test/fixtures/output/php/curl/query.php +++ b/test/fixtures/output/php/curl/query.php @@ -3,13 +3,13 @@ $curl = curl_init(); curl_setopt_array($curl, [ - CURLOPT_URL => "http://mockbin.com/har?foo=bar&foo=baz&baz=abc&key=value", + CURLOPT_URL => 'http://mockbin.com/har?foo=bar&foo=baz&baz=abc&key=value', CURLOPT_RETURNTRANSFER => true, - CURLOPT_ENCODING => "", + CURLOPT_ENCODING => '', CURLOPT_MAXREDIRS => 10, CURLOPT_TIMEOUT => 30, CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1, - CURLOPT_CUSTOMREQUEST => "GET", + CURLOPT_CUSTOMREQUEST => 'GET', ]); $response = curl_exec($curl); @@ -18,7 +18,7 @@ curl_close($curl); if ($err) { - echo "cURL Error #:" . $err; + echo 'cURL Error #:' . $err; } else { echo $response; } diff --git a/test/fixtures/output/php/curl/short.php b/test/fixtures/output/php/curl/short.php index 9188e25..9f81196 100644 --- a/test/fixtures/output/php/curl/short.php +++ b/test/fixtures/output/php/curl/short.php @@ -3,13 +3,13 @@ $curl = curl_init(); curl_setopt_array($curl, [ - CURLOPT_URL => "http://mockbin.com/har", + CURLOPT_URL => 'http://mockbin.com/har', CURLOPT_RETURNTRANSFER => true, - CURLOPT_ENCODING => "", + CURLOPT_ENCODING => '', CURLOPT_MAXREDIRS => 10, CURLOPT_TIMEOUT => 30, CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1, - CURLOPT_CUSTOMREQUEST => "GET", + CURLOPT_CUSTOMREQUEST => 'GET', ]); $response = curl_exec($curl); @@ -18,7 +18,7 @@ curl_close($curl); if ($err) { - echo "cURL Error #:" . $err; + echo 'cURL Error #:' . $err; } else { echo $response; } diff --git a/test/fixtures/output/php/curl/text-plain.php b/test/fixtures/output/php/curl/text-plain.php index 8fbb09d..999c5c0 100644 --- a/test/fixtures/output/php/curl/text-plain.php +++ b/test/fixtures/output/php/curl/text-plain.php @@ -3,16 +3,16 @@ $curl = curl_init(); curl_setopt_array($curl, [ - CURLOPT_URL => "http://mockbin.com/har", + CURLOPT_URL => 'http://mockbin.com/har', CURLOPT_RETURNTRANSFER => true, - CURLOPT_ENCODING => "", + CURLOPT_ENCODING => '', CURLOPT_MAXREDIRS => 10, CURLOPT_TIMEOUT => 30, CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1, - CURLOPT_CUSTOMREQUEST => "POST", - CURLOPT_POSTFIELDS => "Hello World", + CURLOPT_CUSTOMREQUEST => 'POST', + CURLOPT_POSTFIELDS => 'Hello World', CURLOPT_HTTPHEADER => [ - "content-type: text/plain" + 'content-type: text/plain' ], ]); @@ -22,7 +22,7 @@ curl_close($curl); if ($err) { - echo "cURL Error #:" . $err; + echo 'cURL Error #:' . $err; } else { echo $response; } diff --git a/test/fixtures/output/php/curl/unparseable-query.php b/test/fixtures/output/php/curl/unparseable-query.php new file mode 100644 index 0000000..8108a21 --- /dev/null +++ b/test/fixtures/output/php/curl/unparseable-query.php @@ -0,0 +1,24 @@ + 'http://mockbin.com/har?&&a=b&&', + CURLOPT_RETURNTRANSFER => true, + CURLOPT_ENCODING => '', + CURLOPT_MAXREDIRS => 10, + CURLOPT_TIMEOUT => 30, + CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1, + CURLOPT_CUSTOMREQUEST => 'GET', +]); + +$response = curl_exec($curl); +$err = curl_error($curl); + +curl_close($curl); + +if ($err) { + echo 'cURL Error #:' . $err; +} else { + echo $response; +} \ No newline at end of file diff --git a/test/fixtures/output/php/http1/compression.php b/test/fixtures/output/php/http1/compression.php new file mode 100644 index 0000000..357272c --- /dev/null +++ b/test/fixtures/output/php/http1/compression.php @@ -0,0 +1,17 @@ +setUrl('http://mockbin.com/har'); +$request->setMethod(HTTP_METH_GET); + +$request->setHeaders([ + 'accept-encoding' => 'deflate, gzip, br' +]); + +try { + $response = $request->send(); + + echo $response->getBody(); +} catch (HttpException $ex) { + echo $ex; +} \ No newline at end of file diff --git a/test/fixtures/output/php/http1/headers.php b/test/fixtures/output/php/http1/headers.php index 8f819c7..7c2fa3b 100644 --- a/test/fixtures/output/php/http1/headers.php +++ b/test/fixtures/output/php/http1/headers.php @@ -6,7 +6,8 @@ $request->setHeaders([ 'accept' => 'application/json', - 'x-foo' => 'Bar' + 'x-foo' => 'Bar', + 'quoted-value' => '"quoted" \'string\'' ]); try { diff --git a/test/fixtures/output/php/http1/malicious.php b/test/fixtures/output/php/http1/malicious.php new file mode 100644 index 0000000..99ba255 --- /dev/null +++ b/test/fixtures/output/php/http1/malicious.php @@ -0,0 +1,59 @@ +setUrl('http://example.test/%27%22%60$(%(%%7B%7B%7B/0%s//'); +$request->setMethod(HTTP_METH_POST); + +$request->setQueryData([ + '\'' => 'squote-key-test', + 'squote-value-test' => '\'', + '"' => 'dquote-key-test', + 'dquote-value-test' => '"', + '`' => 'backtick-key-test', + 'backtick-value-test' => '`', + '$(' => 'dollar-parenthesis-key-test', + 'dollar-parenthesis-value-test' => '$(', + '#{' => 'hash-brace-key-test', + 'hash-brace-value-test' => '#{', + '%(' => 'percent-parenthesis-key-test', + 'percent-parenthesis-value-test' => '%(', + '%{' => 'percent-brace-key-test', + 'percent-brace-value-test' => '%{', + '{{' => 'double-brace-key-test', + 'double-brace-value-test' => '{{', + '\\0' => 'null-key-test', + 'null-value-test' => '\\0', + '%s' => 'string-fmt-key-test', + 'string-fmt-value-test' => '%s', + '\\' => 'slash-key-test', + 'slash-value-test' => '\\' +]); + +$request->setHeaders([ + '\'' => 'squote-key-test', + 'squote-value-test' => '\'', + 'dquote-value-test' => '"', + '`' => 'backtick-key-test', + 'backtick-value-test' => '`', + '$' => 'dollar-key-test', + 'dollar-parenthesis-value-test' => '$(', + '#' => 'hash-key-test', + 'hash-brace-value-test' => '#{', + '%' => 'percent-key-test', + 'percent-parenthesis-value-test' => '%(', + 'percent-brace-value-test' => '%{', + 'double-brace-value-test' => '{{', + 'null-value-test' => '\\0', + 'string-fmt-value-test' => '%s', + 'slash-value-test' => '\\' +]); + +$request->setBody('\' " ` $( #{ %( %{ {{ \\0 %s \\'); + +try { + $response = $request->send(); + + echo $response->getBody(); +} catch (HttpException $ex) { + echo $ex; +} \ No newline at end of file diff --git a/test/fixtures/output/php/http1/unparseable-query.php b/test/fixtures/output/php/http1/unparseable-query.php new file mode 100644 index 0000000..200d80d --- /dev/null +++ b/test/fixtures/output/php/http1/unparseable-query.php @@ -0,0 +1,13 @@ +setUrl('http://mockbin.com/har?&&a=b&&'); +$request->setMethod(HTTP_METH_GET); + +try { + $response = $request->send(); + + echo $response->getBody(); +} catch (HttpException $ex) { + echo $ex; +} \ No newline at end of file diff --git a/test/fixtures/output/php/http2/compression.php b/test/fixtures/output/php/http2/compression.php new file mode 100644 index 0000000..d6b15f2 --- /dev/null +++ b/test/fixtures/output/php/http2/compression.php @@ -0,0 +1,15 @@ +setRequestUrl('http://mockbin.com/har'); +$request->setRequestMethod('GET'); +$request->setHeaders([ + 'accept-encoding' => 'deflate, gzip, br' +]); + +$client->enqueue($request)->send(); +$response = $client->getResponse(); + +echo $response->getBody(); \ No newline at end of file diff --git a/test/fixtures/output/php/http2/headers.php b/test/fixtures/output/php/http2/headers.php index 712a027..cfa3688 100644 --- a/test/fixtures/output/php/http2/headers.php +++ b/test/fixtures/output/php/http2/headers.php @@ -7,7 +7,8 @@ $request->setRequestMethod('GET'); $request->setHeaders([ 'accept' => 'application/json', - 'x-foo' => 'Bar' + 'x-foo' => 'Bar', + 'quoted-value' => '"quoted" \'string\'' ]); $client->enqueue($request)->send(); diff --git a/test/fixtures/output/php/http2/malicious.php b/test/fixtures/output/php/http2/malicious.php new file mode 100644 index 0000000..b21bac8 --- /dev/null +++ b/test/fixtures/output/php/http2/malicious.php @@ -0,0 +1,60 @@ +append('\' " ` $( #{ %( %{ {{ \\0 %s \\'); + +$request->setRequestUrl('http://example.test/%27%22%60$(%(%%7B%7B%7B/0%s//'); +$request->setRequestMethod('POST'); +$request->setBody($body); + +$request->setQuery(new http\QueryString([ + '\'' => 'squote-key-test', + 'squote-value-test' => '\'', + '"' => 'dquote-key-test', + 'dquote-value-test' => '"', + '`' => 'backtick-key-test', + 'backtick-value-test' => '`', + '$(' => 'dollar-parenthesis-key-test', + 'dollar-parenthesis-value-test' => '$(', + '#{' => 'hash-brace-key-test', + 'hash-brace-value-test' => '#{', + '%(' => 'percent-parenthesis-key-test', + 'percent-parenthesis-value-test' => '%(', + '%{' => 'percent-brace-key-test', + 'percent-brace-value-test' => '%{', + '{{' => 'double-brace-key-test', + 'double-brace-value-test' => '{{', + '\\0' => 'null-key-test', + 'null-value-test' => '\\0', + '%s' => 'string-fmt-key-test', + 'string-fmt-value-test' => '%s', + '\\' => 'slash-key-test', + 'slash-value-test' => '\\' +])); + +$request->setHeaders([ + '\'' => 'squote-key-test', + 'squote-value-test' => '\'', + 'dquote-value-test' => '"', + '`' => 'backtick-key-test', + 'backtick-value-test' => '`', + '$' => 'dollar-key-test', + 'dollar-parenthesis-value-test' => '$(', + '#' => 'hash-key-test', + 'hash-brace-value-test' => '#{', + '%' => 'percent-key-test', + 'percent-parenthesis-value-test' => '%(', + 'percent-brace-value-test' => '%{', + 'double-brace-value-test' => '{{', + 'null-value-test' => '\\0', + 'string-fmt-value-test' => '%s', + 'slash-value-test' => '\\' +]); + +$client->enqueue($request)->send(); +$response = $client->getResponse(); + +echo $response->getBody(); \ No newline at end of file diff --git a/test/fixtures/output/php/http2/unparseable-query.php b/test/fixtures/output/php/http2/unparseable-query.php new file mode 100644 index 0000000..52bf547 --- /dev/null +++ b/test/fixtures/output/php/http2/unparseable-query.php @@ -0,0 +1,11 @@ +setRequestUrl('http://mockbin.com/har?&&a=b&&'); +$request->setRequestMethod('GET'); +$client->enqueue($request)->send(); +$response = $client->getResponse(); + +echo $response->getBody(); \ No newline at end of file diff --git a/test/fixtures/output/powershell/restmethod/application-form-encoded.ps1 b/test/fixtures/output/powershell/restmethod/application-form-encoded.ps1 index 5cb5452..72ed8e1 100644 --- a/test/fixtures/output/powershell/restmethod/application-form-encoded.ps1 +++ b/test/fixtures/output/powershell/restmethod/application-form-encoded.ps1 @@ -1,3 +1,3 @@ $headers=@{} -$headers.Add("content-type", "application/x-www-form-urlencoded") +$headers.Add('content-type', 'application/x-www-form-urlencoded') $response = Invoke-RestMethod -Uri 'http://mockbin.com/har' -Method POST -Headers $headers -ContentType 'application/x-www-form-urlencoded' -Body 'foo=bar&hello=world' diff --git a/test/fixtures/output/powershell/restmethod/application-json.ps1 b/test/fixtures/output/powershell/restmethod/application-json.ps1 index 326ca27..ccd7418 100644 --- a/test/fixtures/output/powershell/restmethod/application-json.ps1 +++ b/test/fixtures/output/powershell/restmethod/application-json.ps1 @@ -1,3 +1,3 @@ $headers=@{} -$headers.Add("content-type", "application/json") +$headers.Add('content-type', 'application/json') $response = Invoke-RestMethod -Uri 'http://mockbin.com/har' -Method POST -Headers $headers -ContentType 'application/json' -Body '{"number":1,"string":"f\"oo","arr":[1,2,3],"nested":{"a":"b"},"arr_mix":[1,"a",{"arr_mix_nested":{}}],"boolean":false}' diff --git a/test/fixtures/output/powershell/restmethod/compression.ps1 b/test/fixtures/output/powershell/restmethod/compression.ps1 new file mode 100644 index 0000000..f56137d --- /dev/null +++ b/test/fixtures/output/powershell/restmethod/compression.ps1 @@ -0,0 +1,3 @@ +$headers=@{} +$headers.Add('accept-encoding', 'deflate, gzip, br') +$response = Invoke-RestMethod -Uri 'http://mockbin.com/har' -Method GET -Headers $headers \ No newline at end of file diff --git a/test/fixtures/output/powershell/restmethod/custom-method.ps1 b/test/fixtures/output/powershell/restmethod/custom-method.ps1 index 5e5237a..acbd914 100644 --- a/test/fixtures/output/powershell/restmethod/custom-method.ps1 +++ b/test/fixtures/output/powershell/restmethod/custom-method.ps1 @@ -1 +1 @@ -Method not supported +$response = Invoke-RestMethod -Uri 'http://mockbin.com/har' -CustomMethod PROPFIND \ No newline at end of file diff --git a/test/fixtures/output/powershell/restmethod/full.ps1 b/test/fixtures/output/powershell/restmethod/full.ps1 index 1872466..6dc2d29 100644 --- a/test/fixtures/output/powershell/restmethod/full.ps1 +++ b/test/fixtures/output/powershell/restmethod/full.ps1 @@ -1,6 +1,6 @@ $headers=@{} -$headers.Add("accept", "application/json") -$headers.Add("content-type", "application/x-www-form-urlencoded") +$headers.Add('accept', 'application/json') +$headers.Add('content-type', 'application/x-www-form-urlencoded') $session = New-Object Microsoft.PowerShell.Commands.WebRequestSession $cookie = New-Object System.Net.Cookie $cookie.Name = 'foo' diff --git a/test/fixtures/output/powershell/restmethod/headers.ps1 b/test/fixtures/output/powershell/restmethod/headers.ps1 index 7b2d929..ce31cb3 100644 --- a/test/fixtures/output/powershell/restmethod/headers.ps1 +++ b/test/fixtures/output/powershell/restmethod/headers.ps1 @@ -1,4 +1,5 @@ $headers=@{} -$headers.Add("accept", "application/json") -$headers.Add("x-foo", "Bar") +$headers.Add('accept', 'application/json') +$headers.Add('x-foo', 'Bar') +$headers.Add('quoted-value', '"quoted" ''string''') $response = Invoke-RestMethod -Uri 'http://mockbin.com/har' -Method GET -Headers $headers diff --git a/test/fixtures/output/powershell/restmethod/jsonObj-multiline.ps1 b/test/fixtures/output/powershell/restmethod/jsonObj-multiline.ps1 index 3221803..810dc49 100644 --- a/test/fixtures/output/powershell/restmethod/jsonObj-multiline.ps1 +++ b/test/fixtures/output/powershell/restmethod/jsonObj-multiline.ps1 @@ -1,5 +1,5 @@ $headers=@{} -$headers.Add("content-type", "application/json") +$headers.Add('content-type', 'application/json') $response = Invoke-RestMethod -Uri 'http://mockbin.com/har' -Method POST -Headers $headers -ContentType 'application/json' -Body '{ "foo": "bar" }' diff --git a/test/fixtures/output/powershell/restmethod/jsonObj-null-value.ps1 b/test/fixtures/output/powershell/restmethod/jsonObj-null-value.ps1 index 68c52ea..7593e66 100644 --- a/test/fixtures/output/powershell/restmethod/jsonObj-null-value.ps1 +++ b/test/fixtures/output/powershell/restmethod/jsonObj-null-value.ps1 @@ -1,3 +1,3 @@ $headers=@{} -$headers.Add("content-type", "application/json") +$headers.Add('content-type', 'application/json') $response = Invoke-RestMethod -Uri 'http://mockbin.com/har' -Method POST -Headers $headers -ContentType 'application/json' -Body '{"foo":null}' diff --git a/test/fixtures/output/powershell/restmethod/malicious.ps1 b/test/fixtures/output/powershell/restmethod/malicious.ps1 new file mode 100644 index 0000000..1ede1d0 --- /dev/null +++ b/test/fixtures/output/powershell/restmethod/malicious.ps1 @@ -0,0 +1,18 @@ +$headers=@{} +$headers.Add('''', 'squote-key-test') +$headers.Add('squote-value-test', '''') +$headers.Add('dquote-value-test', '"') +$headers.Add('`', 'backtick-key-test') +$headers.Add('backtick-value-test', '`') +$headers.Add('$', 'dollar-key-test') +$headers.Add('dollar-parenthesis-value-test', '$(') +$headers.Add('#', 'hash-key-test') +$headers.Add('hash-brace-value-test', '#{') +$headers.Add('%', 'percent-key-test') +$headers.Add('percent-parenthesis-value-test', '%(') +$headers.Add('percent-brace-value-test', '%{') +$headers.Add('double-brace-value-test', '{{') +$headers.Add('null-value-test', '\0') +$headers.Add('string-fmt-value-test', '%s') +$headers.Add('slash-value-test', '\') +$response = Invoke-RestMethod -Uri 'http://example.test/%27%22%60$(%(%%7B%7B%7B/0%s//?''=squote-key-test&squote-value-test=''&%22=dquote-key-test&dquote-value-test=%22&%60=backtick-key-test&backtick-value-test=%60&%24(=dollar-parenthesis-key-test&dollar-parenthesis-value-test=%24(&%23%7B=hash-brace-key-test&hash-brace-value-test=%23%7B&%25(=percent-parenthesis-key-test&percent-parenthesis-value-test=%25(&%25%7B=percent-brace-key-test&percent-brace-value-test=%25%7B&%7B%7B=double-brace-key-test&double-brace-value-test=%7B%7B&%5C0=null-key-test&null-value-test=%5C0&%25s=string-fmt-key-test&string-fmt-value-test=%25s&%5C=slash-key-test&slash-value-test=%5C' -Method POST -Headers $headers -Body ''' " ` $( #{ %( %{ {{ \0 %s \' \ No newline at end of file diff --git a/test/fixtures/output/powershell/restmethod/multipart-data.ps1 b/test/fixtures/output/powershell/restmethod/multipart-data.ps1 index 9324af5..c98b409 100644 --- a/test/fixtures/output/powershell/restmethod/multipart-data.ps1 +++ b/test/fixtures/output/powershell/restmethod/multipart-data.ps1 @@ -1,5 +1,5 @@ $headers=@{} -$headers.Add("content-type", "multipart/form-data; boundary=---011000010111000001101001") +$headers.Add('content-type', 'multipart/form-data; boundary=---011000010111000001101001') $response = Invoke-RestMethod -Uri 'http://mockbin.com/har' -Method POST -Headers $headers -ContentType 'multipart/form-data; boundary=---011000010111000001101001' -Body '-----011000010111000001101001 Content-Disposition: form-data; name="foo"; filename="hello.txt" Content-Type: text/plain diff --git a/test/fixtures/output/powershell/restmethod/multipart-file.ps1 b/test/fixtures/output/powershell/restmethod/multipart-file.ps1 index e1329cb..9a60551 100644 --- a/test/fixtures/output/powershell/restmethod/multipart-file.ps1 +++ b/test/fixtures/output/powershell/restmethod/multipart-file.ps1 @@ -1,5 +1,5 @@ $headers=@{} -$headers.Add("content-type", "multipart/form-data; boundary=---011000010111000001101001") +$headers.Add('content-type', 'multipart/form-data; boundary=---011000010111000001101001') $response = Invoke-RestMethod -Uri 'http://mockbin.com/har' -Method POST -Headers $headers -ContentType 'multipart/form-data; boundary=---011000010111000001101001' -Body '-----011000010111000001101001 Content-Disposition: form-data; name="foo"; filename="hello.txt" Content-Type: text/plain diff --git a/test/fixtures/output/powershell/restmethod/multipart-form-data.ps1 b/test/fixtures/output/powershell/restmethod/multipart-form-data.ps1 index bb78bfb..f48c03e 100644 --- a/test/fixtures/output/powershell/restmethod/multipart-form-data.ps1 +++ b/test/fixtures/output/powershell/restmethod/multipart-form-data.ps1 @@ -1,5 +1,5 @@ $headers=@{} -$headers.Add("Content-Type", "multipart/form-data; boundary=---011000010111000001101001") +$headers.Add('Content-Type', 'multipart/form-data; boundary=---011000010111000001101001') $response = Invoke-RestMethod -Uri 'http://mockbin.com/har' -Method POST -Headers $headers -ContentType 'multipart/form-data; boundary=---011000010111000001101001' -Body '-----011000010111000001101001 Content-Disposition: form-data; name="foo" diff --git a/test/fixtures/output/powershell/restmethod/text-plain.ps1 b/test/fixtures/output/powershell/restmethod/text-plain.ps1 index ccfdf49..5cf7d20 100644 --- a/test/fixtures/output/powershell/restmethod/text-plain.ps1 +++ b/test/fixtures/output/powershell/restmethod/text-plain.ps1 @@ -1,3 +1,3 @@ $headers=@{} -$headers.Add("content-type", "text/plain") +$headers.Add('content-type', 'text/plain') $response = Invoke-RestMethod -Uri 'http://mockbin.com/har' -Method POST -Headers $headers -ContentType 'text/plain' -Body 'Hello World' diff --git a/test/fixtures/output/powershell/restmethod/unparseable-query.ps1 b/test/fixtures/output/powershell/restmethod/unparseable-query.ps1 new file mode 100644 index 0000000..8ca0208 --- /dev/null +++ b/test/fixtures/output/powershell/restmethod/unparseable-query.ps1 @@ -0,0 +1 @@ +$response = Invoke-RestMethod -Uri 'http://mockbin.com/har?&&a=b&&' -Method GET \ No newline at end of file diff --git a/test/fixtures/output/powershell/webrequest/application-form-encoded.ps1 b/test/fixtures/output/powershell/webrequest/application-form-encoded.ps1 index 9ea45de..cd01c2b 100644 --- a/test/fixtures/output/powershell/webrequest/application-form-encoded.ps1 +++ b/test/fixtures/output/powershell/webrequest/application-form-encoded.ps1 @@ -1,3 +1,3 @@ $headers=@{} -$headers.Add("content-type", "application/x-www-form-urlencoded") +$headers.Add('content-type', 'application/x-www-form-urlencoded') $response = Invoke-WebRequest -Uri 'http://mockbin.com/har' -Method POST -Headers $headers -ContentType 'application/x-www-form-urlencoded' -Body 'foo=bar&hello=world' diff --git a/test/fixtures/output/powershell/webrequest/application-json.ps1 b/test/fixtures/output/powershell/webrequest/application-json.ps1 index 786292d..024d331 100644 --- a/test/fixtures/output/powershell/webrequest/application-json.ps1 +++ b/test/fixtures/output/powershell/webrequest/application-json.ps1 @@ -1,3 +1,3 @@ $headers=@{} -$headers.Add("content-type", "application/json") +$headers.Add('content-type', 'application/json') $response = Invoke-WebRequest -Uri 'http://mockbin.com/har' -Method POST -Headers $headers -ContentType 'application/json' -Body '{"number":1,"string":"f\"oo","arr":[1,2,3],"nested":{"a":"b"},"arr_mix":[1,"a",{"arr_mix_nested":{}}],"boolean":false}' diff --git a/test/fixtures/output/powershell/webrequest/compression.ps1 b/test/fixtures/output/powershell/webrequest/compression.ps1 new file mode 100644 index 0000000..4cdbf72 --- /dev/null +++ b/test/fixtures/output/powershell/webrequest/compression.ps1 @@ -0,0 +1,3 @@ +$headers=@{} +$headers.Add('accept-encoding', 'deflate, gzip, br') +$response = Invoke-WebRequest -Uri 'http://mockbin.com/har' -Method GET -Headers $headers \ No newline at end of file diff --git a/test/fixtures/output/powershell/webrequest/custom-method.ps1 b/test/fixtures/output/powershell/webrequest/custom-method.ps1 index 5e5237a..5f587e4 100644 --- a/test/fixtures/output/powershell/webrequest/custom-method.ps1 +++ b/test/fixtures/output/powershell/webrequest/custom-method.ps1 @@ -1 +1 @@ -Method not supported +$response = Invoke-WebRequest -Uri 'http://mockbin.com/har' -CustomMethod PROPFIND \ No newline at end of file diff --git a/test/fixtures/output/powershell/webrequest/full.ps1 b/test/fixtures/output/powershell/webrequest/full.ps1 index 42e308f..5e22949 100644 --- a/test/fixtures/output/powershell/webrequest/full.ps1 +++ b/test/fixtures/output/powershell/webrequest/full.ps1 @@ -1,6 +1,6 @@ $headers=@{} -$headers.Add("accept", "application/json") -$headers.Add("content-type", "application/x-www-form-urlencoded") +$headers.Add('accept', 'application/json') +$headers.Add('content-type', 'application/x-www-form-urlencoded') $session = New-Object Microsoft.PowerShell.Commands.WebRequestSession $cookie = New-Object System.Net.Cookie $cookie.Name = 'foo' diff --git a/test/fixtures/output/powershell/webrequest/headers.ps1 b/test/fixtures/output/powershell/webrequest/headers.ps1 index a6a817e..d23512b 100644 --- a/test/fixtures/output/powershell/webrequest/headers.ps1 +++ b/test/fixtures/output/powershell/webrequest/headers.ps1 @@ -1,4 +1,5 @@ $headers=@{} -$headers.Add("accept", "application/json") -$headers.Add("x-foo", "Bar") +$headers.Add('accept', 'application/json') +$headers.Add('x-foo', 'Bar') +$headers.Add('quoted-value', '"quoted" ''string''') $response = Invoke-WebRequest -Uri 'http://mockbin.com/har' -Method GET -Headers $headers diff --git a/test/fixtures/output/powershell/webrequest/jsonObj-multiline.ps1 b/test/fixtures/output/powershell/webrequest/jsonObj-multiline.ps1 index 6548f20..4ed84da 100644 --- a/test/fixtures/output/powershell/webrequest/jsonObj-multiline.ps1 +++ b/test/fixtures/output/powershell/webrequest/jsonObj-multiline.ps1 @@ -1,5 +1,5 @@ $headers=@{} -$headers.Add("content-type", "application/json") +$headers.Add('content-type', 'application/json') $response = Invoke-WebRequest -Uri 'http://mockbin.com/har' -Method POST -Headers $headers -ContentType 'application/json' -Body '{ "foo": "bar" }' diff --git a/test/fixtures/output/powershell/webrequest/jsonObj-null-value.ps1 b/test/fixtures/output/powershell/webrequest/jsonObj-null-value.ps1 index 1ee9a4f..3be77fa 100644 --- a/test/fixtures/output/powershell/webrequest/jsonObj-null-value.ps1 +++ b/test/fixtures/output/powershell/webrequest/jsonObj-null-value.ps1 @@ -1,3 +1,3 @@ $headers=@{} -$headers.Add("content-type", "application/json") +$headers.Add('content-type', 'application/json') $response = Invoke-WebRequest -Uri 'http://mockbin.com/har' -Method POST -Headers $headers -ContentType 'application/json' -Body '{"foo":null}' diff --git a/test/fixtures/output/powershell/webrequest/malicious.ps1 b/test/fixtures/output/powershell/webrequest/malicious.ps1 new file mode 100644 index 0000000..026ffb0 --- /dev/null +++ b/test/fixtures/output/powershell/webrequest/malicious.ps1 @@ -0,0 +1,18 @@ +$headers=@{} +$headers.Add('''', 'squote-key-test') +$headers.Add('squote-value-test', '''') +$headers.Add('dquote-value-test', '"') +$headers.Add('`', 'backtick-key-test') +$headers.Add('backtick-value-test', '`') +$headers.Add('$', 'dollar-key-test') +$headers.Add('dollar-parenthesis-value-test', '$(') +$headers.Add('#', 'hash-key-test') +$headers.Add('hash-brace-value-test', '#{') +$headers.Add('%', 'percent-key-test') +$headers.Add('percent-parenthesis-value-test', '%(') +$headers.Add('percent-brace-value-test', '%{') +$headers.Add('double-brace-value-test', '{{') +$headers.Add('null-value-test', '\0') +$headers.Add('string-fmt-value-test', '%s') +$headers.Add('slash-value-test', '\') +$response = Invoke-WebRequest -Uri 'http://example.test/%27%22%60$(%(%%7B%7B%7B/0%s//?''=squote-key-test&squote-value-test=''&%22=dquote-key-test&dquote-value-test=%22&%60=backtick-key-test&backtick-value-test=%60&%24(=dollar-parenthesis-key-test&dollar-parenthesis-value-test=%24(&%23%7B=hash-brace-key-test&hash-brace-value-test=%23%7B&%25(=percent-parenthesis-key-test&percent-parenthesis-value-test=%25(&%25%7B=percent-brace-key-test&percent-brace-value-test=%25%7B&%7B%7B=double-brace-key-test&double-brace-value-test=%7B%7B&%5C0=null-key-test&null-value-test=%5C0&%25s=string-fmt-key-test&string-fmt-value-test=%25s&%5C=slash-key-test&slash-value-test=%5C' -Method POST -Headers $headers -Body ''' " ` $( #{ %( %{ {{ \0 %s \' \ No newline at end of file diff --git a/test/fixtures/output/powershell/webrequest/multipart-data.ps1 b/test/fixtures/output/powershell/webrequest/multipart-data.ps1 index 64a05c8..e483ba0 100644 --- a/test/fixtures/output/powershell/webrequest/multipart-data.ps1 +++ b/test/fixtures/output/powershell/webrequest/multipart-data.ps1 @@ -1,5 +1,5 @@ $headers=@{} -$headers.Add("content-type", "multipart/form-data; boundary=---011000010111000001101001") +$headers.Add('content-type', 'multipart/form-data; boundary=---011000010111000001101001') $response = Invoke-WebRequest -Uri 'http://mockbin.com/har' -Method POST -Headers $headers -ContentType 'multipart/form-data; boundary=---011000010111000001101001' -Body '-----011000010111000001101001 Content-Disposition: form-data; name="foo"; filename="hello.txt" Content-Type: text/plain diff --git a/test/fixtures/output/powershell/webrequest/multipart-file.ps1 b/test/fixtures/output/powershell/webrequest/multipart-file.ps1 index c1dc54b..7c6bfd1 100644 --- a/test/fixtures/output/powershell/webrequest/multipart-file.ps1 +++ b/test/fixtures/output/powershell/webrequest/multipart-file.ps1 @@ -1,5 +1,5 @@ $headers=@{} -$headers.Add("content-type", "multipart/form-data; boundary=---011000010111000001101001") +$headers.Add('content-type', 'multipart/form-data; boundary=---011000010111000001101001') $response = Invoke-WebRequest -Uri 'http://mockbin.com/har' -Method POST -Headers $headers -ContentType 'multipart/form-data; boundary=---011000010111000001101001' -Body '-----011000010111000001101001 Content-Disposition: form-data; name="foo"; filename="hello.txt" Content-Type: text/plain diff --git a/test/fixtures/output/powershell/webrequest/multipart-form-data.ps1 b/test/fixtures/output/powershell/webrequest/multipart-form-data.ps1 index 91f16b8..92b1a25 100644 --- a/test/fixtures/output/powershell/webrequest/multipart-form-data.ps1 +++ b/test/fixtures/output/powershell/webrequest/multipart-form-data.ps1 @@ -1,5 +1,5 @@ $headers=@{} -$headers.Add("Content-Type", "multipart/form-data; boundary=---011000010111000001101001") +$headers.Add('Content-Type', 'multipart/form-data; boundary=---011000010111000001101001') $response = Invoke-WebRequest -Uri 'http://mockbin.com/har' -Method POST -Headers $headers -ContentType 'multipart/form-data; boundary=---011000010111000001101001' -Body '-----011000010111000001101001 Content-Disposition: form-data; name="foo" diff --git a/test/fixtures/output/powershell/webrequest/text-plain.ps1 b/test/fixtures/output/powershell/webrequest/text-plain.ps1 index 876683a..f095d4b 100644 --- a/test/fixtures/output/powershell/webrequest/text-plain.ps1 +++ b/test/fixtures/output/powershell/webrequest/text-plain.ps1 @@ -1,3 +1,3 @@ $headers=@{} -$headers.Add("content-type", "text/plain") +$headers.Add('content-type', 'text/plain') $response = Invoke-WebRequest -Uri 'http://mockbin.com/har' -Method POST -Headers $headers -ContentType 'text/plain' -Body 'Hello World' diff --git a/test/fixtures/output/powershell/webrequest/unparseable-query.ps1 b/test/fixtures/output/powershell/webrequest/unparseable-query.ps1 new file mode 100644 index 0000000..19bd44b --- /dev/null +++ b/test/fixtures/output/powershell/webrequest/unparseable-query.ps1 @@ -0,0 +1 @@ +$response = Invoke-WebRequest -Uri 'http://mockbin.com/har?&&a=b&&' -Method GET \ No newline at end of file diff --git a/test/fixtures/output/python/python3/compression.py b/test/fixtures/output/python/python3/compression.py new file mode 100644 index 0000000..a3bc5e3 --- /dev/null +++ b/test/fixtures/output/python/python3/compression.py @@ -0,0 +1,16 @@ +import http.client +import gzip + +conn = http.client.HTTPConnection("mockbin.com") + +headers = { "accept-encoding": "deflate, gzip, br" } + +conn.request("GET", "/har", headers=headers) + +res = conn.getresponse() +data = res.read() + +if res.headers['content-encoding'] == 'gzip': + print(gzip.decompress(data).decode("utf-8")) +else: + print(data.decode("utf-8")) \ No newline at end of file diff --git a/test/fixtures/output/python/python3/content-encoding-gzip.py b/test/fixtures/output/python/python3/content-encoding-gzip.py new file mode 100644 index 0000000..7273599 --- /dev/null +++ b/test/fixtures/output/python/python3/content-encoding-gzip.py @@ -0,0 +1,16 @@ +import http.client +import gzip + +conn = http.client.HTTPConnection("mockbin.com") + +headers = { "accept-encoding": "gzip" } + +conn.request("GET", "/har", headers=headers) + +res = conn.getresponse() +data = res.read() + +if res.headers['content-encoding'] == 'gzip': + print(gzip.decompress(data).decode("utf-8")) +else: + print(data.decode("utf-8")) diff --git a/test/fixtures/output/python/python3/full.py b/test/fixtures/output/python/python3/full.py index 75131d7..38c2dbb 100644 --- a/test/fixtures/output/python/python3/full.py +++ b/test/fixtures/output/python/python3/full.py @@ -8,7 +8,7 @@ "cookie": "foo=bar; bar=baz", "accept": "application/json", "content-type": "application/x-www-form-urlencoded" - } +} conn.request("POST", "/har?foo=bar&foo=baz&baz=abc&key=value", payload, headers) diff --git a/test/fixtures/output/python/python3/headers.py b/test/fixtures/output/python/python3/headers.py index 6de1d8a..60182d7 100644 --- a/test/fixtures/output/python/python3/headers.py +++ b/test/fixtures/output/python/python3/headers.py @@ -4,8 +4,9 @@ headers = { "accept": "application/json", - "x-foo": "Bar" - } + "x-foo": "Bar", + "quoted-value": "\"quoted\" 'string'" +} conn.request("GET", "/har", headers=headers) diff --git a/test/fixtures/output/python/python3/malicious.py b/test/fixtures/output/python/python3/malicious.py new file mode 100644 index 0000000..9d5ecd8 --- /dev/null +++ b/test/fixtures/output/python/python3/malicious.py @@ -0,0 +1,31 @@ +import http.client + +conn = http.client.HTTPConnection("example.test") + +payload = "' \" ` $( #{ %( %{ {{ \\0 %s \\" + +headers = { + "'": "squote-key-test", + "squote-value-test": "'", + "dquote-value-test": "\"", + "`": "backtick-key-test", + "backtick-value-test": "`", + "$": "dollar-key-test", + "dollar-parenthesis-value-test": "$(", + "#": "hash-key-test", + "hash-brace-value-test": "#{", + "%": "percent-key-test", + "percent-parenthesis-value-test": "%(", + "percent-brace-value-test": "%{", + "double-brace-value-test": "{{", + "null-value-test": "\\0", + "string-fmt-value-test": "%s", + "slash-value-test": "\\" +} + +conn.request("POST", "/%27%22%60$(%(%%7B%7B%7B/0%s//?'=squote-key-test&squote-value-test='&%22=dquote-key-test&dquote-value-test=%22&%60=backtick-key-test&backtick-value-test=%60&%24(=dollar-parenthesis-key-test&dollar-parenthesis-value-test=%24(&%23%7B=hash-brace-key-test&hash-brace-value-test=%23%7B&%25(=percent-parenthesis-key-test&percent-parenthesis-value-test=%25(&%25%7B=percent-brace-key-test&percent-brace-value-test=%25%7B&%7B%7B=double-brace-key-test&double-brace-value-test=%7B%7B&%5C0=null-key-test&null-value-test=%5C0&%25s=string-fmt-key-test&string-fmt-value-test=%25s&%5C=slash-key-test&slash-value-test=%5C", payload, headers) + +res = conn.getresponse() +data = res.read() + +print(data.decode("utf-8")) \ No newline at end of file diff --git a/test/fixtures/output/python/python3/unparseable-query.py b/test/fixtures/output/python/python3/unparseable-query.py new file mode 100644 index 0000000..4a74ee4 --- /dev/null +++ b/test/fixtures/output/python/python3/unparseable-query.py @@ -0,0 +1,10 @@ +import http.client + +conn = http.client.HTTPConnection("mockbin.com") + +conn.request("GET", "/har?&&a=b&&") + +res = conn.getresponse() +data = res.read() + +print(data.decode("utf-8")) \ No newline at end of file diff --git a/test/fixtures/output/python/requests/compression.py b/test/fixtures/output/python/requests/compression.py new file mode 100644 index 0000000..9461c17 --- /dev/null +++ b/test/fixtures/output/python/requests/compression.py @@ -0,0 +1,9 @@ +import requests + +url = "http://mockbin.com/har" + +headers = { "accept-encoding": "deflate, gzip, br" } + +response = requests.get(url, headers=headers) + +print(response.text) \ No newline at end of file diff --git a/test/fixtures/output/python/requests/headers.py b/test/fixtures/output/python/requests/headers.py index 8da4089..d2e3b3f 100644 --- a/test/fixtures/output/python/requests/headers.py +++ b/test/fixtures/output/python/requests/headers.py @@ -4,7 +4,8 @@ headers = { "accept": "application/json", - "x-foo": "Bar" + "x-foo": "Bar", + "quoted-value": "\"quoted\" 'string'" } response = requests.get(url, headers=headers) diff --git a/test/fixtures/output/python/requests/malicious.py b/test/fixtures/output/python/requests/malicious.py new file mode 100644 index 0000000..14eb9dd --- /dev/null +++ b/test/fixtures/output/python/requests/malicious.py @@ -0,0 +1,52 @@ +import requests + +url = "http://example.test/%27%22%60$(%(%%7B%7B%7B/0%s//" + +querystring = { + "'": "squote-key-test", + "squote-value-test": "'", + "\"": "dquote-key-test", + "dquote-value-test": "\"", + "`": "backtick-key-test", + "backtick-value-test": "`", + "$(": "dollar-parenthesis-key-test", + "dollar-parenthesis-value-test": "$(", + "#{": "hash-brace-key-test", + "hash-brace-value-test": "#{", + "%(": "percent-parenthesis-key-test", + "percent-parenthesis-value-test": "%(", + "%{": "percent-brace-key-test", + "percent-brace-value-test": "%{", + "{{": "double-brace-key-test", + "double-brace-value-test": "{{", + "\\0": "null-key-test", + "null-value-test": "\\0", + "%s": "string-fmt-key-test", + "string-fmt-value-test": "%s", + "\\": "slash-key-test", + "slash-value-test": "\\" +} + +payload = "' \" ` $( #{ %( %{ {{ \\0 %s \\" +headers = { + "'": "squote-key-test", + "squote-value-test": "'", + "dquote-value-test": "\"", + "`": "backtick-key-test", + "backtick-value-test": "`", + "$": "dollar-key-test", + "dollar-parenthesis-value-test": "$(", + "#": "hash-key-test", + "hash-brace-value-test": "#{", + "%": "percent-key-test", + "percent-parenthesis-value-test": "%(", + "percent-brace-value-test": "%{", + "double-brace-value-test": "{{", + "null-value-test": "\\0", + "string-fmt-value-test": "%s", + "slash-value-test": "\\" +} + +response = requests.post(url, data=payload, headers=headers, params=querystring) + +print(response.text) \ No newline at end of file diff --git a/test/fixtures/output/python/requests/unparseable-query.py b/test/fixtures/output/python/requests/unparseable-query.py new file mode 100644 index 0000000..af5d7bd --- /dev/null +++ b/test/fixtures/output/python/requests/unparseable-query.py @@ -0,0 +1,7 @@ +import requests + +url = "http://mockbin.com/har?&&a=b&&" + +response = requests.get(url) + +print(response.text) \ No newline at end of file diff --git a/test/fixtures/output/r/httr/compression.r b/test/fixtures/output/r/httr/compression.r new file mode 100644 index 0000000..60df700 --- /dev/null +++ b/test/fixtures/output/r/httr/compression.r @@ -0,0 +1,7 @@ +library(httr) + +url <- "http://mockbin.com/har" + +response <- VERB("GET", url, add_headers(accept_encoding = 'deflate, gzip, br'), content_type("application/octet-stream")) + +content(response, "text") \ No newline at end of file diff --git a/test/fixtures/output/r/httr/headers.r b/test/fixtures/output/r/httr/headers.r index 26a20cb..2694465 100644 --- a/test/fixtures/output/r/httr/headers.r +++ b/test/fixtures/output/r/httr/headers.r @@ -2,6 +2,6 @@ library(httr) url <- "http://mockbin.com/har" -response <- VERB("GET", url, add_headers(x_foo = 'Bar'), content_type("application/octet-stream"), accept("application/json")) +response <- VERB("GET", url, add_headers(x_foo = 'Bar', quoted_value = '"quoted" \'string\''), content_type("application/octet-stream"), accept("application/json")) content(response, "text") diff --git a/test/fixtures/output/r/httr/malicious.r b/test/fixtures/output/r/httr/malicious.r new file mode 100644 index 0000000..ac36ea6 --- /dev/null +++ b/test/fixtures/output/r/httr/malicious.r @@ -0,0 +1,36 @@ +library(httr) + +url <- "http://example.test/%27%22%60$(%(%%7B%7B%7B/0%s//" + +queryString <- list( + "'" = "squote-key-test", + "squote-value-test" = "'", + "\"" = "dquote-key-test", + "dquote-value-test" = "\"", + "`" = "backtick-key-test", + "backtick-value-test" = "`", + "$(" = "dollar-parenthesis-key-test", + "dollar-parenthesis-value-test" = "$(", + "#{" = "hash-brace-key-test", + "hash-brace-value-test" = "#{", + "%(" = "percent-parenthesis-key-test", + "percent-parenthesis-value-test" = "%(", + "%{" = "percent-brace-key-test", + "percent-brace-value-test" = "%{", + "{{" = "double-brace-key-test", + "double-brace-value-test" = "{{", + "\\0" = "null-key-test", + "null-value-test" = "\\0", + "%s" = "string-fmt-key-test", + "string-fmt-value-test" = "%s", + "\\" = "slash-key-test" + "slash-value-test" = "\\", +) + +payload <- "' \" ` $( #{ %( %{ {{ \\0 %s \\" + +encode <- "raw" + +response <- VERB("POST", url, body = payload, query = queryString, add_headers("'" = 'squote-key-test', squote_value_test = '\'', dquote_value_test = '"', "`" = 'backtick-key-test', backtick_value_test = '`', "$" = 'dollar-key-test', dollar_parenthesis_value_test = '$(', "#" = 'hash-key-test', hash_brace_value_test = '#{', "%" = 'percent-key-test', percent_parenthesis_value_test = '%(', percent_brace_value_test = '%{', double_brace_value_test = '{{', null_value_test = '\\0', string_fmt_value_test = '%s', slash_value_test = '\\'), content_type("text/plain"), encode = encode) + +content(response, "text") \ No newline at end of file diff --git a/test/fixtures/output/r/httr/nested.r b/test/fixtures/output/r/httr/nested.r index 669352c..07aa1a1 100644 --- a/test/fixtures/output/r/httr/nested.r +++ b/test/fixtures/output/r/httr/nested.r @@ -3,7 +3,7 @@ library(httr) url <- "http://mockbin.com/har" queryString <- list( - foo[bar] = "baz,zap", + "foo[bar]" = "baz,zap", fiz = "buz" ) diff --git a/test/fixtures/output/r/httr/unparseable-query.r b/test/fixtures/output/r/httr/unparseable-query.r new file mode 100644 index 0000000..b39a545 --- /dev/null +++ b/test/fixtures/output/r/httr/unparseable-query.r @@ -0,0 +1,7 @@ +library(httr) + +url <- "http://mockbin.com/har?&&a=b&&" + +response <- VERB("GET", url, content_type("application/octet-stream")) + +content(response, "text") \ No newline at end of file diff --git a/test/fixtures/output/ruby/faraday/application-form-encoded.rb b/test/fixtures/output/ruby/faraday/application-form-encoded.rb new file mode 100644 index 0000000..9f15c8a --- /dev/null +++ b/test/fixtures/output/ruby/faraday/application-form-encoded.rb @@ -0,0 +1,18 @@ +require 'faraday' + +data = { + :foo => "bar", + :hello => "world", +} + +conn = Faraday.new( + url: 'http://mockbin.com', + headers: {'Content-Type' => 'application/x-www-form-urlencoded'} +) + +response = conn.post('/har') do |req| + req.body = URI.encode_www_form(data) +end + +puts response.status +puts response.body \ No newline at end of file diff --git a/test/fixtures/output/ruby/faraday/application-json.rb b/test/fixtures/output/ruby/faraday/application-json.rb new file mode 100644 index 0000000..2c22a0e --- /dev/null +++ b/test/fixtures/output/ruby/faraday/application-json.rb @@ -0,0 +1,13 @@ +require 'faraday' + +conn = Faraday.new( + url: 'http://mockbin.com', + headers: {'Content-Type' => 'application/json'} +) + +response = conn.post('/har') do |req| + req.body = "{\"number\":1,\"string\":\"f\\\"oo\",\"arr\":[1,2,3],\"nested\":{\"a\":\"b\"},\"arr_mix\":[1,\"a\",{\"arr_mix_nested\":{}}],\"boolean\":false}" +end + +puts response.status +puts response.body \ No newline at end of file diff --git a/test/fixtures/output/ruby/faraday/compression.rb b/test/fixtures/output/ruby/faraday/compression.rb new file mode 100644 index 0000000..4c0f30b --- /dev/null +++ b/test/fixtures/output/ruby/faraday/compression.rb @@ -0,0 +1,12 @@ +require 'faraday' + +conn = Faraday.new( + url: 'http://mockbin.com', +) + +response = conn.get('/har') do |req| + req.headers['accept-encoding'] = 'deflate, gzip, br' +end + +puts response.status +puts response.body \ No newline at end of file diff --git a/test/fixtures/output/ruby/faraday/cookies.rb b/test/fixtures/output/ruby/faraday/cookies.rb new file mode 100644 index 0000000..5c884d7 --- /dev/null +++ b/test/fixtures/output/ruby/faraday/cookies.rb @@ -0,0 +1,12 @@ +require 'faraday' + +conn = Faraday.new( + url: 'http://mockbin.com', +) + +response = conn.post('/har') do |req| + req.headers['cookie'] = 'foo=bar; bar=baz' +end + +puts response.status +puts response.body \ No newline at end of file diff --git a/test/fixtures/output/ruby/faraday/custom-method.rb b/test/fixtures/output/ruby/faraday/custom-method.rb new file mode 100644 index 0000000..213ada5 --- /dev/null +++ b/test/fixtures/output/ruby/faraday/custom-method.rb @@ -0,0 +1 @@ +# Faraday cannot currently run PROPFIND requests. Please use another client. \ No newline at end of file diff --git a/test/fixtures/output/ruby/faraday/full.rb b/test/fixtures/output/ruby/faraday/full.rb new file mode 100644 index 0000000..00cf3c6 --- /dev/null +++ b/test/fixtures/output/ruby/faraday/full.rb @@ -0,0 +1,22 @@ +require 'faraday' + +data = { + :foo => "bar", +} + +conn = Faraday.new( + url: 'http://mockbin.com', + headers: {'Content-Type' => 'application/x-www-form-urlencoded'} +) + +response = conn.post('/har') do |req| + req.headers['cookie'] = 'foo=bar; bar=baz' + req.headers['accept'] = 'application/json' + req.params['foo'] = ["bar","baz"] + req.params['baz'] = 'abc' + req.params['key'] = 'value' + req.body = URI.encode_www_form(data) +end + +puts response.status +puts response.body \ No newline at end of file diff --git a/test/fixtures/output/ruby/faraday/headers.rb b/test/fixtures/output/ruby/faraday/headers.rb new file mode 100644 index 0000000..efaaa37 --- /dev/null +++ b/test/fixtures/output/ruby/faraday/headers.rb @@ -0,0 +1,14 @@ +require 'faraday' + +conn = Faraday.new( + url: 'http://mockbin.com', +) + +response = conn.get('/har') do |req| + req.headers['accept'] = 'application/json' + req.headers['x-foo'] = 'Bar' + req.headers['quoted-value'] = '"quoted" \'string\'' +end + +puts response.status +puts response.body \ No newline at end of file diff --git a/test/fixtures/output/ruby/faraday/https.rb b/test/fixtures/output/ruby/faraday/https.rb new file mode 100644 index 0000000..8416136 --- /dev/null +++ b/test/fixtures/output/ruby/faraday/https.rb @@ -0,0 +1,11 @@ +require 'faraday' + +conn = Faraday.new( + url: 'https://mockbin.com', +) + +response = conn.get('/har') do |req| +end + +puts response.status +puts response.body \ No newline at end of file diff --git a/test/fixtures/output/ruby/faraday/jsonObj-multiline.rb b/test/fixtures/output/ruby/faraday/jsonObj-multiline.rb new file mode 100644 index 0000000..e6e66b0 --- /dev/null +++ b/test/fixtures/output/ruby/faraday/jsonObj-multiline.rb @@ -0,0 +1,13 @@ +require 'faraday' + +conn = Faraday.new( + url: 'http://mockbin.com', + headers: {'Content-Type' => 'application/json'} +) + +response = conn.post('/har') do |req| + req.body = "{\n \"foo\": \"bar\"\n}" +end + +puts response.status +puts response.body \ No newline at end of file diff --git a/test/fixtures/output/ruby/faraday/jsonObj-null-value.rb b/test/fixtures/output/ruby/faraday/jsonObj-null-value.rb new file mode 100644 index 0000000..d2ecc57 --- /dev/null +++ b/test/fixtures/output/ruby/faraday/jsonObj-null-value.rb @@ -0,0 +1,13 @@ +require 'faraday' + +conn = Faraday.new( + url: 'http://mockbin.com', + headers: {'Content-Type' => 'application/json'} +) + +response = conn.post('/har') do |req| + req.body = "{\"foo\":null}" +end + +puts response.status +puts response.body \ No newline at end of file diff --git a/test/fixtures/output/ruby/faraday/malicious.rb b/test/fixtures/output/ruby/faraday/malicious.rb new file mode 100644 index 0000000..a5423a2 --- /dev/null +++ b/test/fixtures/output/ruby/faraday/malicious.rb @@ -0,0 +1,50 @@ +require 'faraday' + +conn = Faraday.new( + url: 'http://example.test', +) + +response = conn.post('/%27%22%60$(%(%%7B%7B%7B/0%s//') do |req| + req.headers['\''] = 'squote-key-test' + req.headers['squote-value-test'] = '\'' + req.headers['dquote-value-test'] = '"' + req.headers['`'] = 'backtick-key-test' + req.headers['backtick-value-test'] = '`' + req.headers['$'] = 'dollar-key-test' + req.headers['dollar-parenthesis-value-test'] = '$(' + req.headers['#'] = 'hash-key-test' + req.headers['hash-brace-value-test'] = '#{' + req.headers['%'] = 'percent-key-test' + req.headers['percent-parenthesis-value-test'] = '%(' + req.headers['percent-brace-value-test'] = '%{' + req.headers['double-brace-value-test'] = '{{' + req.headers['null-value-test'] = '\\0' + req.headers['string-fmt-value-test'] = '%s' + req.headers['slash-value-test'] = '\\' + req.params['\''] = 'squote-key-test' + req.params['squote-value-test'] = '\'' + req.params['"'] = 'dquote-key-test' + req.params['dquote-value-test'] = '"' + req.params['`'] = 'backtick-key-test' + req.params['backtick-value-test'] = '`' + req.params['$('] = 'dollar-parenthesis-key-test' + req.params['dollar-parenthesis-value-test'] = '$(' + req.params['#{'] = 'hash-brace-key-test' + req.params['hash-brace-value-test'] = '#{' + req.params['%('] = 'percent-parenthesis-key-test' + req.params['percent-parenthesis-value-test'] = '%(' + req.params['%{'] = 'percent-brace-key-test' + req.params['percent-brace-value-test'] = '%{' + req.params['{{'] = 'double-brace-key-test' + req.params['double-brace-value-test'] = '{{' + req.params['\\0'] = 'null-key-test' + req.params['null-value-test'] = '\\0' + req.params['%s'] = 'string-fmt-key-test' + req.params['string-fmt-value-test'] = '%s' + req.params['\\'] = 'slash-key-test' + req.params['slash-value-test'] = '\\' + req.body = "' \" ` $( #{ %( %{ {{ \\0 %s \\" +end + +puts response.status +puts response.body \ No newline at end of file diff --git a/test/fixtures/output/ruby/faraday/multipart-data.rb b/test/fixtures/output/ruby/faraday/multipart-data.rb new file mode 100644 index 0000000..225c6f6 --- /dev/null +++ b/test/fixtures/output/ruby/faraday/multipart-data.rb @@ -0,0 +1,13 @@ +require 'faraday' + +conn = Faraday.new( + url: 'http://mockbin.com', + headers: {'Content-Type' => 'multipart/form-data; boundary=---011000010111000001101001'} +) + +response = conn.post('/har') do |req| + req.body = "-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"foo\"; filename=\"hello.txt\"\r\nContent-Type: text/plain\r\n\r\nHello World\r\n-----011000010111000001101001--\r\n" +end + +puts response.status +puts response.body \ No newline at end of file diff --git a/test/fixtures/output/ruby/faraday/multipart-file.rb b/test/fixtures/output/ruby/faraday/multipart-file.rb new file mode 100644 index 0000000..4d71689 --- /dev/null +++ b/test/fixtures/output/ruby/faraday/multipart-file.rb @@ -0,0 +1,13 @@ +require 'faraday' + +conn = Faraday.new( + url: 'http://mockbin.com', + headers: {'Content-Type' => 'multipart/form-data; boundary=---011000010111000001101001'} +) + +response = conn.post('/har') do |req| + req.body = "-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"foo\"; filename=\"hello.txt\"\r\nContent-Type: text/plain\r\n\r\n\r\n-----011000010111000001101001--\r\n" +end + +puts response.status +puts response.body \ No newline at end of file diff --git a/test/fixtures/output/ruby/faraday/multipart-form-data.rb b/test/fixtures/output/ruby/faraday/multipart-form-data.rb new file mode 100644 index 0000000..fe3e144 --- /dev/null +++ b/test/fixtures/output/ruby/faraday/multipart-form-data.rb @@ -0,0 +1,13 @@ +require 'faraday' + +conn = Faraday.new( + url: 'http://mockbin.com', + headers: {'Content-Type' => 'multipart/form-data; boundary=---011000010111000001101001'} +) + +response = conn.post('/har') do |req| + req.body = "-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"foo\"\r\n\r\nbar\r\n-----011000010111000001101001--\r\n" +end + +puts response.status +puts response.body \ No newline at end of file diff --git a/test/fixtures/output/ruby/faraday/nested.rb b/test/fixtures/output/ruby/faraday/nested.rb new file mode 100644 index 0000000..1a6966d --- /dev/null +++ b/test/fixtures/output/ruby/faraday/nested.rb @@ -0,0 +1,14 @@ +require 'faraday' + +conn = Faraday.new( + url: 'http://mockbin.com', +) + +response = conn.get('/har') do |req| + req.params['foo[bar]'] = 'baz,zap' + req.params['fiz'] = 'buz' + req.params['key'] = 'value' +end + +puts response.status +puts response.body \ No newline at end of file diff --git a/test/fixtures/output/ruby/faraday/query.rb b/test/fixtures/output/ruby/faraday/query.rb new file mode 100644 index 0000000..c418c55 --- /dev/null +++ b/test/fixtures/output/ruby/faraday/query.rb @@ -0,0 +1,14 @@ +require 'faraday' + +conn = Faraday.new( + url: 'http://mockbin.com', +) + +response = conn.get('/har') do |req| + req.params['foo'] = ["bar","baz"] + req.params['baz'] = 'abc' + req.params['key'] = 'value' +end + +puts response.status +puts response.body \ No newline at end of file diff --git a/test/fixtures/output/ruby/faraday/short.rb b/test/fixtures/output/ruby/faraday/short.rb new file mode 100644 index 0000000..8ce34f7 --- /dev/null +++ b/test/fixtures/output/ruby/faraday/short.rb @@ -0,0 +1,11 @@ +require 'faraday' + +conn = Faraday.new( + url: 'http://mockbin.com', +) + +response = conn.get('/har') do |req| +end + +puts response.status +puts response.body \ No newline at end of file diff --git a/test/fixtures/output/ruby/faraday/text-plain.rb b/test/fixtures/output/ruby/faraday/text-plain.rb new file mode 100644 index 0000000..b253cc3 --- /dev/null +++ b/test/fixtures/output/ruby/faraday/text-plain.rb @@ -0,0 +1,13 @@ +require 'faraday' + +conn = Faraday.new( + url: 'http://mockbin.com', + headers: {'Content-Type' => 'text/plain'} +) + +response = conn.post('/har') do |req| + req.body = "Hello World" +end + +puts response.status +puts response.body \ No newline at end of file diff --git a/test/fixtures/output/ruby/faraday/unparseable-query.rb b/test/fixtures/output/ruby/faraday/unparseable-query.rb new file mode 100644 index 0000000..8ce34f7 --- /dev/null +++ b/test/fixtures/output/ruby/faraday/unparseable-query.rb @@ -0,0 +1,11 @@ +require 'faraday' + +conn = Faraday.new( + url: 'http://mockbin.com', +) + +response = conn.get('/har') do |req| +end + +puts response.status +puts response.body \ No newline at end of file diff --git a/test/fixtures/output/ruby/native/compression.rb b/test/fixtures/output/ruby/native/compression.rb new file mode 100644 index 0000000..d2f7260 --- /dev/null +++ b/test/fixtures/output/ruby/native/compression.rb @@ -0,0 +1,12 @@ +require 'uri' +require 'net/http' + +url = URI("http://mockbin.com/har") + +http = Net::HTTP.new(url.host, url.port) + +request = Net::HTTP::Get.new(url) +request["accept-encoding"] = 'deflate, gzip, br' + +response = http.request(request) +puts response.read_body \ No newline at end of file diff --git a/test/fixtures/output/ruby/native/headers.rb b/test/fixtures/output/ruby/native/headers.rb index f2a4dba..82219f4 100644 --- a/test/fixtures/output/ruby/native/headers.rb +++ b/test/fixtures/output/ruby/native/headers.rb @@ -8,6 +8,7 @@ request = Net::HTTP::Get.new(url) request["accept"] = 'application/json' request["x-foo"] = 'Bar' +request["quoted-value"] = '"quoted" \'string\'' response = http.request(request) puts response.read_body diff --git a/test/fixtures/output/ruby/native/https.rb b/test/fixtures/output/ruby/native/https.rb index 8d645dd..94d60f5 100644 --- a/test/fixtures/output/ruby/native/https.rb +++ b/test/fixtures/output/ruby/native/https.rb @@ -1,12 +1,10 @@ require 'uri' require 'net/http' -require 'openssl' url = URI("https://mockbin.com/har") http = Net::HTTP.new(url.host, url.port) http.use_ssl = true -http.verify_mode = OpenSSL::SSL::VERIFY_NONE request = Net::HTTP::Get.new(url) diff --git a/test/fixtures/output/ruby/native/malicious.rb b/test/fixtures/output/ruby/native/malicious.rb new file mode 100644 index 0000000..6294fb8 --- /dev/null +++ b/test/fixtures/output/ruby/native/malicious.rb @@ -0,0 +1,28 @@ +require 'uri' +require 'net/http' + +url = URI("http://example.test/%27%22%60$(%(%%7B%7B%7B/0%s//?'=squote-key-test&squote-value-test='&%22=dquote-key-test&dquote-value-test=%22&%60=backtick-key-test&backtick-value-test=%60&%24(=dollar-parenthesis-key-test&dollar-parenthesis-value-test=%24(&%23%7B=hash-brace-key-test&hash-brace-value-test=%23%7B&%25(=percent-parenthesis-key-test&percent-parenthesis-value-test=%25(&%25%7B=percent-brace-key-test&percent-brace-value-test=%25%7B&%7B%7B=double-brace-key-test&double-brace-value-test=%7B%7B&%5C0=null-key-test&null-value-test=%5C0&%25s=string-fmt-key-test&string-fmt-value-test=%25s&%5C=slash-key-test&slash-value-test=%5C") + +http = Net::HTTP.new(url.host, url.port) + +request = Net::HTTP::Post.new(url) +request["'"] = 'squote-key-test' +request["squote-value-test"] = '\'' +request["dquote-value-test"] = '"' +request["`"] = 'backtick-key-test' +request["backtick-value-test"] = '`' +request["$"] = 'dollar-key-test' +request["dollar-parenthesis-value-test"] = '$(' +request["#"] = 'hash-key-test' +request["hash-brace-value-test"] = '#{' +request["%"] = 'percent-key-test' +request["percent-parenthesis-value-test"] = '%(' +request["percent-brace-value-test"] = '%{' +request["double-brace-value-test"] = '{{' +request["null-value-test"] = '\\0' +request["string-fmt-value-test"] = '%s' +request["slash-value-test"] = '\\' +request.body = "' \" ` $( #{ %( %{ {{ \\0 %s \\" + +response = http.request(request) +puts response.read_body \ No newline at end of file diff --git a/test/fixtures/output/ruby/native/unparseable-query.rb b/test/fixtures/output/ruby/native/unparseable-query.rb new file mode 100644 index 0000000..3653394 --- /dev/null +++ b/test/fixtures/output/ruby/native/unparseable-query.rb @@ -0,0 +1,11 @@ +require 'uri' +require 'net/http' + +url = URI("http://mockbin.com/har?&&a=b&&") + +http = Net::HTTP.new(url.host, url.port) + +request = Net::HTTP::Get.new(url) + +response = http.request(request) +puts response.read_body \ No newline at end of file diff --git a/test/fixtures/output/rust/reqwest/application-form-encoded.rs b/test/fixtures/output/rust/reqwest/application-form-encoded.rs new file mode 100644 index 0000000..4a96f4a --- /dev/null +++ b/test/fixtures/output/rust/reqwest/application-form-encoded.rs @@ -0,0 +1,29 @@ +use serde_json::json; +use reqwest; + +#[tokio::main] +pub async fn main() { + let url = "http://mockbin.com/har"; + + let payload = json!({ + "foo": "bar", + "hello": "world" + }); + + let mut headers = reqwest::header::HeaderMap::new(); + headers.insert("content-type", "application/x-www-form-urlencoded".parse().unwrap()); + + let client = reqwest::Client::new(); + let response = client.post(url) + .headers(headers) + .form(&payload) + .send() + .await; + + let results = response.unwrap() + .json::() + .await + .unwrap(); + + dbg!(results); +} \ No newline at end of file diff --git a/test/fixtures/output/rust/reqwest/application-json.rs b/test/fixtures/output/rust/reqwest/application-json.rs new file mode 100644 index 0000000..d3105ac --- /dev/null +++ b/test/fixtures/output/rust/reqwest/application-json.rs @@ -0,0 +1,33 @@ +use serde_json::json; +use reqwest; + +#[tokio::main] +pub async fn main() { + let url = "http://mockbin.com/har"; + + let payload = json!({ + "number": 1, + "string": "f\"oo", + "arr": (1, 2, 3), + "nested": json!({"a": "b"}), + "arr_mix": (1, "a", json!({"arr_mix_nested": json!({})})), + "boolean": false + }); + + let mut headers = reqwest::header::HeaderMap::new(); + headers.insert("content-type", "application/json".parse().unwrap()); + + let client = reqwest::Client::new(); + let response = client.post(url) + .headers(headers) + .json(&payload) + .send() + .await; + + let results = response.unwrap() + .json::() + .await + .unwrap(); + + dbg!(results); +} \ No newline at end of file diff --git a/test/fixtures/output/rust/reqwest/compression.rs b/test/fixtures/output/rust/reqwest/compression.rs new file mode 100644 index 0000000..df4fdb4 --- /dev/null +++ b/test/fixtures/output/rust/reqwest/compression.rs @@ -0,0 +1,22 @@ +use reqwest; + +#[tokio::main] +pub async fn main() { + let url = "http://mockbin.com/har"; + + let mut headers = reqwest::header::HeaderMap::new(); + headers.insert("accept-encoding", "deflate, gzip, br".parse().unwrap()); + + let client = reqwest::Client::new(); + let response = client.get(url) + .headers(headers) + .send() + .await; + + let results = response.unwrap() + .json::() + .await + .unwrap(); + + dbg!(results); +} \ No newline at end of file diff --git a/test/fixtures/output/rust/reqwest/cookies.rs b/test/fixtures/output/rust/reqwest/cookies.rs new file mode 100644 index 0000000..c420b5a --- /dev/null +++ b/test/fixtures/output/rust/reqwest/cookies.rs @@ -0,0 +1,22 @@ +use reqwest; + +#[tokio::main] +pub async fn main() { + let url = "http://mockbin.com/har"; + + let mut headers = reqwest::header::HeaderMap::new(); + headers.insert("cookie", "foo=bar; bar=baz".parse().unwrap()); + + let client = reqwest::Client::new(); + let response = client.post(url) + .headers(headers) + .send() + .await; + + let results = response.unwrap() + .json::() + .await + .unwrap(); + + dbg!(results); +} \ No newline at end of file diff --git a/test/fixtures/output/rust/reqwest/custom-method.rs b/test/fixtures/output/rust/reqwest/custom-method.rs new file mode 100644 index 0000000..449e46c --- /dev/null +++ b/test/fixtures/output/rust/reqwest/custom-method.rs @@ -0,0 +1,19 @@ +use std::str::FromStr; +use reqwest; + +#[tokio::main] +pub async fn main() { + let url = "http://mockbin.com/har"; + + let client = reqwest::Client::new(); + let response = client.request(reqwest::Method::from_str("PROPFIND").unwrap(), url) + .send() + .await; + + let results = response.unwrap() + .json::() + .await + .unwrap(); + + dbg!(results); +} \ No newline at end of file diff --git a/test/fixtures/output/rust/reqwest/full.rs b/test/fixtures/output/rust/reqwest/full.rs new file mode 100644 index 0000000..486a102 --- /dev/null +++ b/test/fixtures/output/rust/reqwest/full.rs @@ -0,0 +1,35 @@ +use serde_json::json; +use reqwest; + +#[tokio::main] +pub async fn main() { + let url = "http://mockbin.com/har"; + + let querystring = [ + ("foo", "barbaz"), + ("baz", "abc"), + ("key", "value"), + ]; + + let payload = json!({"foo": "bar"}); + + let mut headers = reqwest::header::HeaderMap::new(); + headers.insert("cookie", "foo=bar; bar=baz".parse().unwrap()); + headers.insert("accept", "application/json".parse().unwrap()); + headers.insert("content-type", "application/x-www-form-urlencoded".parse().unwrap()); + + let client = reqwest::Client::new(); + let response = client.post(url) + .query(&querystring) + .headers(headers) + .form(&payload) + .send() + .await; + + let results = response.unwrap() + .json::() + .await + .unwrap(); + + dbg!(results); +} \ No newline at end of file diff --git a/test/fixtures/output/rust/reqwest/headers.rs b/test/fixtures/output/rust/reqwest/headers.rs new file mode 100644 index 0000000..59cfbbc --- /dev/null +++ b/test/fixtures/output/rust/reqwest/headers.rs @@ -0,0 +1,24 @@ +use reqwest; + +#[tokio::main] +pub async fn main() { + let url = "http://mockbin.com/har"; + + let mut headers = reqwest::header::HeaderMap::new(); + headers.insert("accept", "application/json".parse().unwrap()); + headers.insert("x-foo", "Bar".parse().unwrap()); + headers.insert("quoted-value", "\"quoted\" 'string'".parse().unwrap()); + + let client = reqwest::Client::new(); + let response = client.get(url) + .headers(headers) + .send() + .await; + + let results = response.unwrap() + .json::() + .await + .unwrap(); + + dbg!(results); +} \ No newline at end of file diff --git a/test/fixtures/output/rust/reqwest/https.rs b/test/fixtures/output/rust/reqwest/https.rs new file mode 100644 index 0000000..2b783c2 --- /dev/null +++ b/test/fixtures/output/rust/reqwest/https.rs @@ -0,0 +1,18 @@ +use reqwest; + +#[tokio::main] +pub async fn main() { + let url = "https://mockbin.com/har"; + + let client = reqwest::Client::new(); + let response = client.get(url) + .send() + .await; + + let results = response.unwrap() + .json::() + .await + .unwrap(); + + dbg!(results); +} \ No newline at end of file diff --git a/test/fixtures/output/rust/reqwest/jsonObj-multiline.rs b/test/fixtures/output/rust/reqwest/jsonObj-multiline.rs new file mode 100644 index 0000000..c883631 --- /dev/null +++ b/test/fixtures/output/rust/reqwest/jsonObj-multiline.rs @@ -0,0 +1,26 @@ +use serde_json::json; +use reqwest; + +#[tokio::main] +pub async fn main() { + let url = "http://mockbin.com/har"; + + let payload = json!({"foo": "bar"}); + + let mut headers = reqwest::header::HeaderMap::new(); + headers.insert("content-type", "application/json".parse().unwrap()); + + let client = reqwest::Client::new(); + let response = client.post(url) + .headers(headers) + .json(&payload) + .send() + .await; + + let results = response.unwrap() + .json::() + .await + .unwrap(); + + dbg!(results); +} \ No newline at end of file diff --git a/test/fixtures/output/rust/reqwest/jsonObj-null-value.rs b/test/fixtures/output/rust/reqwest/jsonObj-null-value.rs new file mode 100644 index 0000000..daa72c9 --- /dev/null +++ b/test/fixtures/output/rust/reqwest/jsonObj-null-value.rs @@ -0,0 +1,26 @@ +use serde_json::json; +use reqwest; + +#[tokio::main] +pub async fn main() { + let url = "http://mockbin.com/har"; + + let payload = json!({"foo": json!(null)}); + + let mut headers = reqwest::header::HeaderMap::new(); + headers.insert("content-type", "application/json".parse().unwrap()); + + let client = reqwest::Client::new(); + let response = client.post(url) + .headers(headers) + .json(&payload) + .send() + .await; + + let results = response.unwrap() + .json::() + .await + .unwrap(); + + dbg!(results); +} \ No newline at end of file diff --git a/test/fixtures/output/rust/reqwest/malicious.rs b/test/fixtures/output/rust/reqwest/malicious.rs new file mode 100644 index 0000000..f6e19d1 --- /dev/null +++ b/test/fixtures/output/rust/reqwest/malicious.rs @@ -0,0 +1,67 @@ +use serde_json::json; +use reqwest; + +#[tokio::main] +pub async fn main() { + let url = "http://example.test/%27%22%60$(%(%%7B%7B%7B/0%s//"; + + let querystring = [ + ("'", "squote-key-test"), + ("squote-value-test", "'"), + ("\"", "dquote-key-test"), + ("dquote-value-test", "\""), + ("`", "backtick-key-test"), + ("backtick-value-test", "`"), + ("$(", "dollar-parenthesis-key-test"), + ("dollar-parenthesis-value-test", "$("), + ("#{", "hash-brace-key-test"), + ("hash-brace-value-test", "#{"), + ("%(", "percent-parenthesis-key-test"), + ("percent-parenthesis-value-test", "%("), + ("%{", "percent-brace-key-test"), + ("percent-brace-value-test", "%{"), + ("{{", "double-brace-key-test"), + ("double-brace-value-test", "{{"), + ("\\0", "null-key-test"), + ("null-value-test", "\\0"), + ("%s", "string-fmt-key-test"), + ("string-fmt-value-test", "%s"), + ("\\", "slash-key-test"), + ("slash-value-test", "\\"), + ]; + + let payload = "' \" ` $( #{ %( %{ {{ \\0 %s \\"; + + let mut headers = reqwest::header::HeaderMap::new(); + headers.insert("'", "squote-key-test".parse().unwrap()); + headers.insert("squote-value-test", "'".parse().unwrap()); + headers.insert("dquote-value-test", "\"".parse().unwrap()); + headers.insert("`", "backtick-key-test".parse().unwrap()); + headers.insert("backtick-value-test", "`".parse().unwrap()); + headers.insert("$", "dollar-key-test".parse().unwrap()); + headers.insert("dollar-parenthesis-value-test", "$(".parse().unwrap()); + headers.insert("#", "hash-key-test".parse().unwrap()); + headers.insert("hash-brace-value-test", "#{".parse().unwrap()); + headers.insert("%", "percent-key-test".parse().unwrap()); + headers.insert("percent-parenthesis-value-test", "%(".parse().unwrap()); + headers.insert("percent-brace-value-test", "%{".parse().unwrap()); + headers.insert("double-brace-value-test", "{{".parse().unwrap()); + headers.insert("null-value-test", "\\0".parse().unwrap()); + headers.insert("string-fmt-value-test", "%s".parse().unwrap()); + headers.insert("slash-value-test", "\\".parse().unwrap()); + + let client = reqwest::Client::new(); + let response = client.post(url) + .query(&querystring) + .headers(headers) + .body(payload) + .send() + .await; + + let results = response.unwrap() + .json::() + .await + .unwrap(); + + dbg!(results); +} \ No newline at end of file diff --git a/test/fixtures/output/rust/reqwest/multipart-data.rs b/test/fixtures/output/rust/reqwest/multipart-data.rs new file mode 100644 index 0000000..ae79cbf --- /dev/null +++ b/test/fixtures/output/rust/reqwest/multipart-data.rs @@ -0,0 +1,33 @@ +use reqwest; + +#[tokio::main] +pub async fn main() { + let url = "http://mockbin.com/har"; + + async fn file_to_part(file_name: &'static str) -> reqwest::multipart::Part { + let file = tokio::fs::File::open(file_name).await.unwrap(); + let stream = tokio_util::codec::FramedRead::new(file, tokio_util::codec::BytesCodec::new()); + let body = reqwest::Body::wrap_stream(stream); + reqwest::multipart::Part::stream(body) + .file_name(file_name) + .mime_str("text/plain").unwrap() + } + + let form = reqwest::multipart::Form::new() + .part("foo", file_to_part("hello.txt").await); + let mut headers = reqwest::header::HeaderMap::new(); + + let client = reqwest::Client::new(); + let response = client.post(url) + .multipart(form) + .headers(headers) + .send() + .await; + + let results = response.unwrap() + .json::() + .await + .unwrap(); + + dbg!(results); +} \ No newline at end of file diff --git a/test/fixtures/output/rust/reqwest/multipart-file.rs b/test/fixtures/output/rust/reqwest/multipart-file.rs new file mode 100644 index 0000000..64f372b --- /dev/null +++ b/test/fixtures/output/rust/reqwest/multipart-file.rs @@ -0,0 +1,33 @@ +use reqwest; + +#[tokio::main] +pub async fn main() { + let url = "http://mockbin.com/har"; + + async fn file_to_part(file_name: &'static str) -> reqwest::multipart::Part { + let file = tokio::fs::File::open(file_name).await.unwrap(); + let stream = tokio_util::codec::FramedRead::new(file, tokio_util::codec::BytesCodec::new()); + let body = reqwest::Body::wrap_stream(stream); + reqwest::multipart::Part::stream(body) + .file_name(file_name) + .mime_str("text/plain").unwrap() + } + + let form = reqwest::multipart::Form::new() + .part("foo", file_to_part("test/fixtures/files/hello.txt").await); + let mut headers = reqwest::header::HeaderMap::new(); + + let client = reqwest::Client::new(); + let response = client.post(url) + .multipart(form) + .headers(headers) + .send() + .await; + + let results = response.unwrap() + .json::() + .await + .unwrap(); + + dbg!(results); +} \ No newline at end of file diff --git a/test/fixtures/output/rust/reqwest/multipart-form-data.rs b/test/fixtures/output/rust/reqwest/multipart-form-data.rs new file mode 100644 index 0000000..a2907cc --- /dev/null +++ b/test/fixtures/output/rust/reqwest/multipart-form-data.rs @@ -0,0 +1,24 @@ +use reqwest; + +#[tokio::main] +pub async fn main() { + let url = "http://mockbin.com/har"; + + let form = reqwest::multipart::Form::new() + .text("foo", "bar"); + let mut headers = reqwest::header::HeaderMap::new(); + + let client = reqwest::Client::new(); + let response = client.post(url) + .multipart(form) + .headers(headers) + .send() + .await; + + let results = response.unwrap() + .json::() + .await + .unwrap(); + + dbg!(results); +} \ No newline at end of file diff --git a/test/fixtures/output/rust/reqwest/nested.rs b/test/fixtures/output/rust/reqwest/nested.rs new file mode 100644 index 0000000..77ddc19 --- /dev/null +++ b/test/fixtures/output/rust/reqwest/nested.rs @@ -0,0 +1,25 @@ +use reqwest; + +#[tokio::main] +pub async fn main() { + let url = "http://mockbin.com/har"; + + let querystring = [ + ("foo[bar]", "baz,zap"), + ("fiz", "buz"), + ("key", "value"), + ]; + + let client = reqwest::Client::new(); + let response = client.get(url) + .query(&querystring) + .send() + .await; + + let results = response.unwrap() + .json::() + .await + .unwrap(); + + dbg!(results); +} \ No newline at end of file diff --git a/test/fixtures/output/rust/reqwest/query.rs b/test/fixtures/output/rust/reqwest/query.rs new file mode 100644 index 0000000..753741c --- /dev/null +++ b/test/fixtures/output/rust/reqwest/query.rs @@ -0,0 +1,25 @@ +use reqwest; + +#[tokio::main] +pub async fn main() { + let url = "http://mockbin.com/har"; + + let querystring = [ + ("foo", "barbaz"), + ("baz", "abc"), + ("key", "value"), + ]; + + let client = reqwest::Client::new(); + let response = client.get(url) + .query(&querystring) + .send() + .await; + + let results = response.unwrap() + .json::() + .await + .unwrap(); + + dbg!(results); +} \ No newline at end of file diff --git a/test/fixtures/output/rust/reqwest/short.rs b/test/fixtures/output/rust/reqwest/short.rs new file mode 100644 index 0000000..4250488 --- /dev/null +++ b/test/fixtures/output/rust/reqwest/short.rs @@ -0,0 +1,18 @@ +use reqwest; + +#[tokio::main] +pub async fn main() { + let url = "http://mockbin.com/har"; + + let client = reqwest::Client::new(); + let response = client.get(url) + .send() + .await; + + let results = response.unwrap() + .json::() + .await + .unwrap(); + + dbg!(results); +} \ No newline at end of file diff --git a/test/fixtures/output/rust/reqwest/text-plain.rs b/test/fixtures/output/rust/reqwest/text-plain.rs new file mode 100644 index 0000000..3a47ddf --- /dev/null +++ b/test/fixtures/output/rust/reqwest/text-plain.rs @@ -0,0 +1,26 @@ +use serde_json::json; +use reqwest; + +#[tokio::main] +pub async fn main() { + let url = "http://mockbin.com/har"; + + let payload = "Hello World"; + + let mut headers = reqwest::header::HeaderMap::new(); + headers.insert("content-type", "text/plain".parse().unwrap()); + + let client = reqwest::Client::new(); + let response = client.post(url) + .headers(headers) + .body(payload) + .send() + .await; + + let results = response.unwrap() + .json::() + .await + .unwrap(); + + dbg!(results); +} \ No newline at end of file diff --git a/test/fixtures/output/rust/reqwest/unparseable-query.rs b/test/fixtures/output/rust/reqwest/unparseable-query.rs new file mode 100644 index 0000000..c402cdf --- /dev/null +++ b/test/fixtures/output/rust/reqwest/unparseable-query.rs @@ -0,0 +1,18 @@ +use reqwest; + +#[tokio::main] +pub async fn main() { + let url = "http://mockbin.com/har?&&a=b&&"; + + let client = reqwest::Client::new(); + let response = client.get(url) + .send() + .await; + + let results = response.unwrap() + .json::() + .await + .unwrap(); + + dbg!(results); +} \ No newline at end of file diff --git a/test/fixtures/output/shell/curl/compression.sh b/test/fixtures/output/shell/curl/compression.sh new file mode 100644 index 0000000..da25c0d --- /dev/null +++ b/test/fixtures/output/shell/curl/compression.sh @@ -0,0 +1,4 @@ +curl --request GET \ + --url http://mockbin.com/har \ + --compressed \ + --header 'accept-encoding: deflate, gzip, br' \ No newline at end of file diff --git a/test/fixtures/output/shell/curl/headers.sh b/test/fixtures/output/shell/curl/headers.sh index c415136..7a4ea84 100644 --- a/test/fixtures/output/shell/curl/headers.sh +++ b/test/fixtures/output/shell/curl/headers.sh @@ -1,4 +1,5 @@ curl --request GET \ --url http://mockbin.com/har \ --header 'accept: application/json' \ + --header 'quoted-value: "quoted" '\''string'\''' \ --header 'x-foo: Bar' diff --git a/test/fixtures/output/shell/curl/malicious.sh b/test/fixtures/output/shell/curl/malicious.sh new file mode 100644 index 0000000..ee64132 --- /dev/null +++ b/test/fixtures/output/shell/curl/malicious.sh @@ -0,0 +1,19 @@ +curl --request POST \ + --url 'http://example.test/%27%22%60$(%(%%7B%7B%7B/0%s//?'\''=squote-key-test&squote-value-test='\''&%22=dquote-key-test&dquote-value-test=%22&%60=backtick-key-test&backtick-value-test=%60&%24(=dollar-parenthesis-key-test&dollar-parenthesis-value-test=%24(&%23%7B=hash-brace-key-test&hash-brace-value-test=%23%7B&%25(=percent-parenthesis-key-test&percent-parenthesis-value-test=%25(&%25%7B=percent-brace-key-test&percent-brace-value-test=%25%7B&%7B%7B=double-brace-key-test&double-brace-value-test=%7B%7B&%5C0=null-key-test&null-value-test=%5C0&%25s=string-fmt-key-test&string-fmt-value-test=%25s&%5C=slash-key-test&slash-value-test=%5C' \ + --header '#: hash-key-test' \ + --header '$: dollar-key-test' \ + --header '%: percent-key-test' \ + --header ''\'': squote-key-test' \ + --header '`: backtick-key-test' \ + --header 'backtick-value-test: `' \ + --header 'dollar-parenthesis-value-test: $(' \ + --header 'double-brace-value-test: {{' \ + --header 'dquote-value-test: "' \ + --header 'hash-brace-value-test: #{' \ + --header 'null-value-test: \0' \ + --header 'percent-brace-value-test: %{' \ + --header 'percent-parenthesis-value-test: %(' \ + --header 'slash-value-test: \' \ + --header 'squote-value-test: '\''' \ + --header 'string-fmt-value-test: %s' \ + --data ''\'' " ` $( #{ %( %{ {{ \0 %s \' \ No newline at end of file diff --git a/test/fixtures/output/shell/curl/multipart-data.sh b/test/fixtures/output/shell/curl/multipart-data.sh index 40a0201..216ae23 100644 --- a/test/fixtures/output/shell/curl/multipart-data.sh +++ b/test/fixtures/output/shell/curl/multipart-data.sh @@ -1,4 +1,4 @@ curl --request POST \ --url http://mockbin.com/har \ - --header 'content-type: multipart/form-data; boundary=---011000010111000001101001' \ + --header 'content-type: multipart/form-data' \ --form foo=@hello.txt diff --git a/test/fixtures/output/shell/curl/multipart-file.sh b/test/fixtures/output/shell/curl/multipart-file.sh index e054807..9f18a58 100644 --- a/test/fixtures/output/shell/curl/multipart-file.sh +++ b/test/fixtures/output/shell/curl/multipart-file.sh @@ -1,4 +1,4 @@ curl --request POST \ --url http://mockbin.com/har \ - --header 'content-type: multipart/form-data; boundary=---011000010111000001101001' \ + --header 'content-type: multipart/form-data' \ --form foo=@test/fixtures/files/hello.txt diff --git a/test/fixtures/output/shell/curl/multipart-form-data.sh b/test/fixtures/output/shell/curl/multipart-form-data.sh index def1f43..fd5d2d1 100644 --- a/test/fixtures/output/shell/curl/multipart-form-data.sh +++ b/test/fixtures/output/shell/curl/multipart-form-data.sh @@ -1,4 +1,4 @@ curl --request POST \ --url http://mockbin.com/har \ - --header 'Content-Type: multipart/form-data; boundary=---011000010111000001101001' \ + --header 'Content-Type: multipart/form-data' \ --form foo=bar diff --git a/test/fixtures/output/shell/curl/unparseable-query.sh b/test/fixtures/output/shell/curl/unparseable-query.sh new file mode 100644 index 0000000..1b2f29c --- /dev/null +++ b/test/fixtures/output/shell/curl/unparseable-query.sh @@ -0,0 +1,2 @@ +curl --request GET \ + --url 'http://mockbin.com/har?&&a=b&&' \ No newline at end of file diff --git a/test/fixtures/output/shell/httpie/application-json.sh b/test/fixtures/output/shell/httpie/application-json.sh index 073a258..979ef3a 100644 --- a/test/fixtures/output/shell/httpie/application-json.sh +++ b/test/fixtures/output/shell/httpie/application-json.sh @@ -1,3 +1,3 @@ -echo '{"number":1,"string":"f\"oo","arr":[1,2,3],"nested":{"a":"b"},"arr_mix":[1,"a",{"arr_mix_nested":{}}],"boolean":false}' | \ +printf '%s' '{"number":1,"string":"f\"oo","arr":[1,2,3],"nested":{"a":"b"},"arr_mix":[1,"a",{"arr_mix_nested":{}}],"boolean":false}' | \ http POST http://mockbin.com/har \ content-type:application/json diff --git a/test/fixtures/output/shell/httpie/compression.sh b/test/fixtures/output/shell/httpie/compression.sh new file mode 100644 index 0000000..2e8d060 --- /dev/null +++ b/test/fixtures/output/shell/httpie/compression.sh @@ -0,0 +1,2 @@ +http GET http://mockbin.com/har \ + accept-encoding:'deflate, gzip, br' \ No newline at end of file diff --git a/test/fixtures/output/shell/httpie/headers.sh b/test/fixtures/output/shell/httpie/headers.sh index 427ae78..1659df8 100644 --- a/test/fixtures/output/shell/httpie/headers.sh +++ b/test/fixtures/output/shell/httpie/headers.sh @@ -1,3 +1,4 @@ http GET http://mockbin.com/har \ accept:application/json \ + quoted-value:'"quoted" '\''string'\''' \ x-foo:Bar diff --git a/test/fixtures/output/shell/httpie/malicious.sh b/test/fixtures/output/shell/httpie/malicious.sh new file mode 100644 index 0000000..e9e64d3 --- /dev/null +++ b/test/fixtures/output/shell/httpie/malicious.sh @@ -0,0 +1,18 @@ +printf '%s' ''\'' " ` $( #{ %( %{ {{ \0 %s \' | \ + http POST 'http://example.test/%27%22%60$(%(%%7B%7B%7B/0%s//?'\''=squote-key-test&squote-value-test='\''&%22=dquote-key-test&dquote-value-test=%22&%60=backtick-key-test&backtick-value-test=%60&%24(=dollar-parenthesis-key-test&dollar-parenthesis-value-test=%24(&%23%7B=hash-brace-key-test&hash-brace-value-test=%23%7B&%25(=percent-parenthesis-key-test&percent-parenthesis-value-test=%25(&%25%7B=percent-brace-key-test&percent-brace-value-test=%25%7B&%7B%7B=double-brace-key-test&double-brace-value-test=%7B%7B&%5C0=null-key-test&null-value-test=%5C0&%25s=string-fmt-key-test&string-fmt-value-test=%25s&%5C=slash-key-test&slash-value-test=%5C' \ + '#':hash-key-test \ + '$':dollar-key-test \ + %:percent-key-test \ + ''\''':squote-key-test \ + '`':backtick-key-test \ + backtick-value-test:'`' \ + dollar-parenthesis-value-test:'$(' \ + double-brace-value-test:'{{' \ + dquote-value-test:'"' \ + hash-brace-value-test:'#{' \ + null-value-test:'\0' \ + percent-brace-value-test:'%{' \ + percent-parenthesis-value-test:'%(' \ + slash-value-test:'\' \ + squote-value-test:''\''' \ + string-fmt-value-test:%s \ No newline at end of file diff --git a/test/fixtures/output/shell/httpie/unparseable-query.sh b/test/fixtures/output/shell/httpie/unparseable-query.sh new file mode 100644 index 0000000..0a973a2 --- /dev/null +++ b/test/fixtures/output/shell/httpie/unparseable-query.sh @@ -0,0 +1 @@ +http GET 'http://mockbin.com/har?&&a=b&&' \ No newline at end of file diff --git a/test/fixtures/output/shell/wget/compression.sh b/test/fixtures/output/shell/wget/compression.sh new file mode 100644 index 0000000..50d8266 --- /dev/null +++ b/test/fixtures/output/shell/wget/compression.sh @@ -0,0 +1,5 @@ +wget --quiet \ + --method GET \ + --header 'accept-encoding: deflate, gzip, br' \ + --output-document \ + - http://mockbin.com/har \ No newline at end of file diff --git a/test/fixtures/output/shell/wget/headers.sh b/test/fixtures/output/shell/wget/headers.sh index e39f090..2389d65 100644 --- a/test/fixtures/output/shell/wget/headers.sh +++ b/test/fixtures/output/shell/wget/headers.sh @@ -2,5 +2,6 @@ wget --quiet \ --method GET \ --header 'accept: application/json' \ --header 'x-foo: Bar' \ + --header 'quoted-value: "quoted" '\''string'\''' \ --output-document \ - http://mockbin.com/har diff --git a/test/fixtures/output/shell/wget/malicious.sh b/test/fixtures/output/shell/wget/malicious.sh new file mode 100644 index 0000000..3649342 --- /dev/null +++ b/test/fixtures/output/shell/wget/malicious.sh @@ -0,0 +1,21 @@ +wget --quiet \ + --method POST \ + --header ''\'': squote-key-test' \ + --header 'squote-value-test: '\''' \ + --header 'dquote-value-test: "' \ + --header '`: backtick-key-test' \ + --header 'backtick-value-test: `' \ + --header '$: dollar-key-test' \ + --header 'dollar-parenthesis-value-test: $(' \ + --header '#: hash-key-test' \ + --header 'hash-brace-value-test: #{' \ + --header '%: percent-key-test' \ + --header 'percent-parenthesis-value-test: %(' \ + --header 'percent-brace-value-test: %{' \ + --header 'double-brace-value-test: {{' \ + --header 'null-value-test: \0' \ + --header 'string-fmt-value-test: %s' \ + --header 'slash-value-test: \' \ + --body-data ''\'' " ` $( #{ %( %{ {{ \0 %s \' \ + --output-document \ + - 'http://example.test/%27%22%60$(%(%%7B%7B%7B/0%s//?'\''=squote-key-test&squote-value-test='\''&%22=dquote-key-test&dquote-value-test=%22&%60=backtick-key-test&backtick-value-test=%60&%24(=dollar-parenthesis-key-test&dollar-parenthesis-value-test=%24(&%23%7B=hash-brace-key-test&hash-brace-value-test=%23%7B&%25(=percent-parenthesis-key-test&percent-parenthesis-value-test=%25(&%25%7B=percent-brace-key-test&percent-brace-value-test=%25%7B&%7B%7B=double-brace-key-test&double-brace-value-test=%7B%7B&%5C0=null-key-test&null-value-test=%5C0&%25s=string-fmt-key-test&string-fmt-value-test=%25s&%5C=slash-key-test&slash-value-test=%5C' \ No newline at end of file diff --git a/test/fixtures/output/shell/wget/unparseable-query.sh b/test/fixtures/output/shell/wget/unparseable-query.sh new file mode 100644 index 0000000..ef5ca27 --- /dev/null +++ b/test/fixtures/output/shell/wget/unparseable-query.sh @@ -0,0 +1,4 @@ +wget --quiet \ + --method GET \ + --output-document \ + - 'http://mockbin.com/har?&&a=b&&' \ No newline at end of file diff --git a/test/fixtures/output/swift/nsurlsession/compression.swift b/test/fixtures/output/swift/nsurlsession/compression.swift new file mode 100644 index 0000000..96f296b --- /dev/null +++ b/test/fixtures/output/swift/nsurlsession/compression.swift @@ -0,0 +1,21 @@ +import Foundation + +let headers = ["accept-encoding": "deflate, gzip, br"] + +let request = NSMutableURLRequest(url: NSURL(string: "http://mockbin.com/har")! as URL, + cachePolicy: .useProtocolCachePolicy, + timeoutInterval: 10.0) +request.httpMethod = "GET" +request.allHTTPHeaderFields = headers + +let session = URLSession.shared +let dataTask = session.dataTask(with: request as URLRequest, completionHandler: { (data, response, error) -> Void in + if (error != nil) { + print(error) + } else { + let httpResponse = response as? HTTPURLResponse + print(httpResponse) + } +}) + +dataTask.resume() \ No newline at end of file diff --git a/test/fixtures/output/swift/nsurlsession/headers.swift b/test/fixtures/output/swift/nsurlsession/headers.swift index 8902e1a..5b4ed4d 100644 --- a/test/fixtures/output/swift/nsurlsession/headers.swift +++ b/test/fixtures/output/swift/nsurlsession/headers.swift @@ -2,7 +2,8 @@ import Foundation let headers = [ "accept": "application/json", - "x-foo": "Bar" + "x-foo": "Bar", + "quoted-value": "\"quoted\" 'string'" ] let request = NSMutableURLRequest(url: NSURL(string: "http://mockbin.com/har")! as URL, diff --git a/test/fixtures/output/swift/nsurlsession/malicious.swift b/test/fixtures/output/swift/nsurlsession/malicious.swift new file mode 100644 index 0000000..7dd4777 --- /dev/null +++ b/test/fixtures/output/swift/nsurlsession/malicious.swift @@ -0,0 +1,41 @@ +import Foundation + +let headers = [ + "'": "squote-key-test", + "squote-value-test": "'", + "dquote-value-test": "\"", + "`": "backtick-key-test", + "backtick-value-test": "`", + "$": "dollar-key-test", + "dollar-parenthesis-value-test": "$(", + "#": "hash-key-test", + "hash-brace-value-test": "#{", + "%": "percent-key-test", + "percent-parenthesis-value-test": "%(", + "percent-brace-value-test": "%{", + "double-brace-value-test": "{{", + "null-value-test": "\\0", + "string-fmt-value-test": "%s", + "slash-value-test": "\\" +] + +let postData = NSData(data: "' \" ` $( #{ %( %{ {{ \\0 %s \\".data(using: String.Encoding.utf8)!) + +let request = NSMutableURLRequest(url: NSURL(string: "http://example.test/%27%22%60$(%(%%7B%7B%7B/0%s//?'=squote-key-test&squote-value-test='&%22=dquote-key-test&dquote-value-test=%22&%60=backtick-key-test&backtick-value-test=%60&%24(=dollar-parenthesis-key-test&dollar-parenthesis-value-test=%24(&%23%7B=hash-brace-key-test&hash-brace-value-test=%23%7B&%25(=percent-parenthesis-key-test&percent-parenthesis-value-test=%25(&%25%7B=percent-brace-key-test&percent-brace-value-test=%25%7B&%7B%7B=double-brace-key-test&double-brace-value-test=%7B%7B&%5C0=null-key-test&null-value-test=%5C0&%25s=string-fmt-key-test&string-fmt-value-test=%25s&%5C=slash-key-test&slash-value-test=%5C")! as URL, + cachePolicy: .useProtocolCachePolicy, + timeoutInterval: 10.0) +request.httpMethod = "POST" +request.allHTTPHeaderFields = headers +request.httpBody = postData as Data + +let session = URLSession.shared +let dataTask = session.dataTask(with: request as URLRequest, completionHandler: { (data, response, error) -> Void in + if (error != nil) { + print(error) + } else { + let httpResponse = response as? HTTPURLResponse + print(httpResponse) + } +}) + +dataTask.resume() \ No newline at end of file diff --git a/test/fixtures/output/swift/nsurlsession/unparseable-query.swift b/test/fixtures/output/swift/nsurlsession/unparseable-query.swift new file mode 100644 index 0000000..995fb60 --- /dev/null +++ b/test/fixtures/output/swift/nsurlsession/unparseable-query.swift @@ -0,0 +1,18 @@ +import Foundation + +let request = NSMutableURLRequest(url: NSURL(string: "http://mockbin.com/har?&&a=b&&")! as URL, + cachePolicy: .useProtocolCachePolicy, + timeoutInterval: 10.0) +request.httpMethod = "GET" + +let session = URLSession.shared +let dataTask = session.dataTask(with: request as URLRequest, completionHandler: { (data, response, error) -> Void in + if (error != nil) { + print(error) + } else { + let httpResponse = response as? HTTPURLResponse + print(httpResponse) + } +}) + +dataTask.resume() \ No newline at end of file diff --git a/test/fixtures/requests/compression.json b/test/fixtures/requests/compression.json new file mode 100644 index 0000000..1bc9160 --- /dev/null +++ b/test/fixtures/requests/compression.json @@ -0,0 +1,10 @@ +{ + "method": "GET", + "url": "http://mockbin.com/har", + "headers": [ + { + "name": "accept-encoding", + "value": "deflate, gzip, br" + } + ] +} diff --git a/test/fixtures/requests/headers.json b/test/fixtures/requests/headers.json index 6f41b38..bdca607 100644 --- a/test/fixtures/requests/headers.json +++ b/test/fixtures/requests/headers.json @@ -9,6 +9,10 @@ { "name": "x-foo", "value": "Bar" + }, + { + "name": "quoted-value", + "value": "\"quoted\" 'string'" } ] } diff --git a/test/fixtures/requests/malicious.json b/test/fixtures/requests/malicious.json new file mode 100644 index 0000000..a701153 --- /dev/null +++ b/test/fixtures/requests/malicious.json @@ -0,0 +1,164 @@ +{ + "method": "POST", + "url": "http://example.test/'\"`$(%(%{{{\\0%s\\/", + "queryString": [ + { + "name": "'", + "value": "squote-key-test" + }, + { + "name": "squote-value-test", + "value": "'" + }, + { + "name": "\"", + "value": "dquote-key-test" + }, + { + "name": "dquote-value-test", + "value": "\"" + }, + { + "name": "`", + "value": "backtick-key-test" + }, + { + "name": "backtick-value-test", + "value": "`" + }, + { + "name": "$(", + "value": "dollar-parenthesis-key-test" + }, + { + "name": "dollar-parenthesis-value-test", + "value": "$(" + }, + { + "name": "#{", + "value": "hash-brace-key-test" + }, + { + "name": "hash-brace-value-test", + "value": "#{" + }, + { + "name": "%(", + "value": "percent-parenthesis-key-test" + }, + { + "name": "percent-parenthesis-value-test", + "value": "%(" + }, + { + "name": "%{", + "value": "percent-brace-key-test" + }, + { + "name": "percent-brace-value-test", + "value": "%{" + }, + { + "name": "{{", + "value": "double-brace-key-test" + }, + { + "name": "double-brace-value-test", + "value": "{{" + }, + { + "name": "\\0", + "value": "null-key-test" + }, + { + "name": "null-value-test", + "value": "\\0" + }, + { + "name": "%s", + "value": "string-fmt-key-test" + }, + { + "name": "string-fmt-value-test", + "value": "%s" + }, + { + "name": "\\", + "value": "slash-key-test" + }, + { + "name": "slash-value-test", + "value": "\\" + } + ], + "headers": [ + { + "name": "'", + "value": "squote-key-test" + }, + { + "name": "squote-value-test", + "value": "'" + }, + { + "name": "dquote-value-test", + "value": "\"" + }, + { + "name": "`", + "value": "backtick-key-test" + }, + { + "name": "backtick-value-test", + "value": "`" + }, + { + "name": "$", + "value": "dollar-key-test" + }, + { + "name": "dollar-parenthesis-value-test", + "value": "$(" + }, + { + "name": "#", + "value": "hash-key-test" + }, + { + "name": "hash-brace-value-test", + "value": "#{" + }, + { + "name": "%", + "value": "percent-key-test" + }, + { + "name": "percent-parenthesis-value-test", + "value": "%(" + }, + { + "name": "percent-brace-value-test", + "value": "%{" + }, + { + "name": "double-brace-value-test", + "value": "{{" + }, + { + "name": "null-value-test", + "value": "\\0" + }, + { + "name": "string-fmt-value-test", + "value": "%s" + }, + { + "name": "slash-value-test", + "value": "\\" + } + ], + "postData": { + "mimeType": "text/plain", + "text": "' \" ` $( #{ %( %{ {{ \\0 %s \\" + } + } diff --git a/test/fixtures/requests/unparseable-query.json b/test/fixtures/requests/unparseable-query.json new file mode 100644 index 0000000..30875b6 --- /dev/null +++ b/test/fixtures/requests/unparseable-query.json @@ -0,0 +1,11 @@ +{ + "method": "GET", + "url": "http://mockbin.com/har?&&a=b&&", + "queryString": [ + { + "name": "a", + "value": "b" + } + ], + "httpVersion": "HTTP/1.1" +} diff --git a/test/index.js b/test/index.js index d35bda6..1b748da 100644 --- a/test/index.js +++ b/test/index.js @@ -158,7 +158,8 @@ describe('HTTPSnippet', function () { req.headersObj.should.be.an.Object() req.headersObj.should.eql({ accept: 'application/json', - 'x-foo': 'Bar' + 'x-foo': 'Bar', + 'quoted-value': "\"quoted\" 'string'" }) done() @@ -177,7 +178,8 @@ describe('HTTPSnippet', function () { req.headersObj.should.eql({ 'Kong-Admin-Token': 'Hunter1', accept: 'application/json', - 'x-foo': 'Bar' + 'x-foo': 'Bar', + 'quoted-value': "\"quoted\" 'string'" }) done() @@ -196,7 +198,8 @@ describe('HTTPSnippet', function () { req.headersObj.should.eql({ 'kong-admin-token': 'Hunter1', accept: 'application/json', - 'x-foo': 'Bar' + 'x-foo': 'Bar', + 'quoted-value': "\"quoted\" 'string'" }) done() diff --git a/test/requests.js b/test/requests.js index dd52ff9..de765c0 100644 --- a/test/requests.js +++ b/test/requests.js @@ -8,7 +8,7 @@ const targets = require('../src/targets') const shell = require('child_process') const util = require('util') -require('should') +const should = require('should') const base = './test/fixtures/output/' const requests = [ @@ -25,7 +25,7 @@ const requests = [ // test all the things! fixtures.cli.forEach(function (cli) { - describe(targets[cli.target].info.title + ' Request Validation', function () { + describe.skip(targets[cli.target].info.title + ' Request Validation', function () { cli.clients.forEach(function (client) { requests.forEach(function (request) { it(client + ' request should match mock for ' + request, function (done) { @@ -40,6 +40,11 @@ fixtures.cli.forEach(function (cli) { }) ls.on('exit', function (code) { + if (code !== 0) { + console.error(stdout) + should.fail(0, code, `Process '${cli.run.split(' ')[0]}' exited unexpectedly with code ${code}`) + } + let har try { har = JSON.parse(stdout) diff --git a/test/targets.js b/test/targets.js index 58d77e3..0e4cf6c 100644 --- a/test/targets.js +++ b/test/targets.js @@ -92,6 +92,9 @@ describe('Available Targets', function () { fixtures['available-targets'].should.containEql(target) }) }) + + // Update with: + // node -e "console.log(JSON.stringify(require('.').availableTargets(), null, 2))" > ./test/fixtures/available-targets.json }) describe('Custom targets', function () { diff --git a/test/targets/crystal/native.js b/test/targets/crystal/native.js new file mode 100644 index 0000000..b77cc77 --- /dev/null +++ b/test/targets/crystal/native.js @@ -0,0 +1,3 @@ +'use strict' + +module.exports = function (snippet, fixtures) {} diff --git a/test/targets/go/native.js b/test/targets/go/native.js index 5137ecc..db5315b 100644 --- a/test/targets/go/native.js +++ b/test/targets/go/native.js @@ -9,7 +9,7 @@ module.exports = function (HTTPSnippet, fixtures) { }) result.should.be.a.String() - result.should.eql('url := "http://mockbin.com/har?foo=bar&foo=baz&baz=abc&key=value"\n\npayload := strings.NewReader("foo=bar")\n\nreq, _ := http.NewRequest("POST", url, payload)\n\nreq.Header.Add("cookie", "foo=bar; bar=baz")\nreq.Header.Add("accept", "application/json")\nreq.Header.Add("content-type", "application/x-www-form-urlencoded")\n\nres, _ := http.DefaultClient.Do(req)\n\ndefer res.Body.Close()\nbody, _ := ioutil.ReadAll(res.Body)\n\nfmt.Println(res)\nfmt.Println(string(body))') + result.should.eql('url := "http://mockbin.com/har?foo=bar&foo=baz&baz=abc&key=value"\n\npayload := strings.NewReader("foo=bar")\n\nreq, _ := http.NewRequest("POST", url, payload)\n\nreq.Header.Add("cookie", "foo=bar; bar=baz")\nreq.Header.Add("accept", "application/json")\nreq.Header.Add("content-type", "application/x-www-form-urlencoded")\n\nres, _ := http.DefaultClient.Do(req)\n\ndefer res.Body.Close()\nbody, _ := io.ReadAll(res.Body)\n\nfmt.Println(res)\nfmt.Println(string(body))') }) it('should support checkErrors option', function () { @@ -24,7 +24,7 @@ import ( \t"fmt" \t"strings" \t"net/http" -\t"io/ioutil" +\t"io" ) func main() { @@ -48,7 +48,7 @@ func main() { \t} \tdefer res.Body.Close() -\tbody, err := ioutil.ReadAll(res.Body) +\tbody, err := io.ReadAll(res.Body) \tif err != nil { \t\tpanic(err) \t} @@ -105,7 +105,7 @@ import ( \t"time" \t"strings" \t"net/http" -\t"io/ioutil" +\t"io" ) func main() { @@ -127,7 +127,52 @@ func main() { \tres, _ := client.Do(req) \tdefer res.Body.Close() -\tbody, _ := ioutil.ReadAll(res.Body) +\tbody, _ := io.ReadAll(res.Body) + +\tfmt.Println(res) +\tfmt.Println(string(body)) + +}`) + }) + + it('should support insecureSkipVerify option', function () { + const result = new HTTPSnippet(fixtures.requests.full).convert('go', 'native', { + insecureSkipVerify: true + }) + + result.should.be.a.String() + result.should.eql(`package main + +import ( +\t"fmt" +\t"crypto/tls" +\t"strings" +\t"net/http" +\t"io" +) + +func main() { + +\tinsecureTransport := http.DefaultTransport.(*http.Transport).Clone() +\tinsecureTransport.TLSClientConfig = &tls.Config{InsecureSkipVerify: true} +\tclient := http.Client{ +\t\tTransport: insecureTransport, +\t} + +\turl := "http://mockbin.com/har?foo=bar&foo=baz&baz=abc&key=value" + +\tpayload := strings.NewReader("foo=bar") + +\treq, _ := http.NewRequest("POST", url, payload) + +\treq.Header.Add("cookie", "foo=bar; bar=baz") +\treq.Header.Add("accept", "application/json") +\treq.Header.Add("content-type", "application/x-www-form-urlencoded") + +\tres, _ := client.Do(req) + +\tdefer res.Body.Close() +\tbody, _ := io.ReadAll(res.Body) \tfmt.Println(res) \tfmt.Println(string(body)) diff --git a/test/targets/java/restclient.js b/test/targets/java/restclient.js new file mode 100644 index 0000000..9ad8c17 --- /dev/null +++ b/test/targets/java/restclient.js @@ -0,0 +1,5 @@ +'use strict' + +require('should') + +module.exports = function (snippet, fixtures) {} diff --git a/test/targets/node/native.js b/test/targets/node/native.js index b77cc77..133faf6 100644 --- a/test/targets/node/native.js +++ b/test/targets/node/native.js @@ -1,3 +1,36 @@ 'use strict' -module.exports = function (snippet, fixtures) {} +module.exports = function (HTTPSnippet, fixtures) { + it('should support the insecureSkipVerify option', function () { + const result = new HTTPSnippet(fixtures.requests.https).convert('node', 'native', { + insecureSkipVerify: true + }) + + result.should.be.a.String() + result.should.eql(`const http = require("https"); + +const options = { + "method": "GET", + "hostname": "mockbin.com", + "port": null, + "path": "/har", + "headers": {}, + "rejectUnauthorized": false +}; + +const req = http.request(options, function (res) { + const chunks = []; + + res.on("data", function (chunk) { + chunks.push(chunk); + }); + + res.on("end", function () { + const body = Buffer.concat(chunks); + console.log(body.toString()); + }); +}); + +req.end();`) + }) +} diff --git a/test/targets/python/python3.js b/test/targets/python/python3.js index 9ad8c17..ad6bddc 100644 --- a/test/targets/python/python3.js +++ b/test/targets/python/python3.js @@ -2,4 +2,23 @@ require('should') -module.exports = function (snippet, fixtures) {} +module.exports = function (HTTPSnippet, fixtures) { + it('should support insecureSkipVerify', function () { + const result = new HTTPSnippet(fixtures.requests.https).convert('python', 'python3', { + insecureSkipVerify: true + }) + + result.should.be.a.String() + result.should.eql(`import http.client +import ssl + +conn = http.client.HTTPSConnection("mockbin.com", context = ssl._create_unverified_context()) + +conn.request("GET", "/har") + +res = conn.getresponse() +data = res.read() + +print(data.decode("utf-8"))`) + }) +} diff --git a/test/targets/ruby/faraday.js b/test/targets/ruby/faraday.js new file mode 100644 index 0000000..b77cc77 --- /dev/null +++ b/test/targets/ruby/faraday.js @@ -0,0 +1,3 @@ +'use strict' + +module.exports = function (snippet, fixtures) {} diff --git a/test/targets/ruby/native.js b/test/targets/ruby/native.js index b77cc77..c376cd9 100644 --- a/test/targets/ruby/native.js +++ b/test/targets/ruby/native.js @@ -1,3 +1,24 @@ 'use strict' -module.exports = function (snippet, fixtures) {} +module.exports = function (HTTPSnippet, fixtures) { + it('should support insecureSkipVerify', function () { + const result = new HTTPSnippet(fixtures.requests.https).convert('ruby', 'native', { + insecureSkipVerify: true + }) + + result.should.be.a.String() + result.should.eql(`require 'uri' +require 'net/http' + +url = URI("https://mockbin.com/har") + +http = Net::HTTP.new(url.host, url.port) +http.use_ssl = true +http.verify_mode = OpenSSL::SSL::VERIFY_NONE + +request = Net::HTTP::Get.new(url) + +response = http.request(request) +puts response.read_body`) + }) +} diff --git a/test/targets/rust/reqwest.js b/test/targets/rust/reqwest.js new file mode 100644 index 0000000..b77cc77 --- /dev/null +++ b/test/targets/rust/reqwest.js @@ -0,0 +1,3 @@ +'use strict' + +module.exports = function (snippet, fixtures) {} diff --git a/test/targets/shell/curl.js b/test/targets/shell/curl.js index 9435639..44323bb 100644 --- a/test/targets/shell/curl.js +++ b/test/targets/shell/curl.js @@ -55,6 +55,16 @@ module.exports = function (HTTPSnippet, fixtures) { result.should.eql("curl --request GET --url 'http://mockbin.com/har?foo%5Bbar%5D=baz%2Czap&fiz=buz&key=value'") }) + it('should support insecureSkipVerify', function () { + const result = new HTTPSnippet(fixtures.requests.https).convert('shell', 'curl', { + indent: false, + insecureSkipVerify: true + }) + + result.should.be.a.String() + result.should.eql('curl --request GET --url https://mockbin.com/har --insecure') + }) + it('should use --http1.0 for HTTP/1.0', function () { const result = new HTTPSnippet(fixtures.curl.http1).convert('shell', 'curl', { indent: false