diff --git a/.eslintrc b/.eslintrc new file mode 100644 index 00000000..2ed1b63d --- /dev/null +++ b/.eslintrc @@ -0,0 +1,49 @@ +{ + "root": true, + "extends": [ + "@readme/eslint-config", + "@readme/eslint-config/typescript", + ], + "env": { + "browser": true, + "node": true + }, + "rules": { + "no-plusplus": "off", + "no-restricted-syntax": "off", + "no-underscore-dangle": "off", + "no-use-before-define": "off", + "prefer-rest-params": "off", + "prefer-spread": "off" + }, + "overrides": [ + { + // The typings in this file are pretty bad right now, when we have native types we can + // remove this. + "files": ["lib/index.d.ts"], + "rules": { + "@typescript-eslint/consistent-indexed-object-style": "off", + "@typescript-eslint/consistent-type-imports": "off", + "@typescript-eslint/no-explicit-any": "off", + "@typescript-eslint/sort-type-constituents": "off", + "eslint-comments/no-unused-disable": "off", + "lines-between-class-members": "off", + "max-classes-per-file": "off", + "quotes": "off", + "typescript-sort-keys/interface": "off" + } + }, + { + // These can all get removed when the library is moved over to native TS. + "files": ["*.js"], + "rules": { + "@typescript-eslint/no-this-alias": "off", + "@typescript-eslint/no-unused-vars": "off", + "@typescript-eslint/no-use-before-define": "off", + "@typescript-eslint/no-var-requires": "off", + "eslint-comments/no-unused-disable": "off", + "func-names": "off" + } + } + ] +} diff --git a/.eslintrc.yml b/.eslintrc.yml deleted file mode 100644 index b6122376..00000000 --- a/.eslintrc.yml +++ /dev/null @@ -1,13 +0,0 @@ -root: true -extends: "@readme/eslint-config" -env: - browser: true - node: true - mocha: true -rules: - no-plusplus: off - no-restricted-syntax: off - no-underscore-dangle: off - no-use-before-define: off - prefer-rest-params: off - prefer-spread: off diff --git a/.gitattributes b/.gitattributes index 4ca9ecdb..64c7f58c 100644 --- a/.gitattributes +++ b/.gitattributes @@ -17,6 +17,7 @@ *.js text eol=lf *.jsx text eol=lf *.ts text eol=lf +*.mts text eol=lf *.tsx text eol=lf *.json text eol=lf *.yml text eol=lf diff --git a/.github/dependabot.yml b/.github/dependabot.yml index 8caed43d..77defa8e 100644 --- a/.github/dependabot.yml +++ b/.github/dependabot.yml @@ -1,7 +1,7 @@ version: 2 updates: - package-ecosystem: github-actions - directory: "/" + directory: '/' schedule: interval: monthly reviewers: @@ -13,7 +13,7 @@ updates: prefix-development: chore(deps-dev) - package-ecosystem: npm - directory: "/" + directory: '/' schedule: interval: monthly open-pull-requests-limit: 10 diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index aed09e53..5ba0e6db 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -31,17 +31,11 @@ jobs: node-version: ${{ matrix.node }} cache: npm - - name: Install dependencies - run: npm ci + - run: npm ci + - run: npm run lint - - name: Run linter - run: npm run lint - - - name: Run TypeScript tests - run: npm run test:typescript - - - name: Run Node tests - run: npm run coverage + - name: Run tests + run: npm run test --ignore-scripts env: # `chalk` has troubles with color detection while on CI and also in how it's used within our tests. # https://github.com/chalk/supports-color/issues/106 diff --git a/.gitignore b/.gitignore index f9373ad4..b6a5989b 100644 --- a/.gitignore +++ b/.gitignore @@ -13,7 +13,6 @@ nbproject # IDEs & Text Editors .idea .sublime-* -.vscode/settings.json .netbeans nbproject diff --git a/.mocharc.yml b/.mocharc.yml deleted file mode 100644 index 2ee714b4..00000000 --- a/.mocharc.yml +++ /dev/null @@ -1,10 +0,0 @@ -# Mocha options -# https://mochajs.org/#configuring-mocha-nodejs -# https://github.com/mochajs/mocha/blob/master/example/config/.mocharc.yml - -spec: test/specs/**/*.spec.js - -bail: true -recursive: true -async-only: true -retries: 2 diff --git a/.npmignore b/.npmignore index 5f495dc3..a34d18ef 100644 --- a/.npmignore +++ b/.npmignore @@ -1,8 +1,4 @@ .github/ -.husky/ -.nyc_output/ coverage/ .eslint* -.mocha* -.nyc* -debug.js +vitest.* diff --git a/.nycrc.yml b/.nycrc.yml deleted file mode 100644 index b7e965e4..00000000 --- a/.nycrc.yml +++ /dev/null @@ -1,10 +0,0 @@ -# NYC config -# https://github.com/istanbuljs/nyc#configuration-files - -extension: - - .js - - .ts - -reporter: - - text - - lcov diff --git a/.prettierignore b/.prettierignore new file mode 100644 index 00000000..f9cae01d --- /dev/null +++ b/.prettierignore @@ -0,0 +1 @@ +test/specs/large-file-memory-leak/cloudflare-stringified.json diff --git a/.vscode/settings.json b/.vscode/settings.json new file mode 100644 index 00000000..c8e04def --- /dev/null +++ b/.vscode/settings.json @@ -0,0 +1,5 @@ +{ + "editor.codeActionsOnSave": { + "source.fixAll": "explicit" + } +} diff --git a/README.md b/README.md index ff93ef48..189c9055 100644 --- a/README.md +++ b/README.md @@ -10,8 +10,8 @@ [![Online Demo](https://apitools.dev/swagger-parser/online/img/demo.svg)](https://apitools.dev/swagger-parser/online/) - ## Features + - Parses Swagger specs in **JSON** or **YAML** format - Validates against the [Swagger 2.0 schema](https://github.com/OAI/OpenAPI-Specification/blob/main/schemas/v2.0/schema.json), [OpenAPI 3.0 Schema](https://github.com/OAI/OpenAPI-Specification/blob/main/schemas/v3.0/schema.json), or [OpenAPI 3.1 Schema](https://github.com/OAI/OpenAPI-Specification/blob/main/schemas/v3.1/schema.json) - [Resolves](https://apitools.dev/swagger-parser/docs/swagger-parser.html#resolveapi-options-callback) all `$ref` pointers, including external files and URLs @@ -22,16 +22,14 @@ - Supports [circular references](https://apitools.dev/swagger-parser/docs/#circular-refs), nested references, back-references, and cross-references - Maintains object reference equality — `$ref` pointers to the same value always resolve to the same object instance - ## Example ```javascript OpenAPIParser.validate(myAPI, (err, api) => { if (err) { console.error(err); - } - else { - console.log("API name: %s, Version: %s", api.info.title, api.info.version); + } else { + console.log('API name: %s, Version: %s', api.info.title, api.info.version); } }); ``` @@ -41,39 +39,38 @@ Or use `async`/`await` or [Promise](http://javascriptplayground.com/blog/2015/02 ```javascript try { let api = await OpenAPIParser.validate(myAPI); - console.log("API name: %s, Version: %s", api.info.title, api.info.version); -} -catch(err) { + console.log('API name: %s, Version: %s', api.info.title, api.info.version); +} catch (err) { console.error(err); } ``` For more detailed examples, please see the [API Documentation](https://apitools.dev/swagger-parser/docs/) - ## Installation + Install using [npm](https://docs.npmjs.com/about-npm/): ```bash npm install @readme/openapi-parser ``` - ## Usage + When using Swagger Parser in Node.js apps, you'll probably want to use **CommonJS** syntax: ```javascript -const OpenAPIParser = require("@readme/openapi-parser"); +const OpenAPIParser = require('@readme/openapi-parser'); ``` When using a transpiler such as [Babel](https://babeljs.io/) or [TypeScript](https://www.typescriptlang.org/), or a bundler such as [Webpack](https://webpack.js.org/) or [Rollup](https://rollupjs.org/), you can use **ECMAScript modules** syntax instead: ```javascript -import OpenAPIParser from "@readme/openapi-parser"; +import OpenAPIParser from '@readme/openapi-parser'; ``` - ## Differences from `@apidevtools/swagger-parser` + `@apidevtools/swagger-parser` returns schema validation errors as the raw error stack from Ajv. For example: @@ -84,12 +81,12 @@ To reduce the amount of potentially unnecessary noise that these JSON pointer er Additionally with these error reporting differences, this library ships with a `validation.colorizeErrors` option that will disable colorization within these prettified errors. - ## Browser support + Swagger Parser supports recent versions of every major web browser. Older browsers may require [Babel](https://babeljs.io/) and/or [polyfills](https://babeljs.io/docs/en/next/babel-polyfill). To use Swagger Parser in a browser, you'll need to use a bundling tool such as [Webpack](https://webpack.js.org/), [Rollup](https://rollupjs.org/), [Parcel](https://parceljs.org/), or [Browserify](http://browserify.org/). Some bundlers may require a bit of configuration, such as setting `browser: true` in [rollup-plugin-resolve](https://github.com/rollup/rollup-plugin-node-resolve). - ## API Documentation + Full API documentation is available [right here](https://apitools.dev/swagger-parser/docs/) diff --git a/bin/refresh-real-world-apis b/bin/refresh-real-world-apis index c2461743..025d4712 100755 --- a/bin/refresh-real-world-apis +++ b/bin/refresh-real-world-apis @@ -1,11 +1,12 @@ #! /usr/bin/env node +/* eslint-disable @typescript-eslint/no-var-requires */ +/* eslint-disable no-param-reassign */ /** * This script regenerates the list of real world API definitions from APIs.guru that the test suite uses for parsing * and validating integration tests. * * @link https://github.com/APIs-guru/openapi-directory */ -/* eslint-disable no-param-reassign */ const fs = require('fs'); fetch('https://api.apis.guru/v2/list.json') @@ -53,5 +54,5 @@ fetch('https://api.apis.guru/v2/list.json') return apisMap; }) .then(apis => { - fs.writeFileSync(`${__dirname}/../test/fixtures/real-world-apis.json`, JSON.stringify(apis, null, 2)); + fs.writeFileSync(`${__dirname}/../test/fixtures/real-world-apis.json`, `${JSON.stringify(apis, null, 2)}\n`); }); diff --git a/docs/README.md b/docs/README.md index 4cd88406..c084ffab 100644 --- a/docs/README.md +++ b/docs/README.md @@ -1,14 +1,15 @@ # OpenAPI Parser API ## Things to Know + - [Class methods vs. Instance methods](#class-methods-vs-instance-methods) - [Callbacks vs. Promises](#callbacks-vs-promises) - [Circular references](#circular-refs) - ## Classes & Methods #### [The `OpenAPIParser` class](openapi-parser.md) + - [`api` property](openapi-parser.md#api) - [`$refs` property](openapi-parser.md#refs) - [`validate()` method](openapi-parser.md#validateapi-options-callback) @@ -18,6 +19,7 @@ - [`resolve()` method](openapi-parser.md#resolveapi-options-callback) #### [The `$Refs` class](refs.md) + - [`circular` property](refs.md#circular) - [`paths()` method](refs.md#pathstypes) - [`values()` method](refs.md#valuestypes) @@ -27,28 +29,28 @@ #### [The `Options` object](options.md) - ### Class methods vs. Instance methods -All of Swagger Parser's methods are available as static (class) methods, and as instance methods. The static methods simply create a new [`OpenAPIParser`](openapi-parser.md) instance and then call the corresponding instance method. Thus, the following line... + +All of Swagger Parser's methods are available as static (class) methods, and as instance methods. The static methods simply create a new [`OpenAPIParser`](openapi-parser.md) instance and then call the corresponding instance method. Thus, the following line... ```javascript -OpenAPIParser.validate("my-api.yaml"); +OpenAPIParser.validate('my-api.yaml'); ``` ... is the same as this: ```javascript let parser = new OpenAPIParser(); -parser.validate("my-api.yaml"); +parser.validate('my-api.yaml'); ``` The difference is that in the second example you now have a reference to `parser`, which means you can access the results ([`parser.api`](openapi-parser.md#api-object) and [`parser.$refs`](openapi-parser.md#refs)) anytime you want, rather than just in the callback function. - ### Callbacks vs. Promises -Many people prefer `async`/`await` or [Promise](http://javascriptplayground.com/blog/2015/02/promises/) syntax instead of callbacks. Swagger Parser allows you to use whichever one you prefer. -If you pass a callback function to any method, then the method will call the callback using the Node.js error-first convention. If you do _not_ pass a callback function, then the method will return a Promise. +Many people prefer `async`/`await` or [Promise](http://javascriptplayground.com/blog/2015/02/promises/) syntax instead of callbacks. Swagger Parser allows you to use whichever one you prefer. + +If you pass a callback function to any method, then the method will call the callback using the Node.js error-first convention. If you do _not_ pass a callback function, then the method will return a Promise. The following two examples are equivalent: @@ -57,8 +59,7 @@ The following two examples are equivalent: OpenAPIParser.validate(mySchema, (err, api) => { if (err) { // Error - } - else { + } else { // Success } }); @@ -70,21 +71,20 @@ try { let api = await OpenAPIParser.validate(mySchema); // Success -} -catch(err) { +} catch (err) { // Error } ``` - ### Circular $Refs -Swagger APIs can contain [circular $ref pointers](https://gist.github.com/JamesMessinger/d18278935fc73e3a0ee1), and Swagger Parser fully supports them. Circular references can be resolved and dereferenced just like any other reference. However, if you intend to serialize the dereferenced api as JSON, then you should be aware that [`JSON.stringify`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/JSON/stringify) does not support circular references by default, so you will need to [use a custom replacer function](https://stackoverflow.com/questions/11616630/json-stringify-avoid-typeerror-converting-circular-structure-to-json). + +Swagger APIs can contain [circular $ref pointers](https://gist.github.com/JamesMessinger/d18278935fc73e3a0ee1), and Swagger Parser fully supports them. Circular references can be resolved and dereferenced just like any other reference. However, if you intend to serialize the dereferenced api as JSON, then you should be aware that [`JSON.stringify`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/JSON/stringify) does not support circular references by default, so you will need to [use a custom replacer function](https://stackoverflow.com/questions/11616630/json-stringify-avoid-typeerror-converting-circular-structure-to-json). You can disable circular references by setting the [`dereference.circular`](options.md) option to `false`. Then, if a circular reference is found, a `ReferenceError` will be thrown. -Or you can choose to just ignore circular references altogether by setting the [`dereference.circular`](options.md) option to `"ignore"`. In this case, all non-circular references will still be dereferenced as normal, but any circular references will remain in the schema. +Or you can choose to just ignore circular references altogether by setting the [`dereference.circular`](options.md) option to `"ignore"`. In this case, all non-circular references will still be dereferenced as normal, but any circular references will remain in the schema. -Another option is to use the [`bundle`](openapi-parser.md#bundleapi-options-callback) method rather than the [`dereference`](openapi-parser.md#dereferenceapi-options-callback) method. Bundling does _not_ result in circular references, because it simply converts _external_ `$ref` pointers to _internal_ ones. +Another option is to use the [`bundle`](openapi-parser.md#bundleapi-options-callback) method rather than the [`dereference`](openapi-parser.md#dereferenceapi-options-callback) method. Bundling does _not_ result in circular references, because it simply converts _external_ `$ref` pointers to _internal_ ones. ```javascript "person": { diff --git a/docs/openapi-parser.md b/docs/openapi-parser.md index 75d7e645..4933111b 100644 --- a/docs/openapi-parser.md +++ b/docs/openapi-parser.md @@ -1,36 +1,38 @@ # `SwaggerParser` class -This is the default export of Swagger Parser. You can create instances of this class using `new SwaggerParser()`, or you can just call its [static methods](README.md#class-methods-vs-instance-methods). +This is the default export of Swagger Parser. You can create instances of this class using `new SwaggerParser()`, or you can just call its [static methods](README.md#class-methods-vs-instance-methods). ##### Properties + - [`api`](#api) - [`$refs`](#refs) ##### Methods + - [`validate()`](#validateapi-options-callback) - [`dereference()`](#dereferenceapi-options-callback) - [`bundle()`](#bundleapi-options-callback) - [`parse()`](#parseapi-options-callback) - [`resolve()`](#resolveapi-options-callback) - ### `api` -The `api` property is the parsed/bundled/dereferenced Swagger API object. This is the same value that is passed to the callback function (or Promise) when calling the [`parse`](#parseapi-options-callback), [`bundle`](#bundleapi-options-callback), or [`dereference`](#dereferenceapi-options-callback) methods. + +The `api` property is the parsed/bundled/dereferenced Swagger API object. This is the same value that is passed to the callback function (or Promise) when calling the [`parse`](#parseapi-options-callback), [`bundle`](#bundleapi-options-callback), or [`dereference`](#dereferenceapi-options-callback) methods. ```javascript let parser = new SwaggerParser(); -parser.api; // => null +parser.api; // => null -let api = await parser.dereference("my-api.yaml"); +let api = await parser.dereference('my-api.yaml'); -typeof parser.api; // => "object" +typeof parser.api; // => "object" api === parser.api; // => true ``` - ### `$refs` + The `$refs` property is a [`$Refs`](refs.md) object, which lets you access all of the externally-referenced files in the API, as well as easily get and set specific values in the schema using JSON pointers. This is the same value that is passed to the callback function (or Promise) when calling the [`resolve`](#resolveapi-options-callback) method. @@ -38,27 +40,26 @@ This is the same value that is passed to the callback function (or Promise) when ```javascript let parser = new SwaggerParser(); -parser.$refs.paths(); // => [] empty array +parser.$refs.paths(); // => [] empty array -await parser.dereference("my-api.json"); +await parser.dereference('my-api.json'); -parser.$refs.paths(); // => ["my-api.json"] +parser.$refs.paths(); // => ["my-api.json"] ``` - ### `validate(api, [options], [callback])` - **api** (_required_) - `string` or `object`
-A [Swagger Object](https://github.com/OAI/OpenAPI-Specification/blob/main/versions/2.0.md#swagger-object), or the file path or URL of your Swagger API. See the [`parse`](#parseapi-options-callback) method for more info. + A [Swagger Object](https://github.com/OAI/OpenAPI-Specification/blob/main/versions/2.0.md#swagger-object), or the file path or URL of your Swagger API. See the [`parse`](#parseapi-options-callback) method for more info. - **options** (_optional_) - `object`
-See [options](options.md) for the full list of options + See [options](options.md) for the full list of options - **callback** (_optional_) - `function(err, api)`
-A callback that will receive the dereferenced and validated [Swagger object](https://github.com/OAI/OpenAPI-Specification/blob/main/versions/2.0.md#swagger-object). + A callback that will receive the dereferenced and validated [Swagger object](https://github.com/OAI/OpenAPI-Specification/blob/main/versions/2.0.md#swagger-object). - **Return Value:** `Promise`
-See [Callbacks vs. Promises](README.md#callbacks-vs-promises) + See [Callbacks vs. Promises](README.md#callbacks-vs-promises) Validates the Swagger API against the [Swagger 2.0 schema](https://github.com/OAI/OpenAPI-Specification/blob/main/schemas/v2.0/schema.json), [OpenAPI 3.0 Schema](https://github.com/OAI/OpenAPI-Specification/blob/main/schemas/v3.0/schema.json), or [OpenAPI 3.1 Schema](https://github.com/OAI/OpenAPI-Specification/blob/main/schemas/v3.1/schema.json). @@ -70,119 +71,114 @@ This method calls [`dereference`](#dereferenceapi-options-callback) internally, ```javascript try { - let api = await SwaggerParser.validate("my-api.yaml"); + let api = await SwaggerParser.validate('my-api.yaml'); console.log('Yay! The API is valid.'); -} -catch(err) { +} catch (err) { console.error('Onoes! The API is invalid. ' + err.message); } ``` - ### `dereference(api, [options], [callback])` - **api** (_required_) - `string` or `object`
-A [Swagger Object](https://github.com/OAI/OpenAPI-Specification/blob/main/versions/2.0.md#swagger-object), or the file path or URL of your Swagger API. See the [`parse`](#parseapi-options-callback) method for more info. + A [Swagger Object](https://github.com/OAI/OpenAPI-Specification/blob/main/versions/2.0.md#swagger-object), or the file path or URL of your Swagger API. See the [`parse`](#parseapi-options-callback) method for more info. - **options** (_optional_) - `object`
-See [options](options.md) for the full list of options + See [options](options.md) for the full list of options - **callback** (_optional_) - `function(err, api)`
-A callback that will receive the dereferenced [Swagger object](https://github.com/OAI/OpenAPI-Specification/blob/main/versions/2.0.md#swagger-object). + A callback that will receive the dereferenced [Swagger object](https://github.com/OAI/OpenAPI-Specification/blob/main/versions/2.0.md#swagger-object). - **Return Value:** `Promise`
-See [Callbacks vs. Promises](README.md#callbacks-vs-promises) + See [Callbacks vs. Promises](README.md#callbacks-vs-promises) -Dereferences all `$ref` pointers in the Swagger API, replacing each reference with its resolved value. This results in a [Swagger object](https://github.com/OAI/OpenAPI-Specification/blob/main/versions/2.0.md#swagger-object) that does not contain _any_ `$ref` pointers. Instead, it's a normal JavaScript object tree that can easily be crawled and used just like any other JavaScript object. This is great for programmatic usage, especially when using tools that don't understand JSON references. +Dereferences all `$ref` pointers in the Swagger API, replacing each reference with its resolved value. This results in a [Swagger object](https://github.com/OAI/OpenAPI-Specification/blob/main/versions/2.0.md#swagger-object) that does not contain _any_ `$ref` pointers. Instead, it's a normal JavaScript object tree that can easily be crawled and used just like any other JavaScript object. This is great for programmatic usage, especially when using tools that don't understand JSON references. -The `dereference` method maintains object reference equality, meaning that all `$ref` pointers that point to the same object will be replaced with references to the same object. Again, this is great for programmatic usage, but it does introduce the risk of [circular references](README.md#circular-refs), so be careful if you intend to serialize the API using [`JSON.stringify()`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/JSON/stringify). Consider using the [`bundle`](#bundleapi-options-callback) method instead, which does not create circular references. +The `dereference` method maintains object reference equality, meaning that all `$ref` pointers that point to the same object will be replaced with references to the same object. Again, this is great for programmatic usage, but it does introduce the risk of [circular references](README.md#circular-refs), so be careful if you intend to serialize the API using [`JSON.stringify()`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/JSON/stringify). Consider using the [`bundle`](#bundleapi-options-callback) method instead, which does not create circular references. ```javascript -let api = await SwaggerParser.dereference("my-api.yaml"); +let api = await SwaggerParser.dereference('my-api.yaml'); // The `api` object is a normal JavaScript object, // so you can easily access any part of the API using simple dot notation console.log(api.definitions.person.properties.firstName); // => {type: "string"} ``` - ### `bundle(api, [options], [callback])` - **api** (_required_) - `string` or `object`
-A [Swagger Object](https://github.com/OAI/OpenAPI-Specification/blob/main/versions/2.0.md#swagger-object), or the file path or URL of your Swagger API. See the [`parse`](#parseapi-options-callback) method for more info. + A [Swagger Object](https://github.com/OAI/OpenAPI-Specification/blob/main/versions/2.0.md#swagger-object), or the file path or URL of your Swagger API. See the [`parse`](#parseapi-options-callback) method for more info. - **options** (_optional_) - `object`
-See [options](options.md) for the full list of options + See [options](options.md) for the full list of options - **callback** (_optional_) - `function(err, api)`
-A callback that will receive the bundled [Swagger object](https://github.com/OAI/OpenAPI-Specification/blob/main/versions/2.0.md#swagger-object). + A callback that will receive the bundled [Swagger object](https://github.com/OAI/OpenAPI-Specification/blob/main/versions/2.0.md#swagger-object). - **Return Value:** `Promise`
-See [Callbacks vs. Promises](README.md#callbacks-vs-promises) + See [Callbacks vs. Promises](README.md#callbacks-vs-promises) -Bundles all referenced files/URLs into a single api that only has _internal_ `$ref` pointers. This lets you split-up your API however you want while you're building it, but easily combine all those files together when it's time to package or distribute the API to other people. The resulting API size will be small, since it will still contain _internal_ JSON references rather than being [fully-dereferenced](#dereferenceapi-options-callback). +Bundles all referenced files/URLs into a single api that only has _internal_ `$ref` pointers. This lets you split-up your API however you want while you're building it, but easily combine all those files together when it's time to package or distribute the API to other people. The resulting API size will be small, since it will still contain _internal_ JSON references rather than being [fully-dereferenced](#dereferenceapi-options-callback). This also eliminates the risk of [circular references](README.md#circular-refs), so the API can be safely serialized using [`JSON.stringify()`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/JSON/stringify). ```javascript -let api = await SwaggerParser.bundle("my-api.yaml"); +let api = await SwaggerParser.bundle('my-api.yaml'); console.log(api.definitions.person); // => {$ref: "#/definitions/schemas~1person.yaml"} ``` - ### `parse(api, [options], [callback])` - **api** (_required_) - `string` or `object`
-A [Swagger Object](https://github.com/OAI/OpenAPI-Specification/blob/main/versions/2.0.md#swagger-object), or the file path or URL of your Swagger API. -

-The path can be absolute or relative. In Node, the path is relative to `process.cwd()`. In the browser, it's relative to the URL of the page. + A [Swagger Object](https://github.com/OAI/OpenAPI-Specification/blob/main/versions/2.0.md#swagger-object), or the file path or URL of your Swagger API. +

+ The path can be absolute or relative. In Node, the path is relative to `process.cwd()`. In the browser, it's relative to the URL of the page. - **options** (_optional_) - `object`
-See [options](options.md) for the full list of options + See [options](options.md) for the full list of options - **callback** (_optional_) - `function(err, api)`
-A callback that will receive the parsed [Swagger object](https://github.com/OAI/OpenAPI-Specification/blob/main/versions/2.0.md#swagger-object), or an error. + A callback that will receive the parsed [Swagger object](https://github.com/OAI/OpenAPI-Specification/blob/main/versions/2.0.md#swagger-object), or an error. - **Return Value:** `Promise`
-See [Callbacks vs. Promises](README.md#callbacks-vs-promises) + See [Callbacks vs. Promises](README.md#callbacks-vs-promises) -> This method is used internally by other methods, such as [`bundle`](#bundleapi-options-callback) and [`dereference`](#dereferenceapi-options-callback). You probably won't need to call this method yourself. +> This method is used internally by other methods, such as [`bundle`](#bundleapi-options-callback) and [`dereference`](#dereferenceapi-options-callback). You probably won't need to call this method yourself. -Parses the given Swagger API (in JSON or YAML format), and returns it as a JavaScript object. This method **does not** resolve `$ref` pointers or dereference anything. It simply parses _one_ file and returns it. +Parses the given Swagger API (in JSON or YAML format), and returns it as a JavaScript object. This method **does not** resolve `$ref` pointers or dereference anything. It simply parses _one_ file and returns it. ```javascript -let api = await SwaggerParser.parse("my-api.yaml"); -console.log("API name: %s, Version: %s", api.info.title, api.info.version); +let api = await SwaggerParser.parse('my-api.yaml'); +console.log('API name: %s, Version: %s', api.info.title, api.info.version); ``` - ### `resolve(api, [options], [callback])` - **api** (_required_) - `string` or `object`
-A [Swagger Object](https://github.com/OAI/OpenAPI-Specification/blob/main/versions/2.0.md#swagger-object), or the file path or URL of your Swagger API. See the [`parse`](#parseapi-options-callback) method for more info. + A [Swagger Object](https://github.com/OAI/OpenAPI-Specification/blob/main/versions/2.0.md#swagger-object), or the file path or URL of your Swagger API. See the [`parse`](#parseapi-options-callback) method for more info. - **options** (_optional_) - `object`
-See [options](options.md) for the full list of options + See [options](options.md) for the full list of options - **callback** (_optional_) - `function(err, $refs)`
-A callback that will receive a [`$Refs`](refs.yaml) object. + A callback that will receive a [`$Refs`](refs.yaml) object. - **Return Value:** `Promise`
-See [Callbacks vs. Promises](README.md#callbacks-vs-promises) + See [Callbacks vs. Promises](README.md#callbacks-vs-promises) -> This method is used internally by other methods, such as [`bundle`](#bundleapi-options-callback) and [`dereference`](#dereferenceapi-options-callback). You probably won't need to call this method yourself. +> This method is used internally by other methods, such as [`bundle`](#bundleapi-options-callback) and [`dereference`](#dereferenceapi-options-callback). You probably won't need to call this method yourself. -Resolves all JSON references (`$ref` pointers) in the given Swagger API. If it references any other files/URLs, then they will be downloaded and resolved as well (unless `options.$refs.external` is false). This method **does not** dereference anything. It simply gives you a [`$Refs`](refs.yaml) object, which is a map of all the resolved references and their values. +Resolves all JSON references (`$ref` pointers) in the given Swagger API. If it references any other files/URLs, then they will be downloaded and resolved as well (unless `options.$refs.external` is false). This method **does not** dereference anything. It simply gives you a [`$Refs`](refs.yaml) object, which is a map of all the resolved references and their values. ```javascript -let $refs = await SwaggerParser.resolve("my-api.yaml"); +let $refs = await SwaggerParser.resolve('my-api.yaml'); // $refs.paths() returns the paths of all the files in your API let filePaths = $refs.paths(); // $refs.get() lets you query parts of your API -let name = $refs.get("schemas/person.yaml#/properties/name"); +let name = $refs.get('schemas/person.yaml#/properties/name'); // $refs.set() lets you change parts of your API -$refs.set("schemas/person.yaml#/properties/favoriteColor/default", "blue"); +$refs.set('schemas/person.yaml#/properties/favoriteColor/default', 'blue'); ``` diff --git a/docs/options.md b/docs/options.md index 6cab66ab..c5a52db6 100644 --- a/docs/options.md +++ b/docs/options.md @@ -2,45 +2,46 @@ All [`OpenAPIParser`](openapi-parser.md) methods accept an optional `options` parameter, which you can use to customize how the API is parsed, resolved, dereferenced, etc. -If you pass an options parameter, you _don't_ need to specify _every_ option. Any options you don't specify will use their default values. +If you pass an options parameter, you _don't_ need to specify _every_ option. Any options you don't specify will use their default values. ## Example ```javascript -OpenAPIParser.validate("my-api.yaml", { - continueOnError: true, // Don't throw on the first error +OpenAPIParser.validate('my-api.yaml', { + continueOnError: true, // Don't throw on the first error parse: { - json: false, // Disable the JSON parser + json: false, // Disable the JSON parser yaml: { - allowEmpty: false // Don't allow empty YAML files + allowEmpty: false, // Don't allow empty YAML files }, text: { - canParse: [".txt", ".html"], // Parse .txt and .html files as plain text (strings) - encoding: 'utf16' // Use UTF-16 encoding - } + canParse: ['.txt', '.html'], // Parse .txt and .html files as plain text (strings) + encoding: 'utf16', // Use UTF-16 encoding + }, }, resolve: { - file: false, // Don't resolve local file references + file: false, // Don't resolve local file references http: { - timeout: 2000, // 2 second timeout - withCredentials: true, // Include auth credentials when resolving HTTP references - } + timeout: 2000, // 2 second timeout + withCredentials: true, // Include auth credentials when resolving HTTP references + }, }, dereference: { - circular: false // Don't allow circular $refs + circular: false, // Don't allow circular $refs }, validate: { - spec: false // Don't validate against the Swagger spec - } + spec: false, // Don't validate against the Swagger spec + }, }); ``` - ## `parse` Options + The `parse` options determine how different types of files will be parsed. -Swagger Parser comes with built-in JSON, YAML, plain-text, and binary parsers, any of which you can configure or disable. You can also add [your own custom parsers](https://apitools.dev/json-schema-ref-parser/docs/plugins/parsers.html) if you want. +Swagger Parser comes with built-in JSON, YAML, plain-text, and binary parsers, any of which you can configure or disable. You can also add [your own custom parsers](https://apitools.dev/json-schema-ref-parser/docs/plugins/parsers.html) if you want. + |Option(s) |Type |Description |:----------------------------|:----------|:------------ |`json`
`yaml`
`text`
`binary`|`object` `boolean`|These are the built-in parsers. In addition, you can add [your own custom parsers](https://apitools.dev/json-schema-ref-parser/docs/plugins/parsers.html)

To disable a parser, just set it to `false`. @@ -48,13 +49,15 @@ Swagger Parser comes with built-in JSON, YAML, plain-text, and binary parsers, a |`json.allowEmpty` `yaml.allowEmpty` `text.allowEmpty` `binary.allowEmpty`|`boolean`|All of the built-in parsers allow empty files by default. The JSON and YAML parsers will parse empty files as `undefined`. The text parser will parse empty files as an empty string. The binary parser will parse empty files as an empty byte array.

You can set `allowEmpty: false` on any parser, which will cause an error to be thrown if a file empty. |`json.canParse` `yaml.canParse` `text.canParse` `binary.canParse`|`boolean`, `RegExp`, `string`, `array`, `function`|Determines which parsers will be used for which files.

A regular expression can be used to match files by their full path. A string (or array of strings) can be used to match files by their file extension. Or a function can be used to perform more complex matching logic. See the [custom parser](https://apitools.dev/json-schema-ref-parser/docs/plugins/parsers.html) docs for details. |`text.encoding`|`string` |The encoding to use when parsing text-based files. The default is "utf8". - + ## `resolve` Options + The `resolve` options control how Swagger Parser will resolve file paths and URLs, and how those files will be read/downloaded. -Swagger Parser comes with built-in support for HTTP and HTTPS, as well as support for local files (when running in Node.js). You can configure or disable either of these built-in resolvers. You can also add [your own custom resolvers](https://apitools.dev/json-schema-ref-parser/docs/plugins/resolvers.html) if you want. +Swagger Parser comes with built-in support for HTTP and HTTPS, as well as support for local files (when running in Node.js). You can configure or disable either of these built-in resolvers. You can also add [your own custom resolvers](https://apitools.dev/json-schema-ref-parser/docs/plugins/resolvers.html) if you want. + |Option(s) |Type |Description |:----------------------------|:----------|:------------ |`external`|`boolean`|Determines whether external $ref pointers will be resolved. If this option is disabled, then external $ref pointers will simply be ignored. @@ -65,25 +68,30 @@ Swagger Parser comes with built-in support for HTTP and HTTPS, as well as suppor |`http.timeout` |`number` |The amount of time (in milliseconds) to wait for a response from the server when downloading files. The default is 5 seconds. |`http.redirects` |`number` |The maximum number of HTTP redirects to follow per file. The default is 5. To disable automatic following of redirects, set this to zero. |`http.withCredentials`|`boolean`|Set this to `true` if you're downloading files from a CORS-enabled server that requires authentication - + ## `dereference` Options + The `dereference` options control how Swagger Parser will dereference `$ref` pointers within the API. + |Option(s) |Type |Description |:---------------------|:-------------------|:------------ |`circular`|`boolean` or `"ignore"`|Determines whether [circular `$ref` pointers](README.md#circular-refs) are handled.

If set to `false`, then a `ReferenceError` will be thrown if the API contains any circular references.

If set to `"ignore"`, then circular references will simply be ignored. No error will be thrown, but the [`$Refs.circular`](refs.md#circular) property will still be set to `true`. - + ## `validate` Options + The `validate` options control how Swagger Parser will validate the API. -Swagger Parser comes with built-in support for validating against the [Swagger 2.0 Schema](https://github.com/OAI/OpenAPI-Specification/blob/main/schemas/v2.0/schema.json), [OpenAPI 3.0 Schema](https://github.com/OAI/OpenAPI-Specification/blob/main/schemas/v3.0/schema.json), and [OpenAPI 3.1 Schema](https://github.com/OAI/OpenAPI-Specification/blob/main/schemas/v3.1/schema.json). It can also validate against the [Swagger 2.0 Specification](https://github.com/OAI/OpenAPI-Specification/blob/main/versions/2.0.md). The specification validator will catch some things that aren't covered by the Swagger 2.0 Schema, such as duplicate parameters, invalid MIME types, etc. +Swagger Parser comes with built-in support for validating against the [Swagger 2.0 Schema](https://github.com/OAI/OpenAPI-Specification/blob/main/schemas/v2.0/schema.json), [OpenAPI 3.0 Schema](https://github.com/OAI/OpenAPI-Specification/blob/main/schemas/v3.0/schema.json), and [OpenAPI 3.1 Schema](https://github.com/OAI/OpenAPI-Specification/blob/main/schemas/v3.1/schema.json). It can also validate against the [Swagger 2.0 Specification](https://github.com/OAI/OpenAPI-Specification/blob/main/versions/2.0.md). The specification validator will catch some things that aren't covered by the Swagger 2.0 Schema, such as duplicate parameters, invalid MIME types, etc. You can disable either (or both) of these built-in validators by setting them to false. + |Option(s) |Type |Description |:---------------------|:-------------------|:------------ |`colorizeErrors`|`boolean`|If set to `true` then validation errors will be colorized and styled. |`schema`|`boolean`|Set to `false` to disable validating against the [Swagger 2.0 Schema](https://github.com/OAI/OpenAPI-Specification/tree/main/schemas/v2.0), [OpenAPI 3.0 Schema](https://github.com/OAI/OpenAPI-Specification/blob/main/schemas/v3.0/schema.json), or [OpenAPI 3.1 Schema](https://github.com/OAI/OpenAPI-Specification/blob/main/schemas/v3.0/schema.json) |`spec`|`boolean`|Set to `false` to disable validating against the [Swagger 2.0 Specification](https://github.com/OAI/OpenAPI-Specification/blob/main/versions/2.0.md). + diff --git a/docs/refs.md b/docs/refs.md index f438bad8..abde8af0 100644 --- a/docs/refs.md +++ b/docs/refs.md @@ -1,126 +1,121 @@ # `$Refs` class -When you call the [`resolve`](openapi-parser.md#resolveschema-options-callback) method, the value that gets passed to the callback function (or Promise) is a `$Refs` object. This same object is accessible via the [`parser.$refs`](openapi-parser.md#refs) property of `OpenAPIParser` objects. - -This object is a map of JSON References and their resolved values. It also has several convenient helper methods that make it easy for you to navigate and manipulate the JSON References. +When you call the [`resolve`](openapi-parser.md#resolveschema-options-callback) method, the value that gets passed to the callback function (or Promise) is a `$Refs` object. This same object is accessible via the [`parser.$refs`](openapi-parser.md#refs) property of `OpenAPIParser` objects. +This object is a map of JSON References and their resolved values. It also has several convenient helper methods that make it easy for you to navigate and manipulate the JSON References. ##### Properties + - [`circular`](#circular) ##### Methods + - [`paths()`](#pathstypes) - [`values()`](#valuestypes) - [`exists()`](#existsref) - [`get()`](#getref-options) - [`set()`](#setref-value-options) - ### `circular` - **Type:** `boolean` -This property is `true` if the API contains any [circular references](README.md#circular-refs). You may want to check this property before serializing the dereferenced schema as JSON, since [`JSON.stringify()`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/JSON/stringify) does not support circular references by default. +This property is `true` if the API contains any [circular references](README.md#circular-refs). You may want to check this property before serializing the dereferenced schema as JSON, since [`JSON.stringify()`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/JSON/stringify) does not support circular references by default. ```javascript let parser = new OpenAPIParser(); -await parser.dereference("my-api.yaml"); +await parser.dereference('my-api.yaml'); if (parser.$refs.circular) { console.log('The API contains circular references'); } ``` - ### `paths([types])` - **types** (_optional_) - `string` (one or more)
-Optionally only return certain types of paths ("file", "http", etc.) + Optionally only return certain types of paths ("file", "http", etc.) - **Return Value:** `array` of `string`
-Returns the paths/URLs of all the files in your API (including the main api file). + Returns the paths/URLs of all the files in your API (including the main api file). ```javascript -let $refs = await OpenAPIParser.resolve("my-api.yaml"); +let $refs = await OpenAPIParser.resolve('my-api.yaml'); // Get the paths of ALL files in the API $refs.paths(); // Get the paths of local files only -$refs.paths("fs"); +$refs.paths('fs'); // Get all URLs -$refs.paths("http", "https"); +$refs.paths('http', 'https'); ``` - ### `values([types])` - **types** (_optional_) - `string` (one or more)
-Optionally only return values from certain locations ("file", "http", etc.) + Optionally only return values from certain locations ("file", "http", etc.) - **Return Value:** `object`
-Returns a map of paths/URLs and their correspond values. + Returns a map of paths/URLs and their correspond values. ```javascript -let $refs = await OpenAPIParser.resolve("my-api.yaml"); +let $refs = await OpenAPIParser.resolve('my-api.yaml'); // Get ALL paths & values in the API // (this is the same as $refs.toJSON()) let values = $refs.values(); -values["schemas/person.yaml"]; -values["http://company.com/my-api.yaml"]; +values['schemas/person.yaml']; +values['http://company.com/my-api.yaml']; ``` - ### `exists($ref)` - **$ref** (_required_) - `string`
-The JSON Reference path, optionally with a JSON Pointer in the hash + The JSON Reference path, optionally with a JSON Pointer in the hash - **Return Value:** `boolean`
-Returns `true` if the given path exists in the API; otherwise, returns `false` + Returns `true` if the given path exists in the API; otherwise, returns `false` ```javascript -let $refs = await OpenAPIParser.resolve("my-api.yaml"); +let $refs = await OpenAPIParser.resolve('my-api.yaml'); -$refs.exists("schemas/person.yaml#/properties/firstName"); // => true -$refs.exists("schemas/person.yaml#/properties/foobar"); // => false +$refs.exists('schemas/person.yaml#/properties/firstName'); // => true +$refs.exists('schemas/person.yaml#/properties/foobar'); // => false ``` - ### `get($ref, [options])` - **$ref** (_required_) - `string`
-The JSON Reference path, optionally with a JSON Pointer in the hash + The JSON Reference path, optionally with a JSON Pointer in the hash - **options** (_optional_) - `object`
-See [options](options.md) for the full list of options + See [options](options.md) for the full list of options - **Return Value:** `boolean`
-Gets the value at the given path in the API. Throws an error if the path does not exist. + Gets the value at the given path in the API. Throws an error if the path does not exist. ```javascript -let $refs = await OpenAPIParser.resolve("my-api.yaml"); -let value = $refs.get("schemas/person.yaml#/properties/firstName"); +let $refs = await OpenAPIParser.resolve('my-api.yaml'); +let value = $refs.get('schemas/person.yaml#/properties/firstName'); ``` - ### `set($ref, value, [options])` - **$ref** (_required_) - `string`
-The JSON Reference path, optionally with a JSON Pointer in the hash + The JSON Reference path, optionally with a JSON Pointer in the hash - **value** (_required_)
-The value to assign. Can be anything (object, string, number, etc.) + The value to assign. Can be anything (object, string, number, etc.) - **options** (_optional_) - `object`
-See [options](options.md) for the full list of options + See [options](options.md) for the full list of options Sets the value at the given path in the API. If the property, or any of its parents, don't exist, they will be created. ```javascript -let $refs = await OpenAPIParser.resolve("my-api.yaml"); -$refs.set("schemas/person.yaml#/properties/favoriteColor/default", "blue"); +let $refs = await OpenAPIParser.resolve('my-api.yaml'); +$refs.set('schemas/person.yaml#/properties/favoriteColor/default', 'blue'); ``` diff --git a/lib/index.d.ts b/lib/index.d.ts index d9d16075..666b6a89 100644 --- a/lib/index.d.ts +++ b/lib/index.d.ts @@ -1,4 +1,4 @@ -import { OpenAPI } from "openapi-types"; +import { OpenAPI } from 'openapi-types'; export = OpenAPIParser; @@ -8,7 +8,6 @@ export = OpenAPIParser; * See https://apitools.dev/swagger-parser/docs/swagger-parser.html */ declare class OpenAPIParser { - /** * The `api` property is the parsed/bundled/dereferenced OpenAPI definition. This is the same value that is passed to the callback function (or Promise) when calling the parse, bundle, or dereference methods. * @@ -36,11 +35,24 @@ declare class OpenAPIParser { * @param callback (optional) A callback that will receive the dereferenced OpenAPI definition */ public validate(api: string | OpenAPI.Document, callback: OpenAPIParser.ApiCallback): void; - public validate(api: string | OpenAPI.Document, options: OpenAPIParser.Options, callback: OpenAPIParser.ApiCallback): void; - public validate(baseUrl: string, api: string | OpenAPI.Document, options: OpenAPIParser.Options, callback: OpenAPIParser.ApiCallback): void; + public validate( + api: string | OpenAPI.Document, + options: OpenAPIParser.Options, + callback: OpenAPIParser.ApiCallback, + ): void; + public validate( + baseUrl: string, + api: string | OpenAPI.Document, + options: OpenAPIParser.Options, + callback: OpenAPIParser.ApiCallback, + ): void; public validate(api: string | OpenAPI.Document): Promise; public validate(api: string | OpenAPI.Document, options: OpenAPIParser.Options): Promise; - public validate(baseUrl: string, api: string | OpenAPI.Document, options: OpenAPIParser.Options): Promise; + public validate( + baseUrl: string, + api: string | OpenAPI.Document, + options: OpenAPIParser.Options, + ): Promise; /** * Parses, dereferences, and validates the given Swagger API. @@ -53,11 +65,24 @@ declare class OpenAPIParser { * @param callback (optional) A callback that will receive the dereferenced OpenAPI definition */ public static validate(api: string | OpenAPI.Document, callback: OpenAPIParser.ApiCallback): void; - public static validate(api: string | OpenAPI.Document, options: OpenAPIParser.Options, callback: OpenAPIParser.ApiCallback): void; - public static validate(baseUrl: string, api: string | OpenAPI.Document, options: OpenAPIParser.Options, callback: OpenAPIParser.ApiCallback): void; + public static validate( + api: string | OpenAPI.Document, + options: OpenAPIParser.Options, + callback: OpenAPIParser.ApiCallback, + ): void; + public static validate( + baseUrl: string, + api: string | OpenAPI.Document, + options: OpenAPIParser.Options, + callback: OpenAPIParser.ApiCallback, + ): void; public static validate(api: string | OpenAPI.Document): Promise; public static validate(api: string | OpenAPI.Document, options: OpenAPIParser.Options): Promise; - public static validate(baseUrl: string, api: string | OpenAPI.Document, options: OpenAPIParser.Options): Promise; + public static validate( + baseUrl: string, + api: string | OpenAPI.Document, + options: OpenAPIParser.Options, + ): Promise; /** * Dereferences all `$ref` pointers in the OpenAPI definition, replacing each reference with its resolved value. This results in an API definition that does not contain any `$ref` pointers. Instead, it's a normal JavaScript object tree that can easily be crawled and used just like any other JavaScript object. This is great for programmatic usage, especially when using tools that don't understand JSON references. @@ -71,11 +96,24 @@ declare class OpenAPIParser { * @param callback (optional) A callback that will receive the dereferenced OpenAPI definition */ public dereference(api: string | OpenAPI.Document, callback: OpenAPIParser.ApiCallback): void; - public dereference(api: string | OpenAPI.Document, options: OpenAPIParser.Options, callback: OpenAPIParser.ApiCallback): void; - public dereference(baseUrl: string, api: string | OpenAPI.Document, options: OpenAPIParser.Options, callback: OpenAPIParser.ApiCallback): void; + public dereference( + api: string | OpenAPI.Document, + options: OpenAPIParser.Options, + callback: OpenAPIParser.ApiCallback, + ): void; + public dereference( + baseUrl: string, + api: string | OpenAPI.Document, + options: OpenAPIParser.Options, + callback: OpenAPIParser.ApiCallback, + ): void; public dereference(api: string | OpenAPI.Document): Promise; public dereference(api: string | OpenAPI.Document, options: OpenAPIParser.Options): Promise; - public dereference(baseUrl: string, api: string | OpenAPI.Document, options: OpenAPIParser.Options): Promise; + public dereference( + baseUrl: string, + api: string | OpenAPI.Document, + options: OpenAPIParser.Options, + ): Promise; /** * Dereferences all `$ref` pointers in the OpenAPI definition, replacing each reference with its resolved value. This results in an API definition that does not contain any `$ref` pointers. Instead, it's a normal JavaScript object tree that can easily be crawled and used just like any other JavaScript object. This is great for programmatic usage, especially when using tools that don't understand JSON references. @@ -89,11 +127,24 @@ declare class OpenAPIParser { * @param callback (optional) A callback that will receive the dereferenced OpenAPI definition */ public static dereference(api: string | OpenAPI.Document, callback: OpenAPIParser.ApiCallback): void; - public static dereference(api: string | OpenAPI.Document, options: OpenAPIParser.Options, callback: OpenAPIParser.ApiCallback): void; - public static dereference(baseUrl: string, api: string | OpenAPI.Document, options: OpenAPIParser.Options, callback: OpenAPIParser.ApiCallback): void; + public static dereference( + api: string | OpenAPI.Document, + options: OpenAPIParser.Options, + callback: OpenAPIParser.ApiCallback, + ): void; + public static dereference( + baseUrl: string, + api: string | OpenAPI.Document, + options: OpenAPIParser.Options, + callback: OpenAPIParser.ApiCallback, + ): void; public static dereference(api: string | OpenAPI.Document): Promise; public static dereference(api: string | OpenAPI.Document, options: OpenAPIParser.Options): Promise; - public static dereference(baseUrl: string, api: string | OpenAPI.Document, options: OpenAPIParser.Options): Promise; + public static dereference( + baseUrl: string, + api: string | OpenAPI.Document, + options: OpenAPIParser.Options, + ): Promise; /** * Bundles all referenced files/URLs into a single API definition that only has internal `$ref` pointers. This lets you split-up your API definition however you want while you're building it, but easily combine all those files together when it's time to package or distribute the API definition to other people. The resulting API definition size will be small, since it will still contain internal JSON references rather than being fully-dereferenced. @@ -107,11 +158,24 @@ declare class OpenAPIParser { * @param callback (optional) A callback that will receive the bundled API definition object */ public bundle(api: string | OpenAPI.Document, callback: OpenAPIParser.ApiCallback): void; - public bundle(api: string | OpenAPI.Document, options: OpenAPIParser.Options, callback: OpenAPIParser.ApiCallback): void; - public bundle(baseUrl: string, api: string | OpenAPI.Document, options: OpenAPIParser.Options, callback: OpenAPIParser.ApiCallback): void; + public bundle( + api: string | OpenAPI.Document, + options: OpenAPIParser.Options, + callback: OpenAPIParser.ApiCallback, + ): void; + public bundle( + baseUrl: string, + api: string | OpenAPI.Document, + options: OpenAPIParser.Options, + callback: OpenAPIParser.ApiCallback, + ): void; public bundle(api: string | OpenAPI.Document): Promise; public bundle(api: string | OpenAPI.Document, options: OpenAPIParser.Options): Promise; - public bundle(baseUrl: string, api: string | OpenAPI.Document, options: OpenAPIParser.Options): Promise; + public bundle( + baseUrl: string, + api: string | OpenAPI.Document, + options: OpenAPIParser.Options, + ): Promise; /** * Bundles all referenced files/URLs into a single API definition that only has internal `$ref` pointers. This lets you split-up your API definition however you want while you're building it, but easily combine all those files together when it's time to package or distribute the API definition to other people. The resulting API definition size will be small, since it will still contain internal JSON references rather than being fully-dereferenced. @@ -125,11 +189,24 @@ declare class OpenAPIParser { * @param callback (optional) A callback that will receive the bundled API definition object */ public static bundle(api: string | OpenAPI.Document, callback: OpenAPIParser.ApiCallback): void; - public static bundle(api: string | OpenAPI.Document, options: OpenAPIParser.Options, callback: OpenAPIParser.ApiCallback): void; - public static bundle(baseUrl: string, api: string | OpenAPI.Document, options: OpenAPIParser.Options, callback: OpenAPIParser.ApiCallback): void; + public static bundle( + api: string | OpenAPI.Document, + options: OpenAPIParser.Options, + callback: OpenAPIParser.ApiCallback, + ): void; + public static bundle( + baseUrl: string, + api: string | OpenAPI.Document, + options: OpenAPIParser.Options, + callback: OpenAPIParser.ApiCallback, + ): void; public static bundle(api: string | OpenAPI.Document): Promise; public static bundle(api: string | OpenAPI.Document, options: OpenAPIParser.Options): Promise; - public static bundle(baseUrl: string, api: string | OpenAPI.Document, options: OpenAPIParser.Options): Promise; + public static bundle( + baseUrl: string, + api: string | OpenAPI.Document, + options: OpenAPIParser.Options, + ): Promise; /** * *This method is used internally by other methods, such as `bundle` and `dereference`. You probably won't need to call this method yourself.* @@ -143,11 +220,24 @@ declare class OpenAPIParser { * @param callback (optional) A callback that will receive the parsed OpenAPI definition object, or an error */ public parse(api: string | OpenAPI.Document, callback: OpenAPIParser.ApiCallback): void; - public parse(api: string | OpenAPI.Document, options: OpenAPIParser.Options, callback: OpenAPIParser.ApiCallback): void; - public parse(baseUrl: string, api: string | OpenAPI.Document, options: OpenAPIParser.Options, callback: OpenAPIParser.ApiCallback): void; + public parse( + api: string | OpenAPI.Document, + options: OpenAPIParser.Options, + callback: OpenAPIParser.ApiCallback, + ): void; + public parse( + baseUrl: string, + api: string | OpenAPI.Document, + options: OpenAPIParser.Options, + callback: OpenAPIParser.ApiCallback, + ): void; public parse(api: string | OpenAPI.Document): Promise; public parse(api: string | OpenAPI.Document, options: OpenAPIParser.Options): Promise; - public parse(baseUrl: string, api: string | OpenAPI.Document, options: OpenAPIParser.Options): Promise; + public parse( + baseUrl: string, + api: string | OpenAPI.Document, + options: OpenAPIParser.Options, + ): Promise; /** * *This method is used internally by other methods, such as `bundle` and `dereference`. You probably won't need to call this method yourself.* @@ -161,11 +251,24 @@ declare class OpenAPIParser { * @param callback (optional) A callback that will receive the parsed OpenAPI definition object, or an error */ public static parse(api: string | OpenAPI.Document, callback: OpenAPIParser.ApiCallback): void; - public static parse(api: string | OpenAPI.Document, options: OpenAPIParser.Options, callback: OpenAPIParser.ApiCallback): void; - public static parse(baseUrl: string, api: string | OpenAPI.Document, options: OpenAPIParser.Options, callback: OpenAPIParser.ApiCallback): void; + public static parse( + api: string | OpenAPI.Document, + options: OpenAPIParser.Options, + callback: OpenAPIParser.ApiCallback, + ): void; + public static parse( + baseUrl: string, + api: string | OpenAPI.Document, + options: OpenAPIParser.Options, + callback: OpenAPIParser.ApiCallback, + ): void; public static parse(api: string | OpenAPI.Document): Promise; public static parse(api: string | OpenAPI.Document, options: OpenAPIParser.Options): Promise; - public static parse(baseUrl: string, api: string | OpenAPI.Document, options: OpenAPIParser.Options): Promise; + public static parse( + baseUrl: string, + api: string | OpenAPI.Document, + options: OpenAPIParser.Options, + ): Promise; /** * *This method is used internally by other methods, such as `bundle` and `dereference`. You probably won't need to call this method yourself.* @@ -179,11 +282,24 @@ declare class OpenAPIParser { * @param callback (optional) A callback that will receive a `$Refs` object */ public resolve(api: string | OpenAPI.Document, callback: OpenAPIParser.$RefsCallback): void; - public resolve(api: string | OpenAPI.Document, options: OpenAPIParser.Options, callback: OpenAPIParser.$RefsCallback): void; - public resolve(baseUrl: string, api: string | OpenAPI.Document, options: OpenAPIParser.Options, callback: OpenAPIParser.$RefsCallback): void; + public resolve( + api: string | OpenAPI.Document, + options: OpenAPIParser.Options, + callback: OpenAPIParser.$RefsCallback, + ): void; + public resolve( + baseUrl: string, + api: string | OpenAPI.Document, + options: OpenAPIParser.Options, + callback: OpenAPIParser.$RefsCallback, + ): void; public resolve(api: string | OpenAPI.Document): Promise; public resolve(api: string | OpenAPI.Document, options: OpenAPIParser.Options): Promise; - public resolve(baseUrl: string, api: string | OpenAPI.Document, options: OpenAPIParser.Options): Promise; + public resolve( + baseUrl: string, + api: string | OpenAPI.Document, + options: OpenAPIParser.Options, + ): Promise; /** * *This method is used internally by other methods, such as `bundle` and `dereference`. You probably won't need to call this method yourself.* @@ -197,16 +313,28 @@ declare class OpenAPIParser { * @param callback (optional) A callback that will receive a `$Refs` object */ public static resolve(api: string | OpenAPI.Document, callback: OpenAPIParser.$RefsCallback): void; - public static resolve(api: string | OpenAPI.Document, options: OpenAPIParser.Options, callback: OpenAPIParser.$RefsCallback): void; - public static resolve(baseUrl: string, api: string | OpenAPI.Document, options: OpenAPIParser.Options, callback: OpenAPIParser.$RefsCallback): void; + public static resolve( + api: string | OpenAPI.Document, + options: OpenAPIParser.Options, + callback: OpenAPIParser.$RefsCallback, + ): void; + public static resolve( + baseUrl: string, + api: string | OpenAPI.Document, + options: OpenAPIParser.Options, + callback: OpenAPIParser.$RefsCallback, + ): void; public static resolve(api: string | OpenAPI.Document): Promise; public static resolve(api: string | OpenAPI.Document, options: OpenAPIParser.Options): Promise; - public static resolve(baseUrl: string, api: string | OpenAPI.Document, options: OpenAPIParser.Options): Promise; + public static resolve( + baseUrl: string, + api: string | OpenAPI.Document, + options: OpenAPIParser.Options, + ): Promise; } // eslint-disable-next-line no-redeclare declare namespace OpenAPIParser { - export type ApiCallback = (err: Error | null, api?: OpenAPI.Document) => any; export type $RefsCallback = (err: Error | null, $refs?: $Refs) => any; @@ -214,7 +342,6 @@ declare namespace OpenAPIParser { * See https://apitools.dev/swagger-parser/docs/options.html */ export interface Options { - /** * The `parse` options determine how different types of files will be parsed. * @@ -233,7 +360,6 @@ declare namespace OpenAPIParser { * JSON Schema `$Ref` Parser comes with built-in support for HTTP and HTTPS, as well as support for local files (when running in Node.js). You can configure or disable either of these built-in resolvers. You can also add your own custom resolvers if you want. */ resolve?: { - /** * Determines whether external $ref pointers will be resolved. If this option is disabled, then external `$ref` pointers will simply be ignored. */ @@ -246,7 +372,6 @@ declare namespace OpenAPIParser { * The `dereference` options control how JSON Schema `$Ref` Parser will dereference `$ref` pointers within the JSON schema. */ dereference?: { - /** * Determines whether circular `$ref` pointers are handled. * @@ -254,7 +379,7 @@ declare namespace OpenAPIParser { * * If set to `"ignore"`, then circular references will simply be ignored. No error will be thrown, but the `$Refs.circular` property will still be set to `true`. */ - circular?: boolean | "ignore"; + circular?: boolean | 'ignore'; }; /** @@ -279,7 +404,6 @@ declare namespace OpenAPIParser { } export interface HTTPResolverOptions extends Partial { - /** * You can specify any HTTP headers that should be sent when downloading files. For example, some servers may require you to set the `Accept` or `Referrer` header. */ @@ -307,7 +431,6 @@ declare namespace OpenAPIParser { * See https://apitools.dev/json-schema-ref-parser/docs/plugins/resolvers.html */ export interface ResolverOptions { - /** * All resolvers have an order property, even the built-in resolvers. If you don't specify an order property, then your resolver will run last. Specifying `order: 1`, like we did in this example, will make your resolver run first. Or you can squeeze your resolver in-between some of the built-in resolvers. For example, `order: 101` would make it run after the file resolver, but before the HTTP resolver. You can see the order of all the built-in resolvers by looking at their source code. * @@ -327,12 +450,11 @@ declare namespace OpenAPIParser { */ read( file: FileInfo, - callback?: (error: Error | null, data: string | null) => any + callback?: (error: Error | null, data: string | null) => any, ): string | Buffer | Promise; } export interface ParserOptions { - /** * Parsers run in a specific order, relative to other parsers. For example, a parser with `order: 5` will run before a parser with `order: 10`. If a parser is unable to successfully parse a file, then the next parser is tried, until one succeeds or they all fail. * @@ -363,7 +485,6 @@ declare namespace OpenAPIParser { * See https://apitools.dev/json-schema-ref-parser/docs/plugins/file-info-object.html */ export interface FileInfo { - /** * The full URL of the file. This could be any type of URL, including "http://", "https://", "file://", "ftp://", "mongodb://", or even a local filesystem path (when running in Node.js). */ @@ -402,7 +523,7 @@ declare namespace OpenAPIParser { * * @param types (optional) Optionally only return certain types of paths ("file", "http", etc.) */ - public paths(...types: string[]): string[] + public paths(...types: string[]): string[]; /** * Returns a map of paths/URLs and their correspond values. @@ -411,7 +532,7 @@ declare namespace OpenAPIParser { * * @param types (optional) Optionally only return values from certain locations ("file", "http", etc.) */ - public values(...types: string[]): { [url: string]: any } + public values(...types: string[]): { [url: string]: any }; /** * Returns `true` if the given path exists in the OpenAPI definition; otherwise, returns `false` @@ -420,7 +541,7 @@ declare namespace OpenAPIParser { * * @param $ref The JSON Reference path, optionally with a JSON Pointer in the hash */ - public exists($ref: string): boolean + public exists($ref: string): boolean; /** * Gets the value at the given path in the OpenAPI definition. Throws an error if the path does not exist. @@ -429,7 +550,7 @@ declare namespace OpenAPIParser { * * @param $ref The JSON Reference path, optionally with a JSON Pointer in the hash */ - public get($ref: string): any + public get($ref: string): any; /** * Sets the value at the given path in the OpenAPI definition. If the property, or any of its parents, don't exist, they will be created. @@ -437,7 +558,6 @@ declare namespace OpenAPIParser { * @param $ref The JSON Reference path, optionally with a JSON Pointer in the hash * @param value The value to assign. Can be anything (object, string, number, etc.) */ - public set($ref: string, value: any): void + public set($ref: string, value: any): void; } - } diff --git a/lib/validators/schema.js b/lib/validators/schema.js index 7895b44a..972b6f04 100644 --- a/lib/validators/schema.js +++ b/lib/validators/schema.js @@ -75,7 +75,7 @@ function validateSchema(api, options) { additionalErrors = reducedErrors.length - 20; reducedErrors = reducedErrors.slice(0, 20); } - } catch (err) { + } catch (error) { // If we failed to stringify the API definition to look at its size then we should process // all of its errors as-is. } diff --git a/package-lock.json b/package-lock.json index 8ab776d4..facb7668 100644 --- a/package-lock.json +++ b/package-lock.json @@ -19,18 +19,16 @@ "call-me-maybe": "^1.0.1" }, "devDependencies": { - "@babel/polyfill": "^7.12.1", "@jsdevtools/host-environment": "^2.1.2", "@readme/eslint-config": "^14.0.0", "@types/node": "^20.12.7", - "chai": "^4.3.8", + "@vitest/coverage-v8": "^1.6.0", "eslint": "^8.56.0", - "mocha": "^10.2.0", - "nyc": "^15.1.0", "openapi-types": "^12.1.3", "prettier": "^3.1.1", "sinon": "^17.0.0", - "typescript": "^5.4.5" + "typescript": "^5.4.5", + "vitest": "^1.6.0" }, "engines": { "node": ">=18" @@ -49,13 +47,13 @@ } }, "node_modules/@ampproject/remapping": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/@ampproject/remapping/-/remapping-2.2.0.tgz", - "integrity": "sha512-qRmjj8nj9qmLTQXXmaR1cck3UXSRMPrbsLJAasZpF+t3riI71BXed5ebIOYwQntykeZuhjsdweEc9BxH5Jc26w==", + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/@ampproject/remapping/-/remapping-2.3.0.tgz", + "integrity": "sha512-30iZtAPgz+LTIYoeivqYo853f02jBYSd5uGnGpkFV0M3xOt9aN73erkgYAmZU43x4VfqcnLxW9Kpg3R5LC4YYw==", "dev": true, "dependencies": { - "@jridgewell/gen-mapping": "^0.1.0", - "@jridgewell/trace-mapping": "^0.3.9" + "@jridgewell/gen-mapping": "^0.3.5", + "@jridgewell/trace-mapping": "^0.3.24" }, "engines": { "node": ">=6.0.0" @@ -86,199 +84,6 @@ "node": ">=6.9.0" } }, - "node_modules/@babel/compat-data": { - "version": "7.17.10", - "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.17.10.tgz", - "integrity": "sha512-GZt/TCsG70Ms19gfZO1tM4CVnXsPgEPBCpJu+Qz3L0LUDsY5nZqFZglIoPC1kIYOtNBZlrnFT+klg12vFGZXrw==", - "dev": true, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/core": { - "version": "7.18.2", - "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.18.2.tgz", - "integrity": "sha512-A8pri1YJiC5UnkdrWcmfZTJTV85b4UXTAfImGmCfYmax4TR9Cw8sDS0MOk++Gp2mE/BefVJ5nwy5yzqNJbP/DQ==", - "dev": true, - "dependencies": { - "@ampproject/remapping": "^2.1.0", - "@babel/code-frame": "^7.16.7", - "@babel/generator": "^7.18.2", - "@babel/helper-compilation-targets": "^7.18.2", - "@babel/helper-module-transforms": "^7.18.0", - "@babel/helpers": "^7.18.2", - "@babel/parser": "^7.18.0", - "@babel/template": "^7.16.7", - "@babel/traverse": "^7.18.2", - "@babel/types": "^7.18.2", - "convert-source-map": "^1.7.0", - "debug": "^4.1.0", - "gensync": "^1.0.0-beta.2", - "json5": "^2.2.1", - "semver": "^6.3.0" - }, - "engines": { - "node": ">=6.9.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/babel" - } - }, - "node_modules/@babel/core/node_modules/semver": { - "version": "6.3.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", - "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", - "dev": true, - "bin": { - "semver": "bin/semver.js" - } - }, - "node_modules/@babel/generator": { - "version": "7.24.4", - "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.24.4.tgz", - "integrity": "sha512-Xd6+v6SnjWVx/nus+y0l1sxMOTOMBkyL4+BIdbALyatQnAe/SRVjANeDPSCYaX+i1iJmuGSKf3Z+E+V/va1Hvw==", - "dev": true, - "dependencies": { - "@babel/types": "^7.24.0", - "@jridgewell/gen-mapping": "^0.3.5", - "@jridgewell/trace-mapping": "^0.3.25", - "jsesc": "^2.5.1" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/generator/node_modules/@jridgewell/gen-mapping": { - "version": "0.3.5", - "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.5.tgz", - "integrity": "sha512-IzL8ZoEDIBRWEzlCcRhOaCupYyN5gdIK+Q6fbFdPDg6HqX6jpkItn7DFIpW9LQzXG6Df9sA7+OKnq0qlz/GaQg==", - "dev": true, - "dependencies": { - "@jridgewell/set-array": "^1.2.1", - "@jridgewell/sourcemap-codec": "^1.4.10", - "@jridgewell/trace-mapping": "^0.3.24" - }, - "engines": { - "node": ">=6.0.0" - } - }, - "node_modules/@babel/helper-compilation-targets": { - "version": "7.18.2", - "resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.18.2.tgz", - "integrity": "sha512-s1jnPotJS9uQnzFtiZVBUxe67CuBa679oWFHpxYYnTpRL/1ffhyX44R9uYiXoa/pLXcY9H2moJta0iaanlk/rQ==", - "dev": true, - "dependencies": { - "@babel/compat-data": "^7.17.10", - "@babel/helper-validator-option": "^7.16.7", - "browserslist": "^4.20.2", - "semver": "^6.3.0" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0" - } - }, - "node_modules/@babel/helper-compilation-targets/node_modules/semver": { - "version": "6.3.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", - "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", - "dev": true, - "bin": { - "semver": "bin/semver.js" - } - }, - "node_modules/@babel/helper-environment-visitor": { - "version": "7.22.20", - "resolved": "https://registry.npmjs.org/@babel/helper-environment-visitor/-/helper-environment-visitor-7.22.20.tgz", - "integrity": "sha512-zfedSIzFhat/gFhWfHtgWvlec0nqB9YEIVrpuwjruLlXfUSnA8cJB0miHKwqDnQ7d32aKo2xt88/xZptwxbfhA==", - "dev": true, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/helper-function-name": { - "version": "7.23.0", - "resolved": "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.23.0.tgz", - "integrity": "sha512-OErEqsrxjZTJciZ4Oo+eoZqeW9UIiOcuYKRJA4ZAgV9myA+pOXhhmpfNCKjEH/auVfEYVFJ6y1Tc4r0eIApqiw==", - "dev": true, - "dependencies": { - "@babel/template": "^7.22.15", - "@babel/types": "^7.23.0" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/helper-hoist-variables": { - "version": "7.22.5", - "resolved": "https://registry.npmjs.org/@babel/helper-hoist-variables/-/helper-hoist-variables-7.22.5.tgz", - "integrity": "sha512-wGjk9QZVzvknA6yKIUURb8zY3grXCcOZt+/7Wcy8O2uctxhplmUPkOdlgoNhmdVee2c92JXbf1xpMtVNbfoxRw==", - "dev": true, - "dependencies": { - "@babel/types": "^7.22.5" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/helper-module-imports": { - "version": "7.16.7", - "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.16.7.tgz", - "integrity": "sha512-LVtS6TqjJHFc+nYeITRo6VLXve70xmq7wPhWTqDJusJEgGmkAACWwMiTNrvfoQo6hEhFwAIixNkvB0jPXDL8Wg==", - "dev": true, - "dependencies": { - "@babel/types": "^7.16.7" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/helper-module-transforms": { - "version": "7.18.0", - "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.18.0.tgz", - "integrity": "sha512-kclUYSUBIjlvnzN2++K9f2qzYKFgjmnmjwL4zlmU5f8ZtzgWe8s0rUPSTGy2HmK4P8T52MQsS+HTQAgZd3dMEA==", - "dev": true, - "dependencies": { - "@babel/helper-environment-visitor": "^7.16.7", - "@babel/helper-module-imports": "^7.16.7", - "@babel/helper-simple-access": "^7.17.7", - "@babel/helper-split-export-declaration": "^7.16.7", - "@babel/helper-validator-identifier": "^7.16.7", - "@babel/template": "^7.16.7", - "@babel/traverse": "^7.18.0", - "@babel/types": "^7.18.0" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/helper-simple-access": { - "version": "7.18.2", - "resolved": "https://registry.npmjs.org/@babel/helper-simple-access/-/helper-simple-access-7.18.2.tgz", - "integrity": "sha512-7LIrjYzndorDY88MycupkpQLKS1AFfsVRm2k/9PtKScSy5tZq0McZTj+DiMRynboZfIqOKvo03pmhTaUgiD6fQ==", - "dev": true, - "dependencies": { - "@babel/types": "^7.18.2" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/helper-split-export-declaration": { - "version": "7.22.6", - "resolved": "https://registry.npmjs.org/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.22.6.tgz", - "integrity": "sha512-AsUnxuLhRYsisFiaJwvp1QF+I3KjD5FOxut14q/GzovUe6orHLesW2C7d754kRm53h5gqrz6sFl6sxc4BVtE/g==", - "dev": true, - "dependencies": { - "@babel/types": "^7.22.5" - }, - "engines": { - "node": ">=6.9.0" - } - }, "node_modules/@babel/helper-string-parser": { "version": "7.24.1", "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.24.1.tgz", @@ -296,29 +101,6 @@ "node": ">=6.9.0" } }, - "node_modules/@babel/helper-validator-option": { - "version": "7.16.7", - "resolved": "https://registry.npmjs.org/@babel/helper-validator-option/-/helper-validator-option-7.16.7.tgz", - "integrity": "sha512-TRtenOuRUVo9oIQGPC5G9DgK4743cdxvtOw0weQNpZXaS16SCBi5MNjZF8vba3ETURjZpTbVn7Vvcf2eAwFozQ==", - "dev": true, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/helpers": { - "version": "7.18.2", - "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.18.2.tgz", - "integrity": "sha512-j+d+u5xT5utcQSzrh9p+PaJX94h++KN+ng9b9WEJq7pkUPAd61FGqhjuUEdfknb3E/uDBb7ruwEeKkIxNJPIrg==", - "dev": true, - "dependencies": { - "@babel/template": "^7.16.7", - "@babel/traverse": "^7.18.2", - "@babel/types": "^7.18.2" - }, - "engines": { - "node": ">=6.9.0" - } - }, "node_modules/@babel/highlight": { "version": "7.24.2", "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.24.2.tgz", @@ -377,17 +159,6 @@ "node": ">=6.0.0" } }, - "node_modules/@babel/polyfill": { - "version": "7.12.1", - "resolved": "https://registry.npmjs.org/@babel/polyfill/-/polyfill-7.12.1.tgz", - "integrity": "sha512-X0pi0V6gxLi6lFZpGmeNa4zxtwEmCs42isWLNjZZDE0Y8yVfgu0T2OAHlzBbdYlqbW/YXVvoBHpATEM+goCj8g==", - "deprecated": "🚨 This package has been deprecated in favor of separate inclusion of a polyfill and regenerator-runtime (when needed). See the @babel/polyfill docs (https://babeljs.io/docs/en/babel-polyfill) for more information.", - "dev": true, - "dependencies": { - "core-js": "^2.6.5", - "regenerator-runtime": "^0.13.4" - } - }, "node_modules/@babel/runtime": { "version": "7.21.0", "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.21.0.tgz", @@ -399,41 +170,6 @@ "node": ">=6.9.0" } }, - "node_modules/@babel/template": { - "version": "7.24.0", - "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.24.0.tgz", - "integrity": "sha512-Bkf2q8lMB0AFpX0NFEqSbx1OkTHf0f+0j82mkw+ZpzBnkk7e9Ql0891vlfgi+kHwOk8tQjiQHpqh4LaSa0fKEA==", - "dev": true, - "dependencies": { - "@babel/code-frame": "^7.23.5", - "@babel/parser": "^7.24.0", - "@babel/types": "^7.24.0" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/traverse": { - "version": "7.24.1", - "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.24.1.tgz", - "integrity": "sha512-xuU6o9m68KeqZbQuDt2TcKSxUw/mrsvavlEqQ1leZ/B+C9tk6E4sRWy97WaXgvq5E+nU3cXMxv3WKOCanVMCmQ==", - "dev": true, - "dependencies": { - "@babel/code-frame": "^7.24.1", - "@babel/generator": "^7.24.1", - "@babel/helper-environment-visitor": "^7.22.20", - "@babel/helper-function-name": "^7.23.0", - "@babel/helper-hoist-variables": "^7.22.5", - "@babel/helper-split-export-declaration": "^7.22.6", - "@babel/parser": "^7.24.1", - "@babel/types": "^7.24.0", - "debug": "^4.3.1", - "globals": "^11.1.0" - }, - "engines": { - "node": ">=6.9.0" - } - }, "node_modules/@babel/types": { "version": "7.24.0", "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.24.0.tgz", @@ -448,97 +184,471 @@ "node": ">=6.9.0" } }, - "node_modules/@eslint-community/eslint-utils": { - "version": "4.4.0", - "resolved": "https://registry.npmjs.org/@eslint-community/eslint-utils/-/eslint-utils-4.4.0.tgz", - "integrity": "sha512-1/sA4dwrzBAyeUoQ6oxahHKmrZvsnLCg4RfxW3ZFGGmQkSNQPFNLV9CUEFQP1x9EYXHTo5p6xdhZM1Ne9p/AfA==", + "node_modules/@bcoe/v8-coverage": { + "version": "0.2.3", + "resolved": "https://registry.npmjs.org/@bcoe/v8-coverage/-/v8-coverage-0.2.3.tgz", + "integrity": "sha512-0hYQ8SB4Db5zvZB4axdMHGwEaQjkZzFjQiN9LVYvIFB2nSUHW9tYpxWriPrWDASIxiaXax83REcLxuSdnGPZtw==", + "dev": true + }, + "node_modules/@esbuild/aix-ppc64": { + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.20.2.tgz", + "integrity": "sha512-D+EBOJHXdNZcLJRBkhENNG8Wji2kgc9AZ9KiPr1JuZjsNtyHzrsfLRrY0tk2H2aoFu6RANO1y1iPPUCDYWkb5g==", + "cpu": [ + "ppc64" + ], "dev": true, - "dependencies": { - "eslint-visitor-keys": "^3.3.0" - }, + "optional": true, + "os": [ + "aix" + ], "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" - }, - "peerDependencies": { - "eslint": "^6.0.0 || ^7.0.0 || >=8.0.0" + "node": ">=12" } }, - "node_modules/@eslint-community/regexpp": { - "version": "4.6.2", - "resolved": "https://registry.npmjs.org/@eslint-community/regexpp/-/regexpp-4.6.2.tgz", - "integrity": "sha512-pPTNuaAG3QMH+buKyBIGJs3g/S5y0caxw0ygM3YyE6yJFySwiGGSzA+mM3KJ8QQvzeLh3blwgSonkFjgQdxzMw==", + "node_modules/@esbuild/android-arm": { + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.20.2.tgz", + "integrity": "sha512-t98Ra6pw2VaDhqNWO2Oph2LXbz/EJcnLmKLGBJwEwXX/JAN83Fym1rU8l0JUWK6HkIbWONCSSatf4sf2NBRx/w==", + "cpu": [ + "arm" + ], "dev": true, + "optional": true, + "os": [ + "android" + ], "engines": { - "node": "^12.0.0 || ^14.0.0 || >=16.0.0" + "node": ">=12" } }, - "node_modules/@eslint/eslintrc": { - "version": "2.1.4", - "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-2.1.4.tgz", - "integrity": "sha512-269Z39MS6wVJtsoUl10L60WdkhJVdPG24Q4eZTH3nnF6lpvSShEK3wQjDX9JRWAUPvPh7COouPpU9IrqaZFvtQ==", + "node_modules/@esbuild/android-arm64": { + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.20.2.tgz", + "integrity": "sha512-mRzjLacRtl/tWU0SvD8lUEwb61yP9cqQo6noDZP/O8VkwafSYwZ4yWy24kan8jE/IMERpYncRt2dw438LP3Xmg==", + "cpu": [ + "arm64" + ], "dev": true, - "dependencies": { - "ajv": "^6.12.4", - "debug": "^4.3.2", - "espree": "^9.6.0", - "globals": "^13.19.0", - "ignore": "^5.2.0", - "import-fresh": "^3.2.1", - "js-yaml": "^4.1.0", - "minimatch": "^3.1.2", - "strip-json-comments": "^3.1.1" - }, + "optional": true, + "os": [ + "android" + ], "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" - }, - "funding": { - "url": "https://opencollective.com/eslint" + "node": ">=12" } }, - "node_modules/@eslint/eslintrc/node_modules/ajv": { - "version": "6.12.6", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", - "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", + "node_modules/@esbuild/android-x64": { + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.20.2.tgz", + "integrity": "sha512-btzExgV+/lMGDDa194CcUQm53ncxzeBrWJcncOBxuC6ndBkKxnHdFJn86mCIgTELsooUmwUm9FkhSp5HYu00Rg==", + "cpu": [ + "x64" + ], "dev": true, - "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" + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=12" } }, - "node_modules/@eslint/eslintrc/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/@eslint/eslintrc/node_modules/globals": { - "version": "13.24.0", - "resolved": "https://registry.npmjs.org/globals/-/globals-13.24.0.tgz", - "integrity": "sha512-AhO5QUcj8llrbG09iWhPU2B204J1xnPeL8kQmVorSsy+Sjj1sk8gIyh6cUocGmH4L0UuhAJy+hJMRA4mgA4mFQ==", + "node_modules/@esbuild/darwin-arm64": { + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.20.2.tgz", + "integrity": "sha512-4J6IRT+10J3aJH3l1yzEg9y3wkTDgDk7TSDFX+wKFiWjqWp/iCfLIYzGyasx9l0SAFPT1HwSCR+0w/h1ES/MjA==", + "cpu": [ + "arm64" + ], "dev": true, - "dependencies": { - "type-fest": "^0.20.2" - }, + "optional": true, + "os": [ + "darwin" + ], "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "node": ">=12" } }, - "node_modules/@eslint/eslintrc/node_modules/js-yaml": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz", - "integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==", + "node_modules/@esbuild/darwin-x64": { + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.20.2.tgz", + "integrity": "sha512-tBcXp9KNphnNH0dfhv8KYkZhjc+H3XBkF5DKtswJblV7KlT9EI2+jeA8DgBjp908WEuYll6pF+UStUCfEpdysA==", + "cpu": [ + "x64" + ], "dev": true, - "dependencies": { - "argparse": "^2.0.1" + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/freebsd-arm64": { + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.20.2.tgz", + "integrity": "sha512-d3qI41G4SuLiCGCFGUrKsSeTXyWG6yem1KcGZVS+3FYlYhtNoNgYrWcvkOoaqMhwXSMrZRl69ArHsGJ9mYdbbw==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/freebsd-x64": { + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.20.2.tgz", + "integrity": "sha512-d+DipyvHRuqEeM5zDivKV1KuXn9WeRX6vqSqIDgwIfPQtwMP4jaDsQsDncjTDDsExT4lR/91OLjRo8bmC1e+Cw==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-arm": { + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.20.2.tgz", + "integrity": "sha512-VhLPeR8HTMPccbuWWcEUD1Az68TqaTYyj6nfE4QByZIQEQVWBB8vup8PpR7y1QHL3CpcF6xd5WVBU/+SBEvGTg==", + "cpu": [ + "arm" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-arm64": { + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.20.2.tgz", + "integrity": "sha512-9pb6rBjGvTFNira2FLIWqDk/uaf42sSyLE8j1rnUpuzsODBq7FvpwHYZxQ/It/8b+QOS1RYfqgGFNLRI+qlq2A==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-ia32": { + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.20.2.tgz", + "integrity": "sha512-o10utieEkNPFDZFQm9CoP7Tvb33UutoJqg3qKf1PWVeeJhJw0Q347PxMvBgVVFgouYLGIhFYG0UGdBumROyiig==", + "cpu": [ + "ia32" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-loong64": { + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.20.2.tgz", + "integrity": "sha512-PR7sp6R/UC4CFVomVINKJ80pMFlfDfMQMYynX7t1tNTeivQ6XdX5r2XovMmha/VjR1YN/HgHWsVcTRIMkymrgQ==", + "cpu": [ + "loong64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-mips64el": { + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.20.2.tgz", + "integrity": "sha512-4BlTqeutE/KnOiTG5Y6Sb/Hw6hsBOZapOVF6njAESHInhlQAghVVZL1ZpIctBOoTFbQyGW+LsVYZ8lSSB3wkjA==", + "cpu": [ + "mips64el" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-ppc64": { + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.20.2.tgz", + "integrity": "sha512-rD3KsaDprDcfajSKdn25ooz5J5/fWBylaaXkuotBDGnMnDP1Uv5DLAN/45qfnf3JDYyJv/ytGHQaziHUdyzaAg==", + "cpu": [ + "ppc64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-riscv64": { + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.20.2.tgz", + "integrity": "sha512-snwmBKacKmwTMmhLlz/3aH1Q9T8v45bKYGE3j26TsaOVtjIag4wLfWSiZykXzXuE1kbCE+zJRmwp+ZbIHinnVg==", + "cpu": [ + "riscv64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-s390x": { + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.20.2.tgz", + "integrity": "sha512-wcWISOobRWNm3cezm5HOZcYz1sKoHLd8VL1dl309DiixxVFoFe/o8HnwuIwn6sXre88Nwj+VwZUvJf4AFxkyrQ==", + "cpu": [ + "s390x" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-x64": { + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.20.2.tgz", + "integrity": "sha512-1MdwI6OOTsfQfek8sLwgyjOXAu+wKhLEoaOLTjbijk6E2WONYpH9ZU2mNtR+lZ2B4uwr+usqGuVfFT9tMtGvGw==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/netbsd-x64": { + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.20.2.tgz", + "integrity": "sha512-K8/DhBxcVQkzYc43yJXDSyjlFeHQJBiowJ0uVL6Tor3jGQfSGHNNJcWxNbOI8v5k82prYqzPuwkzHt3J1T1iZQ==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "netbsd" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/openbsd-x64": { + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.20.2.tgz", + "integrity": "sha512-eMpKlV0SThJmmJgiVyN9jTPJ2VBPquf6Kt/nAoo6DgHAoN57K15ZghiHaMvqjCye/uU4X5u3YSMgVBI1h3vKrQ==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "openbsd" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/sunos-x64": { + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.20.2.tgz", + "integrity": "sha512-2UyFtRC6cXLyejf/YEld4Hajo7UHILetzE1vsRcGL3earZEW77JxrFjH4Ez2qaTiEfMgAXxfAZCm1fvM/G/o8w==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "sunos" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/win32-arm64": { + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.20.2.tgz", + "integrity": "sha512-GRibxoawM9ZCnDxnP3usoUDO9vUkpAxIIZ6GQI+IlVmr5kP3zUq+l17xELTHMWTWzjxa2guPNyrpq1GWmPvcGQ==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/win32-ia32": { + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.20.2.tgz", + "integrity": "sha512-HfLOfn9YWmkSKRQqovpnITazdtquEW8/SoHW7pWpuEeguaZI4QnCRW6b+oZTztdBnZOS2hqJ6im/D5cPzBTTlQ==", + "cpu": [ + "ia32" + ], + "dev": true, + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/win32-x64": { + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.20.2.tgz", + "integrity": "sha512-N49X4lJX27+l9jbLKSqZ6bKNjzQvHaT8IIFUy+YIqmXQdjYCToGWwOItDrfby14c78aDd5NHQl29xingXfCdLQ==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@eslint-community/eslint-utils": { + "version": "4.4.0", + "resolved": "https://registry.npmjs.org/@eslint-community/eslint-utils/-/eslint-utils-4.4.0.tgz", + "integrity": "sha512-1/sA4dwrzBAyeUoQ6oxahHKmrZvsnLCg4RfxW3ZFGGmQkSNQPFNLV9CUEFQP1x9EYXHTo5p6xdhZM1Ne9p/AfA==", + "dev": true, + "dependencies": { + "eslint-visitor-keys": "^3.3.0" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "peerDependencies": { + "eslint": "^6.0.0 || ^7.0.0 || >=8.0.0" + } + }, + "node_modules/@eslint-community/regexpp": { + "version": "4.6.2", + "resolved": "https://registry.npmjs.org/@eslint-community/regexpp/-/regexpp-4.6.2.tgz", + "integrity": "sha512-pPTNuaAG3QMH+buKyBIGJs3g/S5y0caxw0ygM3YyE6yJFySwiGGSzA+mM3KJ8QQvzeLh3blwgSonkFjgQdxzMw==", + "dev": true, + "engines": { + "node": "^12.0.0 || ^14.0.0 || >=16.0.0" + } + }, + "node_modules/@eslint/eslintrc": { + "version": "2.1.4", + "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-2.1.4.tgz", + "integrity": "sha512-269Z39MS6wVJtsoUl10L60WdkhJVdPG24Q4eZTH3nnF6lpvSShEK3wQjDX9JRWAUPvPh7COouPpU9IrqaZFvtQ==", + "dev": true, + "dependencies": { + "ajv": "^6.12.4", + "debug": "^4.3.2", + "espree": "^9.6.0", + "globals": "^13.19.0", + "ignore": "^5.2.0", + "import-fresh": "^3.2.1", + "js-yaml": "^4.1.0", + "minimatch": "^3.1.2", + "strip-json-comments": "^3.1.1" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/@eslint/eslintrc/node_modules/ajv": { + "version": "6.12.6", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", + "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", + "dev": true, + "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/@eslint/eslintrc/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/@eslint/eslintrc/node_modules/globals": { + "version": "13.24.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-13.24.0.tgz", + "integrity": "sha512-AhO5QUcj8llrbG09iWhPU2B204J1xnPeL8kQmVorSsy+Sjj1sk8gIyh6cUocGmH4L0UuhAJy+hJMRA4mgA4mFQ==", + "dev": true, + "dependencies": { + "type-fest": "^0.20.2" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/@eslint/eslintrc/node_modules/js-yaml": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz", + "integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==", + "dev": true, + "dependencies": { + "argparse": "^2.0.1" }, "bin": { "js-yaml": "bin/js-yaml.js" @@ -612,85 +722,36 @@ "integrity": "sha512-6EwiSjwWYP7pTckG6I5eyFANjPhmPjUX9JRLUSfNPC7FX7zK9gyZAfUEaECL6ALTpGX5AjnBq3C9XmVWPitNpw==", "dev": true }, - "node_modules/@istanbuljs/load-nyc-config": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/@istanbuljs/load-nyc-config/-/load-nyc-config-1.1.0.tgz", - "integrity": "sha512-VjeHSlIzpv/NyD3N0YuHfXOPDIixcA1q2ZV98wsMqcYlPmv2n3Yb2lYP9XMElnaFVXg5A7YLTeLu6V84uQDjmQ==", - "dev": true, - "dependencies": { - "camelcase": "^5.3.1", - "find-up": "^4.1.0", - "get-package-type": "^0.1.0", - "js-yaml": "^3.13.1", - "resolve-from": "^5.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/@istanbuljs/load-nyc-config/node_modules/find-up": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz", - "integrity": "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==", - "dev": true, - "dependencies": { - "locate-path": "^5.0.0", - "path-exists": "^4.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/@istanbuljs/load-nyc-config/node_modules/locate-path": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz", - "integrity": "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==", + "node_modules/@istanbuljs/schema": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/@istanbuljs/schema/-/schema-0.1.2.tgz", + "integrity": "sha512-tsAQNx32a8CoFhjhijUIhI4kccIAgmGhy8LZMZgGfmXcpMbPRUqn5LWmgRttILi6yeGmBJd2xsPkFMs0PzgPCw==", "dev": true, - "dependencies": { - "p-locate": "^4.1.0" - }, "engines": { "node": ">=8" } }, - "node_modules/@istanbuljs/load-nyc-config/node_modules/p-locate": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-4.1.0.tgz", - "integrity": "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==", + "node_modules/@jest/schemas": { + "version": "29.6.3", + "resolved": "https://registry.npmjs.org/@jest/schemas/-/schemas-29.6.3.tgz", + "integrity": "sha512-mo5j5X+jIZmJQveBKeS/clAueipV7KgiX1vMgCxam1RNYiqE1w62n0/tJJnHtjW8ZHcQco5gY85jA3mi0L+nSA==", "dev": true, "dependencies": { - "p-limit": "^2.2.0" + "@sinclair/typebox": "^0.27.8" }, "engines": { - "node": ">=8" - } - }, - "node_modules/@istanbuljs/load-nyc-config/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/@istanbuljs/schema": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/@istanbuljs/schema/-/schema-0.1.2.tgz", - "integrity": "sha512-tsAQNx32a8CoFhjhijUIhI4kccIAgmGhy8LZMZgGfmXcpMbPRUqn5LWmgRttILi6yeGmBJd2xsPkFMs0PzgPCw==", - "dev": true, - "engines": { - "node": ">=8" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, "node_modules/@jridgewell/gen-mapping": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.1.1.tgz", - "integrity": "sha512-sQXCasFk+U8lWYEe66WxRDOE9PjVz4vSM51fTu3Hw+ClTpUSQb718772vH3pyS5pShp6lvQM7SxgIDXXXmOX7w==", + "version": "0.3.5", + "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.5.tgz", + "integrity": "sha512-IzL8ZoEDIBRWEzlCcRhOaCupYyN5gdIK+Q6fbFdPDg6HqX6jpkItn7DFIpW9LQzXG6Df9sA7+OKnq0qlz/GaQg==", "dev": true, "dependencies": { - "@jridgewell/set-array": "^1.0.0", - "@jridgewell/sourcemap-codec": "^1.4.10" + "@jridgewell/set-array": "^1.2.1", + "@jridgewell/sourcemap-codec": "^1.4.10", + "@jridgewell/trace-mapping": "^0.3.24" }, "engines": { "node": ">=6.0.0" @@ -979,32 +1040,246 @@ "url": "https://opencollective.com/typescript-eslint" } }, - "node_modules/@readme/json-schema-ref-parser": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/@readme/json-schema-ref-parser/-/json-schema-ref-parser-1.2.0.tgz", - "integrity": "sha512-Bt3QVovFSua4QmHa65EHUmh2xS0XJ3rgTEUPH998f4OW4VVJke3BuS16f+kM0ZLOGdvIrzrPRqwihuv5BAjtrA==", - "dependencies": { - "@jsdevtools/ono": "^7.1.3", - "@types/json-schema": "^7.0.6", - "call-me-maybe": "^1.0.1", - "js-yaml": "^4.1.0" - } + "node_modules/@readme/json-schema-ref-parser": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/@readme/json-schema-ref-parser/-/json-schema-ref-parser-1.2.0.tgz", + "integrity": "sha512-Bt3QVovFSua4QmHa65EHUmh2xS0XJ3rgTEUPH998f4OW4VVJke3BuS16f+kM0ZLOGdvIrzrPRqwihuv5BAjtrA==", + "dependencies": { + "@jsdevtools/ono": "^7.1.3", + "@types/json-schema": "^7.0.6", + "call-me-maybe": "^1.0.1", + "js-yaml": "^4.1.0" + } + }, + "node_modules/@readme/json-schema-ref-parser/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==" + }, + "node_modules/@readme/json-schema-ref-parser/node_modules/js-yaml": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz", + "integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==", + "dependencies": { + "argparse": "^2.0.1" + }, + "bin": { + "js-yaml": "bin/js-yaml.js" + } + }, + "node_modules/@rollup/rollup-android-arm-eabi": { + "version": "4.18.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.18.0.tgz", + "integrity": "sha512-Tya6xypR10giZV1XzxmH5wr25VcZSncG0pZIjfePT0OVBvqNEurzValetGNarVrGiq66EBVAFn15iYX4w6FKgQ==", + "cpu": [ + "arm" + ], + "dev": true, + "optional": true, + "os": [ + "android" + ] + }, + "node_modules/@rollup/rollup-android-arm64": { + "version": "4.18.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.18.0.tgz", + "integrity": "sha512-avCea0RAP03lTsDhEyfy+hpfr85KfyTctMADqHVhLAF3MlIkq83CP8UfAHUssgXTYd+6er6PaAhx/QGv4L1EiA==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "android" + ] + }, + "node_modules/@rollup/rollup-darwin-arm64": { + "version": "4.18.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.18.0.tgz", + "integrity": "sha512-IWfdwU7KDSm07Ty0PuA/W2JYoZ4iTj3TUQjkVsO/6U+4I1jN5lcR71ZEvRh52sDOERdnNhhHU57UITXz5jC1/w==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "darwin" + ] + }, + "node_modules/@rollup/rollup-darwin-x64": { + "version": "4.18.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.18.0.tgz", + "integrity": "sha512-n2LMsUz7Ynu7DoQrSQkBf8iNrjOGyPLrdSg802vk6XT3FtsgX6JbE8IHRvposskFm9SNxzkLYGSq9QdpLYpRNA==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "darwin" + ] + }, + "node_modules/@rollup/rollup-linux-arm-gnueabihf": { + "version": "4.18.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.18.0.tgz", + "integrity": "sha512-C/zbRYRXFjWvz9Z4haRxcTdnkPt1BtCkz+7RtBSuNmKzMzp3ZxdM28Mpccn6pt28/UWUCTXa+b0Mx1k3g6NOMA==", + "cpu": [ + "arm" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-arm-musleabihf": { + "version": "4.18.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-musleabihf/-/rollup-linux-arm-musleabihf-4.18.0.tgz", + "integrity": "sha512-l3m9ewPgjQSXrUMHg93vt0hYCGnrMOcUpTz6FLtbwljo2HluS4zTXFy2571YQbisTnfTKPZ01u/ukJdQTLGh9A==", + "cpu": [ + "arm" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-arm64-gnu": { + "version": "4.18.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.18.0.tgz", + "integrity": "sha512-rJ5D47d8WD7J+7STKdCUAgmQk49xuFrRi9pZkWoRD1UeSMakbcepWXPF8ycChBoAqs1pb2wzvbY6Q33WmN2ftw==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-arm64-musl": { + "version": "4.18.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.18.0.tgz", + "integrity": "sha512-be6Yx37b24ZwxQ+wOQXXLZqpq4jTckJhtGlWGZs68TgdKXJgw54lUUoFYrg6Zs/kjzAQwEwYbp8JxZVzZLRepQ==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-powerpc64le-gnu": { + "version": "4.18.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-powerpc64le-gnu/-/rollup-linux-powerpc64le-gnu-4.18.0.tgz", + "integrity": "sha512-hNVMQK+qrA9Todu9+wqrXOHxFiD5YmdEi3paj6vP02Kx1hjd2LLYR2eaN7DsEshg09+9uzWi2W18MJDlG0cxJA==", + "cpu": [ + "ppc64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-riscv64-gnu": { + "version": "4.18.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.18.0.tgz", + "integrity": "sha512-ROCM7i+m1NfdrsmvwSzoxp9HFtmKGHEqu5NNDiZWQtXLA8S5HBCkVvKAxJ8U+CVctHwV2Gb5VUaK7UAkzhDjlg==", + "cpu": [ + "riscv64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-s390x-gnu": { + "version": "4.18.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-s390x-gnu/-/rollup-linux-s390x-gnu-4.18.0.tgz", + "integrity": "sha512-0UyyRHyDN42QL+NbqevXIIUnKA47A+45WyasO+y2bGJ1mhQrfrtXUpTxCOrfxCR4esV3/RLYyucGVPiUsO8xjg==", + "cpu": [ + "s390x" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-x64-gnu": { + "version": "4.18.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.18.0.tgz", + "integrity": "sha512-xuglR2rBVHA5UsI8h8UbX4VJ470PtGCf5Vpswh7p2ukaqBGFTnsfzxUBetoWBWymHMxbIG0Cmx7Y9qDZzr648w==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-x64-musl": { + "version": "4.18.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.18.0.tgz", + "integrity": "sha512-LKaqQL9osY/ir2geuLVvRRs+utWUNilzdE90TpyoX0eNqPzWjRm14oMEE+YLve4k/NAqCdPkGYDaDF5Sw+xBfg==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ] }, - "node_modules/@readme/json-schema-ref-parser/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==" + "node_modules/@rollup/rollup-win32-arm64-msvc": { + "version": "4.18.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.18.0.tgz", + "integrity": "sha512-7J6TkZQFGo9qBKH0pk2cEVSRhJbL6MtfWxth7Y5YmZs57Pi+4x6c2dStAUvaQkHQLnEQv1jzBUW43GvZW8OFqA==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "win32" + ] }, - "node_modules/@readme/json-schema-ref-parser/node_modules/js-yaml": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz", - "integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==", - "dependencies": { - "argparse": "^2.0.1" - }, - "bin": { - "js-yaml": "bin/js-yaml.js" - } + "node_modules/@rollup/rollup-win32-ia32-msvc": { + "version": "4.18.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.18.0.tgz", + "integrity": "sha512-Txjh+IxBPbkUB9+SXZMpv+b/vnTEtFyfWZgJ6iyCmt2tdx0OF5WhFowLmnh8ENGNpfUlUZkdI//4IEmhwPieNg==", + "cpu": [ + "ia32" + ], + "dev": true, + "optional": true, + "os": [ + "win32" + ] + }, + "node_modules/@rollup/rollup-win32-x64-msvc": { + "version": "4.18.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.18.0.tgz", + "integrity": "sha512-UOo5FdvOL0+eIVTgS4tIdbW+TtnBLWg1YBCcU2KWM7nuNwRz9bksDX1bekJJCpu25N1DVWaCwnT39dVQxzqS8g==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "win32" + ] + }, + "node_modules/@sinclair/typebox": { + "version": "0.27.8", + "resolved": "https://registry.npmjs.org/@sinclair/typebox/-/typebox-0.27.8.tgz", + "integrity": "sha512-+Fj43pSMwJs4KRrH/938Uf+uAELIgVBmQzg/q1YG10djyfA3TnrU8N8XzqCh/okZdszqBQTZf96idMfE5lnwTA==", + "dev": true }, "node_modules/@sinonjs/commons": { "version": "2.0.0", @@ -1050,10 +1325,10 @@ "integrity": "sha512-sXXKG+uL9IrKqViTtao2Ws6dy0znu9sOaP1di/jKGW1M6VssO8vlpXCQcpZ+jisQ1tTFAC5Jo/EOzFbggBagFQ==", "dev": true }, - "node_modules/@types/color-name": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/@types/color-name/-/color-name-1.1.1.tgz", - "integrity": "sha512-rr+OQyAjxze7GgWrSaJwydHStIhHq2lvY3BOC2Mj7KnzI7XK0Uw1TOOdI9lDoajEbSWLiYgoo4f1R51erQfhPQ==", + "node_modules/@types/estree": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.5.tgz", + "integrity": "sha512-/kYRxGDLWzHOB7q+wtSUQlFrtcdUccpfy+X+9iMBpHK8QLLhx2wIPYuS5DYtR9Wa/YlZAbIovy7qVdB1Aq6Lyw==", "dev": true }, "node_modules/@types/json-schema": { @@ -1427,12 +1702,134 @@ "integrity": "sha512-zuVdFrMJiuCDQUMCzQaD6KL28MjnqqN8XnAqiEq9PNm/hCPTSGfrXCOfwj1ow4LFb/tNymJPwsNbVePc1xFqrQ==", "dev": true }, + "node_modules/@vitest/coverage-v8": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/@vitest/coverage-v8/-/coverage-v8-1.6.0.tgz", + "integrity": "sha512-KvapcbMY/8GYIG0rlwwOKCVNRc0OL20rrhFkg/CHNzncV03TE2XWvO5w9uZYoxNiMEBacAJt3unSOiZ7svePew==", + "dev": true, + "dependencies": { + "@ampproject/remapping": "^2.2.1", + "@bcoe/v8-coverage": "^0.2.3", + "debug": "^4.3.4", + "istanbul-lib-coverage": "^3.2.2", + "istanbul-lib-report": "^3.0.1", + "istanbul-lib-source-maps": "^5.0.4", + "istanbul-reports": "^3.1.6", + "magic-string": "^0.30.5", + "magicast": "^0.3.3", + "picocolors": "^1.0.0", + "std-env": "^3.5.0", + "strip-literal": "^2.0.0", + "test-exclude": "^6.0.0" + }, + "funding": { + "url": "https://opencollective.com/vitest" + }, + "peerDependencies": { + "vitest": "1.6.0" + } + }, + "node_modules/@vitest/expect": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/@vitest/expect/-/expect-1.6.0.tgz", + "integrity": "sha512-ixEvFVQjycy/oNgHjqsL6AZCDduC+tflRluaHIzKIsdbzkLn2U/iBnVeJwB6HsIjQBdfMR8Z0tRxKUsvFJEeWQ==", + "dev": true, + "dependencies": { + "@vitest/spy": "1.6.0", + "@vitest/utils": "1.6.0", + "chai": "^4.3.10" + }, + "funding": { + "url": "https://opencollective.com/vitest" + } + }, + "node_modules/@vitest/runner": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/@vitest/runner/-/runner-1.6.0.tgz", + "integrity": "sha512-P4xgwPjwesuBiHisAVz/LSSZtDjOTPYZVmNAnpHHSR6ONrf8eCJOFRvUwdHn30F5M1fxhqtl7QZQUk2dprIXAg==", + "dev": true, + "dependencies": { + "@vitest/utils": "1.6.0", + "p-limit": "^5.0.0", + "pathe": "^1.1.1" + }, + "funding": { + "url": "https://opencollective.com/vitest" + } + }, + "node_modules/@vitest/runner/node_modules/p-limit": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-5.0.0.tgz", + "integrity": "sha512-/Eaoq+QyLSiXQ4lyYV23f14mZRQcXnxfHrN0vCai+ak9G0pp9iEQukIIZq5NccEvwRB8PUnZT0KsOoDCINS1qQ==", + "dev": true, + "dependencies": { + "yocto-queue": "^1.0.0" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/@vitest/runner/node_modules/yocto-queue": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-1.0.0.tgz", + "integrity": "sha512-9bnSc/HEW2uRy67wc+T8UwauLuPJVn28jb+GtJY16iiKWyvmYJRXVT4UamsAEGQfPohgr2q4Tq0sQbQlxTfi1g==", + "dev": true, + "engines": { + "node": ">=12.20" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/@vitest/snapshot": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/@vitest/snapshot/-/snapshot-1.6.0.tgz", + "integrity": "sha512-+Hx43f8Chus+DCmygqqfetcAZrDJwvTj0ymqjQq4CvmpKFSTVteEOBzCusu1x2tt4OJcvBflyHUE0DZSLgEMtQ==", + "dev": true, + "dependencies": { + "magic-string": "^0.30.5", + "pathe": "^1.1.1", + "pretty-format": "^29.7.0" + }, + "funding": { + "url": "https://opencollective.com/vitest" + } + }, + "node_modules/@vitest/spy": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/@vitest/spy/-/spy-1.6.0.tgz", + "integrity": "sha512-leUTap6B/cqi/bQkXUu6bQV5TZPx7pmMBKBQiI0rJA8c3pB56ZsaTbREnF7CJfmvAS4V2cXIBAh/3rVwrrCYgw==", + "dev": true, + "dependencies": { + "tinyspy": "^2.2.0" + }, + "funding": { + "url": "https://opencollective.com/vitest" + } + }, + "node_modules/@vitest/utils": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/@vitest/utils/-/utils-1.6.0.tgz", + "integrity": "sha512-21cPiuGMoMZwiOHa2i4LXkMkMkCGzA+MVFV70jRwHo95dL4x/ts5GZhML1QWuy7yfp3WzK3lRvZi3JnXTYqrBw==", + "dev": true, + "dependencies": { + "diff-sequences": "^29.6.3", + "estree-walker": "^3.0.3", + "loupe": "^2.3.7", + "pretty-format": "^29.7.0" + }, + "funding": { + "url": "https://opencollective.com/vitest" + } + }, "node_modules/acorn": { - "version": "6.4.1", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-6.4.1.tgz", - "integrity": "sha512-ZVA9k326Nwrj3Cj9jlh3wGFutC2ZornPNARZwsNYqQYgN0EsV2d53w5RN/co65Ohn4sUAUtb1rSUAOD6XN9idA==", + "version": "8.11.3", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.11.3.tgz", + "integrity": "sha512-Y9rRfJG5jcKOE0CLisYbojUjIrIEE7AGMzA/Sm4BslANhbS+cDMpgBdcPT91oJ7OuJ9hYJBx59RjbhxVnrF8Xg==", "dev": true, - "peer": true, "bin": { "acorn": "bin/acorn" }, @@ -1449,17 +1846,13 @@ "acorn": "^6.0.0 || ^7.0.0 || ^8.0.0" } }, - "node_modules/aggregate-error": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/aggregate-error/-/aggregate-error-3.1.0.tgz", - "integrity": "sha512-4I7Td01quW/RpocfNayFdFVk1qSuoh0E7JrbRJ16nH01HhKFQ88INq9Sd+nd72zqRySlr9BmDA8xlEJ6vJMrYA==", + "node_modules/acorn-walk": { + "version": "8.3.2", + "resolved": "https://registry.npmjs.org/acorn-walk/-/acorn-walk-8.3.2.tgz", + "integrity": "sha512-cjkyv4OtNCIeqhHrfS81QWXoCBPExR/J62oyEqepVw8WaQeSqpW2uhuLPh1m9eWhDuOo/jUXVTlifvesOWp/4A==", "dev": true, - "dependencies": { - "clean-stack": "^2.0.0", - "indent-string": "^4.0.0" - }, "engines": { - "node": ">=8" + "node": ">=0.4.0" } }, "node_modules/ajv": { @@ -1510,46 +1903,6 @@ "node": ">=4" } }, - "node_modules/anymatch": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.2.tgz", - "integrity": "sha512-P43ePfOAIupkguHUycrc4qJ9kz8ZiuOUijaETwX7THt0Y/GNK7v0aa8rY816xWjZ7rJdA5XdMcpVFTKMq+RvWg==", - "dev": true, - "dependencies": { - "normalize-path": "^3.0.0", - "picomatch": "^2.0.4" - }, - "engines": { - "node": ">= 8" - } - }, - "node_modules/append-transform": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/append-transform/-/append-transform-2.0.0.tgz", - "integrity": "sha512-7yeyCEurROLQJFv5Xj4lEGTy0borxepjFv1g22oAdqFu//SrAlDl1O1Nxx15SH1RoliUml6p8dwJW9jvZughhg==", - "dev": true, - "dependencies": { - "default-require-extensions": "^3.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/archy": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/archy/-/archy-1.0.0.tgz", - "integrity": "sha1-+cjBN1fMHde8N5rHeyxipcKGjEA=", - "dev": true - }, - "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/aria-query": { "version": "5.1.3", "resolved": "https://registry.npmjs.org/aria-query/-/aria-query-5.1.3.tgz", @@ -1779,15 +2132,6 @@ "integrity": "sha1-ibTRmasr7kneFk6gK4nORi1xt2c=", "dev": true }, - "node_modules/binary-extensions": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.1.0.tgz", - "integrity": "sha512-1Yj8h9Q+QDF5FzhMs/c9+6UntbD5MkRfRwac8DoEm9ZfUBZ7tZ55YcGVAzEe4bXsdQHEk+s9S5wsOKVdZrw0tQ==", - "dev": true, - "engines": { - "node": ">=8" - } - }, "node_modules/brace-expansion": { "version": "1.1.11", "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", @@ -1798,12 +2142,6 @@ "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/browserslist": { "version": "4.22.2", "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.22.2.tgz", @@ -1848,54 +2186,15 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/caching-transform": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/caching-transform/-/caching-transform-4.0.0.tgz", - "integrity": "sha512-kpqOvwXnjjN44D89K5ccQC+RUrsy7jB/XLlRrx0D7/2HNcTPqzsb6XgYoErwko6QsV184CA2YgS1fxDiiDZMWA==", - "dev": true, - "dependencies": { - "hasha": "^5.0.0", - "make-dir": "^3.0.0", - "package-hash": "^4.0.0", - "write-file-atomic": "^3.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/caching-transform/node_modules/make-dir": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-3.1.0.tgz", - "integrity": "sha512-g3FeP20LNwhALb/6Cz6Dd4F2ngze0jz7tbzrD2wAV+o9FeNHe4rL+yK2md0J/fiSf1sa1ADhXqi5+oVwOM/eGw==", + "node_modules/cac": { + "version": "6.7.14", + "resolved": "https://registry.npmjs.org/cac/-/cac-6.7.14.tgz", + "integrity": "sha512-b6Ilus+c3RrdDk+JhLKUAQfzzgLEPy6wcXqS7f/xe1EETvsDP6GORG7SFuOs6cID5YkqchW/LXZbX5bc8j7ZcQ==", "dev": true, - "dependencies": { - "semver": "^6.0.0" - }, "engines": { "node": ">=8" } }, - "node_modules/caching-transform/node_modules/semver": { - "version": "6.3.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", - "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", - "dev": true, - "bin": { - "semver": "bin/semver.js" - } - }, - "node_modules/caching-transform/node_modules/write-file-atomic": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/write-file-atomic/-/write-file-atomic-3.0.3.tgz", - "integrity": "sha512-AvHcyZ5JnSfq3ioSyjrBkH9yW4m7Ayk8/9My/DD9onKeu/94fwrMocemO2QAJFAlnnDN+ZDS+ZjAR5ua1/PV/Q==", - "dev": true, - "dependencies": { - "imurmurhash": "^0.1.4", - "is-typedarray": "^1.0.0", - "signal-exit": "^3.0.2", - "typedarray-to-buffer": "^3.1.5" - } - }, "node_modules/call-bind": { "version": "1.0.7", "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.7.tgz", @@ -1929,15 +2228,6 @@ "node": ">=6" } }, - "node_modules/camelcase": { - "version": "5.3.1", - "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-5.3.1.tgz", - "integrity": "sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==", - "dev": true, - "engines": { - "node": ">=6" - } - }, "node_modules/caniuse-lite": { "version": "1.0.30001572", "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001572.tgz", @@ -2033,78 +2323,6 @@ "node": "*" } }, - "node_modules/chokidar": { - "version": "3.5.3", - "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.5.3.tgz", - "integrity": "sha512-Dr3sfKRP6oTcjf2JmUmFJfeVMvXBdegxB0iVQ5eb2V10uFJUCAS8OByZdVAyVb8xXNz3GjjTgj9kLWsZTqE6kw==", - "dev": true, - "funding": [ - { - "type": "individual", - "url": "https://paulmillr.com/funding/" - } - ], - "dependencies": { - "anymatch": "~3.1.2", - "braces": "~3.0.2", - "glob-parent": "~5.1.2", - "is-binary-path": "~2.1.0", - "is-glob": "~4.0.1", - "normalize-path": "~3.0.0", - "readdirp": "~3.6.0" - }, - "engines": { - "node": ">= 8.10.0" - }, - "optionalDependencies": { - "fsevents": "~2.3.2" - } - }, - "node_modules/chokidar/node_modules/braces": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz", - "integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==", - "dev": true, - "dependencies": { - "fill-range": "^7.0.1" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/chokidar/node_modules/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, - "dependencies": { - "to-regex-range": "^5.0.1" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/chokidar/node_modules/is-number": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", - "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", - "dev": true, - "engines": { - "node": ">=0.12.0" - } - }, - "node_modules/chokidar/node_modules/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, - "dependencies": { - "is-number": "^7.0.0" - }, - "engines": { - "node": ">=8.0" - } - }, "node_modules/ci-info": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-4.0.0.tgz", @@ -2117,39 +2335,19 @@ } ], "engines": { - "node": ">=8" - } - }, - "node_modules/clean-regexp": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/clean-regexp/-/clean-regexp-1.0.0.tgz", - "integrity": "sha512-GfisEZEJvzKrmGWkvfhgzcz/BllN1USeqD2V6tg14OAOgaCD2Z/PUEuxnAZ/nPvmaHRG7a8y77p1T/IRQ4D1Hw==", - "dev": true, - "dependencies": { - "escape-string-regexp": "^1.0.5" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/clean-stack": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/clean-stack/-/clean-stack-2.2.0.tgz", - "integrity": "sha512-4diC9HaTE+KRAMWhDhrGOECgWZxoevMc5TlkObMqNSsVU62PYzXZ/SMTjzyGAFF1YusgxGcSWTEXBhp0CPwQ1A==", - "dev": true, - "engines": { - "node": ">=6" + "node": ">=8" } }, - "node_modules/cliui": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/cliui/-/cliui-6.0.0.tgz", - "integrity": "sha512-t6wbgtoCXvAzst7QgXxJYqPt0usEfbgQdftEPbLL/cvv6HPE5VgvqCuAIDR0NgU52ds6rFwqrgakNLrHEjCbrQ==", + "node_modules/clean-regexp": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/clean-regexp/-/clean-regexp-1.0.0.tgz", + "integrity": "sha512-GfisEZEJvzKrmGWkvfhgzcz/BllN1USeqD2V6tg14OAOgaCD2Z/PUEuxnAZ/nPvmaHRG7a8y77p1T/IRQ4D1Hw==", "dev": true, "dependencies": { - "string-width": "^4.2.0", - "strip-ansi": "^6.0.0", - "wrap-ansi": "^6.2.0" + "escape-string-regexp": "^1.0.5" + }, + "engines": { + "node": ">=4" } }, "node_modules/code-error-fragment": { @@ -2173,39 +2371,24 @@ "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", "integrity": "sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==" }, - "node_modules/commondir": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/commondir/-/commondir-1.0.1.tgz", - "integrity": "sha1-3dgA2gxmEnOTzKWVDqloo6rxJTs=", - "dev": true - }, "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/confbox": { + "version": "0.1.7", + "resolved": "https://registry.npmjs.org/confbox/-/confbox-0.1.7.tgz", + "integrity": "sha512-uJcB/FKZtBMCJpK8MQji6bJHgu1tixKPxRLeGkNzBoOZzpnZUJm0jm2/sBDWcuBx1dYgxV4JU+g5hmNxCyAmdA==", + "dev": true + }, "node_modules/confusing-browser-globals": { "version": "1.0.10", "resolved": "https://registry.npmjs.org/confusing-browser-globals/-/confusing-browser-globals-1.0.10.tgz", "integrity": "sha512-gNld/3lySHwuhaVluJUKLePYirM3QNCKzVxqAdhJII9/WXKVX5PURzMVJspS1jTslSqjeuG4KMVTSouit5YPHA==", "dev": true }, - "node_modules/convert-source-map": { - "version": "1.7.0", - "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-1.7.0.tgz", - "integrity": "sha512-4FJkXzKXEDB1snCFZlLP4gpC3JILicCpGbzG9f9G7tGqGCzETQ2hWPrcinA9oU4wtf2biUaEH5065UnMeR33oA==", - "dev": true, - "dependencies": { - "safe-buffer": "~5.1.1" - } - }, - "node_modules/core-js": { - "version": "2.6.11", - "resolved": "https://registry.npmjs.org/core-js/-/core-js-2.6.11.tgz", - "integrity": "sha512-5wjnpaT/3dV+XB4borEsnAYQchn00XSgTAWKDkEqv+K8KevjbzmofK6hfJ9TZIlpj2N0xQpazy7PiRQiWHqzWg==", - "dev": true - }, "node_modules/core-js-compat": { "version": "3.35.0", "resolved": "https://registry.npmjs.org/core-js-compat/-/core-js-compat-3.35.0.tgz", @@ -2219,6 +2402,20 @@ "url": "https://opencollective.com/core-js" } }, + "node_modules/cross-spawn": { + "version": "7.0.3", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz", + "integrity": "sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==", + "dev": true, + "dependencies": { + "path-key": "^3.1.0", + "shebang-command": "^2.0.0", + "which": "^2.0.1" + }, + "engines": { + "node": ">= 8" + } + }, "node_modules/damerau-levenshtein": { "version": "1.0.8", "resolved": "https://registry.npmjs.org/damerau-levenshtein/-/damerau-levenshtein-1.0.8.tgz", @@ -2293,15 +2490,6 @@ } } }, - "node_modules/decamelize": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-1.2.0.tgz", - "integrity": "sha1-9lNNFRSCabIDUue+4m9QH5oZEpA=", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, "node_modules/deep-eql": { "version": "4.1.3", "resolved": "https://registry.npmjs.org/deep-eql/-/deep-eql-4.1.3.tgz", @@ -2354,27 +2542,6 @@ "integrity": "sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==", "dev": true }, - "node_modules/default-require-extensions": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/default-require-extensions/-/default-require-extensions-3.0.0.tgz", - "integrity": "sha512-ek6DpXq/SCpvjhpFsLFRVtIxJCRw6fUR42lYMVZuUMK7n8eMz4Uh5clckdBjEpLhn/gEBZo7hDJnJcwdKLKQjg==", - "dev": true, - "dependencies": { - "strip-bom": "^4.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/default-require-extensions/node_modules/strip-bom": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-4.0.0.tgz", - "integrity": "sha512-3xurFv5tEgii33Zi8Jtp55wEIILR9eh34FAW00PZf+JnSsTmV/ioewSgQl97JHvgjoRGwPShsWm+IdrxB35d0w==", - "dev": true, - "engines": { - "node": ">=8" - } - }, "node_modules/define-data-property": { "version": "1.1.4", "resolved": "https://registry.npmjs.org/define-data-property/-/define-data-property-1.1.4.tgz", @@ -2409,13 +2576,13 @@ "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/diff": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/diff/-/diff-5.0.0.tgz", - "integrity": "sha512-/VTCrvm5Z0JGty/BWHljh+BAiw3IK+2j87NGMu8Nwc/f48WoDAC395uomO9ZD117ZOBaHmkX1oyLvkVM/aIT3w==", + "node_modules/diff-sequences": { + "version": "29.6.3", + "resolved": "https://registry.npmjs.org/diff-sequences/-/diff-sequences-29.6.3.tgz", + "integrity": "sha512-EjePK1srD3P08o2j4f0ExnylqRs5B9tJjcp9t1krH2qRi8CCdsYfwe9JgSLurFBWwq4uOlipzfk5fHNvwFKr8Q==", "dev": true, "engines": { - "node": ">=0.3.1" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, "node_modules/dir-glob": { @@ -2448,12 +2615,6 @@ "integrity": "sha512-1n7zWYh8eS0L9Uy+GskE0lkBUNK83cXTVJI0pU3mGprFsbfSdAc15VTFbo+A+Bq4pwstmL30AVcEU3Fo463lNg==", "dev": true }, - "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/error-ex": { "version": "1.3.2", "resolved": "https://registry.npmjs.org/error-ex/-/error-ex-1.3.2.tgz", @@ -2647,11 +2808,43 @@ "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/es6-error": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/es6-error/-/es6-error-4.1.1.tgz", - "integrity": "sha512-Um/+FxMr9CISWh0bi5Zv0iOD+4cFh5qLeks1qhAopKVAJw3drgKbKySikp7wGhDL0HPeaja0P5ULZrxLkniUVg==", - "dev": true + "node_modules/esbuild": { + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.20.2.tgz", + "integrity": "sha512-WdOOppmUNU+IbZ0PaDiTst80zjnrOkyJNHoKupIcVyU8Lvla3Ugx94VzkQ32Ijqd7UhHJy75gNWDMUekcrSJ6g==", + "dev": true, + "hasInstallScript": true, + "bin": { + "esbuild": "bin/esbuild" + }, + "engines": { + "node": ">=12" + }, + "optionalDependencies": { + "@esbuild/aix-ppc64": "0.20.2", + "@esbuild/android-arm": "0.20.2", + "@esbuild/android-arm64": "0.20.2", + "@esbuild/android-x64": "0.20.2", + "@esbuild/darwin-arm64": "0.20.2", + "@esbuild/darwin-x64": "0.20.2", + "@esbuild/freebsd-arm64": "0.20.2", + "@esbuild/freebsd-x64": "0.20.2", + "@esbuild/linux-arm": "0.20.2", + "@esbuild/linux-arm64": "0.20.2", + "@esbuild/linux-ia32": "0.20.2", + "@esbuild/linux-loong64": "0.20.2", + "@esbuild/linux-mips64el": "0.20.2", + "@esbuild/linux-ppc64": "0.20.2", + "@esbuild/linux-riscv64": "0.20.2", + "@esbuild/linux-s390x": "0.20.2", + "@esbuild/linux-x64": "0.20.2", + "@esbuild/netbsd-x64": "0.20.2", + "@esbuild/openbsd-x64": "0.20.2", + "@esbuild/sunos-x64": "0.20.2", + "@esbuild/win32-arm64": "0.20.2", + "@esbuild/win32-ia32": "0.20.2", + "@esbuild/win32-x64": "0.20.2" + } }, "node_modules/escalade": { "version": "3.1.1", @@ -3563,20 +3756,6 @@ "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==", "dev": true }, - "node_modules/eslint/node_modules/cross-spawn": { - "version": "7.0.3", - "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz", - "integrity": "sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==", - "dev": true, - "dependencies": { - "path-key": "^3.1.0", - "shebang-command": "^2.0.0", - "which": "^2.0.1" - }, - "engines": { - "node": ">= 8" - } - }, "node_modules/eslint/node_modules/escape-string-regexp": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz", @@ -3729,36 +3908,6 @@ "node": ">=8" } }, - "node_modules/eslint/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/eslint/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/eslint/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/eslint/node_modules/type-fest": { "version": "0.20.2", "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.20.2.tgz", @@ -3771,21 +3920,6 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/eslint/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/espree": { "version": "9.6.1", "resolved": "https://registry.npmjs.org/espree/-/espree-9.6.1.tgz", @@ -3803,31 +3937,6 @@ "url": "https://opencollective.com/eslint" } }, - "node_modules/espree/node_modules/acorn": { - "version": "8.11.3", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.11.3.tgz", - "integrity": "sha512-Y9rRfJG5jcKOE0CLisYbojUjIrIEE7AGMzA/Sm4BslANhbS+cDMpgBdcPT91oJ7OuJ9hYJBx59RjbhxVnrF8Xg==", - "dev": true, - "bin": { - "acorn": "bin/acorn" - }, - "engines": { - "node": ">=0.4.0" - } - }, - "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/esquery": { "version": "1.5.0", "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.5.0.tgz", @@ -3879,6 +3988,15 @@ "node": ">=4.0" } }, + "node_modules/estree-walker": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/estree-walker/-/estree-walker-3.0.3.tgz", + "integrity": "sha512-7RUKfXgSMMkzt6ZuXmqapOurLGPPfgj6l9uRZ7lRGolvk0y2yocc35LdcxKC5PQZdn2DMqioAQ2NoWcrTKmm6g==", + "dev": true, + "dependencies": { + "@types/estree": "^1.0.0" + } + }, "node_modules/esutils": { "version": "2.0.3", "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz", @@ -3888,6 +4006,41 @@ "node": ">=0.10.0" } }, + "node_modules/execa": { + "version": "8.0.1", + "resolved": "https://registry.npmjs.org/execa/-/execa-8.0.1.tgz", + "integrity": "sha512-VyhnebXciFV2DESc+p6B+y0LjSm0krU4OgJN44qFAhBY0TJ+1V61tYD2+wHusZ6F9n5K+vl8k0sTy7PEfV4qpg==", + "dev": true, + "dependencies": { + "cross-spawn": "^7.0.3", + "get-stream": "^8.0.1", + "human-signals": "^5.0.0", + "is-stream": "^3.0.0", + "merge-stream": "^2.0.0", + "npm-run-path": "^5.1.0", + "onetime": "^6.0.0", + "signal-exit": "^4.1.0", + "strip-final-newline": "^3.0.0" + }, + "engines": { + "node": ">=16.17" + }, + "funding": { + "url": "https://github.com/sindresorhus/execa?sponsor=1" + } + }, + "node_modules/execa/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/fast-deep-equal": { "version": "3.1.3", "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", @@ -4000,136 +4153,49 @@ "node": "^10.12.0 || >=12.0.0" } }, - "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": "3.0.4", - "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-3.0.4.tgz", - "integrity": "sha512-dm9s5Pw7Jc0GvMYbshN6zchCA9RgQlzzEZX3vylR9IqFfS8XciblUXOKfW6SiuJ0e13eDYZoZV5wdrev7P3Nwg==", - "dev": true, - "dependencies": { - "flatted": "^3.1.0", - "rimraf": "^3.0.2" - }, - "engines": { - "node": "^10.12.0 || >=12.0.0" - } - }, - "node_modules/flat-cache/node_modules/rimraf": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", - "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==", - "dev": true, - "dependencies": { - "glob": "^7.1.3" - }, - "bin": { - "rimraf": "bin.js" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, - "node_modules/flatted": { - "version": "3.2.5", - "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.2.5.tgz", - "integrity": "sha512-WIWGi2L3DyTUvUrwRKgGi9TwxQMUEqPOPQBVi71R96jZXJdFskXEmf54BoZaS1kknGODoIGASGEzBUYdyMCBJg==", - "dev": true - }, - "node_modules/for-each": { - "version": "0.3.3", - "resolved": "https://registry.npmjs.org/for-each/-/for-each-0.3.3.tgz", - "integrity": "sha512-jqYfLp7mo9vIyQf8ykW2v7A+2N4QjeCeI5+Dz9XraiO1ign81wjiH7Fb9vSOWvQfNtmSa4H2RoQTrrXivdUZmw==", - "dev": true, - "dependencies": { - "is-callable": "^1.1.3" - } - }, - "node_modules/foreground-child": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/foreground-child/-/foreground-child-2.0.0.tgz", - "integrity": "sha512-dCIq9FpEcyQyXKCkyzmlPTFNgrCzPudOe+mhvJU5zAtlBnGVy2yKxtfsxK2tQBThwq225jcvBjpw1Gr40uzZCA==", - "dev": true, - "dependencies": { - "cross-spawn": "^7.0.0", - "signal-exit": "^3.0.2" - }, - "engines": { - "node": ">=8.0.0" - } - }, - "node_modules/foreground-child/node_modules/cross-spawn": { - "version": "7.0.3", - "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz", - "integrity": "sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==", - "dev": true, - "dependencies": { - "path-key": "^3.1.0", - "shebang-command": "^2.0.0", - "which": "^2.0.1" - }, - "engines": { - "node": ">= 8" - } - }, - "node_modules/foreground-child/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/foreground-child/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/foreground-child/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==", + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-3.0.4.tgz", + "integrity": "sha512-dm9s5Pw7Jc0GvMYbshN6zchCA9RgQlzzEZX3vylR9IqFfS8XciblUXOKfW6SiuJ0e13eDYZoZV5wdrev7P3Nwg==", "dev": true, + "dependencies": { + "flatted": "^3.1.0", + "rimraf": "^3.0.2" + }, "engines": { - "node": ">=8" + "node": "^10.12.0 || >=12.0.0" } }, - "node_modules/foreground-child/node_modules/which": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", - "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", + "node_modules/flat-cache/node_modules/rimraf": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", + "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==", "dev": true, "dependencies": { - "isexe": "^2.0.0" + "glob": "^7.1.3" }, "bin": { - "node-which": "bin/node-which" + "rimraf": "bin.js" }, - "engines": { - "node": ">= 8" + "funding": { + "url": "https://github.com/sponsors/isaacs" } }, - "node_modules/fromentries": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/fromentries/-/fromentries-1.2.1.tgz", - "integrity": "sha512-Xu2Qh8yqYuDhQGOhD5iJGninErSfI9A3FrriD3tjUgV5VbJFeH8vfgZ9HnC6jWN80QDVNQK5vmxRAmEAp7Mevw==", + "node_modules/flatted": { + "version": "3.2.5", + "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.2.5.tgz", + "integrity": "sha512-WIWGi2L3DyTUvUrwRKgGi9TwxQMUEqPOPQBVi71R96jZXJdFskXEmf54BoZaS1kknGODoIGASGEzBUYdyMCBJg==", "dev": true }, + "node_modules/for-each": { + "version": "0.3.3", + "resolved": "https://registry.npmjs.org/for-each/-/for-each-0.3.3.tgz", + "integrity": "sha512-jqYfLp7mo9vIyQf8ykW2v7A+2N4QjeCeI5+Dz9XraiO1ign81wjiH7Fb9vSOWvQfNtmSa4H2RoQTrrXivdUZmw==", + "dev": true, + "dependencies": { + "is-callable": "^1.1.3" + } + }, "node_modules/fs.realpath": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", @@ -4137,9 +4203,9 @@ "dev": true }, "node_modules/fsevents": { - "version": "2.3.2", - "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.2.tgz", - "integrity": "sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==", + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz", + "integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==", "dev": true, "hasInstallScript": true, "optional": true, @@ -4186,24 +4252,6 @@ "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/gensync": { - "version": "1.0.0-beta.2", - "resolved": "https://registry.npmjs.org/gensync/-/gensync-1.0.0-beta.2.tgz", - "integrity": "sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg==", - "dev": true, - "engines": { - "node": ">=6.9.0" - } - }, - "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-func-name": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/get-func-name/-/get-func-name-2.0.2.tgz", @@ -4232,13 +4280,16 @@ "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/get-package-type": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/get-package-type/-/get-package-type-0.1.0.tgz", - "integrity": "sha512-pjzuKtY64GYfWizNAJ0fr9VqttZkNiK2iS430LtIHzjBEr6bX8Am2zm4sW4Ro5wjWW5cAlRL1qAMTcXbjNAO2Q==", + "node_modules/get-stream": { + "version": "8.0.1", + "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-8.0.1.tgz", + "integrity": "sha512-VaUJspBffn/LMCJVoMvSAdmscJyS1auj5Zulnn5UoYcY531UWmdwhRWkcGKnGU93m5HSXP9LP2usOryrBtQowA==", "dev": true, "engines": { - "node": ">=8.0.0" + "node": ">=16" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, "node_modules/get-symbol-description": { @@ -4302,15 +4353,6 @@ "node": ">= 6" } }, - "node_modules/globals": { - "version": "11.12.0", - "resolved": "https://registry.npmjs.org/globals/-/globals-11.12.0.tgz", - "integrity": "sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA==", - "dev": true, - "engines": { - "node": ">=4" - } - }, "node_modules/globalthis": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/globalthis/-/globalthis-1.0.3.tgz", @@ -4455,37 +4497,6 @@ "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/hasha": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/hasha/-/hasha-5.2.0.tgz", - "integrity": "sha512-2W+jKdQbAdSIrggA8Q35Br8qKadTrqCTC8+XZvBWepKDK6m9XkX6Iz1a2yh2KP01kzAR/dpuMeUnocoLYDcskw==", - "dev": true, - "dependencies": { - "is-stream": "^2.0.0", - "type-fest": "^0.8.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/hasha/node_modules/is-stream": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-2.0.0.tgz", - "integrity": "sha512-XCoy+WlUr7d1+Z8GgSuXmpuUFC9fOhRXglJMx+dwLKTkL44Cjd4W1Z5P+BQZpr+cR93aGP4S/s7Ftw6Nd/kiEw==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/hasha/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/hasown": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.2.tgz", @@ -4498,15 +4509,6 @@ "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", @@ -4519,6 +4521,15 @@ "integrity": "sha512-H2iMtd0I4Mt5eYiapRdIDjp+XzelXQ0tFE4JS7YFwFevXXMmOp9myNrUvCg0D6ws8iqkRPBfKHgbwig1SmlLfg==", "dev": true }, + "node_modules/human-signals": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/human-signals/-/human-signals-5.0.0.tgz", + "integrity": "sha512-AXcZb6vzzrFAUE61HnN4mpLqd/cSIwNQjtNWR0euPm6y0iqx3G4gOXaIDdtdDwZmhwe82LA6+zinmW4UBWVePQ==", + "dev": true, + "engines": { + "node": ">=16.17.0" + } + }, "node_modules/ignore": { "version": "5.3.0", "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.3.0.tgz", @@ -4666,18 +4677,6 @@ "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/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, - "dependencies": { - "binary-extensions": "^2.0.0" - }, - "engines": { - "node": ">=8" - } - }, "node_modules/is-boolean-object": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/is-boolean-object/-/is-boolean-object-1.1.2.tgz", @@ -4784,15 +4783,6 @@ "url": "https://github.com/sponsors/ljharb" } }, - "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/is-generator-function": { "version": "1.0.10", "resolved": "https://registry.npmjs.org/is-generator-function/-/is-generator-function-1.0.10.tgz", @@ -4905,6 +4895,18 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/is-stream": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-3.0.0.tgz", + "integrity": "sha512-LnQR4bZ9IADDRSkvpqMGvt/tEJWclzklNgSw48V5EAaAeDd6qGvN8ei6k5p0tvxSR171VmGyHuTiAOfxAbr8kA==", + "dev": true, + "engines": { + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/is-string": { "version": "1.0.7", "resolved": "https://registry.npmjs.org/is-string/-/is-string-1.0.7.tgz", @@ -4950,24 +4952,6 @@ "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/is-typedarray": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-typedarray/-/is-typedarray-1.0.0.tgz", - "integrity": "sha1-5HnICFjfDBsR3dppQPlgEfzaSpo=", - "dev": true - }, - "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/is-weakmap": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/is-weakmap/-/is-weakmap-2.0.1.tgz", @@ -5002,15 +4986,6 @@ "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/is-windows": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/is-windows/-/is-windows-1.0.2.tgz", - "integrity": "sha512-eXK1UInq2bPmjyX6e3VHIzMLobc4J94i4AWn+Hpq3OU5KkrRC96OAcR3PRJ/pGu6m8TRnBHP9dkXQVsT/COVIA==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, "node_modules/isexe": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", @@ -5018,208 +4993,46 @@ "dev": true }, "node_modules/istanbul-lib-coverage": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/istanbul-lib-coverage/-/istanbul-lib-coverage-3.0.0.tgz", - "integrity": "sha512-UiUIqxMgRDET6eR+o5HbfRYP1l0hqkWOs7vNxC/mggutCMUIhWMm8gAHb8tHlyfD3/l6rlgNA5cKdDzEAf6hEg==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/istanbul-lib-hook": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/istanbul-lib-hook/-/istanbul-lib-hook-3.0.0.tgz", - "integrity": "sha512-Pt/uge1Q9s+5VAZ+pCo16TYMWPBIl+oaNIjgLQxcX0itS6ueeaA+pEfThZpH8WxhFgCiEb8sAJY6MdUKgiIWaQ==", - "dev": true, - "dependencies": { - "append-transform": "^2.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/istanbul-lib-instrument": { - "version": "4.0.3", - "resolved": "https://registry.npmjs.org/istanbul-lib-instrument/-/istanbul-lib-instrument-4.0.3.tgz", - "integrity": "sha512-BXgQl9kf4WTCPCCpmFGoJkz/+uhvm7h7PFKUYxh7qarQd3ER33vHG//qaE8eN25l07YqZPpHXU9I09l/RD5aGQ==", - "dev": true, - "dependencies": { - "@babel/core": "^7.7.5", - "@istanbuljs/schema": "^0.1.2", - "istanbul-lib-coverage": "^3.0.0", - "semver": "^6.3.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/istanbul-lib-instrument/node_modules/semver": { - "version": "6.3.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", - "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", - "dev": true, - "bin": { - "semver": "bin/semver.js" - } - }, - "node_modules/istanbul-lib-processinfo": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/istanbul-lib-processinfo/-/istanbul-lib-processinfo-2.0.2.tgz", - "integrity": "sha512-kOwpa7z9hme+IBPZMzQ5vdQj8srYgAtaRqeI48NGmAQ+/5yKiHLV0QbYqQpxsdEF0+w14SoB8YbnHKcXE2KnYw==", - "dev": true, - "dependencies": { - "archy": "^1.0.0", - "cross-spawn": "^7.0.0", - "istanbul-lib-coverage": "^3.0.0-alpha.1", - "make-dir": "^3.0.0", - "p-map": "^3.0.0", - "rimraf": "^3.0.0", - "uuid": "^3.3.3" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/istanbul-lib-processinfo/node_modules/cross-spawn": { - "version": "7.0.3", - "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz", - "integrity": "sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==", - "dev": true, - "dependencies": { - "path-key": "^3.1.0", - "shebang-command": "^2.0.0", - "which": "^2.0.1" - }, - "engines": { - "node": ">= 8" - } - }, - "node_modules/istanbul-lib-processinfo/node_modules/make-dir": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-3.1.0.tgz", - "integrity": "sha512-g3FeP20LNwhALb/6Cz6Dd4F2ngze0jz7tbzrD2wAV+o9FeNHe4rL+yK2md0J/fiSf1sa1ADhXqi5+oVwOM/eGw==", - "dev": true, - "dependencies": { - "semver": "^6.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/istanbul-lib-processinfo/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/istanbul-lib-processinfo/node_modules/rimraf": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", - "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==", - "dev": true, - "dependencies": { - "glob": "^7.1.3" - }, - "bin": { - "rimraf": "bin.js" - } - }, - "node_modules/istanbul-lib-processinfo/node_modules/semver": { - "version": "6.3.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", - "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", - "dev": true, - "bin": { - "semver": "bin/semver.js" - } - }, - "node_modules/istanbul-lib-processinfo/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/istanbul-lib-processinfo/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==", + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/istanbul-lib-coverage/-/istanbul-lib-coverage-3.2.2.tgz", + "integrity": "sha512-O8dpsF+r0WV/8MNRKfnmrtCWhuKjxrq2w+jpzBL5UZKTi2LeVWnWOmWRxFlesJONmc+wLAGvKQZEOanko0LFTg==", "dev": true, "engines": { "node": ">=8" } }, - "node_modules/istanbul-lib-processinfo/node_modules/uuid": { - "version": "3.4.0", - "resolved": "https://registry.npmjs.org/uuid/-/uuid-3.4.0.tgz", - "integrity": "sha512-HjSDRw6gZE5JMggctHBcjVak08+KEVhSIiDzFnT9S9aegmp85S/bReBVTb4QTFaRNptJ9kuYaNhnbNEOkbKb/A==", - "dev": true, - "bin": { - "uuid": "bin/uuid" - } - }, - "node_modules/istanbul-lib-processinfo/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/istanbul-lib-report": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/istanbul-lib-report/-/istanbul-lib-report-3.0.0.tgz", - "integrity": "sha512-wcdi+uAKzfiGT2abPpKZ0hSU1rGQjUQnLvtY5MpQ7QCTahD3VODhcu4wcfY1YtkGaDD5yuydOLINXsfbus9ROw==", + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/istanbul-lib-report/-/istanbul-lib-report-3.0.1.tgz", + "integrity": "sha512-GCfE1mtsHGOELCU8e/Z7YWzpmybrx/+dSTfLrvY8qRmaY6zXTKWn6WQIjaAFw069icm6GVMNkgu0NzI4iPZUNw==", "dev": true, "dependencies": { "istanbul-lib-coverage": "^3.0.0", - "make-dir": "^3.0.0", + "make-dir": "^4.0.0", "supports-color": "^7.1.0" }, "engines": { - "node": ">=8" + "node": ">=10" } }, - "node_modules/istanbul-lib-report/node_modules/make-dir": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-3.1.0.tgz", - "integrity": "sha512-g3FeP20LNwhALb/6Cz6Dd4F2ngze0jz7tbzrD2wAV+o9FeNHe4rL+yK2md0J/fiSf1sa1ADhXqi5+oVwOM/eGw==", + "node_modules/istanbul-lib-source-maps": { + "version": "5.0.4", + "resolved": "https://registry.npmjs.org/istanbul-lib-source-maps/-/istanbul-lib-source-maps-5.0.4.tgz", + "integrity": "sha512-wHOoEsNJTVltaJp8eVkm8w+GVkVNHT2YDYo53YdzQEL2gWm1hBX5cGFR9hQJtuGLebidVX7et3+dmDZrmclduw==", "dev": true, "dependencies": { - "semver": "^6.0.0" + "@jridgewell/trace-mapping": "^0.3.23", + "debug": "^4.1.1", + "istanbul-lib-coverage": "^3.0.0" }, "engines": { - "node": ">=8" - } - }, - "node_modules/istanbul-lib-report/node_modules/semver": { - "version": "6.3.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", - "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", - "dev": true, - "bin": { - "semver": "bin/semver.js" + "node": ">=10" } }, "node_modules/istanbul-reports": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/istanbul-reports/-/istanbul-reports-3.0.2.tgz", - "integrity": "sha512-9tZvz7AiR3PEDNGiV9vIouQ/EAcqMXFmkcA1CDFTwOB98OZVDL0PH9glHotf5Ugp6GCOTypfzGWI/OqjWNCRUw==", + "version": "3.1.7", + "resolved": "https://registry.npmjs.org/istanbul-reports/-/istanbul-reports-3.1.7.tgz", + "integrity": "sha512-BewmUXImeuRk2YY0PVbxgKAysvhRPUQE0h5QRM++nVWyubKGV0l8qQ5op8+B2DOmwSe63Jivj0BjkPQVf8fP5g==", "dev": true, "dependencies": { "html-escaper": "^2.0.0", @@ -5247,31 +5060,6 @@ "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==" }, - "node_modules/js-yaml": { - "version": "3.14.0", - "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.14.0.tgz", - "integrity": "sha512-/4IbIeHcD9VMHFqDR/gQ7EdZdLimOvW2DdcxFjdyyZ9NsbS+ccrXqVWDtab/lRl5AlUqmpBx8EhPaWR+OtY17A==", - "dev": true, - "dependencies": { - "argparse": "^1.0.7", - "esprima": "^4.0.0" - }, - "bin": { - "js-yaml": "bin/js-yaml.js" - } - }, - "node_modules/jsesc": { - "version": "2.5.2", - "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-2.5.2.tgz", - "integrity": "sha512-OYu7XEzjkCQ3C5Ps3QIZsQfNpqoJyZZA99wd9aWd05NCtC5pWOkShK2mkL6HXQR6/Cy2lbNdPlZBpuQHXE63gA==", - "dev": true, - "bin": { - "jsesc": "bin/jsesc" - }, - "engines": { - "node": ">=4" - } - }, "node_modules/json-parse-even-better-errors": { "version": "2.3.1", "resolved": "https://registry.npmjs.org/json-parse-even-better-errors/-/json-parse-even-better-errors-2.3.1.tgz", @@ -5307,18 +5095,6 @@ "node": ">= 4" } }, - "node_modules/json5": { - "version": "2.2.3", - "resolved": "https://registry.npmjs.org/json5/-/json5-2.2.3.tgz", - "integrity": "sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg==", - "dev": true, - "bin": { - "json5": "lib/cli.js" - }, - "engines": { - "node": ">=6" - } - }, "node_modules/jsonpointer": { "version": "5.0.0", "resolved": "https://registry.npmjs.org/jsonpointer/-/jsonpointer-5.0.0.tgz", @@ -5364,430 +5140,193 @@ "integrity": "sha512-qJhlO9cGXi6hBGKoxEG/sKZDAHD5Hnu9Hs4WbOY3pCWXDhw0N8x1NenNzm2EnNLkLkk7J2SdxAkDSbb6ftT+UQ==", "dev": true, "dependencies": { - "language-subtag-registry": "~0.3.2" - } - }, - "node_modules/leven": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/leven/-/leven-3.1.0.tgz", - "integrity": "sha512-qsda+H8jTaUaN/x5vzW2rzc+8Rw4TAQ/4KjB46IwK5VH+IlVeeeje/EoZRpiXvIqjFgK84QffqPztGI3VBLG1A==", - "engines": { - "node": ">=6" - } - }, - "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/lines-and-columns": { - "version": "1.2.4", - "resolved": "https://registry.npmjs.org/lines-and-columns/-/lines-and-columns-1.2.4.tgz", - "integrity": "sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg==", - "dev": true - }, - "node_modules/lodash": { - "version": "4.17.21", - "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz", - "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==", - "dev": true - }, - "node_modules/lodash.flattendeep": { - "version": "4.4.0", - "resolved": "https://registry.npmjs.org/lodash.flattendeep/-/lodash.flattendeep-4.4.0.tgz", - "integrity": "sha1-+wMJF/hqMTTlvJvsDWngAT3f7bI=", - "dev": true - }, - "node_modules/lodash.get": { - "version": "4.4.2", - "resolved": "https://registry.npmjs.org/lodash.get/-/lodash.get-4.4.2.tgz", - "integrity": "sha512-z+Uw/vLuy6gQe8cfaFWD7p0wVv8fJl3mbzXh33RS+0oW2wvUqiRXiQ69gLWSLpgB5/6sU+r6BlQR0MBILadqTQ==", - "dev": true - }, - "node_modules/lodash.merge": { - "version": "4.6.2", - "resolved": "https://registry.npmjs.org/lodash.merge/-/lodash.merge-4.6.2.tgz", - "integrity": "sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==", - "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/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/loupe": { - "version": "2.3.6", - "resolved": "https://registry.npmjs.org/loupe/-/loupe-2.3.6.tgz", - "integrity": "sha512-RaPMZKiMy8/JruncMU5Bt6na1eftNoo++R4Y+N2FrxkDVTrGvcyzFTsaGif4QTeKESheMGegbhw6iUAq+5A8zA==", - "dev": true, - "dependencies": { - "get-func-name": "^2.0.0" - } - }, - "node_modules/merge2": { - "version": "1.4.1", - "resolved": "https://registry.npmjs.org/merge2/-/merge2-1.4.1.tgz", - "integrity": "sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==", - "dev": true, - "engines": { - "node": ">= 8" - } - }, - "node_modules/min-indent": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/min-indent/-/min-indent-1.0.1.tgz", - "integrity": "sha512-I9jwMn07Sy/IwOj3zVkVik2JTvgpaykDZEigL6Rx6N9LbMywwUSMtxET+7lVoDLLd3O3IXwJwvuuns8UB/HeAg==", - "dev": true, - "engines": { - "node": ">=4" - } - }, - "node_modules/minimatch": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", - "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", - "dev": true, - "dependencies": { - "brace-expansion": "^1.1.7" - }, - "engines": { - "node": "*" - } - }, - "node_modules/minimist": { - "version": "1.2.8", - "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.8.tgz", - "integrity": "sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==", - "dev": true, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/mocha": { - "version": "10.4.0", - "resolved": "https://registry.npmjs.org/mocha/-/mocha-10.4.0.tgz", - "integrity": "sha512-eqhGB8JKapEYcC4ytX/xrzKforgEc3j1pGlAXVy3eRwrtAy5/nIfT1SvgGzfN0XZZxeLq0aQWkOUAmqIJiv+bA==", - "dev": true, - "dependencies": { - "ansi-colors": "4.1.1", - "browser-stdout": "1.3.1", - "chokidar": "3.5.3", - "debug": "4.3.4", - "diff": "5.0.0", - "escape-string-regexp": "4.0.0", - "find-up": "5.0.0", - "glob": "8.1.0", - "he": "1.2.0", - "js-yaml": "4.1.0", - "log-symbols": "4.1.0", - "minimatch": "5.0.1", - "ms": "2.1.3", - "serialize-javascript": "6.0.0", - "strip-json-comments": "3.1.1", - "supports-color": "8.1.1", - "workerpool": "6.2.1", - "yargs": "16.2.0", - "yargs-parser": "20.2.4", - "yargs-unparser": "2.0.0" - }, - "bin": { - "_mocha": "bin/_mocha", - "mocha": "bin/mocha.js" - }, - "engines": { - "node": ">= 14.0.0" - } - }, - "node_modules/mocha/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/mocha/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/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.1", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", - "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", - "dev": true, - "dependencies": { - "balanced-match": "^1.0.0" - } - }, - "node_modules/mocha/node_modules/cliui": { - "version": "7.0.4", - "resolved": "https://registry.npmjs.org/cliui/-/cliui-7.0.4.tgz", - "integrity": "sha512-OcRE68cOsVMXp1Yvonl/fzkQOyjLSu/8bhPDfQt0e0/Eb283TKP20Fs2MqoPsr9SwA595rRCA+QMzYc9nBP+JQ==", - "dev": true, - "dependencies": { - "string-width": "^4.2.0", - "strip-ansi": "^6.0.0", - "wrap-ansi": "^7.0.0" - } - }, - "node_modules/mocha/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/mocha/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/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" - } - }, - "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" - } - }, - "node_modules/mocha/node_modules/glob": { - "version": "8.1.0", - "resolved": "https://registry.npmjs.org/glob/-/glob-8.1.0.tgz", - "integrity": "sha512-r8hpEjiQEYlF2QU0df3dS+nxxSIreXQS1qRhMJM0Q5NDdR386C7jb7Hwwod8Fgiuex+k0GFjgft18yvxm5XoCQ==", - "dev": true, - "dependencies": { - "fs.realpath": "^1.0.0", - "inflight": "^1.0.4", - "inherits": "2", - "minimatch": "^5.0.1", - "once": "^1.3.0" - }, - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, - "node_modules/mocha/node_modules/js-yaml": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz", - "integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==", - "dev": true, - "dependencies": { - "argparse": "^2.0.1" - }, - "bin": { - "js-yaml": "bin/js-yaml.js" + "language-subtag-registry": "~0.3.2" } }, - "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==", + "node_modules/leven": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/leven/-/leven-3.1.0.tgz", + "integrity": "sha512-qsda+H8jTaUaN/x5vzW2rzc+8Rw4TAQ/4KjB46IwK5VH+IlVeeeje/EoZRpiXvIqjFgK84QffqPztGI3VBLG1A==", + "engines": { + "node": ">=6" + } + }, + "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": { - "p-locate": "^5.0.0" + "prelude-ls": "^1.2.1", + "type-check": "~0.4.0" }, "engines": { - "node": ">=10" + "node": ">= 0.8.0" } }, - "node_modules/mocha/node_modules/minimatch": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-5.0.1.tgz", - "integrity": "sha512-nLDxIFRyhDblz3qMuq+SoRZED4+miJ/G+tdDrjkkkRnjAsBexeGpgjLEQ0blJy7rHhR2b93rhQY4SvyWu9v03g==", + "node_modules/lines-and-columns": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/lines-and-columns/-/lines-and-columns-1.2.4.tgz", + "integrity": "sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg==", + "dev": true + }, + "node_modules/local-pkg": { + "version": "0.5.0", + "resolved": "https://registry.npmjs.org/local-pkg/-/local-pkg-0.5.0.tgz", + "integrity": "sha512-ok6z3qlYyCDS4ZEU27HaU6x/xZa9Whf8jD4ptH5UZTQYZVYeb9bnZ3ojVhiJNLiXK1Hfc0GNbLXcmZ5plLDDBg==", "dev": true, "dependencies": { - "brace-expansion": "^2.0.1" + "mlly": "^1.4.2", + "pkg-types": "^1.0.3" }, "engines": { - "node": ">=10" + "node": ">=14" + }, + "funding": { + "url": "https://github.com/sponsors/antfu" } }, - "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==", + "node_modules/lodash": { + "version": "4.17.21", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz", + "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==", "dev": true }, - "node_modules/mocha/node_modules/p-limit": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.0.2.tgz", - "integrity": "sha512-iwqZSOoWIW+Ew4kAGUlN16J4M7OB3ysMLSZtnhmqx7njIHFPlxWBX8xo3lVTyFVq6mI/lL9qt2IsN1sHwaxJkg==", + "node_modules/lodash.get": { + "version": "4.4.2", + "resolved": "https://registry.npmjs.org/lodash.get/-/lodash.get-4.4.2.tgz", + "integrity": "sha512-z+Uw/vLuy6gQe8cfaFWD7p0wVv8fJl3mbzXh33RS+0oW2wvUqiRXiQ69gLWSLpgB5/6sU+r6BlQR0MBILadqTQ==", + "dev": true + }, + "node_modules/lodash.merge": { + "version": "4.6.2", + "resolved": "https://registry.npmjs.org/lodash.merge/-/lodash.merge-4.6.2.tgz", + "integrity": "sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==", + "dev": true + }, + "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": { - "p-try": "^2.0.0" + "js-tokens": "^3.0.0 || ^4.0.0" }, - "engines": { - "node": ">=10" + "bin": { + "loose-envify": "cli.js" } }, - "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==", + "node_modules/loupe": { + "version": "2.3.7", + "resolved": "https://registry.npmjs.org/loupe/-/loupe-2.3.7.tgz", + "integrity": "sha512-zSMINGVYkdpYSOBmLi0D1Uo7JU9nVdQKrHxC8eYlV+9YKK9WePqAlL7lSlorG/U2Fw1w0hTBmaa/jrQ3UbPHtA==", "dev": true, "dependencies": { - "p-limit": "^3.0.2" - }, - "engines": { - "node": ">=10" + "get-func-name": "^2.0.1" } }, - "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==", + "node_modules/magic-string": { + "version": "0.30.10", + "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.30.10.tgz", + "integrity": "sha512-iIRwTIf0QKV3UAnYK4PU8uiEc4SRh5jX0mwpIwETPpHdhVM4f53RSwS/vXvN1JhGX+Cs7B8qIq3d6AH49O5fAQ==", "dev": true, - "engines": { - "node": ">=8" + "dependencies": { + "@jridgewell/sourcemap-codec": "^1.4.15" } }, - "node_modules/mocha/node_modules/serialize-javascript": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-6.0.0.tgz", - "integrity": "sha512-Qr3TosvguFt8ePWqsvRfrKyQXIiW+nGbYpy8XK24NQHE83caxWt+mIymTT19DGFbNWNLfEwsrkSmN64lVWB9ag==", + "node_modules/magicast": { + "version": "0.3.4", + "resolved": "https://registry.npmjs.org/magicast/-/magicast-0.3.4.tgz", + "integrity": "sha512-TyDF/Pn36bBji9rWKHlZe+PZb6Mx5V8IHCSxk7X4aljM4e/vyDvZZYwHewdVaqiA0nb3ghfHU/6AUpDxWoER2Q==", "dev": true, "dependencies": { - "randombytes": "^2.1.0" + "@babel/parser": "^7.24.4", + "@babel/types": "^7.24.0", + "source-map-js": "^1.2.0" } }, - "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==", + "node_modules/make-dir": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-4.0.0.tgz", + "integrity": "sha512-hXdUTZYIVOt1Ex//jAQi+wTZZpUpwBj/0QsOzqegb3rGMMeJiSEu5xLHnYfBrRV4RH2+OCSOO95Is/7x1WJ4bw==", "dev": true, "dependencies": { - "has-flag": "^4.0.0" + "semver": "^7.5.3" }, "engines": { "node": ">=10" }, "funding": { - "url": "https://github.com/chalk/supports-color?sponsor=1" + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/mocha/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==", + "node_modules/merge-stream": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/merge-stream/-/merge-stream-2.0.0.tgz", + "integrity": "sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w==", + "dev": true + }, + "node_modules/merge2": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/merge2/-/merge2-1.4.1.tgz", + "integrity": "sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==", "dev": true, - "dependencies": { - "ansi-styles": "^4.0.0", - "string-width": "^4.1.0", - "strip-ansi": "^6.0.0" - }, "engines": { - "node": ">=10" + "node": ">= 8" + } + }, + "node_modules/mimic-fn": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-4.0.0.tgz", + "integrity": "sha512-vqiC06CuhBTUdZH+RYl8sFrL096vA45Ok5ISO6sE/Mr1jRbGH4Csnhi8f3wKVl7x8mO4Au7Ir9D3Oyv1VYMFJw==", + "dev": true, + "engines": { + "node": ">=12" }, "funding": { - "url": "https://github.com/chalk/wrap-ansi?sponsor=1" + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/mocha/node_modules/y18n": { - "version": "5.0.8", - "resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz", - "integrity": "sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==", + "node_modules/min-indent": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/min-indent/-/min-indent-1.0.1.tgz", + "integrity": "sha512-I9jwMn07Sy/IwOj3zVkVik2JTvgpaykDZEigL6Rx6N9LbMywwUSMtxET+7lVoDLLd3O3IXwJwvuuns8UB/HeAg==", "dev": true, "engines": { - "node": ">=10" + "node": ">=4" } }, - "node_modules/mocha/node_modules/yargs": { - "version": "16.2.0", - "resolved": "https://registry.npmjs.org/yargs/-/yargs-16.2.0.tgz", - "integrity": "sha512-D1mvvtDG0L5ft/jGWkLpG1+m0eQxOfaBvTNELraWj22wSVUMWxZUvYgJYcKh6jGGIkJFhH4IZPQhR4TKpc8mBw==", + "node_modules/minimatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", "dev": true, "dependencies": { - "cliui": "^7.0.2", - "escalade": "^3.1.1", - "get-caller-file": "^2.0.5", - "require-directory": "^2.1.1", - "string-width": "^4.2.0", - "y18n": "^5.0.5", - "yargs-parser": "^20.2.2" + "brace-expansion": "^1.1.7" }, "engines": { - "node": ">=10" + "node": "*" } }, - "node_modules/mocha/node_modules/yargs-parser": { - "version": "20.2.4", - "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-20.2.4.tgz", - "integrity": "sha512-WOkpgNhPTlE73h4VFAFsOnomJVaovO8VqLDzy5saChRBFQFBoMYirowyW+Q9HB4HFF4Z7VZTiG3iSzJJA29yRA==", + "node_modules/minimist": { + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.8.tgz", + "integrity": "sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==", "dev": true, - "engines": { - "node": ">=10" + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/mlly": { + "version": "1.7.0", + "resolved": "https://registry.npmjs.org/mlly/-/mlly-1.7.0.tgz", + "integrity": "sha512-U9SDaXGEREBYQgfejV97coK0UL1r+qnF2SyO9A3qcI8MzKnsIFKHNVEkrDyNncQTKQQumsasmeq84eNMdBfsNQ==", + "dev": true, + "dependencies": { + "acorn": "^8.11.3", + "pathe": "^1.1.2", + "pkg-types": "^1.1.0", + "ufo": "^1.5.3" } }, "node_modules/ms": { @@ -5796,6 +5335,24 @@ "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", "dev": true }, + "node_modules/nanoid": { + "version": "3.3.7", + "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.7.tgz", + "integrity": "sha512-eSRppjcPIatRIMC1U6UngP8XFcz8MQWGQdt1MTBQ7NaAmvXDfvNxbvWV3x2y6CdEUciCSsDHDQZbhYaB8QEo2g==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "bin": { + "nanoid": "bin/nanoid.cjs" + }, + "engines": { + "node": "^10 || ^12 || ^13.7 || ^14 || >=15.0.1" + } + }, "node_modules/natural-compare": { "version": "1.4.0", "resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz", @@ -5824,236 +5381,73 @@ "node_modules/nise/node_modules/@sinonjs/fake-timers": { "version": "10.3.0", "resolved": "https://registry.npmjs.org/@sinonjs/fake-timers/-/fake-timers-10.3.0.tgz", - "integrity": "sha512-V4BG07kuYSUkTCSBHG8G8TNhM+F19jXFWnQtzj+we8DrkpSBCee9Z3Ms8yiGer/dlmhe35/Xdgyo3/0rQKg7YA==", - "dev": true, - "dependencies": { - "@sinonjs/commons": "^3.0.0" - } - }, - "node_modules/nise/node_modules/@sinonjs/fake-timers/node_modules/@sinonjs/commons": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/@sinonjs/commons/-/commons-3.0.0.tgz", - "integrity": "sha512-jXBtWAF4vmdNmZgD5FoKsVLv3rPgDnLgPbU84LIJ3otV44vJlDRokVng5v8NFJdCf/da9legHcKaRuZs4L7faA==", - "dev": true, - "dependencies": { - "type-detect": "4.0.8" - } - }, - "node_modules/node-preload": { - "version": "0.2.1", - "resolved": "https://registry.npmjs.org/node-preload/-/node-preload-0.2.1.tgz", - "integrity": "sha512-RM5oyBy45cLEoHqCeh+MNuFAxO0vTFBLskvQbOKnEE7YTTSN4tbN8QWDIPQ6L+WvKsB/qLEGpYe2ZZ9d4W9OIQ==", - "dev": true, - "dependencies": { - "process-on-spawn": "^1.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/node-releases": { - "version": "2.0.14", - "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.14.tgz", - "integrity": "sha512-y10wOWt8yZpqXmOgRo77WaHEmhYQYGNA6y421PKsKYWEK8aW+cqAphborZDhqfyKrbZEN92CN1X2KbafY2s7Yw==", - "dev": true - }, - "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/semver": { - "version": "5.7.2", - "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.2.tgz", - "integrity": "sha512-cBznnQ9KjJqU67B52RMC65CMarK2600WFnbkcaiwWq3xy/5haFJlshgnpjovMVJ+Hff49d8GEn0b87C5pDQ10g==", - "dev": true, - "bin": { - "semver": "bin/semver" - } - }, - "node_modules/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, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/nyc": { - "version": "15.1.0", - "resolved": "https://registry.npmjs.org/nyc/-/nyc-15.1.0.tgz", - "integrity": "sha512-jMW04n9SxKdKi1ZMGhvUTHBN0EICCRkHemEoE5jm6mTYcqcdas0ATzgUgejlQUHMvpnOZqGB5Xxsv9KxJW1j8A==", - "dev": true, - "dependencies": { - "@istanbuljs/load-nyc-config": "^1.0.0", - "@istanbuljs/schema": "^0.1.2", - "caching-transform": "^4.0.0", - "convert-source-map": "^1.7.0", - "decamelize": "^1.2.0", - "find-cache-dir": "^3.2.0", - "find-up": "^4.1.0", - "foreground-child": "^2.0.0", - "get-package-type": "^0.1.0", - "glob": "^7.1.6", - "istanbul-lib-coverage": "^3.0.0", - "istanbul-lib-hook": "^3.0.0", - "istanbul-lib-instrument": "^4.0.0", - "istanbul-lib-processinfo": "^2.0.2", - "istanbul-lib-report": "^3.0.0", - "istanbul-lib-source-maps": "^4.0.0", - "istanbul-reports": "^3.0.2", - "make-dir": "^3.0.0", - "node-preload": "^0.2.1", - "p-map": "^3.0.0", - "process-on-spawn": "^1.0.0", - "resolve-from": "^5.0.0", - "rimraf": "^3.0.0", - "signal-exit": "^3.0.2", - "spawn-wrap": "^2.0.0", - "test-exclude": "^6.0.0", - "yargs": "^15.0.2" - }, - "bin": { - "nyc": "bin/nyc.js" - }, - "engines": { - "node": ">=8.9" - } - }, - "node_modules/nyc/node_modules/find-cache-dir": { - "version": "3.3.1", - "resolved": "https://registry.npmjs.org/find-cache-dir/-/find-cache-dir-3.3.1.tgz", - "integrity": "sha512-t2GDMt3oGC/v+BMwzmllWDuJF/xcDtE5j/fCGbqDD7OLuJkj0cfh1YSA5VKPvwMeLFLNDBkwOKZ2X85jGLVftQ==", - "dev": true, - "dependencies": { - "commondir": "^1.0.1", - "make-dir": "^3.0.2", - "pkg-dir": "^4.1.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/nyc/node_modules/find-up": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz", - "integrity": "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==", - "dev": true, - "dependencies": { - "locate-path": "^5.0.0", - "path-exists": "^4.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/nyc/node_modules/istanbul-lib-source-maps": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/istanbul-lib-source-maps/-/istanbul-lib-source-maps-4.0.0.tgz", - "integrity": "sha512-c16LpFRkR8vQXyHZ5nLpY35JZtzj1PQY1iZmesUbf1FZHbIupcWfjgOXBY9YHkLEQ6puz1u4Dgj6qmU/DisrZg==", - "dev": true, - "dependencies": { - "debug": "^4.1.1", - "istanbul-lib-coverage": "^3.0.0", - "source-map": "^0.6.1" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/nyc/node_modules/locate-path": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz", - "integrity": "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==", - "dev": true, - "dependencies": { - "p-locate": "^4.1.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/nyc/node_modules/make-dir": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-3.1.0.tgz", - "integrity": "sha512-g3FeP20LNwhALb/6Cz6Dd4F2ngze0jz7tbzrD2wAV+o9FeNHe4rL+yK2md0J/fiSf1sa1ADhXqi5+oVwOM/eGw==", - "dev": true, - "dependencies": { - "semver": "^6.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/nyc/node_modules/p-locate": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-4.1.0.tgz", - "integrity": "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==", + "integrity": "sha512-V4BG07kuYSUkTCSBHG8G8TNhM+F19jXFWnQtzj+we8DrkpSBCee9Z3Ms8yiGer/dlmhe35/Xdgyo3/0rQKg7YA==", "dev": true, "dependencies": { - "p-limit": "^2.2.0" - }, - "engines": { - "node": ">=8" + "@sinonjs/commons": "^3.0.0" } }, - "node_modules/nyc/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==", + "node_modules/nise/node_modules/@sinonjs/fake-timers/node_modules/@sinonjs/commons": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/@sinonjs/commons/-/commons-3.0.0.tgz", + "integrity": "sha512-jXBtWAF4vmdNmZgD5FoKsVLv3rPgDnLgPbU84LIJ3otV44vJlDRokVng5v8NFJdCf/da9legHcKaRuZs4L7faA==", "dev": true, - "engines": { - "node": ">=8" + "dependencies": { + "type-detect": "4.0.8" } }, - "node_modules/nyc/node_modules/pkg-dir": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-4.2.0.tgz", - "integrity": "sha512-HRDzbaKjC+AOWVXxAU/x54COGeIv9eb+6CkDSQoNTt4XyWoIJvuPsXizxu/Fr23EiekbtZwmh1IcIG/l/a10GQ==", + "node_modules/node-releases": { + "version": "2.0.14", + "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.14.tgz", + "integrity": "sha512-y10wOWt8yZpqXmOgRo77WaHEmhYQYGNA6y421PKsKYWEK8aW+cqAphborZDhqfyKrbZEN92CN1X2KbafY2s7Yw==", + "dev": true + }, + "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": { - "find-up": "^4.0.0" - }, - "engines": { - "node": ">=8" + "hosted-git-info": "^2.1.4", + "resolve": "^1.10.0", + "semver": "2 || 3 || 4 || 5", + "validate-npm-package-license": "^3.0.1" } }, - "node_modules/nyc/node_modules/rimraf": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", - "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==", + "node_modules/normalize-package-data/node_modules/semver": { + "version": "5.7.2", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.2.tgz", + "integrity": "sha512-cBznnQ9KjJqU67B52RMC65CMarK2600WFnbkcaiwWq3xy/5haFJlshgnpjovMVJ+Hff49d8GEn0b87C5pDQ10g==", "dev": true, - "dependencies": { - "glob": "^7.1.3" - }, "bin": { - "rimraf": "bin.js" + "semver": "bin/semver" } }, - "node_modules/nyc/node_modules/semver": { - "version": "6.3.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", - "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", + "node_modules/npm-run-path": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-5.3.0.tgz", + "integrity": "sha512-ppwTtiJZq0O/ai0z7yfudtBpWIoxM8yE6nHi1X47eFR2EWORqfbu6CnPlNsjeN683eT0qG6H/Pyf9fCcvjnnnQ==", "dev": true, - "bin": { - "semver": "bin/semver.js" + "dependencies": { + "path-key": "^4.0.0" + }, + "engines": { + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/nyc/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==", + "node_modules/npm-run-path/node_modules/path-key": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/path-key/-/path-key-4.0.0.tgz", + "integrity": "sha512-haREypq7xkM7ErfgIyA0z+Bj4AGKlMSdlQE2jvJo6huWD1EdkKYV+G/T4nq0YEF2vgTT8kqMFKo1uHn950r4SQ==", "dev": true, "engines": { - "node": ">=0.10.0" + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, "node_modules/object-assign": { @@ -6203,6 +5597,21 @@ "wrappy": "1" } }, + "node_modules/onetime": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/onetime/-/onetime-6.0.0.tgz", + "integrity": "sha512-1FlR+gjXK7X+AsAHso35MnyN5KqGwJRi/31ft6x0M194ht7S+rWAvd7PHss9xSKMzE0asv1pyIHaJYq+BbacAQ==", + "dev": true, + "dependencies": { + "mimic-fn": "^4.0.0" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/openapi-types": { "version": "12.1.3", "resolved": "https://registry.npmjs.org/openapi-types/-/openapi-types-12.1.3.tgz", @@ -6238,18 +5647,6 @@ "node": ">=6" } }, - "node_modules/p-map": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/p-map/-/p-map-3.0.0.tgz", - "integrity": "sha512-d3qXVTF/s+W+CdJ5A29wywV2n8CQQYahlgz2bFiA+4eVNJbHJodPZ+/gXwPGh0bOqA+j8S+6+ckmvLGPk1QpxQ==", - "dev": true, - "dependencies": { - "aggregate-error": "^3.0.0" - }, - "engines": { - "node": ">=8" - } - }, "node_modules/p-try": { "version": "2.2.0", "resolved": "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz", @@ -6259,21 +5656,6 @@ "node": ">=6" } }, - "node_modules/package-hash": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/package-hash/-/package-hash-4.0.0.tgz", - "integrity": "sha512-whdkPIooSu/bASggZ96BWVvZTRMOFxnyUG5PnTSGKoJE2gd5mbVNmR2Nj20QFzxYYgAXpoqC+AiXzl+UMRh7zQ==", - "dev": true, - "dependencies": { - "graceful-fs": "^4.1.15", - "hasha": "^5.0.0", - "lodash.flattendeep": "^4.4.0", - "release-zalgo": "^1.0.0" - }, - "engines": { - "node": ">=8" - } - }, "node_modules/parent-module": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz", @@ -6313,6 +5695,15 @@ "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", @@ -6343,6 +5734,12 @@ "node": ">=8" } }, + "node_modules/pathe": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/pathe/-/pathe-1.1.2.tgz", + "integrity": "sha512-whLdWMYL2TwI08hn8/ZqAbrVemu0LNaNNJZX73O6qaIdCTfXutsLhMkjdENX0qhsQ9uIimo4/aQOmXkoon2nDQ==", + "dev": true + }, "node_modules/pathval": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/pathval/-/pathval-1.1.1.tgz", @@ -6369,6 +5766,17 @@ "url": "https://github.com/sponsors/jonschlinkert" } }, + "node_modules/pkg-types": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/pkg-types/-/pkg-types-1.1.1.tgz", + "integrity": "sha512-ko14TjmDuQJ14zsotODv7dBlwxKhUKQEhuhmbqo1uCi9BB0Z2alo/wAXg6q1dTR5TyuqYyWhjtfe/Tsh+X28jQ==", + "dev": true, + "dependencies": { + "confbox": "^0.1.7", + "mlly": "^1.7.0", + "pathe": "^1.1.2" + } + }, "node_modules/pluralize": { "version": "8.0.0", "resolved": "https://registry.npmjs.org/pluralize/-/pluralize-8.0.0.tgz", @@ -6387,6 +5795,34 @@ "node": ">= 0.4" } }, + "node_modules/postcss": { + "version": "8.4.38", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.38.tgz", + "integrity": "sha512-Wglpdk03BSfXkHoQa3b/oulrotAkwrlLDRSOb9D0bN86FdRyE9lppSp33aHNPgBa0JKCoB+drFLZkQoRRYae5A==", + "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/postcss/" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/postcss" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "dependencies": { + "nanoid": "^3.3.7", + "picocolors": "^1.0.0", + "source-map-js": "^1.2.0" + }, + "engines": { + "node": "^10 || ^12 || >=14" + } + }, "node_modules/prelude-ls": { "version": "1.2.1", "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.2.1.tgz", @@ -6411,16 +5847,30 @@ "url": "https://github.com/prettier/prettier?sponsor=1" } }, - "node_modules/process-on-spawn": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/process-on-spawn/-/process-on-spawn-1.0.0.tgz", - "integrity": "sha512-1WsPDsUSMmZH5LeMLegqkPDrsGgsWwk1Exipy2hvB0o/F0ASzbpIctSCcZIK1ykJvtTJULEH+20WOFjMvGnCTg==", + "node_modules/pretty-format": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-29.7.0.tgz", + "integrity": "sha512-Pdlw/oPxN+aXdmM9R00JVC9WVFoCLTKJvDVLgmJ+qAffBMxsV85l/Lu7sNx4zSzPyoL2euImuEwHhOXdEgNFZQ==", "dev": true, "dependencies": { - "fromentries": "^1.2.0" + "@jest/schemas": "^29.6.3", + "ansi-styles": "^5.0.0", + "react-is": "^18.0.0" }, "engines": { - "node": ">=8" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/pretty-format/node_modules/ansi-styles": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-5.2.0.tgz", + "integrity": "sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA==", + "dev": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" } }, "node_modules/prop-types": { @@ -6468,14 +5918,11 @@ } ] }, - "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/react-is": { + "version": "18.3.1", + "resolved": "https://registry.npmjs.org/react-is/-/react-is-18.3.1.tgz", + "integrity": "sha512-/LLMVyas0ljjAtoYiPqYiL8VWXzUUdThrmU5+n20DZv+a+ClRoevUzw5JxU+Ieh5/c87ytoTBV9G1FiKfNJdmg==", + "dev": true }, "node_modules/read-pkg": { "version": "5.2.0", @@ -6573,18 +6020,6 @@ "node": ">=8" } }, - "node_modules/readdirp": { - "version": "3.6.0", - "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz", - "integrity": "sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==", - "dev": true, - "dependencies": { - "picomatch": "^2.2.1" - }, - "engines": { - "node": ">=8.10.0" - } - }, "node_modules/reflect.getprototypeof": { "version": "1.0.6", "resolved": "https://registry.npmjs.org/reflect.getprototypeof/-/reflect.getprototypeof-1.0.6.tgz", @@ -6650,27 +6085,6 @@ "url": "https://github.com/sponsors/mysticatea" } }, - "node_modules/release-zalgo": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/release-zalgo/-/release-zalgo-1.0.0.tgz", - "integrity": "sha1-CXALflB0Mpc5Mw5TXFqQ+2eFFzA=", - "dev": true, - "dependencies": { - "es6-error": "^4.0.1" - }, - "engines": { - "node": ">=4" - } - }, - "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/require-from-string": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/require-from-string/-/require-from-string-2.0.2.tgz", @@ -6679,12 +6093,6 @@ "node": ">=0.10.0" } }, - "node_modules/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 - }, "node_modules/requireindex": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/requireindex/-/requireindex-1.2.0.tgz", @@ -6711,15 +6119,6 @@ "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/resolve-from": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-5.0.0.tgz", - "integrity": "sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw==", - "dev": true, - "engines": { - "node": ">=8" - } - }, "node_modules/resolve-pkg-maps": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/resolve-pkg-maps/-/resolve-pkg-maps-1.0.0.tgz", @@ -6739,6 +6138,41 @@ "node": ">=0.10.0" } }, + "node_modules/rollup": { + "version": "4.18.0", + "resolved": "https://registry.npmjs.org/rollup/-/rollup-4.18.0.tgz", + "integrity": "sha512-QmJz14PX3rzbJCN1SG4Xe/bAAX2a6NpCP8ab2vfu2GiUr8AQcr2nCV/oEO3yneFarB67zk8ShlIyWb2LGTb3Sg==", + "dev": true, + "dependencies": { + "@types/estree": "1.0.5" + }, + "bin": { + "rollup": "dist/bin/rollup" + }, + "engines": { + "node": ">=18.0.0", + "npm": ">=8.0.0" + }, + "optionalDependencies": { + "@rollup/rollup-android-arm-eabi": "4.18.0", + "@rollup/rollup-android-arm64": "4.18.0", + "@rollup/rollup-darwin-arm64": "4.18.0", + "@rollup/rollup-darwin-x64": "4.18.0", + "@rollup/rollup-linux-arm-gnueabihf": "4.18.0", + "@rollup/rollup-linux-arm-musleabihf": "4.18.0", + "@rollup/rollup-linux-arm64-gnu": "4.18.0", + "@rollup/rollup-linux-arm64-musl": "4.18.0", + "@rollup/rollup-linux-powerpc64le-gnu": "4.18.0", + "@rollup/rollup-linux-riscv64-gnu": "4.18.0", + "@rollup/rollup-linux-s390x-gnu": "4.18.0", + "@rollup/rollup-linux-x64-gnu": "4.18.0", + "@rollup/rollup-linux-x64-musl": "4.18.0", + "@rollup/rollup-win32-arm64-msvc": "4.18.0", + "@rollup/rollup-win32-ia32-msvc": "4.18.0", + "@rollup/rollup-win32-x64-msvc": "4.18.0", + "fsevents": "~2.3.2" + } + }, "node_modules/run-parallel": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/run-parallel/-/run-parallel-1.2.0.tgz", @@ -6786,12 +6220,6 @@ "integrity": "sha512-xHjhDr3cNBK0BzdUJSPXZntQUx/mwMS5Rw4A7lPJ90XGAO6ISP/ePDNuo0vhqOZU+UD5JoodwCAAoZQd3FeAKw==", "dev": true }, - "node_modules/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 - }, "node_modules/safe-regex-test": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/safe-regex-test/-/safe-regex-test-1.0.3.tgz", @@ -6842,12 +6270,6 @@ "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", "dev": true }, - "node_modules/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 - }, "node_modules/set-function-length": { "version": "1.2.2", "resolved": "https://registry.npmjs.org/set-function-length/-/set-function-length-1.2.2.tgz", @@ -6880,6 +6302,27 @@ "node": ">= 0.4" } }, + "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/side-channel": { "version": "1.0.6", "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.0.6.tgz", @@ -6898,10 +6341,10 @@ "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/signal-exit": { - "version": "3.0.7", - "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.7.tgz", - "integrity": "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==", + "node_modules/siginfo": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/siginfo/-/siginfo-2.0.0.tgz", + "integrity": "sha512-ybx0WO1/8bSBLEWXZvEd7gMW3Sn3JFlW3TvX1nREbDLRNQNaeNN8WK0meBwPdAaOI7TtRRRJn/Es1zhrrCHu7g==", "dev": true }, "node_modules/sinon": { @@ -6949,69 +6392,13 @@ "node": ">=8" } }, - "node_modules/spawn-wrap": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/spawn-wrap/-/spawn-wrap-2.0.0.tgz", - "integrity": "sha512-EeajNjfN9zMnULLwhZZQU3GWBoFNkbngTUPfaawT4RkMiviTxcX0qfhVbGey39mfctfDHkWtuecgQ8NJcyQWHg==", - "dev": true, - "dependencies": { - "foreground-child": "^2.0.0", - "is-windows": "^1.0.2", - "make-dir": "^3.0.0", - "rimraf": "^3.0.0", - "signal-exit": "^3.0.2", - "which": "^2.0.1" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/spawn-wrap/node_modules/make-dir": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-3.1.0.tgz", - "integrity": "sha512-g3FeP20LNwhALb/6Cz6Dd4F2ngze0jz7tbzrD2wAV+o9FeNHe4rL+yK2md0J/fiSf1sa1ADhXqi5+oVwOM/eGw==", - "dev": true, - "dependencies": { - "semver": "^6.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/spawn-wrap/node_modules/rimraf": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", - "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==", - "dev": true, - "dependencies": { - "glob": "^7.1.3" - }, - "bin": { - "rimraf": "bin.js" - } - }, - "node_modules/spawn-wrap/node_modules/semver": { - "version": "6.3.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", - "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", - "dev": true, - "bin": { - "semver": "bin/semver.js" - } - }, - "node_modules/spawn-wrap/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" - }, + "node_modules/source-map-js": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.2.0.tgz", + "integrity": "sha512-itJW8lvSA0TXEphiRoawsCksnlf8SyvmFzIhltqAHluXd88pkCd+cXJVHTDwdCr0IzwptSm035IHQktUu1QUMg==", + "dev": true, "engines": { - "node": ">= 8" + "node": ">=0.10.0" } }, "node_modules/spdx-correct": { @@ -7046,10 +6433,16 @@ "integrity": "sha512-sh8PWc/ftMqAAdFiBu6Fy6JUOYjqDJBJvIhpfDMyHrr0Rbp5liZqd4TjtQ/RgfLjKFZb+LMx5hpml5qOWy0qvg==", "dev": true }, - "node_modules/sprintf-js": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz", - "integrity": "sha1-BOaSb2YolTVPPdAVIDYzuFcpfiw=", + "node_modules/stackback": { + "version": "0.0.2", + "resolved": "https://registry.npmjs.org/stackback/-/stackback-0.0.2.tgz", + "integrity": "sha512-1XMJE5fQo1jGH6Y/7ebnwPOBEkIEnT4QF32d5R1+VXdXveM0IBMJt8zfaxX1P3QhVwrYe+576+jkANtSS2mBbw==", + "dev": true + }, + "node_modules/std-env": { + "version": "3.7.0", + "resolved": "https://registry.npmjs.org/std-env/-/std-env-3.7.0.tgz", + "integrity": "sha512-JPbdCEQLj1w5GilpiHAx3qJvFndqybBysA3qUOnznweH4QbNYUsW/ea8QzSrnh0vNsezMMw5bcVool8lM0gwzg==", "dev": true }, "node_modules/stop-iteration-iterator": { @@ -7064,20 +6457,6 @@ "node": ">= 0.4" } }, - "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.prototype.matchall": { "version": "4.0.11", "resolved": "https://registry.npmjs.org/string.prototype.matchall/-/string.prototype.matchall-4.0.11.tgz", @@ -7174,6 +6553,18 @@ "node": ">=4" } }, + "node_modules/strip-final-newline": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/strip-final-newline/-/strip-final-newline-3.0.0.tgz", + "integrity": "sha512-dOESqjYr96iWYylGObzd39EuNTa5VJxyvVAEm5Jnh7KGo75V43Hk1odPQkNDyXNmUR6k+gEiDVXnjB8HJ3crXw==", + "dev": true, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/strip-indent": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/strip-indent/-/strip-indent-3.0.0.tgz", @@ -7195,6 +6586,24 @@ "node": ">=8" } }, + "node_modules/strip-literal": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/strip-literal/-/strip-literal-2.1.0.tgz", + "integrity": "sha512-Op+UycaUt/8FbN/Z2TWPBLge3jWrP3xj10f3fnYxf052bKuS3EKs1ZQcVGjnEMdsNVAM+plXRdmjrZ/KgG3Skw==", + "dev": true, + "dependencies": { + "js-tokens": "^9.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/antfu" + } + }, + "node_modules/strip-literal/node_modules/js-tokens": { + "version": "9.0.0", + "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-9.0.0.tgz", + "integrity": "sha512-WriZw1luRMlmV3LGJaR6QOJjWwgLUTf89OwT2lUOyjX2dJGBwgmIkbcz+7WFZjrZM635JOIR517++e/67CP9dQ==", + "dev": true + }, "node_modules/supports-color": { "version": "7.2.0", "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", @@ -7260,6 +6669,30 @@ "integrity": "sha1-f17oI66AUgfACvLfSoTsP8+lcLQ=", "dev": true }, + "node_modules/tinybench": { + "version": "2.8.0", + "resolved": "https://registry.npmjs.org/tinybench/-/tinybench-2.8.0.tgz", + "integrity": "sha512-1/eK7zUnIklz4JUUlL+658n58XO2hHLQfSk1Zf2LKieUjxidN16eKFEoDEfjHc3ohofSSqK3X5yO6VGb6iW8Lw==", + "dev": true + }, + "node_modules/tinypool": { + "version": "0.8.4", + "resolved": "https://registry.npmjs.org/tinypool/-/tinypool-0.8.4.tgz", + "integrity": "sha512-i11VH5gS6IFeLY3gMBQ00/MmLncVP7JLXOw1vlgkytLmJK7QnEr7NXf0LBdxfmNPAeyetukOk0bOYrJrFGjYJQ==", + "dev": true, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/tinyspy": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/tinyspy/-/tinyspy-2.2.1.tgz", + "integrity": "sha512-KYad6Vy5VDWV4GH3fjpseMQ/XU2BhIYP7Vzd0LG44qRWm/Yt2WCOTicFdvmgo6gWaqooMQCawTtILVQJupKu7A==", + "dev": true, + "engines": { + "node": ">=14.0.0" + } + }, "node_modules/to-fast-properties": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/to-fast-properties/-/to-fast-properties-2.0.0.tgz", @@ -7420,15 +6853,6 @@ "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/typedarray-to-buffer": { - "version": "3.1.5", - "resolved": "https://registry.npmjs.org/typedarray-to-buffer/-/typedarray-to-buffer-3.1.5.tgz", - "integrity": "sha512-zdu8XMNEDepKKR+XYOXAVPtWui0ly0NtohUscw+UmaHiAWT8hrV1rr//H6V+0DvJ3OQ19S979M0laLfX8rm82Q==", - "dev": true, - "dependencies": { - "is-typedarray": "^1.0.0" - } - }, "node_modules/typescript": { "version": "5.4.5", "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.4.5.tgz", @@ -7442,6 +6866,12 @@ "node": ">=14.17" } }, + "node_modules/ufo": { + "version": "1.5.3", + "resolved": "https://registry.npmjs.org/ufo/-/ufo-1.5.3.tgz", + "integrity": "sha512-Y7HYmWaFwPUmkoQCUIAYpKqkOf+SbVj/2fJJZ4RJMCfZp0rTGwRbzQD+HghfnhKOjL9E01okqz+ncJskGYfBNw==", + "dev": true + }, "node_modules/unbox-primitive": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/unbox-primitive/-/unbox-primitive-1.0.2.tgz", @@ -7511,6 +6941,163 @@ "spdx-expression-parse": "^3.0.0" } }, + "node_modules/vite": { + "version": "5.2.11", + "resolved": "https://registry.npmjs.org/vite/-/vite-5.2.11.tgz", + "integrity": "sha512-HndV31LWW05i1BLPMUCE1B9E9GFbOu1MbenhS58FuK6owSO5qHm7GiCotrNY1YE5rMeQSFBGmT5ZaLEjFizgiQ==", + "dev": true, + "dependencies": { + "esbuild": "^0.20.1", + "postcss": "^8.4.38", + "rollup": "^4.13.0" + }, + "bin": { + "vite": "bin/vite.js" + }, + "engines": { + "node": "^18.0.0 || >=20.0.0" + }, + "funding": { + "url": "https://github.com/vitejs/vite?sponsor=1" + }, + "optionalDependencies": { + "fsevents": "~2.3.3" + }, + "peerDependencies": { + "@types/node": "^18.0.0 || >=20.0.0", + "less": "*", + "lightningcss": "^1.21.0", + "sass": "*", + "stylus": "*", + "sugarss": "*", + "terser": "^5.4.0" + }, + "peerDependenciesMeta": { + "@types/node": { + "optional": true + }, + "less": { + "optional": true + }, + "lightningcss": { + "optional": true + }, + "sass": { + "optional": true + }, + "stylus": { + "optional": true + }, + "sugarss": { + "optional": true + }, + "terser": { + "optional": true + } + } + }, + "node_modules/vite-node": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/vite-node/-/vite-node-1.6.0.tgz", + "integrity": "sha512-de6HJgzC+TFzOu0NTC4RAIsyf/DY/ibWDYQUcuEA84EMHhcefTUGkjFHKKEJhQN4A+6I0u++kr3l36ZF2d7XRw==", + "dev": true, + "dependencies": { + "cac": "^6.7.14", + "debug": "^4.3.4", + "pathe": "^1.1.1", + "picocolors": "^1.0.0", + "vite": "^5.0.0" + }, + "bin": { + "vite-node": "vite-node.mjs" + }, + "engines": { + "node": "^18.0.0 || >=20.0.0" + }, + "funding": { + "url": "https://opencollective.com/vitest" + } + }, + "node_modules/vitest": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/vitest/-/vitest-1.6.0.tgz", + "integrity": "sha512-H5r/dN06swuFnzNFhq/dnz37bPXnq8xB2xB5JOVk8K09rUtoeNN+LHWkoQ0A/i3hvbUKKcCei9KpbxqHMLhLLA==", + "dev": true, + "dependencies": { + "@vitest/expect": "1.6.0", + "@vitest/runner": "1.6.0", + "@vitest/snapshot": "1.6.0", + "@vitest/spy": "1.6.0", + "@vitest/utils": "1.6.0", + "acorn-walk": "^8.3.2", + "chai": "^4.3.10", + "debug": "^4.3.4", + "execa": "^8.0.1", + "local-pkg": "^0.5.0", + "magic-string": "^0.30.5", + "pathe": "^1.1.1", + "picocolors": "^1.0.0", + "std-env": "^3.5.0", + "strip-literal": "^2.0.0", + "tinybench": "^2.5.1", + "tinypool": "^0.8.3", + "vite": "^5.0.0", + "vite-node": "1.6.0", + "why-is-node-running": "^2.2.2" + }, + "bin": { + "vitest": "vitest.mjs" + }, + "engines": { + "node": "^18.0.0 || >=20.0.0" + }, + "funding": { + "url": "https://opencollective.com/vitest" + }, + "peerDependencies": { + "@edge-runtime/vm": "*", + "@types/node": "^18.0.0 || >=20.0.0", + "@vitest/browser": "1.6.0", + "@vitest/ui": "1.6.0", + "happy-dom": "*", + "jsdom": "*" + }, + "peerDependenciesMeta": { + "@edge-runtime/vm": { + "optional": true + }, + "@types/node": { + "optional": true + }, + "@vitest/browser": { + "optional": true + }, + "@vitest/ui": { + "optional": true + }, + "happy-dom": { + "optional": true + }, + "jsdom": { + "optional": true + } + } + }, + "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/which-boxed-primitive": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/which-boxed-primitive/-/which-boxed-primitive-1.0.2.tgz", @@ -7574,12 +7161,6 @@ "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/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 - }, "node_modules/which-typed-array": { "version": "1.1.15", "resolved": "https://registry.npmjs.org/which-typed-array/-/which-typed-array-1.1.15.tgz", @@ -7599,198 +7180,28 @@ "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/workerpool": { - "version": "6.2.1", - "resolved": "https://registry.npmjs.org/workerpool/-/workerpool-6.2.1.tgz", - "integrity": "sha512-ILEIE97kDZvF9Wb9f6h5aXK4swSlKGUcOEGiIYb2OOu/IrDU9iwj0fD//SsA6E5ibwJxpEvhullJY4Sl4GcpAw==", - "dev": true - }, - "node_modules/wrap-ansi": { - "version": "6.2.0", - "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-6.2.0.tgz", - "integrity": "sha512-r6lPcBGxZXlIcymEu7InxDMhdW0KDxpLgoFLcguasxCaJ/SOIZwINatK9KY/tf+ZrlywOKU0UDj3ATXUBfxJXA==", + "node_modules/why-is-node-running": { + "version": "2.2.2", + "resolved": "https://registry.npmjs.org/why-is-node-running/-/why-is-node-running-2.2.2.tgz", + "integrity": "sha512-6tSwToZxTOcotxHeA+qGCq1mVzKR3CwcJGmVcY+QE8SHy6TnpFnh8PAvPNHYr7EcuVeG0QSMxtYCuO1ta/G/oA==", "dev": true, "dependencies": { - "ansi-styles": "^4.0.0", - "string-width": "^4.1.0", - "strip-ansi": "^6.0.0" + "siginfo": "^2.0.0", + "stackback": "0.0.2" }, - "engines": { - "node": ">=8" - } - }, - "node_modules/wrap-ansi/node_modules/ansi-styles": { - "version": "4.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.2.1.tgz", - "integrity": "sha512-9VGjrMsG1vePxcSweQsN20KY/c4zN0h9fLjqAbwbPfahM3t+NL+M9HC8xeXG2I8pX5NoamTGNuomEUFI7fcUjA==", - "dev": true, - "dependencies": { - "@types/color-name": "^1.1.1", - "color-convert": "^2.0.1" + "bin": { + "why-is-node-running": "cli.js" }, "engines": { "node": ">=8" } }, - "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/wrappy": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=", "dev": true }, - "node_modules/y18n": { - "version": "4.0.3", - "resolved": "https://registry.npmjs.org/y18n/-/y18n-4.0.3.tgz", - "integrity": "sha512-JKhqTOwSrqNA1NY5lSztJ1GrBiUodLMmIZuLiDaMRJ+itFd+ABVE8XBjOvIWL+rSqNDC74LCSFmlb/U4UZ4hJQ==", - "dev": true - }, - "node_modules/yargs": { - "version": "15.4.1", - "resolved": "https://registry.npmjs.org/yargs/-/yargs-15.4.1.tgz", - "integrity": "sha512-aePbxDmcYW++PaqBsJ+HYUFwCdv4LVvdnhBy78E57PIor8/OVvhMrADFFEDh8DHDFRv/O9i3lPhsENjO7QX0+A==", - "dev": true, - "dependencies": { - "cliui": "^6.0.0", - "decamelize": "^1.2.0", - "find-up": "^4.1.0", - "get-caller-file": "^2.0.1", - "require-directory": "^2.1.1", - "require-main-filename": "^2.0.0", - "set-blocking": "^2.0.0", - "string-width": "^4.2.0", - "which-module": "^2.0.0", - "y18n": "^4.0.0", - "yargs-parser": "^18.1.2" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/yargs-parser": { - "version": "18.1.3", - "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-18.1.3.tgz", - "integrity": "sha512-o50j0JeToy/4K6OZcaQmW6lyXXKhq7csREXcDwk2omFPJEwUNOVtJKvmDr9EI1fAJZUyZcRF7kxGBWmRXudrCQ==", - "dev": true, - "dependencies": { - "camelcase": "^5.0.0", - "decamelize": "^1.2.0" - }, - "engines": { - "node": ">=6" - } - }, - "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/yargs-unparser/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/yargs/node_modules/find-up": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz", - "integrity": "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==", - "dev": true, - "dependencies": { - "locate-path": "^5.0.0", - "path-exists": "^4.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/yargs/node_modules/locate-path": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz", - "integrity": "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==", - "dev": true, - "dependencies": { - "p-locate": "^4.1.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/yargs/node_modules/p-locate": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-4.1.0.tgz", - "integrity": "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==", - "dev": true, - "dependencies": { - "p-limit": "^2.2.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/yargs/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/yocto-queue": { "version": "0.1.0", "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz", diff --git a/package.json b/package.json index 51fe0bd3..168e56d5 100644 --- a/package.json +++ b/package.json @@ -38,27 +38,24 @@ "node": ">=18" }, "scripts": { - "clean": "rm -rf .nyc_output coverage", - "coverage": "nyc mocha", - "lint": "eslint .", + "lint": "npm run lint:js && npm run prettier", + "lint:js": "eslint . --ext .js,.ts --ignore-path .gitignore", "pretest": "npm run lint", - "test": "npm run test:node && npm run test:typescript", - "test:node": "mocha", - "test:typescript": "tsc --noEmit --strict --lib esnext,dom test/specs/typescript-definition.spec.ts" + "prettier": "prettier --check .", + "prettier:write": "prettier --check --write .", + "test": "vitest run --coverage" }, "devDependencies": { - "@babel/polyfill": "^7.12.1", "@jsdevtools/host-environment": "^2.1.2", "@readme/eslint-config": "^14.0.0", "@types/node": "^20.12.7", - "chai": "^4.3.8", + "@vitest/coverage-v8": "^1.6.0", "eslint": "^8.56.0", - "mocha": "^10.2.0", - "nyc": "^15.1.0", "openapi-types": "^12.1.3", "prettier": "^3.1.1", "sinon": "^17.0.0", - "typescript": "^5.4.5" + "typescript": "^5.4.5", + "vitest": "^1.6.0" }, "dependencies": { "@apidevtools/openapi-schemas": "^2.1.0", @@ -73,10 +70,5 @@ "peerDependencies": { "openapi-types": ">=7" }, - "prettier": "@readme/eslint-config/prettier", - "commitlint": { - "extends": [ - "@commitlint/config-conventional" - ] - } + "prettier": "@readme/eslint-config/prettier" } diff --git a/test/.eslintrc b/test/.eslintrc new file mode 100644 index 00000000..b412a80f --- /dev/null +++ b/test/.eslintrc @@ -0,0 +1,7 @@ +{ + "extends": "@readme/eslint-config/testing/vitest", + "rules": { + "no-console": "off", + "unicorn/no-unsafe-regex": "off" + } +} diff --git a/test/.eslintrc.yml b/test/.eslintrc.yml deleted file mode 100644 index 74e8932d..00000000 --- a/test/.eslintrc.yml +++ /dev/null @@ -1,3 +0,0 @@ -rules: - no-console: off - unicorn/no-unsafe-regex: off diff --git a/test/fixtures/mocha.js b/test/fixtures/mocha.js deleted file mode 100644 index 870be868..00000000 --- a/test/fixtures/mocha.js +++ /dev/null @@ -1,6 +0,0 @@ -beforeEach(function () { - // Most of our tests perform multiple AJAX requests, - // so we need to increase the timeouts to allow for that - this.currentTest.timeout(20000); - this.currentTest.slow(10000); -}); diff --git a/test/fixtures/real-world-apis.json b/test/fixtures/real-world-apis.json index 730328a2..90d2352b 100644 --- a/test/fixtures/real-world-apis.json +++ b/test/fixtures/real-world-apis.json @@ -12604,4 +12604,4 @@ "version": "2021-08-20", "url": "https://api.apis.guru/v2/specs/zuora.com/2021-08-20/openapi.yaml" } -] \ No newline at end of file +] diff --git a/test/specs/better-errors/2.0/misplaced-additionalProperty.yaml b/test/specs/better-errors/2.0/misplaced-additionalProperty.yaml index f160546e..7b7502d0 100644 --- a/test/specs/better-errors/2.0/misplaced-additionalProperty.yaml +++ b/test/specs/better-errors/2.0/misplaced-additionalProperty.yaml @@ -1,4 +1,4 @@ -swagger: "2.0" +swagger: '2.0' host: httpbin.org schemes: - https @@ -7,18 +7,18 @@ info: title: Invalid API version: 1.0.0 paths: - "/anything": + '/anything': get: produces: - application/json responses: - "200": + '200': description: successful operation schema: type: object additionalProperties: - $ref: "#/definitions/CliOption" - originalRef: CliOption # <---- this shouldn't be here + $ref: '#/definitions/CliOption' + originalRef: CliOption # <---- this shouldn't be here definitions: CliOption: type: object diff --git a/test/specs/better-errors/3.0/invalid-x-extension-path.yaml b/test/specs/better-errors/3.0/invalid-x-extension-path.yaml index c4789789..f4befc08 100644 --- a/test/specs/better-errors/3.0/invalid-x-extension-path.yaml +++ b/test/specs/better-errors/3.0/invalid-x-extension-path.yaml @@ -10,4 +10,4 @@ paths: responses: 400: description: OK - invalid-x-extension: true # <---- this shouldn't be here + invalid-x-extension: true # <---- this shouldn't be here diff --git a/test/specs/better-errors/3.0/invalid-x-extension-root.yaml b/test/specs/better-errors/3.0/invalid-x-extension-root.yaml index e1e5feba..ffb2cd3f 100644 --- a/test/specs/better-errors/3.0/invalid-x-extension-root.yaml +++ b/test/specs/better-errors/3.0/invalid-x-extension-root.yaml @@ -10,4 +10,4 @@ paths: responses: 400: description: OK -invalid-x-extension: true # <---- this shouldn't be here +invalid-x-extension: true # <---- this shouldn't be here diff --git a/test/specs/better-errors/3.0/misplaced-additionalProperty.yaml b/test/specs/better-errors/3.0/misplaced-additionalProperty.yaml index a3a58d30..61f6d162 100644 --- a/test/specs/better-errors/3.0/misplaced-additionalProperty.yaml +++ b/test/specs/better-errors/3.0/misplaced-additionalProperty.yaml @@ -8,15 +8,15 @@ paths: /anything: get: responses: - "200": + '200': description: successful operation content: application/json: schema: type: object additionalProperties: - $ref: "#/components/schemas/CliOption" - originalRef: CliOption # <---- this shouldn't be here + $ref: '#/components/schemas/CliOption' + originalRef: CliOption # <---- this shouldn't be here components: schemas: CliOption: diff --git a/test/specs/better-errors/3.1/invalid-component-name.yaml b/test/specs/better-errors/3.1/invalid-component-name.yaml index 39e15d51..6c81beb1 100644 --- a/test/specs/better-errors/3.1/invalid-component-name.yaml +++ b/test/specs/better-errors/3.1/invalid-component-name.yaml @@ -1,6 +1,6 @@ openapi: 3.1.0 info: - version: "1.0" + version: '1.0' title: Invalid API paths: /anything: @@ -13,10 +13,10 @@ paths: schema: type: array items: - "$ref": "#/components/schemas/User«Information»" + '$ref': '#/components/schemas/User«Information»' components: schemas: - User«Information»: # <---- component names should match ^[a-zA-Z0-9\.\-_]+$ + User«Information»: # <---- component names should match ^[a-zA-Z0-9\.\-_]+$ type: object properties: first: diff --git a/test/specs/better-errors/3.1/invalid-x-extension-path.yaml b/test/specs/better-errors/3.1/invalid-x-extension-path.yaml index 458a690b..a5761f03 100644 --- a/test/specs/better-errors/3.1/invalid-x-extension-path.yaml +++ b/test/specs/better-errors/3.1/invalid-x-extension-path.yaml @@ -10,4 +10,4 @@ paths: responses: 400: description: OK - invalid-x-extension: true # <---- this shouldn't be here + invalid-x-extension: true # <---- this shouldn't be here diff --git a/test/specs/better-errors/3.1/invalid-x-extension-root.yaml b/test/specs/better-errors/3.1/invalid-x-extension-root.yaml index 670a395c..eae8e27a 100644 --- a/test/specs/better-errors/3.1/invalid-x-extension-root.yaml +++ b/test/specs/better-errors/3.1/invalid-x-extension-root.yaml @@ -10,4 +10,4 @@ paths: responses: 400: description: OK -invalid-x-extension: true # <---- this shouldn't be here +invalid-x-extension: true # <---- this shouldn't be here diff --git a/test/specs/better-errors/better-errors.spec.js b/test/specs/better-errors/better-errors.test.ts similarity index 86% rename from test/specs/better-errors/better-errors.spec.js rename to test/specs/better-errors/better-errors.test.ts index 2f12903d..c897a123 100644 --- a/test/specs/better-errors/better-errors.spec.js +++ b/test/specs/better-errors/better-errors.test.ts @@ -1,15 +1,14 @@ -const { expect } = require('chai'); +import { describe, it, expect, assert } from 'vitest'; -const OpenAPIParser = require('../../..'); -const path = require('../../utils/path'); +import OpenAPIParser from '../../..'; +import path from '../../utils/path'; -function assertInvalid(file, error) { +function assertInvalid(file: string, error: string) { return OpenAPIParser.validate(path.rel(`specs/better-errors/${file}`)) .then(() => { - throw new Error('Validation should have failed, but it succeeded!'); + assert.fail('Validation should have failed, but it succeeded!'); }) .catch(err => { - // console.log(err.message); expect(err).to.be.an.instanceOf(SyntaxError); expect(err.message).to.contain(error); }); @@ -58,7 +57,7 @@ describe('Better errors', () => { }); describe('missing component', () => { - it.skip('OpenAPI 3.0'); - it.skip('OpenAPI 3.1'); + it.todo('OpenAPI 3.0'); + it.todo('OpenAPI 3.1'); }); }); diff --git a/test/specs/callbacks-promises/callbacks-promises-error.yaml b/test/specs/callbacks-promises/callbacks-promises-error.yaml index d6fc2bc9..221a36ed 100644 --- a/test/specs/callbacks-promises/callbacks-promises-error.yaml +++ b/test/specs/callbacks-promises/callbacks-promises-error.yaml @@ -1 +1 @@ -swagger: "ERROR" +swagger: 'ERROR' diff --git a/test/specs/callbacks-promises/callbacks-promises.spec.js b/test/specs/callbacks-promises/callbacks-promises.spec.js deleted file mode 100644 index f2c3620e..00000000 --- a/test/specs/callbacks-promises/callbacks-promises.spec.js +++ /dev/null @@ -1,104 +0,0 @@ -const { expect } = require('chai'); - -const OpenAPIParser = require('../../..'); -const helper = require('../../utils/helper'); -const path = require('../../utils/path'); - -const bundledAPI = require('./bundled'); -const dereferencedAPI = require('./dereferenced'); -const parsedAPI = require('./parsed'); - -describe('Callback & Promise syntax', () => { - for (const method of ['parse', 'resolve', 'dereference', 'bundle', 'validate']) { - describe(`${method} method`, () => { - it('should call the callback function upon success', testCallbackSuccess(method)); - it('should call the callback function upon failure', testCallbackError(method)); - it('should resolve the Promise upon success', testPromiseSuccess(method)); - it('should reject the Promise upon failure', testPromiseError(method)); - }); - } - - function testCallbackSuccess(method) { - return function (done) { - const parser = new OpenAPIParser(); - parser[method](path.rel('specs/callbacks-promises/callbacks-promises.yaml'), (err, result) => { - try { - expect(err).to.equal(null); - expect(result).to.be.an('object'); - expect(parser.$refs.paths()).to.deep.equal([path.abs('specs/callbacks-promises/callbacks-promises.yaml')]); - - if (method === 'resolve') { - expect(result).to.equal(parser.$refs); - } else { - expect(result).to.equal(parser.schema); - - // Make sure the API was parsed correctly - const expected = getSchema(method); - expect(result).to.deep.equal(expected); - } - done(); - } catch (e) { - done(e); - } - }); - }; - } - - function testCallbackError(method) { - return function (done) { - OpenAPIParser[method](path.rel('specs/callbacks-promises/callbacks-promises-error.yaml'), (err, result) => { - try { - expect(err).to.be.an.instanceOf(SyntaxError); - expect(result).to.equal(undefined); - done(); - } catch (e) { - done(e); - } - }); - }; - } - - function testPromiseSuccess(method) { - return function () { - const parser = new OpenAPIParser(); - return parser[method](path.rel('specs/callbacks-promises/callbacks-promises.yaml')).then(result => { - expect(result).to.be.an('object'); - expect(parser.$refs.paths()).to.deep.equal([path.abs('specs/callbacks-promises/callbacks-promises.yaml')]); - - if (method === 'resolve') { - expect(result).to.equal(parser.$refs); - } else { - expect(result).to.equal(parser.schema); - - // Make sure the API was parsed correctly - const expected = getSchema(method); - expect(result).to.deep.equal(expected); - } - }); - }; - } - - function testPromiseError(method) { - return function () { - return OpenAPIParser[method](path.rel('specs/callbacks-promises/callbacks-promises-error.yaml')) - .then(helper.shouldNotGetCalled) - .catch(err => { - expect(err).to.be.an.instanceOf(SyntaxError); - }); - }; - } - - function getSchema(method) { - switch (method) { - case 'parse': - return parsedAPI; - case 'dereference': - case 'validate': - return dereferencedAPI; - case 'bundle': - return bundledAPI; - default: - throw new Error('Unrecognized schema method called.'); - } - } -}); diff --git a/test/specs/callbacks-promises/callbacks-promises.test.ts b/test/specs/callbacks-promises/callbacks-promises.test.ts new file mode 100644 index 00000000..b3b353d0 --- /dev/null +++ b/test/specs/callbacks-promises/callbacks-promises.test.ts @@ -0,0 +1,90 @@ +import { describe, it, expect } from 'vitest'; + +import OpenAPIParser from '../../..'; +import path from '../../utils/path'; + +import bundledAPI from './bundled'; +import dereferencedAPI from './dereferenced'; +import parsedAPI from './parsed'; + +function getSchema(method: string) { + switch (method) { + case 'parse': + return parsedAPI; + case 'dereference': + case 'validate': + return dereferencedAPI; + case 'bundle': + return bundledAPI; + default: + throw new Error('Unrecognized schema method called.'); + } +} + +describe('Callback & Promise syntax', () => { + describe.each(['parse', 'resolve', 'dereference', 'bundle', 'validate'])('%s method', method => { + it('should call the callback function upon success', () => { + return new Promise((resolve, reject) => { + const parser = new OpenAPIParser(); + parser[method](path.rel('specs/callbacks-promises/callbacks-promises.yaml'), (err, result) => { + try { + expect(err).to.equal(null); + expect(result).to.be.an('object'); + expect(parser.$refs.paths()).to.deep.equal([path.abs('specs/callbacks-promises/callbacks-promises.yaml')]); + + if (method === 'resolve') { + expect(result).to.equal(parser.$refs); + } else { + expect(result).to.equal(parser.schema); + + // Make sure the API was parsed correctly + const expected = getSchema(method); + expect(result).to.deep.equal(expected); + } + resolve(true); + } catch (e) { + reject(e); + } + }); + }); + }); + + it('should call the callback function upon failure', () => { + return new Promise((resolve, reject) => { + OpenAPIParser[method](path.rel('specs/callbacks-promises/callbacks-promises-error.yaml'), (err, result) => { + try { + expect(err).to.be.an.instanceOf(SyntaxError); + expect(result).to.equal(undefined); + resolve(true); + } catch (e) { + reject(e); + } + }); + }); + }); + + it('should resolve the Promise upon success', () => { + const parser = new OpenAPIParser(); + return parser[method](path.rel('specs/callbacks-promises/callbacks-promises.yaml')).then(result => { + expect(result).to.be.an('object'); + expect(parser.$refs.paths()).to.deep.equal([path.abs('specs/callbacks-promises/callbacks-promises.yaml')]); + + if (method === 'resolve') { + expect(result).to.equal(parser.$refs); + } else { + expect(result).to.equal(parser.schema); + + // Make sure the API was parsed correctly + const expected = getSchema(method); + expect(result).to.deep.equal(expected); + } + }); + }); + + it('should reject the Promise upon failure', async () => { + await expect( + OpenAPIParser[method](path.rel('specs/callbacks-promises/callbacks-promises-error.yaml')), + ).rejects.toThrow(SyntaxError); + }); + }); +}); diff --git a/test/specs/callbacks-promises/callbacks-promises.yaml b/test/specs/callbacks-promises/callbacks-promises.yaml index 829cb3de..7ca30c92 100644 --- a/test/specs/callbacks-promises/callbacks-promises.yaml +++ b/test/specs/callbacks-promises/callbacks-promises.yaml @@ -1,4 +1,4 @@ -swagger: "2.0" +swagger: '2.0' info: version: 1.0.0 title: Name API @@ -16,7 +16,7 @@ paths: 200: description: Returns the requested name schema: - $ref: "#/definitions/name" + $ref: '#/definitions/name' definitions: name: @@ -26,20 +26,20 @@ definitions: - last properties: first: - $ref: "#/definitions/requiredString" + $ref: '#/definitions/requiredString' last: - $ref: "#/definitions/name/properties/first" + $ref: '#/definitions/name/properties/first' middle: type: string enum: - - $ref: "#/definitions/name/properties/first/type" - - $ref: "#/definitions/name/properties/last/title" + - $ref: '#/definitions/name/properties/first/type' + - $ref: '#/definitions/name/properties/last/title' prefix: - $ref: "#/definitions/name/properties/last" + $ref: '#/definitions/name/properties/last' minLength: 3 suffix: type: string - $ref: "#/definitions/name/properties/prefix" + $ref: '#/definitions/name/properties/prefix' maxLength: 3 requiredString: title: requiredString diff --git a/test/specs/circular/circular.spec.js b/test/specs/circular/circular.test.ts similarity index 76% rename from test/specs/circular/circular.spec.js rename to test/specs/circular/circular.test.ts index 4141e7b8..59dc90b8 100644 --- a/test/specs/circular/circular.spec.js +++ b/test/specs/circular/circular.test.ts @@ -1,16 +1,15 @@ -const { expect } = require('chai'); +import { describe, it, expect, assert } from 'vitest'; -const OpenAPIParser = require('../../..'); -const helper = require('../../utils/helper'); -const path = require('../../utils/path'); +import OpenAPIParser from '../../..'; +import * as helper from '../../utils/helper'; +import path from '../../utils/path'; -const bundledAPI = require('./bundled'); -const dereferencedAPI = require('./dereferenced'); -const parsedAPI = require('./parsed'); -const validatedAPI = require('./validated'); +import bundledAPI from './bundled'; +import dereferencedAPI from './dereferenced'; +import parsedAPI from './parsed'; +import validatedAPI from './validated'; -// @fixme temporarily skipped due to problems with the upgrade to @apidevtools/json-schema-ref-parser -describe.skip('API with circular (recursive) $refs', () => { +describe('API with circular (recursive) $refs', () => { it('should parse successfully', async () => { const parser = new OpenAPIParser(); const api = await parser.parse(path.rel('specs/circular/circular.yaml')); @@ -46,7 +45,9 @@ describe.skip('API with circular (recursive) $refs', () => { expect(api.definitions.child.properties.parents.items).to.equal(api.definitions.parent); }); - it('should validate successfully', async () => { + // @fixme temporarily skipped due to problems with the upgrade to @apidevtools/json-schema-ref-parser + // eslint-disable-next-line vitest/no-disabled-tests + it.skip('should validate successfully', async () => { const parser = new OpenAPIParser(); const api = await parser.validate(path.rel('specs/circular/circular.yaml')); expect(api).to.equal(parser.api); @@ -57,7 +58,9 @@ describe.skip('API with circular (recursive) $refs', () => { expect(api.definitions.child.properties.parents.items).to.equal(api.definitions.parent); }); - it('should not dereference circular $refs if "options.dereference.circular" is "ignore"', async () => { + // @fixme temporarily skipped due to problems with the upgrade to @apidevtools/json-schema-ref-parser + // eslint-disable-next-line vitest/no-disabled-tests + it.skip('should not dereference circular $refs if "options.dereference.circular" is "ignore"', async () => { const parser = new OpenAPIParser(); const api = await parser.validate(path.rel('specs/circular/circular.yaml'), { dereference: { circular: 'ignore' }, @@ -73,7 +76,7 @@ describe.skip('API with circular (recursive) $refs', () => { try { await parser.validate(path.rel('specs/circular/circular.yaml'), { dereference: { circular: false } }); - helper.shouldNotGetCalled(); + assert.fail(); } catch (err) { expect(err).to.be.an.instanceOf(ReferenceError); expect(err.message).to.equal('The API contains circular references'); diff --git a/test/specs/circular/circular.yaml b/test/specs/circular/circular.yaml index 875a9276..12bf3e0b 100644 --- a/test/specs/circular/circular.yaml +++ b/test/specs/circular/circular.yaml @@ -1,4 +1,4 @@ -swagger: "2.0" +swagger: '2.0' info: version: 1.0.0 description: This API contains circular (recursive) JSON references @@ -11,7 +11,7 @@ paths: 200: description: Returns a pet schema: - $ref: "#/definitions/pet" + $ref: '#/definitions/pet' /thing: get: @@ -19,34 +19,34 @@ paths: 200: description: Returns a thing schema: - $ref: "#/definitions/thing" + $ref: '#/definitions/thing' /person: get: responses: 200: description: Returns a person schema: - $ref: "#/definitions/person" + $ref: '#/definitions/person' /parent: get: responses: 200: description: Returns a parent schema: - $ref: "#/definitions/parent" + $ref: '#/definitions/parent' definitions: pet: - $ref: definitions/pet.yaml # <--- not circular + $ref: definitions/pet.yaml # <--- not circular thing: - $ref: 'circular.yaml#/definitions/thing' # <--- circular reference to self + $ref: 'circular.yaml#/definitions/thing' # <--- circular reference to self person: - $ref: definitions/person.yaml # <--- circular reference to ancestor + $ref: definitions/person.yaml # <--- circular reference to ancestor parent: - $ref: definitions/parent.yaml # <--- indirect circular reference + $ref: definitions/parent.yaml # <--- indirect circular reference child: - $ref: definitions/child.yaml # <--- indirect circular reference + $ref: definitions/child.yaml # <--- indirect circular reference diff --git a/test/specs/circular/definitions/child.yaml b/test/specs/circular/definitions/child.yaml index ffa8635a..0030b774 100644 --- a/test/specs/circular/definitions/child.yaml +++ b/test/specs/circular/definitions/child.yaml @@ -6,4 +6,4 @@ properties: parents: type: array items: - $ref: parent.yaml # indirect circular reference + $ref: parent.yaml # indirect circular reference diff --git a/test/specs/circular/definitions/parent.yaml b/test/specs/circular/definitions/parent.yaml index 1b4b4123..17d64e75 100644 --- a/test/specs/circular/definitions/parent.yaml +++ b/test/specs/circular/definitions/parent.yaml @@ -6,4 +6,4 @@ properties: children: type: array items: - $ref: child.yaml # indirect circular reference + $ref: child.yaml # indirect circular reference diff --git a/test/specs/colorize-errors-option/colorize-errors-option.spec.js b/test/specs/colorize-errors-option/colorize-errors-option.test.ts similarity index 67% rename from test/specs/colorize-errors-option/colorize-errors-option.spec.js rename to test/specs/colorize-errors-option/colorize-errors-option.test.ts index d3f58b06..8af3b242 100644 --- a/test/specs/colorize-errors-option/colorize-errors-option.spec.js +++ b/test/specs/colorize-errors-option/colorize-errors-option.test.ts @@ -1,8 +1,7 @@ -const { expect } = require('chai'); +import { describe, it, expect, assert } from 'vitest'; -const OpenAPIParser = require('../../..'); -const helper = require('../../utils/helper'); -const path = require('../../utils/path'); +import OpenAPIParser from '../../..'; +import path from '../../utils/path'; describe('`validate.colorizeErrors` option', () => { it('should not colorize errors by default', async () => { @@ -10,11 +9,10 @@ describe('`validate.colorizeErrors` option', () => { try { await parser.validate(path.rel('specs/colorize-errors-option/invalid.json')); - helper.shouldNotGetCalled(); + assert.fail(); } catch (err) { expect(err).to.be.an.instanceOf(SyntaxError); - // eslint-disable-next-line no-regex-spaces - expect(err.message).to.match(/> 19 | "type": "array",/); + expect(err.message).to.contain('> 19 | "type": "array",'); } }); @@ -28,7 +26,7 @@ describe('`validate.colorizeErrors` option', () => { }, }); - helper.shouldNotGetCalled(); + assert.fail(); } catch (err) { expect(err).to.be.an.instanceOf(SyntaxError); expect(err.message).to.contain('\u001b'); diff --git a/test/specs/deep-circular/deep-circular.spec.js b/test/specs/deep-circular/deep-circular.test.ts similarity index 91% rename from test/specs/deep-circular/deep-circular.spec.js rename to test/specs/deep-circular/deep-circular.test.ts index 75204a24..c2ccc721 100644 --- a/test/specs/deep-circular/deep-circular.spec.js +++ b/test/specs/deep-circular/deep-circular.test.ts @@ -1,12 +1,12 @@ -const { expect } = require('chai'); +import { describe, it, expect } from 'vitest'; -const OpenAPIParser = require('../../..'); -const helper = require('../../utils/helper'); -const path = require('../../utils/path'); +import OpenAPIParser from '../../..'; +import * as helper from '../../utils/helper'; +import path from '../../utils/path'; -const bundledAPI = require('./bundled'); -const dereferencedAPI = require('./dereferenced'); -const parsedAPI = require('./parsed'); +import bundledAPI from './bundled'; +import dereferencedAPI from './dereferenced'; +import parsedAPI from './parsed'; describe('API with deeply-nested circular $refs', () => { it('should parse successfully', async () => { diff --git a/test/specs/deep-circular/deep-circular.yaml b/test/specs/deep-circular/deep-circular.yaml index 27b52a67..3fd9dfaa 100644 --- a/test/specs/deep-circular/deep-circular.yaml +++ b/test/specs/deep-circular/deep-circular.yaml @@ -1,4 +1,4 @@ -swagger: "2.0" +swagger: '2.0' info: version: 1.0.0 description: This API contains a VERY DEEP circular (recursive) JSON reference @@ -221,4 +221,4 @@ paths: name: $ref: definitions/name.yaml level30: - $ref: "#/paths/~1family-tree/get/responses/200/schema" + $ref: '#/paths/~1family-tree/get/responses/200/schema' diff --git a/test/specs/deep-circular/definitions/name.yaml b/test/specs/deep-circular/definitions/name.yaml index 3889e6ea..ad427e10 100644 --- a/test/specs/deep-circular/definitions/name.yaml +++ b/test/specs/deep-circular/definitions/name.yaml @@ -11,12 +11,12 @@ properties: middle: type: string enum: - - $ref: "#/properties/first/type" - - $ref: "#/properties/last/title" + - $ref: '#/properties/first/type' + - $ref: '#/properties/last/title' prefix: - $ref: "#/properties/last" + $ref: '#/properties/last' minLength: 3 suffix: type: string - $ref: "#/properties/prefix" + $ref: '#/properties/prefix' maxLength: 3 diff --git a/test/specs/exports.spec.js b/test/specs/exports.test.ts similarity index 58% rename from test/specs/exports.spec.js rename to test/specs/exports.test.ts index 6dc67139..e78e62a8 100644 --- a/test/specs/exports.spec.js +++ b/test/specs/exports.test.ts @@ -1,20 +1,20 @@ -const { expect } = require('chai'); +import { describe, it, expect } from 'vitest'; -const OpenAPIParser = require('../..'); +import OpenAPIParser from '../..'; describe('Exports', () => { - it('should export the OpenAPIParser class', async () => { + it('should export the OpenAPIParser class', () => { expect(OpenAPIParser).to.be.a('function'); }); - it('should export all the static methods of OpenAPIParser', async () => { + it('should export all the static methods of OpenAPIParser', () => { expect(OpenAPIParser.parse).to.be.a('function'); expect(OpenAPIParser.resolve).to.be.a('function'); expect(OpenAPIParser.bundle).to.be.a('function'); expect(OpenAPIParser.dereference).to.be.a('function'); }); - it('should export the validate method', async () => { + it('should export the validate method', () => { expect(OpenAPIParser.validate).to.be.a('function'); }); }); diff --git a/test/specs/invalid/invalid.spec.js b/test/specs/invalid/invalid.test.ts similarity index 84% rename from test/specs/invalid/invalid.spec.js rename to test/specs/invalid/invalid.test.ts index 2e96f0f0..1ad506b5 100644 --- a/test/specs/invalid/invalid.spec.js +++ b/test/specs/invalid/invalid.test.ts @@ -1,14 +1,13 @@ -const { expect } = require('chai'); +import { describe, it, expect, assert } from 'vitest'; -const OpenAPIParser = require('../../..'); -const helper = require('../../utils/helper'); -const path = require('../../utils/path'); +import OpenAPIParser from '../../..'; +import path from '../../utils/path'; describe("Invalid APIs (can't be parsed)", () => { it('not a Swagger API', async () => { try { await OpenAPIParser.parse(path.rel('specs/invalid/not-swagger.yaml')); - helper.shouldNotGetCalled(); + assert.fail(); } catch (err) { expect(err).to.be.an.instanceOf(SyntaxError); expect(err.message).to.contain('not-swagger.yaml is not a valid OpenAPI definition'); @@ -18,7 +17,7 @@ describe("Invalid APIs (can't be parsed)", () => { it('not a valid OpenAPI 3.1 definition', async () => { try { await OpenAPIParser.parse(path.rel('specs/invalid/no-paths-or-webhooks.yaml')); - helper.shouldNotGetCalled(); + assert.fail(); } catch (err) { expect(err).to.be.an.instanceOf(SyntaxError); expect(err.message).to.contain('no-paths-or-webhooks.yaml is not a valid OpenAPI definition'); @@ -28,7 +27,7 @@ describe("Invalid APIs (can't be parsed)", () => { it('invalid Swagger version (1.2)', async () => { try { await OpenAPIParser.dereference(path.rel('specs/invalid/old-version.yaml')); - helper.shouldNotGetCalled(); + assert.fail(); } catch (err) { expect(err).to.be.an.instanceOf(SyntaxError); expect(err.message).to.equal('Unrecognized Swagger version: 1.2. Expected 2.0'); @@ -38,7 +37,7 @@ describe("Invalid APIs (can't be parsed)", () => { it('invalid Swagger version (3.0)', async () => { try { await OpenAPIParser.bundle(path.rel('specs/invalid/newer-version.yaml')); - helper.shouldNotGetCalled(); + assert.fail(); } catch (err) { expect(err).to.be.an.instanceOf(SyntaxError); expect(err.message).to.equal('Unrecognized Swagger version: 3.0. Expected 2.0'); @@ -48,7 +47,7 @@ describe("Invalid APIs (can't be parsed)", () => { it('numeric Swagger version (instead of a string)', async () => { try { await OpenAPIParser.validate(path.rel('specs/invalid/numeric-version.yaml')); - helper.shouldNotGetCalled(); + assert.fail(); } catch (err) { expect(err).to.be.an.instanceOf(SyntaxError); expect(err.message).to.equal('Swagger version number must be a string (e.g. "2.0") not a number.'); @@ -58,7 +57,7 @@ describe("Invalid APIs (can't be parsed)", () => { it('numeric API version (instead of a string)', async () => { try { await OpenAPIParser.validate(path.rel('specs/invalid/numeric-info-version.yaml')); - helper.shouldNotGetCalled(); + assert.fail(); } catch (err) { expect(err).to.be.an.instanceOf(SyntaxError); expect(err.message).to.equal('API version number must be a string (e.g. "1.0.0") not a number.'); diff --git a/test/specs/invalid/newer-version.yaml b/test/specs/invalid/newer-version.yaml index a7a713d9..8a3b33bf 100644 --- a/test/specs/invalid/newer-version.yaml +++ b/test/specs/invalid/newer-version.yaml @@ -1,11 +1,11 @@ -swagger: "3.0" +swagger: '3.0' info: - version: "1.0.0" + version: '1.0.0' title: newer version description: This swagger spec is invalid because version 3.0 is not supported paths: /users: get: responses: - "200": - description: hello world + '200': + description: hello world diff --git a/test/specs/invalid/no-paths-or-webhooks.yaml b/test/specs/invalid/no-paths-or-webhooks.yaml index dfef231b..bec8ae01 100644 --- a/test/specs/invalid/no-paths-or-webhooks.yaml +++ b/test/specs/invalid/no-paths-or-webhooks.yaml @@ -1,4 +1,4 @@ -openapi: "3.1" +openapi: '3.1' info: - version: "1.0.0" + version: '1.0.0' title: Invalid API diff --git a/test/specs/invalid/numeric-info-version.yaml b/test/specs/invalid/numeric-info-version.yaml index cae097b7..5a08d517 100644 --- a/test/specs/invalid/numeric-info-version.yaml +++ b/test/specs/invalid/numeric-info-version.yaml @@ -1,4 +1,4 @@ -swagger: "2.0" +swagger: '2.0' info: version: 1.0 title: old version @@ -7,5 +7,5 @@ paths: /users: get: responses: - "200": - description: hello world + '200': + description: hello world diff --git a/test/specs/invalid/numeric-version.yaml b/test/specs/invalid/numeric-version.yaml index b6b83932..999a2efe 100644 --- a/test/specs/invalid/numeric-version.yaml +++ b/test/specs/invalid/numeric-version.yaml @@ -1,11 +1,11 @@ swagger: 2.0 info: - version: "1.0.0" + version: '1.0.0' title: old version description: This swagger spec is invalid because version 1.2 is not supported paths: /users: get: responses: - "200": - description: hello world + '200': + description: hello world diff --git a/test/specs/invalid/old-version.yaml b/test/specs/invalid/old-version.yaml index 5b4b8602..04989534 100644 --- a/test/specs/invalid/old-version.yaml +++ b/test/specs/invalid/old-version.yaml @@ -1,11 +1,11 @@ -swagger: "1.2" +swagger: '1.2' info: - version: "1.0.0" + version: '1.0.0' title: old version description: This swagger spec is invalid because version 1.2 is not supported paths: /users: get: responses: - "200": - description: hello world + '200': + description: hello world diff --git a/test/specs/large-file-memory-leak/large-file-memory-leak.spec.js b/test/specs/large-file-memory-leak/large-file-memory-leak.spec.js deleted file mode 100644 index fed9a3f3..00000000 --- a/test/specs/large-file-memory-leak/large-file-memory-leak.spec.js +++ /dev/null @@ -1,36 +0,0 @@ -const { expect } = require('chai'); - -const OpenAPIParser = require('../../..'); -const helper = require('../../utils/helper'); -const path = require('../../utils/path'); - -describe('Large file memory leak protection', function () { - this.timeout(20000); - - const tests = [ - { - name: 'cloudflare spec (stringified to a single line)', - file: 'cloudflare-stringified.json', - }, - { - name: 'cloudflare spec', - file: 'cloudflare.json', - }, - ]; - - for (const test of tests) { - it(test.name, async function () { - try { - await OpenAPIParser.validate(path.rel(`specs/large-file-memory-leak/${test.file}`)); - helper.shouldNotGetCalled(); - } catch (err) { - expect(err).to.be.an.instanceOf(SyntaxError); - expect(err.message).to.match(/^OpenAPI schema validation failed.\n(.*)+/); - expect((err.message.match(/4xx is not expected to be here!/g) || []).length).to.equal(20); - expect(err.message).to.contain( - 'Plus an additional 1016 errors. Please resolve the above and re-run validation to see more.', - ); - } - }); - } -}); diff --git a/test/specs/large-file-memory-leak/large-file-memory-leak.test.ts b/test/specs/large-file-memory-leak/large-file-memory-leak.test.ts new file mode 100644 index 00000000..89d4e4b1 --- /dev/null +++ b/test/specs/large-file-memory-leak/large-file-memory-leak.test.ts @@ -0,0 +1,23 @@ +import { describe, it, expect, assert } from 'vitest'; + +import OpenAPIParser from '../../..'; +import path from '../../utils/path'; + +describe('Large file memory leak protection', { timeout: 20000 }, () => { + it.each([ + ['cloudflare spec (stringified to a single line)', 'cloudflare-stringified.json'], + ['cloudflare spec', 'cloudflare.json'], + ])('%s', async (name, file) => { + try { + await OpenAPIParser.validate(path.rel(`specs/large-file-memory-leak/${file}`)); + assert.fail(); + } catch (err) { + expect(err).to.be.an.instanceOf(SyntaxError); + expect(err.message).to.match(/^OpenAPI schema validation failed.\n(.*)+/); + expect((err.message.match(/4xx is not expected to be here!/g) || []).length).to.equal(20); + expect(err.message).to.contain( + 'Plus an additional 1016 errors. Please resolve the above and re-run validation to see more.', + ); + } + }); +}); diff --git a/test/specs/oas-relative-servers/v3-non-relative-server.json b/test/specs/oas-relative-servers/v3-non-relative-server.json index d18d65b3..e6b3373e 100644 --- a/test/specs/oas-relative-servers/v3-non-relative-server.json +++ b/test/specs/oas-relative-servers/v3-non-relative-server.json @@ -1,77 +1,74 @@ { - "openapi": "3.0.0", - "info": { - "version": "1.0.0", - "title": "Swagger Petstore" - }, - "servers": [ + "openapi": "3.0.0", + "info": { + "version": "1.0.0", + "title": "Swagger Petstore" + }, + "servers": [ + { + "url": "https://petstore3.swagger.com/api/v3" + } + ], + "paths": { + "/pet": { + "servers": [ { - "url": "https://petstore3.swagger.com/api/v3" + "url": "https://petstore3.swagger.com/api/v4" } - ], - "paths": { - "/pet": { - "servers": [ - { - "url": "https://petstore3.swagger.com/api/v4" - } - ], - "get": { - "servers": [ - { - "url": "https://petstore3.swagger.com/api/v5" - } - ], - "summary": "List all pets", - "operationId": "listPets", - "parameters": [ - { - "name": "limit", - "in": "query", - "description": "How many items to return at one time (max 100)", - "required": false, - "schema": { - "type": "integer", - "format": "int32" - } - } - ], - "responses": { - "200": { - "description": "A paged array of pets", - "content": { - "application/json": { - "schema":{ - "type": "array", - "items": { - "$ref": "#/components/schemas/Pet" - } - } - } - } - } - } + ], + "get": { + "servers": [ + { + "url": "https://petstore3.swagger.com/api/v5" + } + ], + "summary": "List all pets", + "operationId": "listPets", + "parameters": [ + { + "name": "limit", + "in": "query", + "description": "How many items to return at one time (max 100)", + "required": false, + "schema": { + "type": "integer", + "format": "int32" } - } - }, - "components": { - "schemas": { - "Pet": { - "type": "object", - "required": [ - "id", - "name" - ], - "properties": { - "id": { - "type": "integer", - "format": "int64" - }, - "name": { - "type": "string" - } + } + ], + "responses": { + "200": { + "description": "A paged array of pets", + "content": { + "application/json": { + "schema": { + "type": "array", + "items": { + "$ref": "#/components/schemas/Pet" + } } + } } + } + } + } + } + }, + "components": { + "schemas": { + "Pet": { + "type": "object", + "required": ["id", "name"], + "properties": { + "id": { + "type": "integer", + "format": "int64" + }, + "name": { + "type": "string" + } } + } } -} \ No newline at end of file + } +} diff --git a/test/specs/oas-relative-servers/v3-relative-server-paths-ops.json b/test/specs/oas-relative-servers/v3-relative-server-paths-ops.json index 903e59f2..15d2cce2 100644 --- a/test/specs/oas-relative-servers/v3-relative-server-paths-ops.json +++ b/test/specs/oas-relative-servers/v3-relative-server-paths-ops.json @@ -1,77 +1,74 @@ { - "openapi": "3.0.0", - "info": { - "version": "1.0.0", - "title": "Swagger Petstore" - }, - "servers": [ + "openapi": "3.0.0", + "info": { + "version": "1.0.0", + "title": "Swagger Petstore" + }, + "servers": [ + { + "url": "/api/v3" + } + ], + "paths": { + "/pet": { + "servers": [ { - "url": "/api/v3" + "url": "/api/v4" } - ], - "paths": { - "/pet": { - "servers": [ - { - "url": "/api/v4" - } - ], - "get": { - "servers": [ - { - "url": "/api/v5" - } - ], - "summary": "List all pets", - "operationId": "listPets", - "parameters": [ - { - "name": "limit", - "in": "query", - "description": "How many items to return at one time (max 100)", - "required": false, - "schema": { - "type": "integer", - "format": "int32" - } - } - ], - "responses": { - "200": { - "description": "A paged array of pets", - "content": { - "application/json": { - "schema":{ - "type": "array", - "items": { - "$ref": "#/components/schemas/Pet" - } - } - } - } - } - } + ], + "get": { + "servers": [ + { + "url": "/api/v5" + } + ], + "summary": "List all pets", + "operationId": "listPets", + "parameters": [ + { + "name": "limit", + "in": "query", + "description": "How many items to return at one time (max 100)", + "required": false, + "schema": { + "type": "integer", + "format": "int32" } - } - }, - "components": { - "schemas": { - "Pet": { - "type": "object", - "required": [ - "id", - "name" - ], - "properties": { - "id": { - "type": "integer", - "format": "int64" - }, - "name": { - "type": "string" - } + } + ], + "responses": { + "200": { + "description": "A paged array of pets", + "content": { + "application/json": { + "schema": { + "type": "array", + "items": { + "$ref": "#/components/schemas/Pet" + } } + } } + } + } + } + } + }, + "components": { + "schemas": { + "Pet": { + "type": "object", + "required": ["id", "name"], + "properties": { + "id": { + "type": "integer", + "format": "int64" + }, + "name": { + "type": "string" + } } + } } -} \ No newline at end of file + } +} diff --git a/test/specs/oas-relative-servers/v3-relative-server.json b/test/specs/oas-relative-servers/v3-relative-server.json index cb00b912..79b5865b 100644 --- a/test/specs/oas-relative-servers/v3-relative-server.json +++ b/test/specs/oas-relative-servers/v3-relative-server.json @@ -1,67 +1,64 @@ { - "openapi": "3.0.0", - "info": { - "version": "1.0.0", - "title": "Swagger Petstore" - }, - "servers": [ - { - "url": "/api/v3" - } - ], - "paths": { - "/pet": { - "get": { - "summary": "List all pets", - "operationId": "listPets", - "parameters": [ - { - "name": "limit", - "in": "query", - "description": "How many items to return at one time (max 100)", - "required": false, - "schema": { - "type": "integer", - "format": "int32" - } - } - ], - "responses": { - "200": { - "description": "A paged array of pets", - "content": { - "application/json": { - "schema":{ - "type": "array", - "items": { - "$ref": "#/components/schemas/Pet" - } - } - } - } - } - } + "openapi": "3.0.0", + "info": { + "version": "1.0.0", + "title": "Swagger Petstore" + }, + "servers": [ + { + "url": "/api/v3" + } + ], + "paths": { + "/pet": { + "get": { + "summary": "List all pets", + "operationId": "listPets", + "parameters": [ + { + "name": "limit", + "in": "query", + "description": "How many items to return at one time (max 100)", + "required": false, + "schema": { + "type": "integer", + "format": "int32" } - } - }, - "components": { - "schemas": { - "Pet": { - "type": "object", - "required": [ - "id", - "name" - ], - "properties": { - "id": { - "type": "integer", - "format": "int64" - }, - "name": { - "type": "string" - } + } + ], + "responses": { + "200": { + "description": "A paged array of pets", + "content": { + "application/json": { + "schema": { + "type": "array", + "items": { + "$ref": "#/components/schemas/Pet" + } } + } } + } + } + } + } + }, + "components": { + "schemas": { + "Pet": { + "type": "object", + "required": ["id", "name"], + "properties": { + "id": { + "type": "integer", + "format": "int64" + }, + "name": { + "type": "string" + } } + } } -} \ No newline at end of file + } +} diff --git a/test/specs/oas-relative-servers/v3-relative-servers.spec.js b/test/specs/oas-relative-servers/v3-relative-servers.test.ts similarity index 84% rename from test/specs/oas-relative-servers/v3-relative-servers.spec.js rename to test/specs/oas-relative-servers/v3-relative-servers.test.ts index 563069fd..f453d586 100644 --- a/test/specs/oas-relative-servers/v3-relative-servers.spec.js +++ b/test/specs/oas-relative-servers/v3-relative-servers.test.ts @@ -1,14 +1,14 @@ -const $RefParser = require('@readme/json-schema-ref-parser'); -const { expect } = require('chai'); -const sinon = require('sinon'); +import $RefParser from '@readme/json-schema-ref-parser'; +import sinon from 'sinon'; +import { describe, it, expect, beforeEach, afterEach } from 'vitest'; -const OpenAPIParser = require('../../../lib'); -const path = require('../../utils/path'); +import OpenAPIParser from '../../../lib'; +import path from '../../utils/path'; // Import of our fixed OpenAPI JSON files -const v3NonRelativeServerJson = require('./v3-non-relative-server.json'); -const v3RelativeServerPathsOpsJson = require('./v3-relative-server-paths-ops.json'); -const v3RelativeServerJson = require('./v3-relative-server.json'); +import v3NonRelativeServerJson from './v3-non-relative-server.json'; +import v3RelativeServerPathsOpsJson from './v3-relative-server-paths-ops.json'; +import v3RelativeServerJson from './v3-relative-server.json'; // Petstore v3 json has relative path in "servers" const RELATIVE_SERVERS_OAS3_URL_1 = 'https://petstore3.swagger.io/api/v3/openapi.json'; @@ -19,12 +19,12 @@ const RELATIVE_SERVERS_OAS3_URL_2 = 'https://foo.my.cloud/v1/petstore/relativese describe('Servers with relative paths in OpenAPI v3 files', () => { let mockParse; - before(() => { + beforeEach(() => { // Mock the parse function mockParse = sinon.stub($RefParser.prototype, 'parse'); }); - after(() => { + afterEach(() => { // Restore the parse function $RefParser.prototype.parse.restore(); }); diff --git a/test/specs/object-source/definitions/name.yaml b/test/specs/object-source/definitions/name.yaml index 9d795707..518dae1b 100644 --- a/test/specs/object-source/definitions/name.yaml +++ b/test/specs/object-source/definitions/name.yaml @@ -10,13 +10,13 @@ properties: $ref: ./required-string.yaml middle: type: - $ref: "#/properties/first/type" + $ref: '#/properties/first/type' minLength: - $ref: "#/properties/first/minLength" + $ref: '#/properties/first/minLength' prefix: - $ref: "#/properties/last" + $ref: '#/properties/last' minLength: 3 suffix: type: string - $ref: "#/properties/prefix" + $ref: '#/properties/prefix' maxLength: 3 diff --git a/test/specs/object-source/object-source.spec.js b/test/specs/object-source/object-source.test.ts similarity index 92% rename from test/specs/object-source/object-source.spec.js rename to test/specs/object-source/object-source.test.ts index 150b5565..4a2c6952 100644 --- a/test/specs/object-source/object-source.spec.js +++ b/test/specs/object-source/object-source.test.ts @@ -1,11 +1,11 @@ -const { expect } = require('chai'); +import { describe, it, expect } from 'vitest'; -const OpenAPIParser = require('../../..'); -const path = require('../../utils/path'); +import OpenAPIParser from '../../..'; +import path from '../../utils/path'; -const bundledAPI = require('./bundled'); -const dereferencedAPI = require('./dereferenced'); -const parsedAPI = require('./parsed'); +import bundledAPI from './bundled'; +import dereferencedAPI from './dereferenced'; +import parsedAPI from './parsed'; describe('Object sources (instead of file paths)', () => { it('should dereference an object that references external files', async () => { diff --git a/test/specs/real-world/known-errors.js b/test/specs/real-world/known-errors.js deleted file mode 100644 index 96b00d11..00000000 --- a/test/specs/real-world/known-errors.js +++ /dev/null @@ -1,347 +0,0 @@ -const knownErrors = { - /** - * An array of known validation errors in certain API definitions on APIs.guru - */ - all: getKnownApiErrors(), - - /** - * Determines whether an API and error match a known error. - */ - find(api, error) { - for (const knownError of knownErrors.all) { - if (typeof knownError.api === 'string' && !api.name.includes(knownError.api)) { - // eslint-disable-next-line no-continue - continue; - } - - if (typeof knownError.error === 'string' && !error.message.includes(knownError.error)) { - // eslint-disable-next-line no-continue - continue; - } - - if (knownError.error instanceof RegExp && !knownError.error.test(error.message)) { - // eslint-disable-next-line no-continue - continue; - } - - return knownError; - } - - return false; - }, -}; - -module.exports = knownErrors; - -/** - * Returns a list of known validation errors in certain API definitions on APIs.guru. - */ -function getKnownApiErrors() { - const errors = [ - // Many of the Azure API definitions have references to external files that don't exist - // NOTE: This entry must come FIRST, otherwise every broken Azure API is retried multiple times - { - api: 'azure.com', - error: /Error downloading https?:/, - whatToDo: 'ignore', - }, - - // If the API definition failed to download, then retry - { - error: /Error downloading https?:/, - whatToDo: 'retry', - }, - { - error: 'socket hang up', - whatToDo: 'retry', - }, - - { - api: 'autotask.net', - error: '/definitions/Expression[Func[AccountAlert,Int64]] has an invalid name', - whatToDo: 'ignore', - }, - - // Many Azure API definitions erroneously reference external files that don't exist - { - api: 'azure.com', - error: /Error downloading .*\.json\s+HTTP ERROR 404/, - whatToDo: 'ignore', - }, - - // Many Azure API definitions have endpoints with multiple "location" placeholders, which is invalid. - { - api: 'azure.com', - error: 'has multiple path placeholders named {location}', - whatToDo: 'ignore', - }, - - { - api: 'azure.com:deviceprovisioningservices-iotdps', - error: 'Definition names should match against: /^[a-zA-Z0-9.-_]+$/', - whatToDo: 'ignore', - }, - - { - api: 'azure.com:labservices-ML', - error: 'Definition names should match against: /^[a-zA-Z0-9.-_]+$/', - whatToDo: 'ignore', - }, - - { - api: 'azure.com:migrateprojects-migrate', - error: 'Definition names should match against: /^[a-zA-Z0-9.-_]+$/', - whatToDo: 'ignore', - }, - - { - api: 'azure.com:provisioningservices-iotdps', - error: 'Definition names should match against: /^[a-zA-Z0-9.-_]+$/', - whatToDo: 'ignore', - }, - - { - api: 'azure.com:web-service', - error: 'Definition names should match against: /^[a-zA-Z0-9.-_]+$/', - whatToDo: 'ignore', - }, - - { - api: 'avaza.com', - error: 'has a file parameter, so it must consume multipart/form-data or application/x-www-form-urlencoded', - whatToDo: 'ignore', - }, - - { - api: 'adyen.com:CheckoutService', - error: 'source is not expected to be here', - whatToDo: 'ignore', - }, - { - api: 'adyen.com:PaymentService', - error: 'source is not expected to be here', - whatToDo: 'ignore', - }, - { - api: 'adyen.com:PayoutService', - error: 'source is not expected to be here', - whatToDo: 'ignore', - }, - { - api: 'adyen.com:RecurringService', - error: 'source is not expected to be here', - whatToDo: 'ignore', - }, - { - api: 'amadeus.com:amadeus-hotel-ratings', - error: - "Property 'avgHotelAvailabilityResponseTime' listed as required but does not exist in '/definitions/HotelSentiment'", - whatToDo: 'ignore', - }, - { - api: 'billbee.io', - error: 'Definition names should match against: /^[a-zA-Z0-9.-_]+$/', - whatToDo: 'ignore', - }, - { - api: 'blazemeter.com', - error: 'Definition names should match against: /^[a-zA-Z0-9.-_]+$/', - whatToDo: 'ignore', - }, - { - api: 'clarify.io', - error: 'Definition names should match against: /^[a-zA-Z0-9.-_]+$/', - whatToDo: 'ignore', - }, - { - api: 'clicksend.com', - error: '/paths/uploads?convert={convert}/post is missing path parameter(s) for {convert}', - whatToDo: 'ignore', - }, - - // Cloudmersive.com's API definition contains invalid JSON Schema types - { - api: 'cloudmersive.com:ocr', - error: 'ENUM must be equal to one of the allowed values', - whatToDo: 'ignore', - }, - - // Contribly's API has a misspelled field name - { - api: 'contribly.com', - error: "Property 'includeThumbnail' listed as required but does not exist", - whatToDo: 'ignore', - }, - - { - api: 'dnd5eapi.co', - error: 'TYPE must be array', - whatToDo: 'ignore', - }, - { - api: 'enode.io', - error: 'explode is not expected to be here', - whatToDo: 'ignore', - }, - { - api: 'frankiefinancial.io', - error: "Property 'rowid' listed as required but does not exist", - whatToDo: 'ignore', - }, - { - api: 'geneea.com', - error: 'Definition names should match against: /^[a-zA-Z0-9.-_]+$/', - whatToDo: 'ignore', - }, - { - api: 'github.com', - error: 'Token "0" does not exist', - whatToDo: 'ignore', - }, - { - api: 'github.com', - error: 'Token "expires_at" does not exist', - whatToDo: 'ignore', - }, - - // Some Google APIs have a `source` property at the root. - { - api: 'googleapis.com', - error: 'source is not expected to be here', - whatToDo: 'ignore', - }, - - { - api: 'hetras-certification.net:booking', - error: 'Definition names should match against: /^[a-zA-Z0-9.-_]+$/', - whatToDo: 'ignore', - }, - { - api: 'hetras-certification.net:hotel', - error: 'Definition names should match against: /^[a-zA-Z0-9.-_]+$/', - whatToDo: 'ignore', - }, - { - api: 'icons8.com', - error: - '/paths/api/iconsets/v3/latest?term={term}&amount={amount}&offset={offset}&platform={platform}&language={language}/get is missing path parameter(s) for {term}', - whatToDo: 'ignore', - }, - { - api: 'motaword.com', - error: 'descriptipon is not expected to be here', - whatToDo: 'ignore', - }, - { - api: 'naviplancentral.com:plan', - error: 'Definition names should match against: /^[a-zA-Z0-9.-_]+$/', - whatToDo: 'ignore', - }, - { - api: 'openapi-generator.tech', - error: 'originalRef is not expected to be here!', - whatToDo: 'ignore', - }, - { - api: 'opensuse.org', - error: 'example is not expected to be here!', - whatToDo: 'ignore', - }, - - // Missing a required field - { - api: 'opto22.com:groov', - error: "Property 'isCoreInUse' listed as required but does not exist", - whatToDo: 'ignore', - }, - - { - api: 'osisoft.com', - error: '/definitions/Item[Attribute] has an invalid name', - whatToDo: 'ignore', - }, - { - api: 'parliament.uk', - error: '/definitions/ResourceCollection[BusinessItem] has an invalid name', - whatToDo: 'ignore', - }, - { - api: 'personio.de', - error: 'Token "comment" does not exist', - whatToDo: 'ignore', - }, - - // Missing a required field - { - api: 'postmarkapp.com:server', - error: "Property 'TemplateId' listed as required but does not exist", - whatToDo: 'ignore', - }, - - { - api: 'rebilly.com', - error: 'Token "feature" does not exist', - whatToDo: 'ignore', - }, - { - api: 'semantria.com', - error: '/definitions/Request class has an invalid name', - whatToDo: 'ignore', - }, - { - api: 'staging-ecotaco.com', - error: '/paths/rides?page={page}&per_page={per_page}/post is missing path parameter(s) for {page},{per_page}', - whatToDo: 'ignore', - }, - { - api: 'statsocial.com', - error: 'Token "18_24" does not exist', - whatToDo: 'ignore', - }, - { - api: 'testfire.net:altoroj', - error: "Property 'passwrod1' listed as required but does not exist", - whatToDo: 'ignore', - }, - { - api: 'turbinelabs.io', - error: "Property 'listener_key' listed as required but does not exist", - whatToDo: 'ignore', - }, - - // VersionEye's API definition is missing MIME types - { - api: 'versioneye.com', - error: 'has a file parameter, so it must consume multipart/form-data or application/x-www-form-urlencoded', - whatToDo: 'ignore', - }, - - { - api: 'vestorly.com', - error: "Property 'orginator_email' listed as required but does not exist", - whatToDo: 'ignore', - }, - { - api: 'viator.com', - error: 'Token "pas" does not exist', - whatToDo: 'ignore', - }, - { - api: 'wedpax.com', - error: '/definitions/ListResultDto[PermissionDto] has an invalid name', - whatToDo: 'ignore', - }, - { - api: 'whapi.com:accounts', - error: "Property 'nif (italy only)' listed as required but does not exist", - whatToDo: 'ignore', - }, - { - api: 'xero.com:xero_accounting', - error: 'type is not expected to be here', - whatToDo: 'ignore', - }, - ]; - - return errors; -} diff --git a/test/specs/real-world/known-errors.ts b/test/specs/real-world/known-errors.ts new file mode 100644 index 00000000..b1aacaa5 --- /dev/null +++ b/test/specs/real-world/known-errors.ts @@ -0,0 +1,268 @@ +interface KnownError { + api: string; + error: RegExp | string; +} + +const knownErrors: KnownError[] = [ + { + api: 'autotask.net', + error: '/definitions/Expression[Func[AccountAlert,Int64]] has an invalid name', + }, + + // Many Azure API definitions erroneously reference external files that don't exist + { + api: 'azure.com', + error: /Error downloading .*\.json\s+HTTP ERROR 404/, + }, + + // Many Azure API definitions have endpoints with multiple "location" placeholders, which is invalid. + { + api: 'azure.com', + error: 'has multiple path placeholders named {location}', + }, + + { + api: 'azure.com:deviceprovisioningservices-iotdps', + error: 'Definition names should match against: /^[a-zA-Z0-9.-_]+$/', + }, + + { + api: 'azure.com:labservices-ML', + error: 'Definition names should match against: /^[a-zA-Z0-9.-_]+$/', + }, + + { + api: 'azure.com:migrateprojects-migrate', + error: 'Definition names should match against: /^[a-zA-Z0-9.-_]+$/', + }, + + { + api: 'azure.com:provisioningservices-iotdps', + error: 'Definition names should match against: /^[a-zA-Z0-9.-_]+$/', + }, + + { + api: 'azure.com:web-service', + error: 'Definition names should match against: /^[a-zA-Z0-9.-_]+$/', + }, + + { + api: 'avaza.com', + error: 'has a file parameter, so it must consume multipart/form-data or application/x-www-form-urlencoded', + }, + + { + api: 'adyen.com:CheckoutService', + error: 'source is not expected to be here', + }, + { + api: 'adyen.com:PaymentService', + error: 'source is not expected to be here', + }, + { + api: 'adyen.com:PayoutService', + error: 'source is not expected to be here', + }, + { + api: 'adyen.com:RecurringService', + error: 'source is not expected to be here', + }, + { + api: 'amadeus.com:amadeus-hotel-ratings', + error: + "Property 'avgHotelAvailabilityResponseTime' listed as required but does not exist in '/definitions/HotelSentiment'", + }, + { + api: 'billbee.io', + error: 'Definition names should match against: /^[a-zA-Z0-9.-_]+$/', + }, + { + api: 'blazemeter.com', + error: 'Definition names should match against: /^[a-zA-Z0-9.-_]+$/', + }, + { + api: 'clarify.io', + error: 'Definition names should match against: /^[a-zA-Z0-9.-_]+$/', + }, + { + api: 'clicksend.com', + error: '/paths/uploads?convert={convert}/post is missing path parameter(s) for {convert}', + }, + + // Cloudmersive.com's API definition contains invalid JSON Schema types + { + api: 'cloudmersive.com:ocr', + error: 'ENUM must be equal to one of the allowed values', + }, + + // Contribly's API has a misspelled field name + { + api: 'contribly.com', + error: "Property 'includeThumbnail' listed as required but does not exist", + }, + + { + api: 'dnd5eapi.co', + error: 'TYPE must be array', + }, + { + api: 'enode.io', + error: 'explode is not expected to be here', + }, + { + api: 'frankiefinancial.io', + error: "Property 'rowid' listed as required but does not exist", + }, + { + api: 'geneea.com', + error: 'Definition names should match against: /^[a-zA-Z0-9.-_]+$/', + }, + { + api: 'github.com', + error: 'Token "0" does not exist', + }, + { + api: 'github.com', + error: 'Token "expires_at" does not exist', + }, + + // Some Google APIs have a `source` property at the root. + { + api: 'googleapis.com', + error: 'source is not expected to be here', + }, + + { + api: 'hetras-certification.net:booking', + error: 'Definition names should match against: /^[a-zA-Z0-9.-_]+$/', + }, + { + api: 'hetras-certification.net:hotel', + error: 'Definition names should match against: /^[a-zA-Z0-9.-_]+$/', + }, + { + api: 'icons8.com', + error: + '/paths/api/iconsets/v3/latest?term={term}&amount={amount}&offset={offset}&platform={platform}&language={language}/get is missing path parameter(s) for {term}', + }, + { + api: 'motaword.com', + error: 'descriptipon is not expected to be here', + }, + { + api: 'naviplancentral.com:plan', + error: 'Definition names should match against: /^[a-zA-Z0-9.-_]+$/', + }, + { + api: 'openapi-generator.tech', + error: 'originalRef is not expected to be here!', + }, + { + api: 'opensuse.org', + error: 'example is not expected to be here!', + }, + + // Missing a required field + { + api: 'opto22.com:groov', + error: "Property 'isCoreInUse' listed as required but does not exist", + }, + + { + api: 'osisoft.com', + error: '/definitions/Item[Attribute] has an invalid name', + }, + { + api: 'parliament.uk', + error: '/definitions/ResourceCollection[BusinessItem] has an invalid name', + }, + { + api: 'personio.de', + error: 'Token "comment" does not exist', + }, + + // Missing a required field + { + api: 'postmarkapp.com:server', + error: "Property 'TemplateId' listed as required but does not exist", + }, + + { + api: 'rebilly.com', + error: 'Token "feature" does not exist', + }, + { + api: 'semantria.com', + error: '/definitions/Request class has an invalid name', + }, + { + api: 'staging-ecotaco.com', + error: '/paths/rides?page={page}&per_page={per_page}/post is missing path parameter(s) for {page},{per_page}', + }, + { + api: 'statsocial.com', + error: 'Token "18_24" does not exist', + }, + { + api: 'testfire.net:altoroj', + error: "Property 'passwrod1' listed as required but does not exist", + }, + { + api: 'turbinelabs.io', + error: "Property 'listener_key' listed as required but does not exist", + }, + + // VersionEye's API definition is missing MIME types + { + api: 'versioneye.com', + error: 'has a file parameter, so it must consume multipart/form-data or application/x-www-form-urlencoded', + }, + + { + api: 'vestorly.com', + error: "Property 'orginator_email' listed as required but does not exist", + }, + { + api: 'viator.com', + error: 'Token "pas" does not exist', + }, + { + api: 'wedpax.com', + error: '/definitions/ListResultDto[PermissionDto] has an invalid name', + }, + { + api: 'whapi.com:accounts', + error: "Property 'nif (italy only)' listed as required but does not exist", + }, + { + api: 'xero.com:xero_accounting', + error: 'type is not expected to be here', + }, +]; + +/** + * Determines whether an API and error match a known error. + * + */ +export function isKnownError(api: string, error: Error) { + for (const knownError of knownErrors) { + if (typeof knownError.api === 'string' && !api.includes(knownError.api)) { + // eslint-disable-next-line no-continue + continue; + } + + if (typeof knownError.error === 'string' && !error.message.includes(knownError.error)) { + // eslint-disable-next-line no-continue + continue; + } + + if (knownError.error instanceof RegExp && !knownError.error.test(error.message)) { + // eslint-disable-next-line no-continue + continue; + } + + return knownError; + } + + return false; +} diff --git a/test/specs/real-world/real-world.spec.js b/test/specs/real-world/real-world.spec.js deleted file mode 100644 index 59177ca4..00000000 --- a/test/specs/real-world/real-world.spec.js +++ /dev/null @@ -1,82 +0,0 @@ -const { host } = require('@jsdevtools/host-environment'); - -const OpenAPIParser = require('../../..'); -const realWorldAPIs = require('../../fixtures/real-world-apis.json'); - -const knownErrors = require('./known-errors'); - -// How many APIs to test in "quick mode" and normal mode -const MAX_APIS_TO_TEST = process.argv.includes('--quick-test') ? 10 : 1500; -const START_AT_INDEX = 0; -const MAX_DOWNLOAD_RETRIES = 3; - -describe('Real-world APIs', () => { - beforeEach(function () { - // Increase the timeouts by A LOT because: - // 1) CI is really slow - // 2) Some API definitions are HUGE and take a while to download - // 3) If the download fails, we retry 2 times, which takes even more time - // 4) Really large API definitions take longer to pase, dereference, and validate - this.currentTest.timeout(host.ci ? 300000 : 60000); // 5 minutes in CI, 1 minute locally - this.currentTest.slow(5000); - }); - - // Mocha requires us to create our tests synchronously. But the list of APIs is downloaded asynchronously. - // So, we just create a bunch of placeholder tests, and then rename them later to reflect which API they're testing. - for (let index = START_AT_INDEX; index < START_AT_INDEX + MAX_APIS_TO_TEST; index++) { - if (!(index in realWorldAPIs)) { - return; - } - - it(`${index + 1}) `, testAPI(index)); - } - - /** - * This Mocha test is repeated for each API in the APIs.guru registry - */ - function testAPI(index) { - return async function () { - const api = realWorldAPIs[index]; - this.test.title += api.name; - await validateApi(api); - }; - } - - /** - * Downloads an API definition and validates it. Automatically retries if the download fails. - */ - async function validateApi(api, attemptNumber = 1) { - try { - await OpenAPIParser.validate(api.url); - } catch (error) { - // Validation failed. But is this a known error? - const knownError = knownErrors.find(api, error); - - if (knownError) { - if (knownError.whatToDo === 'ignore') { - // Ignore the error. It's a known problem with this API - return null; - } else if (knownError.whatToDo === 'retry') { - if (attemptNumber >= MAX_DOWNLOAD_RETRIES) { - console.error(' failed to download. giving up.'); - return null; - } - - // Wait a few seconds, then try the download again - await new Promise(resolve => { - console.error(' failed to download. trying again...'); - setTimeout(resolve, 2000); - }); - - await validateApi(api, attemptNumber + 1); - } - } else { - // This is not a known error - console.error('\n\nERROR IN THIS API:', JSON.stringify(api, null, 2)); - throw error; - } - } - - return null; - } -}); diff --git a/test/specs/real-world/real-world.test.ts b/test/specs/real-world/real-world.test.ts new file mode 100644 index 00000000..03719b48 --- /dev/null +++ b/test/specs/real-world/real-world.test.ts @@ -0,0 +1,41 @@ +import { host } from '@jsdevtools/host-environment'; +import { describe, it } from 'vitest'; + +import OpenAPIParser from '../../..'; +import realWorldAPIs from '../../fixtures/real-world-apis.json'; + +import { isKnownError } from './known-errors'; + +const MAX_APIS_TO_TEST = host.ci ? 1500 : 100; + +describe( + 'Real-world APIs', + { + // Increase the timeouts by A LOT because: + // 1) CI is really slow + // 2) Some API definitions are HUGE and take a while to download + // 3) If the download fails, we retry 2 times, which takes even more time + // 4) Really large API definitions take longer to pase, dereference, and validate + // timeout: host.ci ? 300000 : 60000, // 5 minutes in CI, 1 minute locally + }, + () => { + it.each(realWorldAPIs.slice(0, MAX_APIS_TO_TEST))('$name', async api => { + try { + await OpenAPIParser.validate(api.url); + } catch (error) { + // If we have errors pulling the API definition down then don't fail out. + if (error.message.includes('Error downloading https://') || error.message.includes('socket hang up')) { + return; + } + + // Validation failed but maybe we've marked this as a known and acceptable error. + const knownError = isKnownError(api.name, error); + if (knownError) { + return; + } + + throw error; + } + }); + }, +); diff --git a/test/specs/typescript-definition.spec.ts b/test/specs/typescript-definition.spec.ts index ff31746f..0e288d73 100644 --- a/test/specs/typescript-definition.spec.ts +++ b/test/specs/typescript-definition.spec.ts @@ -1,31 +1,33 @@ -import * as assert from "assert"; -import { OpenAPI } from "openapi-types"; -import * as OpenAPIParser from "../../lib"; +/* eslint-disable @typescript-eslint/no-unused-vars */ +/* eslint-disable vitest/require-hook */ +/* eslint-disable vitest/consistent-test-filename */ +import type { OpenAPI } from 'openapi-types'; -const baseUrl = "http://example.com/api"; -const openapiPath = "my-api.json"; +import * as assert from 'assert'; + +import * as OpenAPIParser from '../../lib'; + +const baseUrl = 'http://example.com/api'; +const openapiPath = 'my-api.json'; const options = {}; const promiseResolve = (_: object) => undefined; const promiseReject = (_: Error) => undefined; const callback = (_err: Error | null, _api?: object) => undefined; const openapiObject: OpenAPI.Document = { - openapi: "3.0.0", + openapi: '3.0.0', info: { - title: "My API", - version: "1.0.0", + title: 'My API', + version: '1.0.0', }, - paths: {} + paths: {}, }; - // OpenAPIParser class instance -let parser = new OpenAPIParser(); - +const parser = new OpenAPIParser(); // OpenAPIParser instance properties assert(parser.$refs.circular === true); -assert(parser.api.info.title === "My API"); - +assert(parser.api.info.title === 'My API'); // OpenAPIParser instance methods (with callbacks) parser.bundle(openapiPath, callback); @@ -63,7 +65,6 @@ parser.resolve(openapiObject, options, callback); parser.resolve(baseUrl, openapiPath, options, callback); parser.resolve(baseUrl, openapiObject, options, callback); - // OpenAPIParser instance methods (with Promises) parser.bundle(openapiPath).then(promiseResolve, promiseReject); parser.bundle(openapiObject).then(promiseResolve, promiseReject); @@ -100,7 +101,6 @@ parser.resolve(openapiObject, options).then(promiseResolve, promiseReject); parser.resolve(baseUrl, openapiPath, options).then(promiseResolve, promiseReject); parser.resolve(baseUrl, openapiObject, options).then(promiseResolve, promiseReject); - // OpenAPIParser static methods (with callbacks) OpenAPIParser.bundle(openapiPath, callback); OpenAPIParser.bundle(openapiObject, callback); @@ -137,7 +137,6 @@ OpenAPIParser.resolve(openapiObject, options, callback); OpenAPIParser.resolve(baseUrl, openapiPath, options, callback); OpenAPIParser.resolve(baseUrl, openapiObject, options, callback); - // OpenAPIParser static methods (with Promises) OpenAPIParser.bundle(openapiPath).then(promiseResolve, promiseReject); OpenAPIParser.bundle(openapiObject).then(promiseResolve, promiseReject); diff --git a/test/specs/unknown/dereferenced.js b/test/specs/unknown/dereferenced.js index 9910df9c..c7835da4 100644 --- a/test/specs/unknown/dereferenced.js +++ b/test/specs/unknown/dereferenced.js @@ -27,7 +27,7 @@ module.exports = { schema: { type: 'file', default: - '\n\n\n \n \n\n\n

Hello World

\n\n\n', + '\n\n \n \n \n\n\n

Hello World

\n\n\n', }, }, }, diff --git a/test/specs/unknown/files/page.html b/test/specs/unknown/files/page.html index ec185c34..56ac49a1 100644 --- a/test/specs/unknown/files/page.html +++ b/test/specs/unknown/files/page.html @@ -1,17 +1,17 @@ - - + + - - + +

Hello World

- + diff --git a/test/specs/unknown/parsed.js b/test/specs/unknown/parsed.js index 10e83d56..add47d6c 100644 --- a/test/specs/unknown/parsed.js +++ b/test/specs/unknown/parsed.js @@ -74,7 +74,7 @@ module.exports = { text: 'Hello\nWorld\n', - html: '\n\n\n \n \n\n\n

Hello World

\n\n\n', + html: '\n\n \n \n \n \n \n

Hello World

\n \n\n', binary: { type: 'Buffer', diff --git a/test/specs/unknown/unknown.spec.js b/test/specs/unknown/unknown.test.ts similarity index 93% rename from test/specs/unknown/unknown.spec.js rename to test/specs/unknown/unknown.test.ts index 5d00aa06..755735c2 100644 --- a/test/specs/unknown/unknown.spec.js +++ b/test/specs/unknown/unknown.test.ts @@ -1,11 +1,11 @@ -const { expect } = require('chai'); +import { describe, it, expect } from 'vitest'; -const OpenAPIParser = require('../../..'); -const helper = require('../../utils/helper'); -const path = require('../../utils/path'); +import OpenAPIParser from '../../..'; +import * as helper from '../../utils/helper'; +import path from '../../utils/path'; -const dereferencedAPI = require('./dereferenced'); -const parsedAPI = require('./parsed'); +import dereferencedAPI from './dereferenced'; +import parsedAPI from './parsed'; describe('API with $refs to unknown file types', () => { it('should parse successfully', async () => { diff --git a/test/specs/unknown/unknown.yaml b/test/specs/unknown/unknown.yaml index 3360fd4e..95aa7d7d 100644 --- a/test/specs/unknown/unknown.yaml +++ b/test/specs/unknown/unknown.yaml @@ -1,4 +1,4 @@ -swagger: "2.0" +swagger: '2.0' info: version: 1.0.0 title: Unknown file types diff --git a/test/specs/validate-schema/invalid/anyof.yaml b/test/specs/validate-schema/invalid/anyof.yaml index 2a1d542c..a4199906 100644 --- a/test/specs/validate-schema/invalid/anyof.yaml +++ b/test/specs/validate-schema/invalid/anyof.yaml @@ -1,6 +1,6 @@ -swagger: "2.0" +swagger: '2.0' info: - version: "1.0.0" + version: '1.0.0' title: Invalid API paths: @@ -8,9 +8,9 @@ paths: get: responses: default: - description: hello world + description: hello world schema: - anyOf: # <--- "anyOf" is not supported by Swagger 2.0. Only "allOf" is supported. + anyOf: # <--- "anyOf" is not supported by Swagger 2.0. Only "allOf" is supported. - properties: firstName: type: string diff --git a/test/specs/validate-schema/invalid/file-body-param.yaml b/test/specs/validate-schema/invalid/file-body-param.yaml index 73a40cce..82949e30 100644 --- a/test/specs/validate-schema/invalid/file-body-param.yaml +++ b/test/specs/validate-schema/invalid/file-body-param.yaml @@ -1,6 +1,6 @@ -swagger: "2.0" +swagger: '2.0' info: - version: "1.0.0" + version: '1.0.0' title: Invalid API paths: @@ -13,8 +13,8 @@ paths: - name: image in: body schema: - type: file # <--- The "file" type can't be used with "body" params + type: file # <--- The "file" type can't be used with "body" params post: responses: default: - description: hello world + description: hello world diff --git a/test/specs/validate-schema/invalid/file-header-param.yaml b/test/specs/validate-schema/invalid/file-header-param.yaml index f98a1c2e..5cb3a7d6 100644 --- a/test/specs/validate-schema/invalid/file-header-param.yaml +++ b/test/specs/validate-schema/invalid/file-header-param.yaml @@ -1,6 +1,6 @@ -swagger: "2.0" +swagger: '2.0' info: - version: "1.0.0" + version: '1.0.0' title: Invalid API paths: @@ -12,8 +12,8 @@ paths: required: true - name: image in: header - type: file # <--- The "file" type can't be used with "header" params + type: file # <--- The "file" type can't be used with "header" params post: responses: default: - description: hello world + description: hello world diff --git a/test/specs/validate-schema/invalid/invalid-param-location.yaml b/test/specs/validate-schema/invalid/invalid-param-location.yaml index 45bd2898..2324b0ce 100644 --- a/test/specs/validate-schema/invalid/invalid-param-location.yaml +++ b/test/specs/validate-schema/invalid/invalid-param-location.yaml @@ -1,6 +1,6 @@ -swagger: "2.0" +swagger: '2.0' info: - version: "1.0.0" + version: '1.0.0' title: Invalid API paths: @@ -11,9 +11,9 @@ paths: required: true type: string - name: img_id - in: cookie # <--- "cookie" is not a valid Swagger param location + in: cookie # <--- "cookie" is not a valid Swagger param location type: number get: responses: default: - description: hello world + description: hello world diff --git a/test/specs/validate-schema/invalid/invalid-param-type.yaml b/test/specs/validate-schema/invalid/invalid-param-type.yaml index 0d199234..eeda3dd3 100644 --- a/test/specs/validate-schema/invalid/invalid-param-type.yaml +++ b/test/specs/validate-schema/invalid/invalid-param-type.yaml @@ -1,6 +1,6 @@ -swagger: "2.0" +swagger: '2.0' info: - version: "1.0.0" + version: '1.0.0' title: Invalid API paths: @@ -8,8 +8,8 @@ paths: parameters: - name: user in: query - type: user # <---- "user" is not a valid param type + type: user # <---- "user" is not a valid param type post: responses: default: - description: hello world + description: hello world diff --git a/test/specs/validate-schema/invalid/invalid-response-code.yaml b/test/specs/validate-schema/invalid/invalid-response-code.yaml index bd0ae633..59b311ce 100644 --- a/test/specs/validate-schema/invalid/invalid-response-code.yaml +++ b/test/specs/validate-schema/invalid/invalid-response-code.yaml @@ -1,11 +1,11 @@ -swagger: "2.0" +swagger: '2.0' info: - version: "1.0.0" + version: '1.0.0' title: Invalid API paths: /users: get: responses: - "foobar": # <----- Invalid response code - description: hello world + 'foobar': # <----- Invalid response code + description: hello world diff --git a/test/specs/validate-schema/invalid/invalid-response-header-type.yaml b/test/specs/validate-schema/invalid/invalid-response-header-type.yaml index 6de7ff0b..8ef057bb 100644 --- a/test/specs/validate-schema/invalid/invalid-response-header-type.yaml +++ b/test/specs/validate-schema/invalid/invalid-response-header-type.yaml @@ -1,16 +1,16 @@ -swagger: "2.0" +swagger: '2.0' info: - version: "1.0.0" + version: '1.0.0' title: Invalid API paths: /users: get: responses: - "default": - description: hello world + 'default': + description: hello world headers: Content-Type: type: string Last-Modified: - type: date # <--- Not a valid header type + type: date # <--- Not a valid header type diff --git a/test/specs/validate-schema/invalid/invalid-response-type.yaml b/test/specs/validate-schema/invalid/invalid-response-type.yaml index b3e81056..4b8eaebc 100644 --- a/test/specs/validate-schema/invalid/invalid-response-type.yaml +++ b/test/specs/validate-schema/invalid/invalid-response-type.yaml @@ -1,13 +1,13 @@ -swagger: "2.0" +swagger: '2.0' info: - version: "1.0.0" + version: '1.0.0' title: Invalid API paths: /users: get: responses: - "default": - description: hello world + 'default': + description: hello world schema: - type: user # <--- Invalid response type + type: user # <--- Invalid response type diff --git a/test/specs/validate-schema/invalid/invalid-schema-type.yaml b/test/specs/validate-schema/invalid/invalid-schema-type.yaml index 8e7bdb2d..4a9a635c 100644 --- a/test/specs/validate-schema/invalid/invalid-schema-type.yaml +++ b/test/specs/validate-schema/invalid/invalid-schema-type.yaml @@ -1,6 +1,6 @@ -swagger: "2.0" +swagger: '2.0' info: - version: "1.0.0" + version: '1.0.0' title: Invalid API paths: @@ -9,8 +9,8 @@ paths: - name: user in: body schema: - type: user # <---- "user" is not a valid JSON Schema type + type: user # <---- "user" is not a valid JSON Schema type post: responses: default: - description: hello world + description: hello world diff --git a/test/specs/validate-schema/invalid/invalid-security-scheme.yaml b/test/specs/validate-schema/invalid/invalid-security-scheme.yaml index eb732d0d..bf2578f5 100644 --- a/test/specs/validate-schema/invalid/invalid-security-scheme.yaml +++ b/test/specs/validate-schema/invalid/invalid-security-scheme.yaml @@ -1,6 +1,6 @@ -openapi: "3.0.0" +openapi: '3.0.0' info: - version: "1.0.0" + version: '1.0.0' title: Invalid API paths: @@ -8,11 +8,11 @@ paths: post: responses: 200: - description: "OK" + description: 'OK' security: - tlsAuth: [] components: securitySchemes: tlsAuth: - type: "mutualTLS" # <---- mutualTLS is only available on OpenAPI 3.1 + type: 'mutualTLS' # <---- mutualTLS is only available on OpenAPI 3.1 diff --git a/test/specs/validate-schema/invalid/multi-header-param.yaml b/test/specs/validate-schema/invalid/multi-header-param.yaml index da1d7bbe..fe5d27e0 100644 --- a/test/specs/validate-schema/invalid/multi-header-param.yaml +++ b/test/specs/validate-schema/invalid/multi-header-param.yaml @@ -1,6 +1,6 @@ -swagger: "2.0" +swagger: '2.0' info: - version: "1.0.0" + version: '1.0.0' title: Invalid API paths: @@ -11,8 +11,8 @@ paths: type: array items: type: string - collectionFormat: multi # <--- Not valid for header params + collectionFormat: multi # <--- Not valid for header params get: responses: default: - description: hello world + description: hello world diff --git a/test/specs/validate-schema/invalid/multi-path-param.yaml b/test/specs/validate-schema/invalid/multi-path-param.yaml index 25f5c811..6f3b31e9 100644 --- a/test/specs/validate-schema/invalid/multi-path-param.yaml +++ b/test/specs/validate-schema/invalid/multi-path-param.yaml @@ -1,6 +1,6 @@ -swagger: "2.0" +swagger: '2.0' info: - version: "1.0.0" + version: '1.0.0' title: Invalid API paths: @@ -12,8 +12,8 @@ paths: type: array items: type: string - collectionFormat: multi # <--- Not valid for header params + collectionFormat: multi # <--- Not valid for header params get: responses: default: - description: hello world + description: hello world diff --git a/test/specs/validate-schema/invalid/non-primitive-param-type.yaml b/test/specs/validate-schema/invalid/non-primitive-param-type.yaml index 97678a08..db9dc76e 100644 --- a/test/specs/validate-schema/invalid/non-primitive-param-type.yaml +++ b/test/specs/validate-schema/invalid/non-primitive-param-type.yaml @@ -1,6 +1,6 @@ -swagger: "2.0" +swagger: '2.0' info: - version: "1.0.0" + version: '1.0.0' title: Invalid API paths: @@ -8,8 +8,8 @@ paths: parameters: - name: user in: query - type: object # <---- only primitive types are allowed for params + type: object # <---- only primitive types are allowed for params post: responses: default: - description: hello world + description: hello world diff --git a/test/specs/validate-schema/invalid/non-primitive-response-header-type.yaml b/test/specs/validate-schema/invalid/non-primitive-response-header-type.yaml index bf3b8a47..e2c4235a 100644 --- a/test/specs/validate-schema/invalid/non-primitive-response-header-type.yaml +++ b/test/specs/validate-schema/invalid/non-primitive-response-header-type.yaml @@ -1,16 +1,16 @@ -swagger: "2.0" +swagger: '2.0' info: - version: "1.0.0" + version: '1.0.0' title: Invalid API paths: /users: get: responses: - "default": - description: hello world + 'default': + description: hello world headers: Content-Type: type: string Last-Modified: - type: object # <--- Not a valid header type + type: object # <--- Not a valid header type diff --git a/test/specs/validate-schema/invalid/non-required-path-param.yaml b/test/specs/validate-schema/invalid/non-required-path-param.yaml index 56a3d2f1..45731275 100644 --- a/test/specs/validate-schema/invalid/non-required-path-param.yaml +++ b/test/specs/validate-schema/invalid/non-required-path-param.yaml @@ -1,6 +1,6 @@ -swagger: "2.0" +swagger: '2.0' info: - version: "1.0.0" + version: '1.0.0' title: Invalid API paths: @@ -10,10 +10,10 @@ paths: in: path required: true type: string - - name: img_id # <--- Error! Missing "required: true" + - name: img_id # <--- Error! Missing "required: true" in: path type: number get: responses: default: - description: hello world + description: hello world diff --git a/test/specs/validate-schema/invalid/oneof.yaml b/test/specs/validate-schema/invalid/oneof.yaml index a4667d9a..acbe2322 100644 --- a/test/specs/validate-schema/invalid/oneof.yaml +++ b/test/specs/validate-schema/invalid/oneof.yaml @@ -1,6 +1,6 @@ -swagger: "2.0" +swagger: '2.0' info: - version: "1.0.0" + version: '1.0.0' title: Invalid API paths: @@ -8,9 +8,9 @@ paths: get: responses: default: - description: hello world + description: hello world schema: - oneOf: # <--- "oneOf" is not supported by Swagger 2.0. Only "allOf" is supported. + oneOf: # <--- "oneOf" is not supported by Swagger 2.0. Only "allOf" is supported. - properties: firstName: type: string diff --git a/test/specs/validate-schema/invalid/optional-path-param.yaml b/test/specs/validate-schema/invalid/optional-path-param.yaml index 0c7ed80c..760503f0 100644 --- a/test/specs/validate-schema/invalid/optional-path-param.yaml +++ b/test/specs/validate-schema/invalid/optional-path-param.yaml @@ -1,6 +1,6 @@ -swagger: "2.0" +swagger: '2.0' info: - version: "1.0.0" + version: '1.0.0' title: Invalid API paths: @@ -12,9 +12,9 @@ paths: type: string - name: img_id in: path - required: false # <--- Error! Path params *must* be required + required: false # <--- Error! Path params *must* be required type: number get: responses: default: - description: hello world + description: hello world diff --git a/test/specs/validate-schema/invalid/ref-to-invalid-path.yaml b/test/specs/validate-schema/invalid/ref-to-invalid-path.yaml index 335cd09f..e0e687b0 100644 --- a/test/specs/validate-schema/invalid/ref-to-invalid-path.yaml +++ b/test/specs/validate-schema/invalid/ref-to-invalid-path.yaml @@ -1,13 +1,13 @@ -swagger: "2.0" +swagger: '2.0' info: - version: "1.0.0" + version: '1.0.0' title: Invalid API paths: /users: - $ref: "#/definitions/users/default" + $ref: '#/definitions/users/default' /products: - $ref: "#/definitions/products" # <--- Points to the "products" MODEL, not a Path + $ref: '#/definitions/products' # <--- Points to the "products" MODEL, not a Path definitions: users: @@ -15,7 +15,7 @@ definitions: get: responses: default: - description: hello world + description: hello world products: type: object diff --git a/test/specs/validate-schema/valid/allof.yaml b/test/specs/validate-schema/valid/allof.yaml index ea0934de..eedd9bba 100644 --- a/test/specs/validate-schema/valid/allof.yaml +++ b/test/specs/validate-schema/valid/allof.yaml @@ -1,6 +1,6 @@ -swagger: "2.0" +swagger: '2.0' info: - version: "1.0.0" + version: '1.0.0' title: Invalid API paths: @@ -8,7 +8,7 @@ paths: get: responses: default: - description: hello world + description: hello world schema: allOf: - properties: diff --git a/test/specs/validate-schema/valid/unknown-format.yaml b/test/specs/validate-schema/valid/unknown-format.yaml index 125feefb..fc26e1c8 100644 --- a/test/specs/validate-schema/valid/unknown-format.yaml +++ b/test/specs/validate-schema/valid/unknown-format.yaml @@ -1,6 +1,6 @@ -swagger: "2.0" +swagger: '2.0' info: - version: "1.0.0" + version: '1.0.0' title: Invalid API paths: @@ -8,16 +8,16 @@ paths: get: responses: default: - description: hello world + description: hello world schema: type: object properties: foo: type: boolean - format: falsy # <--- Unknown boolean format + format: falsy # <--- Unknown boolean format bar: type: integer - format: abignumber # <--- Unknown integer format + format: abignumber # <--- Unknown integer format baz: type: string - format: customdateformat # <--- Unknown string format + format: customdateformat # <--- Unknown string format diff --git a/test/specs/validate-schema/validate-schema.spec.js b/test/specs/validate-schema/validate-schema.test.ts similarity index 52% rename from test/specs/validate-schema/validate-schema.spec.js rename to test/specs/validate-schema/validate-schema.test.ts index b3cf0c55..07d7d2d6 100644 --- a/test/specs/validate-schema/validate-schema.spec.js +++ b/test/specs/validate-schema/validate-schema.test.ts @@ -1,182 +1,160 @@ -const { expect } = require('chai'); +import { describe, it, expect, assert } from 'vitest'; -const OpenAPIParser = require('../../..'); -const path = require('../../utils/path'); +import OpenAPIParser from '../../..'; +import path from '../../utils/path'; describe('Invalid APIs (Swagger 2.0 and OpenAPI 3.x schema validation)', () => { - const tests = [ + it('should pass validation if "options.validate.schema" is false', async () => { + const api = await OpenAPIParser.validate(path.rel('specs/validate-schema/invalid/invalid-response-code.yaml'), { + validate: { schema: false }, + }); + expect(api).to.be.an('object'); + }); + + it('should return all errors', async () => { + try { + await OpenAPIParser.validate(path.rel('specs/validate-schema/invalid/multiple-invalid-properties.yaml')); + assert.fail('Validation should have failed, but it succeeded!'); + } catch (err) { + expect(err).to.be.an.instanceOf(SyntaxError); + expect(err.message).to.match(/^OpenAPI schema validation failed.\n(.*)+/); + + expect(err.details).to.be.an('array').to.have.length(3); + expect(err.totalErrors).to.equal(2); + + expect(err.message).to.contain("REQUIRED must have required property 'url'"); + expect(err.message).to.contain('url is missing here'); + expect(err.message).to.contain('ADDITIONAL PROPERTY must NOT have additional properties'); + expect(err.message).to.contain('tagss is not expected to be here'); + } + }); + + it.each([ + { + name: 'unknown JSON Schema format', + file: 'unknown-format.yaml', + }, + { + name: 'Schema with "allOf"', + file: 'allof.yaml', + }, + ])('$name', async ({ file }) => { + const api = await OpenAPIParser.validate(path.rel(`specs/validate-schema/valid/${file}`)); + expect(api).to.be.an('object'); + }); + + it.each([ { name: 'invalid response code', - valid: false, file: 'invalid-response-code.yaml', }, { name: 'optional path param', - valid: false, file: 'optional-path-param.yaml', }, { name: 'non-required path param', - valid: false, file: 'non-required-path-param.yaml', }, { name: 'invalid schema type', - valid: false, file: 'invalid-schema-type.yaml', }, { name: 'invalid param type', - valid: false, file: 'invalid-param-type.yaml', }, { name: 'non-primitive param type', - valid: false, file: 'non-primitive-param-type.yaml', }, { name: 'invalid parameter location', - valid: false, file: 'invalid-param-location.yaml', }, { name: '"file" type used for non-formData param', - valid: false, file: 'file-header-param.yaml', }, { name: '"file" type used for body param', - valid: false, file: 'file-body-param.yaml', - error: - 'Validation failed. /paths/users/{username}/profile/image/post/parameters/image has an invalid type (file)', }, { name: '"multi" header param', - valid: false, file: 'multi-header-param.yaml', }, { name: '"multi" path param', - valid: false, file: 'multi-path-param.yaml', }, { name: 'invalid response header type', - valid: false, file: 'invalid-response-header-type.yaml', }, { name: 'non-primitive response header type', - valid: false, file: 'non-primitive-response-header-type.yaml', }, { name: 'invalid response schema type', - valid: false, file: 'invalid-response-type.yaml', }, - { - name: 'unknown JSON Schema format', - valid: true, - file: 'unknown-format.yaml', - }, { name: '$ref to invalid Path object', - valid: false, file: 'ref-to-invalid-path.yaml', }, - { - name: 'Schema with "allOf"', - valid: true, - file: 'allof.yaml', - }, { name: 'Schema with "anyOf"', - valid: false, file: 'anyof.yaml', }, { name: 'Schema with "oneOf"', - valid: false, file: 'oneof.yaml', }, { name: 'invalid security scheme for OpenAPI 3.0', - valid: false, file: 'invalid-security-scheme.yaml', - openapi: true, + isOpenAPI: true, }, - ]; - - it('should pass validation if "options.validate.schema" is false', async () => { - const invalid = tests[0]; - expect(invalid.valid).to.equal(false); - - const api = await OpenAPIParser.validate(path.rel(`specs/validate-schema/invalid/${invalid.file}`), { - validate: { schema: false }, - }); - expect(api).to.be.an('object'); - }); - - it('should return all errors', async () => { + ])('$name', async ({ file, isOpenAPI }) => { try { - await OpenAPIParser.validate(path.rel('specs/validate-schema/invalid/multiple-invalid-properties.yaml')); - throw new Error('Validation should have failed, but it succeeded!'); + await OpenAPIParser.validate(path.rel(`specs/validate-schema/invalid/${file}`)); + assert.fail('Validation should have failed, but it succeeded!'); } catch (err) { expect(err).to.be.an.instanceOf(SyntaxError); - expect(err.message).to.match(/^OpenAPI schema validation failed.\n(.*)+/); + if (isOpenAPI) { + expect(err.message).to.match(/^OpenAPI schema validation failed.\n(.*)+/); + } else { + expect(err.message).to.match(/^Swagger schema validation failed.\n(.*)+/); + } - expect(err.details).to.be.an('array').to.have.length(3); - expect(err.totalErrors).to.equal(2); + expect(err.details).to.be.an('array').with.length.above(0); + expect(err.totalErrors).to.be.at.least(1); - expect(err.message).to.contain("REQUIRED must have required property 'url'"); - expect(err.message).to.contain('url is missing here'); - expect(err.message).to.contain('ADDITIONAL PROPERTY must NOT have additional properties'); - expect(err.message).to.contain('tagss is not expected to be here'); + // Make sure the Ajv error details object is valid + const details = err.details[0]; + expect(details.instancePath) + .to.be.a('string') + .and.match(/[a-zA-Z/~01]+/); // /paths/~1users/get/responses + expect(details.schemaPath) + .to.be.a('string') + .and.match(/^#\/[a-zA-Z\\/]+/); // #/properties/parameters/items/oneOf + expect(details.keyword).to.be.a('string').and.match(/\w+/); // oneOf + expect(details.params).to.be.a('object'); // { passingSchemas: null } + expect(details.message).to.be.a('string').with.length.of.at.least(1); // must match exactly one schema in oneOf } }); - for (const test of tests) { - if (test.valid) { - it(test.name, async () => { - try { - const api = await OpenAPIParser.validate(path.rel(`specs/validate-schema/valid/${test.file}`)); - expect(api).to.be.an('object'); - } catch (err) { - throw new Error(`Validation should have succeeded, but it failed!\n${err.stack}`); - } - }); - } else { - it(test.name, async () => { - try { - await OpenAPIParser.validate(path.rel(`specs/validate-schema/invalid/${test.file}`)); - throw new Error('Validation should have failed, but it succeeded!'); - } catch (err) { - expect(err).to.be.an.instanceOf(SyntaxError); - if (test.openapi) { - expect(err.message).to.match(/^OpenAPI schema validation failed.\n(.*)+/); - } else { - expect(err.message).to.match(/^Swagger schema validation failed.\n(.*)+/); - } + // for (const test of tests) { + // if (test.valid) { + // it(test.name, async () => { - expect(err.details).to.be.an('array').with.length.above(0); - expect(err.totalErrors).to.be.at.least(1); + // }); + // } else { + // it(test.name, async () => { - // Make sure the Ajv error details object is valid - const details = err.details[0]; - expect(details.instancePath) - .to.be.a('string') - .and.match(/[a-zA-Z/~01]+/); // /paths/~1users/get/responses - expect(details.schemaPath) - .to.be.a('string') - .and.match(/^#\/[a-zA-Z\\/]+/); // #/properties/parameters/items/oneOf - expect(details.keyword).to.be.a('string').and.match(/\w+/); // oneOf - expect(details.params).to.be.a('object'); // { passingSchemas: null } - expect(details.message).to.be.a('string').with.length.of.at.least(1); // must match exactly one schema in oneOf - } - }); - } - } + // }); + // } + // } }); diff --git a/test/specs/validate-spec/invalid/2.0/array-body-no-items.yaml b/test/specs/validate-spec/invalid/2.0/array-body-no-items.yaml index beb48108..e17b9065 100644 --- a/test/specs/validate-spec/invalid/2.0/array-body-no-items.yaml +++ b/test/specs/validate-spec/invalid/2.0/array-body-no-items.yaml @@ -1,6 +1,6 @@ -swagger: "2.0" +swagger: '2.0' info: - version: "1.0.0" + version: '1.0.0' title: Invalid API paths: @@ -13,4 +13,4 @@ paths: post: responses: default: - description: hello world + description: hello world diff --git a/test/specs/validate-spec/invalid/2.0/array-no-items.yaml b/test/specs/validate-spec/invalid/2.0/array-no-items.yaml index 5c976e2b..a36735ac 100644 --- a/test/specs/validate-spec/invalid/2.0/array-no-items.yaml +++ b/test/specs/validate-spec/invalid/2.0/array-no-items.yaml @@ -1,6 +1,6 @@ -swagger: "2.0" +swagger: '2.0' info: - version: "1.0.0" + version: '1.0.0' title: Invalid API paths: @@ -12,4 +12,4 @@ paths: get: responses: default: - description: hello world + description: hello world diff --git a/test/specs/validate-spec/invalid/2.0/array-response-body-no-items.yaml b/test/specs/validate-spec/invalid/2.0/array-response-body-no-items.yaml index d153e6fd..6762cf6f 100644 --- a/test/specs/validate-spec/invalid/2.0/array-response-body-no-items.yaml +++ b/test/specs/validate-spec/invalid/2.0/array-response-body-no-items.yaml @@ -1,6 +1,6 @@ -swagger: "2.0" +swagger: '2.0' info: - version: "1.0.0" + version: '1.0.0' title: Invalid API paths: @@ -8,6 +8,6 @@ paths: get: responses: 200: - description: hello world + description: hello world schema: type: array diff --git a/test/specs/validate-spec/invalid/2.0/array-response-header-no-items.yaml b/test/specs/validate-spec/invalid/2.0/array-response-header-no-items.yaml index 182e3498..f00de20b 100644 --- a/test/specs/validate-spec/invalid/2.0/array-response-header-no-items.yaml +++ b/test/specs/validate-spec/invalid/2.0/array-response-header-no-items.yaml @@ -1,14 +1,14 @@ -swagger: "2.0" +swagger: '2.0' info: - version: "1.0.0" + version: '1.0.0' title: Invalid API paths: /users: get: responses: - "default": - description: hello world + 'default': + description: hello world headers: Content-Type: type: string diff --git a/test/specs/validate-spec/invalid/2.0/body-and-form-params.yaml b/test/specs/validate-spec/invalid/2.0/body-and-form-params.yaml index fcc7bc38..1b611634 100644 --- a/test/specs/validate-spec/invalid/2.0/body-and-form-params.yaml +++ b/test/specs/validate-spec/invalid/2.0/body-and-form-params.yaml @@ -1,6 +1,6 @@ -swagger: "2.0" +swagger: '2.0' info: - version: "1.0.0" + version: '1.0.0' title: Invalid API paths: @@ -11,7 +11,7 @@ paths: required: true type: string - name: username - in: body # <---- Body param + in: body # <---- Body param schema: type: string get: @@ -20,13 +20,13 @@ paths: in: path required: true type: string - - name: username # <---- Not an error. This just overrides the path-level param + - name: username # <---- Not an error. This just overrides the path-level param in: body schema: type: number responses: default: - description: hello world + description: hello world post: parameters: - name: username @@ -38,8 +38,8 @@ paths: type: number required: true - name: bar - in: formData # <---- formData param + in: formData # <---- formData param type: number responses: default: - description: hello world + description: hello world diff --git a/test/specs/validate-spec/invalid/2.0/definition-schema-with-invalid-characters.yaml b/test/specs/validate-spec/invalid/2.0/definition-schema-with-invalid-characters.yaml index 24481ebd..b2a21f84 100644 --- a/test/specs/validate-spec/invalid/2.0/definition-schema-with-invalid-characters.yaml +++ b/test/specs/validate-spec/invalid/2.0/definition-schema-with-invalid-characters.yaml @@ -1,6 +1,6 @@ -swagger: "2.0" +swagger: '2.0' info: - version: "1.0" + version: '1.0' title: Invalid API paths: /anything: @@ -9,9 +9,9 @@ paths: '200': description: OK schema: - "$ref": "#/definitions/User«Information»" + '$ref': '#/definitions/User«Information»' definitions: - User«Information»: # <---- component names should match ^[a-zA-Z0-9\.\-_]+$ + User«Information»: # <---- component names should match ^[a-zA-Z0-9\.\-_]+$ type: object properties: first: diff --git a/test/specs/validate-spec/invalid/2.0/duplicate-header-params.yaml b/test/specs/validate-spec/invalid/2.0/duplicate-header-params.yaml index bf667feb..99b76743 100644 --- a/test/specs/validate-spec/invalid/2.0/duplicate-header-params.yaml +++ b/test/specs/validate-spec/invalid/2.0/duplicate-header-params.yaml @@ -1,6 +1,6 @@ -swagger: "2.0" +swagger: '2.0' info: - version: "1.0.0" + version: '1.0.0' title: Invalid API paths: @@ -10,7 +10,7 @@ paths: in: path required: true type: string - - name: foo # <---- Duplicate param + - name: foo # <---- Duplicate param in: header type: string required: false @@ -21,11 +21,11 @@ paths: in: body schema: type: string - - name: foo # <---- Duplicate param + - name: foo # <---- Duplicate param in: header type: number required: true get: responses: default: - description: hello world + description: hello world diff --git a/test/specs/validate-spec/invalid/2.0/duplicate-operation-ids.yaml b/test/specs/validate-spec/invalid/2.0/duplicate-operation-ids.yaml index c2a51e9f..03b9d1e9 100644 --- a/test/specs/validate-spec/invalid/2.0/duplicate-operation-ids.yaml +++ b/test/specs/validate-spec/invalid/2.0/duplicate-operation-ids.yaml @@ -1,6 +1,6 @@ -swagger: "2.0" +swagger: '2.0' info: - version: "1.0.0" + version: '1.0.0' title: Invalid API paths: @@ -9,9 +9,9 @@ paths: operationId: users responses: default: - description: hello world + description: hello world post: - operationId: users # <---- duplicate + operationId: users # <---- duplicate responses: default: - description: hello world + description: hello world diff --git a/test/specs/validate-spec/invalid/2.0/duplicate-operation-params.yaml b/test/specs/validate-spec/invalid/2.0/duplicate-operation-params.yaml index e823af83..250ce73a 100644 --- a/test/specs/validate-spec/invalid/2.0/duplicate-operation-params.yaml +++ b/test/specs/validate-spec/invalid/2.0/duplicate-operation-params.yaml @@ -1,13 +1,13 @@ -swagger: "2.0" +swagger: '2.0' info: - version: "1.0.0" + version: '1.0.0' title: Invalid API paths: /users/{username}: get: parameters: - - name: username # <---- Duplicate param + - name: username # <---- Duplicate param in: path required: true type: string @@ -22,10 +22,10 @@ paths: in: body schema: type: string - - name: username # <---- Duplicate param + - name: username # <---- Duplicate param in: path type: number required: true responses: default: - description: hello world + description: hello world diff --git a/test/specs/validate-spec/invalid/2.0/duplicate-path-placeholders.yaml b/test/specs/validate-spec/invalid/2.0/duplicate-path-placeholders.yaml index 925b6887..ea2707be 100644 --- a/test/specs/validate-spec/invalid/2.0/duplicate-path-placeholders.yaml +++ b/test/specs/validate-spec/invalid/2.0/duplicate-path-placeholders.yaml @@ -1,10 +1,10 @@ -swagger: "2.0" +swagger: '2.0' info: - version: "1.0.0" + version: '1.0.0' title: Invalid API paths: - /users/{username}/profile/{username}/image/{img_id}: # <---- duplicate {username} placeholders + /users/{username}/profile/{username}/image/{img_id}: # <---- duplicate {username} placeholders parameters: - name: username in: path @@ -17,4 +17,4 @@ paths: get: responses: default: - description: hello world + description: hello world diff --git a/test/specs/validate-spec/invalid/2.0/file-invalid-consumes.yaml b/test/specs/validate-spec/invalid/2.0/file-invalid-consumes.yaml index 9292ec01..7f98a04c 100644 --- a/test/specs/validate-spec/invalid/2.0/file-invalid-consumes.yaml +++ b/test/specs/validate-spec/invalid/2.0/file-invalid-consumes.yaml @@ -1,11 +1,11 @@ -swagger: "2.0" +swagger: '2.0' info: - version: "1.0.0" + version: '1.0.0' title: Invalid API consumes: - - multipart/form-data # <--- The API allows "file" params - - application/x-www-form-urlencoded # <--- The API allows "file" params + - multipart/form-data # <--- The API allows "file" params + - application/x-www-form-urlencoded # <--- The API allows "file" params paths: /users/{username}/profile/image: @@ -16,11 +16,11 @@ paths: required: true - name: image in: formData - type: file # <--- "file" params REQUIRE multipart/form-data or application/x-www-form-urlencoded + type: file # <--- "file" params REQUIRE multipart/form-data or application/x-www-form-urlencoded post: - consumes: # <--- This operation's "consumes" OVERRIDES the API's "consumes" + consumes: # <--- This operation's "consumes" OVERRIDES the API's "consumes" - application/octet-stream - image/png responses: default: - description: hello world + description: hello world diff --git a/test/specs/validate-spec/invalid/2.0/file-no-consumes.yaml b/test/specs/validate-spec/invalid/2.0/file-no-consumes.yaml index 833e8bdd..ed57cc54 100644 --- a/test/specs/validate-spec/invalid/2.0/file-no-consumes.yaml +++ b/test/specs/validate-spec/invalid/2.0/file-no-consumes.yaml @@ -1,6 +1,6 @@ -swagger: "2.0" +swagger: '2.0' info: - version: "1.0.0" + version: '1.0.0' title: Invalid API paths: @@ -12,8 +12,8 @@ paths: required: true - name: image in: formData - type: file # <--- "file" type requires "consumes" to be specified + type: file # <--- "file" type requires "consumes" to be specified post: responses: default: - description: hello world + description: hello world diff --git a/test/specs/validate-spec/invalid/2.0/invalid-response-code.yaml b/test/specs/validate-spec/invalid/2.0/invalid-response-code.yaml index 75548530..4f4ec110 100644 --- a/test/specs/validate-spec/invalid/2.0/invalid-response-code.yaml +++ b/test/specs/validate-spec/invalid/2.0/invalid-response-code.yaml @@ -1,11 +1,11 @@ -swagger: "2.0" +swagger: '2.0' info: - version: "1.0.0" + version: '1.0.0' title: Invalid API paths: /users: get: responses: - "888": # <----- Invalid HTTP response code - description: hello world + '888': # <----- Invalid HTTP response code + description: hello world diff --git a/test/specs/validate-spec/invalid/2.0/multiple-body-params.yaml b/test/specs/validate-spec/invalid/2.0/multiple-body-params.yaml index b46c0771..ba230224 100644 --- a/test/specs/validate-spec/invalid/2.0/multiple-body-params.yaml +++ b/test/specs/validate-spec/invalid/2.0/multiple-body-params.yaml @@ -1,6 +1,6 @@ -swagger: "2.0" +swagger: '2.0' info: - version: "1.0.0" + version: '1.0.0' title: Invalid API paths: @@ -11,7 +11,7 @@ paths: required: true type: string - name: username - in: body # <---- Body param #1 + in: body # <---- Body param #1 schema: type: string get: @@ -24,13 +24,13 @@ paths: in: header type: number required: true - - name: username # <---- Not an error. This just overrides the path-level param + - name: username # <---- Not an error. This just overrides the path-level param in: body schema: type: number responses: default: - description: hello world + description: hello world post: parameters: - name: username @@ -42,9 +42,9 @@ paths: type: number required: true - name: bar - in: body # <---- Body param #2 + in: body # <---- Body param #2 schema: type: number responses: default: - description: hello world + description: hello world diff --git a/test/specs/validate-spec/invalid/2.0/multiple-operation-body-params.yaml b/test/specs/validate-spec/invalid/2.0/multiple-operation-body-params.yaml index 37e1f270..a4a61865 100644 --- a/test/specs/validate-spec/invalid/2.0/multiple-operation-body-params.yaml +++ b/test/specs/validate-spec/invalid/2.0/multiple-operation-body-params.yaml @@ -1,6 +1,6 @@ -swagger: "2.0" +swagger: '2.0' info: - version: "1.0.0" + version: '1.0.0' title: Invalid API paths: @@ -12,7 +12,7 @@ paths: required: true type: string - name: username - in: body # <---- Body param #1 + in: body # <---- Body param #1 schema: type: string - name: bar @@ -20,9 +20,9 @@ paths: type: number required: true - name: bar - in: body # <---- Body param #2 + in: body # <---- Body param #2 schema: type: number responses: default: - description: hello world + description: hello world diff --git a/test/specs/validate-spec/invalid/2.0/multiple-path-body-params.yaml b/test/specs/validate-spec/invalid/2.0/multiple-path-body-params.yaml index e111c30f..d844c969 100644 --- a/test/specs/validate-spec/invalid/2.0/multiple-path-body-params.yaml +++ b/test/specs/validate-spec/invalid/2.0/multiple-path-body-params.yaml @@ -1,6 +1,6 @@ -swagger: "2.0" +swagger: '2.0' info: - version: "1.0.0" + version: '1.0.0' title: Invalid API paths: @@ -11,7 +11,7 @@ paths: required: true type: string - name: username - in: body # <---- Body param #1 + in: body # <---- Body param #1 schema: type: string - name: bar @@ -19,10 +19,10 @@ paths: type: number required: true - name: bar - in: body # <---- Body param #2 + in: body # <---- Body param #2 schema: type: number get: responses: default: - description: hello world + description: hello world diff --git a/test/specs/validate-spec/invalid/2.0/no-path-params.yaml b/test/specs/validate-spec/invalid/2.0/no-path-params.yaml index 592bbd64..8cfa2286 100644 --- a/test/specs/validate-spec/invalid/2.0/no-path-params.yaml +++ b/test/specs/validate-spec/invalid/2.0/no-path-params.yaml @@ -1,11 +1,11 @@ -swagger: "2.0" +swagger: '2.0' info: - version: "1.0.0" + version: '1.0.0' title: Invalid API paths: - /users/{username}/{foo}: # <---- {username} and {foo} placeholders - parameters: # <---- no path params + /users/{username}/{foo}: # <---- {username} and {foo} placeholders + parameters: # <---- no path params - name: username in: header required: true @@ -15,7 +15,7 @@ paths: schema: type: string get: - parameters: # <---- no path params + parameters: # <---- no path params - name: username in: header required: true @@ -26,13 +26,13 @@ paths: type: number responses: default: - description: hello world + description: hello world post: - parameters: # <---- no path params + parameters: # <---- no path params - name: username in: header required: true type: string responses: default: - description: hello world + description: hello world diff --git a/test/specs/validate-spec/invalid/2.0/path-param-no-placeholder.yaml b/test/specs/validate-spec/invalid/2.0/path-param-no-placeholder.yaml index 084b24af..a975c012 100644 --- a/test/specs/validate-spec/invalid/2.0/path-param-no-placeholder.yaml +++ b/test/specs/validate-spec/invalid/2.0/path-param-no-placeholder.yaml @@ -1,10 +1,10 @@ -swagger: "2.0" +swagger: '2.0' info: - version: "1.0.0" + version: '1.0.0' title: Invalid API paths: - /users/{username}: # <---- {username} placeholder + /users/{username}: # <---- {username} placeholder parameters: - name: username in: path @@ -26,17 +26,17 @@ paths: type: number responses: default: - description: hello world + description: hello world post: parameters: - name: username in: path required: true type: string - - name: foo # <---- There is no {foo} placeholder + - name: foo # <---- There is no {foo} placeholder in: path required: true type: number responses: default: - description: hello world + description: hello world diff --git a/test/specs/validate-spec/invalid/2.0/path-placeholder-no-param.yaml b/test/specs/validate-spec/invalid/2.0/path-placeholder-no-param.yaml index 46b8aaba..2b27636f 100644 --- a/test/specs/validate-spec/invalid/2.0/path-placeholder-no-param.yaml +++ b/test/specs/validate-spec/invalid/2.0/path-placeholder-no-param.yaml @@ -1,12 +1,12 @@ -swagger: "2.0" +swagger: '2.0' info: - version: "1.0.0" + version: '1.0.0' title: Invalid API paths: - /users/{username}/{foo}: # <---- {username} and {foo} placeholders + /users/{username}/{foo}: # <---- {username} and {foo} placeholders parameters: - - name: username # <---- "username" path param + - name: username # <---- "username" path param in: path required: true type: string @@ -15,7 +15,7 @@ paths: schema: type: string get: - parameters: # <---- there's no "foo" path param + parameters: # <---- there's no "foo" path param - name: username in: path required: true @@ -26,13 +26,13 @@ paths: type: number responses: default: - description: hello world + description: hello world post: - parameters: # <---- there's no "foo" path param + parameters: # <---- there's no "foo" path param - name: username in: path required: true type: string responses: default: - description: hello world + description: hello world diff --git a/test/specs/validate-spec/invalid/2.0/required-property-not-defined-definitions.yaml b/test/specs/validate-spec/invalid/2.0/required-property-not-defined-definitions.yaml index 150406c6..9d1aefa3 100644 --- a/test/specs/validate-spec/invalid/2.0/required-property-not-defined-definitions.yaml +++ b/test/specs/validate-spec/invalid/2.0/required-property-not-defined-definitions.yaml @@ -4,26 +4,26 @@ info: title: Swagger Petstore paths: '/pet/{petId}': - get: - summary: Find pet by ID - parameters: - - name: petId - in: path - description: ID of pet to return - required: true - type: integer - format: int64 - responses: - '200': - description: successful operation - schema: - $ref: '#/definitions/Pet' + get: + summary: Find pet by ID + parameters: + - name: petId + in: path + description: ID of pet to return + required: true + type: integer + format: int64 + responses: + '200': + description: successful operation + schema: + $ref: '#/definitions/Pet' definitions: Pet: type: object required: - name - - photoUrls # <--- does not exist + - photoUrls # <--- does not exist properties: name: type: string diff --git a/test/specs/validate-spec/invalid/2.0/required-property-not-defined-input.yaml b/test/specs/validate-spec/invalid/2.0/required-property-not-defined-input.yaml index fc8145d4..d99f69ae 100644 --- a/test/specs/validate-spec/invalid/2.0/required-property-not-defined-input.yaml +++ b/test/specs/validate-spec/invalid/2.0/required-property-not-defined-input.yaml @@ -14,7 +14,7 @@ paths: schema: type: object required: - - notExists # <--- does not exist + - notExists # <--- does not exist properties: name: type: string diff --git a/test/specs/validate-spec/invalid/3.0/component-schema-with-invalid-characters.yaml b/test/specs/validate-spec/invalid/3.0/component-schema-with-invalid-characters.yaml index 754adeae..81bfff3e 100644 --- a/test/specs/validate-spec/invalid/3.0/component-schema-with-invalid-characters.yaml +++ b/test/specs/validate-spec/invalid/3.0/component-schema-with-invalid-characters.yaml @@ -1,6 +1,6 @@ openapi: 3.0.3 info: - version: "1.0" + version: '1.0' title: Invalid API paths: /anything: @@ -13,10 +13,10 @@ paths: schema: type: array items: - "$ref": "#/components/schemas/User«Information»" + '$ref': '#/components/schemas/User«Information»' components: schemas: - User«Information»: # <---- component names should match ^[a-zA-Z0-9\.\-_]+$ + User«Information»: # <---- component names should match ^[a-zA-Z0-9\.\-_]+$ type: object properties: first: diff --git a/test/specs/validate-spec/invalid/3.0/component-schema-with-space.yaml b/test/specs/validate-spec/invalid/3.0/component-schema-with-space.yaml index 5ca4ebb5..248c480e 100644 --- a/test/specs/validate-spec/invalid/3.0/component-schema-with-space.yaml +++ b/test/specs/validate-spec/invalid/3.0/component-schema-with-space.yaml @@ -1,9 +1,9 @@ openapi: 3.0.3 info: - version: "1.0.0" + version: '1.0.0' title: Invalid API security: - - "Basic Access Authentication": ["read", "write"] + - 'Basic Access Authentication': ['read', 'write'] paths: /: post: @@ -12,9 +12,9 @@ paths: description: OK components: securitySchemes: - "Basic Access Authentication": # <---- component names shouldn't have a space in them + 'Basic Access Authentication': # <---- component names shouldn't have a space in them type: apiKey name: API-TOKEN in: header - scheme: api token # <---- `scheme` or `bearerFormat` be here but this spec should fail on the component name + scheme: api token # <---- `scheme` or `bearerFormat` be here but this spec should fail on the component name bearerFormat: JWT diff --git a/test/specs/validate-spec/invalid/3.0/invalid-discriminator.yaml b/test/specs/validate-spec/invalid/3.0/invalid-discriminator.yaml index 96f276f3..b9a26c5b 100644 --- a/test/specs/validate-spec/invalid/3.0/invalid-discriminator.yaml +++ b/test/specs/validate-spec/invalid/3.0/invalid-discriminator.yaml @@ -5,26 +5,26 @@ info: servers: - url: https://httpbin.org paths: - "/anything": + '/anything': post: requestBody: required: true content: application/json: schema: - "$ref": "#/components/schemas/TokenCreateRequest" + '$ref': '#/components/schemas/TokenCreateRequest' responses: '200': description: OK content: - "*/*": + '*/*': schema: - "$ref": "#/components/schemas/Token" + '$ref': '#/components/schemas/Token' components: schemas: TokenCreateRequest: type: object - discriminator: '' # <---- discriminators should always only be an object + discriminator: '' # <---- discriminators should always only be an object properties: appKey: type: string @@ -32,7 +32,7 @@ components: type: string Token: type: object - discriminator: '' # <---- discriminators should always only be an object + discriminator: '' # <---- discriminators should always only be an object properties: accessToken: type: string diff --git a/test/specs/validate-spec/invalid/3.1/component-schema-with-invalid-characters.yaml b/test/specs/validate-spec/invalid/3.1/component-schema-with-invalid-characters.yaml index 39e15d51..6c81beb1 100644 --- a/test/specs/validate-spec/invalid/3.1/component-schema-with-invalid-characters.yaml +++ b/test/specs/validate-spec/invalid/3.1/component-schema-with-invalid-characters.yaml @@ -1,6 +1,6 @@ openapi: 3.1.0 info: - version: "1.0" + version: '1.0' title: Invalid API paths: /anything: @@ -13,10 +13,10 @@ paths: schema: type: array items: - "$ref": "#/components/schemas/User«Information»" + '$ref': '#/components/schemas/User«Information»' components: schemas: - User«Information»: # <---- component names should match ^[a-zA-Z0-9\.\-_]+$ + User«Information»: # <---- component names should match ^[a-zA-Z0-9\.\-_]+$ type: object properties: first: diff --git a/test/specs/validate-spec/invalid/3.1/component-schema-with-space.yaml b/test/specs/validate-spec/invalid/3.1/component-schema-with-space.yaml index e76d9906..072491a2 100644 --- a/test/specs/validate-spec/invalid/3.1/component-schema-with-space.yaml +++ b/test/specs/validate-spec/invalid/3.1/component-schema-with-space.yaml @@ -1,9 +1,9 @@ openapi: 3.1.0 info: - version: "1.0.0" + version: '1.0.0' title: Invalid API security: - - "Basic Access Authentication": ["read", "write"] + - 'Basic Access Authentication': ['read', 'write'] paths: /: post: @@ -12,7 +12,7 @@ paths: description: OK components: securitySchemes: - "Basic Access Authentication": # <---- component names shouldn't have a space in them + 'Basic Access Authentication': # <---- component names shouldn't have a space in them type: apiKey name: API-TOKEN in: header diff --git a/test/specs/validate-spec/invalid/3.1/invalid-discriminator.yaml b/test/specs/validate-spec/invalid/3.1/invalid-discriminator.yaml index 26e13b56..a3b5c5f7 100644 --- a/test/specs/validate-spec/invalid/3.1/invalid-discriminator.yaml +++ b/test/specs/validate-spec/invalid/3.1/invalid-discriminator.yaml @@ -5,26 +5,26 @@ info: servers: - url: https://httpbin.org paths: - "/anything": + '/anything': post: requestBody: required: true content: application/json: schema: - "$ref": "#/components/schemas/TokenCreateRequest" + '$ref': '#/components/schemas/TokenCreateRequest' responses: '200': description: OK content: - "*/*": + '*/*': schema: - "$ref": "#/components/schemas/Token" + '$ref': '#/components/schemas/Token' components: schemas: TokenCreateRequest: type: object - discriminator: '' # <---- discriminators should always only be an object + discriminator: '' # <---- discriminators should always only be an object properties: appKey: type: string @@ -32,7 +32,7 @@ components: type: string Token: type: object - discriminator: '' # <---- discriminators should always only be an object + discriminator: '' # <---- discriminators should always only be an object properties: accessToken: type: string diff --git a/test/specs/validate-spec/invalid/3.x/array-no-items.yaml b/test/specs/validate-spec/invalid/3.x/array-no-items.yaml index a02625c6..4b17a25c 100644 --- a/test/specs/validate-spec/invalid/3.x/array-no-items.yaml +++ b/test/specs/validate-spec/invalid/3.x/array-no-items.yaml @@ -1,6 +1,6 @@ openapi: 3.0.0 info: - version: "1.0.0" + version: '1.0.0' title: Invalid API paths: diff --git a/test/specs/validate-spec/invalid/3.x/array-response-body-no-items.yaml b/test/specs/validate-spec/invalid/3.x/array-response-body-no-items.yaml index 66af6f70..2577517b 100644 --- a/test/specs/validate-spec/invalid/3.x/array-response-body-no-items.yaml +++ b/test/specs/validate-spec/invalid/3.x/array-response-body-no-items.yaml @@ -1,6 +1,6 @@ openapi: 3.0.0 info: - version: "1.0.0" + version: '1.0.0' title: Invalid API paths: diff --git a/test/specs/validate-spec/invalid/3.x/array-response-header-content-no-items.yaml b/test/specs/validate-spec/invalid/3.x/array-response-header-content-no-items.yaml index 2f9b48f3..5cf6a847 100644 --- a/test/specs/validate-spec/invalid/3.x/array-response-header-content-no-items.yaml +++ b/test/specs/validate-spec/invalid/3.x/array-response-header-content-no-items.yaml @@ -1,13 +1,13 @@ openapi: 3.0.0 info: - version: "1.0.0" + version: '1.0.0' title: Invalid API paths: /users: get: responses: - "default": + 'default': description: hello world headers: Content-Type: diff --git a/test/specs/validate-spec/invalid/3.x/array-response-header-no-items.yaml b/test/specs/validate-spec/invalid/3.x/array-response-header-no-items.yaml index f40c7227..2386ff82 100644 --- a/test/specs/validate-spec/invalid/3.x/array-response-header-no-items.yaml +++ b/test/specs/validate-spec/invalid/3.x/array-response-header-no-items.yaml @@ -1,13 +1,13 @@ openapi: 3.0.0 info: - version: "1.0.0" + version: '1.0.0' title: Invalid API paths: /users: get: responses: - "default": + 'default': description: hello world headers: Content-Type: diff --git a/test/specs/validate-spec/invalid/3.x/duplicate-header-params.yaml b/test/specs/validate-spec/invalid/3.x/duplicate-header-params.yaml index a84907e6..20847be4 100644 --- a/test/specs/validate-spec/invalid/3.x/duplicate-header-params.yaml +++ b/test/specs/validate-spec/invalid/3.x/duplicate-header-params.yaml @@ -1,6 +1,6 @@ openapi: 3.0.0 info: - version: "1.0.0" + version: '1.0.0' title: Invalid API paths: @@ -11,7 +11,7 @@ paths: required: true schema: type: string - - name: foo # <---- Duplicate param + - name: foo # <---- Duplicate param in: header required: false schema: @@ -20,7 +20,7 @@ paths: in: header schema: type: string - - name: foo # <---- Duplicate param + - name: foo # <---- Duplicate param in: header required: true schema: diff --git a/test/specs/validate-spec/invalid/3.x/duplicate-operation-ids.yaml b/test/specs/validate-spec/invalid/3.x/duplicate-operation-ids.yaml index 6807b694..b98fc10f 100644 --- a/test/specs/validate-spec/invalid/3.x/duplicate-operation-ids.yaml +++ b/test/specs/validate-spec/invalid/3.x/duplicate-operation-ids.yaml @@ -1,6 +1,6 @@ openapi: 3.0.0 info: - version: "1.0.0" + version: '1.0.0' title: Invalid API paths: @@ -11,7 +11,7 @@ paths: default: description: hello world post: - operationId: users # <---- duplicate + operationId: users # <---- duplicate responses: default: description: hello world diff --git a/test/specs/validate-spec/invalid/3.x/duplicate-operation-params.yaml b/test/specs/validate-spec/invalid/3.x/duplicate-operation-params.yaml index 89d76573..ae10c107 100644 --- a/test/specs/validate-spec/invalid/3.x/duplicate-operation-params.yaml +++ b/test/specs/validate-spec/invalid/3.x/duplicate-operation-params.yaml @@ -1,13 +1,13 @@ openapi: 3.0.0 info: - version: "1.0.0" + version: '1.0.0' title: Invalid API paths: /users/{username}: get: parameters: - - name: username # <---- Duplicate param + - name: username # <---- Duplicate param in: path required: true schema: @@ -21,7 +21,7 @@ paths: in: header schema: type: string - - name: username # <---- Duplicate param + - name: username # <---- Duplicate param in: path required: true schema: diff --git a/test/specs/validate-spec/invalid/3.x/no-path-params.yaml b/test/specs/validate-spec/invalid/3.x/no-path-params.yaml index 7ea2e979..5f6986c7 100644 --- a/test/specs/validate-spec/invalid/3.x/no-path-params.yaml +++ b/test/specs/validate-spec/invalid/3.x/no-path-params.yaml @@ -1,18 +1,18 @@ openapi: 3.0.0 info: - version: "1.0.0" + version: '1.0.0' title: Invalid API paths: - /users/{username}/{foo}: # <---- {username} and {foo} placeholders - parameters: # <---- no path params + /users/{username}/{foo}: # <---- {username} and {foo} placeholders + parameters: # <---- no path params - name: username in: header required: true schema: type: string get: - parameters: # <---- no path params + parameters: # <---- no path params - name: username in: header required: true @@ -22,7 +22,7 @@ paths: default: description: hello world post: - parameters: # <---- no path params + parameters: # <---- no path params - name: username in: header required: true diff --git a/test/specs/validate-spec/invalid/3.x/path-param-no-placeholder.yaml b/test/specs/validate-spec/invalid/3.x/path-param-no-placeholder.yaml index 87690bf2..033445b7 100644 --- a/test/specs/validate-spec/invalid/3.x/path-param-no-placeholder.yaml +++ b/test/specs/validate-spec/invalid/3.x/path-param-no-placeholder.yaml @@ -1,10 +1,10 @@ openapi: 3.0.0 info: - version: "1.0.0" + version: '1.0.0' title: Invalid API paths: - /users/{username}: # <---- {username} placeholder + /users/{username}: # <---- {username} placeholder parameters: - name: username in: path @@ -28,7 +28,7 @@ paths: required: true schema: type: string - - name: foo # <---- There is no {foo} placeholder + - name: foo # <---- There is no {foo} placeholder in: path required: true schema: diff --git a/test/specs/validate-spec/invalid/3.x/path-placeholder-no-param.yaml b/test/specs/validate-spec/invalid/3.x/path-placeholder-no-param.yaml index 33a890b1..6cba9693 100644 --- a/test/specs/validate-spec/invalid/3.x/path-placeholder-no-param.yaml +++ b/test/specs/validate-spec/invalid/3.x/path-placeholder-no-param.yaml @@ -1,18 +1,18 @@ openapi: 3.0.0 info: - version: "1.0.0" + version: '1.0.0' title: Invalid API paths: - /users/{username}/{foo}: # <---- {username} and {foo} placeholders + /users/{username}/{foo}: # <---- {username} and {foo} placeholders parameters: - - name: username # <---- "username" path param + - name: username # <---- "username" path param in: path required: true schema: type: string get: - parameters: # <---- there's no "foo" path param + parameters: # <---- there's no "foo" path param - name: username in: path required: true @@ -22,7 +22,7 @@ paths: default: description: hello world post: - parameters: # <---- there's no "foo" path param + parameters: # <---- there's no "foo" path param - name: username in: path required: true diff --git a/test/specs/validate-spec/invalid/3.x/required-property-not-defined-components.yaml b/test/specs/validate-spec/invalid/3.x/required-property-not-defined-components.yaml index 6f2058ac..835dccfe 100644 --- a/test/specs/validate-spec/invalid/3.x/required-property-not-defined-components.yaml +++ b/test/specs/validate-spec/invalid/3.x/required-property-not-defined-components.yaml @@ -4,30 +4,30 @@ info: title: Swagger Petstore paths: '/pet/{petId}': - get: - summary: Find pet by ID - parameters: - - name: petId - in: path - description: ID of pet to return - required: true - schema: - type: integer - format: int64 - responses: - '200': - description: successful operation - content: - application/json: - schema: - $ref: '#/components/schemas/Pet' + get: + summary: Find pet by ID + parameters: + - name: petId + in: path + description: ID of pet to return + required: true + schema: + type: integer + format: int64 + responses: + '200': + description: successful operation + content: + application/json: + schema: + $ref: '#/components/schemas/Pet' components: schemas: Pet: type: object required: - name - - photoUrls # <--- does not exist + - photoUrls # <--- does not exist properties: name: type: string diff --git a/test/specs/validate-spec/invalid/3.x/required-property-not-defined-input.yaml b/test/specs/validate-spec/invalid/3.x/required-property-not-defined-input.yaml index 953cb026..b1517cc8 100644 --- a/test/specs/validate-spec/invalid/3.x/required-property-not-defined-input.yaml +++ b/test/specs/validate-spec/invalid/3.x/required-property-not-defined-input.yaml @@ -17,7 +17,7 @@ paths: description: Pet to add to the store type: object required: - - notExists # <--- does not exist + - notExists # <--- does not exist properties: name: type: string diff --git a/test/specs/validate-spec/valid/2.0/definition-name-with-hyphens.yaml b/test/specs/validate-spec/valid/2.0/definition-name-with-hyphens.yaml index f543dfba..73793f7f 100644 --- a/test/specs/validate-spec/valid/2.0/definition-name-with-hyphens.yaml +++ b/test/specs/validate-spec/valid/2.0/definition-name-with-hyphens.yaml @@ -1,6 +1,6 @@ -swagger: "2.0" +swagger: '2.0' info: - version: "1.0" + version: '1.0' title: Valid API paths: @@ -10,7 +10,7 @@ paths: '200': description: OK schema: - "$ref": "#/definitions/User-Information" + '$ref': '#/definitions/User-Information' definitions: User-Information: diff --git a/test/specs/validate-spec/valid/2.0/file-vendor-specific-consumes-formdata.yaml b/test/specs/validate-spec/valid/2.0/file-vendor-specific-consumes-formdata.yaml index 837ba791..f3e24687 100644 --- a/test/specs/validate-spec/valid/2.0/file-vendor-specific-consumes-formdata.yaml +++ b/test/specs/validate-spec/valid/2.0/file-vendor-specific-consumes-formdata.yaml @@ -1,6 +1,6 @@ -swagger: "2.0" +swagger: '2.0' info: - version: "1.0.0" + version: '1.0.0' title: Valid API paths: @@ -12,10 +12,10 @@ paths: required: true - name: image in: formData - type: file # <--- "file" params REQUIRE multipart/form-data or application/x-www-form-urlencoded + type: file # <--- "file" params REQUIRE multipart/form-data or application/x-www-form-urlencoded post: consumes: - - multipart/vnd.specific+form-data;version=1.0 # <--- Vendor specific version of multipart/form-data with a parameter + - multipart/vnd.specific+form-data;version=1.0 # <--- Vendor specific version of multipart/form-data with a parameter responses: default: - description: hello world + description: hello world diff --git a/test/specs/validate-spec/valid/2.0/file-vendor-specific-consumes-urlencoded.yaml b/test/specs/validate-spec/valid/2.0/file-vendor-specific-consumes-urlencoded.yaml index e480a84d..f91aa805 100644 --- a/test/specs/validate-spec/valid/2.0/file-vendor-specific-consumes-urlencoded.yaml +++ b/test/specs/validate-spec/valid/2.0/file-vendor-specific-consumes-urlencoded.yaml @@ -1,6 +1,6 @@ -swagger: "2.0" +swagger: '2.0' info: - version: "1.0.0" + version: '1.0.0' title: Valid API paths: @@ -12,10 +12,10 @@ paths: required: true - name: image in: formData - type: file # <--- "file" params REQUIRE multipart/form-data or application/x-www-form-urlencoded + type: file # <--- "file" params REQUIRE multipart/form-data or application/x-www-form-urlencoded post: consumes: - - application/vnd.specific+x-www-form-urlencoded;version=1.0 # <--- Vendor specific version of application/x-www-form-urlencoded with a parameter + - application/vnd.specific+x-www-form-urlencoded;version=1.0 # <--- Vendor specific version of application/x-www-form-urlencoded with a parameter responses: default: - description: hello world + description: hello world diff --git a/test/specs/validate-spec/valid/2.0/inherited-required-properties.yaml b/test/specs/validate-spec/valid/2.0/inherited-required-properties.yaml index 707d978b..cb0554d5 100644 --- a/test/specs/validate-spec/valid/2.0/inherited-required-properties.yaml +++ b/test/specs/validate-spec/valid/2.0/inherited-required-properties.yaml @@ -49,7 +49,7 @@ definitions: allOf: - $ref: '#/definitions/Offering' required: - - contentId # <-- all required properties are inherited + - contentId # <-- all required properties are inherited - start - end OfferingMetadataResponse: diff --git a/test/specs/validate-spec/valid/3.0/component-schema-with-hyphens.yaml b/test/specs/validate-spec/valid/3.0/component-schema-with-hyphens.yaml index b13b84fd..23c06337 100644 --- a/test/specs/validate-spec/valid/3.0/component-schema-with-hyphens.yaml +++ b/test/specs/validate-spec/valid/3.0/component-schema-with-hyphens.yaml @@ -1,6 +1,6 @@ openapi: 3.0.3 info: - version: "1.0" + version: '1.0' title: Invalid API paths: /anything: @@ -13,7 +13,7 @@ paths: schema: type: array items: - "$ref": "#/components/schemas/User-Information" + '$ref': '#/components/schemas/User-Information' components: schemas: User-Information: diff --git a/test/specs/validate-spec/valid/3.1/component-schema-with-hyphens.yaml b/test/specs/validate-spec/valid/3.1/component-schema-with-hyphens.yaml index 76187fdd..141e7d0e 100644 --- a/test/specs/validate-spec/valid/3.1/component-schema-with-hyphens.yaml +++ b/test/specs/validate-spec/valid/3.1/component-schema-with-hyphens.yaml @@ -1,6 +1,6 @@ openapi: 3.1.0 info: - version: "1.0" + version: '1.0' title: Invalid API paths: /anything: @@ -13,7 +13,7 @@ paths: schema: type: array items: - "$ref": "#/components/schemas/User-Information" + '$ref': '#/components/schemas/User-Information' components: schemas: User-Information: diff --git a/test/specs/validate-spec/validate-spec.spec.js b/test/specs/validate-spec/validate-spec.test.ts similarity index 96% rename from test/specs/validate-spec/validate-spec.spec.js rename to test/specs/validate-spec/validate-spec.test.ts index 7a8a519e..e038635b 100644 --- a/test/specs/validate-spec/validate-spec.spec.js +++ b/test/specs/validate-spec/validate-spec.test.ts @@ -1,18 +1,18 @@ -const { expect } = require('chai'); +import { describe, it, expect, assert } from 'vitest'; -const OpenAPIParser = require('../../..'); -const path = require('../../utils/path'); +import OpenAPIParser from '../../..'; +import path from '../../utils/path'; -function assertValid(file) { +function assertValid(file: string) { return OpenAPIParser.validate(path.rel(`specs/validate-spec/valid/${file}`)).then(api => { expect(api).to.be.an('object'); }); } -function assertInvalid(file, error) { +function assertInvalid(file: string, error: string) { return OpenAPIParser.validate(path.rel(`specs/validate-spec/invalid/${file}`)) .then(() => { - throw new Error('Validation should have failed, but it succeeded!'); + assert.fail('Validation should have failed, but it succeeded!'); }) .catch(err => { expect(err).to.be.an.instanceOf(SyntaxError); @@ -206,6 +206,7 @@ describe('Invalid APIs (specification validation)', () => { }); // @todo add a case for this + // eslint-disable-next-line vitest/no-disabled-tests it.skip('OpenAPI 3.x', () => { return assertInvalid( '3.x/array-body-no-items.yaml', @@ -248,6 +249,7 @@ describe('Invalid APIs (specification validation)', () => { }); // @todo add a case for requestBody having a required property that doesn't exist in its schema + // eslint-disable-next-line vitest/no-disabled-tests it.skip('OpenAPI 3.x', () => { return assertInvalid( '3.x/required-property-not-defined-input.yaml', @@ -262,6 +264,7 @@ describe('Invalid APIs (specification validation)', () => { }); // @todo add a case for this + // eslint-disable-next-line vitest/no-disabled-tests it.skip('OpenAPI 3.x', () => { return assertValid('3.x/inherited-required-properties.yaml'); }); @@ -304,6 +307,7 @@ describe('Invalid APIs (specification validation)', () => { // best, or fastest, handling for nested schemas. It would likely be easier and faster to use something like // `jsonpath` but that library unfortunately would add a lot of bloat to this library and it doesn't play well with // browsers. + // eslint-disable-next-line vitest/no-disabled-tests it.skip('OpenAPI 3.1', () => { return assertInvalid('3.1/invalid-discriminator.yaml', 'TKTK'); }); diff --git a/test/utils/helper.js b/test/utils/helper.js deleted file mode 100644 index a104c13d..00000000 --- a/test/utils/helper.js +++ /dev/null @@ -1,72 +0,0 @@ -const { expect } = require('chai'); - -const OpenAPIParser = require('../..'); - -const path = require('./path'); - -const helper = { - /** - * Throws an error if called. - */ - shouldNotGetCalled() { - throw new Error('This function should not have gotten called.'); - }, - - /** - * Tests the {@link OpenAPIParser.resolve} method, - * and asserts that the given file paths resolve to the given values. - * - * @param {string} filePath - The file path that should be resolved - * @param {*} resolvedValue - The resolved value of the file - * @param {...*} [params] - Additional file paths and resolved values - * @returns {Function} - */ - // eslint-disable-next-line no-unused-vars - testResolve(filePath, resolvedValue, params) { - const schemaFile = path.rel(arguments[0]); - const parsedAPI = arguments[1]; - const expectedFiles = []; - const expectedValues = []; - for (let i = 0; i < arguments.length; i++) { - expectedFiles.push(path.abs(arguments[i])); - expectedValues.push(arguments[++i]); - } - - return async () => { - const parser = new OpenAPIParser(); - const $refs = await parser.resolve(schemaFile); - - expect(parser.api).to.deep.equal(parsedAPI); - expect(parser.$refs).to.equal($refs); - - // Resolved file paths - expect($refs.paths()).to.have.same.members(expectedFiles); - expect($refs.paths(['file'])).to.have.same.members(expectedFiles); - expect($refs.paths('http')).to.be.an('array').with.lengthOf(0); - - // Resolved values - const values = $refs.values(); - expect(values).to.have.keys(expectedFiles); - for (const [i, file] of expectedFiles.entries()) { - const actual = helper.convertNodeBuffersToPOJOs(values[file]); - const expected = expectedValues[i]; - expect(actual).to.deep.equal(expected, file); - } - }; - }, - - /** - * Converts Buffer objects to POJOs, so they can be compared using Chai - */ - convertNodeBuffersToPOJOs(value) { - if (value && (value._isBuffer || (value.constructor && value.constructor.name === 'Buffer'))) { - // Convert Buffers to POJOs for comparison - // eslint-disable-next-line no-param-reassign - value = value.toJSON(); - } - - return value; - }, -}; - -module.exports = helper; diff --git a/test/utils/helper.ts b/test/utils/helper.ts new file mode 100644 index 00000000..7bee3a7d --- /dev/null +++ b/test/utils/helper.ts @@ -0,0 +1,62 @@ +/* eslint-disable @typescript-eslint/no-explicit-any */ +import { expect } from 'vitest'; + +import OpenAPIParser from '../..'; + +import path from './path'; + +/** + * Converts Buffer objects to POJOs, so they can be compared using Chai + */ +export function convertNodeBuffersToPOJOs(value) { + if (value && (value._isBuffer || (value.constructor && value.constructor.name === 'Buffer'))) { + // Convert Buffers to POJOs for comparison + // eslint-disable-next-line no-param-reassign + value = value.toJSON(); + } + + return value; +} + +/** + * Tests the {@link OpenAPIParser.resolve} method, + * and asserts that the given file paths resolve to the given values. + * + * @param {string} filePath - The file path that should be resolved + * @param {*} resolvedValue - The resolved value of the file + * @param {...*} [params] - Additional file paths and resolved values + * @returns {Function} + */ +// eslint-disable-next-line @typescript-eslint/no-unused-vars +export function testResolve(filePath: string, resolvedValue: any, ...params: any | string) { + const schemaFile = path.rel(arguments[0]); + const parsedAPI = arguments[1]; + const expectedFiles: string[] = []; + const expectedValues: string[] = []; + for (let i = 0; i < arguments.length; i++) { + expectedFiles.push(path.abs(arguments[i])); + expectedValues.push(arguments[++i]); + } + + return async () => { + const parser = new OpenAPIParser(); + const $refs = await parser.resolve(schemaFile); + + expect(parser.api).to.deep.equal(parsedAPI); + expect(parser.$refs).to.equal($refs); + + // Resolved file paths + expect($refs.paths()).to.have.same.members(expectedFiles); + expect($refs.paths(['file'])).to.have.same.members(expectedFiles); + expect($refs.paths('http')).to.be.an('array').with.lengthOf(0); + + // Resolved values + const values = $refs.values(); + expect(values).to.have.keys(expectedFiles); + for (const [i, file] of expectedFiles.entries()) { + const actual = convertNodeBuffersToPOJOs(values[file]); + const expected = expectedValues[i]; + expect(actual).to.deep.equal(expected, file); + } + }; +} diff --git a/test/utils/path.js b/test/utils/path.js index c653cc3f..7447397f 100644 --- a/test/utils/path.js +++ b/test/utils/path.js @@ -1,11 +1,11 @@ - -const nodePath = require('path') -const nodeUrl = require('url') +const nodePath = require('path'); +const nodeUrl = require('url'); const testsDir = nodePath.resolve(__dirname, '..'); const isWindows = /^win/.test(process.platform); // Run all tests from the "test" directory +// eslint-disable-next-line vitest/require-hook process.chdir(nodePath.join(__dirname, '..')); /** diff --git a/vitest.config.mts b/vitest.config.mts new file mode 100644 index 00000000..1d65462c --- /dev/null +++ b/vitest.config.mts @@ -0,0 +1,23 @@ +// eslint-disable-next-line import/no-extraneous-dependencies +import { defineConfig } from 'vitest/config'; + +export default defineConfig({ + test: { + exclude: [ + '**/node_modules/**', + '**/dist/**', + + // This test is better served by native TS typings. Ignoring until we have those. + '**/typescript-definition.spec.ts', + ], + + /** + * We can't run tests with `threads` on because we use `process.chdir()` in some tests and + * that isn't available in worker threads, and it's way too much work to mock out an entire + * filesystem and `fs` calls for the tests that use it. + * + * @see {@link https://github.com/vitest-dev/vitest/issues/566} + */ + pool: 'forks', + }, +});