diff --git a/.github/workflows/ci.yaml b/.github/workflows/ci.yaml index 16dccef2..c5bcc78b 100644 --- a/.github/workflows/ci.yaml +++ b/.github/workflows/ci.yaml @@ -22,7 +22,7 @@ jobs: strategy: matrix: - node-version: [14.x, 16.x, 18.x] + node-version: [18.x, 20.x, 22.x] steps: - uses: actions/checkout@v3 diff --git a/NOTICE b/NOTICE index ca01fe4b..4d637b65 100644 --- a/NOTICE +++ b/NOTICE @@ -1,5 +1,5 @@ Apache CouchDB Nano -Copyright [2016-2018] The Apache Software Foundation +Copyright [2016-2024] The Apache Software Foundation This product includes software developed at The Apache Software Foundation (http://www.apache.org/). diff --git a/README.md b/README.md index 6b35cc1d..24396157 100644 --- a/README.md +++ b/README.md @@ -4,6 +4,9 @@ Offical [Apache CouchDB](https://couchdb.apache.org/) library for [Node.js](https://nodejs.org/). +> Note: Nano >=11.0.0 is a **breaking change for Node.js versions 16 and older**. Nano 11 uses Node.js's built-in "fetch" HTTP client but this is only available in Node.js versions 18 or later. If you are using Node 16 or older then continue using Nano 10. +> See our [migration guide](migration_guide_v10_to_v11.md) for moving from Nano 10 to Nano 11. + Features: * **Minimalistic** - There is only a minimum of abstraction between you and @@ -31,66 +34,66 @@ Note the minimum required version of Node.js is 10. - [Tutorials & screencasts](#tutorials-examples-in-the-wild--screencasts) - [Configuration](#configuration) - [Database functions](#database-functions) - - [nano.db.create(name, [callback])](#nanodbcreatename-callback) - - [nano.db.get(name, [callback])](#nanodbgetname-callback) - - [nano.db.destroy(name, [callback])](#nanodbdestroyname-callback) - - [nano.db.list([callback])](#nanodblistcallback) + - [nano.db.create(name)](#nanodbcreatename) + - [nano.db.get(name)](#nanodbgetname) + - [nano.db.destroy(name)](#nanodbdestroyname) + - [nano.db.list()](#nanodblist) - [nano.db.listAsStream()](#nanodblistasstream) - - [nano.db.compact(name, [designname], [callback])](#nanodbcompactname-designname-callback) - - [nano.db.replicate(source, target, [opts], [callback])](#nanodbreplicatesource-target-opts-callback) - - [nano.db.replication.enable(source, target, [opts], [callback])](#nanodbreplicationenablesource-target-opts-callback) - - [nano.db.replication.query(id, [opts], [callback])](#nanodbreplicationenablesource-target-opts-callback) - - [nano.db.replication.disable(id, [opts], [callback])](#nanodbreplicationdisableid-opts-callback) - - [nano.db.changes(name, [params], [callback])](#nanodbchangesname-params-callback) + - [nano.db.compact(name, [designname])](#nanodbcompactname-designname) + - [nano.db.replicate(source, target, [opts])](#nanodbreplicatesource-target-opts) + - [nano.db.replication.enable(source, target, [opts])](#nanodbreplicationenablesource-target-opts) + - [nano.db.replication.query(id, [opts])](#nanodbreplicationenablesource-target-opts) + - [nano.db.replication.disable(id, [opts])](#nanodbreplicationdisableid-opts) + - [nano.db.changes(name, [params])](#nanodbchangesname-params) - [nano.db.changesAsStream(name, [params])](#nanodbchangesasstreamname-params) - - [nano.db.info([callback])](#nanodbinfocallback) + - [nano.db.info()](#nanodbinfo) - [nano.use(name)](#nanousename) - - [nano.request(opts, [callback])](#nanorequestopts-callback) + - [nano.request(opts)](#nanorequestopts) - [nano.config](#nanoconfig) - - [nano.updates([params], [callback])](#nanoupdatesparams-callback) - - [nano.info([callback])](#nanoinfocallback) + - [nano.updates([params])](#nanoupdatesparams) + - [nano.info()](#nanoinfo) - [Document functions](#document-functions) - - [db.insert(doc, [params], [callback])](#dbinsertdoc-params-callback) - - [db.destroy(docname, rev, [callback])](#dbdestroydocname-rev-callback) - - [db.get(docname, [params], [callback])](#dbgetdocname-params-callback) - - [db.head(docname, [callback])](#dbheaddocname-callback) - - [db.bulk(docs, [params], [callback])](#dbbulkdocs-params-callback) - - [db.list([params], [callback])](#dblistparams-callback) + - [db.insert(doc, [params])](#dbinsertdoc-params) + - [db.destroy(docname, rev)](#dbdestroydocname-rev) + - [db.get(docname, [params])](#dbgetdocname-params) + - [db.head(docname)](#dbheaddocname) + - [db.bulk(docs, [params])](#dbbulkdocs-params) + - [db.list([params])](#dblistparams) - [db.listAsStream([params])](#dblistasstreamparams) - - [db.fetch(docnames, [params], [callback])](#dbfetchdocnames-params-callback) - - [db.fetchRevs(docnames, [params], [callback])](#dbfetchrevsdocnames-params-callback) - - [db.createIndex(indexDef, [callback])](#dbcreateindexindexdef-callback) + - [db.fetch(docnames, [params])](#dbfetchdocnames-params) + - [db.fetchRevs(docnames, [params])](#dbfetchrevsdocnames-params) + - [db.createIndex(indexDef)](#dbcreateindexindexdef) - [db.changesReader](#reading-changes-feed) - [Partitioned database functions](#partition-functions) - - [db.partitionInfo(partitionKey, [callback])](#dbpartitioninfopartitionkey-callback)) - - [db.partitionedList(partitionKey, [params], [callback])](#dbpartitionedlistpartitionkey-params-callback) + - [db.partitionInfo(partitionKey)](#dbpartitioninfopartitionkey)) + - [db.partitionedList(partitionKey, [params])](#dbpartitionedlistpartitionkey-params) - [db.partitionedListAsStream(partitionKey, [params])](#dbpartitionedlistasstreampartitionkey-params) - - [db.partitionedFind(partitionKey, query, [callback])](#dbpartitionedfindpartitionkey-query-params) + - [db.partitionedFind(partitionKey, query)](#dbpartitionedfindpartitionkey-query-params) - [db.partitionedFindAsStream(partitionKey, query)](#dbpartitionedfindasstreampartitionkey-query) - - [db.partitionedSearch(partitionKey, designName, searchName, params, [callback])](#dbpartitionedsearchpartitioney-designname-searchname-params-callback) + - [db.partitionedSearch(partitionKey, designName, searchName, params)](#dbpartitionedsearchpartitioney-designname-searchname-params) - [db.partitionedSearchAsStream(partitionKey, designName, searchName, params)](#dbpartitionedsearchasstreampartitionkey-designName-searchName-params) - - [db.partitionedView(partitionKey, designName, viewName, [params], [callback])](#dbpartitionediewpartitionkey-designname-viewname-params-callback) + - [db.partitionedView(partitionKey, designName, viewName, [params])](#dbpartitionediewpartitionkey-designname-viewname-params) - [db.partitionedViewAsStream(partitionKey, designName, viewName, [params])](#dbpartitionediewasstreampartitionkey-designname-viewname-params) - [Multipart functions](#multipart-functions) - - [db.multipart.insert(doc, attachments, [params], [callback])](#dbmultipartinsertdoc-attachments-params-callback) - - [db.multipart.get(docname, [params], [callback])](#dbmultipartgetdocname-params-callback) + - [db.multipart.insert(doc, attachments, [params])](#dbmultipartinsertdoc-attachments-params) + - [db.multipart.get(docname, [params])](#dbmultipartgetdocname-params) - [Attachments functions](#attachments-functions) - - [db.attachment.insert(docname, attname, att, contenttype, [params], [callback])](#dbattachmentinsertdocname-attname-att-contenttype-params-callback) + - [db.attachment.insert(docname, attname, att, contenttype, [params])](#dbattachmentinsertdocname-attname-att-contenttype-params) - [db.attachment.insertAsStream(docname, attname, att, contenttype, [params])](#dbattachmentinsertasstreamdocname-attname-att-contenttype-params) - - [db.attachment.get(docname, attname, [params], [callback])](#dbattachmentgetdocname-attname-params-callback) + - [db.attachment.get(docname, attname, [params])](#dbattachmentgetdocname-attname-params) - [db.attachment.getAsStream(docname, attname, [params])](#dbattachmentgetasstreamdocname-attname-params) - - [db.attachment.destroy(docname, attname, [params], [callback])](#dbattachmentdestroydocname-attname-params-callback) + - [db.attachment.destroy(docname, attname, [params])](#dbattachmentdestroydocname-attname-params) - [Views and design functions](#views-and-design-functions) - - [db.view(designname, viewname, [params], [callback])](#dbviewdesignname-viewname-params-callback) + - [db.view(designname, viewname, [params])](#dbviewdesignname-viewname-params) - [db.viewAsStream(designname, viewname, [params])](#dbviewasstreamdesignname-viewname-params) - [db.viewWithList(designname, viewname, listname, [params])](#dbviewwithlistdesignname-viewname-params) - [db.viewWithListAsStream(designname__viewname, listname, [params])](#dbviewwithlistasstreamdesignname-viewname-params) - - [db.show(designname, showname, doc_id, [params], [callback])](#dbshowdesignname-showname-doc_id-params-callback) - - [db.atomic(designname, updatename, docname, [body], [callback])](#dbatomicdesignname-updatename-docname-body-callback) - - [db.search(designname, viewname, params, [callback])](#dbsearchdesignname-searchname-params-callback) + - [db.show(designname, showname, doc_id, [params])](#dbshowdesignname-showname-doc_id-params) + - [db.atomic(designname, updatename, docname, [body])](#dbatomicdesignname-updatename-docname-body) + - [db.search(designname, viewname, params)](#dbsearchdesignname-searchname-params) - [db.searchAsStream(designname, viewname, params)](#dbsearchasstreamdesignname-searchname-params) - - [db.find(selector, [callback])](#dbfindselector-callback) + - [db.find(selector)](#dbfindselector) - [db.findAsStream(selector)](#dbfindasstreamselector) - [Using cookie authentication](#using-cookie-authentication) - [Advanced features](#advanced-features) @@ -105,7 +108,7 @@ Note the minimum required version of Node.js is 10. To use `nano` you need to connect it to your CouchDB install, to do that: ```js -const nano = require('nano')('http://localhost:5984'); +const nano = require('nano')('http://127.0.0.1:5984'); ``` > Note: Supplying authentication credentials in the URL e.g. `http://admin:mypassword@localhost:5984` is deprecated. Use `nano.auth` instead. @@ -134,7 +137,7 @@ nano.db.create('alice').then((data) => { }) ``` -or in the async/await style: +2) or in the async/await style: ```js try { @@ -147,21 +150,6 @@ try { } ``` -2) Callbacks - -```js -nano.db.create('alice', (err, data) => { - // errors are in 'err' & response is in 'data' -}) -``` - -In `nano` the callback function receives always three arguments: - -* `err` - The error, if any. -* `body` - The HTTP _response body_ from CouchDB, if no error. - JSON parsed body, binary for non JSON responses. -* `header` - The HTTP _response header_ from CouchDB, if no error. - The documentation will follow the *async/await* style. ------------------ @@ -189,14 +177,14 @@ you have inserted a document with an _id of rabbit. rev: '1-6e4cb465d49c0368ac3946506d26335d' } ``` -You can also see your document in futon (http://localhost:5984/_utils). +You can also see your document in futon (http://127.0.0.1:5984/_utils). ## Configuration Configuring nano to use your database server is as simple as: ```js -const nano = require('nano')('http://localhost:5984') +const nano = require('nano')('http://127.0.0.1:5984') const db = nano.use('foo'); ``` @@ -204,76 +192,72 @@ If you don't need to instrument database objects you can simply: ```js // nano parses the URL and knows this is a database -const db = require('nano')('http://localhost:5984/foo'); +const db = require('nano')('http://127.0.0.1:5984/foo'); ``` -You can also pass options to the require to specify further configuration options you can pass an object literal instead: +You can tell nano to not parse the URL (maybe the server is behind a proxy, is accessed through a rewrite rule or other): ```js -// nano parses the URL and knows this is a database -const opts = { - url: 'http://localhost:5984/foo', - requestDefaults: { - proxy: { - protocol: 'http', - host: 'myproxy.net' - }, - headers: { - customheader: 'MyCustomHeader' - } - } -}; -const db = require('nano')(opts); +// nano does not parse the URL and return the server api +// "http://127.0.0.1:5984/prefix" is the CouchDB server root +const couch = require('nano')( + { + url : "http://127.0.0.1:5984/prefix" + parseUrl : false + }); +const db = couch.use('foo'); ``` -Nano works perfectly well over HTTPS as long as the SSL cert is signed by a certification authority known by your client operating system. If you have a custom or self-signed certificate, you may need to create your own HTTPS agent and pass it to Nano e.g. +### Pool size and open sockets + +To specify the number of connections, timeouts and pool size, supply an `agentOptions` object when starting up Nano. ```js -const httpsAgent = new https.Agent({ - ca: '/path/to/cert', - rejectUnauthorized: true, - keepAlive: true, - maxSockets: 6 -}) -const nano = Nano({ - url: process.env.COUCH_URL, - requestDefaults: { - agent: httpsAgent, - } -}) +const agentOptions = { + bodyTimeout: 30000, + headersTimeout: 30000, + keepAliveMaxTimeout: 600000, + keepAliveTimeout: 30000, + keepAliveTimeoutThreshold: 1000, + maxHeaderSize: 16384, + maxResponseSize: -1, + pipelining: 6, + connect: { + timeout: 10000 + }, + strictContentLength: true, + connections: null, + maxRedirections: 0 +} +const undici = require('undici') +const undiciOptions = new undici.Agent(agentOptions) +const nano = Nano({ url: 'http://127.0.0.1:5984', undiciOptions }) ``` -Please check [axios] for more information on the defaults. They support features like proxies, timeout etc. +The meanings of the agentOptions attributes is described [here](https://undici.nodejs.org/#/docs/api/Agent?id=new-undiciagentoptions), [here](https://undici.nodejs.org/#/docs/api/Pool?id=parameter-pooloptions) and [here](https://undici.nodejs.org/#/docs/api/Client?id=parameter-clientoptions) -You can tell nano to not parse the URL (maybe the server is behind a proxy, is accessed through a rewrite rule or other): +You may also supply a pre-existing `undici.Agent` e.g. ```js -// nano does not parse the URL and return the server api -// "http://localhost:5984/prefix" is the CouchDB server root -const couch = require('nano')( - { url : "http://localhost:5984/prefix" - parseUrl : false - }); -const db = couch.use('foo'); +const agent = new undici.Agent({bodyTimeout: 30000 }) +const nano = Nano({ url: 'http://127.0.0.1:5984', agentOptions: agent }) ``` -### Pool size and open sockets +> Note `requestDefaults` is no longer supported. -A very important configuration parameter if you have a high traffic website and are using `nano` is the HTTP pool size. By default, the Node.js HTTP global agent has a infinite number of active connections that can run simultaneously. This can be limited to user-defined number (`maxSockets`) of requests that are "in flight", while others are kept in a queue. Here's an example explicitly using the Node.js HTTP agent configured with [custom options](https://nodejs.org/api/http.html#http_new_agent_options): +## Custom headers -```js -const http = require('http') -const myagent = new http.Agent({ - keepAlive: true, - maxSockets: 25 -}) +To supply customer headers with each request, supply a headers object when starting up Nano: -const db = require('nano')({ - url: 'http://localhost:5984/foo', - requestDefaults : { - agent : myagent - } -}); + +```js +const couch = require('nano')( + { + url : "http://127.0.0.1:5984/prefix" + headers: { + mycustomheader: '42' + } + }); ``` ## TypeScript @@ -283,7 +267,7 @@ There is a full TypeScript definition included in the the *nano* package. Your T ```ts import * as Nano from 'nano' -let n = Nano('http://USERNAME:PASSWORD@localhost:5984') +let n = Nano('http://USERNAME:PASSWORD@127.0.0.1:5984') let db = n.db.use('people') interface iPerson extends Nano.MaybeDocument { @@ -321,7 +305,7 @@ db.insert(p).then((response) => { ## Database functions -### nano.db.create(name, [opts], [callback]) +### nano.db.create(name, [opts]) Creates a CouchDB database with the given `name`, with options `opts`. @@ -329,7 +313,7 @@ Creates a CouchDB database with the given `name`, with options `opts`. await nano.db.create('alice', { n: 3 }) ``` -### nano.db.get(name, [callback]) +### nano.db.get(name) Get information about the database `name`: @@ -337,7 +321,7 @@ Get information about the database `name`: const info = await nano.db.get('alice') ``` -### nano.db.destroy(name, [callback]) +### nano.db.destroy(name) Destroys the database `name`: @@ -345,7 +329,7 @@ Destroys the database `name`: await nano.db.destroy('alice') ``` -### nano.db.list([callback]) +### nano.db.list() Lists all the CouchDB databases: @@ -363,11 +347,11 @@ nano.db.listAsStream() .pipe(process.stdout); ``` -### nano.db.compact(name, [designname], [callback]) +### nano.db.compact(name, [designname]) Compacts `name`, if `designname` is specified also compacts its views. -### nano.db.replicate(source, target, [opts], [callback]) +### nano.db.replicate(source, target, [opts]) Replicates `source` to `target` with options `opts`. The `target`database has to exist, add `create_target:true` to `opts` to create it prior to @@ -379,7 +363,7 @@ const response = await nano.db.replicate('alice', { create_target:true }) ``` -### nano.db.replication.enable(source, target, [opts], [callback]) +### nano.db.replication.enable(source, target, [opts]) Enables replication using the new CouchDB api from `source` to `target` with options `opts`. `target` has to exist, add `create_target:true` to @@ -391,7 +375,7 @@ const response = await nano.db.replication.enable('alice', { create_target:true }) ``` -### nano.db.replication.query(id, [opts], [callback]) +### nano.db.replication.query(id, [opts]) Queries the state of replication using the new CouchDB API. The `id` comes from the response given by the call to `replication.enable`: @@ -403,7 +387,7 @@ const r = await nano.db.replication.enable('alice', const q = await nano.db.replication.query(r.id) ``` -### nano.db.replication.disable(id, [opts], [callback]) +### nano.db.replication.disable(id, [opts]) Disables replication using the new CouchDB API. The `id` comes from the response given by the call to `replication.enable`: @@ -415,7 +399,7 @@ const r = await nano.db.replication.enable('alice', await nano.db.replication.disable(r.id); ``` -### nano.db.changes(name, [params], [callback]) +### nano.db.changes(name, [params]) Asks for the changes feed of `name`, `params` contains additions to the query string. @@ -432,7 +416,7 @@ Same as `nano.db.changes` but returns a stream. nano.db.changes('alice').pipe(process.stdout); ``` -### nano.db.info([callback]) +### nano.db.info() Gets database information: @@ -463,7 +447,7 @@ Alias for `nano.use` Alias for `nano.use` -### nano.request(opts, [callback]) +### nano.request(opts) Makes a custom request to CouchDB. This can be used to create your own HTTP request to the CouchDB server, to perform operations where there is no `nano` function that encapsulates it. The available `opts` are: @@ -482,7 +466,7 @@ server, to perform operations where there is no `nano` function that encapsulate * `opts.multipart` – array of objects for multipart request * `opts.stream` - if `true`, a `request` object is returned. Default `false` and a Promise is returned. -### nano.relax(opts, [callback]) +### nano.relax(opts) Alias for `nano.request` @@ -493,7 +477,7 @@ An object containing the `nano` configurations, possible keys are: * `url` - the CouchDB URL * `db` - the database name -### nano.updates([params], [callback]) +### nano.updates([params]) Listen to db updates, the available `params` are: @@ -504,7 +488,7 @@ Listen to db updates, the available `params` are: * `params.timeout` – Number of seconds until CouchDB closes the connection. Default is 60. * `params.heartbeat` – Whether CouchDB will send a newline character (\n) on timeout. Default is true. -### nano.info([callback]) +### nano.info() Fetch information about the CouchDB cluster: @@ -516,7 +500,7 @@ The response is an object with [CouchDB cluster information](https://docs.couchd ## Document functions -### db.insert(doc, [params], [callback]) +### db.insert(doc, [params]) Inserts `doc` in the database with optional `params`. If params is a string, it's assumed it is the intended document `_id`. If params is an object, it's passed as query string parameters and `docName` is checked for defining the document `_id`: @@ -525,7 +509,7 @@ const alice = nano.use('alice'); const response = await alice.insert({ happy: true }, 'rabbit') ``` -The `insert` function can also be used with the method signature `db.insert(doc,[callback])`, where the `doc` contains the `_id` field e.g. +The `insert` function can also be used with the method signature `db.insert(doc,)`, where the `doc` contains the `_id` field e.g. ```js const alice = nano.use('alice') @@ -539,7 +523,7 @@ const alice = nano.use('alice') const response = await alice.insert({ _id: 'myid', _rev: '1-23202479633c2b380f79507a776743d5', happy: false }) ``` -### db.destroy(docname, rev, [callback]) +### db.destroy(docname, rev) Removes a document from CouchDB whose `_id` is `docname` and whose revision (`_rev`) is `rev`: @@ -547,7 +531,7 @@ Removes a document from CouchDB whose `_id` is `docname` and whose revision (`_r const response = await alice.destroy('rabbit', '3-66c01cdf99e84c83a9b3fe65b88db8c0') ``` -### db.get(docname, [params], [callback]) +### db.get(docname, [params]) Gets a document from CouchDB whose `_id` is `docname`: @@ -563,13 +547,13 @@ const doc = await alice.get('rabbit', { revs_info: true }) If you pass `attachments=true`, the `doc._attachments.attachmentNameN.data` fields will contain the [base-64 encoded attachments](https://docs.couchdb.org/en/stable/json-structure.html#document-with-attachments). -Or, you can use [`db.multipart.get`](https://github.com/DougReeder/couchdb-nano#dbmultipartgetdocname-params-callback) +Or, you can use [`db.multipart.get`](https://github.com/DougReeder/couchdb-nano#dbmultipartgetdocname-params) and parse the returned buffer to get the document and attachments. See the [attachments methods](https://github.com/apache/couchdb-nano#attachments-functions) to retrieve *just* an attachment. -### db.head(docname, [callback]) +### db.head(docname) Same as `get` but lightweight version that returns headers only: @@ -577,9 +561,7 @@ Same as `get` but lightweight version that returns headers only: const headers = await alice.head('rabbit') ``` -*Note:* if you call `alice.head` in the callback style, the headers are returned to you as the third argument of the callback function. - -### db.bulk(docs, [params], [callback]) +### db.bulk(docs, [params]) Bulk operations(update/delete/insert) on the database, refer to the [CouchDB doc](https://docs.couchdb.org/en/stable/api/database/bulk-api.html#post--db-_bulk_docs) e.g: @@ -592,7 +574,7 @@ const documents = [ const response = await alice.bulk({ docs: documents }) ``` -### db.list([params], [callback]) +### db.list([params]) List all the docs in the database . @@ -620,7 +602,7 @@ alice.listAsStream() .pipe(process.stdout) ``` -### db.fetch(docnames, [params], [callback]) +### db.fetch(docnames, [params]) Bulk fetch of the database documents, `docnames` are specified as per [CouchDB doc](https://docs.couchdb.org/en/latest/api/database/bulk-api.html#post--db-_all_docs). @@ -632,7 +614,7 @@ const keys = ['tiger', 'zebra', 'donkey']; const datat = await alice.fetch({keys: keys}) ``` -### db.fetchRevs(docnames, [params], [callback]) +### db.fetchRevs(docnames, [params]) ** changed in version 6 ** @@ -641,7 +623,7 @@ Bulk fetch of the revisions of the database documents, `docnames` are specified additional query string `params` can be specified, this is the same method as fetch but `include_docs` is not automatically set to `true`. -### db.createIndex(indexDef, [callback]) +### db.createIndex(indexDef) Create index on database fields, as specified in [CouchDB doc](https://docs.couchdb.org/en/latest/api/database/find.html#db-index). @@ -845,7 +827,7 @@ const ddoc = { await db.insert(ddoc) ``` -### db.partitionInfo(partitionKey, [callback]) +### db.partitionInfo(partitionKey) Fetch the stats of a single partition: @@ -853,7 +835,7 @@ Fetch the stats of a single partition: const stats = await alice.partitionInfo('canidae') ``` -### db.partitionedList(partitionKey, [params], [callback]) +### db.partitionedList(partitionKey, [params]) Fetch documents from a database partition: @@ -901,7 +883,7 @@ db.partitionedFindAsStream('canidae', { 'selector' : { 'name': 'Wolf' }}) .pipe(process.stdout) ``` -### db.partitionedSearch(partitionKey, designName, searchName, params, [callback]) +### db.partitionedSearch(partitionKey, designName, searchName, params) Search documents from a partition by supplying a Lucene query: @@ -927,7 +909,7 @@ db.partitionedSearchAsStream('canidae', 'search-ddoc', 'search-index', params) // { total_rows: ... , bookmark: ..., rows: [ ...] } ``` -### db.partitionedView(partitionKey, designName, viewName, params, [callback]) +### db.partitionedView(partitionKey, designName, viewName, params) Fetch documents from a MapReduce view from a partition: @@ -959,7 +941,7 @@ db.partitionedViewAsStream('canidae', 'view-ddoc', 'view-name', params) ## Multipart functions -### db.multipart.insert(doc, attachments, params, [callback]) +### db.multipart.insert(doc, attachments, params) Inserts a `doc` together with `attachments` and `params`. If params is a string, it's assumed as the intended document `_id`. If params is an object, its passed as query string parameters and `docName` is checked for defining the `_id`. Refer to the [doc](https://docs.couchdb.org/en/stable/api/document/common.html) for more details. The `attachments` parameter must be an array of objects with `name`, `data` and `content_type` properties. @@ -974,7 +956,7 @@ fs.readFile('rabbit.png', (err, data) => { }); ``` -### db.multipart.get(docname, [params], [callback]) +### db.multipart.get(docname, [params]) Get `docname` together with its attachments via `multipart/related` request with optional [query string additions](https://docs.couchdb.org/en/stable/api/document/common.html#get--db-docid). The multipart response body is a `Buffer`. @@ -984,7 +966,7 @@ const response = await alice.multipart.get('rabbit') ## Attachments functions -### db.attachment.insert(docname, attname, att, contenttype, [params], [callback]) +### db.attachment.insert(docname, attname, att, contenttype, [params]) Inserts an attachment `attname` to `docname`, in most cases `params.rev` is required. Refer to the @@ -1009,7 +991,7 @@ fs.readFile('rabbit.png', (err, data) => { As of Nano 9.x, the function `db.attachment.insertAsStream` is now deprecated. Now simply pass a readable stream to `db.attachment.insert` as the third paramseter. -### db.attachment.get(docname, attname, [params], [callback]) +### db.attachment.get(docname, attname, [params]) Get `docname`'s attachment `attname` with optional query string additions `params`. @@ -1030,7 +1012,7 @@ alice.attachment.getAsStream('rabbit', 'rabbit.png') .pipe(fs.createWriteStream('rabbit.png')); ``` -### db.attachment.destroy(docname, attname, [params], [callback]) +### db.attachment.destroy(docname, attname, [params]) **changed in version 6** @@ -1042,7 +1024,7 @@ const response = await alice.attachment.destroy('rabbit', 'rabbit.png', {rev: '1 ## Views and design functions -### db.view(designname, viewname, [params], [callback]) +### db.view(designname, viewname, [params]) Calls a view of the specified `designname` with optional query string `params`. If you're looking to filter the view results by key(s) pass an array of keys, e.g `{ keys: ['key1', 'key2', 'key_n'] }`, as `params`. @@ -1080,7 +1062,7 @@ alice.viewAsStream('characters', 'happy_ones', {reduce: false}) .pipe(process.stdout); ``` -### db.viewWithList(designname, viewname, listname, [params], [callback]) +### db.viewWithList(designname, viewname, listname, [params]) Calls a list function fed by the given view from the specified design document. @@ -1088,7 +1070,7 @@ Calls a list function fed by the given view from the specified design document. const body = await alice.viewWithList('characters', 'happy_ones', 'my_list') ``` -### db.viewWithListAsStream(designname, viewname, listname, [params], [callback]) +### db.viewWithListAsStream(designname, viewname, listname, [params]) Calls a list function fed by the given view from the specified design document as a stream. @@ -1098,7 +1080,7 @@ alice.viewWithListAsStream('characters', 'happy_ones', 'my_list') .pipe(process.stdout); ``` -### db.show(designname, showname, doc_id, [params], [callback]) +### db.show(designname, showname, doc_id, [params]) Calls a show function from the specified design for the document specified by doc_id with optional query string additions `params`. @@ -1110,7 +1092,7 @@ const doc = await alice.show('characters', 'format_doc', '3621898430') Take a look at the [CouchDB wiki](https://guide.couchdb.org/draft/show.html) for possible query paramaters and more information on show functions. -### db.atomic(designname, updatename, docname, [body], [callback]) +### db.atomic(designname, updatename, docname, [body]) Calls the design's update function with the specified doc in input. @@ -1134,7 +1116,7 @@ An example update handler follows: } ``` -### db.search(designname, searchname, params, [callback]) +### db.search(designname, searchname, params) Calls a view of the specified design with optional query string additions `params`. @@ -1159,7 +1141,7 @@ Calls a view of the specified design with optional query string additions `param alice.search('characters', 'happy_ones', { q: 'cat' }).pipe(process.stdout); ``` -### db.find(selector, [callback]) +### db.find(selector) Perform a ["Mango" query](https://docs.couchdb.org/en/2.1.1/api/database/find.html) by supplying a JavaScript object containing a selector: @@ -1201,10 +1183,7 @@ Nano supports making requests using CouchDB's [cookie authentication](http://gui ```js const nano = require('nano')({ - url: 'http://localhost:5984', - requestDefaults: { - jar: true - } + url: 'http://127.0.0.1:5984' }) const username = 'user' const userpass = 'pass' @@ -1361,7 +1340,6 @@ npm run test [2]: https://github.com/apache/couchdb-nano/issues [4]: https://github.com/apache/couchdb-nano/blob/main/cfg/couch.example.js [8]: https://webchat.freenode.net?channels=%23couchdb-dev -[axios]: https://github.com/axios/axios https://freenode.org/ diff --git a/examples/bulk_transform.js b/examples/bulk_transform.js deleted file mode 100644 index 0bb1a51d..00000000 --- a/examples/bulk_transform.js +++ /dev/null @@ -1,46 +0,0 @@ -// Licensed under the Apache License, Version 2.0 (the 'License'); you may not -// use this file except in compliance with the License. You may obtain a copy of -// the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an 'AS IS' BASIS, WITHOUT -// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -// License for the specific language governing permissions and limitations under -// the License. - -const db = require('nano')('http://localhost:5984/emails') -const async = require('async') - -function updateRow (row, cb) { - const doc = row.doc - delete doc.subject - db.insert(doc, doc._id, function (err, data) { - if (err) { console.log('err at ' + doc._id); cb(err) } else { console.log('updated ' + doc._id); cb() } - }) -} - -function list (offset) { - let ended = false - offset = offset || 0 - db.list({ include_docs: true, limit: 10, skip: offset }, - function (err, data) { - let rows - if (err) { console.log('fuuuu: ' + err.message); rows = []; return } - const total = data.total_rows - const offset = data.offset - rows = data.rows - if (offset === total) { - ended = true - return - } - async.forEach(rows, updateRow, function (err) { - if (err) { console.log('something failed, check logs') } - if (ended) { return } - list(offset + 10) - }) - }) -} - -list() diff --git a/examples/express.js b/examples/express.js deleted file mode 100644 index 06767a33..00000000 --- a/examples/express.js +++ /dev/null @@ -1,29 +0,0 @@ -// Licensed under the Apache License, Version 2.0 (the 'License'); you may not -// use this file except in compliance with the License. You may obtain a copy of -// the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an 'AS IS' BASIS, WITHOUT -// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -// License for the specific language governing permissions and limitations under -// the License. - -const express = require('express') -const db = require('nano')('http://localhost:5984/my_couch') -const app = module.exports = express() - -app.get('/', function (req, res) { - db.get('foo', function (error, body, headers) { - if (error) { - res.status(error.statusCode) - return res.send(error.message) - } - res.status(200) - res.send(body) - }) -}) - -app.listen(3333) -console.log('server is running. check expressjs.com for more cool tricks') diff --git a/examples/lazy_creation_of_views.js b/examples/lazy_creation_of_views.js deleted file mode 100644 index cfef9709..00000000 --- a/examples/lazy_creation_of_views.js +++ /dev/null @@ -1,115 +0,0 @@ -// Licensed under the Apache License, Version 2.0 (the 'License'); you may not -// use this file except in compliance with the License. You may obtain a copy of -// the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an 'AS IS' BASIS, WITHOUT -// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -// License for the specific language governing permissions and limitations under -// the License. - -module.exports = function () { - const nano = require('nano')('http://localhost:5984') - const users = nano.use('users') - const VIEWS = { - by_twitter_id: - { map: 'function(doc) { emit(doc.twitter.screen_name, doc); }' } - } - - /***************************************************************************** - * user.get() - ****************************************************************************/ - function userGet (id, callback) { - return users.get(id, callback) - } - - /***************************************************************************** - * user.new() - ****************************************************************************/ - function userNew (id, body, callback) { - return users.insert(body, id, callback) - } - - /***************************************************************************** - * user.create() - ****************************************************************************/ - function createUsersDatabase (emailAddress, secret, name, retries) { - nano.db.create('users', function (e, b, h) { - userCreate(emailAddress, secret, name, retries + 1) - }) - } - - function userCreate (emailAddress, secret, name, retries) { - if (!retries) { - retries = 0 - } - users.insert({ emailAddress, secret, name }, secret, - function (e, b, h) { - if (e && e.message === 'no_db_file' && retries < 1) { - return createUsersDatabase(emailAddress, secret, name, retries) - } - (function () { })(e, b, h) - }) - } - - /***************************************************************************** - * user.find() - ****************************************************************************/ - // - // some more logic needed - // what if design document exists but view doesnt, we cant just overwrite it - // - // we need a way to fectch and build on - // and thats the reason why im not doing this at 5am - - function userFind (view, id, opts, tried, callback) { - if (typeof tried === 'function') { - callback = tried - tried = { tried: 0, max_retries: 2 } - } - users.view('users', view, opts, function (e, b, h) { - if (e) { - const currentView = VIEWS[view] - if (!currentView) { - e.message = 'View is not available' - return callback(e, b, h) - } - if (tried.tried < tried.max_retries) { - if (e.message === 'missing' || e.message === 'deleted') { // create design document - const designDoc = { views: {} } - designDoc.views[view] = currentView - return users.insert(designDoc, '_design/users', function () { - tried.tried += 1 - userFind(view, id, opts, tried, callback) - }) - } - if (e.message === 'missing_named_view') { - users.get('_design/users', function (e, b, h) { // create view - tried.tried += 1 - if (e) { return userFind(view, id, opts, tried, callback) } - b.views[view] = currentView - users.insert(b, '_design/users', function (e, b, h) { - return userFind(view, id, opts, tried, callback) - }) - }) - return - } - } else { return callback(e, b, h) } - } - return callback(null, b, h) - }) - } - - function userFirst (view, id, callback) { - return userFind(view, id, { startkey: ('"' + id + '"'), limit: 1 }, callback) - } - - return { - new: userNew, - get: userGet, - create: userCreate, - first: userFirst - } -} diff --git a/examples/lazy_db_creation_and_replication.js b/examples/lazy_db_creation_and_replication.js deleted file mode 100644 index 98790c83..00000000 --- a/examples/lazy_db_creation_and_replication.js +++ /dev/null @@ -1,65 +0,0 @@ -// Licensed under the Apache License, Version 2.0 (the 'License'); you may not -// use this file except in compliance with the License. You may obtain a copy of -// the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an 'AS IS' BASIS, WITHOUT -// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -// License for the specific language governing permissions and limitations under -// the License. - -const nano = require('nano') -const couch = - { - master: 'http://localhost:5984/landing_m', - replica: 'http://localhost:5984/landing_r' - } - -function insertWithRetry (db, email, retries, callback) { - if (typeof retries === 'function') { - callback = retries - retries = 0 - } - callback = callback || function () {} - db.insert(email, function (err, resp, head) { - if (err) { - if (err.message === 'no_db_file' && retries < 1) { - const dbName = db.config.db - const server = nano(db.config.url) - - server.db.create(dbName, function (err2, resp2, head2) { - if (err2) { return callback(err2, resp2, head2) } - insertWithRetry(db, email, retries + 1, callback) - }) - } else { return callback(err, resp, head) } - } - callback(err, resp, head) - }) -} - -function replicateWithRetry (masterUri, replicaUri, retries, callback) { - if (typeof retries === 'function') { - callback = retries - retries = 0 - } - callback = callback || function () {} - retries = retries || 0 - const master = nano(couch.master) - master.replicate(couch.replica, function (err, resp, head) { - if (err && err.error === 'db_not_found' && retries < 1) { - const replica = nano(couch.replica) - const dbName = replica.config.db - const server = nano(replica.config.url) - - server.db.create(dbName, function (err2, resp2, head2) { - if (err2) { return callback(err2, resp2, head2) } - replicateWithRetry(masterUri, replicaUri, retries + 1, callback) - }) - } - callback(err, resp, head) - }) -} - -module.exports = { insert: insertWithRetry, replicate: replicateWithRetry } diff --git a/examples/pipe.js b/examples/pipe.js deleted file mode 100644 index 54ea484f..00000000 --- a/examples/pipe.js +++ /dev/null @@ -1,25 +0,0 @@ -// Licensed under the Apache License, Version 2.0 (the 'License'); you may not -// use this file except in compliance with the License. You may obtain a copy of -// the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an 'AS IS' BASIS, WITHOUT -// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -// License for the specific language governing permissions and limitations under -// the License. - -const express = require('express') -const nano = require('nano')('http://localhost:5984') -const app = express.createServer() -const dbName = 'test' -const db = nano.use(dbName) - -app.get('/', function (request, response) { - db.attachment.get('new', 'logo.png').pipe(response) -}) - -app.listen(3333) - -module.exports = app diff --git a/examples/readme.md b/examples/readme.md deleted file mode 100644 index 093b7cd5..00000000 --- a/examples/readme.md +++ /dev/null @@ -1,7 +0,0 @@ -# samples - -if you have a sample please feel free to send a pull request. - -also the tests are very concise and helpful. - -i would recommend taking a peek. \ No newline at end of file diff --git a/lib/changesreader.js b/lib/changesreader.js index a79c6567..98ca422f 100644 --- a/lib/changesreader.js +++ b/lib/changesreader.js @@ -1,5 +1,5 @@ const EventEmitter = require('events').EventEmitter -const AbortController = global.AbortController || require('node-abort-controller').AbortController +const AbortController = global.AbortController const stream = require('stream') const EVENT_BATCH = 'batch' const EVENT_CHANGE = 'change' @@ -279,6 +279,9 @@ class ChangesReader { const lin = liner() const cp = changeProcessor(self.ee, self.batchSize) self.request(req) + .on(EVENT_ERROR, (e) => { + self.ee.emit(EVENT_ERROR, e) + }) .pipe(lin) .pipe(cp) .on('finish', (lastSeq) => { @@ -287,9 +290,6 @@ class ChangesReader { self.ee.emit('end', cp.lastSeq) }, 10) }) - .on(EVENT_ERROR, (e) => { - self.ee.emit(EVENT_ERROR, e) - }) return self.ee } diff --git a/lib/nano.d.ts b/lib/nano.d.ts index c8166068..60131cec 100644 --- a/lib/nano.d.ts +++ b/lib/nano.d.ts @@ -1,7 +1,7 @@ /** * @file nano.d.ts * - * Type definitions for nano 6.4 + * Type definitions for nano 11 * * Project: https://github.com/apache/couchdb-nano * @@ -19,6 +19,8 @@ /// import { EventEmitter } from "events"; +import { ConnectionOptions } from "tls"; +import undici from "undici"; /** nano entry function */ declare function nano( @@ -26,19 +28,62 @@ declare function nano( ): nano.ServerScope; declare namespace nano { - /** RequestDefaults.auth options */ - interface RequestDefaultOptionsAuth { - username: string, - password: string - } - - /** RequestDefaults options */ - interface RequestDefaultsOptions { - timeout?: number; - agent?: any; - headers?: object; - auth?: RequestDefaultOptionsAuth; - jar?: boolean; + /** AgentOptionsConnect options */ + interface AgentOptionsConnect extends ConnectionOptions { + /** An IPC endpoint, either Unix domain socket or Windows named pipe. + * Default: null */ + socketPath: string, + /** Maximum number of TLS cached sessions. Use 0 to disable TLS session + * caching. Default: 100 */ + maxCachedSessions: number, + /** Connection timeout in ms. Default: 10000 */ + timeout?: number, + /** Default: null */ + servername: string + } + /** AgentOptions options */ + interface AgentOptions { + /** The timeout after which a request will time out, in milliseconds. + * Monitors time between receiving body data. Use 0 to disable it entirely. + * Default: 30000 */ + bodyTimeout?: number, + /** The amount of time the parser will wait to receive the complete + * HTTP headers while not sending the request. Default: 30000 */ + headersTimeout?: number, + /** The maximum allowed keepAliveTimeout in ms when overridden by keep-alive hints + * from the server. Default: 600000 */ + keepAliveMaxTimeout?: number, + /** The timeout in ms after which a socket without active requests will time out. + * Monitors time between activity on a connected socket. This value may be + * overridden by keep-alive hints from the server. Default: 4000 */ + keepAliveTimeout?: number, + /** A number subtracted from server keep-alive hints when overriding + * keepAliveTimeout to account for timing inaccuracies caused by + * e.g. transport latency. Default: 1000 */ + keepAliveTimeoutThreshold?: number, + /** The maximum length of request headers in bytes. Default: 16384 */ + maxHeaderSize?: number, + /** The maximum length of response body in bytes. Set to -1 to disable. Default: -1 */ + maxResponseSize?: number, + /** The amount of concurrent requests to be sent over the single TCP/TLS + * connection according to RFC7230. Carefully consider your workload and + * environment before enabling concurrent requests as pipelining may reduce + * performance if used incorrectly. Pipelining is sensitive to network stack + * settings as well as head of line blocking caused by e.g. long running r + * equests. Set to 0 to disable keep-alive connections. Default: 1 */ + pipelining?: number, + /** Connection options */ + connect?: AgentOptionsConnect, + /** Whether to treat request content length mismatches as errors. If true, + * an error is thrown when the request content-length header doesn't match + * the length of the request body. Default: true */ + strictContentLength?: boolean, + /** The number of Client instances to create. + * When set to null, the Pool instance will create an unlimited amount + * of Client instances. */ + connections: null, + /** The number of HTTP redirection to follow - Default: 0 */ + maxRedirections?: null } /** Nano configuration */ @@ -49,10 +94,10 @@ declare namespace nano { url: string; /** For cookie authentication */ cookie?: string; - /** HTTP request options + /** HTTP Agent options * @see README: {@link https://www.npmjs.com/package/nano#pool-size-and-open-sockets} */ - requestDefaults?: RequestDefaultsOptions; + agentOptions?: AgentOptions | typeof undici.Agent | typeof undici.MockAgent | typeof undici.Dispatcher; /** Logging function * @see README: {@link https://www.npmjs.com/package/nano#logging} */ @@ -63,8 +108,6 @@ declare namespace nano { parseUrl?: boolean; } - type Callback = (error: RequestError | null, response: R, headers?: any) => void; - /** An error triggered by nano */ interface RequestError extends Error { /** An error code. */ @@ -109,44 +152,44 @@ declare namespace nano { scope(db: string): DocumentScope; /** * Initiates a custom request - * @see README: {@link https://www.npmjs.com/package/nano#nanorequestopts-callback} + * @see README: {@link https://www.npmjs.com/package/nano#nanorequestopts} **/ - request(opts: RequestOptions | string, callback?: Callback): Promise; + request(opts: RequestOptions | string): Promise; /** * Initiates a custom request - * @see README: {@link https://www.npmjs.com/package/nano#nanorequestopts-callback} + * @see README: {@link https://www.npmjs.com/package/nano#nanorequestopts} **/ - relax(opts: RequestOptions | string, callback?: Callback): Promise; + relax(opts: RequestOptions | string): Promise; /** * Initiates a custom request - * @see README: {@link https://www.npmjs.com/package/nano#nanorequestopts-callback} + * @see README: {@link https://www.npmjs.com/package/nano#nanorequestopts} **/ - dinosaur(opts: RequestOptions | string, callback?: Callback): Promise; + dinosaur(opts: RequestOptions | string): Promise; /** * Initiates new session for specified user credentials by providing Cookie value. * @see Docs: {@link http://docs.couchdb.org/en/latest/api/server/authn.html#cookie-authentication} */ - auth(username: string, userpass: string, callback?: Callback): Promise; + auth(username: string, userpass: string): Promise; /** * Returns information about the authenticated user, including a User Context Object, the authentication method and database that were used, and a list of configured authentication handlers on the server. * @see Docs: {@link http://docs.couchdb.org/en/latest/api/server/authn.html#get--_session} */ - session(callback?: Callback): Promise; + session(): Promise; /** * Returns a list of all database events in the CouchDB instance. * @see Docs: {@link http://docs.couchdb.org/en/latest/api/server/common.html#get--_db_updates} */ - updates(callback?: Callback): Promise; + updates(): Promise; /** * Returns a list of all database events in the CouchDB instance. * @see Docs: {@link http://docs.couchdb.org/en/latest/api/server/common.html#get--_db_updates} */ - updates(params: UpdatesParams, callback?: Callback): Promise; + updates(params: UpdatesParams): Promise; /** * Requests one or more Universally Unique Identifiers (UUIDs) from the CouchDB instance. * @see Docs: {@link https://docs.couchdb.org/en/stable/api/server/common.html#uuids} */ - uuids(num?: number, callback?: Callback): Promise; + uuids(num?: number): Promise; /** * Accessing the root of a CouchDB instance returns meta information about the instance. * @see Docs: {@link https://docs.couchdb.org/en/stable/api/server/common.html#api-server-root} */ - info(callback?: Callback): Promise; + info(): Promise; } interface UUIDObject { @@ -177,23 +220,23 @@ declare namespace nano { /** Database scope */ interface DatabaseScope { replication: { - enable(source: string, target: string, opts0: object, callback0?: Callback): Promise; - disable(id:string, rev: string, opts0: object, callback0?: Callback): Promise; - query(id: string, opts0: object, callback0?: Callback): Promise; + enable(source: string, target: string, opts: object): Promise; + disable(id:string, rev: string, opts: object): Promise; + query(id: string, opts: object): Promise; }; /** * Create database. * @see Docs: {@link http://docs.couchdb.org/en/latest/api/database/common.html#put--db} */ - create(name: string, params?: DatabaseCreateParams, callback?: Callback): Promise; + create(name: string, params?: DatabaseCreateParams): Promise; /** Get database information. * @see Docs: {@link http://docs.couchdb.org/en/latest/api/database/common.html#get--db} */ - get(name: string, callback?: Callback): Promise; + get(name: string): Promise; /** Delete database. * @see Docs: {@link http://docs.couchdb.org/en/latest/api/database/common.html#delete--db} */ - destroy(name: string, callback?: Callback): Promise; + destroy(name: string): Promise; /** List databases. * @see Docs: {@link http://docs.couchdb.org/en/latest/api/server/common.html#get--_all_dbs} */ - list(callback?: Callback): Promise; + list(): Promise; /** List databases as a stream. * @see Docs: {@link http://docs.couchdb.org/en/latest/api/server/common.html#get--_all_dbs} */ listAsStream(): NodeJS.ReadStream; @@ -202,31 +245,29 @@ declare namespace nano { use(db: string): DocumentScope; /** Request compaction on a database. * @see Docs: {@link https://docs.couchdb.org/en/stable/api/database/compact.html} */ - compact(name: string, callback?: Callback): Promise; + compact(name: string): Promise; /** Request compaction of a database's view indexes. * @see Docs: {@link https://docs.couchdb.org/en/stable/api/database/compact.html} */ - compact(name: string, designname: string, callback?: Callback): Promise; + compact(name: string, designname: string): Promise; /** Request a replication operation. * @see Docs: {@link http://docs.couchdb.org/en/latest/api/server/common.html#post--_replicate} */ replicate( source: string | DocumentScope, - target: string | DocumentScope, - callback?: Callback + target: string | DocumentScope ): Promise; /** Reqiest a replication * @see Docs: {@link http://docs.couchdb.org/en/latest/api/server/common.html#post--_replicate} */ replicate( source: string | DocumentScope, target: string | DocumentScope, - options: DatabaseReplicateOptions, - callback?: Callback + options: DatabaseReplicateOptions ): Promise; /** Return sorted list of changes to a database. * @see Docs: {@link http://docs.couchdb.org/en/latest/api/database/changes.html#get--db-_changes} */ - changes(name: string, callback?: Callback): Promise; + changes(name: string): Promise; /** Return sorted list of changes to a database with options. * @see Docs: {@link http://docs.couchdb.org/en/latest/api/database/compact.html#post--db-_compact} */ - changes(name: string, params: DatabaseChangesParams, callback?: Callback): Promise; + changes(name: string, params: DatabaseChangesParams): Promise; /** Return sorted list of changes to a database as a stream. * @see Docs: {@link http://docs.couchdb.org/en/latest/api/database/changes.html#get--db-_changes} */ changesAsStream(name: string): NodeJS.ReadStream; @@ -235,10 +276,10 @@ declare namespace nano { changesAsStream(name: string, params: DatabaseChangesParams): NodeJS.ReadStream; /** Return a list of all database events. * @see Docs: {@link http://docs.couchdb.org/en/latest/api/server/common.html#get--_db_updates} */ - updates(callback?: Callback): Promise; + updates(): Promise; /** Return a list of all database event with options * @see Docs: {@link http://docs.couchdb.org/en/latest/api/server/common.html#get--_db_updates} */ - updates(params: UpdatesParams, callback?: Callback): Promise; + updates(params: UpdatesParams): Promise; } /** ChangesReader options */ @@ -285,75 +326,70 @@ declare namespace nano { readonly config: ServerConfig; /** Get database info * @see Docs: {@link http://docs.couchdb.org/en/latest/api/database/common.html#get--db} */ - info(callback?: Callback): Promise; + info(): Promise; /** Request a replication opertation with this datbase as the target. * @see Docs: {@link http://docs.couchdb.org/en/latest/api/server/common.html#post--_replicate} */ - replicate( - target: string | DocumentScope, - callback?: Callback - ): Promise; + replicate(target: string | DocumentScope): Promise; /** Request a replication opertation with this datbase as the target with options. * @see Docs: {@link http://docs.couchdb.org/en/latest/api/server/common.html#post--_replicate} */ replicate( target: string | DocumentScope, - options: any, - callback?: Callback + options: any ): Promise; /** Request compaction on this database. * @see Docs: {@link http://docs.couchdb.org/en/latest/api/database/compact.html#post--db-_compact} */ - compact(callback?: Callback): Promise; + compact(): Promise; /** Return sorted list of changes to this database. * @see Docs: {@link http://docs.couchdb.org/en/latest/api/database/changes.html#get--db-_changes} */ - changes(callback?: Callback): Promise; + changes(): Promise; /** Return sorted list of changes to this database with options. * @see Docs: {@link http://docs.couchdb.org/en/latest/api/database/changes.html#get--db-_changes} */ - changes(params: DatabaseChangesParams, callback?: Callback): Promise; + changes(params: DatabaseChangesParams): Promise; /** Changes feed follower. * @see README: {@link https://www.npmjs.com/package/nano#reading-changes-feed} */ changesReader: ChangesReaderScope; /** Initiates new session for specified user credentials by providing Cookie value. * @see Docs: {@link http://docs.couchdb.org/en/latest/api/server/authn.html#cookie-authentication} */ - auth(username: string, userpass: string, callback?: Callback): Promise; + auth(username: string, userpass: string): Promise; /** Returns information about the authenticated user, including a User Context Object, the authentication method and database that were used, and a list of configured authentication handlers on the server. * @see Docs: {@link http://docs.couchdb.org/en/latest/api/server/authn.html#get--_session} */ - session(callback?: Callback): Promise; + session(): Promise; /** Insert a document into this database. * @see POST Docs: {@link http://docs.couchdb.org/en/latest/api/database/common.html#post--db} * @see PUT Docs: {@link http://docs.couchdb.org/en/latest/api/document/common.html#put--db-docid} */ - insert(document: ViewDocument | D & MaybeDocument, callback?: Callback): Promise; + insert(document: ViewDocument | D & MaybeDocument): Promise; /** * Insert a document into this database with options. * @see POST Docs: {@link http://docs.couchdb.org/en/latest/api/database/common.html#post--db} * @see PUT Docs: {@link http://docs.couchdb.org/en/latest/api/document/common.html#put--db-docid} */ insert( document: ViewDocument | D & MaybeDocument, - params: DocumentInsertParams | string | null, - callback?: Callback + params: DocumentInsertParams | string | null ): Promise; /** Fetch a document from this database. * @see Docs: {@link http://docs.couchdb.org/en/latest/api/document/common.html#get--db-docid} */ - get(docname: string, callback?: Callback): Promise; + get(docname: string): Promise; /** Fetch a document from this database with options. * @see Docs: {@link http://docs.couchdb.org/en/latest/api/document/common.html#get--db-docid} */ - get(docname: string, params?: DocumentGetParams, callback?: Callback): Promise; + get(docname: string, params?: DocumentGetParams): Promise; /** Fetch document meta data, useful for fetching a document's current revision. * @see Docs: {@link http://docs.couchdb.org/en/latest/api/document/common.html#head--db-docid} */ - head(docname: string, callback?: Callback): Promise; + head(docname: string): Promise; /** Delete a document from this database. * @see Docs: {@link http://docs.couchdb.org/en/latest/api/document/common.html#delete--db-docid} */ - destroy(docname: string, rev: string, callback?: Callback): Promise; + destroy(docname: string, rev: string): Promise; /** Bulk insert/update/delete multiple documents in this database. * @see Docs: {@link https://docs.couchdb.org/en/stable/api/database/bulk-api.html#db-bulk-docs} */ - bulk(docs: BulkModifyDocsWrapper, callback?: Callback): Promise; + bulk(docs: BulkModifyDocsWrapper): Promise; /** Bulk insert/update/delete multiple documents in this database, with options. * @see Docs: {@link https://docs.couchdb.org/en/stable/api/database/bulk-api.html#db-bulk-docs} */ - bulk(docs: BulkModifyDocsWrapper, params: any, callback?: Callback): Promise; + bulk(docs: BulkModifyDocsWrapper, params: any): Promise; /** List documents from this database. * @see Docs: {@link http://docs.couchdb.org/en/latest/api/database/bulk-api.html#get--db-_all_docs} */ - list(callback?: Callback>): Promise>; + list(): Promise>; /** List documents from this database with options. * @see Docs: {@link http://docs.couchdb.org/en/latest/api/database/bulk-api.html#get--db-_all_docs} */ - list(params: DocumentListParams, callback?: Callback>): Promise>; + list(params: DocumentListParams): Promise>; /** List document from this database as a stream. * @see Docs: {@link http://docs.couchdb.org/en/latest/api/database/bulk-api.html#get--db-_all_docs} */ listAsStream(): NodeJS.ReadStream; @@ -362,29 +398,25 @@ declare namespace nano { listAsStream(params: DocumentListParams): NodeJS.ReadStream; /** Fetch a list of documents by _id. * @see Docs: {@link http://docs.couchdb.org/en/latest/api/database/bulk-api.html#post--db-_all_docs} */ - fetch(docnames: BulkFetchDocsWrapper, callback?: Callback>): Promise>; + fetch(docnames: BulkFetchDocsWrapper): Promise>; /** Fetch a list of documents by _id with options. * @see Docs: {@link http://docs.couchdb.org/en/latest/api/database/bulk-api.html#post--db-_all_docs} */ fetch( docnames: BulkFetchDocsWrapper, - params: DocumentFetchParams, - callback?: Callback> + params: DocumentFetchParams ): Promise>; /** Fetch revisions of a list of document _ids. * @see Docs: {@link http://docs.couchdb.org/en/latest/api/database/bulk-api.html#post--db-_all_docs} */ - fetchRevs(docnames: BulkFetchDocsWrapper, callback?: Callback>): Promise>; + fetchRevs(docnames: BulkFetchDocsWrapper): Promise>; /** Fetch revisions of a list of document _ids with options. * @see Docs: {@link http://docs.couchdb.org/en/latest/api/database/bulk-api.html#post--db-_all_docs} */ fetchRevs( docnames: BulkFetchDocsWrapper, - params: DocumentFetchParams, - callback?: Callback> + params: DocumentFetchParams ): Promise>; /** Create a Mango index. * @see Docs: {@link http://docs.couchdb.org/en/latest/api/database/find.html#db-index} */ - createIndex(indexDef: CreateIndexRequest, - callback?: Callback - ): Promise; + createIndex(indexDef: CreateIndexRequest): Promise; /** Multipart HTTP functions */ multipart: Multipart; /** Attachment functions */ @@ -394,8 +426,7 @@ declare namespace nano { show( designname: string, showname: string, - doc_id: string, - callback?: Callback + doc_id: string ): Promise; /** Apply a show function to a document. * @see Docs: {@link http://docs.couchdb.org/en/latest/api/ddoc/render.html#get--db-_design-ddoc-_show-func} */ @@ -403,16 +434,14 @@ declare namespace nano { designname: string, showname: string, doc_id: string, - params: any, - callback?: Callback + params: any ): Promise; /** Executes an update function on the server side for the supplied document id. * @see Docs: {@link http://docs.couchdb.org/en/latest/api/ddoc/render.html#put--db-_design-ddoc-_update-func-docid} */ atomic( designname: string, updatename: string, - docname: string, - callback?: Callback + docname: string ): Promise; /** Executes an update function on the server side for the supplied document id with body. * @see Docs: {@link http://docs.couchdb.org/en/latest/api/ddoc/render.html#put--db-_design-ddoc-_update-func-docid} */ @@ -420,16 +449,14 @@ declare namespace nano { designname: string, updatename: string, docname: string, - body: any, - callback?: Callback + body: any ): Promise; /** Executes an update function on the server side for the supplied document id. * @see Docs: {@link http://docs.couchdb.org/en/latest/api/ddoc/render.html#put--db-_design-ddoc-_update-func-docid} */ updateWithHandler( designname: string, updatename: string, - docname: string, - callback?: Callback + docname: string ): Promise; /** Executes an update function on the server side for the supplied document id with body. * @see Docs: {@link http://docs.couchdb.org/en/latest/api/ddoc/render.html#put--db-_design-ddoc-_update-func-docid} */ @@ -437,16 +464,14 @@ declare namespace nano { designname: string, updatename: string, docname: string, - body: any, - callback?: Callback + body: any ): Promise; /** Executes a search request against the named index. * @see Docs: {@link https://docs.couchdb.org/en/latest/api/ddoc/search.html#db-design-design-doc-search-index-name} */ search( designname: string, searchname: string, - params: DocumentSearchParams, - callback?: Callback> + params: DocumentSearchParams ): Promise>; /** Executes a search request against the named index as a stream. * @see Docs: {@link https://docs.couchdb.org/en/latest/api/ddoc/search.html#db-design-design-doc-search-index-name} */ @@ -461,23 +486,20 @@ declare namespace nano { designname: string, viewname: string, meta: any, - params?: any, - callback?: Callback + params?: any ): Promise; /** Executes a view from a Design Document. * @see Docs: {@link http://docs.couchdb.org/en/latest/api/ddoc/views.html#get--db-_design-ddoc-_view-view} */ view( designname: string, - viewname: string, - callback?: Callback> + viewname: string ): Promise>; /** Executes a view from a Design Document, with options. * @see Docs: {@link http://docs.couchdb.org/en/latest/api/ddoc/views.html#get--db-_design-ddoc-_view-view} */ view( designname: string, viewname: string, - params: DocumentViewParams, - callback?: Callback> + params: DocumentViewParams ): Promise>; /** Executes a view from a Design Document as a stream * @see Docs: {@link http://docs.couchdb.org/en/latest/api/ddoc/views.html#get--db-_design-ddoc-_view-view} */ @@ -497,8 +519,7 @@ declare namespace nano { viewWithList( designname: string, viewname: string, - listname: string, - callback?: Callback + listname: string ): Promise; /** Applies a list function to a view with options. * @see Docs: {@link http://docs.couchdb.org/en/latest/api/ddoc/render.html#db-design-design-doc-list-list-name-view-name} */ @@ -506,16 +527,14 @@ declare namespace nano { designname: string, viewname: string, listname: string, - params: DocumentViewParams, - callback?: Callback + params: DocumentViewParams ): Promise; /** Applies a list function to a view as a stream. * @see Docs: {@link http://docs.couchdb.org/en/latest/api/ddoc/render.html#db-design-design-doc-list-list-name-view-name} */ viewWithListAsStream( designname: string, viewname: string, - listname: string, - callback?: Callback + listname: string ): NodeJS.ReadStream; /** Applies a list function to a view with options as a stream. * @see Docs: {@link http://docs.couchdb.org/en/latest/api/ddoc/render.html#db-design-design-doc-list-list-name-view-name} */ @@ -523,26 +542,25 @@ declare namespace nano { designname: string, viewname: string, listname: string, - params: DocumentViewParams, - callback?: Callback + params: DocumentViewParams ): NodeJS.ReadStream; /** Run Mango query. * @see Docs: {@link http://docs.couchdb.org/en/latest/api/database/find.html#db-find} */ - find(query: MangoQuery, callback?: Callback>): Promise >; + find(query: MangoQuery): Promise >; /** Server scope */ server: ServerScope; /** Fetch information about a single partition in this database. * @see Docs: {@link https://docs.couchdb.org/en/latest/api/partitioned-dbs.html#db-partition-partition} */ - partitionInfo(partitionKey: string, callback?: Callback): Promise ; + partitionInfo(partitionKey: string): Promise ; /** List documents in a single partition in this database. * @see Docs: {@link https://docs.couchdb.org/en/latest/api/partitioned-dbs.html#db-partition-partition-all-docs} */ - partitionedList(partitionKey: string, params?: DocumentFetchParams, callback?: Callback>): Promise>; + partitionedList(partitionKey: string, params?: DocumentFetchParams): Promise>; /** List documents in a single partition in this database as a stream. * @see Docs: {@link https://docs.couchdb.org/en/latest/api/partitioned-dbs.html#db-partition-partition-all-docs} */ partitionedListAsStream(partitionKey: string, params?: DocumentFetchParams): NodeJS.ReadStream; /** Run Mango query a single partition in this database. * @see Docs: {@link https://docs.couchdb.org/en/latest/api/partitioned-dbs.html#db-partition-partition-id-find} */ - partitionedFind(partitionKey: string, query: MangoQuery, callback?: Callback>): Promise >; + partitionedFind(partitionKey: string, query: MangoQuery): Promise >; /** Run Mango query a single partition in this database, as a stream. * @see Docs: {@link https://docs.couchdb.org/en/latest/api/partitioned-dbs.html#db-partition-partition-id-find} */ partitionedFindAsStream(partitionKey: string, query: MangoQuery): NodeJS.ReadStream; @@ -551,8 +569,7 @@ declare namespace nano { partitionKey: string, designname: string, searchname: string, - params: DocumentSearchParams, - callback?: Callback> + params: DocumentSearchParams ): Promise>; /** Run a full-text search in a single partition in this database, as a stream. */ partitionedSearchAsStream( @@ -567,8 +584,7 @@ declare namespace nano { partitionKey: string, designname: string, viewname: string, - params: DocumentViewParams, - callback?: Callback> + params: DocumentViewParams ): Promise>; /** Executes the specified view function in a single partition from the specified design document, as a stream * @see Docs: {@link https://docs.couchdb.org/en/latest/api/partitioned-dbs.html#db-partition-partition-design-design-doc-view-view-name} */ @@ -591,16 +607,16 @@ declare namespace nano { interface Multipart { /** Create doc with multiple attachments using mutlipart HTTP request. * @see Docs: {@link http://docs.couchdb.org/en/latest/api/document/common.html#creating-multiple-attachments} */ - insert(doc: D, attachments: AttachmentData[], callback?: Callback): Promise; + insert(doc: D, attachments: AttachmentData[]): Promise; /** Create doc with multiple attachments using mutlipart HTTP request with options. * @see Docs: {@link http://docs.couchdb.org/en/latest/api/document/common.html#creating-multiple-attachments} */ - insert(doc: D, attachments: AttachmentData[], params: any, callback?: Callback): Promise; + insert(doc: D, attachments: AttachmentData[], params: any): Promise; /** Fetch document and its attachments as a multipart HTTP request. * @see Docs: {@link https://docs.couchdb.org/en/latest/api/document/common.html#efficient-multiple-attachments-retrieving} */ - get(docname: string, callback?: Callback): Promise; + get(docname: string): Promise; /** Fetch document and its attachments as a multipart HTTP request with options. * @see Docs: {@link https://docs.couchdb.org/en/latest/api/document/common.html#efficient-multiple-attachments-retrieving} */ - get(docname: string, params: any, callback?: Callback): Promise; + get(docname: string, params: any): Promise; } /** Attachment functions */ @@ -611,8 +627,7 @@ declare namespace nano { docname: string, attname: string, att: any, - contenttype: string, - callback?: Callback + contenttype: string ): Promise; /** Insert an attachment with options. * @see Docs: {@link https://docs.couchdb.org/en/latest/api/document/attachments.html#put--db-docid-attname} */ @@ -621,12 +636,11 @@ declare namespace nano { attname: string, att: any, contenttype: string, - params: any, - callback?: Callback + params: any ): Promise; /** Get an attachment. * @see Docs: {@link https://docs.couchdb.org/en/latest/api/document/attachments.html#get--db-docid-attname} */ - get(docname: string, attname: string, callback?: Callback): Promise; + get(docname: string, attname: string): Promise; /** Get an attachment as a stream. * @see Docs: {@link https://docs.couchdb.org/en/latest/api/document/attachments.html#get--db-docid-attname} */ getAsStream(docname: string, attname: string): NodeJS.ReadStream; @@ -635,19 +649,17 @@ declare namespace nano { get( docname: string, attname: string, - params: any, - callback?: Callback + params: any ): Promise; /** Delete an attachment. * @see Docs: {@link https://docs.couchdb.org/en/latest/api/document/attachments.html#delete--db-docid-attname} */ - destroy(docname: string, attname: string, callback?: Callback): Promise; + destroy(docname: string, attname: string): Promise; /** Delete an attachment with options. * @see Docs: {@link https://docs.couchdb.org/en/latest/api/document/attachments.html#delete--db-docid-attname} */ destroy( docname: string, attname: string, - params: any, - callback?: Callback + params: any ): Promise; } @@ -658,7 +670,7 @@ declare namespace nano { } /** Custom request options - * @see README: {@link https://www.npmjs.com/package/nano#nanorequestopts-callback}*/ + * @see README: {@link https://www.npmjs.com/package/nano#nanorequestopts}*/ interface RequestOptions { db?: string; method?: string; diff --git a/lib/nano.js b/lib/nano.js index d88de731..c76f3e1f 100644 --- a/lib/nano.js +++ b/lib/nano.js @@ -11,51 +11,28 @@ // the License. const { URL } = require('url') -const http = require('http') -const https = require('https') const assert = require('assert') -const querystring = require('qs') -const axios = require('axios') const stream = require('stream') -const pkg = require('../package.json') -const AGENT_DEFAULTS = { keepAlive: true, maxSockets: 50, keepAliveMsecs: 30000 } -const defaultHttpAgent = new http.Agent(AGENT_DEFAULTS) -const defaultHttpsAgent = new https.Agent(AGENT_DEFAULTS) -const SCRUBBED_STR = 'XXXXXX' +const Readable = stream.Readable const ChangesReader = require('./changesreader.js') const CookieJar = require('./cookie.js') const MultiPartFactory = require('./multipart.js') +const pkg = require('../package.json') + +const SCRUBBED_STR = 'XXXXXX' function isEmpty (val) { return val == null || !(Object.keys(val) || val).length } -function getCallback (opts, callback) { - if (typeof opts === 'function') { - callback = opts - opts = {} - } - opts = opts || {} - return { - opts, - callback - } -} - -// feed this any number of arguements, it will return true if +// feed this any number of arguments, it will return true if // any of them are missing (falsey) function missing (...params) { return params.some(param => !param) } -// calls the supplied callback or if not supplied, returns a rejected promise -function callbackOrRejectError (callback, error = new Error('Invalid parameters')) { - if (callback) { - return callback(error, null) - } else { - return Promise.reject(error) - } -} +// the stock error returned when a call has missing or invalid parameters +const invalidParametersError = new Error('Invalid parameters') module.exports = exports = function dbScope (cfg) { let serverScope = {} @@ -69,14 +46,32 @@ module.exports = exports = function dbScope (cfg) { assert.ok(/^https?:/.test(cfg.url), 'url is not valid') cfg = Object.assign({}, cfg) - serverScope.config = cfg - cfg.requestDefaults = cfg.requestDefaults || {} - const dummyLogger = () => {} const log = typeof cfg.log === 'function' ? cfg.log : dummyLogger const parseUrl = 'parseUrl' in cfg ? cfg.parseUrl : true + // pre-parse the URL to extract URL without auth details + cfg.parsedURL = new URL(cfg.url) + cfg.plainURL = `${cfg.parsedURL.origin}${cfg.parsedURL.pathname}` + cfg.headers = cfg.headers || {} + if (cfg.parsedURL.username && cfg.parsedURL.password) { + cfg.headers.Authorization = 'Basic ' + Buffer.from(`${cfg.parsedURL.username}:${cfg.parsedURL.password}`).toString('base64') + } + + // look for agentOptions + if (cfg.agentOptions) { + // if we've been passed a undici.Agent or undici.MockAgent, + // basically anything inherited from undici.Dispatcher, we + // can use it + cfg.agent = cfg.agentOptions + } + + // warn using still using requestDefaults + if (cfg.requestDefaults) { + console.error('WARNING: requestDefaults is no longer supported. See agentOptions.') + } + // create cookieJar for this Nano cfg.cookieJar = new CookieJar() @@ -109,30 +104,21 @@ module.exports = exports = function dbScope (cfg) { if (req.headers.cookie) { req.headers.cookie = 'XXXXXXX' } - if (req.auth) { - if (!cloned) { - req.auth = JSON.parse(JSON.stringify(req.auth)) // clone just auth if not already cloned - } - req.auth.username = SCRUBBED_STR - req.auth.password = SCRUBBED_STR + if (req.headers.Authorization) { + req.headers.Authorization = 'XXXXXXX' } } - const responseHandler = function (response, req, opts, resolve, reject, callback) { - const statusCode = response.status || (response.response && response.response.status) || 500 - if (response.isAxiosError && response.response) { - response = response.response - } - let body = response.data + const responseHandler = async function (response, req, opts, resolve, reject) { + const statusCode = response.status || 500 + let body = response.body response.statusCode = statusCode // cookie parsing if (response.headers) { - const h = response.headers['set-cookie'] - if (h && h.length) { - h.forEach((header) => { - cfg.cookieJar.parse(header, req.url) - }) + const h = response.headers.get('set-cookie') + if (h) { + cfg.cookieJar.parse(h, req.url) } } @@ -140,27 +126,12 @@ module.exports = exports = function dbScope (cfg) { const responseHeaders = Object.assign({ uri: scrubURL(req.url), statusCode - }, response.headers) + }, response.headers ? response.headers : {}) if (!response.status) { - if (axios.isCancel(response)) { - if (resolve) { - resolve('canceled') - } - if (callback) { - callback(null, 'canceled', responseHeaders) - } - return - } - + response.statusText = response.cause.toString() log({ err: 'socket', body, headers: responseHeaders }) if (reject) { - reject(new Error(`error happened in your connection. Reason: ${response.message}`)) - } - if (callback) { - const returnError = new Error(`error happened in your connection. Reason: ${response.message}`) - returnError.scope = 'socket' - returnError.errid = 'request' - callback(returnError) + reject(new Error(`error happened in your connection. Reason: ${response.statusText}`)) } return } @@ -168,29 +139,53 @@ module.exports = exports = function dbScope (cfg) { delete responseHeaders.server delete responseHeaders['content-length'] - /* if (opts.dontParse) { - parsed = body - } else { - try { parsed = JSON.parse(body) } catch (err) { parsed = body } - } */ - if (statusCode >= 200 && statusCode < 400) { - log({ err: null, body, headers: responseHeaders }) - if (resolve) { - resolve(body) + // collect response + const contentType = response.headers.get('content-type') + let retval = '' + // when doing head requests, we return the response headers, not the response body + if (req.method === 'head') { + retval = Object.fromEntries(response.headers) + } else if (contentType === 'application/json') { + try { + retval = await response.json() + } catch { + // do nothing + } + } else if (contentType && (contentType.startsWith('text/') || contentType.startsWith('multipart/related'))) { + retval = await response.text() + } else { + const ab = await response.arrayBuffer() + retval = Buffer.from(ab) } - if (callback) { - callback(null, body, responseHeaders) + + // log + log({ err: null, retval, headers: responseHeaders }) + + // promisey + if (resolve) { + resolve(retval) } return } // cloudant stacktrace + try { + body = await response.json() + } catch (e) { + // if we were expecting a JSON response but didn't get one, set the body to a blank string + // rather than throw an error. This happens when + // - we do HEAD /db/docid + // - or we get a 500 from CouchDB with no body + // In these cases we expect a rejected promise. + body = '' + } + if (typeof body === 'string') { body = { message: body } } - if (!body.message && (body.reason || body.error)) { + if (body && !body.message && (body.reason || body.error)) { body.message = (body.reason || body.error) } @@ -220,24 +215,16 @@ module.exports = exports = function dbScope (cfg) { if (reject) { reject(errors) } - if (callback) { - callback(errors) - } } const streamResponseHandler = function (response, req, stream) { const statusCode = response.status || (response.response && response.response.status) || 500 - if (response.isAxiosError && response.response) { - response = response.response - } const message = response.statusText - scrubRequest(req) - const responseHeaders = Object.assign({ uri: req.url, statusCode - }, response.headers) + }, response.headers ? Object.fromEntries(response.headers) : {}) const error = new Error(message) error.scope = 'couch' @@ -251,128 +238,119 @@ module.exports = exports = function dbScope (cfg) { log({ err: 'couch', body: message, headers: responseHeaders }) - stream.emit('error', error) + setTimeout(() => { + stream.emit('error', error) + }, 10) } - function relax (opts, callback) { + function relax (opts) { if (typeof opts === 'function') { - callback = opts opts = { path: '' } } - if (typeof opts === 'string') { opts = { path: opts } } - if (!opts) { opts = { path: '' } - callback = null } - const qs = Object.assign({}, opts.qs) + // the building blocks of the request + let body, uri + // construct headers object to be passed in the request const headers = { - 'content-type': 'application/json', + // 'content-type': 'application/json', accept: 'application/json', 'user-agent': `${pkg.name}/${pkg.version} (Node.js ${process.version})`, 'Accept-Encoding': 'deflate, gzip' } + Object.assign(headers, cfg.headers ? cfg.headers : {}) + if (!headers['content-type']) { + headers['content-type'] = 'application/json' + } - const req = Object.assign({ - method: (opts.method || 'GET'), - headers, - uri: cfg.url - }, { - ...cfg.requestDefaults, - headers: Object.assign(headers, cfg.requestDefaults && cfg.requestDefaults.headers ? cfg.requestDefaults.headers : {}) - }) + // prevent bugs where people set encoding when piping + if (opts.encoding !== undefined) { + // req.encoding = opts.encoding + delete headers['content-type'] + delete headers.accept + } - // https://github.com/mikeal/request#requestjar - const isJar = opts.jar || cfg.jar || (cfg.requestDefaults && cfg.requestDefaults.jar) + if (opts.contentType) { + headers['content-type'] = opts.contentType + delete headers.accept + } - if (opts.signal) { - req.signal = opts.signal + if (opts.accept) { + headers.accept = opts.accept } - if (isJar) { - req.withCredentials = true + // http://guide.couchdb.org/draft/security.html#cookies + if (cfg.cookie) { + headers['X-CouchDB-WWW-Authenticate'] = 'Cookie' + headers.cookie = cfg.cookie } - // http://wiki.apache.org/couchdb/HTTP_database_API#Naming_and_Addressing - if (opts.db) { - req.uri = urlResolveFix(req.uri, encodeURIComponent(opts.db)) + // form submission + if (opts.form) { + headers['content-type'] = + 'application/x-www-form-urlencoded; charset=utf-8' + body = new URLSearchParams(opts.form) } + // multipart requests if (opts.multipart) { // generate the multipart/related body, header and boundary to // upload multiple binary attachments in one request const mp = new MultiPartFactory(opts.multipart) - opts.contentType = mp.header - req.body = mp.data + headers['content-type'] = mp.header + body = mp.data } - req.headers = Object.assign(req.headers, opts.headers, cfg.defaultHeaders) + // construct the URL + const method = opts.method ? opts.method.toLowerCase() : 'get' + uri = cfg.plainURL + if (opts.db) { + uri = urlResolveFix(uri, encodeURIComponent(opts.db)) + } + // http://wiki.apache.org/couchdb/HTTP_database_API#Naming_and_Addressing if (opts.path) { - req.uri += '/' + opts.path + if (!uri.endsWith('/')) { + uri += '/' + } + uri += opts.path } else if (opts.doc) { if (!/^_design|_local/.test(opts.doc)) { // http://wiki.apache.org/couchdb/HTTP_Document_API#Naming.2FAddressing - req.uri += '/' + encodeURIComponent(opts.doc) + uri += '/' + encodeURIComponent(opts.doc) } else { // http://wiki.apache.org/couchdb/HTTP_Document_API#Document_IDs - req.uri += '/' + opts.doc + uri += '/' + opts.doc } // http://wiki.apache.org/couchdb/HTTP_Document_API#Attachments if (opts.att) { - req.uri += '/' + opts.att + uri += '/' + opts.att } } - // prevent bugs where people set encoding when piping - if (opts.encoding !== undefined) { - req.encoding = opts.encoding - delete req.headers['content-type'] - delete req.headers.accept - } - - if (opts.contentType) { - req.headers['content-type'] = opts.contentType - delete req.headers.accept - } - - if (opts.accept) { - req.headers.accept = opts.accept - } - - // http://guide.couchdb.org/draft/security.html#cookies - if (cfg.cookie) { - req.headers['X-CouchDB-WWW-Authenticate'] = 'Cookie' - req.headers.cookie = cfg.cookie - } - // http://wiki.apache.org/couchdb/HTTP_view_API#Querying_Options - if (typeof opts.qs === 'object' && !isEmpty(opts.qs)) { + const qs = Object.assign({}, opts.qs) + if (typeof qs === 'object' && !isEmpty(qs)) { ['startkey', 'endkey', 'key', 'keys', 'start_key', 'end_key'].forEach(function (key) { - if (key in opts.qs) { - qs[key] = JSON.stringify(opts.qs[key]) + if (key in qs) { + qs[key] = JSON.stringify(qs[key]) } }) - req.qs = qs - } - - // add any cookies for this domain - const cookie = cfg.cookieJar.getCookieString(req.uri) - if (cookie) { - req.headers.cookie = cookie } + // HTTP request body if (opts.body) { if (Buffer.isBuffer(opts.body) || opts.dontStringify) { - req.body = opts.body + body = opts.body } else { - req.body = JSON.stringify(opts.body, function (key, value) { + body = JSON.stringify(opts.body, function (key, value) { // don't encode functions if (typeof (value) === 'function') { return value.toString() @@ -383,85 +361,83 @@ module.exports = exports = function dbScope (cfg) { } } - if (opts.form) { - req.headers['content-type'] = - 'application/x-www-form-urlencoded; charset=utf-8' - req.body = querystring.stringify(opts.form).toString('utf8') - } - - // ask request to render query string arrays as repeated values e.g. - // ?drilldown=["author","Dickens"]&drilldown=["publisher","Penguin"] - req.qsStringifyOptions = { arrayFormat: 'repeat' } - - // This where the HTTP request is made. - // Nano used to use the now-deprecated "request" library but now we're going to - // use axios, so let's modify the "req" object to suit axios - req.url = req.uri - delete req.uri - req.method = req.method.toLowerCase() - req.params = req.qs - delete req.qs - req.paramsSerializer = { - serialize: (params) => querystring.stringify(params, { arrayFormat: 'brackets' }) - } - req.data = req.body - delete req.body - req.maxRedirects = 0 - if (opts.stream) { - req.responseType = 'stream' - } else if (opts.dontParse) { - req.responseType = 'arraybuffer' - } - // scrub and log const scrubbedReq = { - method: req.method, - headers: JSON.parse(JSON.stringify(req.headers)), - url: req.url + method, + headers: JSON.parse(JSON.stringify(headers)), + url: uri } scrubRequest(scrubbedReq, true) log(scrubbedReq) - // add http agents - req.httpAgent = cfg.requestDefaults.agent || defaultHttpAgent - req.httpsAgent = cfg.requestDefaults.agent || defaultHttpsAgent - const ax = axios.create({ - httpAgent: req.httpAgent, - httpsAgent: req.httpsAgent - }) + // insert basic auth headers, if present + Object.assign(headers, cfg.headers) + + // build the options we send to undici.fetch + const fetchOptions = { + url: uri, + method, + headers, + credentials: 'include', + body: method !== 'get' && body ? body : undefined, + redirect: 'error', + signal: opts.signal, + bodyTimeout: 0 + } + + // add custom agent if present + if (cfg.agent) { + fetchOptions.dispatcher = cfg.agent + } + + // add querystring params + const searchParams = new URLSearchParams(qs) + const queryString = searchParams.toString() + if (queryString.length > 0) { + fetchOptions.url += '?' + queryString + } + + // if the body is readable stream + if (fetchOptions.body && fetchOptions.body instanceof stream.Readable) { + fetchOptions.duplex = 'half' + fetchOptions.keepalive = false + } + + // add any cookies for this domain + const cookie = cfg.cookieJar.getCookieString(uri) + if (cookie) { + fetchOptions.headers.cookie = cookie + } // actually do the HTTP request if (opts.stream) { // return the Request object for streaming const outStream = new stream.PassThrough() - ax(req) - .then((response) => { - response.data.pipe(outStream) - }).catch(e => { - streamResponseHandler(e, req, outStream) - }) + fetch(fetchOptions.url, fetchOptions).then((response) => { + const readableWebStream = response.body + const readableNodeStream = Readable.fromWeb ? Readable.fromWeb(readableWebStream) : Readable.from(readableWebStream) + if (response.status > 300) { + streamResponseHandler(response, fetchOptions, outStream) + } else { + readableNodeStream.pipe(outStream) + } + }).catch((e) => { + streamResponseHandler(e, fetchOptions, outStream) + }) return outStream } else { - if (typeof callback === 'function') { - ax(req).then((response) => { - responseHandler(response, req, opts, null, null, callback) + return new Promise((resolve, reject) => { + fetch(fetchOptions.url, fetchOptions).then((response) => { + responseHandler(response, fetchOptions, opts, resolve, reject) }).catch((e) => { - responseHandler(e, req, opts, null, null, callback) - }) - } else { - return new Promise((resolve, reject) => { - ax(req).then((response) => { - responseHandler(response, req, opts, resolve, reject) - }).catch((e) => { - responseHandler(e, req, opts, resolve, reject) - }) + responseHandler(e, fetchOptions, opts, resolve, reject) }) - } + }) } } // http://docs.couchdb.org/en/latest/api/server/authn.html#cookie-authentication - function auth (username, password, callback) { + function auth (username, password) { return relax({ method: 'POST', db: '_session', @@ -469,56 +445,54 @@ module.exports = exports = function dbScope (cfg) { name: username, password } - }, callback) + }) } // http://docs.couchdb.org/en/latest/api/server/authn.html#post--_session - function session (callback) { - return relax({ db: '_session' }, callback) + function session () { + return relax({ db: '_session' }) } // https://docs.couchdb.org/en/latest/api/server/common.html#api-server-root - function info (callback) { - return relax({ path: '' }, callback) + function info () { + return relax({ path: '' }) } // http://docs.couchdb.org/en/latest/api/server/common.html#get--_db_updates - function updates (qs0, callback0) { - const { opts, callback } = getCallback(qs0, callback0) + function updates (qs) { return relax({ db: '_db_updates', - qs: opts - }, callback) + qs + }) } // http://docs.couchdb.org/en/latest/api/database/common.html#put--db - function createDb (dbName, qs0, callback0) { - const { opts, callback } = getCallback(qs0, callback0) + function createDb (dbName, qs) { if (missing(dbName)) { - return callbackOrRejectError(callback) + return Promise.reject(invalidParametersError) } - return relax({ db: dbName, method: 'PUT', qs: opts }, callback) + return relax({ db: dbName, method: 'PUT', qs }) } // http://docs.couchdb.org/en/latest/api/database/common.html#delete--db - function destroyDb (dbName, callback) { + function destroyDb (dbName) { if (missing(dbName)) { - return callbackOrRejectError(callback) + return Promise.reject(invalidParametersError) } - return relax({ db: dbName, method: 'DELETE' }, callback) + return relax({ db: dbName, method: 'DELETE' }) } // http://docs.couchdb.org/en/latest/api/database/common.html#get--db - function getDb (dbName, callback) { + function getDb (dbName) { if (missing(dbName)) { - return callbackOrRejectError(callback) + return Promise.reject(invalidParametersError) } - return relax({ db: dbName }, callback) + return relax({ db: dbName }) } // http://docs.couchdb.org/en/latest/api/server/common.html#get--_all_dbs - function listDbs (callback) { - return relax({ db: '_all_dbs' }, callback) + function listDbs () { + return relax({ db: '_all_dbs' }) } // http://docs.couchdb.org/en/latest/api/server/common.html#get--_all_dbs @@ -527,33 +501,28 @@ module.exports = exports = function dbScope (cfg) { } // http://docs.couchdb.org/en/latest/api/database/compact.html#post--db-_compact - function compactDb (dbName, ddoc, callback) { - if (typeof ddoc === 'function') { - callback = ddoc - ddoc = null - } + function compactDb (dbName, ddoc) { if (missing(dbName)) { - return callbackOrRejectError(callback) + return Promise.reject(invalidParametersError) } return relax({ db: dbName, doc: '_compact', att: ddoc, method: 'POST' - }, callback) + }) } // http://docs.couchdb.org/en/latest/api/database/changes.html#get--db-_changes - function changesDb (dbName, qs0, callback0) { - const { opts, callback } = getCallback(qs0, callback0) + function changesDb (dbName, qs) { if (missing(dbName)) { - return callbackOrRejectError(callback) + return Promise.reject(invalidParametersError) } - return relax({ db: dbName, path: '_changes', qs: opts }, callback) + return relax({ db: dbName, path: '_changes', qs }) } - function changesDbAsStream (dbName, opts) { - return relax({ db: dbName, path: '_changes', stream: true, qs: opts }) + function changesDbAsStream (dbName, qs) { + return relax({ db: dbName, path: '_changes', stream: true, qs }) } function _serializeAsUrl (db) { @@ -572,67 +541,61 @@ module.exports = exports = function dbScope (cfg) { } // http://docs.couchdb.org/en/latest/api/server/common.html#post--_replicate - function replicateDb (source, target, opts0, callback0) { - const { opts, callback } = getCallback(opts0, callback0) - + function replicateDb (source, target, opts) { if (missing(source, target)) { - return callbackOrRejectError(callback) + return Promise.reject(invalidParametersError) } // _replicate + opts = opts || {} opts.source = _serializeAsUrl(source) opts.target = _serializeAsUrl(target) - return relax({ db: '_replicate', body: opts, method: 'POST' }, callback) + return relax({ db: '_replicate', body: opts, method: 'POST' }) } // http://docs.couchdb.org/en/latest/api/server/common.html#uuids - function uuids (count, callback) { - if (typeof count === 'function') { - callback = count - count = 1 - } + function uuids (count) { count = count || 1 - return relax({ method: 'GET', path: '_uuids', qs: { count } }, callback) + return relax({ method: 'GET', path: '_uuids', qs: { count } }) } // http://guide.couchdb.org/draft/replication.html - function enableReplication (source, target, opts0, callback0) { - const { opts, callback } = getCallback(opts0, callback0) + function enableReplication (source, target, opts) { if (missing(source, target)) { - return callbackOrRejectError(callback) + return Promise.reject(invalidParametersError) } // _replicator + opts = opts || {} opts.source = _serializeAsUrl(source) opts.target = _serializeAsUrl(target) - return relax({ db: '_replicator', body: opts, method: 'POST' }, callback) + return relax({ db: '_replicator', body: opts, method: 'POST' }) } // http://guide.couchdb.org/draft/replication.html - function queryReplication (id, opts0, callback0) { - const { opts, callback } = getCallback(opts0, callback0) + function queryReplication (id, qs) { if (missing(id)) { - return callbackOrRejectError(callback) + return Promise.reject(invalidParametersError) } - return relax({ db: '_replicator', method: 'GET', path: id, qs: opts }, callback) + return relax({ db: '_replicator', method: 'GET', path: id, qs }) } // http://guide.couchdb.org/draft/replication.html - function disableReplication (id, rev, opts0, callback0) { - const { opts, callback } = getCallback(opts0, callback0) + function disableReplication (id, rev, opts) { if (missing(id, rev)) { - return callbackOrRejectError(callback) + return Promise.reject(invalidParametersError) } + opts = opts || {} const req = { db: '_replicator', method: 'DELETE', path: id, qs: Object.assign(opts, { rev }) } - return relax(req, callback) + return relax(req) } function docModule (dbName) { @@ -641,31 +604,29 @@ module.exports = exports = function dbScope (cfg) { // http://docs.couchdb.org/en/latest/api/document/common.html#put--db-docid // http://docs.couchdb.org/en/latest/api/database/common.html#post--db - function insertDoc (doc, qs0, callback0) { + function insertDoc (doc, qs ) { const req = { db: dbName, body: doc, method: 'POST' } - let { opts, callback } = getCallback(qs0, callback0) - - if (typeof opts === 'string') { - opts = { docName: opts } + if (typeof qs === 'string') { + qs = { docName: qs } } - if (opts) { - if (opts.docName) { - req.doc = opts.docName + if (qs) { + if (qs.docName) { + req.doc = qs.docName req.method = 'PUT' - delete opts.docName + delete qs.docName } - req.qs = opts + req.qs = qs } - return relax(req, callback) + return relax(req) } // http://docs.couchdb.org/en/latest/api/document/common.html#delete--db-docid - function destroyDoc (docName, rev, callback) { + function destroyDoc (docName, rev) { if (missing(docName)) { - return callbackOrRejectError(callback) + return Promise.reject(invalidParametersError) } return relax({ @@ -673,72 +634,49 @@ module.exports = exports = function dbScope (cfg) { doc: docName, method: 'DELETE', qs: { rev } - }, callback) + }) } // http://docs.couchdb.org/en/latest/api/document/common.html#get--db-docid - function getDoc (docName, qs0, callback0) { - const { opts, callback } = getCallback(qs0, callback0) - + function getDoc (docName, qs) { if (missing(docName)) { - return callbackOrRejectError(callback) + return Promise.reject(invalidParametersError) } - return relax({ db: dbName, doc: docName, qs: opts }, callback) + return relax({ db: dbName, doc: docName, qs }) } // http://docs.couchdb.org/en/latest/api/document/common.html#head--db-docid - function headDoc (docName, callback) { + function headDoc (docName) { if (missing(docName)) { - return callbackOrRejectError(callback) - } - if (callback) { - relax({ - db: dbName, - doc: docName, - method: 'HEAD', - qs: {} - }, callback) - } else { - // this function doesn't pass on the Promise from relax because it needs - // to return the headers when resolving the Promise - return new Promise(function (resolve, reject) { - relax({ - db: dbName, - doc: docName, - method: 'HEAD', - qs: {} - }, function (err, body, headers) { - if (err) { - reject(err) - } else { - resolve(headers) - } - }) - }) + return Promise.reject(invalidParametersError) } + return relax({ + db: dbName, + doc: docName, + method: 'HEAD' + }) } // http://docs.couchdb.org/en/latest/api/database/bulk-api.html#get--db-_all_docs - function listDoc (qs0, callback0) { - const { opts, callback } = getCallback(qs0, callback0) - return relax({ db: dbName, path: '_all_docs', qs: opts }, callback) + function listDoc (qs) { + return relax({ db: dbName, path: '_all_docs', qs }) } // http://docs.couchdb.org/en/latest/api/database/bulk-api.html#get--db-_all_docs - function listDocAsStream (opts) { - return relax({ db: dbName, path: '_all_docs', qs: opts, stream: true }) + function listDocAsStream (qs) { + return relax({ db: dbName, path: '_all_docs', qs, stream: true }) } // http://docs.couchdb.org/en/latest/api/database/bulk-api.html#post--db-_all_docs - function fetchDocs (docNames, qs0, callback0) { - const { opts, callback } = getCallback(qs0, callback0) + function fetchDocs (docNames, qs) { + const opts = qs || {} opts.include_docs = true if (missing(docNames) || typeof docNames !== 'object' || !docNames.keys || !Array.isArray(docNames.keys) || docNames.keys.length === 0) { - return callbackOrRejectError(callback) + return Promise.reject(invalidParametersError) } return relax({ @@ -747,32 +685,29 @@ module.exports = exports = function dbScope (cfg) { method: 'POST', qs: opts, body: docNames - }, callback) + }) } - function fetchRevs (docNames, qs0, callback0) { - const { opts, callback } = getCallback(qs0, callback0) + function fetchRevs (docNames, qs) { if (missing(docNames) || typeof docNames !== 'object' || !docNames.keys || !Array.isArray(docNames.keys) || docNames.keys.length === 0) { - return callbackOrRejectError(callback) + return Promise.reject(invalidParametersError) } return relax({ db: dbName, path: '_all_docs', method: 'POST', - qs: opts, + qs, body: docNames - }, callback) + }) } - function view (ddoc, viewName, meta, qs0, callback0) { - const { opts, callback } = getCallback(qs0, callback0) - + function view (ddoc, viewName, meta, qs) { if (missing(ddoc, viewName) && !meta.viewPath) { - return callbackOrRejectError(callback) + return Promise.reject(invalidParametersError) } if (typeof meta.stream !== 'boolean') { @@ -780,7 +715,7 @@ module.exports = exports = function dbScope (cfg) { } // prevent mutation of the client qs object by using a clone - const qs1 = Object.assign({}, opts) + const qs1 = Object.assign({}, qs) const viewPath = meta.viewPath || '_design/' + ddoc + '/_' + meta.type + '/' + viewName @@ -792,7 +727,7 @@ module.exports = exports = function dbScope (cfg) { method: 'POST', body: qs1, stream: meta.stream - }, callback) + }) } else if (qs1 && qs1.keys) { const body = { keys: qs1.keys } delete qs1.keys @@ -803,7 +738,7 @@ module.exports = exports = function dbScope (cfg) { qs: qs1, body, stream: meta.stream - }, callback) + }) } else if (qs1 && qs1.queries) { const body = { queries: qs1.queries } delete qs1.queries @@ -813,7 +748,7 @@ module.exports = exports = function dbScope (cfg) { method: 'POST', qs: qs1, body - }, callback) + }) } else { const req = { db: dbName, @@ -827,13 +762,13 @@ module.exports = exports = function dbScope (cfg) { req.body = meta.body } - return relax(req, callback) + return relax(req) } } // http://docs.couchdb.org/en/latest/api/ddoc/views.html#post--db-_design-ddoc-_view-view - function viewDocs (ddoc, viewName, qs, callback) { - return view(ddoc, viewName, { type: 'view' }, qs, callback) + function viewDocs (ddoc, viewName, qs) { + return view(ddoc, viewName, { type: 'view' }, qs) } // http://docs.couchdb.org/en/latest/api/ddoc/views.html#post--db-_design-ddoc-_view-view @@ -842,8 +777,8 @@ module.exports = exports = function dbScope (cfg) { } // cloudant - function viewSearch (ddoc, viewName, qs, callback) { - return view(ddoc, viewName, { type: 'search' }, qs, callback) + function viewSearch (ddoc, viewName, qs) { + return view(ddoc, viewName, { type: 'search' }, qs) } // cloudant @@ -852,56 +787,52 @@ module.exports = exports = function dbScope (cfg) { } // http://docs.couchdb.org/en/latest/api/ddoc/render.html#get--db-_design-ddoc-_show-func - function showDoc (ddoc, viewName, docName, qs, callback) { + function showDoc (ddoc, viewName, docName, qs) { if (missing(ddoc, viewName, docName)) { - return callbackOrRejectError(callback) + return Promise.reject(invalidParametersError) } - return view(ddoc, viewName + '/' + docName, { type: 'show' }, qs, callback) + return view(ddoc, viewName + '/' + docName, { type: 'show' }, qs) } // http://docs.couchdb.org/en/latest/api/ddoc/render.html#put--db-_design-ddoc-_update-func-docid - function updateWithHandler (ddoc, viewName, docName, body, callback) { - if (typeof body === 'function') { - callback = body - body = undefined - } + function updateWithHandler (ddoc, viewName, docName, body) { if (missing(ddoc, viewName, docName)) { - return callbackOrRejectError(callback) + return Promise.reject(invalidParametersError) } return view(ddoc, viewName + '/' + encodeURIComponent(docName), { type: 'update', method: 'PUT', body - }, callback) + }) } - function viewWithList (ddoc, viewName, listName, qs, callback) { + function viewWithList (ddoc, viewName, listName, qs) { return view(ddoc, listName + '/' + viewName, { type: 'list' - }, qs, callback) + }, qs) } - function viewWithListAsStream (ddoc, viewName, listName, qs, callback) { + function viewWithListAsStream (ddoc, viewName, listName, qs) { return view(ddoc, listName + '/' + viewName, { - type: 'list', stream: true - }, qs, callback) + type: 'list', + stream: true + }, qs) } // http://docs.couchdb.org/en/latest/api/database/bulk-api.html#post--db-_bulksDoc - function bulksDoc (docs, qs0, callback0) { - const { opts, callback } = getCallback(qs0, callback0) + function bulksDoc (docs, qs) { return relax({ db: dbName, path: '_bulk_docs', body: docs, method: 'POST', - qs: opts - }, callback) + qs + }) } // http://docs.couchdb.org/en/latest/api/document/common.html#creating-multiple-attachments - function insertMultipart (doc, attachments, qs, callback) { + function insertMultipart (doc, attachments, qs) { if (typeof qs === 'string') { qs = { docName: qs } } @@ -911,7 +842,7 @@ module.exports = exports = function dbScope (cfg) { delete qs.docName if (missing(doc, attachments, docName)) { - return callbackOrRejectError(callback) + return Promise.reject(invalidParametersError) } doc = Object.assign({ _attachments: {} }, doc) @@ -941,15 +872,15 @@ module.exports = exports = function dbScope (cfg) { doc: docName, qs, multipart - }, callback) + }) } - function getMultipart (docName, qs0, callback0) { - const { opts, callback } = getCallback(qs0, callback0) - opts.attachments = true + function getMultipart (docName, qs) { + qs = qs || {} + qs.attachments = true if (missing(docName)) { - return callbackOrRejectError(callback) + return Promise.reject(invalidParametersError) } return relax({ @@ -957,14 +888,13 @@ module.exports = exports = function dbScope (cfg) { doc: docName, encoding: null, accept: 'multipart/related', - qs: opts - }, callback) + qs + }) } - function insertAtt (docName, attName, att, contentType, qs0, callback0) { - const { opts, callback } = getCallback(qs0, callback0) + function insertAtt (docName, attName, att, contentType, qs) { if (missing(docName, attName, att, contentType)) { - return callbackOrRejectError(callback) + return Promise.reject(invalidParametersError) } return relax({ @@ -973,44 +903,43 @@ module.exports = exports = function dbScope (cfg) { method: 'PUT', contentType, doc: docName, - qs: opts, + qs, body: att, dontStringify: true - }, callback) + }) } - function getAtt (docName, attName, qs0, callback0) { - const { opts, callback } = getCallback(qs0, callback0) - + function getAtt (docName, attName, qs) { + if (missing(docName, attName)) { - return callbackOrRejectError(callback) + return Promise.reject(invalidParametersError) } return relax({ db: dbName, att: attName, doc: docName, - qs: opts, + qs, encoding: null, dontParse: true - }, callback) + }) } - function getAttAsStream (docName, attName, opts) { + function getAttAsStream (docName, attName, qs) { return relax({ db: dbName, att: attName, doc: docName, - qs: opts, + qs, stream: true, encoding: null, dontParse: true }) } - function destroyAtt (docName, attName, qs, callback) { + function destroyAtt (docName, attName, qs) { if (missing(docName, attName)) { - return callbackOrRejectError(callback) + return Promise.reject(invalidParametersError) } return relax({ @@ -1019,12 +948,12 @@ module.exports = exports = function dbScope (cfg) { method: 'DELETE', doc: docName, qs - }, callback) + }) } - function find (query, callback) { + function find (query) { if (missing(query) || typeof query !== 'object') { - return callbackOrRejectError(callback) + return Promise.reject(invalidParametersError) } return relax({ @@ -1032,7 +961,7 @@ module.exports = exports = function dbScope (cfg) { path: '_find', method: 'POST', body: query - }, callback) + }) } function findAsStream (query) { @@ -1045,9 +974,9 @@ module.exports = exports = function dbScope (cfg) { }) } - function createIndex (indexDef, callback) { + function createIndex (indexDef) { if (missing(indexDef) || typeof indexDef !== 'object') { - return callbackOrRejectError(callback) + return Promise.reject(invalidParametersError) } return relax({ @@ -1055,30 +984,29 @@ module.exports = exports = function dbScope (cfg) { path: '_index', method: 'POST', body: indexDef - }, callback) + }) } - function partitionInfo (partitionKey, callback) { + function partitionInfo (partitionKey) { if (missing(partitionKey)) { - return callbackOrRejectError(callback) + return Promise.reject(invalidParametersError) } return relax({ db: dbName, path: '_partition/' + encodeURIComponent(partitionKey) - }, callback) + }) } - function partitionedList (partitionKey, qs0, callback0) { - const { opts, callback } = getCallback(qs0, callback0) + function partitionedList (partitionKey, qs) { if (missing(partitionKey)) { - return callbackOrRejectError(callback) + return Promise.reject(invalidParametersError) } return relax({ db: dbName, path: '_partition/' + encodeURIComponent(partitionKey) + '/_all_docs', - qs: opts - }, callback) + qs + }) } function partitionedListAsStream (partitionKey, qs) { @@ -1090,9 +1018,9 @@ module.exports = exports = function dbScope (cfg) { }) } - function partitionedFind (partition, query, callback) { + function partitionedFind (partition, query) { if (missing(partition, query) || typeof query !== 'object') { - return callbackOrRejectError(callback) + return Promise.reject(invalidParametersError) } return relax({ @@ -1100,7 +1028,7 @@ module.exports = exports = function dbScope (cfg) { path: '_partition/' + encodeURIComponent(partition) + '/_find', method: 'POST', body: query - }, callback) + }) } function partitionedFindAsStream (partition, query) { @@ -1113,59 +1041,59 @@ module.exports = exports = function dbScope (cfg) { }) } - function partitionedSearch (partition, ddoc, searchName, opts, callback) { - if (missing(partition, ddoc, searchName, opts) || typeof opts !== 'object') { - return callbackOrRejectError(callback) + function partitionedSearch (partition, ddoc, searchName, qs) { + if (missing(partition, ddoc, searchName, qs) || typeof qs !== 'object') { + return Promise.reject(invalidParametersError) } return relax({ db: dbName, path: '_partition/' + encodeURIComponent(partition) + '/_design/' + ddoc + '/_search/' + searchName, - qs: opts - }, callback) + qs + }) } - function partitionedSearchAsStream (partition, ddoc, searchName, opts) { + function partitionedSearchAsStream (partition, ddoc, searchName, qs) { return relax({ db: dbName, path: '_partition/' + encodeURIComponent(partition) + '/_design/' + ddoc + '/_search/' + searchName, - qs: opts, + qs, stream: true }) } - function partitionedView (partition, ddoc, viewName, opts, callback) { + function partitionedView (partition, ddoc, viewName, qs) { if (missing(partition, ddoc, viewName)) { - return callbackOrRejectError(callback) + return Promise.reject(invalidParametersError) } return relax({ db: dbName, path: '_partition/' + encodeURIComponent(partition) + '/_design/' + ddoc + '/_view/' + viewName, - qs: opts - }, callback) + qs + }) } - function partitionedViewAsStream (partition, ddoc, viewName, opts) { + function partitionedViewAsStream (partition, ddoc, viewName, qs) { return relax({ db: dbName, path: '_partition/' + encodeURIComponent(partition) + '/_design/' + ddoc + '/_view/' + viewName, - qs: opts, + qs, stream: true }) } // db level exports docScope = { - info: function (cb) { - return getDb(dbName, cb) + info: function () { + return getDb(dbName) }, - replicate: function (target, opts, cb) { - return replicateDb(dbName, target, opts, cb) + replicate: function (target, opts) { + return replicateDb(dbName, target, opts) }, - compact: function (cb) { - return compactDb(dbName, cb) + compact: function () { + return compactDb(dbName) }, - changes: function (qs, cb) { - return changesDb(dbName, qs, cb) + changes: function (qs) { + return changesDb(dbName, qs) }, changesAsStream: function (qs) { return changesDbAsStream(dbName, qs) @@ -1208,14 +1136,14 @@ module.exports = exports = function dbScope (cfg) { viewWithListAsStream, server: serverScope, replication: { - enable: function (target, opts, cb) { - return enableReplication(dbName, target, opts, cb) + enable: function (target, opts) { + return enableReplication(dbName, target, opts) }, - disable: function (id, revision, opts, cb) { - return disableReplication(id, revision, opts, cb) + disable: function (id, revision, opts) { + return disableReplication(id, revision, opts) }, - query: function (id, opts, cb) { - return queryReplication(id, opts, cb) + query: function (id, opts) { + return queryReplication(id, opts) } }, partitionInfo, @@ -1229,8 +1157,8 @@ module.exports = exports = function dbScope (cfg) { partitionedViewAsStream } - docScope.view.compact = function (ddoc, cb) { - return compactDb(dbName, ddoc, cb) + docScope.view.compact = function (ddoc) { + return compactDb(dbName, ddoc) } return docScope diff --git a/migration_8_to_9.md b/migration_8_to_9.md deleted file mode 100644 index fb29ee1f..00000000 --- a/migration_8_to_9.md +++ /dev/null @@ -1,43 +0,0 @@ -# Migration Guide for moving from Nano 8.x to 9.x - -The 9.x release of Nano sees the following changes: - -- the underlying library that handles HTTP request changes to [axios](https://www.npmjs.com/package/axios) as the previous library has been deprecated. -- the number of dependencies has been reduced - there are now only two runtime dependencies. -- the changes feed handler has been rewritten and bundled as part of Nano. See "changesReader". -- reworked custom logging. - -Most Nano users will be able to switch from Nano 8.x to Nano 9.x without modifying any code but as this is a major version release, some things have changed which _may_ break your code - pay particular attention if you were using the "Follow" library or had configured custom logging. - -## Following the changes feed - -The changes feed reader is completely rewritten and has a new interface: - -```js -const db = nano.db.use('mydb') -db.changesReader.start({ batchSize: 50 }) - .on('batch', (b) => { - console.log('a batch of', b.length, 'changes has arrived'); - }).on('seq', (s) => { - console.log('sequence token', s); - }).on('error', (e) => { - console.error('error', e); - }) -``` - -## Logging - -```js -const url = require('url') -const logger = (data) => { - // if this is a request - if (typeof data.err === 'undefined') { - const u = new url.URL(data.uri) - console.log(data.method, u.pathname, data.qs) - } else { - // this is a response - const prefix = data.err ? 'ERR' : 'OK' - console.log(prefix, data.headers.statusCode, JSON.stringify(data.body).length) - } -} -const nano = Nano({ url: process.env.COUCH_URL, log: logger }) \ No newline at end of file diff --git a/migration_guide_v10_to_v11.md b/migration_guide_v10_to_v11.md new file mode 100644 index 00000000..bcd7875f --- /dev/null +++ b/migration_guide_v10_to_v11.md @@ -0,0 +1,77 @@ +# Migrating from Nano 10 to Nano 11 + +The highlights: + +- Nano 11's HTTP client is replaced with the native Node.js _fetch_ function meaning that Nano 11 only works on Node.js 18 and above. +- Nano no longer supports `requestDefaults` to configure the client options. +- Nano no longer supports callbacks. + +## Node.js versions + +> ** Nano 11 is a breaking change for users of Node.s 16 or earlier ** + +Nano 10 uses the Axios library as an HTTP/HTTPS client. Keeping up with changes to Axios and its dependencies made maintaining this library a chore, so as of Nano 11 we use Node.js's built-in _fetch_ API as our HTTP client. This makes Nano a _zero dependency_ library which makes for faster installs, easier maintenance and slightly better performance. + +Nano 11 is only compatible with Node.js versions 18 and older, because it is only these Node versions that have the [fetch](https://nodejs.org/dist/latest-v18.x/docs/api/globals.html#fetch) HTTP client baked in. See [Node.js's Long-term Support page](https://nodejs.org/en/about/previous-releases) to see which are the currently supported and maintained versions. In short: + +- If you are using Node.js 18 or newer, use Nano 11. +- If you need to use Node.js 16 or older, use Nano 10. + +Nano 10 may continue to receive some security fixes for a time, but Nano 11 represents the future of this project and at some point, support for Nano 10 will cease. + +## Agent options + +> ** Nano 11 no longer supports `requestDefaults` to configure the HTTP client ** + +None of Nano's API has changed _except_ when a user is supplying non-default connection handling parameters. Gone is `requestDefaults` which dates back to the "request" days and instead an optional `agentOptions` can be provided which is documented in the README and in TypeScript. + +```js +const agentOptions = { + bodyTimeout: 30000, + headersTimeout: 30000, + keepAliveMaxTimeout: 600000, + keepAliveTimeout: 30000, + keepAliveTimeoutThreshold: 1000, + maxHeaderSize: 16384, + maxResponseSize: -1, + pipelining: 6, + connect: { + timeout: 10000 + }, + strictContentLength: true, + connections: null, + maxRedirections: 0 +} +const undici = require('undici') +const undiciOptions = new undici.Agent(agentOptions) +const nano = Nano({ url: 'http://127.0.0.1:5984', undiciOptions }) +``` + +> Note: to supply a custom agent, you will need the [undici](https://www.npmjs.com/package/undici) module as a dependency in your own project. Undici is the library that powers Node.js's _fetch_ API but its "Agent" is not programmatically accessible unless undici is imported separately. + +## Callbacks + +> ** Nano 11 no longer supports callbacks ** + +In Nano 10 and earlier, the last parameter to most Nano functions was a callback so you could do: + +```js +db.list(function(err, data) { + console.log('response', err, data) +}) +``` + +This was the way asynchronous activity was handled in the early days of Node.js but as of Nano 11 all callbacks are removed and we expect the use of Promises: + +```js +db.list().then((data) => { console.log('response', data )}) +``` + +or more commonly, the `await` pattern: + +```js +const data = await db.list() +console.log('response', data) +``` + +If your code makes use of the callback style then **it will not work with Nano 11**: you will need to rewrite your code to use Promises or await, or remain on Nano 10. diff --git a/package-lock.json b/package-lock.json index b72937e7..b65f52b2 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,11088 +1,58 @@ { "name": "nano", - "version": "10.1.4", - "lockfileVersion": 2, + "version": "11.0.0", + "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "nano", - "version": "10.1.4", + "version": "11.0.0", "license": "Apache-2.0", - "dependencies": { - "axios": "^1.7.4", - "node-abort-controller": "^3.1.1", - "qs": "^6.13.0" - }, "devDependencies": { "@types/node": "^22.3.0", - "jest": "^29.7.0", - "nock": "^13.5.4", - "standard": "^17.1.0", - "typescript": "^5.5.4" - }, - "engines": { - "node": ">=14" - } - }, - "node_modules/@aashutoshrathi/word-wrap": { - "version": "1.2.6", - "resolved": "https://registry.npmjs.org/@aashutoshrathi/word-wrap/-/word-wrap-1.2.6.tgz", - "integrity": "sha512-1Yjs2SvM8TflER/OD3cOjhWWOZb58A2t7wpE2S9XfBYTiIl+XFhQG2bjy4Pu1I+EAlCNUzRDYDdFwFYUKvXcIA==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/@ampproject/remapping": { - "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.3.5", - "@jridgewell/trace-mapping": "^0.3.24" - }, - "engines": { - "node": ">=6.0.0" - } - }, - "node_modules/@babel/code-frame": { - "version": "7.24.7", - "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.24.7.tgz", - "integrity": "sha512-BcYH1CVJBO9tvyIZ2jVeXgSIMvGZ2FDRvDdOIVQyuklNKSsx+eppDEBq/g47Ayw+RqNFE+URvOShmf+f/qwAlA==", - "dev": true, - "dependencies": { - "@babel/highlight": "^7.24.7", - "picocolors": "^1.0.0" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/compat-data": { - "version": "7.25.2", - "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.25.2.tgz", - "integrity": "sha512-bYcppcpKBvX4znYaPEeFau03bp89ShqNMLs+rmdptMw+heSZh9+z84d2YG+K7cYLbWwzdjtDoW/uqZmPjulClQ==", - "dev": true, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/core": { - "version": "7.25.2", - "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.25.2.tgz", - "integrity": "sha512-BBt3opiCOxUr9euZ5/ro/Xv8/V7yJ5bjYMqG/C1YAo8MIKAnumZalCN+msbci3Pigy4lIQfPUpfMM27HMGaYEA==", - "dev": true, - "dependencies": { - "@ampproject/remapping": "^2.2.0", - "@babel/code-frame": "^7.24.7", - "@babel/generator": "^7.25.0", - "@babel/helper-compilation-targets": "^7.25.2", - "@babel/helper-module-transforms": "^7.25.2", - "@babel/helpers": "^7.25.0", - "@babel/parser": "^7.25.0", - "@babel/template": "^7.25.0", - "@babel/traverse": "^7.25.2", - "@babel/types": "^7.25.2", - "convert-source-map": "^2.0.0", - "debug": "^4.1.0", - "gensync": "^1.0.0-beta.2", - "json5": "^2.2.3", - "semver": "^6.3.1" - }, - "engines": { - "node": ">=6.9.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/babel" - } - }, - "node_modules/@babel/generator": { - "version": "7.25.0", - "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.25.0.tgz", - "integrity": "sha512-3LEEcj3PVW8pW2R1SR1M89g/qrYk/m/mB/tLqn7dn4sbBUQyTqnlod+II2U4dqiGtUmkcnAmkMDralTFZttRiw==", - "dev": true, - "dependencies": { - "@babel/types": "^7.25.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/helper-compilation-targets": { - "version": "7.25.2", - "resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.25.2.tgz", - "integrity": "sha512-U2U5LsSaZ7TAt3cfaymQ8WHh0pxvdHoEk6HVpaexxixjyEquMh0L0YNJNM6CTGKMXV1iksi0iZkGw4AcFkPaaw==", - "dev": true, - "dependencies": { - "@babel/compat-data": "^7.25.2", - "@babel/helper-validator-option": "^7.24.8", - "browserslist": "^4.23.1", - "lru-cache": "^5.1.1", - "semver": "^6.3.1" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/helper-compilation-targets/node_modules/lru-cache": { - "version": "5.1.1", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-5.1.1.tgz", - "integrity": "sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==", - "dev": true, - "dependencies": { - "yallist": "^3.0.2" - } - }, - "node_modules/@babel/helper-compilation-targets/node_modules/yallist": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-3.1.1.tgz", - "integrity": "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==", - "dev": true - }, - "node_modules/@babel/helper-module-imports": { - "version": "7.24.7", - "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.24.7.tgz", - "integrity": "sha512-8AyH3C+74cgCVVXow/myrynrAGv+nTVg5vKu2nZph9x7RcRwzmh0VFallJuFTZ9mx6u4eSdXZfcOzSqTUm0HCA==", - "dev": true, - "dependencies": { - "@babel/traverse": "^7.24.7", - "@babel/types": "^7.24.7" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/helper-module-transforms": { - "version": "7.25.2", - "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.25.2.tgz", - "integrity": "sha512-BjyRAbix6j/wv83ftcVJmBt72QtHI56C7JXZoG2xATiLpmoC7dpd8WnkikExHDVPpi/3qCmO6WY1EaXOluiecQ==", - "dev": true, - "dependencies": { - "@babel/helper-module-imports": "^7.24.7", - "@babel/helper-simple-access": "^7.24.7", - "@babel/helper-validator-identifier": "^7.24.7", - "@babel/traverse": "^7.25.2" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0" - } - }, - "node_modules/@babel/helper-plugin-utils": { - "version": "7.24.8", - "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.24.8.tgz", - "integrity": "sha512-FFWx5142D8h2Mgr/iPVGH5G7w6jDn4jUSpZTyDnQO0Yn7Ks2Kuz6Pci8H6MPCoUJegd/UZQ3tAvfLCxQSnWWwg==", - "dev": true, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/helper-simple-access": { - "version": "7.24.7", - "resolved": "https://registry.npmjs.org/@babel/helper-simple-access/-/helper-simple-access-7.24.7.tgz", - "integrity": "sha512-zBAIvbCMh5Ts+b86r/CjU+4XGYIs+R1j951gxI3KmmxBMhCg4oQMsv6ZXQ64XOm/cvzfU1FmoCyt6+owc5QMYg==", - "dev": true, - "dependencies": { - "@babel/traverse": "^7.24.7", - "@babel/types": "^7.24.7" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/helper-string-parser": { - "version": "7.24.8", - "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.24.8.tgz", - "integrity": "sha512-pO9KhhRcuUyGnJWwyEgnRJTSIZHiT+vMD0kPeD+so0l7mxkMT19g3pjY9GTnHySck/hDzq+dtW/4VgnMkippsQ==", - "dev": true, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/helper-validator-identifier": { - "version": "7.24.7", - "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.24.7.tgz", - "integrity": "sha512-rR+PBcQ1SMQDDyF6X0wxtG8QyLCgUB0eRAGguqRLfkCA87l7yAP7ehq8SNj96OOGTO8OBV70KhuFYcIkHXOg0w==", - "dev": true, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/helper-validator-option": { - "version": "7.24.8", - "resolved": "https://registry.npmjs.org/@babel/helper-validator-option/-/helper-validator-option-7.24.8.tgz", - "integrity": "sha512-xb8t9tD1MHLungh/AIoWYN+gVHaB9kwlu8gffXGSt3FFEIT7RjS+xWbc2vUD1UTZdIpKj/ab3rdqJ7ufngyi2Q==", - "dev": true, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/helpers": { - "version": "7.25.0", - "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.25.0.tgz", - "integrity": "sha512-MjgLZ42aCm0oGjJj8CtSM3DB8NOOf8h2l7DCTePJs29u+v7yO/RBX9nShlKMgFnRks/Q4tBAe7Hxnov9VkGwLw==", - "dev": true, - "dependencies": { - "@babel/template": "^7.25.0", - "@babel/types": "^7.25.0" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/highlight": { - "version": "7.24.7", - "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.24.7.tgz", - "integrity": "sha512-EStJpq4OuY8xYfhGVXngigBJRWxftKX9ksiGDnmlY3o7B/V7KIAc9X4oiK87uPJSc/vs5L869bem5fhZa8caZw==", - "dev": true, - "dependencies": { - "@babel/helper-validator-identifier": "^7.24.7", - "chalk": "^2.4.2", - "js-tokens": "^4.0.0", - "picocolors": "^1.0.0" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/highlight/node_modules/ansi-styles": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", - "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", - "dev": true, - "dependencies": { - "color-convert": "^1.9.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/@babel/highlight/node_modules/chalk": { - "version": "2.4.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", - "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", - "dev": true, - "dependencies": { - "ansi-styles": "^3.2.1", - "escape-string-regexp": "^1.0.5", - "supports-color": "^5.3.0" + "typescript": "^5.5.4", + "undici": "^6.2.1" }, "engines": { - "node": ">=4" - } - }, - "node_modules/@babel/highlight/node_modules/color-convert": { - "version": "1.9.3", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", - "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", - "dev": true, - "dependencies": { - "color-name": "1.1.3" - } - }, - "node_modules/@babel/highlight/node_modules/color-name": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", - "integrity": "sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==", - "dev": true - }, - "node_modules/@babel/highlight/node_modules/escape-string-regexp": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", - "integrity": "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==", - "dev": true, - "engines": { - "node": ">=0.8.0" - } - }, - "node_modules/@babel/highlight/node_modules/has-flag": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", - "integrity": "sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==", - "dev": true, - "engines": { - "node": ">=4" + "node": ">=18.0" } }, - "node_modules/@babel/highlight/node_modules/supports-color": { - "version": "5.5.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", - "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "node_modules/@types/node": { + "version": "22.3.0", + "resolved": "https://registry.npmjs.org/@types/node/-/node-22.3.0.tgz", + "integrity": "sha512-nrWpWVaDZuaVc5X84xJ0vNrLvomM205oQyLsRt7OHNZbSHslcWsvgFR7O7hire2ZonjLrWBbedmotmIlJDVd6g==", "dev": true, "dependencies": { - "has-flag": "^3.0.0" - }, - "engines": { - "node": ">=4" + "undici-types": "~6.18.2" } }, - "node_modules/@babel/parser": { - "version": "7.25.3", - "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.25.3.tgz", - "integrity": "sha512-iLTJKDbJ4hMvFPgQwwsVoxtHyWpKKPBrxkANrSYewDPaPpT5py5yeVkgPIJ7XYXhndxJpaA3PyALSXQ7u8e/Dw==", + "node_modules/typescript": { + "version": "5.5.4", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.5.4.tgz", + "integrity": "sha512-Mtq29sKDAEYP7aljRgtPOpTvOfbwRWlS6dPRzwjdE+C0R4brX/GUyhHSecbHMFLNBLcJIPt9nl9yG5TZ1weH+Q==", "dev": true, - "dependencies": { - "@babel/types": "^7.25.2" - }, "bin": { - "parser": "bin/babel-parser.js" - }, - "engines": { - "node": ">=6.0.0" - } - }, - "node_modules/@babel/plugin-syntax-async-generators": { - "version": "7.8.4", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-async-generators/-/plugin-syntax-async-generators-7.8.4.tgz", - "integrity": "sha512-tycmZxkGfZaxhMRbXlPXuVFpdWlXpir2W4AMhSJgRKzk/eDlIXOhb2LHWoLpDF7TEHylV5zNhykX6KAgHJmTNw==", - "dev": true, - "dependencies": { - "@babel/helper-plugin-utils": "^7.8.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-syntax-bigint": { - "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-bigint/-/plugin-syntax-bigint-7.8.3.tgz", - "integrity": "sha512-wnTnFlG+YxQm3vDxpGE57Pj0srRU4sHE/mDkt1qv2YJJSeUAec2ma4WLUnUPeKjyrfntVwe/N6dCXpU+zL3Npg==", - "dev": true, - "dependencies": { - "@babel/helper-plugin-utils": "^7.8.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-syntax-class-properties": { - "version": "7.12.13", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-class-properties/-/plugin-syntax-class-properties-7.12.13.tgz", - "integrity": "sha512-fm4idjKla0YahUNgFNLCB0qySdsoPiZP3iQE3rky0mBUtMZ23yDJ9SJdg6dXTSDnulOVqiF3Hgr9nbXvXTQZYA==", - "dev": true, - "dependencies": { - "@babel/helper-plugin-utils": "^7.12.13" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-syntax-class-static-block": { - "version": "7.14.5", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-class-static-block/-/plugin-syntax-class-static-block-7.14.5.tgz", - "integrity": "sha512-b+YyPmr6ldyNnM6sqYeMWE+bgJcJpO6yS4QD7ymxgH34GBPNDM/THBh8iunyvKIZztiwLH4CJZ0RxTk9emgpjw==", - "dev": true, - "dependencies": { - "@babel/helper-plugin-utils": "^7.14.5" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-syntax-import-attributes": { - "version": "7.24.7", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-import-attributes/-/plugin-syntax-import-attributes-7.24.7.tgz", - "integrity": "sha512-hbX+lKKeUMGihnK8nvKqmXBInriT3GVjzXKFriV3YC6APGxMbP8RZNFwy91+hocLXq90Mta+HshoB31802bb8A==", - "dev": true, - "dependencies": { - "@babel/helper-plugin-utils": "^7.24.7" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-syntax-import-meta": { - "version": "7.10.4", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-import-meta/-/plugin-syntax-import-meta-7.10.4.tgz", - "integrity": "sha512-Yqfm+XDx0+Prh3VSeEQCPU81yC+JWZ2pDPFSS4ZdpfZhp4MkFMaDC1UqseovEKwSUpnIL7+vK+Clp7bfh0iD7g==", - "dev": true, - "dependencies": { - "@babel/helper-plugin-utils": "^7.10.4" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-syntax-json-strings": { - "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-json-strings/-/plugin-syntax-json-strings-7.8.3.tgz", - "integrity": "sha512-lY6kdGpWHvjoe2vk4WrAapEuBR69EMxZl+RoGRhrFGNYVK8mOPAW8VfbT/ZgrFbXlDNiiaxQnAtgVCZ6jv30EA==", - "dev": true, - "dependencies": { - "@babel/helper-plugin-utils": "^7.8.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-syntax-jsx": { - "version": "7.24.7", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-jsx/-/plugin-syntax-jsx-7.24.7.tgz", - "integrity": "sha512-6ddciUPe/mpMnOKv/U+RSd2vvVy+Yw/JfBB0ZHYjEZt9NLHmCUylNYlsbqCCS1Bffjlb0fCwC9Vqz+sBz6PsiQ==", - "dev": true, - "dependencies": { - "@babel/helper-plugin-utils": "^7.24.7" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-syntax-logical-assignment-operators": { - "version": "7.10.4", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-logical-assignment-operators/-/plugin-syntax-logical-assignment-operators-7.10.4.tgz", - "integrity": "sha512-d8waShlpFDinQ5MtvGU9xDAOzKH47+FFoney2baFIoMr952hKOLp1HR7VszoZvOsV/4+RRszNY7D17ba0te0ig==", - "dev": true, - "dependencies": { - "@babel/helper-plugin-utils": "^7.10.4" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-syntax-nullish-coalescing-operator": { - "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-nullish-coalescing-operator/-/plugin-syntax-nullish-coalescing-operator-7.8.3.tgz", - "integrity": "sha512-aSff4zPII1u2QD7y+F8oDsz19ew4IGEJg9SVW+bqwpwtfFleiQDMdzA/R+UlWDzfnHFCxxleFT0PMIrR36XLNQ==", - "dev": true, - "dependencies": { - "@babel/helper-plugin-utils": "^7.8.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-syntax-numeric-separator": { - "version": "7.10.4", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-numeric-separator/-/plugin-syntax-numeric-separator-7.10.4.tgz", - "integrity": "sha512-9H6YdfkcK/uOnY/K7/aA2xpzaAgkQn37yzWUMRK7OaPOqOpGS1+n0H5hxT9AUw9EsSjPW8SVyMJwYRtWs3X3ug==", - "dev": true, - "dependencies": { - "@babel/helper-plugin-utils": "^7.10.4" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-syntax-object-rest-spread": { - "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-object-rest-spread/-/plugin-syntax-object-rest-spread-7.8.3.tgz", - "integrity": "sha512-XoqMijGZb9y3y2XskN+P1wUGiVwWZ5JmoDRwx5+3GmEplNyVM2s2Dg8ILFQm8rWM48orGy5YpI5Bl8U1y7ydlA==", - "dev": true, - "dependencies": { - "@babel/helper-plugin-utils": "^7.8.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-syntax-optional-catch-binding": { - "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-optional-catch-binding/-/plugin-syntax-optional-catch-binding-7.8.3.tgz", - "integrity": "sha512-6VPD0Pc1lpTqw0aKoeRTMiB+kWhAoT24PA+ksWSBrFtl5SIRVpZlwN3NNPQjehA2E/91FV3RjLWoVTglWcSV3Q==", - "dev": true, - "dependencies": { - "@babel/helper-plugin-utils": "^7.8.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-syntax-optional-chaining": { - "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-optional-chaining/-/plugin-syntax-optional-chaining-7.8.3.tgz", - "integrity": "sha512-KoK9ErH1MBlCPxV0VANkXW2/dw4vlbGDrFgz8bmUsBGYkFRcbRwMh6cIJubdPrkxRwuGdtCk0v/wPTKbQgBjkg==", - "dev": true, - "dependencies": { - "@babel/helper-plugin-utils": "^7.8.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-syntax-private-property-in-object": { - "version": "7.14.5", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-private-property-in-object/-/plugin-syntax-private-property-in-object-7.14.5.tgz", - "integrity": "sha512-0wVnp9dxJ72ZUJDV27ZfbSj6iHLoytYZmh3rFcxNnvsJF3ktkzLDZPy/mA17HGsaQT3/DQsWYX1f1QGWkCoVUg==", - "dev": true, - "dependencies": { - "@babel/helper-plugin-utils": "^7.14.5" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-syntax-top-level-await": { - "version": "7.14.5", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-top-level-await/-/plugin-syntax-top-level-await-7.14.5.tgz", - "integrity": "sha512-hx++upLv5U1rgYfwe1xBQUhRmU41NEvpUvrp8jkrSCdvGSnM5/qdRMtylJ6PG5OFkBaHkbTAKTnd3/YyESRHFw==", - "dev": true, - "dependencies": { - "@babel/helper-plugin-utils": "^7.14.5" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-syntax-typescript": { - "version": "7.24.7", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-typescript/-/plugin-syntax-typescript-7.24.7.tgz", - "integrity": "sha512-c/+fVeJBB0FeKsFvwytYiUD+LBvhHjGSI0g446PRGdSVGZLRNArBUno2PETbAly3tpiNAQR5XaZ+JslxkotsbA==", - "dev": true, - "dependencies": { - "@babel/helper-plugin-utils": "^7.24.7" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/template": { - "version": "7.25.0", - "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.25.0.tgz", - "integrity": "sha512-aOOgh1/5XzKvg1jvVz7AVrx2piJ2XBi227DHmbY6y+bM9H2FlN+IfecYu4Xl0cNiiVejlsCri89LUsbj8vJD9Q==", - "dev": true, - "dependencies": { - "@babel/code-frame": "^7.24.7", - "@babel/parser": "^7.25.0", - "@babel/types": "^7.25.0" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/traverse": { - "version": "7.25.3", - "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.25.3.tgz", - "integrity": "sha512-HefgyP1x754oGCsKmV5reSmtV7IXj/kpaE1XYY+D9G5PvKKoFfSbiS4M77MdjuwlZKDIKFCffq9rPU+H/s3ZdQ==", - "dev": true, - "dependencies": { - "@babel/code-frame": "^7.24.7", - "@babel/generator": "^7.25.0", - "@babel/parser": "^7.25.3", - "@babel/template": "^7.25.0", - "@babel/types": "^7.25.2", - "debug": "^4.3.1", - "globals": "^11.1.0" + "tsc": "bin/tsc", + "tsserver": "bin/tsserver" }, "engines": { - "node": ">=6.9.0" + "node": ">=14.17" } }, - "node_modules/@babel/types": { - "version": "7.25.2", - "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.25.2.tgz", - "integrity": "sha512-YTnYtra7W9e6/oAZEHj0bJehPRUlLH9/fbpT5LfB0NhQXyALCRkRs3zH9v07IYhkgpqX6Z78FnuccZr/l4Fs4Q==", + "node_modules/undici": { + "version": "6.19.7", + "resolved": "https://registry.npmjs.org/undici/-/undici-6.19.7.tgz", + "integrity": "sha512-HR3W/bMGPSr90i8AAp2C4DM3wChFdJPLrWYpIS++LxS8K+W535qftjt+4MyjNYHeWabMj1nvtmLIi7l++iq91A==", "dev": true, - "dependencies": { - "@babel/helper-string-parser": "^7.24.8", - "@babel/helper-validator-identifier": "^7.24.7", - "to-fast-properties": "^2.0.0" - }, "engines": { - "node": ">=6.9.0" + "node": ">=18.17" } }, - "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/@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.10.0", - "resolved": "https://registry.npmjs.org/@eslint-community/regexpp/-/regexpp-4.10.0.tgz", - "integrity": "sha512-Cu96Sd2By9mCNTx2iyKOmq10v22jUVQv0lQnlGNy16oE9589yE+QADPbrMGCkA51cKZSg3Pu/aTJVTGfL/qjUA==", - "dev": true, - "engines": { - "node": "^12.0.0 || ^14.0.0 || >=16.0.0" - } - }, - "node_modules/@eslint/eslintrc": { - "version": "2.1.3", - "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-2.1.3.tgz", - "integrity": "sha512-yZzuIG+jnVu6hNSzFEN07e8BxF3uAzYtQb6uDkaYZLo6oYZDCq454c5kB8zxnzfCYyP4MIuyBn10L0DqwujTmA==", - "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/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/debug": { - "version": "4.3.4", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", - "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", - "dev": true, - "dependencies": { - "ms": "2.1.2" - }, - "engines": { - "node": ">=6.0" - }, - "peerDependenciesMeta": { - "supports-color": { - "optional": true - } - } - }, - "node_modules/@eslint/eslintrc/node_modules/globals": { - "version": "13.23.0", - "resolved": "https://registry.npmjs.org/globals/-/globals-13.23.0.tgz", - "integrity": "sha512-XAmF0RjlrjY23MA51q3HltdlGxUpXPvg0GioKiD9X6HD28iMjo2dKC8Vqwm7lne4GNr78+RHTfliktR6ZH09wA==", - "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" - } - }, - "node_modules/@eslint/eslintrc/node_modules/type-fest": { - "version": "0.20.2", - "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.20.2.tgz", - "integrity": "sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ==", - "dev": true, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/@eslint/js": { - "version": "8.53.0", - "resolved": "https://registry.npmjs.org/@eslint/js/-/js-8.53.0.tgz", - "integrity": "sha512-Kn7K8dx/5U6+cT1yEhpX1w4PCSg0M+XyRILPgvwcEBjerFWCwQj5sbr3/VmxqV0JGHCBCzyd6LxypEuehypY1w==", - "dev": true, - "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" - } - }, - "node_modules/@humanwhocodes/config-array": { - "version": "0.11.13", - "resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.11.13.tgz", - "integrity": "sha512-JSBDMiDKSzQVngfRjOdFXgFfklaXI4K9nLF49Auh21lmBWRLIK3+xTErTWD4KU54pb6coM6ESE7Awz/FNU3zgQ==", - "dev": true, - "dependencies": { - "@humanwhocodes/object-schema": "^2.0.1", - "debug": "^4.1.1", - "minimatch": "^3.0.5" - }, - "engines": { - "node": ">=10.10.0" - } - }, - "node_modules/@humanwhocodes/module-importer": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/@humanwhocodes/module-importer/-/module-importer-1.0.1.tgz", - "integrity": "sha512-bxveV4V8v5Yb4ncFTT3rPSgZBOpCkjfK0y4oVVVJwIuDVBRMDXrPyXRL988i5ap9m9bnyEEjWfm5WkBmtffLfA==", - "dev": true, - "engines": { - "node": ">=12.22" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/nzakas" - } - }, - "node_modules/@humanwhocodes/object-schema": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/@humanwhocodes/object-schema/-/object-schema-2.0.1.tgz", - "integrity": "sha512-dvuCeX5fC9dXgJn9t+X5atfmgQAzUOWqS1254Gh0m6i8wKd10ebXkfNKiRK+1GWi/yTvvLDHpoxLr0xxxeslWw==", - "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/schema": { - "version": "0.1.3", - "resolved": "https://registry.npmjs.org/@istanbuljs/schema/-/schema-0.1.3.tgz", - "integrity": "sha512-ZXRY4jNvVgSVQ8DL3LTcakaAtXwTVUxE81hslsyD2AtoXW/wVob10HkOJ1X/pAlcI7D+2YoZKg5do8G/w6RYgA==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/@jest/console": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/@jest/console/-/console-29.7.0.tgz", - "integrity": "sha512-5Ni4CU7XHQi32IJ398EEP4RrB8eV09sXP2ROqD4bksHrnTree52PsxvX8tpL8LvTZ3pFzXyPbNQReSN41CAhOg==", - "dev": true, - "dependencies": { - "@jest/types": "^29.6.3", - "@types/node": "*", - "chalk": "^4.0.0", - "jest-message-util": "^29.7.0", - "jest-util": "^29.7.0", - "slash": "^3.0.0" - }, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" - } - }, - "node_modules/@jest/core": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/@jest/core/-/core-29.7.0.tgz", - "integrity": "sha512-n7aeXWKMnGtDA48y8TLWJPJmLmmZ642Ceo78cYWEpiD7FzDgmNDV/GCVRorPABdXLJZ/9wzzgZAlHjXjxDHGsg==", - "dev": true, - "dependencies": { - "@jest/console": "^29.7.0", - "@jest/reporters": "^29.7.0", - "@jest/test-result": "^29.7.0", - "@jest/transform": "^29.7.0", - "@jest/types": "^29.6.3", - "@types/node": "*", - "ansi-escapes": "^4.2.1", - "chalk": "^4.0.0", - "ci-info": "^3.2.0", - "exit": "^0.1.2", - "graceful-fs": "^4.2.9", - "jest-changed-files": "^29.7.0", - "jest-config": "^29.7.0", - "jest-haste-map": "^29.7.0", - "jest-message-util": "^29.7.0", - "jest-regex-util": "^29.6.3", - "jest-resolve": "^29.7.0", - "jest-resolve-dependencies": "^29.7.0", - "jest-runner": "^29.7.0", - "jest-runtime": "^29.7.0", - "jest-snapshot": "^29.7.0", - "jest-util": "^29.7.0", - "jest-validate": "^29.7.0", - "jest-watcher": "^29.7.0", - "micromatch": "^4.0.4", - "pretty-format": "^29.7.0", - "slash": "^3.0.0", - "strip-ansi": "^6.0.0" - }, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" - }, - "peerDependencies": { - "node-notifier": "^8.0.1 || ^9.0.0 || ^10.0.0" - }, - "peerDependenciesMeta": { - "node-notifier": { - "optional": true - } - } - }, - "node_modules/@jest/environment": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/@jest/environment/-/environment-29.7.0.tgz", - "integrity": "sha512-aQIfHDq33ExsN4jP1NWGXhxgQ/wixs60gDiKO+XVMd8Mn0NWPWgc34ZQDTb2jKaUWQ7MuwoitXAsN2XVXNMpAw==", - "dev": true, - "dependencies": { - "@jest/fake-timers": "^29.7.0", - "@jest/types": "^29.6.3", - "@types/node": "*", - "jest-mock": "^29.7.0" - }, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" - } - }, - "node_modules/@jest/expect": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/@jest/expect/-/expect-29.7.0.tgz", - "integrity": "sha512-8uMeAMycttpva3P1lBHB8VciS9V0XAr3GymPpipdyQXbBcuhkLQOSe8E/p92RyAdToS6ZD1tFkX+CkhoECE0dQ==", - "dev": true, - "dependencies": { - "expect": "^29.7.0", - "jest-snapshot": "^29.7.0" - }, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" - } - }, - "node_modules/@jest/expect-utils": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/@jest/expect-utils/-/expect-utils-29.7.0.tgz", - "integrity": "sha512-GlsNBWiFQFCVi9QVSx7f5AgMeLxe9YCCs5PuP2O2LdjDAA8Jh9eX7lA1Jq/xdXw3Wb3hyvlFNfZIfcRetSzYcA==", - "dev": true, - "dependencies": { - "jest-get-type": "^29.6.3" - }, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" - } - }, - "node_modules/@jest/fake-timers": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/@jest/fake-timers/-/fake-timers-29.7.0.tgz", - "integrity": "sha512-q4DH1Ha4TTFPdxLsqDXK1d3+ioSL7yL5oCMJZgDYm6i+6CygW5E5xVr/D1HdsGxjt1ZWSfUAs9OxSB/BNelWrQ==", - "dev": true, - "dependencies": { - "@jest/types": "^29.6.3", - "@sinonjs/fake-timers": "^10.0.2", - "@types/node": "*", - "jest-message-util": "^29.7.0", - "jest-mock": "^29.7.0", - "jest-util": "^29.7.0" - }, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" - } - }, - "node_modules/@jest/globals": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/@jest/globals/-/globals-29.7.0.tgz", - "integrity": "sha512-mpiz3dutLbkW2MNFubUGUEVLkTGiqW6yLVTA+JbP6fI6J5iL9Y0Nlg8k95pcF8ctKwCS7WVxteBs29hhfAotzQ==", - "dev": true, - "dependencies": { - "@jest/environment": "^29.7.0", - "@jest/expect": "^29.7.0", - "@jest/types": "^29.6.3", - "jest-mock": "^29.7.0" - }, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" - } - }, - "node_modules/@jest/reporters": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/@jest/reporters/-/reporters-29.7.0.tgz", - "integrity": "sha512-DApq0KJbJOEzAFYjHADNNxAE3KbhxQB1y5Kplb5Waqw6zVbuWatSnMjE5gs8FUgEPmNsnZA3NCWl9NG0ia04Pg==", - "dev": true, - "dependencies": { - "@bcoe/v8-coverage": "^0.2.3", - "@jest/console": "^29.7.0", - "@jest/test-result": "^29.7.0", - "@jest/transform": "^29.7.0", - "@jest/types": "^29.6.3", - "@jridgewell/trace-mapping": "^0.3.18", - "@types/node": "*", - "chalk": "^4.0.0", - "collect-v8-coverage": "^1.0.0", - "exit": "^0.1.2", - "glob": "^7.1.3", - "graceful-fs": "^4.2.9", - "istanbul-lib-coverage": "^3.0.0", - "istanbul-lib-instrument": "^6.0.0", - "istanbul-lib-report": "^3.0.0", - "istanbul-lib-source-maps": "^4.0.0", - "istanbul-reports": "^3.1.3", - "jest-message-util": "^29.7.0", - "jest-util": "^29.7.0", - "jest-worker": "^29.7.0", - "slash": "^3.0.0", - "string-length": "^4.0.1", - "strip-ansi": "^6.0.0", - "v8-to-istanbul": "^9.0.1" - }, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" - }, - "peerDependencies": { - "node-notifier": "^8.0.1 || ^9.0.0 || ^10.0.0" - }, - "peerDependenciesMeta": { - "node-notifier": { - "optional": true - } - } - }, - "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": { - "@sinclair/typebox": "^0.27.8" - }, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" - } - }, - "node_modules/@jest/source-map": { - "version": "29.6.3", - "resolved": "https://registry.npmjs.org/@jest/source-map/-/source-map-29.6.3.tgz", - "integrity": "sha512-MHjT95QuipcPrpLM+8JMSzFx6eHp5Bm+4XeFDJlwsvVBjmKNiIAvasGK2fxz2WbGRlnvqehFbh07MMa7n3YJnw==", - "dev": true, - "dependencies": { - "@jridgewell/trace-mapping": "^0.3.18", - "callsites": "^3.0.0", - "graceful-fs": "^4.2.9" - }, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" - } - }, - "node_modules/@jest/test-result": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/@jest/test-result/-/test-result-29.7.0.tgz", - "integrity": "sha512-Fdx+tv6x1zlkJPcWXmMDAG2HBnaR9XPSd5aDWQVsfrZmLVT3lU1cwyxLgRmXR9yrq4NBoEm9BMsfgFzTQAbJYA==", - "dev": true, - "dependencies": { - "@jest/console": "^29.7.0", - "@jest/types": "^29.6.3", - "@types/istanbul-lib-coverage": "^2.0.0", - "collect-v8-coverage": "^1.0.0" - }, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" - } - }, - "node_modules/@jest/test-sequencer": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/@jest/test-sequencer/-/test-sequencer-29.7.0.tgz", - "integrity": "sha512-GQwJ5WZVrKnOJuiYiAF52UNUJXgTZx1NHjFSEB0qEMmSZKAkdMoIzw/Cj6x6NF4AvV23AUqDpFzQkN/eYCYTxw==", - "dev": true, - "dependencies": { - "@jest/test-result": "^29.7.0", - "graceful-fs": "^4.2.9", - "jest-haste-map": "^29.7.0", - "slash": "^3.0.0" - }, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" - } - }, - "node_modules/@jest/transform": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/@jest/transform/-/transform-29.7.0.tgz", - "integrity": "sha512-ok/BTPFzFKVMwO5eOHRrvnBVHdRy9IrsrW1GpMaQ9MCnilNLXQKmAX8s1YXDFaai9xJpac2ySzV0YeRRECr2Vw==", - "dev": true, - "dependencies": { - "@babel/core": "^7.11.6", - "@jest/types": "^29.6.3", - "@jridgewell/trace-mapping": "^0.3.18", - "babel-plugin-istanbul": "^6.1.1", - "chalk": "^4.0.0", - "convert-source-map": "^2.0.0", - "fast-json-stable-stringify": "^2.1.0", - "graceful-fs": "^4.2.9", - "jest-haste-map": "^29.7.0", - "jest-regex-util": "^29.6.3", - "jest-util": "^29.7.0", - "micromatch": "^4.0.4", - "pirates": "^4.0.4", - "slash": "^3.0.0", - "write-file-atomic": "^4.0.2" - }, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" - } - }, - "node_modules/@jest/types": { - "version": "29.6.3", - "resolved": "https://registry.npmjs.org/@jest/types/-/types-29.6.3.tgz", - "integrity": "sha512-u3UPsIilWKOM3F9CXtrG8LEJmNxwoCQC/XVj4IKYXvvpx7QIi/Kg1LI5uDmDpKlac62NUtX7eLjRh+jVZcLOzw==", - "dev": true, - "dependencies": { - "@jest/schemas": "^29.6.3", - "@types/istanbul-lib-coverage": "^2.0.0", - "@types/istanbul-reports": "^3.0.0", - "@types/node": "*", - "@types/yargs": "^17.0.8", - "chalk": "^4.0.0" - }, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" - } - }, - "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/@jridgewell/resolve-uri": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.2.tgz", - "integrity": "sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw==", - "dev": true, - "engines": { - "node": ">=6.0.0" - } - }, - "node_modules/@jridgewell/set-array": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/@jridgewell/set-array/-/set-array-1.2.1.tgz", - "integrity": "sha512-R8gLRTZeyp03ymzP/6Lil/28tGeGEzhx1q2k703KGWRAI1VdvPIXdG70VJc2pAMw3NA6JKL5hhFu1sJX0Mnn/A==", - "dev": true, - "engines": { - "node": ">=6.0.0" - } - }, - "node_modules/@jridgewell/sourcemap-codec": { - "version": "1.5.0", - "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.5.0.tgz", - "integrity": "sha512-gv3ZRaISU3fjPAgNsriBRqGWQL6quFx04YMPW/zD8XMLsU32mhCCbfbO6KZFLjvYpCZ8zyDEgqsgf+PwPaM7GQ==", - "dev": true - }, - "node_modules/@jridgewell/trace-mapping": { - "version": "0.3.25", - "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.25.tgz", - "integrity": "sha512-vNk6aEwybGtawWmy/PzwnGDOjCkLWSD2wqvjGGAgOAwCGWySYXfYoxt00IJkTF+8Lb57DwOb3Aa0o9CApepiYQ==", - "dev": true, - "dependencies": { - "@jridgewell/resolve-uri": "^3.1.0", - "@jridgewell/sourcemap-codec": "^1.4.14" - } - }, - "node_modules/@nodelib/fs.scandir": { - "version": "2.1.5", - "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz", - "integrity": "sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==", - "dev": true, - "dependencies": { - "@nodelib/fs.stat": "2.0.5", - "run-parallel": "^1.1.9" - }, - "engines": { - "node": ">= 8" - } - }, - "node_modules/@nodelib/fs.stat": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/@nodelib/fs.stat/-/fs.stat-2.0.5.tgz", - "integrity": "sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==", - "dev": true, - "engines": { - "node": ">= 8" - } - }, - "node_modules/@nodelib/fs.walk": { - "version": "1.2.8", - "resolved": "https://registry.npmjs.org/@nodelib/fs.walk/-/fs.walk-1.2.8.tgz", - "integrity": "sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==", - "dev": true, - "dependencies": { - "@nodelib/fs.scandir": "2.1.5", - "fastq": "^1.6.0" - }, - "engines": { - "node": ">= 8" - } - }, - "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": "3.0.1", - "resolved": "https://registry.npmjs.org/@sinonjs/commons/-/commons-3.0.1.tgz", - "integrity": "sha512-K3mCHKQ9sVh8o1C9cxkwxaOmXoAMlDxC1mYyHrjqOWEcBjYr76t96zL2zlj5dUGZ3HSw240X1qgH3Mjf1yJWpQ==", - "dev": true, - "dependencies": { - "type-detect": "4.0.8" - } - }, - "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/@types/babel__core": { - "version": "7.20.5", - "resolved": "https://registry.npmjs.org/@types/babel__core/-/babel__core-7.20.5.tgz", - "integrity": "sha512-qoQprZvz5wQFJwMDqeseRXWv3rqMvhgpbXFfVyWhbx9X47POIA6i/+dXefEmZKoAgOaTdaIgNSMqMIU61yRyzA==", - "dev": true, - "dependencies": { - "@babel/parser": "^7.20.7", - "@babel/types": "^7.20.7", - "@types/babel__generator": "*", - "@types/babel__template": "*", - "@types/babel__traverse": "*" - } - }, - "node_modules/@types/babel__generator": { - "version": "7.6.8", - "resolved": "https://registry.npmjs.org/@types/babel__generator/-/babel__generator-7.6.8.tgz", - "integrity": "sha512-ASsj+tpEDsEiFr1arWrlN6V3mdfjRMZt6LtK/Vp/kreFLnr5QH5+DhvD5nINYZXzwJvXeGq+05iUXcAzVrqWtw==", - "dev": true, - "dependencies": { - "@babel/types": "^7.0.0" - } - }, - "node_modules/@types/babel__template": { - "version": "7.4.4", - "resolved": "https://registry.npmjs.org/@types/babel__template/-/babel__template-7.4.4.tgz", - "integrity": "sha512-h/NUaSyG5EyxBIp8YRxo4RMe2/qQgvyowRwVMzhYhBCONbW8PUsg4lkFMrhgZhUe5z3L3MiLDuvyJ/CaPa2A8A==", - "dev": true, - "dependencies": { - "@babel/parser": "^7.1.0", - "@babel/types": "^7.0.0" - } - }, - "node_modules/@types/babel__traverse": { - "version": "7.20.6", - "resolved": "https://registry.npmjs.org/@types/babel__traverse/-/babel__traverse-7.20.6.tgz", - "integrity": "sha512-r1bzfrm0tomOI8g1SzvCaQHo6Lcv6zu0EA+W2kHrt8dyrHQxGzBBL4kdkzIS+jBMV+EYcMAEAqXqYaLJq5rOZg==", - "dev": true, - "dependencies": { - "@babel/types": "^7.20.7" - } - }, - "node_modules/@types/graceful-fs": { - "version": "4.1.9", - "resolved": "https://registry.npmjs.org/@types/graceful-fs/-/graceful-fs-4.1.9.tgz", - "integrity": "sha512-olP3sd1qOEe5dXTSaFvQG+02VdRXcdytWLAZsAq1PecU8uqQAhkrnbli7DagjtXKW/Bl7YJbUsa8MPcuc8LHEQ==", - "dev": true, - "dependencies": { - "@types/node": "*" - } - }, - "node_modules/@types/istanbul-lib-coverage": { - "version": "2.0.6", - "resolved": "https://registry.npmjs.org/@types/istanbul-lib-coverage/-/istanbul-lib-coverage-2.0.6.tgz", - "integrity": "sha512-2QF/t/auWm0lsy8XtKVPG19v3sSOQlJe/YHZgfjb/KBBHOGSV+J2q/S671rcq9uTBrLAXmZpqJiaQbMT+zNU1w==", - "dev": true - }, - "node_modules/@types/istanbul-lib-report": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/@types/istanbul-lib-report/-/istanbul-lib-report-3.0.3.tgz", - "integrity": "sha512-NQn7AHQnk/RSLOxrBbGyJM/aVQ+pjj5HCgasFxc0K/KhoATfQ/47AyUl15I2yBUpihjmas+a+VJBOqecrFH+uA==", - "dev": true, - "dependencies": { - "@types/istanbul-lib-coverage": "*" - } - }, - "node_modules/@types/istanbul-reports": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/@types/istanbul-reports/-/istanbul-reports-3.0.4.tgz", - "integrity": "sha512-pk2B1NWalF9toCRu6gjBzR69syFjP4Od8WRAX+0mmf9lAjCRicLOWc+ZrxZHx/0XRjotgkF9t6iaMJ+aXcOdZQ==", - "dev": true, - "dependencies": { - "@types/istanbul-lib-report": "*" - } - }, - "node_modules/@types/json5": { - "version": "0.0.29", - "resolved": "https://registry.npmjs.org/@types/json5/-/json5-0.0.29.tgz", - "integrity": "sha512-dRLjCWHYg4oaA77cxO64oO+7JwCwnIzkZPdrrC71jQmQtlhM556pwKo5bUzqvZndkVbeFLIIi+9TC40JNF5hNQ==", - "dev": true - }, - "node_modules/@types/node": { - "version": "22.3.0", - "resolved": "https://registry.npmjs.org/@types/node/-/node-22.3.0.tgz", - "integrity": "sha512-nrWpWVaDZuaVc5X84xJ0vNrLvomM205oQyLsRt7OHNZbSHslcWsvgFR7O7hire2ZonjLrWBbedmotmIlJDVd6g==", - "dev": true, - "dependencies": { - "undici-types": "~6.18.2" - } - }, - "node_modules/@types/stack-utils": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/@types/stack-utils/-/stack-utils-2.0.3.tgz", - "integrity": "sha512-9aEbYZ3TbYMznPdcdr3SmIrLXwC/AKZXQeCf9Pgao5CKb8CyHuEX5jzWPTkvregvhRJHcpRO6BFoGW9ycaOkYw==", - "dev": true - }, - "node_modules/@types/yargs": { - "version": "17.0.33", - "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-17.0.33.tgz", - "integrity": "sha512-WpxBCKWPLr4xSsHgz511rFJAM+wS28w2zEO1QDNY5zM/S8ok70NNfztH0xwhqKyaK0OHCbN98LDAZuy1ctxDkA==", - "dev": true, - "dependencies": { - "@types/yargs-parser": "*" - } - }, - "node_modules/@types/yargs-parser": { - "version": "21.0.3", - "resolved": "https://registry.npmjs.org/@types/yargs-parser/-/yargs-parser-21.0.3.tgz", - "integrity": "sha512-I4q9QU9MQv4oEOz4tAHJtNz1cwuLxn2F3xcc2iV5WdqLPpUnj30aUuxt1mAxYTG+oe8CZMV/+6rU4S4gRDzqtQ==", - "dev": true - }, - "node_modules/@ungap/structured-clone": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/@ungap/structured-clone/-/structured-clone-1.2.0.tgz", - "integrity": "sha512-zuVdFrMJiuCDQUMCzQaD6KL28MjnqqN8XnAqiEq9PNm/hCPTSGfrXCOfwj1ow4LFb/tNymJPwsNbVePc1xFqrQ==", - "dev": true - }, - "node_modules/acorn": { - "version": "8.11.2", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.11.2.tgz", - "integrity": "sha512-nc0Axzp/0FILLEVsm4fNwLCwMttvhEI263QtVPQcbpfZZ3ts0hLsZGOpE6czNlid7CJ9MlyH8reXkpsf3YUY4w==", - "dev": true, - "bin": { - "acorn": "bin/acorn" - }, - "engines": { - "node": ">=0.4.0" - } - }, - "node_modules/acorn-jsx": { - "version": "5.3.2", - "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.3.2.tgz", - "integrity": "sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==", - "dev": true, - "peerDependencies": { - "acorn": "^6.0.0 || ^7.0.0 || ^8.0.0" - } - }, - "node_modules/ajv": { - "version": "6.12.6", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", - "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", - "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/ansi-escapes": { - "version": "4.3.2", - "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-4.3.2.tgz", - "integrity": "sha512-gKXj5ALrKWQLsYG9jlTRmR/xKluxHV+Z9QEwNIgCfM1/uwPMCuzVVnh5mwTd+OuBZcwSIMbqssNWRm1lE51QaQ==", - "dev": true, - "dependencies": { - "type-fest": "^0.21.3" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/ansi-regex": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", - "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/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/anymatch": { - "version": "3.1.3", - "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.3.tgz", - "integrity": "sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw==", - "dev": true, - "dependencies": { - "normalize-path": "^3.0.0", - "picomatch": "^2.0.4" - }, - "engines": { - "node": ">= 8" - } - }, - "node_modules/argparse": { - "version": "1.0.10", - "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz", - "integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==", - "dev": true, - "dependencies": { - "sprintf-js": "~1.0.2" - } - }, - "node_modules/array-buffer-byte-length": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/array-buffer-byte-length/-/array-buffer-byte-length-1.0.0.tgz", - "integrity": "sha512-LPuwb2P+NrQw3XhxGc36+XSvuBPopovXYTR9Ew++Du9Yb/bx5AzBfrIsBoj0EZUifjQU+sHL21sseZ3jerWO/A==", - "dev": true, - "dependencies": { - "call-bind": "^1.0.2", - "is-array-buffer": "^3.0.1" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/array-includes": { - "version": "3.1.7", - "resolved": "https://registry.npmjs.org/array-includes/-/array-includes-3.1.7.tgz", - "integrity": "sha512-dlcsNBIiWhPkHdOEEKnehA+RNUWDc4UqFtnIXU4uuYDPtA4LDkr7qip2p0VvFAEXNDr0yWZ9PJyIRiGjRLQzwQ==", - "dev": true, - "dependencies": { - "call-bind": "^1.0.2", - "define-properties": "^1.2.0", - "es-abstract": "^1.22.1", - "get-intrinsic": "^1.2.1", - "is-string": "^1.0.7" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/array.prototype.findlastindex": { - "version": "1.2.3", - "resolved": "https://registry.npmjs.org/array.prototype.findlastindex/-/array.prototype.findlastindex-1.2.3.tgz", - "integrity": "sha512-LzLoiOMAxvy+Gd3BAq3B7VeIgPdo+Q8hthvKtXybMvRV0jrXfJM/t8mw7nNlpEcVlVUnCnM2KSX4XU5HmpodOA==", - "dev": true, - "dependencies": { - "call-bind": "^1.0.2", - "define-properties": "^1.2.0", - "es-abstract": "^1.22.1", - "es-shim-unscopables": "^1.0.0", - "get-intrinsic": "^1.2.1" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/array.prototype.flat": { - "version": "1.3.2", - "resolved": "https://registry.npmjs.org/array.prototype.flat/-/array.prototype.flat-1.3.2.tgz", - "integrity": "sha512-djYB+Zx2vLewY8RWlNCUdHjDXs2XOgm602S9E7P/UpHgfeHL00cRiIF+IN/G/aUJ7kGPb6yO/ErDI5V2s8iycA==", - "dev": true, - "dependencies": { - "call-bind": "^1.0.2", - "define-properties": "^1.2.0", - "es-abstract": "^1.22.1", - "es-shim-unscopables": "^1.0.0" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/array.prototype.flatmap": { - "version": "1.3.2", - "resolved": "https://registry.npmjs.org/array.prototype.flatmap/-/array.prototype.flatmap-1.3.2.tgz", - "integrity": "sha512-Ewyx0c9PmpcsByhSW4r+9zDU7sGjFc86qf/kKtuSCRdhfbk0SNLLkaT5qvcHnRGgc5NP/ly/y+qkXkqONX54CQ==", - "dev": true, - "dependencies": { - "call-bind": "^1.0.2", - "define-properties": "^1.2.0", - "es-abstract": "^1.22.1", - "es-shim-unscopables": "^1.0.0" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/array.prototype.tosorted": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/array.prototype.tosorted/-/array.prototype.tosorted-1.1.2.tgz", - "integrity": "sha512-HuQCHOlk1Weat5jzStICBCd83NxiIMwqDg/dHEsoefabn/hJRj5pVdWcPUSpRrwhwxZOsQassMpgN/xRYFBMIg==", - "dev": true, - "dependencies": { - "call-bind": "^1.0.2", - "define-properties": "^1.2.0", - "es-abstract": "^1.22.1", - "es-shim-unscopables": "^1.0.0", - "get-intrinsic": "^1.2.1" - } - }, - "node_modules/arraybuffer.prototype.slice": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/arraybuffer.prototype.slice/-/arraybuffer.prototype.slice-1.0.2.tgz", - "integrity": "sha512-yMBKppFur/fbHu9/6USUe03bZ4knMYiwFBcyiaXB8Go0qNehwX6inYPzK9U0NeQvGxKthcmHcaR8P5MStSRBAw==", - "dev": true, - "dependencies": { - "array-buffer-byte-length": "^1.0.0", - "call-bind": "^1.0.2", - "define-properties": "^1.2.0", - "es-abstract": "^1.22.1", - "get-intrinsic": "^1.2.1", - "is-array-buffer": "^3.0.2", - "is-shared-array-buffer": "^1.0.2" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/asynciterator.prototype": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/asynciterator.prototype/-/asynciterator.prototype-1.0.0.tgz", - "integrity": "sha512-wwHYEIS0Q80f5mosx3L/dfG5t5rjEa9Ft51GTaNt862EnpyGHpgz2RkZvLPp1oF5TnAiTohkEKVEu8pQPJI7Vg==", - "dev": true, - "dependencies": { - "has-symbols": "^1.0.3" - } - }, - "node_modules/asynckit": { - "version": "0.4.0", - "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", - "integrity": "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==" - }, - "node_modules/available-typed-arrays": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/available-typed-arrays/-/available-typed-arrays-1.0.5.tgz", - "integrity": "sha512-DMD0KiN46eipeziST1LPP/STfDU0sufISXmjSgvVsoU2tqxctQeASejWcfNtxYKqETM1UxQ8sp2OrSBWpHY6sw==", - "dev": true, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/axios": { - "version": "1.7.4", - "resolved": "https://registry.npmjs.org/axios/-/axios-1.7.4.tgz", - "integrity": "sha512-DukmaFRnY6AzAALSH4J2M3k6PkaC+MfaAGdEERRWcC9q3/TWQwLpHR8ZRLKTdQ3aBDL64EdluRDjJqKw+BPZEw==", - "dependencies": { - "follow-redirects": "^1.15.6", - "form-data": "^4.0.0", - "proxy-from-env": "^1.1.0" - } - }, - "node_modules/babel-jest": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/babel-jest/-/babel-jest-29.7.0.tgz", - "integrity": "sha512-BrvGY3xZSwEcCzKvKsCi2GgHqDqsYkOP4/by5xCgIwGXQxIEh+8ew3gmrE1y7XRR6LHZIj6yLYnUi/mm2KXKBg==", - "dev": true, - "dependencies": { - "@jest/transform": "^29.7.0", - "@types/babel__core": "^7.1.14", - "babel-plugin-istanbul": "^6.1.1", - "babel-preset-jest": "^29.6.3", - "chalk": "^4.0.0", - "graceful-fs": "^4.2.9", - "slash": "^3.0.0" - }, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" - }, - "peerDependencies": { - "@babel/core": "^7.8.0" - } - }, - "node_modules/babel-plugin-istanbul": { - "version": "6.1.1", - "resolved": "https://registry.npmjs.org/babel-plugin-istanbul/-/babel-plugin-istanbul-6.1.1.tgz", - "integrity": "sha512-Y1IQok9821cC9onCx5otgFfRm7Lm+I+wwxOx738M/WLPZ9Q42m4IG5W0FNX8WLL2gYMZo3JkuXIH2DOpWM+qwA==", - "dev": true, - "dependencies": { - "@babel/helper-plugin-utils": "^7.0.0", - "@istanbuljs/load-nyc-config": "^1.0.0", - "@istanbuljs/schema": "^0.1.2", - "istanbul-lib-instrument": "^5.0.4", - "test-exclude": "^6.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/babel-plugin-istanbul/node_modules/istanbul-lib-instrument": { - "version": "5.2.1", - "resolved": "https://registry.npmjs.org/istanbul-lib-instrument/-/istanbul-lib-instrument-5.2.1.tgz", - "integrity": "sha512-pzqtp31nLv/XFOzXGuvhCb8qhjmTVo5vjVk19XE4CRlSWz0KoeJ3bw9XsA7nOp9YBf4qHjwBxkDzKcME/J29Yg==", - "dev": true, - "dependencies": { - "@babel/core": "^7.12.3", - "@babel/parser": "^7.14.7", - "@istanbuljs/schema": "^0.1.2", - "istanbul-lib-coverage": "^3.2.0", - "semver": "^6.3.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/babel-plugin-jest-hoist": { - "version": "29.6.3", - "resolved": "https://registry.npmjs.org/babel-plugin-jest-hoist/-/babel-plugin-jest-hoist-29.6.3.tgz", - "integrity": "sha512-ESAc/RJvGTFEzRwOTT4+lNDk/GNHMkKbNzsvT0qKRfDyyYTskxB5rnU2njIDYVxXCBHHEI1c0YwHob3WaYujOg==", - "dev": true, - "dependencies": { - "@babel/template": "^7.3.3", - "@babel/types": "^7.3.3", - "@types/babel__core": "^7.1.14", - "@types/babel__traverse": "^7.0.6" - }, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" - } - }, - "node_modules/babel-preset-current-node-syntax": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/babel-preset-current-node-syntax/-/babel-preset-current-node-syntax-1.1.0.tgz", - "integrity": "sha512-ldYss8SbBlWva1bs28q78Ju5Zq1F+8BrqBZZ0VFhLBvhh6lCpC2o3gDJi/5DRLs9FgYZCnmPYIVFU4lRXCkyUw==", - "dev": true, - "dependencies": { - "@babel/plugin-syntax-async-generators": "^7.8.4", - "@babel/plugin-syntax-bigint": "^7.8.3", - "@babel/plugin-syntax-class-properties": "^7.12.13", - "@babel/plugin-syntax-class-static-block": "^7.14.5", - "@babel/plugin-syntax-import-attributes": "^7.24.7", - "@babel/plugin-syntax-import-meta": "^7.10.4", - "@babel/plugin-syntax-json-strings": "^7.8.3", - "@babel/plugin-syntax-logical-assignment-operators": "^7.10.4", - "@babel/plugin-syntax-nullish-coalescing-operator": "^7.8.3", - "@babel/plugin-syntax-numeric-separator": "^7.10.4", - "@babel/plugin-syntax-object-rest-spread": "^7.8.3", - "@babel/plugin-syntax-optional-catch-binding": "^7.8.3", - "@babel/plugin-syntax-optional-chaining": "^7.8.3", - "@babel/plugin-syntax-private-property-in-object": "^7.14.5", - "@babel/plugin-syntax-top-level-await": "^7.14.5" - }, - "peerDependencies": { - "@babel/core": "^7.0.0" - } - }, - "node_modules/babel-preset-jest": { - "version": "29.6.3", - "resolved": "https://registry.npmjs.org/babel-preset-jest/-/babel-preset-jest-29.6.3.tgz", - "integrity": "sha512-0B3bhxR6snWXJZtR/RliHTDPRgn1sNHOR0yVtq/IiQFyuOVjFS+wuio/R4gSNkyYmKmJB4wGZv2NZanmKmTnNA==", - "dev": true, - "dependencies": { - "babel-plugin-jest-hoist": "^29.6.3", - "babel-preset-current-node-syntax": "^1.0.0" - }, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0" - } - }, - "node_modules/balanced-match": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", - "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==", - "dev": true - }, - "node_modules/brace-expansion": { - "version": "1.1.11", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", - "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", - "dev": true, - "dependencies": { - "balanced-match": "^1.0.0", - "concat-map": "0.0.1" - } - }, - "node_modules/braces": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.3.tgz", - "integrity": "sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==", - "dev": true, - "dependencies": { - "fill-range": "^7.1.1" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/browserslist": { - "version": "4.23.3", - "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.23.3.tgz", - "integrity": "sha512-btwCFJVjI4YWDNfau8RhZ+B1Q/VLoUITrm3RlP6y1tYGWIOa+InuYiRGXUBXo8nA1qKmHMyLB/iVQg5TT4eFoA==", - "dev": true, - "funding": [ - { - "type": "opencollective", - "url": "https://opencollective.com/browserslist" - }, - { - "type": "tidelift", - "url": "https://tidelift.com/funding/github/npm/browserslist" - }, - { - "type": "github", - "url": "https://github.com/sponsors/ai" - } - ], - "dependencies": { - "caniuse-lite": "^1.0.30001646", - "electron-to-chromium": "^1.5.4", - "node-releases": "^2.0.18", - "update-browserslist-db": "^1.1.0" - }, - "bin": { - "browserslist": "cli.js" - }, - "engines": { - "node": "^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7" - } - }, - "node_modules/bser": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/bser/-/bser-2.1.1.tgz", - "integrity": "sha512-gQxTNE/GAfIIrmHLUE3oJyp5FO6HRBfhjnw4/wMmA63ZGDJnWBmgY/lyQBpnDUkGmAhbSe39tx2d/iTOAfglwQ==", - "dev": true, - "dependencies": { - "node-int64": "^0.4.0" - } - }, - "node_modules/buffer-from": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.2.tgz", - "integrity": "sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==", - "dev": true - }, - "node_modules/builtins": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/builtins/-/builtins-5.0.1.tgz", - "integrity": "sha512-qwVpFEHNfhYJIzNRBvd2C1kyo6jz3ZSMPyyuR47OPdiKWlbYnZNyDWuyR175qDnAJLiCo5fBBqPb3RiXgWlkOQ==", - "dev": true, - "dependencies": { - "semver": "^7.0.0" - } - }, - "node_modules/builtins/node_modules/semver": { - "version": "7.5.4", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.5.4.tgz", - "integrity": "sha512-1bCSESV6Pv+i21Hvpxp3Dx+pSD8lIPt8uVjRrxAUt/nbswYc+tK6Y2btiULjd4+fnq15PX+nqQDC7Oft7WkwcA==", - "dev": true, - "dependencies": { - "lru-cache": "^6.0.0" - }, - "bin": { - "semver": "bin/semver.js" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/call-bind": { - "version": "1.0.7", - "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.7.tgz", - "integrity": "sha512-GHTSNSYICQ7scH7sZ+M2rFopRoLh8t2bLSW6BbgrtLsahOIB5iyAVJf9GjWK3cYTDaMj4XdBpM1cA6pIS0Kv2w==", - "dependencies": { - "es-define-property": "^1.0.0", - "es-errors": "^1.3.0", - "function-bind": "^1.1.2", - "get-intrinsic": "^1.2.4", - "set-function-length": "^1.2.1" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/callsites": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz", - "integrity": "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==", - "dev": true, - "engines": { - "node": ">=6" - } - }, - "node_modules/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.30001651", - "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001651.tgz", - "integrity": "sha512-9Cf+Xv1jJNe1xPZLGuUXLNkE1BoDkqRqYyFJ9TDYSqhduqA4hu4oR9HluGoWYQC/aj8WHjsGVV+bwkh0+tegRg==", - "dev": true, - "funding": [ - { - "type": "opencollective", - "url": "https://opencollective.com/browserslist" - }, - { - "type": "tidelift", - "url": "https://tidelift.com/funding/github/npm/caniuse-lite" - }, - { - "type": "github", - "url": "https://github.com/sponsors/ai" - } - ] - }, - "node_modules/chalk": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", - "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", - "dev": true, - "dependencies": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/chalk/chalk?sponsor=1" - } - }, - "node_modules/char-regex": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/char-regex/-/char-regex-1.0.2.tgz", - "integrity": "sha512-kWWXztvZ5SBQV+eRgKFeh8q5sLuZY2+8WUIzlxWVTg+oGwY14qylx1KbKzHd8P6ZYkAg0xyIDU9JMHhyJMZ1jw==", - "dev": true, - "engines": { - "node": ">=10" - } - }, - "node_modules/ci-info": { - "version": "3.9.0", - "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-3.9.0.tgz", - "integrity": "sha512-NIxF55hv4nSqQswkAeiOi1r83xy8JldOFDTWiug55KBu9Jnblncd2U6ViHmYgHf01TPZS77NJBhBMKdWj9HQMQ==", - "dev": true, - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/sibiraj-s" - } - ], - "engines": { - "node": ">=8" - } - }, - "node_modules/cjs-module-lexer": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/cjs-module-lexer/-/cjs-module-lexer-1.3.1.tgz", - "integrity": "sha512-a3KdPAANPbNE4ZUv9h6LckSl9zLsYOP4MBmhIPkRaeyybt+r4UghLvq+xw/YwUcC1gqylCkL4rdVs3Lwupjm4Q==", - "dev": true - }, - "node_modules/cliui": { - "version": "8.0.1", - "resolved": "https://registry.npmjs.org/cliui/-/cliui-8.0.1.tgz", - "integrity": "sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ==", - "dev": true, - "dependencies": { - "string-width": "^4.2.0", - "strip-ansi": "^6.0.1", - "wrap-ansi": "^7.0.0" - }, - "engines": { - "node": ">=12" - } - }, - "node_modules/co": { - "version": "4.6.0", - "resolved": "https://registry.npmjs.org/co/-/co-4.6.0.tgz", - "integrity": "sha512-QVb0dM5HvG+uaxitm8wONl7jltx8dqhfU33DcqtOZcLSVIKSDDLDi7+0LbAKiyI8hD9u42m2YxXSkMGWThaecQ==", - "dev": true, - "engines": { - "iojs": ">= 1.0.0", - "node": ">= 0.12.0" - } - }, - "node_modules/collect-v8-coverage": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/collect-v8-coverage/-/collect-v8-coverage-1.0.2.tgz", - "integrity": "sha512-lHl4d5/ONEbLlJvaJNtsF/Lz+WvB07u2ycqTYbdrq7UypDXailES4valYb2eWiJFxZlVmpGekfqoxQhzyFdT4Q==", - "dev": true - }, - "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/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/combined-stream": { - "version": "1.0.8", - "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz", - "integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==", - "dependencies": { - "delayed-stream": "~1.0.0" - }, - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/concat-map": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", - "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==", - "dev": true - }, - "node_modules/convert-source-map": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-2.0.0.tgz", - "integrity": "sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg==", - "dev": true - }, - "node_modules/create-jest": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/create-jest/-/create-jest-29.7.0.tgz", - "integrity": "sha512-Adz2bdH0Vq3F53KEMJOoftQFutWCukm6J24wbPWRO4k1kMY7gS7ds/uoJkNuV8wDCtWWnuwGcJwpWcih+zEW1Q==", - "dev": true, - "dependencies": { - "@jest/types": "^29.6.3", - "chalk": "^4.0.0", - "exit": "^0.1.2", - "graceful-fs": "^4.2.9", - "jest-config": "^29.7.0", - "jest-util": "^29.7.0", - "prompts": "^2.0.1" - }, - "bin": { - "create-jest": "bin/create-jest.js" - }, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" - } - }, - "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/debug": { - "version": "4.3.1", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.1.tgz", - "integrity": "sha512-doEwdvm4PCeK4K3RQN2ZC2BYUBaxwLARCqZmMjtF8a51J2Rb0xpVloFRnCODwqjpwnAoao4pelN8l3RJdv3gRQ==", - "dev": true, - "dependencies": { - "ms": "2.1.2" - }, - "engines": { - "node": ">=6.0" - }, - "peerDependenciesMeta": { - "supports-color": { - "optional": true - } - } - }, - "node_modules/dedent": { - "version": "1.5.3", - "resolved": "https://registry.npmjs.org/dedent/-/dedent-1.5.3.tgz", - "integrity": "sha512-NHQtfOOW68WD8lgypbLA5oT+Bt0xXJhiYvoR6SmmNXZfpzOGXwdKWmcwG8N7PwVVWV3eF/68nmD9BaJSsTBhyQ==", - "dev": true, - "peerDependencies": { - "babel-plugin-macros": "^3.1.0" - }, - "peerDependenciesMeta": { - "babel-plugin-macros": { - "optional": true - } - } - }, - "node_modules/deep-is": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.4.tgz", - "integrity": "sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==", - "dev": true - }, - "node_modules/deepmerge": { - "version": "4.3.1", - "resolved": "https://registry.npmjs.org/deepmerge/-/deepmerge-4.3.1.tgz", - "integrity": "sha512-3sUqbMEc77XqpdNO7FRyRog+eW3ph+GYCbj+rK+uYyRMuwsVy0rMiVtPn+QJlKFvWP/1PYpapqYn0Me2knFn+A==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/define-data-property": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/define-data-property/-/define-data-property-1.1.4.tgz", - "integrity": "sha512-rBMvIzlpA8v6E+SJZoo++HAYqsLrkg7MSfIinMPFhmkorw7X+dOXVJQs+QT69zGkzMyfDnIMN2Wid1+NbL3T+A==", - "dependencies": { - "es-define-property": "^1.0.0", - "es-errors": "^1.3.0", - "gopd": "^1.0.1" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/define-properties": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.2.1.tgz", - "integrity": "sha512-8QmQKqEASLd5nx0U1B1okLElbUuuttJ/AnYmRXbbbGDWh6uS208EjD4Xqq/I9wK7u0v6O08XhTWnt5XtEbR6Dg==", - "dev": true, - "dependencies": { - "define-data-property": "^1.0.1", - "has-property-descriptors": "^1.0.0", - "object-keys": "^1.1.1" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/delayed-stream": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", - "integrity": "sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==", - "engines": { - "node": ">=0.4.0" - } - }, - "node_modules/detect-newline": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/detect-newline/-/detect-newline-3.1.0.tgz", - "integrity": "sha512-TLz+x/vEXm/Y7P7wn1EJFNLxYpUD4TgMosxY6fAVJUnJMbupHBOncxyWUG9OpTaH9EBD7uFI5LfEgmMOc54DsA==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "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": "^14.15.0 || ^16.10.0 || >=18.0.0" - } - }, - "node_modules/doctrine": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-3.0.0.tgz", - "integrity": "sha512-yS+Q5i3hBf7GBkd4KG8a7eBNNWNGLTaEwwYWUijIYM7zrlYDM0BFXHjjPWlWZ1Rg7UaddZeIDmi9jF3HmqiQ2w==", - "dev": true, - "dependencies": { - "esutils": "^2.0.2" - }, - "engines": { - "node": ">=6.0.0" - } - }, - "node_modules/electron-to-chromium": { - "version": "1.5.7", - "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.7.tgz", - "integrity": "sha512-6FTNWIWMxMy/ZY6799nBlPtF1DFDQ6VQJ7yyDP27SJNt5lwtQ5ufqVvHylb3fdQefvRcgA3fKcFMJi9OLwBRNw==", - "dev": true - }, - "node_modules/emittery": { - "version": "0.13.1", - "resolved": "https://registry.npmjs.org/emittery/-/emittery-0.13.1.tgz", - "integrity": "sha512-DeWwawk6r5yR9jFgnDKYt4sLS0LmHJJi3ZOnb5/JdbYwj3nW+FxQnHIjhBKz8YLC7oRNPVM9NQ47I3CVx34eqQ==", - "dev": true, - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/sindresorhus/emittery?sponsor=1" - } - }, - "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", - "integrity": "sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g==", - "dev": true, - "dependencies": { - "is-arrayish": "^0.2.1" - } - }, - "node_modules/es-abstract": { - "version": "1.22.3", - "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.22.3.tgz", - "integrity": "sha512-eiiY8HQeYfYH2Con2berK+To6GrK2RxbPawDkGq4UiCQQfZHb6wX9qQqkbpPqaxQFcl8d9QzZqo0tGE0VcrdwA==", - "dev": true, - "dependencies": { - "array-buffer-byte-length": "^1.0.0", - "arraybuffer.prototype.slice": "^1.0.2", - "available-typed-arrays": "^1.0.5", - "call-bind": "^1.0.5", - "es-set-tostringtag": "^2.0.1", - "es-to-primitive": "^1.2.1", - "function.prototype.name": "^1.1.6", - "get-intrinsic": "^1.2.2", - "get-symbol-description": "^1.0.0", - "globalthis": "^1.0.3", - "gopd": "^1.0.1", - "has-property-descriptors": "^1.0.0", - "has-proto": "^1.0.1", - "has-symbols": "^1.0.3", - "hasown": "^2.0.0", - "internal-slot": "^1.0.5", - "is-array-buffer": "^3.0.2", - "is-callable": "^1.2.7", - "is-negative-zero": "^2.0.2", - "is-regex": "^1.1.4", - "is-shared-array-buffer": "^1.0.2", - "is-string": "^1.0.7", - "is-typed-array": "^1.1.12", - "is-weakref": "^1.0.2", - "object-inspect": "^1.13.1", - "object-keys": "^1.1.1", - "object.assign": "^4.1.4", - "regexp.prototype.flags": "^1.5.1", - "safe-array-concat": "^1.0.1", - "safe-regex-test": "^1.0.0", - "string.prototype.trim": "^1.2.8", - "string.prototype.trimend": "^1.0.7", - "string.prototype.trimstart": "^1.0.7", - "typed-array-buffer": "^1.0.0", - "typed-array-byte-length": "^1.0.0", - "typed-array-byte-offset": "^1.0.0", - "typed-array-length": "^1.0.4", - "unbox-primitive": "^1.0.2", - "which-typed-array": "^1.1.13" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/es-define-property": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/es-define-property/-/es-define-property-1.0.0.tgz", - "integrity": "sha512-jxayLKShrEqqzJ0eumQbVhTYQM27CfT1T35+gCgDFoL82JLsXqTJ76zv6A0YLOgEnLUMvLzsDsGIrl8NFpT2gQ==", - "dependencies": { - "get-intrinsic": "^1.2.4" - }, - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/es-errors": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/es-errors/-/es-errors-1.3.0.tgz", - "integrity": "sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==", - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/es-iterator-helpers": { - "version": "1.0.15", - "resolved": "https://registry.npmjs.org/es-iterator-helpers/-/es-iterator-helpers-1.0.15.tgz", - "integrity": "sha512-GhoY8uYqd6iwUl2kgjTm4CZAf6oo5mHK7BPqx3rKgx893YSsy0LGHV6gfqqQvZt/8xM8xeOnfXBCfqclMKkJ5g==", - "dev": true, - "dependencies": { - "asynciterator.prototype": "^1.0.0", - "call-bind": "^1.0.2", - "define-properties": "^1.2.1", - "es-abstract": "^1.22.1", - "es-set-tostringtag": "^2.0.1", - "function-bind": "^1.1.1", - "get-intrinsic": "^1.2.1", - "globalthis": "^1.0.3", - "has-property-descriptors": "^1.0.0", - "has-proto": "^1.0.1", - "has-symbols": "^1.0.3", - "internal-slot": "^1.0.5", - "iterator.prototype": "^1.1.2", - "safe-array-concat": "^1.0.1" - } - }, - "node_modules/es-set-tostringtag": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/es-set-tostringtag/-/es-set-tostringtag-2.0.2.tgz", - "integrity": "sha512-BuDyupZt65P9D2D2vA/zqcI3G5xRsklm5N3xCwuiy+/vKy8i0ifdsQP1sLgO4tZDSCaQUSnmC48khknGMV3D2Q==", - "dev": true, - "dependencies": { - "get-intrinsic": "^1.2.2", - "has-tostringtag": "^1.0.0", - "hasown": "^2.0.0" - }, - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/es-shim-unscopables": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/es-shim-unscopables/-/es-shim-unscopables-1.0.0.tgz", - "integrity": "sha512-Jm6GPcCdC30eMLbZ2x8z2WuRwAws3zTBBKuusffYVUrNj/GVSUAZ+xKMaUpfNDR5IbyNA5LJbaecoUVbmUcB1w==", - "dev": true, - "dependencies": { - "has": "^1.0.3" - } - }, - "node_modules/es-to-primitive": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/es-to-primitive/-/es-to-primitive-1.2.1.tgz", - "integrity": "sha512-QCOllgZJtaUo9miYBcLChTUaHNjJF3PYs1VidD7AwiEj1kYxKeQTctLAezAOH5ZKRH0g2IgPn6KwB4IT8iRpvA==", - "dev": true, - "dependencies": { - "is-callable": "^1.1.4", - "is-date-object": "^1.0.1", - "is-symbol": "^1.0.2" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/escalade": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.1.2.tgz", - "integrity": "sha512-ErCHMCae19vR8vQGe50xIsVomy19rg6gFu3+r3jkEO46suLMWBksvVyoGgQV+jOfl84ZSOSlmv6Gxa89PmTGmA==", - "dev": true, - "engines": { - "node": ">=6" - } - }, - "node_modules/escape-string-regexp": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-2.0.0.tgz", - "integrity": "sha512-UpzcLCXolUWcNu5HtVMHYdXJjArjsF9C0aNnquZYY4uW/Vu0miy5YoWvbV345HauVvcAUnpRuhMMcqTcGOY2+w==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/eslint": { - "version": "8.53.0", - "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.53.0.tgz", - "integrity": "sha512-N4VuiPjXDUa4xVeV/GC/RV3hQW9Nw+Y463lkWaKKXKYMvmRiRDAtfpuPFLN+E1/6ZhyR8J2ig+eVREnYgUsiag==", - "dev": true, - "dependencies": { - "@eslint-community/eslint-utils": "^4.2.0", - "@eslint-community/regexpp": "^4.6.1", - "@eslint/eslintrc": "^2.1.3", - "@eslint/js": "8.53.0", - "@humanwhocodes/config-array": "^0.11.13", - "@humanwhocodes/module-importer": "^1.0.1", - "@nodelib/fs.walk": "^1.2.8", - "@ungap/structured-clone": "^1.2.0", - "ajv": "^6.12.4", - "chalk": "^4.0.0", - "cross-spawn": "^7.0.2", - "debug": "^4.3.2", - "doctrine": "^3.0.0", - "escape-string-regexp": "^4.0.0", - "eslint-scope": "^7.2.2", - "eslint-visitor-keys": "^3.4.3", - "espree": "^9.6.1", - "esquery": "^1.4.2", - "esutils": "^2.0.2", - "fast-deep-equal": "^3.1.3", - "file-entry-cache": "^6.0.1", - "find-up": "^5.0.0", - "glob-parent": "^6.0.2", - "globals": "^13.19.0", - "graphemer": "^1.4.0", - "ignore": "^5.2.0", - "imurmurhash": "^0.1.4", - "is-glob": "^4.0.0", - "is-path-inside": "^3.0.3", - "js-yaml": "^4.1.0", - "json-stable-stringify-without-jsonify": "^1.0.1", - "levn": "^0.4.1", - "lodash.merge": "^4.6.2", - "minimatch": "^3.1.2", - "natural-compare": "^1.4.0", - "optionator": "^0.9.3", - "strip-ansi": "^6.0.1", - "text-table": "^0.2.0" - }, - "bin": { - "eslint": "bin/eslint.js" - }, - "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" - }, - "funding": { - "url": "https://opencollective.com/eslint" - } - }, - "node_modules/eslint-config-standard": { - "version": "17.1.0", - "resolved": "https://registry.npmjs.org/eslint-config-standard/-/eslint-config-standard-17.1.0.tgz", - "integrity": "sha512-IwHwmaBNtDK4zDHQukFDW5u/aTb8+meQWZvNFWkiGmbWjD6bqyuSSBxxXKkCftCUzc1zwCH2m/baCNDLGmuO5Q==", - "dev": true, - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/feross" - }, - { - "type": "patreon", - "url": "https://www.patreon.com/feross" - }, - { - "type": "consulting", - "url": "https://feross.org/support" - } - ], - "engines": { - "node": ">=12.0.0" - }, - "peerDependencies": { - "eslint": "^8.0.1", - "eslint-plugin-import": "^2.25.2", - "eslint-plugin-n": "^15.0.0 || ^16.0.0 ", - "eslint-plugin-promise": "^6.0.0" - } - }, - "node_modules/eslint-config-standard-jsx": { - "version": "11.0.0", - "resolved": "https://registry.npmjs.org/eslint-config-standard-jsx/-/eslint-config-standard-jsx-11.0.0.tgz", - "integrity": "sha512-+1EV/R0JxEK1L0NGolAr8Iktm3Rgotx3BKwgaX+eAuSX8D952LULKtjgZD3F+e6SvibONnhLwoTi9DPxN5LvvQ==", - "dev": true, - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/feross" - }, - { - "type": "patreon", - "url": "https://www.patreon.com/feross" - }, - { - "type": "consulting", - "url": "https://feross.org/support" - } - ], - "peerDependencies": { - "eslint": "^8.8.0", - "eslint-plugin-react": "^7.28.0" - } - }, - "node_modules/eslint-import-resolver-node": { - "version": "0.3.9", - "resolved": "https://registry.npmjs.org/eslint-import-resolver-node/-/eslint-import-resolver-node-0.3.9.tgz", - "integrity": "sha512-WFj2isz22JahUv+B788TlO3N6zL3nNJGU8CcZbPZvVEkBPaJdCV4vy5wyghty5ROFbCRnm132v8BScu5/1BQ8g==", - "dev": true, - "dependencies": { - "debug": "^3.2.7", - "is-core-module": "^2.13.0", - "resolve": "^1.22.4" - } - }, - "node_modules/eslint-import-resolver-node/node_modules/debug": { - "version": "3.2.7", - "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz", - "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==", - "dev": true, - "dependencies": { - "ms": "^2.1.1" - } - }, - "node_modules/eslint-module-utils": { - "version": "2.8.0", - "resolved": "https://registry.npmjs.org/eslint-module-utils/-/eslint-module-utils-2.8.0.tgz", - "integrity": "sha512-aWajIYfsqCKRDgUfjEXNN/JlrzauMuSEy5sbd7WXbtW3EH6A6MpwEh42c7qD+MqQo9QMJ6fWLAeIJynx0g6OAw==", - "dev": true, - "dependencies": { - "debug": "^3.2.7" - }, - "engines": { - "node": ">=4" - }, - "peerDependenciesMeta": { - "eslint": { - "optional": true - } - } - }, - "node_modules/eslint-module-utils/node_modules/debug": { - "version": "3.2.7", - "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz", - "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==", - "dev": true, - "dependencies": { - "ms": "^2.1.1" - } - }, - "node_modules/eslint-plugin-es": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/eslint-plugin-es/-/eslint-plugin-es-4.1.0.tgz", - "integrity": "sha512-GILhQTnjYE2WorX5Jyi5i4dz5ALWxBIdQECVQavL6s7cI76IZTDWleTHkxz/QT3kvcs2QlGHvKLYsSlPOlPXnQ==", - "dev": true, - "dependencies": { - "eslint-utils": "^2.0.0", - "regexpp": "^3.0.0" - }, - "engines": { - "node": ">=8.10.0" - }, - "funding": { - "url": "https://github.com/sponsors/mysticatea" - }, - "peerDependencies": { - "eslint": ">=4.19.1" - } - }, - "node_modules/eslint-plugin-es/node_modules/eslint-utils": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/eslint-utils/-/eslint-utils-2.1.0.tgz", - "integrity": "sha512-w94dQYoauyvlDc43XnGB8lU3Zt713vNChgt4EWwhXAP2XkBvndfxF0AgIqKOOasjPIPzj9JqgwkwbCYD0/V3Zg==", - "dev": true, - "dependencies": { - "eslint-visitor-keys": "^1.1.0" - }, - "engines": { - "node": ">=6" - }, - "funding": { - "url": "https://github.com/sponsors/mysticatea" - } - }, - "node_modules/eslint-plugin-es/node_modules/eslint-visitor-keys": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-1.3.0.tgz", - "integrity": "sha512-6J72N8UNa462wa/KFODt/PJ3IU60SDpC3QXC1Hjc1BXXpfL2C9R5+AU7jhe0F6GREqVMh4Juu+NY7xn+6dipUQ==", - "dev": true, - "engines": { - "node": ">=4" - } - }, - "node_modules/eslint-plugin-import": { - "version": "2.29.0", - "resolved": "https://registry.npmjs.org/eslint-plugin-import/-/eslint-plugin-import-2.29.0.tgz", - "integrity": "sha512-QPOO5NO6Odv5lpoTkddtutccQjysJuFxoPS7fAHO+9m9udNHvTCPSAMW9zGAYj8lAIdr40I8yPCdUYrncXtrwg==", - "dev": true, - "dependencies": { - "array-includes": "^3.1.7", - "array.prototype.findlastindex": "^1.2.3", - "array.prototype.flat": "^1.3.2", - "array.prototype.flatmap": "^1.3.2", - "debug": "^3.2.7", - "doctrine": "^2.1.0", - "eslint-import-resolver-node": "^0.3.9", - "eslint-module-utils": "^2.8.0", - "hasown": "^2.0.0", - "is-core-module": "^2.13.1", - "is-glob": "^4.0.3", - "minimatch": "^3.1.2", - "object.fromentries": "^2.0.7", - "object.groupby": "^1.0.1", - "object.values": "^1.1.7", - "semver": "^6.3.1", - "tsconfig-paths": "^3.14.2" - }, - "engines": { - "node": ">=4" - }, - "peerDependencies": { - "eslint": "^2 || ^3 || ^4 || ^5 || ^6 || ^7.2.0 || ^8" - } - }, - "node_modules/eslint-plugin-import/node_modules/debug": { - "version": "3.2.7", - "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz", - "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==", - "dev": true, - "dependencies": { - "ms": "^2.1.1" - } - }, - "node_modules/eslint-plugin-import/node_modules/doctrine": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-2.1.0.tgz", - "integrity": "sha512-35mSku4ZXK0vfCuHEDAwt55dg2jNajHZ1odvF+8SSr82EsZY4QmXfuWso8oEd8zRhVObSN18aM0CjSdoBX7zIw==", - "dev": true, - "dependencies": { - "esutils": "^2.0.2" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/eslint-plugin-n": { - "version": "15.7.0", - "resolved": "https://registry.npmjs.org/eslint-plugin-n/-/eslint-plugin-n-15.7.0.tgz", - "integrity": "sha512-jDex9s7D/Qial8AGVIHq4W7NswpUD5DPDL2RH8Lzd9EloWUuvUkHfv4FRLMipH5q2UtyurorBkPeNi1wVWNh3Q==", - "dev": true, - "dependencies": { - "builtins": "^5.0.1", - "eslint-plugin-es": "^4.1.0", - "eslint-utils": "^3.0.0", - "ignore": "^5.1.1", - "is-core-module": "^2.11.0", - "minimatch": "^3.1.2", - "resolve": "^1.22.1", - "semver": "^7.3.8" - }, - "engines": { - "node": ">=12.22.0" - }, - "funding": { - "url": "https://github.com/sponsors/mysticatea" - }, - "peerDependencies": { - "eslint": ">=7.0.0" - } - }, - "node_modules/eslint-plugin-n/node_modules/semver": { - "version": "7.5.4", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.5.4.tgz", - "integrity": "sha512-1bCSESV6Pv+i21Hvpxp3Dx+pSD8lIPt8uVjRrxAUt/nbswYc+tK6Y2btiULjd4+fnq15PX+nqQDC7Oft7WkwcA==", - "dev": true, - "dependencies": { - "lru-cache": "^6.0.0" - }, - "bin": { - "semver": "bin/semver.js" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/eslint-plugin-promise": { - "version": "6.1.1", - "resolved": "https://registry.npmjs.org/eslint-plugin-promise/-/eslint-plugin-promise-6.1.1.tgz", - "integrity": "sha512-tjqWDwVZQo7UIPMeDReOpUgHCmCiH+ePnVT+5zVapL0uuHnegBUs2smM13CzOs2Xb5+MHMRFTs9v24yjba4Oig==", - "dev": true, - "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" - }, - "peerDependencies": { - "eslint": "^7.0.0 || ^8.0.0" - } - }, - "node_modules/eslint-plugin-react": { - "version": "7.33.2", - "resolved": "https://registry.npmjs.org/eslint-plugin-react/-/eslint-plugin-react-7.33.2.tgz", - "integrity": "sha512-73QQMKALArI8/7xGLNI/3LylrEYrlKZSb5C9+q3OtOewTnMQi5cT+aE9E41sLCmli3I9PGGmD1yiZydyo4FEPw==", - "dev": true, - "dependencies": { - "array-includes": "^3.1.6", - "array.prototype.flatmap": "^1.3.1", - "array.prototype.tosorted": "^1.1.1", - "doctrine": "^2.1.0", - "es-iterator-helpers": "^1.0.12", - "estraverse": "^5.3.0", - "jsx-ast-utils": "^2.4.1 || ^3.0.0", - "minimatch": "^3.1.2", - "object.entries": "^1.1.6", - "object.fromentries": "^2.0.6", - "object.hasown": "^1.1.2", - "object.values": "^1.1.6", - "prop-types": "^15.8.1", - "resolve": "^2.0.0-next.4", - "semver": "^6.3.1", - "string.prototype.matchall": "^4.0.8" - }, - "engines": { - "node": ">=4" - }, - "peerDependencies": { - "eslint": "^3 || ^4 || ^5 || ^6 || ^7 || ^8" - } - }, - "node_modules/eslint-plugin-react/node_modules/doctrine": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-2.1.0.tgz", - "integrity": "sha512-35mSku4ZXK0vfCuHEDAwt55dg2jNajHZ1odvF+8SSr82EsZY4QmXfuWso8oEd8zRhVObSN18aM0CjSdoBX7zIw==", - "dev": true, - "dependencies": { - "esutils": "^2.0.2" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/eslint-plugin-react/node_modules/resolve": { - "version": "2.0.0-next.4", - "resolved": "https://registry.npmjs.org/resolve/-/resolve-2.0.0-next.4.tgz", - "integrity": "sha512-iMDbmAWtfU+MHpxt/I5iWI7cY6YVEZUQ3MBgPQ++XD1PELuJHIl82xBmObyP2KyQmkNB2dsqF7seoQQiAn5yDQ==", - "dev": true, - "dependencies": { - "is-core-module": "^2.9.0", - "path-parse": "^1.0.7", - "supports-preserve-symlinks-flag": "^1.0.0" - }, - "bin": { - "resolve": "bin/resolve" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/eslint-scope": { - "version": "7.2.2", - "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-7.2.2.tgz", - "integrity": "sha512-dOt21O7lTMhDM+X9mB4GX+DZrZtCUJPL/wlcTqxyrx5IvO0IYtILdtrQGQp+8n5S0gwSVmOf9NQrjMOgfQZlIg==", - "dev": true, - "dependencies": { - "esrecurse": "^4.3.0", - "estraverse": "^5.2.0" - }, - "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" - }, - "funding": { - "url": "https://opencollective.com/eslint" - } - }, - "node_modules/eslint-utils": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/eslint-utils/-/eslint-utils-3.0.0.tgz", - "integrity": "sha512-uuQC43IGctw68pJA1RgbQS8/NP7rch6Cwd4j3ZBtgo4/8Flj4eGE7ZYSZRN3iq5pVUv6GPdW5Z1RFleo84uLDA==", - "dev": true, - "dependencies": { - "eslint-visitor-keys": "^2.0.0" - }, - "engines": { - "node": "^10.0.0 || ^12.0.0 || >= 14.0.0" - }, - "funding": { - "url": "https://github.com/sponsors/mysticatea" - }, - "peerDependencies": { - "eslint": ">=5" - } - }, - "node_modules/eslint-utils/node_modules/eslint-visitor-keys": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-2.1.0.tgz", - "integrity": "sha512-0rSmRBzXgDzIsD6mGdJgevzgezI534Cer5L/vyMX0kHzT/jiB43jRhd9YUlMGYLQy2zprNmoT8qasCGtY+QaKw==", - "dev": true, - "engines": { - "node": ">=10" - } - }, - "node_modules/eslint-visitor-keys": { - "version": "3.4.3", - "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.4.3.tgz", - "integrity": "sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag==", - "dev": true, - "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" - }, - "funding": { - "url": "https://opencollective.com/eslint" - } - }, - "node_modules/eslint/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/node_modules/debug": { - "version": "4.3.4", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", - "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", - "dev": true, - "dependencies": { - "ms": "2.1.2" - }, - "engines": { - "node": ">=6.0" - }, - "peerDependenciesMeta": { - "supports-color": { - "optional": true - } - } - }, - "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", - "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==", - "dev": true, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/eslint/node_modules/find-up": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz", - "integrity": "sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==", - "dev": true, - "dependencies": { - "locate-path": "^6.0.0", - "path-exists": "^4.0.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/eslint/node_modules/globals": { - "version": "13.23.0", - "resolved": "https://registry.npmjs.org/globals/-/globals-13.23.0.tgz", - "integrity": "sha512-XAmF0RjlrjY23MA51q3HltdlGxUpXPvg0GioKiD9X6HD28iMjo2dKC8Vqwm7lne4GNr78+RHTfliktR6ZH09wA==", - "dev": true, - "dependencies": { - "type-fest": "^0.20.2" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/eslint/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" - } - }, - "node_modules/eslint/node_modules/locate-path": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz", - "integrity": "sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==", - "dev": true, - "dependencies": { - "p-locate": "^5.0.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/eslint/node_modules/p-locate": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-5.0.0.tgz", - "integrity": "sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==", - "dev": true, - "dependencies": { - "p-limit": "^3.0.2" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/eslint/node_modules/type-fest": { - "version": "0.20.2", - "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.20.2.tgz", - "integrity": "sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ==", - "dev": true, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/espree": { - "version": "9.6.1", - "resolved": "https://registry.npmjs.org/espree/-/espree-9.6.1.tgz", - "integrity": "sha512-oruZaFkjorTpF32kDSI5/75ViwGeZginGGy2NoOSg3Q9bnwlnmDm4HLnkl0RE3n+njDXR037aY1+x58Z/zFdwQ==", - "dev": true, - "dependencies": { - "acorn": "^8.9.0", - "acorn-jsx": "^5.3.2", - "eslint-visitor-keys": "^3.4.1" - }, - "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" - }, - "funding": { - "url": "https://opencollective.com/eslint" - } - }, - "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", - "integrity": "sha512-YQLXUplAwJgCydQ78IMJywZCceoqk1oH01OERdSAJc/7U2AylwjhSCLDEtqwg811idIS/9fIU5GjG73IgjKMVg==", - "dev": true, - "dependencies": { - "estraverse": "^5.1.0" - }, - "engines": { - "node": ">=0.10" - } - }, - "node_modules/esrecurse": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.3.0.tgz", - "integrity": "sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==", - "dev": true, - "dependencies": { - "estraverse": "^5.2.0" - }, - "engines": { - "node": ">=4.0" - } - }, - "node_modules/estraverse": { - "version": "5.3.0", - "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz", - "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==", - "dev": true, - "engines": { - "node": ">=4.0" - } - }, - "node_modules/esutils": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz", - "integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/execa": { - "version": "5.1.1", - "resolved": "https://registry.npmjs.org/execa/-/execa-5.1.1.tgz", - "integrity": "sha512-8uSpZZocAZRBAPIEINJj3Lo9HyGitllczc27Eh5YYojjMFMn8yHMDMaUHE2Jqfq05D/wucwI4JGURyXt1vchyg==", - "dev": true, - "dependencies": { - "cross-spawn": "^7.0.3", - "get-stream": "^6.0.0", - "human-signals": "^2.1.0", - "is-stream": "^2.0.0", - "merge-stream": "^2.0.0", - "npm-run-path": "^4.0.1", - "onetime": "^5.1.2", - "signal-exit": "^3.0.3", - "strip-final-newline": "^2.0.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sindresorhus/execa?sponsor=1" - } - }, - "node_modules/exit": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/exit/-/exit-0.1.2.tgz", - "integrity": "sha512-Zk/eNKV2zbjpKzrsQ+n1G6poVbErQxJ0LBOJXaKZ1EViLzH+hrLu9cdXI4zw9dBQJslwBEpbQ2P1oS7nDxs6jQ==", - "dev": true, - "engines": { - "node": ">= 0.8.0" - } - }, - "node_modules/expect": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/expect/-/expect-29.7.0.tgz", - "integrity": "sha512-2Zks0hf1VLFYI1kbh0I5jP3KHHyCHpkfyHBzsSXRFgl/Bg9mWYfMW8oD+PdMPlEwy5HNsR9JutYy6pMeOh61nw==", - "dev": true, - "dependencies": { - "@jest/expect-utils": "^29.7.0", - "jest-get-type": "^29.6.3", - "jest-matcher-utils": "^29.7.0", - "jest-message-util": "^29.7.0", - "jest-util": "^29.7.0" - }, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" - } - }, - "node_modules/fast-deep-equal": { - "version": "3.1.3", - "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", - "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==", - "dev": true - }, - "node_modules/fast-json-stable-stringify": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz", - "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==", - "dev": true - }, - "node_modules/fast-levenshtein": { - "version": "2.0.6", - "resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz", - "integrity": "sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==", - "dev": true - }, - "node_modules/fastq": { - "version": "1.13.0", - "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.13.0.tgz", - "integrity": "sha512-YpkpUnK8od0o1hmeSc7UUs/eB/vIPWJYjKck2QKIzAf71Vm1AAQ3EbuZB3g2JIy+pg+ERD0vqI79KyZiB2e2Nw==", - "dev": true, - "dependencies": { - "reusify": "^1.0.4" - } - }, - "node_modules/fb-watchman": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/fb-watchman/-/fb-watchman-2.0.2.tgz", - "integrity": "sha512-p5161BqbuCaSnB8jIbzQHOlpgsPmK5rJVDfDKO91Axs5NC1uu3HRQm6wt9cd9/+GtQQIO53JdGXXoyDpTAsgYA==", - "dev": true, - "dependencies": { - "bser": "2.1.1" - } - }, - "node_modules/file-entry-cache": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-6.0.1.tgz", - "integrity": "sha512-7Gps/XWymbLk2QLYK4NzpMOrYjMhdIxXuIvy2QBsLE6ljuodKvdkWs/cpyJJ3CVIVpH0Oi1Hvg1ovbMzLdFBBg==", - "dev": true, - "dependencies": { - "flat-cache": "^3.0.4" - }, - "engines": { - "node": "^10.12.0 || >=12.0.0" - } - }, - "node_modules/fill-range": { - "version": "7.1.1", - "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.1.1.tgz", - "integrity": "sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==", - "dev": true, - "dependencies": { - "to-regex-range": "^5.0.1" - }, - "engines": { - "node": ">=8" - } - }, - "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/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/flatted": { - "version": "3.2.7", - "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.2.7.tgz", - "integrity": "sha512-5nqDSxl8nn5BSNxyR3n4I6eDmbolI6WT+QqR547RwxQapgjQBmtktdP+HTBb/a/zLsbzERTONyUB5pefh5TtjQ==", - "dev": true - }, - "node_modules/follow-redirects": { - "version": "1.15.6", - "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.6.tgz", - "integrity": "sha512-wWN62YITEaOpSK584EZXJafH1AGpO8RVgElfkuXbTOrPX4fIfOyEpW/CsiNd8JdYrAoOvafRTOEnvsO++qCqFA==", - "funding": [ - { - "type": "individual", - "url": "https://github.com/sponsors/RubenVerborgh" - } - ], - "engines": { - "node": ">=4.0" - }, - "peerDependenciesMeta": { - "debug": { - "optional": 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/form-data": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.0.tgz", - "integrity": "sha512-ETEklSGi5t0QMZuiXoA/Q6vcnxcLQP5vdugSpuAyi6SVGi2clPPp+xgEhuMaHC+zGgn31Kd235W35f7Hykkaww==", - "dependencies": { - "asynckit": "^0.4.0", - "combined-stream": "^1.0.8", - "mime-types": "^2.1.12" - }, - "engines": { - "node": ">= 6" - } - }, - "node_modules/fs.realpath": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", - "integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==", - "dev": true - }, - "node_modules/fsevents": { - "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, - "os": [ - "darwin" - ], - "engines": { - "node": "^8.16.0 || ^10.6.0 || >=11.0.0" - } - }, - "node_modules/function-bind": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz", - "integrity": "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==", - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/function.prototype.name": { - "version": "1.1.6", - "resolved": "https://registry.npmjs.org/function.prototype.name/-/function.prototype.name-1.1.6.tgz", - "integrity": "sha512-Z5kx79swU5P27WEayXM1tBi5Ze/lbIyiNgU3qyXUOf9b2rgXYyF9Dy9Cx+IQv/Lc8WCG6L82zwUPpSS9hGehIg==", - "dev": true, - "dependencies": { - "call-bind": "^1.0.2", - "define-properties": "^1.2.0", - "es-abstract": "^1.22.1", - "functions-have-names": "^1.2.3" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/functions-have-names": { - "version": "1.2.3", - "resolved": "https://registry.npmjs.org/functions-have-names/-/functions-have-names-1.2.3.tgz", - "integrity": "sha512-xckBUXyTIqT97tq2x2AMb+g163b5JFysYk0x4qxNFwbfQkmNZoiRHb6sPzI9/QV33WeuvVYBUIiD4NzNIyqaRQ==", - "dev": true, - "funding": { - "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-intrinsic": { - "version": "1.2.4", - "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.2.4.tgz", - "integrity": "sha512-5uYhsJH8VJBTv7oslg4BznJYhDoRI6waYCxMmCdnTrcCrHA/fCFKoTFz2JKKE0HdDFUF7/oQuhzumXJK7paBRQ==", - "dependencies": { - "es-errors": "^1.3.0", - "function-bind": "^1.1.2", - "has-proto": "^1.0.1", - "has-symbols": "^1.0.3", - "hasown": "^2.0.0" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "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==", - "dev": true, - "engines": { - "node": ">=8.0.0" - } - }, - "node_modules/get-stdin": { - "version": "8.0.0", - "resolved": "https://registry.npmjs.org/get-stdin/-/get-stdin-8.0.0.tgz", - "integrity": "sha512-sY22aA6xchAzprjyqmSEQv4UbAAzRN0L2dQB0NlN5acTTK9Don6nhoc3eAbUnpZiCANAMfd/+40kVdKfFygohg==", - "dev": true, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/get-stream": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-6.0.1.tgz", - "integrity": "sha512-ts6Wi+2j3jQjqi70w5AlN8DFnkSwC+MqmxEzdEALB2qXZYV3X/b1CTfgPLGJNMeAWxdPfU8FO1ms3NUfaHCPYg==", - "dev": true, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/get-symbol-description": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/get-symbol-description/-/get-symbol-description-1.0.0.tgz", - "integrity": "sha512-2EmdH1YvIQiZpltCNgkuiUnyukzxM/R6NDJX31Ke3BG1Nq5b0S2PhX59UKi9vZpPDQVdqn+1IcaAwnzTT5vCjw==", - "dev": true, - "dependencies": { - "call-bind": "^1.0.2", - "get-intrinsic": "^1.1.1" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/glob": { - "version": "7.2.3", - "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", - "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", - "dev": true, - "dependencies": { - "fs.realpath": "^1.0.0", - "inflight": "^1.0.4", - "inherits": "2", - "minimatch": "^3.1.1", - "once": "^1.3.0", - "path-is-absolute": "^1.0.0" - }, - "engines": { - "node": "*" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, - "node_modules/glob-parent": { - "version": "6.0.2", - "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-6.0.2.tgz", - "integrity": "sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==", - "dev": true, - "dependencies": { - "is-glob": "^4.0.3" - }, - "engines": { - "node": ">=10.13.0" - } - }, - "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", - "integrity": "sha512-sFdI5LyBiNTHjRd7cGPWapiHWMOXKyuBNX/cWJ3NfzrZQVa8GI/8cofCl74AOVqq9W5kNmguTIzJ/1s2gyI9wA==", - "dev": true, - "dependencies": { - "define-properties": "^1.1.3" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/gopd": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/gopd/-/gopd-1.0.1.tgz", - "integrity": "sha512-d65bNlIadxvpb/A2abVdlqKqV563juRnZ1Wtk6s1sIR8uNsXR70xqIzVqxVf1eTqDunwT2MkczEeaezCKTZhwA==", - "dependencies": { - "get-intrinsic": "^1.1.3" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/graceful-fs": { - "version": "4.2.10", - "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.10.tgz", - "integrity": "sha512-9ByhssR2fPVsNZj478qUUbKfmL0+t5BDVyjShtyZZLiK7ZDAArFFfopyOTj0M05wE2tJPisA4iTnnXl2YoPvOA==", - "dev": true - }, - "node_modules/graphemer": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/graphemer/-/graphemer-1.4.0.tgz", - "integrity": "sha512-EtKwoO6kxCL9WO5xipiHTZlSzBm7WLT627TqC/uVRd0HKmq8NXyebnNYxDoBi7wt8eTWrUrKXCOVaFq9x1kgag==", - "dev": true - }, - "node_modules/has": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz", - "integrity": "sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==", - "dev": true, - "dependencies": { - "function-bind": "^1.1.1" - }, - "engines": { - "node": ">= 0.4.0" - } - }, - "node_modules/has-bigints": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/has-bigints/-/has-bigints-1.0.2.tgz", - "integrity": "sha512-tSvCKtBr9lkF0Ex0aQiP9N+OpV4zi2r/Nee5VkRDbaqv35RLYMzbwQfFSZZH0kR+Rd6302UJZ2p/bJCEoR3VoQ==", - "dev": true, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/has-flag": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", - "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/has-property-descriptors": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/has-property-descriptors/-/has-property-descriptors-1.0.2.tgz", - "integrity": "sha512-55JNKuIW+vq4Ke1BjOTjM2YctQIvCT7GFzHwmfZPGo5wnrgkid0YQtnAleFSqumZm4az3n2BS+erby5ipJdgrg==", - "dependencies": { - "es-define-property": "^1.0.0" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/has-proto": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/has-proto/-/has-proto-1.0.1.tgz", - "integrity": "sha512-7qE+iP+O+bgF9clE5+UoBFzE65mlBiVj3tKCrlNQ0Ogwm0BjpT/gK4SlLYDMybDh5I3TCTKnPPa0oMG7JDYrhg==", - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/has-symbols": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.3.tgz", - "integrity": "sha512-l3LCuF6MgDNwTDKkdYGEihYjt5pRPbEg46rtlmnSPlUbgmB8LOIrKJbYYFBSbnPaJexMKtiPO8hmeRjRz2Td+A==", - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/has-tostringtag": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/has-tostringtag/-/has-tostringtag-1.0.0.tgz", - "integrity": "sha512-kFjcSNhnlGV1kyoGk7OXKSawH5JOb/LzUc5w9B02hOTO0dfFRjbHQKvg1d6cf3HbeUmtU9VbbV3qzZ2Teh97WQ==", - "dev": true, - "dependencies": { - "has-symbols": "^1.0.2" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/hasown": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.0.tgz", - "integrity": "sha512-vUptKVTpIJhcczKBbgnS+RtcuYMB8+oNzPK2/Hp3hanz8JmpATdmmgLgSaadVREkDm+e2giHwY3ZRkyjSIDDFA==", - "dependencies": { - "function-bind": "^1.1.2" - }, - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/html-escaper": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/html-escaper/-/html-escaper-2.0.2.tgz", - "integrity": "sha512-H2iMtd0I4Mt5eYiapRdIDjp+XzelXQ0tFE4JS7YFwFevXXMmOp9myNrUvCg0D6ws8iqkRPBfKHgbwig1SmlLfg==", - "dev": true - }, - "node_modules/human-signals": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/human-signals/-/human-signals-2.1.0.tgz", - "integrity": "sha512-B4FFZ6q/T2jhhksgkbEW3HBvWIfDW85snkQgawt07S7J5QXTk6BkNV+0yAeZrM5QpMAdYlocGoljn0sJ/WQkFw==", - "dev": true, - "engines": { - "node": ">=10.17.0" - } - }, - "node_modules/ignore": { - "version": "5.2.4", - "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.2.4.tgz", - "integrity": "sha512-MAb38BcSbH0eHNBxn7ql2NH/kX33OkB3lZ1BNdh7ENeRChHTYsTvWrMubiIAMNS2llXEEgZ1MUOBtXChP3kaFQ==", - "dev": true, - "engines": { - "node": ">= 4" - } - }, - "node_modules/import-fresh": { - "version": "3.3.0", - "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.0.tgz", - "integrity": "sha512-veYYhQa+D1QBKznvhUHxb8faxlrwUnxseDAbAp457E0wLNio2bOSKnjYDhMj+YiAq61xrMGhQk9iXVk5FzgQMw==", - "dev": true, - "dependencies": { - "parent-module": "^1.0.0", - "resolve-from": "^4.0.0" - }, - "engines": { - "node": ">=6" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/import-fresh/node_modules/resolve-from": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz", - "integrity": "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==", - "dev": true, - "engines": { - "node": ">=4" - } - }, - "node_modules/import-local": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/import-local/-/import-local-3.2.0.tgz", - "integrity": "sha512-2SPlun1JUPWoM6t3F0dw0FkCF/jWY8kttcY4f599GLTSjh2OCuuhdTkJQsEcZzBqbXZGKMK2OqW1oZsjtf/gQA==", - "dev": true, - "dependencies": { - "pkg-dir": "^4.2.0", - "resolve-cwd": "^3.0.0" - }, - "bin": { - "import-local-fixture": "fixtures/cli.js" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/imurmurhash": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz", - "integrity": "sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==", - "dev": true, - "engines": { - "node": ">=0.8.19" - } - }, - "node_modules/inflight": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", - "integrity": "sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==", - "dev": true, - "dependencies": { - "once": "^1.3.0", - "wrappy": "1" - } - }, - "node_modules/inherits": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", - "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", - "dev": true - }, - "node_modules/internal-slot": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/internal-slot/-/internal-slot-1.0.6.tgz", - "integrity": "sha512-Xj6dv+PsbtwyPpEflsejS+oIZxmMlV44zAhG479uYu89MsjcYOhCFnNyKrkJrihbsiasQyY0afoCl/9BLR65bg==", - "dev": true, - "dependencies": { - "get-intrinsic": "^1.2.2", - "hasown": "^2.0.0", - "side-channel": "^1.0.4" - }, - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/is-array-buffer": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/is-array-buffer/-/is-array-buffer-3.0.2.tgz", - "integrity": "sha512-y+FyyR/w8vfIRq4eQcM1EYgSTnmHXPqaF+IgzgraytCFq5Xh8lllDVmAZolPJiZttZLeFSINPYMaEJ7/vWUa1w==", - "dev": true, - "dependencies": { - "call-bind": "^1.0.2", - "get-intrinsic": "^1.2.0", - "is-typed-array": "^1.1.10" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/is-arrayish": { - "version": "0.2.1", - "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz", - "integrity": "sha512-zz06S8t0ozoDXMG+ube26zeCTNXcKIPJZJi8hBrF4idCLms4CG9QtK7qBl1boi5ODzFpjswb5JPmHCbMpjaYzg==", - "dev": true - }, - "node_modules/is-async-function": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/is-async-function/-/is-async-function-2.0.0.tgz", - "integrity": "sha512-Y1JXKrfykRJGdlDwdKlLpLyMIiWqWvuSd17TvZk68PLAOGOoF4Xyav1z0Xhoi+gCYjZVeC5SI+hYFOfvXmGRCA==", - "dev": true, - "dependencies": { - "has-tostringtag": "^1.0.0" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/is-bigint": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/is-bigint/-/is-bigint-1.0.4.tgz", - "integrity": "sha512-zB9CruMamjym81i2JZ3UMn54PKGsQzsJeo6xvN3HJJ4CAsQNB6iRutp2To77OfCNuoxspsIhzaPoO1zyCEhFOg==", - "dev": true, - "dependencies": { - "has-bigints": "^1.0.1" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/is-boolean-object": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/is-boolean-object/-/is-boolean-object-1.1.2.tgz", - "integrity": "sha512-gDYaKHJmnj4aWxyj6YHyXVpdQawtVLHU5cb+eztPGczf6cjuTdwve5ZIEfgXqH4e57An1D1AKf8CZ3kYrQRqYA==", - "dev": true, - "dependencies": { - "call-bind": "^1.0.2", - "has-tostringtag": "^1.0.0" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/is-callable": { - "version": "1.2.7", - "resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.2.7.tgz", - "integrity": "sha512-1BC0BVFhS/p0qtw6enp8e+8OD0UrK0oFLztSjNzhcKA3WDuJxxAPXzPuPtKkjEY9UUoEWlX/8fgKeu2S8i9JTA==", - "dev": true, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/is-core-module": { - "version": "2.13.1", - "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.13.1.tgz", - "integrity": "sha512-hHrIjvZsftOsvKSn2TRYl63zvxsgE0K+0mYMoH6gD4omR5IWB2KynivBQczo3+wF1cCkjzvptnI9Q0sPU66ilw==", - "dev": true, - "dependencies": { - "hasown": "^2.0.0" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/is-date-object": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/is-date-object/-/is-date-object-1.0.5.tgz", - "integrity": "sha512-9YQaSxsAiSwcvS33MBk3wTCVnWK+HhF8VZR2jRxehM16QcVOdHqPn4VPHmRK4lSr38n9JriurInLcP90xsYNfQ==", - "dev": true, - "dependencies": { - "has-tostringtag": "^1.0.0" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/is-extglob": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", - "integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/is-finalizationregistry": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/is-finalizationregistry/-/is-finalizationregistry-1.0.2.tgz", - "integrity": "sha512-0by5vtUJs8iFQb5TYUHHPudOR+qXYIMKtiUzvLIZITZUjknFmziyBJuLhVRc+Ds0dREFlskDNJKYIdIzu/9pfw==", - "dev": true, - "dependencies": { - "call-bind": "^1.0.2" - }, - "funding": { - "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-fn": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/is-generator-fn/-/is-generator-fn-2.1.0.tgz", - "integrity": "sha512-cTIB4yPYL/Grw0EaSzASzg6bBy9gqCofvWN8okThAYIxKJZC+udlRAmGbM0XLeniEJSs8uEgHPGuHSe1XsOLSQ==", - "dev": true, - "engines": { - "node": ">=6" - } - }, - "node_modules/is-generator-function": { - "version": "1.0.10", - "resolved": "https://registry.npmjs.org/is-generator-function/-/is-generator-function-1.0.10.tgz", - "integrity": "sha512-jsEjy9l3yiXEQ+PsXdmBwEPcOxaXWLspKdplFUVI9vq1iZgIekeC0L167qeu86czQaxed3q/Uzuw0swL0irL8A==", - "dev": true, - "dependencies": { - "has-tostringtag": "^1.0.0" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/is-glob": { - "version": "4.0.3", - "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz", - "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==", - "dev": true, - "dependencies": { - "is-extglob": "^2.1.1" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/is-map": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/is-map/-/is-map-2.0.2.tgz", - "integrity": "sha512-cOZFQQozTha1f4MxLFzlgKYPTyj26picdZTx82hbc/Xf4K/tZOOXSCkMvU4pKioRXGDLJRn0GM7Upe7kR721yg==", - "dev": true, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/is-negative-zero": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/is-negative-zero/-/is-negative-zero-2.0.2.tgz", - "integrity": "sha512-dqJvarLawXsFbNDeJW7zAz8ItJ9cd28YufuuFzh0G8pNHjJMnY08Dv7sYX2uF5UpQOwieAeOExEYAWWfu7ZZUA==", - "dev": true, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "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/is-number-object": { - "version": "1.0.7", - "resolved": "https://registry.npmjs.org/is-number-object/-/is-number-object-1.0.7.tgz", - "integrity": "sha512-k1U0IRzLMo7ZlYIfzRu23Oh6MiIFasgpb9X76eqfFZAqwH44UI4KTBvBYIZ1dSL9ZzChTB9ShHfLkR4pdW5krQ==", - "dev": true, - "dependencies": { - "has-tostringtag": "^1.0.0" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/is-path-inside": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/is-path-inside/-/is-path-inside-3.0.3.tgz", - "integrity": "sha512-Fd4gABb+ycGAmKou8eMftCupSir5lRxqf4aD/vd0cD2qc4HL07OjCeuHMr8Ro4CoMaeCKDB0/ECBOVWjTwUvPQ==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/is-regex": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.1.4.tgz", - "integrity": "sha512-kvRdxDsxZjhzUX07ZnLydzS1TU/TJlTUHHY4YLL87e37oUA49DfkLqgy+VjFocowy29cKvcSiu+kIv728jTTVg==", - "dev": true, - "dependencies": { - "call-bind": "^1.0.2", - "has-tostringtag": "^1.0.0" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/is-set": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/is-set/-/is-set-2.0.2.tgz", - "integrity": "sha512-+2cnTEZeY5z/iXGbLhPrOAaK/Mau5k5eXq9j14CpRTftq0pAJu2MwVRSZhyZWBzx3o6X795Lz6Bpb6R0GKf37g==", - "dev": true, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/is-shared-array-buffer": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/is-shared-array-buffer/-/is-shared-array-buffer-1.0.2.tgz", - "integrity": "sha512-sqN2UDu1/0y6uvXyStCOzyhAjCSlHceFoMKJW8W9EU9cvic/QdsZ0kEU93HEy3IUEFZIiH/3w+AH/UQbPHNdhA==", - "dev": true, - "dependencies": { - "call-bind": "^1.0.2" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/is-stream": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-2.0.1.tgz", - "integrity": "sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg==", - "dev": true, - "engines": { - "node": ">=8" - }, - "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", - "integrity": "sha512-tE2UXzivje6ofPW7l23cjDOMa09gb7xlAqG6jG5ej6uPV32TlWP3NKPigtaGeHNu9fohccRYvIiZMfOOnOYUtg==", - "dev": true, - "dependencies": { - "has-tostringtag": "^1.0.0" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/is-symbol": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/is-symbol/-/is-symbol-1.0.4.tgz", - "integrity": "sha512-C/CPBqKWnvdcxqIARxyOh4v1UUEOCHpgDa0WYgpKDFMszcrPcffg5uhwSgPCLD2WWxmq6isisz87tzT01tuGhg==", - "dev": true, - "dependencies": { - "has-symbols": "^1.0.2" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/is-typed-array": { - "version": "1.1.12", - "resolved": "https://registry.npmjs.org/is-typed-array/-/is-typed-array-1.1.12.tgz", - "integrity": "sha512-Z14TF2JNG8Lss5/HMqt0//T9JeHXttXy5pH/DBU4vi98ozO2btxzq9MwYDZYnKwU8nRsz/+GVFVRDq3DkVuSPg==", - "dev": true, - "dependencies": { - "which-typed-array": "^1.1.11" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/is-weakmap": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/is-weakmap/-/is-weakmap-2.0.1.tgz", - "integrity": "sha512-NSBR4kH5oVj1Uwvv970ruUkCV7O1mzgVFO4/rev2cLRda9Tm9HrL70ZPut4rOHgY0FNrUu9BCbXA2sdQ+x0chA==", - "dev": true, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/is-weakref": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/is-weakref/-/is-weakref-1.0.2.tgz", - "integrity": "sha512-qctsuLZmIQ0+vSSMfoVvyFe2+GSEvnmZ2ezTup1SBse9+twCCeial6EEi3Nc2KFcf6+qz2FBPnjXsk8xhKSaPQ==", - "dev": true, - "dependencies": { - "call-bind": "^1.0.2" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/is-weakset": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/is-weakset/-/is-weakset-2.0.2.tgz", - "integrity": "sha512-t2yVvttHkQktwnNNmBQ98AhENLdPUTDTE21uPqAQ0ARwQfGeQKRVS0NNurH7bTf7RrvcVn1OOge45CnBeHCSmg==", - "dev": true, - "dependencies": { - "call-bind": "^1.0.2", - "get-intrinsic": "^1.1.1" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/isarray": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-2.0.5.tgz", - "integrity": "sha512-xHjhDr3cNBK0BzdUJSPXZntQUx/mwMS5Rw4A7lPJ90XGAO6ISP/ePDNuo0vhqOZU+UD5JoodwCAAoZQd3FeAKw==", - "dev": true - }, - "node_modules/isexe": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", - "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==", - "dev": true - }, - "node_modules/istanbul-lib-coverage": { - "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-instrument": { - "version": "6.0.3", - "resolved": "https://registry.npmjs.org/istanbul-lib-instrument/-/istanbul-lib-instrument-6.0.3.tgz", - "integrity": "sha512-Vtgk7L/R2JHyyGW07spoFlB8/lpjiOLTjMdms6AFMraYt3BaJauod/NGrfnVG/y4Ix1JEuMRPDPEj2ua+zz1/Q==", - "dev": true, - "dependencies": { - "@babel/core": "^7.23.9", - "@babel/parser": "^7.23.9", - "@istanbuljs/schema": "^0.1.3", - "istanbul-lib-coverage": "^3.2.0", - "semver": "^7.5.4" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/istanbul-lib-instrument/node_modules/semver": { - "version": "7.6.3", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.3.tgz", - "integrity": "sha512-oVekP1cKtI+CTDvHWYFUcMtsK/00wmAEfyqKfNdARm8u1wNVhSgaX7A8d4UuIlUI5e84iEwOhs7ZPYRmzU9U6A==", - "dev": true, - "bin": { - "semver": "bin/semver.js" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/istanbul-lib-report": { - "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": "^4.0.0", - "supports-color": "^7.1.0" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/istanbul-lib-source-maps": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/istanbul-lib-source-maps/-/istanbul-lib-source-maps-4.0.1.tgz", - "integrity": "sha512-n3s8EwkdFIJCG3BPKBYvskgXGoy88ARzvegkitk60NxRdwltLOTaH7CUiMRXvwYorl0Q712iEjcWB+fK/MrWVw==", - "dev": true, - "dependencies": { - "debug": "^4.1.1", - "istanbul-lib-coverage": "^3.0.0", - "source-map": "^0.6.1" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/istanbul-reports": { - "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", - "istanbul-lib-report": "^3.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/iterator.prototype": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/iterator.prototype/-/iterator.prototype-1.1.2.tgz", - "integrity": "sha512-DR33HMMr8EzwuRL8Y9D3u2BMj8+RqSE850jfGu59kS7tbmPLzGkZmVSfyCFSDxuZiEY6Rzt3T2NA/qU+NwVj1w==", - "dev": true, - "dependencies": { - "define-properties": "^1.2.1", - "get-intrinsic": "^1.2.1", - "has-symbols": "^1.0.3", - "reflect.getprototypeof": "^1.0.4", - "set-function-name": "^2.0.1" - } - }, - "node_modules/jest": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/jest/-/jest-29.7.0.tgz", - "integrity": "sha512-NIy3oAFp9shda19hy4HK0HRTWKtPJmGdnvywu01nOqNC2vZg+Z+fvJDxpMQA88eb2I9EcafcdjYgsDthnYTvGw==", - "dev": true, - "dependencies": { - "@jest/core": "^29.7.0", - "@jest/types": "^29.6.3", - "import-local": "^3.0.2", - "jest-cli": "^29.7.0" - }, - "bin": { - "jest": "bin/jest.js" - }, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" - }, - "peerDependencies": { - "node-notifier": "^8.0.1 || ^9.0.0 || ^10.0.0" - }, - "peerDependenciesMeta": { - "node-notifier": { - "optional": true - } - } - }, - "node_modules/jest-changed-files": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/jest-changed-files/-/jest-changed-files-29.7.0.tgz", - "integrity": "sha512-fEArFiwf1BpQ+4bXSprcDc3/x4HSzL4al2tozwVpDFpsxALjLYdyiIK4e5Vz66GQJIbXJ82+35PtysofptNX2w==", - "dev": true, - "dependencies": { - "execa": "^5.0.0", - "jest-util": "^29.7.0", - "p-limit": "^3.1.0" - }, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" - } - }, - "node_modules/jest-circus": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/jest-circus/-/jest-circus-29.7.0.tgz", - "integrity": "sha512-3E1nCMgipcTkCocFwM90XXQab9bS+GMsjdpmPrlelaxwD93Ad8iVEjX/vvHPdLPnFf+L40u+5+iutRdA1N9myw==", - "dev": true, - "dependencies": { - "@jest/environment": "^29.7.0", - "@jest/expect": "^29.7.0", - "@jest/test-result": "^29.7.0", - "@jest/types": "^29.6.3", - "@types/node": "*", - "chalk": "^4.0.0", - "co": "^4.6.0", - "dedent": "^1.0.0", - "is-generator-fn": "^2.0.0", - "jest-each": "^29.7.0", - "jest-matcher-utils": "^29.7.0", - "jest-message-util": "^29.7.0", - "jest-runtime": "^29.7.0", - "jest-snapshot": "^29.7.0", - "jest-util": "^29.7.0", - "p-limit": "^3.1.0", - "pretty-format": "^29.7.0", - "pure-rand": "^6.0.0", - "slash": "^3.0.0", - "stack-utils": "^2.0.3" - }, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" - } - }, - "node_modules/jest-cli": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/jest-cli/-/jest-cli-29.7.0.tgz", - "integrity": "sha512-OVVobw2IubN/GSYsxETi+gOe7Ka59EFMR/twOU3Jb2GnKKeMGJB5SGUUrEz3SFVmJASUdZUzy83sLNNQ2gZslg==", - "dev": true, - "dependencies": { - "@jest/core": "^29.7.0", - "@jest/test-result": "^29.7.0", - "@jest/types": "^29.6.3", - "chalk": "^4.0.0", - "create-jest": "^29.7.0", - "exit": "^0.1.2", - "import-local": "^3.0.2", - "jest-config": "^29.7.0", - "jest-util": "^29.7.0", - "jest-validate": "^29.7.0", - "yargs": "^17.3.1" - }, - "bin": { - "jest": "bin/jest.js" - }, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" - }, - "peerDependencies": { - "node-notifier": "^8.0.1 || ^9.0.0 || ^10.0.0" - }, - "peerDependenciesMeta": { - "node-notifier": { - "optional": true - } - } - }, - "node_modules/jest-config": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/jest-config/-/jest-config-29.7.0.tgz", - "integrity": "sha512-uXbpfeQ7R6TZBqI3/TxCU4q4ttk3u0PJeC+E0zbfSoSjq6bJ7buBPxzQPL0ifrkY4DNu4JUdk0ImlBUYi840eQ==", - "dev": true, - "dependencies": { - "@babel/core": "^7.11.6", - "@jest/test-sequencer": "^29.7.0", - "@jest/types": "^29.6.3", - "babel-jest": "^29.7.0", - "chalk": "^4.0.0", - "ci-info": "^3.2.0", - "deepmerge": "^4.2.2", - "glob": "^7.1.3", - "graceful-fs": "^4.2.9", - "jest-circus": "^29.7.0", - "jest-environment-node": "^29.7.0", - "jest-get-type": "^29.6.3", - "jest-regex-util": "^29.6.3", - "jest-resolve": "^29.7.0", - "jest-runner": "^29.7.0", - "jest-util": "^29.7.0", - "jest-validate": "^29.7.0", - "micromatch": "^4.0.4", - "parse-json": "^5.2.0", - "pretty-format": "^29.7.0", - "slash": "^3.0.0", - "strip-json-comments": "^3.1.1" - }, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" - }, - "peerDependencies": { - "@types/node": "*", - "ts-node": ">=9.0.0" - }, - "peerDependenciesMeta": { - "@types/node": { - "optional": true - }, - "ts-node": { - "optional": true - } - } - }, - "node_modules/jest-diff": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/jest-diff/-/jest-diff-29.7.0.tgz", - "integrity": "sha512-LMIgiIrhigmPrs03JHpxUh2yISK3vLFPkAodPeo0+BuF7wA2FoQbkEg1u8gBYBThncu7e1oEDUfIXVuTqLRUjw==", - "dev": true, - "dependencies": { - "chalk": "^4.0.0", - "diff-sequences": "^29.6.3", - "jest-get-type": "^29.6.3", - "pretty-format": "^29.7.0" - }, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" - } - }, - "node_modules/jest-docblock": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/jest-docblock/-/jest-docblock-29.7.0.tgz", - "integrity": "sha512-q617Auw3A612guyaFgsbFeYpNP5t2aoUNLwBUbc/0kD1R4t9ixDbyFTHd1nok4epoVFpr7PmeWHrhvuV3XaJ4g==", - "dev": true, - "dependencies": { - "detect-newline": "^3.0.0" - }, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" - } - }, - "node_modules/jest-each": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/jest-each/-/jest-each-29.7.0.tgz", - "integrity": "sha512-gns+Er14+ZrEoC5fhOfYCY1LOHHr0TI+rQUHZS8Ttw2l7gl+80eHc/gFf2Ktkw0+SIACDTeWvpFcv3B04VembQ==", - "dev": true, - "dependencies": { - "@jest/types": "^29.6.3", - "chalk": "^4.0.0", - "jest-get-type": "^29.6.3", - "jest-util": "^29.7.0", - "pretty-format": "^29.7.0" - }, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" - } - }, - "node_modules/jest-environment-node": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/jest-environment-node/-/jest-environment-node-29.7.0.tgz", - "integrity": "sha512-DOSwCRqXirTOyheM+4d5YZOrWcdu0LNZ87ewUoywbcb2XR4wKgqiG8vNeYwhjFMbEkfju7wx2GYH0P2gevGvFw==", - "dev": true, - "dependencies": { - "@jest/environment": "^29.7.0", - "@jest/fake-timers": "^29.7.0", - "@jest/types": "^29.6.3", - "@types/node": "*", - "jest-mock": "^29.7.0", - "jest-util": "^29.7.0" - }, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" - } - }, - "node_modules/jest-get-type": { - "version": "29.6.3", - "resolved": "https://registry.npmjs.org/jest-get-type/-/jest-get-type-29.6.3.tgz", - "integrity": "sha512-zrteXnqYxfQh7l5FHyL38jL39di8H8rHoecLH3JNxH3BwOrBsNeabdap5e0I23lD4HHI8W5VFBZqG4Eaq5LNcw==", - "dev": true, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" - } - }, - "node_modules/jest-haste-map": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/jest-haste-map/-/jest-haste-map-29.7.0.tgz", - "integrity": "sha512-fP8u2pyfqx0K1rGn1R9pyE0/KTn+G7PxktWidOBTqFPLYX0b9ksaMFkhK5vrS3DVun09pckLdlx90QthlW7AmA==", - "dev": true, - "dependencies": { - "@jest/types": "^29.6.3", - "@types/graceful-fs": "^4.1.3", - "@types/node": "*", - "anymatch": "^3.0.3", - "fb-watchman": "^2.0.0", - "graceful-fs": "^4.2.9", - "jest-regex-util": "^29.6.3", - "jest-util": "^29.7.0", - "jest-worker": "^29.7.0", - "micromatch": "^4.0.4", - "walker": "^1.0.8" - }, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" - }, - "optionalDependencies": { - "fsevents": "^2.3.2" - } - }, - "node_modules/jest-leak-detector": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/jest-leak-detector/-/jest-leak-detector-29.7.0.tgz", - "integrity": "sha512-kYA8IJcSYtST2BY9I+SMC32nDpBT3J2NvWJx8+JCuCdl/CR1I4EKUJROiP8XtCcxqgTTBGJNdbB1A8XRKbTetw==", - "dev": true, - "dependencies": { - "jest-get-type": "^29.6.3", - "pretty-format": "^29.7.0" - }, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" - } - }, - "node_modules/jest-matcher-utils": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/jest-matcher-utils/-/jest-matcher-utils-29.7.0.tgz", - "integrity": "sha512-sBkD+Xi9DtcChsI3L3u0+N0opgPYnCRPtGcQYrgXmR+hmt/fYfWAL0xRXYU8eWOdfuLgBe0YCW3AFtnRLagq/g==", - "dev": true, - "dependencies": { - "chalk": "^4.0.0", - "jest-diff": "^29.7.0", - "jest-get-type": "^29.6.3", - "pretty-format": "^29.7.0" - }, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" - } - }, - "node_modules/jest-message-util": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/jest-message-util/-/jest-message-util-29.7.0.tgz", - "integrity": "sha512-GBEV4GRADeP+qtB2+6u61stea8mGcOT4mCtrYISZwfu9/ISHFJ/5zOMXYbpBE9RsS5+Gb63DW4FgmnKJ79Kf6w==", - "dev": true, - "dependencies": { - "@babel/code-frame": "^7.12.13", - "@jest/types": "^29.6.3", - "@types/stack-utils": "^2.0.0", - "chalk": "^4.0.0", - "graceful-fs": "^4.2.9", - "micromatch": "^4.0.4", - "pretty-format": "^29.7.0", - "slash": "^3.0.0", - "stack-utils": "^2.0.3" - }, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" - } - }, - "node_modules/jest-mock": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/jest-mock/-/jest-mock-29.7.0.tgz", - "integrity": "sha512-ITOMZn+UkYS4ZFh83xYAOzWStloNzJFO2s8DWrE4lhtGD+AorgnbkiKERe4wQVBydIGPx059g6riW5Btp6Llnw==", - "dev": true, - "dependencies": { - "@jest/types": "^29.6.3", - "@types/node": "*", - "jest-util": "^29.7.0" - }, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" - } - }, - "node_modules/jest-pnp-resolver": { - "version": "1.2.3", - "resolved": "https://registry.npmjs.org/jest-pnp-resolver/-/jest-pnp-resolver-1.2.3.tgz", - "integrity": "sha512-+3NpwQEnRoIBtx4fyhblQDPgJI0H1IEIkX7ShLUjPGA7TtUTvI1oiKi3SR4oBR0hQhQR80l4WAe5RrXBwWMA8w==", - "dev": true, - "engines": { - "node": ">=6" - }, - "peerDependencies": { - "jest-resolve": "*" - }, - "peerDependenciesMeta": { - "jest-resolve": { - "optional": true - } - } - }, - "node_modules/jest-regex-util": { - "version": "29.6.3", - "resolved": "https://registry.npmjs.org/jest-regex-util/-/jest-regex-util-29.6.3.tgz", - "integrity": "sha512-KJJBsRCyyLNWCNBOvZyRDnAIfUiRJ8v+hOBQYGn8gDyF3UegwiP4gwRR3/SDa42g1YbVycTidUF3rKjyLFDWbg==", - "dev": true, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" - } - }, - "node_modules/jest-resolve": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/jest-resolve/-/jest-resolve-29.7.0.tgz", - "integrity": "sha512-IOVhZSrg+UvVAshDSDtHyFCCBUl/Q3AAJv8iZ6ZjnZ74xzvwuzLXid9IIIPgTnY62SJjfuupMKZsZQRsCvxEgA==", - "dev": true, - "dependencies": { - "chalk": "^4.0.0", - "graceful-fs": "^4.2.9", - "jest-haste-map": "^29.7.0", - "jest-pnp-resolver": "^1.2.2", - "jest-util": "^29.7.0", - "jest-validate": "^29.7.0", - "resolve": "^1.20.0", - "resolve.exports": "^2.0.0", - "slash": "^3.0.0" - }, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" - } - }, - "node_modules/jest-resolve-dependencies": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/jest-resolve-dependencies/-/jest-resolve-dependencies-29.7.0.tgz", - "integrity": "sha512-un0zD/6qxJ+S0et7WxeI3H5XSe9lTBBR7bOHCHXkKR6luG5mwDDlIzVQ0V5cZCuoTgEdcdwzTghYkTWfubi+nA==", - "dev": true, - "dependencies": { - "jest-regex-util": "^29.6.3", - "jest-snapshot": "^29.7.0" - }, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" - } - }, - "node_modules/jest-runner": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/jest-runner/-/jest-runner-29.7.0.tgz", - "integrity": "sha512-fsc4N6cPCAahybGBfTRcq5wFR6fpLznMg47sY5aDpsoejOcVYFb07AHuSnR0liMcPTgBsA3ZJL6kFOjPdoNipQ==", - "dev": true, - "dependencies": { - "@jest/console": "^29.7.0", - "@jest/environment": "^29.7.0", - "@jest/test-result": "^29.7.0", - "@jest/transform": "^29.7.0", - "@jest/types": "^29.6.3", - "@types/node": "*", - "chalk": "^4.0.0", - "emittery": "^0.13.1", - "graceful-fs": "^4.2.9", - "jest-docblock": "^29.7.0", - "jest-environment-node": "^29.7.0", - "jest-haste-map": "^29.7.0", - "jest-leak-detector": "^29.7.0", - "jest-message-util": "^29.7.0", - "jest-resolve": "^29.7.0", - "jest-runtime": "^29.7.0", - "jest-util": "^29.7.0", - "jest-watcher": "^29.7.0", - "jest-worker": "^29.7.0", - "p-limit": "^3.1.0", - "source-map-support": "0.5.13" - }, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" - } - }, - "node_modules/jest-runtime": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/jest-runtime/-/jest-runtime-29.7.0.tgz", - "integrity": "sha512-gUnLjgwdGqW7B4LvOIkbKs9WGbn+QLqRQQ9juC6HndeDiezIwhDP+mhMwHWCEcfQ5RUXa6OPnFF8BJh5xegwwQ==", - "dev": true, - "dependencies": { - "@jest/environment": "^29.7.0", - "@jest/fake-timers": "^29.7.0", - "@jest/globals": "^29.7.0", - "@jest/source-map": "^29.6.3", - "@jest/test-result": "^29.7.0", - "@jest/transform": "^29.7.0", - "@jest/types": "^29.6.3", - "@types/node": "*", - "chalk": "^4.0.0", - "cjs-module-lexer": "^1.0.0", - "collect-v8-coverage": "^1.0.0", - "glob": "^7.1.3", - "graceful-fs": "^4.2.9", - "jest-haste-map": "^29.7.0", - "jest-message-util": "^29.7.0", - "jest-mock": "^29.7.0", - "jest-regex-util": "^29.6.3", - "jest-resolve": "^29.7.0", - "jest-snapshot": "^29.7.0", - "jest-util": "^29.7.0", - "slash": "^3.0.0", - "strip-bom": "^4.0.0" - }, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" - } - }, - "node_modules/jest-snapshot": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/jest-snapshot/-/jest-snapshot-29.7.0.tgz", - "integrity": "sha512-Rm0BMWtxBcioHr1/OX5YCP8Uov4riHvKPknOGs804Zg9JGZgmIBkbtlxJC/7Z4msKYVbIJtfU+tKb8xlYNfdkw==", - "dev": true, - "dependencies": { - "@babel/core": "^7.11.6", - "@babel/generator": "^7.7.2", - "@babel/plugin-syntax-jsx": "^7.7.2", - "@babel/plugin-syntax-typescript": "^7.7.2", - "@babel/types": "^7.3.3", - "@jest/expect-utils": "^29.7.0", - "@jest/transform": "^29.7.0", - "@jest/types": "^29.6.3", - "babel-preset-current-node-syntax": "^1.0.0", - "chalk": "^4.0.0", - "expect": "^29.7.0", - "graceful-fs": "^4.2.9", - "jest-diff": "^29.7.0", - "jest-get-type": "^29.6.3", - "jest-matcher-utils": "^29.7.0", - "jest-message-util": "^29.7.0", - "jest-util": "^29.7.0", - "natural-compare": "^1.4.0", - "pretty-format": "^29.7.0", - "semver": "^7.5.3" - }, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" - } - }, - "node_modules/jest-snapshot/node_modules/semver": { - "version": "7.6.3", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.3.tgz", - "integrity": "sha512-oVekP1cKtI+CTDvHWYFUcMtsK/00wmAEfyqKfNdARm8u1wNVhSgaX7A8d4UuIlUI5e84iEwOhs7ZPYRmzU9U6A==", - "dev": true, - "bin": { - "semver": "bin/semver.js" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/jest-util": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/jest-util/-/jest-util-29.7.0.tgz", - "integrity": "sha512-z6EbKajIpqGKU56y5KBUgy1dt1ihhQJgWzUlZHArA/+X2ad7Cb5iF+AK1EWVL/Bo7Rz9uurpqw6SiBCefUbCGA==", - "dev": true, - "dependencies": { - "@jest/types": "^29.6.3", - "@types/node": "*", - "chalk": "^4.0.0", - "ci-info": "^3.2.0", - "graceful-fs": "^4.2.9", - "picomatch": "^2.2.3" - }, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" - } - }, - "node_modules/jest-validate": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/jest-validate/-/jest-validate-29.7.0.tgz", - "integrity": "sha512-ZB7wHqaRGVw/9hST/OuFUReG7M8vKeq0/J2egIGLdvjHCmYqGARhzXmtgi+gVeZ5uXFF219aOc3Ls2yLg27tkw==", - "dev": true, - "dependencies": { - "@jest/types": "^29.6.3", - "camelcase": "^6.2.0", - "chalk": "^4.0.0", - "jest-get-type": "^29.6.3", - "leven": "^3.1.0", - "pretty-format": "^29.7.0" - }, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" - } - }, - "node_modules/jest-validate/node_modules/camelcase": { - "version": "6.3.0", - "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-6.3.0.tgz", - "integrity": "sha512-Gmy6FhYlCY7uOElZUSbxo2UCDH8owEk996gkbrpsgGtrJLM3J7jGxl9Ic7Qwwj4ivOE5AWZWRMecDdF7hqGjFA==", - "dev": true, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/jest-watcher": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/jest-watcher/-/jest-watcher-29.7.0.tgz", - "integrity": "sha512-49Fg7WXkU3Vl2h6LbLtMQ/HyB6rXSIX7SqvBLQmssRBGN9I0PNvPmAmCWSOY6SOvrjhI/F7/bGAv9RtnsPA03g==", - "dev": true, - "dependencies": { - "@jest/test-result": "^29.7.0", - "@jest/types": "^29.6.3", - "@types/node": "*", - "ansi-escapes": "^4.2.1", - "chalk": "^4.0.0", - "emittery": "^0.13.1", - "jest-util": "^29.7.0", - "string-length": "^4.0.1" - }, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" - } - }, - "node_modules/jest-worker": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/jest-worker/-/jest-worker-29.7.0.tgz", - "integrity": "sha512-eIz2msL/EzL9UFTFFx7jBTkeZfku0yUAyZZZmJ93H2TYEiroIx2PQjEXcwYtYl8zXCxb+PAmA2hLIt/6ZEkPHw==", - "dev": true, - "dependencies": { - "@types/node": "*", - "jest-util": "^29.7.0", - "merge-stream": "^2.0.0", - "supports-color": "^8.0.0" - }, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" - } - }, - "node_modules/jest-worker/node_modules/supports-color": { - "version": "8.1.1", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-8.1.1.tgz", - "integrity": "sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==", - "dev": true, - "dependencies": { - "has-flag": "^4.0.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/chalk/supports-color?sponsor=1" - } - }, - "node_modules/js-tokens": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", - "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==", - "dev": true - }, - "node_modules/js-yaml": { - "version": "3.14.1", - "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.14.1.tgz", - "integrity": "sha512-okMH7OXXJ7YrN9Ok3/SXrnu4iX9yOk+25nqX4imS2npuvTYDmo/QEZoqwZkYaIDk3jVvBOTOIEgEhaLOynBS9g==", - "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-better-errors": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/json-parse-better-errors/-/json-parse-better-errors-1.0.2.tgz", - "integrity": "sha512-mrqyZKfX5EhL7hvqcV6WG1yYjnjeuYDzDhhcAAUrq8Po85NBQBJP+ZDUT75qZQ98IkUoBqdkExkukOU7Ts2wrw==", - "dev": true - }, - "node_modules/json-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", - "integrity": "sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w==", - "dev": true - }, - "node_modules/json-schema-traverse": { - "version": "0.4.1", - "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", - "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", - "dev": true - }, - "node_modules/json-stable-stringify-without-jsonify": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz", - "integrity": "sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw==", - "dev": true - }, - "node_modules/json-stringify-safe": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz", - "integrity": "sha1-Epai1Y/UXxmg9s4B1lcB4sc1tus=", - "dev": true - }, - "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/jsx-ast-utils": { - "version": "3.3.3", - "resolved": "https://registry.npmjs.org/jsx-ast-utils/-/jsx-ast-utils-3.3.3.tgz", - "integrity": "sha512-fYQHZTZ8jSfmWZ0iyzfwiU4WDX4HpHbMCZ3gPlWYiCl3BoeOTsqKBqnTVfH2rYT7eP5c3sVbeSPHnnJOaTrWiw==", - "dev": true, - "dependencies": { - "array-includes": "^3.1.5", - "object.assign": "^4.1.3" - }, - "engines": { - "node": ">=4.0" - } - }, - "node_modules/kleur": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/kleur/-/kleur-3.0.3.tgz", - "integrity": "sha512-eTIzlVOSUR+JxdDFepEYcBMtZ9Qqdef+rnzWdRZuMbOywu5tO2w2N7rqjoANZ5k9vywhL6Br1VRjUIgTQx4E8w==", - "dev": true, - "engines": { - "node": ">=6" - } - }, - "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==", - "dev": true, - "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/load-json-file": { - "version": "5.3.0", - "resolved": "https://registry.npmjs.org/load-json-file/-/load-json-file-5.3.0.tgz", - "integrity": "sha512-cJGP40Jc/VXUsp8/OrnyKyTZ1y6v/dphm3bioS+RrKXjK2BB6wHUd6JptZEFDGgGahMT+InnZO5i1Ei9mpC8Bw==", - "dev": true, - "dependencies": { - "graceful-fs": "^4.1.15", - "parse-json": "^4.0.0", - "pify": "^4.0.1", - "strip-bom": "^3.0.0", - "type-fest": "^0.3.0" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/load-json-file/node_modules/parse-json": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-4.0.0.tgz", - "integrity": "sha512-aOIos8bujGN93/8Ox/jPLh7RwVnPEysynVFE+fQZyg6jKELEHwzgKdLRFHUgXJL6kylijVSBC4BvN9OmsB48Rw==", - "dev": true, - "dependencies": { - "error-ex": "^1.3.1", - "json-parse-better-errors": "^1.0.1" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/load-json-file/node_modules/strip-bom": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-3.0.0.tgz", - "integrity": "sha512-vavAMRXOgBVNF6nyEEmL3DBK19iRpDcoIwW+swQ+CbGiu7lju6t+JklA1MHweoWtadgt4ISVUsXLyDq34ddcwA==", - "dev": true, - "engines": { - "node": ">=4" - } - }, - "node_modules/load-json-file/node_modules/type-fest": { - "version": "0.3.1", - "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.3.1.tgz", - "integrity": "sha512-cUGJnCdr4STbePCgqNFbpVNCepa+kAVohJs1sLhxzdH+gnEoOd8VhbYa7pD3zZYGiURWM2xzEII3fQcRizDkYQ==", - "dev": true, - "engines": { - "node": ">=6" - } - }, - "node_modules/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/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": { - "js-tokens": "^3.0.0 || ^4.0.0" - }, - "bin": { - "loose-envify": "cli.js" - } - }, - "node_modules/lru-cache": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", - "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", - "dev": true, - "dependencies": { - "yallist": "^4.0.0" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/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": { - "semver": "^7.5.3" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/make-dir/node_modules/semver": { - "version": "7.6.3", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.3.tgz", - "integrity": "sha512-oVekP1cKtI+CTDvHWYFUcMtsK/00wmAEfyqKfNdARm8u1wNVhSgaX7A8d4UuIlUI5e84iEwOhs7ZPYRmzU9U6A==", - "dev": true, - "bin": { - "semver": "bin/semver.js" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/makeerror": { - "version": "1.0.12", - "resolved": "https://registry.npmjs.org/makeerror/-/makeerror-1.0.12.tgz", - "integrity": "sha512-JmqCvUhmt43madlpFzG4BQzG2Z3m6tvQDNKdClZnO3VbIudJYmxsT0FNJMeiB2+JTSlTQTSbU8QdesVmwJcmLg==", - "dev": true, - "dependencies": { - "tmpl": "1.0.5" - } - }, - "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/micromatch": { - "version": "4.0.7", - "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.7.tgz", - "integrity": "sha512-LPP/3KorzCwBxfeUuZmaR6bG2kdeHSbe0P2tY3FLRU4vYrjYz5hI4QZwV0njUx3jeuKe67YukQ1LSPZBKDqO/Q==", - "dev": true, - "dependencies": { - "braces": "^3.0.3", - "picomatch": "^2.3.1" - }, - "engines": { - "node": ">=8.6" - } - }, - "node_modules/mime-db": { - "version": "1.52.0", - "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz", - "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==", - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/mime-types": { - "version": "2.1.35", - "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz", - "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==", - "dependencies": { - "mime-db": "1.52.0" - }, - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/mimic-fn": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-2.1.0.tgz", - "integrity": "sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==", - "dev": true, - "engines": { - "node": ">=6" - } - }, - "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.7", - "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.7.tgz", - "integrity": "sha512-bzfL1YUZsP41gmu/qjrEk0Q6i2ix/cVeAhbCbqH9u3zYutS1cLg00qhrD0M2MVdCcx4Sc0UpP2eBWo9rotpq6g==", - "dev": true, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/ms": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", - "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", - "dev": true - }, - "node_modules/natural-compare": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz", - "integrity": "sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==", - "dev": true - }, - "node_modules/nock": { - "version": "13.5.4", - "resolved": "https://registry.npmjs.org/nock/-/nock-13.5.4.tgz", - "integrity": "sha512-yAyTfdeNJGGBFxWdzSKCBYxs5FxLbCg5X5Q4ets974hcQzG1+qCxvIyOo4j2Ry6MUlhWVMX4OoYDefAIIwupjw==", - "dev": true, - "dependencies": { - "debug": "^4.1.0", - "json-stringify-safe": "^5.0.1", - "propagate": "^2.0.0" - }, - "engines": { - "node": ">= 10.13" - } - }, - "node_modules/node-abort-controller": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/node-abort-controller/-/node-abort-controller-3.1.1.tgz", - "integrity": "sha512-AGK2yQKIjRuqnc6VkX2Xj5d+QW8xZ87pa1UK6yA6ouUyuxfHuMP6umE5QK7UmTeOAymo+Zx1Fxiuw9rVx8taHQ==" - }, - "node_modules/node-int64": { - "version": "0.4.0", - "resolved": "https://registry.npmjs.org/node-int64/-/node-int64-0.4.0.tgz", - "integrity": "sha512-O5lz91xSOeoXP6DulyHfllpq+Eg00MWitZIbtPfoSEvqIHdl5gfcY6hYzDWnj0qD5tz52PI08u9qUvSVeUBeHw==", - "dev": true - }, - "node_modules/node-releases": { - "version": "2.0.18", - "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.18.tgz", - "integrity": "sha512-d9VeXT4SJ7ZeOqGX6R5EM022wpL+eWPooLI+5UpWn2jCT1aosUQEhQP214x33Wkwx3JQMvIm+tIoVOdodFS40g==", - "dev": true - }, - "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/npm-run-path": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-4.0.1.tgz", - "integrity": "sha512-S48WzZW777zhNIrn7gxOlISNAqi9ZC/uQFnRdbeIHhZhCA6UqpkOT8T1G7BvfdgP4Er8gF4sUbaS0i7QvIfCWw==", - "dev": true, - "dependencies": { - "path-key": "^3.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/object-assign": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", - "integrity": "sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/object-inspect": { - "version": "1.13.1", - "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.13.1.tgz", - "integrity": "sha512-5qoj1RUiKOMsCCNLV1CBiPYE10sziTsnmNxkAI/rZhiD63CF7IqdFGC/XzjWjpSgLf0LxXX3bDFIh0E18f6UhQ==", - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/object-keys": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.1.1.tgz", - "integrity": "sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==", - "dev": true, - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/object.assign": { - "version": "4.1.4", - "resolved": "https://registry.npmjs.org/object.assign/-/object.assign-4.1.4.tgz", - "integrity": "sha512-1mxKf0e58bvyjSCtKYY4sRe9itRk3PJpquJOjeIkz885CczcI4IvJJDLPS72oowuSh+pBxUFROpX+TU++hxhZQ==", - "dev": true, - "dependencies": { - "call-bind": "^1.0.2", - "define-properties": "^1.1.4", - "has-symbols": "^1.0.3", - "object-keys": "^1.1.1" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/object.entries": { - "version": "1.1.7", - "resolved": "https://registry.npmjs.org/object.entries/-/object.entries-1.1.7.tgz", - "integrity": "sha512-jCBs/0plmPsOnrKAfFQXRG2NFjlhZgjjcBLSmTnEhU8U6vVTsVe8ANeQJCHTl3gSsI4J+0emOoCgoKlmQPMgmA==", - "dev": true, - "dependencies": { - "call-bind": "^1.0.2", - "define-properties": "^1.2.0", - "es-abstract": "^1.22.1" - }, - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/object.fromentries": { - "version": "2.0.7", - "resolved": "https://registry.npmjs.org/object.fromentries/-/object.fromentries-2.0.7.tgz", - "integrity": "sha512-UPbPHML6sL8PI/mOqPwsH4G6iyXcCGzLin8KvEPenOZN5lpCNBZZQ+V62vdjB1mQHrmqGQt5/OJzemUA+KJmEA==", - "dev": true, - "dependencies": { - "call-bind": "^1.0.2", - "define-properties": "^1.2.0", - "es-abstract": "^1.22.1" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/object.groupby": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/object.groupby/-/object.groupby-1.0.1.tgz", - "integrity": "sha512-HqaQtqLnp/8Bn4GL16cj+CUYbnpe1bh0TtEaWvybszDG4tgxCJuRpV8VGuvNaI1fAnI4lUJzDG55MXcOH4JZcQ==", - "dev": true, - "dependencies": { - "call-bind": "^1.0.2", - "define-properties": "^1.2.0", - "es-abstract": "^1.22.1", - "get-intrinsic": "^1.2.1" - } - }, - "node_modules/object.hasown": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/object.hasown/-/object.hasown-1.1.3.tgz", - "integrity": "sha512-fFI4VcYpRHvSLXxP7yiZOMAd331cPfd2p7PFDVbgUsYOfCT3tICVqXWngbjr4m49OvsBwUBQ6O2uQoJvy3RexA==", - "dev": true, - "dependencies": { - "define-properties": "^1.2.0", - "es-abstract": "^1.22.1" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/object.values": { - "version": "1.1.7", - "resolved": "https://registry.npmjs.org/object.values/-/object.values-1.1.7.tgz", - "integrity": "sha512-aU6xnDFYT3x17e/f0IiiwlGPTy2jzMySGfUB4fq6z7CV8l85CWHDk5ErhyhpfDHhrOMwGFhSQkhMGHaIotA6Ng==", - "dev": true, - "dependencies": { - "call-bind": "^1.0.2", - "define-properties": "^1.2.0", - "es-abstract": "^1.22.1" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/once": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", - "integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==", - "dev": true, - "dependencies": { - "wrappy": "1" - } - }, - "node_modules/onetime": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/onetime/-/onetime-5.1.2.tgz", - "integrity": "sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg==", - "dev": true, - "dependencies": { - "mimic-fn": "^2.1.0" - }, - "engines": { - "node": ">=6" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/optionator": { - "version": "0.9.3", - "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.9.3.tgz", - "integrity": "sha512-JjCoypp+jKn1ttEFExxhetCKeJt9zhAgAve5FXHixTvFDW/5aEktX9bufBKLRRMdU7bNtpLfcGu94B3cdEJgjg==", - "dev": true, - "dependencies": { - "@aashutoshrathi/word-wrap": "^1.2.3", - "deep-is": "^0.1.3", - "fast-levenshtein": "^2.0.6", - "levn": "^0.4.1", - "prelude-ls": "^1.2.1", - "type-check": "^0.4.0" - }, - "engines": { - "node": ">= 0.8.0" - } - }, - "node_modules/p-limit": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz", - "integrity": "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==", - "dev": true, - "dependencies": { - "yocto-queue": "^0.1.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/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/p-locate/node_modules/p-limit": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", - "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", - "dev": true, - "dependencies": { - "p-try": "^2.0.0" - }, - "engines": { - "node": ">=6" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/p-try": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz", - "integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==", - "dev": true, - "engines": { - "node": ">=6" - } - }, - "node_modules/parent-module": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz", - "integrity": "sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==", - "dev": true, - "dependencies": { - "callsites": "^3.0.0" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/parse-json": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-5.2.0.tgz", - "integrity": "sha512-ayCKvm/phCGxOkYRSCM82iDwct8/EonSEgCSxWxD7ve6jHggsFl4fZVQBPRNgQoKiuV/odhFrGzQXZwbifC8Rg==", - "dev": true, - "dependencies": { - "@babel/code-frame": "^7.0.0", - "error-ex": "^1.3.1", - "json-parse-even-better-errors": "^2.3.0", - "lines-and-columns": "^1.1.6" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "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/path-is-absolute": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", - "integrity": "sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/path-key": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", - "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/path-parse": { - "version": "1.0.7", - "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz", - "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==", - "dev": true - }, - "node_modules/picocolors": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.0.1.tgz", - "integrity": "sha512-anP1Z8qwhkbmu7MFP5iTt+wQKXgwzf7zTyGlcdzabySa9vd0Xt392U0rVmz9poOaBj0uHJKyyo9/upk0HrEQew==", - "dev": true - }, - "node_modules/picomatch": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", - "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==", - "dev": true, - "engines": { - "node": ">=8.6" - }, - "funding": { - "url": "https://github.com/sponsors/jonschlinkert" - } - }, - "node_modules/pify": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/pify/-/pify-4.0.1.tgz", - "integrity": "sha512-uB80kBFb/tfd68bVleG9T5GGsGPjJrLAUpR5PZIrhBnIaRTQRjqdJSsIKkOP6OAIFbj7GOrcudc5pNjZ+geV2g==", - "dev": true, - "engines": { - "node": ">=6" - } - }, - "node_modules/pirates": { - "version": "4.0.6", - "resolved": "https://registry.npmjs.org/pirates/-/pirates-4.0.6.tgz", - "integrity": "sha512-saLsH7WeYYPiD25LDuLRRY/i+6HaPYr6G1OUlN39otzkSTxKnubR9RTxS3/Kk50s1g2JTgFwWQDQyplC5/SHZg==", - "dev": true, - "engines": { - "node": ">= 6" - } - }, - "node_modules/pkg-conf": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/pkg-conf/-/pkg-conf-3.1.0.tgz", - "integrity": "sha512-m0OTbR/5VPNPqO1ph6Fqbj7Hv6QU7gR/tQW40ZqrL1rjgCU85W6C1bJn0BItuJqnR98PWzw7Z8hHeChD1WrgdQ==", - "dev": true, - "dependencies": { - "find-up": "^3.0.0", - "load-json-file": "^5.2.0" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/pkg-conf/node_modules/find-up": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/find-up/-/find-up-3.0.0.tgz", - "integrity": "sha512-1yD6RmLI1XBfxugvORwlck6f75tYL+iR0jqwsOrOxMZyGYqUuDhJ0l4AXdO1iX/FTs9cBAMEk1gWSEx1kSbylg==", - "dev": true, - "dependencies": { - "locate-path": "^3.0.0" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/pkg-conf/node_modules/locate-path": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-3.0.0.tgz", - "integrity": "sha512-7AO748wWnIhNqAuaty2ZWHkQHRSNfPVIsPIfwEOWO22AmaoVrWavlOcMR5nzTLNYvp36X220/maaRsrec1G65A==", - "dev": true, - "dependencies": { - "p-locate": "^3.0.0", - "path-exists": "^3.0.0" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/pkg-conf/node_modules/p-limit": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", - "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", - "dev": true, - "dependencies": { - "p-try": "^2.0.0" - }, - "engines": { - "node": ">=6" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/pkg-conf/node_modules/p-locate": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-3.0.0.tgz", - "integrity": "sha512-x+12w/To+4GFfgJhBEpiDcLozRJGegY+Ei7/z0tSLkMmxGZNybVMSfWj9aJn8Z5Fc7dBUNJOOVgPv2H7IwulSQ==", - "dev": true, - "dependencies": { - "p-limit": "^2.0.0" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/pkg-conf/node_modules/path-exists": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-3.0.0.tgz", - "integrity": "sha512-bpC7GYwiDYQ4wYLe+FA8lhRjhQCMcQGuSgGGqDkg/QerRWw9CmGRT0iSOVRSZJ29NMLZgIzqaljJ63oaL4NIJQ==", - "dev": true, - "engines": { - "node": ">=4" - } - }, - "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==", - "dev": true, - "dependencies": { - "find-up": "^4.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/prelude-ls": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.2.1.tgz", - "integrity": "sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==", - "dev": true, - "engines": { - "node": ">= 0.8.0" - } - }, - "node_modules/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": { - "@jest/schemas": "^29.6.3", - "ansi-styles": "^5.0.0", - "react-is": "^18.0.0" - }, - "engines": { - "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/prompts": { - "version": "2.4.2", - "resolved": "https://registry.npmjs.org/prompts/-/prompts-2.4.2.tgz", - "integrity": "sha512-NxNv/kLguCA7p3jE8oL2aEBsrJWgAakBpgmgK6lpPWV+WuOmY6r2/zbAVnP+T8bQlA0nzHXSJSJW0Hq7ylaD2Q==", - "dev": true, - "dependencies": { - "kleur": "^3.0.3", - "sisteransi": "^1.0.5" - }, - "engines": { - "node": ">= 6" - } - }, - "node_modules/prop-types": { - "version": "15.8.1", - "resolved": "https://registry.npmjs.org/prop-types/-/prop-types-15.8.1.tgz", - "integrity": "sha512-oj87CgZICdulUohogVAR7AjlC0327U4el4L6eAvOqCeudMDVU0NThNaV+b9Df4dXgSP1gXMTnPdhfe/2qDH5cg==", - "dev": true, - "dependencies": { - "loose-envify": "^1.4.0", - "object-assign": "^4.1.1", - "react-is": "^16.13.1" - } - }, - "node_modules/prop-types/node_modules/react-is": { - "version": "16.13.1", - "resolved": "https://registry.npmjs.org/react-is/-/react-is-16.13.1.tgz", - "integrity": "sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==", - "dev": true - }, - "node_modules/propagate": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/propagate/-/propagate-2.0.1.tgz", - "integrity": "sha512-vGrhOavPSTz4QVNuBNdcNXePNdNMaO1xj9yBeH1ScQPjk/rhg9sSlCXPhMkFuaNNW/syTvYqsnbIJxMBfRbbag==", - "dev": true, - "engines": { - "node": ">= 8" - } - }, - "node_modules/proxy-from-env": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/proxy-from-env/-/proxy-from-env-1.1.0.tgz", - "integrity": "sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg==" - }, - "node_modules/punycode": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.1.tgz", - "integrity": "sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==", - "dev": true, - "engines": { - "node": ">=6" - } - }, - "node_modules/pure-rand": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/pure-rand/-/pure-rand-6.1.0.tgz", - "integrity": "sha512-bVWawvoZoBYpp6yIoQtQXHZjmz35RSVHnUOTefl8Vcjr8snTPY1wnpSPMWekcFwbxI6gtmT7rSYPFvz71ldiOA==", - "dev": true, - "funding": [ - { - "type": "individual", - "url": "https://github.com/sponsors/dubzzz" - }, - { - "type": "opencollective", - "url": "https://opencollective.com/fast-check" - } - ] - }, - "node_modules/qs": { - "version": "6.13.0", - "resolved": "https://registry.npmjs.org/qs/-/qs-6.13.0.tgz", - "integrity": "sha512-+38qI9SOr8tfZ4QmJNplMUxqjbe7LKvvZgWdExBOmd+egZTtjLB67Gu0HRX3u/XOq7UU2Nx6nsjvS16Z9uwfpg==", - "dependencies": { - "side-channel": "^1.0.6" - }, - "engines": { - "node": ">=0.6" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/queue-microtask": { - "version": "1.2.3", - "resolved": "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.3.tgz", - "integrity": "sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==", - "dev": true, - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/feross" - }, - { - "type": "patreon", - "url": "https://www.patreon.com/feross" - }, - { - "type": "consulting", - "url": "https://feross.org/support" - } - ] - }, - "node_modules/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/reflect.getprototypeof": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/reflect.getprototypeof/-/reflect.getprototypeof-1.0.4.tgz", - "integrity": "sha512-ECkTw8TmJwW60lOTR+ZkODISW6RQ8+2CL3COqtiJKLd6MmB45hN51HprHFziKLGkAuTGQhBb91V8cy+KHlaCjw==", - "dev": true, - "dependencies": { - "call-bind": "^1.0.2", - "define-properties": "^1.2.0", - "es-abstract": "^1.22.1", - "get-intrinsic": "^1.2.1", - "globalthis": "^1.0.3", - "which-builtin-type": "^1.1.3" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/regexp.prototype.flags": { - "version": "1.5.1", - "resolved": "https://registry.npmjs.org/regexp.prototype.flags/-/regexp.prototype.flags-1.5.1.tgz", - "integrity": "sha512-sy6TXMN+hnP/wMy+ISxg3krXx7BAtWVO4UouuCN/ziM9UEne0euamVNafDfvC83bRNr95y0V5iijeDQFUNpvrg==", - "dev": true, - "dependencies": { - "call-bind": "^1.0.2", - "define-properties": "^1.2.0", - "set-function-name": "^2.0.0" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/regexpp": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/regexpp/-/regexpp-3.2.0.tgz", - "integrity": "sha512-pq2bWo9mVD43nbts2wGv17XLiNLya+GklZ8kaDLV2Z08gDCsGpnKn9BFMepvWuHCbyVvY7J5o5+BVvoQbmlJLg==", - "dev": true, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/mysticatea" - } - }, - "node_modules/require-directory": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz", - "integrity": "sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/resolve": { - "version": "1.22.8", - "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.8.tgz", - "integrity": "sha512-oKWePCxqpd6FlLvGV1VU0x7bkPmmCNolxzjMf4NczoDnQcIWrAF+cPtZn5i6n+RfD2d9i0tzpKnG6Yk168yIyw==", - "dev": true, - "dependencies": { - "is-core-module": "^2.13.0", - "path-parse": "^1.0.7", - "supports-preserve-symlinks-flag": "^1.0.0" - }, - "bin": { - "resolve": "bin/resolve" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/resolve-cwd": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/resolve-cwd/-/resolve-cwd-3.0.0.tgz", - "integrity": "sha512-OrZaX2Mb+rJCpH/6CpSqt9xFVpN++x01XnN2ie9g6P5/3xelLAkXWVADpdz1IHD/KFfEXyE6V0U01OQ3UO2rEg==", - "dev": true, - "dependencies": { - "resolve-from": "^5.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "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.exports": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/resolve.exports/-/resolve.exports-2.0.2.tgz", - "integrity": "sha512-X2UW6Nw3n/aMgDVy+0rSqgHlv39WZAlZrXCdnbyEiKm17DSqHX4MmQMaST3FbeWR5FTuRcUwYAziZajji0Y7mg==", - "dev": true, - "engines": { - "node": ">=10" - } - }, - "node_modules/reusify": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/reusify/-/reusify-1.0.4.tgz", - "integrity": "sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw==", - "dev": true, - "engines": { - "iojs": ">=1.0.0", - "node": ">=0.10.0" - } - }, - "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/run-parallel": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/run-parallel/-/run-parallel-1.2.0.tgz", - "integrity": "sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==", - "dev": true, - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/feross" - }, - { - "type": "patreon", - "url": "https://www.patreon.com/feross" - }, - { - "type": "consulting", - "url": "https://feross.org/support" - } - ], - "dependencies": { - "queue-microtask": "^1.2.2" - } - }, - "node_modules/safe-array-concat": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/safe-array-concat/-/safe-array-concat-1.0.1.tgz", - "integrity": "sha512-6XbUAseYE2KtOuGueyeobCySj9L4+66Tn6KQMOPQJrAJEowYKW/YR/MGJZl7FdydUdaFu4LYyDZjxf4/Nmo23Q==", - "dev": true, - "dependencies": { - "call-bind": "^1.0.2", - "get-intrinsic": "^1.2.1", - "has-symbols": "^1.0.3", - "isarray": "^2.0.5" - }, - "engines": { - "node": ">=0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/safe-regex-test": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/safe-regex-test/-/safe-regex-test-1.0.0.tgz", - "integrity": "sha512-JBUUzyOgEwXQY1NuPtvcj/qcBDbDmEvWufhlnXZIm75DEHp+afM1r1ujJpJsV/gSM4t59tpDyPi1sd6ZaPFfsA==", - "dev": true, - "dependencies": { - "call-bind": "^1.0.2", - "get-intrinsic": "^1.1.3", - "is-regex": "^1.1.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "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/set-function-length": { - "version": "1.2.2", - "resolved": "https://registry.npmjs.org/set-function-length/-/set-function-length-1.2.2.tgz", - "integrity": "sha512-pgRc4hJ4/sNjWCSS9AmnS40x3bNMDTknHgL5UaMBTMyJnU90EgWh1Rz+MC9eFu4BuN/UwZjKQuY/1v3rM7HMfg==", - "dependencies": { - "define-data-property": "^1.1.4", - "es-errors": "^1.3.0", - "function-bind": "^1.1.2", - "get-intrinsic": "^1.2.4", - "gopd": "^1.0.1", - "has-property-descriptors": "^1.0.2" - }, - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/set-function-name": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/set-function-name/-/set-function-name-2.0.1.tgz", - "integrity": "sha512-tMNCiqYVkXIZgc2Hnoy2IvC/f8ezc5koaRFkCjrpWzGpCd3qbZXPzVy9MAZzK1ch/X0jvSkojys3oqJN0qCmdA==", - "dev": true, - "dependencies": { - "define-data-property": "^1.0.1", - "functions-have-names": "^1.2.3", - "has-property-descriptors": "^1.0.0" - }, - "engines": { - "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", - "integrity": "sha512-fDW/EZ6Q9RiO8eFG8Hj+7u/oW+XrPTIChwCOM2+th2A6OblDtYYIpve9m+KvI9Z4C9qSEXlaGR6bTEYHReuglA==", - "dependencies": { - "call-bind": "^1.0.7", - "es-errors": "^1.3.0", - "get-intrinsic": "^1.2.4", - "object-inspect": "^1.13.1" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "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==", - "dev": true - }, - "node_modules/sisteransi": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/sisteransi/-/sisteransi-1.0.5.tgz", - "integrity": "sha512-bLGGlR1QxBcynn2d5YmDX4MGjlZvy2MRBDRNHLJ8VI6l6+9FUiyTFNJ0IveOSP0bcXgVDPRcfGqA0pjaqUpfVg==", - "dev": true - }, - "node_modules/slash": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/slash/-/slash-3.0.0.tgz", - "integrity": "sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/source-map": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", - "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/source-map-support": { - "version": "0.5.13", - "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.13.tgz", - "integrity": "sha512-SHSKFHadjVA5oR4PPqhtAVdcBWwRYVd6g6cAXnIbRiIwc2EhPrTuKUBdSLvlEKyIP3GCf89fltvcZiP9MMFA1w==", - "dev": true, - "dependencies": { - "buffer-from": "^1.0.0", - "source-map": "^0.6.0" - } - }, - "node_modules/sprintf-js": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz", - "integrity": "sha512-D9cPgkvLlV3t3IzL0D0YLvGA9Ahk4PcvVwUbN0dSGr1aP0Nrt4AEnTUbuGvquEC0mA64Gqt1fzirlRs5ibXx8g==", - "dev": true - }, - "node_modules/stack-utils": { - "version": "2.0.6", - "resolved": "https://registry.npmjs.org/stack-utils/-/stack-utils-2.0.6.tgz", - "integrity": "sha512-XlkWvfIm6RmsWtNJx+uqtKLS8eqFbxUg0ZzLXqY0caEy9l7hruX8IpiDnjsLavoBgqCCR71TqWO8MaXYheJ3RQ==", - "dev": true, - "dependencies": { - "escape-string-regexp": "^2.0.0" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/standard": { - "version": "17.1.0", - "resolved": "https://registry.npmjs.org/standard/-/standard-17.1.0.tgz", - "integrity": "sha512-jaDqlNSzLtWYW4lvQmU0EnxWMUGQiwHasZl5ZEIwx3S/ijZDjZOzs1y1QqKwKs5vqnFpGtizo4NOYX2s0Voq/g==", - "dev": true, - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/feross" - }, - { - "type": "patreon", - "url": "https://www.patreon.com/feross" - }, - { - "type": "consulting", - "url": "https://feross.org/support" - } - ], - "dependencies": { - "eslint": "^8.41.0", - "eslint-config-standard": "17.1.0", - "eslint-config-standard-jsx": "^11.0.0", - "eslint-plugin-import": "^2.27.5", - "eslint-plugin-n": "^15.7.0", - "eslint-plugin-promise": "^6.1.1", - "eslint-plugin-react": "^7.32.2", - "standard-engine": "^15.0.0", - "version-guard": "^1.1.1" - }, - "bin": { - "standard": "bin/cmd.cjs" - }, - "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" - } - }, - "node_modules/standard-engine": { - "version": "15.0.0", - "resolved": "https://registry.npmjs.org/standard-engine/-/standard-engine-15.0.0.tgz", - "integrity": "sha512-4xwUhJNo1g/L2cleysUqUv7/btn7GEbYJvmgKrQ2vd/8pkTmN8cpqAZg+BT8Z1hNeEH787iWUdOpL8fmApLtxA==", - "dev": true, - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/feross" - }, - { - "type": "patreon", - "url": "https://www.patreon.com/feross" - }, - { - "type": "consulting", - "url": "https://feross.org/support" - } - ], - "dependencies": { - "get-stdin": "^8.0.0", - "minimist": "^1.2.6", - "pkg-conf": "^3.1.0", - "xdg-basedir": "^4.0.0" - }, - "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" - } - }, - "node_modules/string-length": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/string-length/-/string-length-4.0.2.tgz", - "integrity": "sha512-+l6rNN5fYHNhZZy41RXsYptCjA2Igmq4EG7kZAYFQI1E1VTXarr6ZPXBg6eq7Y6eK4FEhY6AJlyuFIb/v/S0VQ==", - "dev": true, - "dependencies": { - "char-regex": "^1.0.2", - "strip-ansi": "^6.0.0" - }, - "engines": { - "node": ">=10" - } - }, - "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.10", - "resolved": "https://registry.npmjs.org/string.prototype.matchall/-/string.prototype.matchall-4.0.10.tgz", - "integrity": "sha512-rGXbGmOEosIQi6Qva94HUjgPs9vKW+dkG7Y8Q5O2OYkWL6wFaTRZO8zM4mhP94uX55wgyrXzfS2aGtGzUL7EJQ==", - "dev": true, - "dependencies": { - "call-bind": "^1.0.2", - "define-properties": "^1.2.0", - "es-abstract": "^1.22.1", - "get-intrinsic": "^1.2.1", - "has-symbols": "^1.0.3", - "internal-slot": "^1.0.5", - "regexp.prototype.flags": "^1.5.0", - "set-function-name": "^2.0.0", - "side-channel": "^1.0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/string.prototype.trim": { - "version": "1.2.8", - "resolved": "https://registry.npmjs.org/string.prototype.trim/-/string.prototype.trim-1.2.8.tgz", - "integrity": "sha512-lfjY4HcixfQXOfaqCvcBuOIapyaroTXhbkfJN3gcB1OtyupngWK4sEET9Knd0cXd28kTUqu/kHoV4HKSJdnjiQ==", - "dev": true, - "dependencies": { - "call-bind": "^1.0.2", - "define-properties": "^1.2.0", - "es-abstract": "^1.22.1" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/string.prototype.trimend": { - "version": "1.0.7", - "resolved": "https://registry.npmjs.org/string.prototype.trimend/-/string.prototype.trimend-1.0.7.tgz", - "integrity": "sha512-Ni79DqeB72ZFq1uH/L6zJ+DKZTkOtPIHovb3YZHQViE+HDouuU4mBrLOLDn5Dde3RF8qw5qVETEjhu9locMLvA==", - "dev": true, - "dependencies": { - "call-bind": "^1.0.2", - "define-properties": "^1.2.0", - "es-abstract": "^1.22.1" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/string.prototype.trimstart": { - "version": "1.0.7", - "resolved": "https://registry.npmjs.org/string.prototype.trimstart/-/string.prototype.trimstart-1.0.7.tgz", - "integrity": "sha512-NGhtDFu3jCEm7B4Fy0DpLewdJQOZcQ0rGbwQ/+stjnrp2i+rlKeCvos9hOIeCmqwratM47OBxY7uFZzjxHXmrg==", - "dev": true, - "dependencies": { - "call-bind": "^1.0.2", - "define-properties": "^1.2.0", - "es-abstract": "^1.22.1" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/strip-ansi": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", - "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", - "dev": true, - "dependencies": { - "ansi-regex": "^5.0.1" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/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/strip-final-newline": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/strip-final-newline/-/strip-final-newline-2.0.0.tgz", - "integrity": "sha512-BrpvfNAE3dcvq7ll3xVumzjKjZQ5tI1sEUIKr3Uoks0XUl45St3FlatVqef9prk4jRDzhW6WZg+3bk93y6pLjA==", - "dev": true, - "engines": { - "node": ">=6" - } - }, - "node_modules/strip-json-comments": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz", - "integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==", - "dev": true, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/supports-color": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", - "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", - "dev": true, - "dependencies": { - "has-flag": "^4.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/supports-preserve-symlinks-flag": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz", - "integrity": "sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==", - "dev": true, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/test-exclude": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/test-exclude/-/test-exclude-6.0.0.tgz", - "integrity": "sha512-cAGWPIyOHU6zlmg88jwm7VRyXnMN7iV68OGAbYDk/Mh/xC/pzVPlQtY6ngoIH/5/tciuhGfvESU8GrHrcxD56w==", - "dev": true, - "dependencies": { - "@istanbuljs/schema": "^0.1.2", - "glob": "^7.1.4", - "minimatch": "^3.0.4" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/text-table": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz", - "integrity": "sha512-N+8UisAXDGk8PFXP4HAzVR9nbfmVJ3zYLAWiTIoqC5v5isinhr+r5uaO8+7r3BMfuNIufIsA7RdpVgacC2cSpw==", - "dev": true - }, - "node_modules/tmpl": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/tmpl/-/tmpl-1.0.5.tgz", - "integrity": "sha512-3f0uOEAQwIqGuWW2MVzYg8fV/QNnc/IpuJNG837rLuczAaLVHslWHZQj4IGiEl5Hs3kkbhwL9Ab7Hrsmuj+Smw==", - "dev": true - }, - "node_modules/to-fast-properties": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/to-fast-properties/-/to-fast-properties-2.0.0.tgz", - "integrity": "sha512-/OaKK0xYrs3DmxRYqL/yDc+FxFUVYhDlXMhRmv3z915w2HF1tnN1omB354j8VUGO/hbRzyD6Y3sA7v7GS/ceog==", - "dev": true, - "engines": { - "node": ">=4" - } - }, - "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/tsconfig-paths": { - "version": "3.14.2", - "resolved": "https://registry.npmjs.org/tsconfig-paths/-/tsconfig-paths-3.14.2.tgz", - "integrity": "sha512-o/9iXgCYc5L/JxCHPe3Hvh8Q/2xm5Z+p18PESBU6Ff33695QnCHBEjcytY2q19ua7Mbl/DavtBOLq+oG0RCL+g==", - "dev": true, - "dependencies": { - "@types/json5": "^0.0.29", - "json5": "^1.0.2", - "minimist": "^1.2.6", - "strip-bom": "^3.0.0" - } - }, - "node_modules/tsconfig-paths/node_modules/json5": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/json5/-/json5-1.0.2.tgz", - "integrity": "sha512-g1MWMLBiz8FKi1e4w0UyVL3w+iJceWAFBAaBnnGKOpNa5f8TLktkbre1+s6oICydWAm+HRUGTmI+//xv2hvXYA==", - "dev": true, - "dependencies": { - "minimist": "^1.2.0" - }, - "bin": { - "json5": "lib/cli.js" - } - }, - "node_modules/tsconfig-paths/node_modules/strip-bom": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-3.0.0.tgz", - "integrity": "sha512-vavAMRXOgBVNF6nyEEmL3DBK19iRpDcoIwW+swQ+CbGiu7lju6t+JklA1MHweoWtadgt4ISVUsXLyDq34ddcwA==", - "dev": true, - "engines": { - "node": ">=4" - } - }, - "node_modules/type-check": { - "version": "0.4.0", - "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.4.0.tgz", - "integrity": "sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==", - "dev": true, - "dependencies": { - "prelude-ls": "^1.2.1" - }, - "engines": { - "node": ">= 0.8.0" - } - }, - "node_modules/type-detect": { - "version": "4.0.8", - "resolved": "https://registry.npmjs.org/type-detect/-/type-detect-4.0.8.tgz", - "integrity": "sha512-0fr/mIH1dlO+x7TlcMy+bIDqKPsw/70tVyeHW787goQjhmqaZe10uwLujubK9q9Lg6Fiho1KUKDYz0Z7k7g5/g==", - "dev": true, - "engines": { - "node": ">=4" - } - }, - "node_modules/type-fest": { - "version": "0.21.3", - "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.21.3.tgz", - "integrity": "sha512-t0rzBq87m3fVcduHDUFhKmyyX+9eo6WQjZvf51Ea/M0Q7+T374Jp1aUiyUl0GKxp8M/OETVHSDvmkyPgvX+X2w==", - "dev": true, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/typed-array-buffer": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/typed-array-buffer/-/typed-array-buffer-1.0.0.tgz", - "integrity": "sha512-Y8KTSIglk9OZEr8zywiIHG/kmQ7KWyjseXs1CbSo8vC42w7hg2HgYTxSWwP0+is7bWDc1H+Fo026CpHFwm8tkw==", - "dev": true, - "dependencies": { - "call-bind": "^1.0.2", - "get-intrinsic": "^1.2.1", - "is-typed-array": "^1.1.10" - }, - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/typed-array-byte-length": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/typed-array-byte-length/-/typed-array-byte-length-1.0.0.tgz", - "integrity": "sha512-Or/+kvLxNpeQ9DtSydonMxCx+9ZXOswtwJn17SNLvhptaXYDJvkFFP5zbfU/uLmvnBJlI4yrnXRxpdWH/M5tNA==", - "dev": true, - "dependencies": { - "call-bind": "^1.0.2", - "for-each": "^0.3.3", - "has-proto": "^1.0.1", - "is-typed-array": "^1.1.10" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/typed-array-byte-offset": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/typed-array-byte-offset/-/typed-array-byte-offset-1.0.0.tgz", - "integrity": "sha512-RD97prjEt9EL8YgAgpOkf3O4IF9lhJFr9g0htQkm0rchFp/Vx7LW5Q8fSXXub7BXAODyUQohRMyOc3faCPd0hg==", - "dev": true, - "dependencies": { - "available-typed-arrays": "^1.0.5", - "call-bind": "^1.0.2", - "for-each": "^0.3.3", - "has-proto": "^1.0.1", - "is-typed-array": "^1.1.10" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/typed-array-length": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/typed-array-length/-/typed-array-length-1.0.4.tgz", - "integrity": "sha512-KjZypGq+I/H7HI5HlOoGHkWUUGq+Q0TPhQurLbyrVrvnKTBgzLhIJ7j6J/XTQOi0d1RjyZ0wdas8bKs2p0x3Ng==", - "dev": true, - "dependencies": { - "call-bind": "^1.0.2", - "for-each": "^0.3.3", - "is-typed-array": "^1.1.9" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/typescript": { - "version": "5.5.4", - "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.5.4.tgz", - "integrity": "sha512-Mtq29sKDAEYP7aljRgtPOpTvOfbwRWlS6dPRzwjdE+C0R4brX/GUyhHSecbHMFLNBLcJIPt9nl9yG5TZ1weH+Q==", - "dev": true, - "bin": { - "tsc": "bin/tsc", - "tsserver": "bin/tsserver" - }, - "engines": { - "node": ">=14.17" - } - }, - "node_modules/unbox-primitive": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/unbox-primitive/-/unbox-primitive-1.0.2.tgz", - "integrity": "sha512-61pPlCD9h51VoreyJ0BReideM3MDKMKnh6+V9L08331ipq6Q8OFXZYiqP6n/tbHx4s5I9uRhcye6BrbkizkBDw==", - "dev": true, - "dependencies": { - "call-bind": "^1.0.2", - "has-bigints": "^1.0.2", - "has-symbols": "^1.0.3", - "which-boxed-primitive": "^1.0.2" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/undici-types": { - "version": "6.18.2", - "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-6.18.2.tgz", - "integrity": "sha512-5ruQbENj95yDYJNS3TvcaxPMshV7aizdv/hWYjGIKoANWKjhWNBsr2YEuYZKodQulB1b8l7ILOuDQep3afowQQ==", - "dev": true - }, - "node_modules/update-browserslist-db": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.1.0.tgz", - "integrity": "sha512-EdRAaAyk2cUE1wOf2DkEhzxqOQvFOoRJFNS6NeyJ01Gp2beMRpBAINjM2iDXE3KCuKhwnvHIQCJm6ThL2Z+HzQ==", - "dev": true, - "funding": [ - { - "type": "opencollective", - "url": "https://opencollective.com/browserslist" - }, - { - "type": "tidelift", - "url": "https://tidelift.com/funding/github/npm/browserslist" - }, - { - "type": "github", - "url": "https://github.com/sponsors/ai" - } - ], - "dependencies": { - "escalade": "^3.1.2", - "picocolors": "^1.0.1" - }, - "bin": { - "update-browserslist-db": "cli.js" - }, - "peerDependencies": { - "browserslist": ">= 4.21.0" - } - }, - "node_modules/uri-js": { - "version": "4.4.1", - "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz", - "integrity": "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==", - "dev": true, - "dependencies": { - "punycode": "^2.1.0" - } - }, - "node_modules/v8-to-istanbul": { - "version": "9.3.0", - "resolved": "https://registry.npmjs.org/v8-to-istanbul/-/v8-to-istanbul-9.3.0.tgz", - "integrity": "sha512-kiGUalWN+rgBJ/1OHZsBtU4rXZOfj/7rKQxULKlIzwzQSvMJUUNgPwJEEh7gU6xEVxC0ahoOBvN2YI8GH6FNgA==", - "dev": true, - "dependencies": { - "@jridgewell/trace-mapping": "^0.3.12", - "@types/istanbul-lib-coverage": "^2.0.1", - "convert-source-map": "^2.0.0" - }, - "engines": { - "node": ">=10.12.0" - } - }, - "node_modules/version-guard": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/version-guard/-/version-guard-1.1.1.tgz", - "integrity": "sha512-MGQLX89UxmYHgDvcXyjBI0cbmoW+t/dANDppNPrno64rYr8nH4SHSuElQuSYdXGEs0mUzdQe1BY+FhVPNsAmJQ==", - "dev": true, - "engines": { - "node": ">=0.10.48" - } - }, - "node_modules/walker": { - "version": "1.0.8", - "resolved": "https://registry.npmjs.org/walker/-/walker-1.0.8.tgz", - "integrity": "sha512-ts/8E8l5b7kY0vlWLewOkDXMmPdLcVV4GmOQLyxuSswIJsweeFZtAsMF7k1Nszz+TYBQrlYRmzOnr398y1JemQ==", - "dev": true, - "dependencies": { - "makeerror": "1.0.12" - } - }, - "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", - "integrity": "sha512-bwZdv0AKLpplFY2KZRX6TvyuN7ojjr7lwkg6ml0roIy9YeuSr7JS372qlNW18UQYzgYK9ziGcerWqZOmEn9VNg==", - "dev": true, - "dependencies": { - "is-bigint": "^1.0.1", - "is-boolean-object": "^1.1.0", - "is-number-object": "^1.0.4", - "is-string": "^1.0.5", - "is-symbol": "^1.0.3" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/which-builtin-type": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/which-builtin-type/-/which-builtin-type-1.1.3.tgz", - "integrity": "sha512-YmjsSMDBYsM1CaFiayOVT06+KJeXf0o5M/CAd4o1lTadFAtacTUM49zoYxr/oroopFDfhvN6iEcBxUyc3gvKmw==", - "dev": true, - "dependencies": { - "function.prototype.name": "^1.1.5", - "has-tostringtag": "^1.0.0", - "is-async-function": "^2.0.0", - "is-date-object": "^1.0.5", - "is-finalizationregistry": "^1.0.2", - "is-generator-function": "^1.0.10", - "is-regex": "^1.1.4", - "is-weakref": "^1.0.2", - "isarray": "^2.0.5", - "which-boxed-primitive": "^1.0.2", - "which-collection": "^1.0.1", - "which-typed-array": "^1.1.9" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/which-collection": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/which-collection/-/which-collection-1.0.1.tgz", - "integrity": "sha512-W8xeTUwaln8i3K/cY1nGXzdnVZlidBcagyNFtBdD5kxnb4TvGKR7FfSIS3mYpwWS1QUCutfKz8IY8RjftB0+1A==", - "dev": true, - "dependencies": { - "is-map": "^2.0.1", - "is-set": "^2.0.1", - "is-weakmap": "^2.0.1", - "is-weakset": "^2.0.1" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/which-typed-array": { - "version": "1.1.13", - "resolved": "https://registry.npmjs.org/which-typed-array/-/which-typed-array-1.1.13.tgz", - "integrity": "sha512-P5Nra0qjSncduVPEAr7xhoF5guty49ArDTwzJ/yNuPIbZppyRxFQsRCWrocxIY+CnMVG+qfbU2FmDKyvSGClow==", - "dev": true, - "dependencies": { - "available-typed-arrays": "^1.0.5", - "call-bind": "^1.0.4", - "for-each": "^0.3.3", - "gopd": "^1.0.1", - "has-tostringtag": "^1.0.0" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/wrap-ansi": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", - "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", - "dev": true, - "dependencies": { - "ansi-styles": "^4.0.0", - "string-width": "^4.1.0", - "strip-ansi": "^6.0.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/chalk/wrap-ansi?sponsor=1" - } - }, - "node_modules/wrappy": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", - "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==", - "dev": true - }, - "node_modules/write-file-atomic": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/write-file-atomic/-/write-file-atomic-4.0.2.tgz", - "integrity": "sha512-7KxauUdBmSdWnmpaGFg+ppNjKF8uNLry8LyzjauQDOVONfFLNKrKvQOxZ/VuTIcS/gge/YNahf5RIIQWTSarlg==", - "dev": true, - "dependencies": { - "imurmurhash": "^0.1.4", - "signal-exit": "^3.0.7" - }, - "engines": { - "node": "^12.13.0 || ^14.15.0 || >=16.0.0" - } - }, - "node_modules/xdg-basedir": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/xdg-basedir/-/xdg-basedir-4.0.0.tgz", - "integrity": "sha512-PSNhEJDejZYV7h50BohL09Er9VaIefr2LMAf3OEmpCkjOi34eYyQYAXUTjEQtZJTKcF0E2UKTh+osDLsgNim9Q==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/y18n": { - "version": "5.0.8", - "resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz", - "integrity": "sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==", - "dev": true, - "engines": { - "node": ">=10" - } - }, - "node_modules/yallist": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", - "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", - "dev": true - }, - "node_modules/yargs": { - "version": "17.7.2", - "resolved": "https://registry.npmjs.org/yargs/-/yargs-17.7.2.tgz", - "integrity": "sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w==", - "dev": true, - "dependencies": { - "cliui": "^8.0.1", - "escalade": "^3.1.1", - "get-caller-file": "^2.0.5", - "require-directory": "^2.1.1", - "string-width": "^4.2.3", - "y18n": "^5.0.5", - "yargs-parser": "^21.1.1" - }, - "engines": { - "node": ">=12" - } - }, - "node_modules/yargs-parser": { - "version": "21.1.1", - "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-21.1.1.tgz", - "integrity": "sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw==", - "dev": true, - "engines": { - "node": ">=12" - } - }, - "node_modules/yocto-queue": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz", - "integrity": "sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==", - "dev": true, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - } - }, - "dependencies": { - "@aashutoshrathi/word-wrap": { - "version": "1.2.6", - "resolved": "https://registry.npmjs.org/@aashutoshrathi/word-wrap/-/word-wrap-1.2.6.tgz", - "integrity": "sha512-1Yjs2SvM8TflER/OD3cOjhWWOZb58A2t7wpE2S9XfBYTiIl+XFhQG2bjy4Pu1I+EAlCNUzRDYDdFwFYUKvXcIA==", - "dev": true - }, - "@ampproject/remapping": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/@ampproject/remapping/-/remapping-2.3.0.tgz", - "integrity": "sha512-30iZtAPgz+LTIYoeivqYo853f02jBYSd5uGnGpkFV0M3xOt9aN73erkgYAmZU43x4VfqcnLxW9Kpg3R5LC4YYw==", - "dev": true, - "requires": { - "@jridgewell/gen-mapping": "^0.3.5", - "@jridgewell/trace-mapping": "^0.3.24" - } - }, - "@babel/code-frame": { - "version": "7.24.7", - "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.24.7.tgz", - "integrity": "sha512-BcYH1CVJBO9tvyIZ2jVeXgSIMvGZ2FDRvDdOIVQyuklNKSsx+eppDEBq/g47Ayw+RqNFE+URvOShmf+f/qwAlA==", - "dev": true, - "requires": { - "@babel/highlight": "^7.24.7", - "picocolors": "^1.0.0" - } - }, - "@babel/compat-data": { - "version": "7.25.2", - "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.25.2.tgz", - "integrity": "sha512-bYcppcpKBvX4znYaPEeFau03bp89ShqNMLs+rmdptMw+heSZh9+z84d2YG+K7cYLbWwzdjtDoW/uqZmPjulClQ==", - "dev": true - }, - "@babel/core": { - "version": "7.25.2", - "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.25.2.tgz", - "integrity": "sha512-BBt3opiCOxUr9euZ5/ro/Xv8/V7yJ5bjYMqG/C1YAo8MIKAnumZalCN+msbci3Pigy4lIQfPUpfMM27HMGaYEA==", - "dev": true, - "requires": { - "@ampproject/remapping": "^2.2.0", - "@babel/code-frame": "^7.24.7", - "@babel/generator": "^7.25.0", - "@babel/helper-compilation-targets": "^7.25.2", - "@babel/helper-module-transforms": "^7.25.2", - "@babel/helpers": "^7.25.0", - "@babel/parser": "^7.25.0", - "@babel/template": "^7.25.0", - "@babel/traverse": "^7.25.2", - "@babel/types": "^7.25.2", - "convert-source-map": "^2.0.0", - "debug": "^4.1.0", - "gensync": "^1.0.0-beta.2", - "json5": "^2.2.3", - "semver": "^6.3.1" - } - }, - "@babel/generator": { - "version": "7.25.0", - "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.25.0.tgz", - "integrity": "sha512-3LEEcj3PVW8pW2R1SR1M89g/qrYk/m/mB/tLqn7dn4sbBUQyTqnlod+II2U4dqiGtUmkcnAmkMDralTFZttRiw==", - "dev": true, - "requires": { - "@babel/types": "^7.25.0", - "@jridgewell/gen-mapping": "^0.3.5", - "@jridgewell/trace-mapping": "^0.3.25", - "jsesc": "^2.5.1" - } - }, - "@babel/helper-compilation-targets": { - "version": "7.25.2", - "resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.25.2.tgz", - "integrity": "sha512-U2U5LsSaZ7TAt3cfaymQ8WHh0pxvdHoEk6HVpaexxixjyEquMh0L0YNJNM6CTGKMXV1iksi0iZkGw4AcFkPaaw==", - "dev": true, - "requires": { - "@babel/compat-data": "^7.25.2", - "@babel/helper-validator-option": "^7.24.8", - "browserslist": "^4.23.1", - "lru-cache": "^5.1.1", - "semver": "^6.3.1" - }, - "dependencies": { - "lru-cache": { - "version": "5.1.1", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-5.1.1.tgz", - "integrity": "sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==", - "dev": true, - "requires": { - "yallist": "^3.0.2" - } - }, - "yallist": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-3.1.1.tgz", - "integrity": "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==", - "dev": true - } - } - }, - "@babel/helper-module-imports": { - "version": "7.24.7", - "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.24.7.tgz", - "integrity": "sha512-8AyH3C+74cgCVVXow/myrynrAGv+nTVg5vKu2nZph9x7RcRwzmh0VFallJuFTZ9mx6u4eSdXZfcOzSqTUm0HCA==", - "dev": true, - "requires": { - "@babel/traverse": "^7.24.7", - "@babel/types": "^7.24.7" - } - }, - "@babel/helper-module-transforms": { - "version": "7.25.2", - "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.25.2.tgz", - "integrity": "sha512-BjyRAbix6j/wv83ftcVJmBt72QtHI56C7JXZoG2xATiLpmoC7dpd8WnkikExHDVPpi/3qCmO6WY1EaXOluiecQ==", - "dev": true, - "requires": { - "@babel/helper-module-imports": "^7.24.7", - "@babel/helper-simple-access": "^7.24.7", - "@babel/helper-validator-identifier": "^7.24.7", - "@babel/traverse": "^7.25.2" - } - }, - "@babel/helper-plugin-utils": { - "version": "7.24.8", - "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.24.8.tgz", - "integrity": "sha512-FFWx5142D8h2Mgr/iPVGH5G7w6jDn4jUSpZTyDnQO0Yn7Ks2Kuz6Pci8H6MPCoUJegd/UZQ3tAvfLCxQSnWWwg==", - "dev": true - }, - "@babel/helper-simple-access": { - "version": "7.24.7", - "resolved": "https://registry.npmjs.org/@babel/helper-simple-access/-/helper-simple-access-7.24.7.tgz", - "integrity": "sha512-zBAIvbCMh5Ts+b86r/CjU+4XGYIs+R1j951gxI3KmmxBMhCg4oQMsv6ZXQ64XOm/cvzfU1FmoCyt6+owc5QMYg==", - "dev": true, - "requires": { - "@babel/traverse": "^7.24.7", - "@babel/types": "^7.24.7" - } - }, - "@babel/helper-string-parser": { - "version": "7.24.8", - "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.24.8.tgz", - "integrity": "sha512-pO9KhhRcuUyGnJWwyEgnRJTSIZHiT+vMD0kPeD+so0l7mxkMT19g3pjY9GTnHySck/hDzq+dtW/4VgnMkippsQ==", - "dev": true - }, - "@babel/helper-validator-identifier": { - "version": "7.24.7", - "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.24.7.tgz", - "integrity": "sha512-rR+PBcQ1SMQDDyF6X0wxtG8QyLCgUB0eRAGguqRLfkCA87l7yAP7ehq8SNj96OOGTO8OBV70KhuFYcIkHXOg0w==", - "dev": true - }, - "@babel/helper-validator-option": { - "version": "7.24.8", - "resolved": "https://registry.npmjs.org/@babel/helper-validator-option/-/helper-validator-option-7.24.8.tgz", - "integrity": "sha512-xb8t9tD1MHLungh/AIoWYN+gVHaB9kwlu8gffXGSt3FFEIT7RjS+xWbc2vUD1UTZdIpKj/ab3rdqJ7ufngyi2Q==", - "dev": true - }, - "@babel/helpers": { - "version": "7.25.0", - "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.25.0.tgz", - "integrity": "sha512-MjgLZ42aCm0oGjJj8CtSM3DB8NOOf8h2l7DCTePJs29u+v7yO/RBX9nShlKMgFnRks/Q4tBAe7Hxnov9VkGwLw==", - "dev": true, - "requires": { - "@babel/template": "^7.25.0", - "@babel/types": "^7.25.0" - } - }, - "@babel/highlight": { - "version": "7.24.7", - "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.24.7.tgz", - "integrity": "sha512-EStJpq4OuY8xYfhGVXngigBJRWxftKX9ksiGDnmlY3o7B/V7KIAc9X4oiK87uPJSc/vs5L869bem5fhZa8caZw==", - "dev": true, - "requires": { - "@babel/helper-validator-identifier": "^7.24.7", - "chalk": "^2.4.2", - "js-tokens": "^4.0.0", - "picocolors": "^1.0.0" - }, - "dependencies": { - "ansi-styles": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", - "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", - "dev": true, - "requires": { - "color-convert": "^1.9.0" - } - }, - "chalk": { - "version": "2.4.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", - "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", - "dev": true, - "requires": { - "ansi-styles": "^3.2.1", - "escape-string-regexp": "^1.0.5", - "supports-color": "^5.3.0" - } - }, - "color-convert": { - "version": "1.9.3", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", - "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", - "dev": true, - "requires": { - "color-name": "1.1.3" - } - }, - "color-name": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", - "integrity": "sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==", - "dev": true - }, - "escape-string-regexp": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", - "integrity": "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==", - "dev": true - }, - "has-flag": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", - "integrity": "sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==", - "dev": true - }, - "supports-color": { - "version": "5.5.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", - "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", - "dev": true, - "requires": { - "has-flag": "^3.0.0" - } - } - } - }, - "@babel/parser": { - "version": "7.25.3", - "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.25.3.tgz", - "integrity": "sha512-iLTJKDbJ4hMvFPgQwwsVoxtHyWpKKPBrxkANrSYewDPaPpT5py5yeVkgPIJ7XYXhndxJpaA3PyALSXQ7u8e/Dw==", - "dev": true, - "requires": { - "@babel/types": "^7.25.2" - } - }, - "@babel/plugin-syntax-async-generators": { - "version": "7.8.4", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-async-generators/-/plugin-syntax-async-generators-7.8.4.tgz", - "integrity": "sha512-tycmZxkGfZaxhMRbXlPXuVFpdWlXpir2W4AMhSJgRKzk/eDlIXOhb2LHWoLpDF7TEHylV5zNhykX6KAgHJmTNw==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.8.0" - } - }, - "@babel/plugin-syntax-bigint": { - "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-bigint/-/plugin-syntax-bigint-7.8.3.tgz", - "integrity": "sha512-wnTnFlG+YxQm3vDxpGE57Pj0srRU4sHE/mDkt1qv2YJJSeUAec2ma4WLUnUPeKjyrfntVwe/N6dCXpU+zL3Npg==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.8.0" - } - }, - "@babel/plugin-syntax-class-properties": { - "version": "7.12.13", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-class-properties/-/plugin-syntax-class-properties-7.12.13.tgz", - "integrity": "sha512-fm4idjKla0YahUNgFNLCB0qySdsoPiZP3iQE3rky0mBUtMZ23yDJ9SJdg6dXTSDnulOVqiF3Hgr9nbXvXTQZYA==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.12.13" - } - }, - "@babel/plugin-syntax-class-static-block": { - "version": "7.14.5", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-class-static-block/-/plugin-syntax-class-static-block-7.14.5.tgz", - "integrity": "sha512-b+YyPmr6ldyNnM6sqYeMWE+bgJcJpO6yS4QD7ymxgH34GBPNDM/THBh8iunyvKIZztiwLH4CJZ0RxTk9emgpjw==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.14.5" - } - }, - "@babel/plugin-syntax-import-attributes": { - "version": "7.24.7", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-import-attributes/-/plugin-syntax-import-attributes-7.24.7.tgz", - "integrity": "sha512-hbX+lKKeUMGihnK8nvKqmXBInriT3GVjzXKFriV3YC6APGxMbP8RZNFwy91+hocLXq90Mta+HshoB31802bb8A==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.24.7" - } - }, - "@babel/plugin-syntax-import-meta": { - "version": "7.10.4", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-import-meta/-/plugin-syntax-import-meta-7.10.4.tgz", - "integrity": "sha512-Yqfm+XDx0+Prh3VSeEQCPU81yC+JWZ2pDPFSS4ZdpfZhp4MkFMaDC1UqseovEKwSUpnIL7+vK+Clp7bfh0iD7g==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.10.4" - } - }, - "@babel/plugin-syntax-json-strings": { - "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-json-strings/-/plugin-syntax-json-strings-7.8.3.tgz", - "integrity": "sha512-lY6kdGpWHvjoe2vk4WrAapEuBR69EMxZl+RoGRhrFGNYVK8mOPAW8VfbT/ZgrFbXlDNiiaxQnAtgVCZ6jv30EA==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.8.0" - } - }, - "@babel/plugin-syntax-jsx": { - "version": "7.24.7", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-jsx/-/plugin-syntax-jsx-7.24.7.tgz", - "integrity": "sha512-6ddciUPe/mpMnOKv/U+RSd2vvVy+Yw/JfBB0ZHYjEZt9NLHmCUylNYlsbqCCS1Bffjlb0fCwC9Vqz+sBz6PsiQ==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.24.7" - } - }, - "@babel/plugin-syntax-logical-assignment-operators": { - "version": "7.10.4", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-logical-assignment-operators/-/plugin-syntax-logical-assignment-operators-7.10.4.tgz", - "integrity": "sha512-d8waShlpFDinQ5MtvGU9xDAOzKH47+FFoney2baFIoMr952hKOLp1HR7VszoZvOsV/4+RRszNY7D17ba0te0ig==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.10.4" - } - }, - "@babel/plugin-syntax-nullish-coalescing-operator": { - "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-nullish-coalescing-operator/-/plugin-syntax-nullish-coalescing-operator-7.8.3.tgz", - "integrity": "sha512-aSff4zPII1u2QD7y+F8oDsz19ew4IGEJg9SVW+bqwpwtfFleiQDMdzA/R+UlWDzfnHFCxxleFT0PMIrR36XLNQ==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.8.0" - } - }, - "@babel/plugin-syntax-numeric-separator": { - "version": "7.10.4", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-numeric-separator/-/plugin-syntax-numeric-separator-7.10.4.tgz", - "integrity": "sha512-9H6YdfkcK/uOnY/K7/aA2xpzaAgkQn37yzWUMRK7OaPOqOpGS1+n0H5hxT9AUw9EsSjPW8SVyMJwYRtWs3X3ug==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.10.4" - } - }, - "@babel/plugin-syntax-object-rest-spread": { - "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-object-rest-spread/-/plugin-syntax-object-rest-spread-7.8.3.tgz", - "integrity": "sha512-XoqMijGZb9y3y2XskN+P1wUGiVwWZ5JmoDRwx5+3GmEplNyVM2s2Dg8ILFQm8rWM48orGy5YpI5Bl8U1y7ydlA==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.8.0" - } - }, - "@babel/plugin-syntax-optional-catch-binding": { - "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-optional-catch-binding/-/plugin-syntax-optional-catch-binding-7.8.3.tgz", - "integrity": "sha512-6VPD0Pc1lpTqw0aKoeRTMiB+kWhAoT24PA+ksWSBrFtl5SIRVpZlwN3NNPQjehA2E/91FV3RjLWoVTglWcSV3Q==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.8.0" - } - }, - "@babel/plugin-syntax-optional-chaining": { - "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-optional-chaining/-/plugin-syntax-optional-chaining-7.8.3.tgz", - "integrity": "sha512-KoK9ErH1MBlCPxV0VANkXW2/dw4vlbGDrFgz8bmUsBGYkFRcbRwMh6cIJubdPrkxRwuGdtCk0v/wPTKbQgBjkg==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.8.0" - } - }, - "@babel/plugin-syntax-private-property-in-object": { - "version": "7.14.5", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-private-property-in-object/-/plugin-syntax-private-property-in-object-7.14.5.tgz", - "integrity": "sha512-0wVnp9dxJ72ZUJDV27ZfbSj6iHLoytYZmh3rFcxNnvsJF3ktkzLDZPy/mA17HGsaQT3/DQsWYX1f1QGWkCoVUg==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.14.5" - } - }, - "@babel/plugin-syntax-top-level-await": { - "version": "7.14.5", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-top-level-await/-/plugin-syntax-top-level-await-7.14.5.tgz", - "integrity": "sha512-hx++upLv5U1rgYfwe1xBQUhRmU41NEvpUvrp8jkrSCdvGSnM5/qdRMtylJ6PG5OFkBaHkbTAKTnd3/YyESRHFw==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.14.5" - } - }, - "@babel/plugin-syntax-typescript": { - "version": "7.24.7", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-typescript/-/plugin-syntax-typescript-7.24.7.tgz", - "integrity": "sha512-c/+fVeJBB0FeKsFvwytYiUD+LBvhHjGSI0g446PRGdSVGZLRNArBUno2PETbAly3tpiNAQR5XaZ+JslxkotsbA==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.24.7" - } - }, - "@babel/template": { - "version": "7.25.0", - "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.25.0.tgz", - "integrity": "sha512-aOOgh1/5XzKvg1jvVz7AVrx2piJ2XBi227DHmbY6y+bM9H2FlN+IfecYu4Xl0cNiiVejlsCri89LUsbj8vJD9Q==", - "dev": true, - "requires": { - "@babel/code-frame": "^7.24.7", - "@babel/parser": "^7.25.0", - "@babel/types": "^7.25.0" - } - }, - "@babel/traverse": { - "version": "7.25.3", - "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.25.3.tgz", - "integrity": "sha512-HefgyP1x754oGCsKmV5reSmtV7IXj/kpaE1XYY+D9G5PvKKoFfSbiS4M77MdjuwlZKDIKFCffq9rPU+H/s3ZdQ==", - "dev": true, - "requires": { - "@babel/code-frame": "^7.24.7", - "@babel/generator": "^7.25.0", - "@babel/parser": "^7.25.3", - "@babel/template": "^7.25.0", - "@babel/types": "^7.25.2", - "debug": "^4.3.1", - "globals": "^11.1.0" - } - }, - "@babel/types": { - "version": "7.25.2", - "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.25.2.tgz", - "integrity": "sha512-YTnYtra7W9e6/oAZEHj0bJehPRUlLH9/fbpT5LfB0NhQXyALCRkRs3zH9v07IYhkgpqX6Z78FnuccZr/l4Fs4Q==", - "dev": true, - "requires": { - "@babel/helper-string-parser": "^7.24.8", - "@babel/helper-validator-identifier": "^7.24.7", - "to-fast-properties": "^2.0.0" - } - }, - "@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 - }, - "@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, - "requires": { - "eslint-visitor-keys": "^3.3.0" - } - }, - "@eslint-community/regexpp": { - "version": "4.10.0", - "resolved": "https://registry.npmjs.org/@eslint-community/regexpp/-/regexpp-4.10.0.tgz", - "integrity": "sha512-Cu96Sd2By9mCNTx2iyKOmq10v22jUVQv0lQnlGNy16oE9589yE+QADPbrMGCkA51cKZSg3Pu/aTJVTGfL/qjUA==", - "dev": true - }, - "@eslint/eslintrc": { - "version": "2.1.3", - "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-2.1.3.tgz", - "integrity": "sha512-yZzuIG+jnVu6hNSzFEN07e8BxF3uAzYtQb6uDkaYZLo6oYZDCq454c5kB8zxnzfCYyP4MIuyBn10L0DqwujTmA==", - "dev": true, - "requires": { - "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" - }, - "dependencies": { - "argparse": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", - "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==", - "dev": true - }, - "debug": { - "version": "4.3.4", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", - "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", - "dev": true, - "requires": { - "ms": "2.1.2" - } - }, - "globals": { - "version": "13.23.0", - "resolved": "https://registry.npmjs.org/globals/-/globals-13.23.0.tgz", - "integrity": "sha512-XAmF0RjlrjY23MA51q3HltdlGxUpXPvg0GioKiD9X6HD28iMjo2dKC8Vqwm7lne4GNr78+RHTfliktR6ZH09wA==", - "dev": true, - "requires": { - "type-fest": "^0.20.2" - } - }, - "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, - "requires": { - "argparse": "^2.0.1" - } - }, - "type-fest": { - "version": "0.20.2", - "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.20.2.tgz", - "integrity": "sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ==", - "dev": true - } - } - }, - "@eslint/js": { - "version": "8.53.0", - "resolved": "https://registry.npmjs.org/@eslint/js/-/js-8.53.0.tgz", - "integrity": "sha512-Kn7K8dx/5U6+cT1yEhpX1w4PCSg0M+XyRILPgvwcEBjerFWCwQj5sbr3/VmxqV0JGHCBCzyd6LxypEuehypY1w==", - "dev": true - }, - "@humanwhocodes/config-array": { - "version": "0.11.13", - "resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.11.13.tgz", - "integrity": "sha512-JSBDMiDKSzQVngfRjOdFXgFfklaXI4K9nLF49Auh21lmBWRLIK3+xTErTWD4KU54pb6coM6ESE7Awz/FNU3zgQ==", - "dev": true, - "requires": { - "@humanwhocodes/object-schema": "^2.0.1", - "debug": "^4.1.1", - "minimatch": "^3.0.5" - } - }, - "@humanwhocodes/module-importer": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/@humanwhocodes/module-importer/-/module-importer-1.0.1.tgz", - "integrity": "sha512-bxveV4V8v5Yb4ncFTT3rPSgZBOpCkjfK0y4oVVVJwIuDVBRMDXrPyXRL988i5ap9m9bnyEEjWfm5WkBmtffLfA==", - "dev": true - }, - "@humanwhocodes/object-schema": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/@humanwhocodes/object-schema/-/object-schema-2.0.1.tgz", - "integrity": "sha512-dvuCeX5fC9dXgJn9t+X5atfmgQAzUOWqS1254Gh0m6i8wKd10ebXkfNKiRK+1GWi/yTvvLDHpoxLr0xxxeslWw==", - "dev": true - }, - "@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, - "requires": { - "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" - } - }, - "@istanbuljs/schema": { - "version": "0.1.3", - "resolved": "https://registry.npmjs.org/@istanbuljs/schema/-/schema-0.1.3.tgz", - "integrity": "sha512-ZXRY4jNvVgSVQ8DL3LTcakaAtXwTVUxE81hslsyD2AtoXW/wVob10HkOJ1X/pAlcI7D+2YoZKg5do8G/w6RYgA==", - "dev": true - }, - "@jest/console": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/@jest/console/-/console-29.7.0.tgz", - "integrity": "sha512-5Ni4CU7XHQi32IJ398EEP4RrB8eV09sXP2ROqD4bksHrnTree52PsxvX8tpL8LvTZ3pFzXyPbNQReSN41CAhOg==", - "dev": true, - "requires": { - "@jest/types": "^29.6.3", - "@types/node": "*", - "chalk": "^4.0.0", - "jest-message-util": "^29.7.0", - "jest-util": "^29.7.0", - "slash": "^3.0.0" - } - }, - "@jest/core": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/@jest/core/-/core-29.7.0.tgz", - "integrity": "sha512-n7aeXWKMnGtDA48y8TLWJPJmLmmZ642Ceo78cYWEpiD7FzDgmNDV/GCVRorPABdXLJZ/9wzzgZAlHjXjxDHGsg==", - "dev": true, - "requires": { - "@jest/console": "^29.7.0", - "@jest/reporters": "^29.7.0", - "@jest/test-result": "^29.7.0", - "@jest/transform": "^29.7.0", - "@jest/types": "^29.6.3", - "@types/node": "*", - "ansi-escapes": "^4.2.1", - "chalk": "^4.0.0", - "ci-info": "^3.2.0", - "exit": "^0.1.2", - "graceful-fs": "^4.2.9", - "jest-changed-files": "^29.7.0", - "jest-config": "^29.7.0", - "jest-haste-map": "^29.7.0", - "jest-message-util": "^29.7.0", - "jest-regex-util": "^29.6.3", - "jest-resolve": "^29.7.0", - "jest-resolve-dependencies": "^29.7.0", - "jest-runner": "^29.7.0", - "jest-runtime": "^29.7.0", - "jest-snapshot": "^29.7.0", - "jest-util": "^29.7.0", - "jest-validate": "^29.7.0", - "jest-watcher": "^29.7.0", - "micromatch": "^4.0.4", - "pretty-format": "^29.7.0", - "slash": "^3.0.0", - "strip-ansi": "^6.0.0" - } - }, - "@jest/environment": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/@jest/environment/-/environment-29.7.0.tgz", - "integrity": "sha512-aQIfHDq33ExsN4jP1NWGXhxgQ/wixs60gDiKO+XVMd8Mn0NWPWgc34ZQDTb2jKaUWQ7MuwoitXAsN2XVXNMpAw==", - "dev": true, - "requires": { - "@jest/fake-timers": "^29.7.0", - "@jest/types": "^29.6.3", - "@types/node": "*", - "jest-mock": "^29.7.0" - } - }, - "@jest/expect": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/@jest/expect/-/expect-29.7.0.tgz", - "integrity": "sha512-8uMeAMycttpva3P1lBHB8VciS9V0XAr3GymPpipdyQXbBcuhkLQOSe8E/p92RyAdToS6ZD1tFkX+CkhoECE0dQ==", - "dev": true, - "requires": { - "expect": "^29.7.0", - "jest-snapshot": "^29.7.0" - } - }, - "@jest/expect-utils": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/@jest/expect-utils/-/expect-utils-29.7.0.tgz", - "integrity": "sha512-GlsNBWiFQFCVi9QVSx7f5AgMeLxe9YCCs5PuP2O2LdjDAA8Jh9eX7lA1Jq/xdXw3Wb3hyvlFNfZIfcRetSzYcA==", - "dev": true, - "requires": { - "jest-get-type": "^29.6.3" - } - }, - "@jest/fake-timers": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/@jest/fake-timers/-/fake-timers-29.7.0.tgz", - "integrity": "sha512-q4DH1Ha4TTFPdxLsqDXK1d3+ioSL7yL5oCMJZgDYm6i+6CygW5E5xVr/D1HdsGxjt1ZWSfUAs9OxSB/BNelWrQ==", - "dev": true, - "requires": { - "@jest/types": "^29.6.3", - "@sinonjs/fake-timers": "^10.0.2", - "@types/node": "*", - "jest-message-util": "^29.7.0", - "jest-mock": "^29.7.0", - "jest-util": "^29.7.0" - } - }, - "@jest/globals": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/@jest/globals/-/globals-29.7.0.tgz", - "integrity": "sha512-mpiz3dutLbkW2MNFubUGUEVLkTGiqW6yLVTA+JbP6fI6J5iL9Y0Nlg8k95pcF8ctKwCS7WVxteBs29hhfAotzQ==", - "dev": true, - "requires": { - "@jest/environment": "^29.7.0", - "@jest/expect": "^29.7.0", - "@jest/types": "^29.6.3", - "jest-mock": "^29.7.0" - } - }, - "@jest/reporters": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/@jest/reporters/-/reporters-29.7.0.tgz", - "integrity": "sha512-DApq0KJbJOEzAFYjHADNNxAE3KbhxQB1y5Kplb5Waqw6zVbuWatSnMjE5gs8FUgEPmNsnZA3NCWl9NG0ia04Pg==", - "dev": true, - "requires": { - "@bcoe/v8-coverage": "^0.2.3", - "@jest/console": "^29.7.0", - "@jest/test-result": "^29.7.0", - "@jest/transform": "^29.7.0", - "@jest/types": "^29.6.3", - "@jridgewell/trace-mapping": "^0.3.18", - "@types/node": "*", - "chalk": "^4.0.0", - "collect-v8-coverage": "^1.0.0", - "exit": "^0.1.2", - "glob": "^7.1.3", - "graceful-fs": "^4.2.9", - "istanbul-lib-coverage": "^3.0.0", - "istanbul-lib-instrument": "^6.0.0", - "istanbul-lib-report": "^3.0.0", - "istanbul-lib-source-maps": "^4.0.0", - "istanbul-reports": "^3.1.3", - "jest-message-util": "^29.7.0", - "jest-util": "^29.7.0", - "jest-worker": "^29.7.0", - "slash": "^3.0.0", - "string-length": "^4.0.1", - "strip-ansi": "^6.0.0", - "v8-to-istanbul": "^9.0.1" - } - }, - "@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, - "requires": { - "@sinclair/typebox": "^0.27.8" - } - }, - "@jest/source-map": { - "version": "29.6.3", - "resolved": "https://registry.npmjs.org/@jest/source-map/-/source-map-29.6.3.tgz", - "integrity": "sha512-MHjT95QuipcPrpLM+8JMSzFx6eHp5Bm+4XeFDJlwsvVBjmKNiIAvasGK2fxz2WbGRlnvqehFbh07MMa7n3YJnw==", - "dev": true, - "requires": { - "@jridgewell/trace-mapping": "^0.3.18", - "callsites": "^3.0.0", - "graceful-fs": "^4.2.9" - } - }, - "@jest/test-result": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/@jest/test-result/-/test-result-29.7.0.tgz", - "integrity": "sha512-Fdx+tv6x1zlkJPcWXmMDAG2HBnaR9XPSd5aDWQVsfrZmLVT3lU1cwyxLgRmXR9yrq4NBoEm9BMsfgFzTQAbJYA==", - "dev": true, - "requires": { - "@jest/console": "^29.7.0", - "@jest/types": "^29.6.3", - "@types/istanbul-lib-coverage": "^2.0.0", - "collect-v8-coverage": "^1.0.0" - } - }, - "@jest/test-sequencer": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/@jest/test-sequencer/-/test-sequencer-29.7.0.tgz", - "integrity": "sha512-GQwJ5WZVrKnOJuiYiAF52UNUJXgTZx1NHjFSEB0qEMmSZKAkdMoIzw/Cj6x6NF4AvV23AUqDpFzQkN/eYCYTxw==", - "dev": true, - "requires": { - "@jest/test-result": "^29.7.0", - "graceful-fs": "^4.2.9", - "jest-haste-map": "^29.7.0", - "slash": "^3.0.0" - } - }, - "@jest/transform": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/@jest/transform/-/transform-29.7.0.tgz", - "integrity": "sha512-ok/BTPFzFKVMwO5eOHRrvnBVHdRy9IrsrW1GpMaQ9MCnilNLXQKmAX8s1YXDFaai9xJpac2ySzV0YeRRECr2Vw==", - "dev": true, - "requires": { - "@babel/core": "^7.11.6", - "@jest/types": "^29.6.3", - "@jridgewell/trace-mapping": "^0.3.18", - "babel-plugin-istanbul": "^6.1.1", - "chalk": "^4.0.0", - "convert-source-map": "^2.0.0", - "fast-json-stable-stringify": "^2.1.0", - "graceful-fs": "^4.2.9", - "jest-haste-map": "^29.7.0", - "jest-regex-util": "^29.6.3", - "jest-util": "^29.7.0", - "micromatch": "^4.0.4", - "pirates": "^4.0.4", - "slash": "^3.0.0", - "write-file-atomic": "^4.0.2" - } - }, - "@jest/types": { - "version": "29.6.3", - "resolved": "https://registry.npmjs.org/@jest/types/-/types-29.6.3.tgz", - "integrity": "sha512-u3UPsIilWKOM3F9CXtrG8LEJmNxwoCQC/XVj4IKYXvvpx7QIi/Kg1LI5uDmDpKlac62NUtX7eLjRh+jVZcLOzw==", - "dev": true, - "requires": { - "@jest/schemas": "^29.6.3", - "@types/istanbul-lib-coverage": "^2.0.0", - "@types/istanbul-reports": "^3.0.0", - "@types/node": "*", - "@types/yargs": "^17.0.8", - "chalk": "^4.0.0" - } - }, - "@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, - "requires": { - "@jridgewell/set-array": "^1.2.1", - "@jridgewell/sourcemap-codec": "^1.4.10", - "@jridgewell/trace-mapping": "^0.3.24" - } - }, - "@jridgewell/resolve-uri": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.2.tgz", - "integrity": "sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw==", - "dev": true - }, - "@jridgewell/set-array": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/@jridgewell/set-array/-/set-array-1.2.1.tgz", - "integrity": "sha512-R8gLRTZeyp03ymzP/6Lil/28tGeGEzhx1q2k703KGWRAI1VdvPIXdG70VJc2pAMw3NA6JKL5hhFu1sJX0Mnn/A==", - "dev": true - }, - "@jridgewell/sourcemap-codec": { - "version": "1.5.0", - "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.5.0.tgz", - "integrity": "sha512-gv3ZRaISU3fjPAgNsriBRqGWQL6quFx04YMPW/zD8XMLsU32mhCCbfbO6KZFLjvYpCZ8zyDEgqsgf+PwPaM7GQ==", - "dev": true - }, - "@jridgewell/trace-mapping": { - "version": "0.3.25", - "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.25.tgz", - "integrity": "sha512-vNk6aEwybGtawWmy/PzwnGDOjCkLWSD2wqvjGGAgOAwCGWySYXfYoxt00IJkTF+8Lb57DwOb3Aa0o9CApepiYQ==", - "dev": true, - "requires": { - "@jridgewell/resolve-uri": "^3.1.0", - "@jridgewell/sourcemap-codec": "^1.4.14" - } - }, - "@nodelib/fs.scandir": { - "version": "2.1.5", - "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz", - "integrity": "sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==", - "dev": true, - "requires": { - "@nodelib/fs.stat": "2.0.5", - "run-parallel": "^1.1.9" - } - }, - "@nodelib/fs.stat": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/@nodelib/fs.stat/-/fs.stat-2.0.5.tgz", - "integrity": "sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==", - "dev": true - }, - "@nodelib/fs.walk": { - "version": "1.2.8", - "resolved": "https://registry.npmjs.org/@nodelib/fs.walk/-/fs.walk-1.2.8.tgz", - "integrity": "sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==", - "dev": true, - "requires": { - "@nodelib/fs.scandir": "2.1.5", - "fastq": "^1.6.0" - } - }, - "@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 - }, - "@sinonjs/commons": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/@sinonjs/commons/-/commons-3.0.1.tgz", - "integrity": "sha512-K3mCHKQ9sVh8o1C9cxkwxaOmXoAMlDxC1mYyHrjqOWEcBjYr76t96zL2zlj5dUGZ3HSw240X1qgH3Mjf1yJWpQ==", - "dev": true, - "requires": { - "type-detect": "4.0.8" - } - }, - "@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, - "requires": { - "@sinonjs/commons": "^3.0.0" - } - }, - "@types/babel__core": { - "version": "7.20.5", - "resolved": "https://registry.npmjs.org/@types/babel__core/-/babel__core-7.20.5.tgz", - "integrity": "sha512-qoQprZvz5wQFJwMDqeseRXWv3rqMvhgpbXFfVyWhbx9X47POIA6i/+dXefEmZKoAgOaTdaIgNSMqMIU61yRyzA==", - "dev": true, - "requires": { - "@babel/parser": "^7.20.7", - "@babel/types": "^7.20.7", - "@types/babel__generator": "*", - "@types/babel__template": "*", - "@types/babel__traverse": "*" - } - }, - "@types/babel__generator": { - "version": "7.6.8", - "resolved": "https://registry.npmjs.org/@types/babel__generator/-/babel__generator-7.6.8.tgz", - "integrity": "sha512-ASsj+tpEDsEiFr1arWrlN6V3mdfjRMZt6LtK/Vp/kreFLnr5QH5+DhvD5nINYZXzwJvXeGq+05iUXcAzVrqWtw==", - "dev": true, - "requires": { - "@babel/types": "^7.0.0" - } - }, - "@types/babel__template": { - "version": "7.4.4", - "resolved": "https://registry.npmjs.org/@types/babel__template/-/babel__template-7.4.4.tgz", - "integrity": "sha512-h/NUaSyG5EyxBIp8YRxo4RMe2/qQgvyowRwVMzhYhBCONbW8PUsg4lkFMrhgZhUe5z3L3MiLDuvyJ/CaPa2A8A==", - "dev": true, - "requires": { - "@babel/parser": "^7.1.0", - "@babel/types": "^7.0.0" - } - }, - "@types/babel__traverse": { - "version": "7.20.6", - "resolved": "https://registry.npmjs.org/@types/babel__traverse/-/babel__traverse-7.20.6.tgz", - "integrity": "sha512-r1bzfrm0tomOI8g1SzvCaQHo6Lcv6zu0EA+W2kHrt8dyrHQxGzBBL4kdkzIS+jBMV+EYcMAEAqXqYaLJq5rOZg==", - "dev": true, - "requires": { - "@babel/types": "^7.20.7" - } - }, - "@types/graceful-fs": { - "version": "4.1.9", - "resolved": "https://registry.npmjs.org/@types/graceful-fs/-/graceful-fs-4.1.9.tgz", - "integrity": "sha512-olP3sd1qOEe5dXTSaFvQG+02VdRXcdytWLAZsAq1PecU8uqQAhkrnbli7DagjtXKW/Bl7YJbUsa8MPcuc8LHEQ==", - "dev": true, - "requires": { - "@types/node": "*" - } - }, - "@types/istanbul-lib-coverage": { - "version": "2.0.6", - "resolved": "https://registry.npmjs.org/@types/istanbul-lib-coverage/-/istanbul-lib-coverage-2.0.6.tgz", - "integrity": "sha512-2QF/t/auWm0lsy8XtKVPG19v3sSOQlJe/YHZgfjb/KBBHOGSV+J2q/S671rcq9uTBrLAXmZpqJiaQbMT+zNU1w==", - "dev": true - }, - "@types/istanbul-lib-report": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/@types/istanbul-lib-report/-/istanbul-lib-report-3.0.3.tgz", - "integrity": "sha512-NQn7AHQnk/RSLOxrBbGyJM/aVQ+pjj5HCgasFxc0K/KhoATfQ/47AyUl15I2yBUpihjmas+a+VJBOqecrFH+uA==", - "dev": true, - "requires": { - "@types/istanbul-lib-coverage": "*" - } - }, - "@types/istanbul-reports": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/@types/istanbul-reports/-/istanbul-reports-3.0.4.tgz", - "integrity": "sha512-pk2B1NWalF9toCRu6gjBzR69syFjP4Od8WRAX+0mmf9lAjCRicLOWc+ZrxZHx/0XRjotgkF9t6iaMJ+aXcOdZQ==", - "dev": true, - "requires": { - "@types/istanbul-lib-report": "*" - } - }, - "@types/json5": { - "version": "0.0.29", - "resolved": "https://registry.npmjs.org/@types/json5/-/json5-0.0.29.tgz", - "integrity": "sha512-dRLjCWHYg4oaA77cxO64oO+7JwCwnIzkZPdrrC71jQmQtlhM556pwKo5bUzqvZndkVbeFLIIi+9TC40JNF5hNQ==", - "dev": true - }, - "@types/node": { - "version": "22.3.0", - "resolved": "https://registry.npmjs.org/@types/node/-/node-22.3.0.tgz", - "integrity": "sha512-nrWpWVaDZuaVc5X84xJ0vNrLvomM205oQyLsRt7OHNZbSHslcWsvgFR7O7hire2ZonjLrWBbedmotmIlJDVd6g==", - "dev": true, - "requires": { - "undici-types": "~6.18.2" - } - }, - "@types/stack-utils": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/@types/stack-utils/-/stack-utils-2.0.3.tgz", - "integrity": "sha512-9aEbYZ3TbYMznPdcdr3SmIrLXwC/AKZXQeCf9Pgao5CKb8CyHuEX5jzWPTkvregvhRJHcpRO6BFoGW9ycaOkYw==", - "dev": true - }, - "@types/yargs": { - "version": "17.0.33", - "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-17.0.33.tgz", - "integrity": "sha512-WpxBCKWPLr4xSsHgz511rFJAM+wS28w2zEO1QDNY5zM/S8ok70NNfztH0xwhqKyaK0OHCbN98LDAZuy1ctxDkA==", - "dev": true, - "requires": { - "@types/yargs-parser": "*" - } - }, - "@types/yargs-parser": { - "version": "21.0.3", - "resolved": "https://registry.npmjs.org/@types/yargs-parser/-/yargs-parser-21.0.3.tgz", - "integrity": "sha512-I4q9QU9MQv4oEOz4tAHJtNz1cwuLxn2F3xcc2iV5WdqLPpUnj30aUuxt1mAxYTG+oe8CZMV/+6rU4S4gRDzqtQ==", - "dev": true - }, - "@ungap/structured-clone": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/@ungap/structured-clone/-/structured-clone-1.2.0.tgz", - "integrity": "sha512-zuVdFrMJiuCDQUMCzQaD6KL28MjnqqN8XnAqiEq9PNm/hCPTSGfrXCOfwj1ow4LFb/tNymJPwsNbVePc1xFqrQ==", - "dev": true - }, - "acorn": { - "version": "8.11.2", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.11.2.tgz", - "integrity": "sha512-nc0Axzp/0FILLEVsm4fNwLCwMttvhEI263QtVPQcbpfZZ3ts0hLsZGOpE6czNlid7CJ9MlyH8reXkpsf3YUY4w==", - "dev": true - }, - "acorn-jsx": { - "version": "5.3.2", - "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.3.2.tgz", - "integrity": "sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==", - "dev": true, - "requires": {} - }, - "ajv": { - "version": "6.12.6", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", - "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", - "dev": true, - "requires": { - "fast-deep-equal": "^3.1.1", - "fast-json-stable-stringify": "^2.0.0", - "json-schema-traverse": "^0.4.1", - "uri-js": "^4.2.2" - } - }, - "ansi-escapes": { - "version": "4.3.2", - "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-4.3.2.tgz", - "integrity": "sha512-gKXj5ALrKWQLsYG9jlTRmR/xKluxHV+Z9QEwNIgCfM1/uwPMCuzVVnh5mwTd+OuBZcwSIMbqssNWRm1lE51QaQ==", - "dev": true, - "requires": { - "type-fest": "^0.21.3" - } - }, - "ansi-regex": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", - "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", - "dev": true - }, - "ansi-styles": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", - "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", - "dev": true, - "requires": { - "color-convert": "^2.0.1" - } - }, - "anymatch": { - "version": "3.1.3", - "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.3.tgz", - "integrity": "sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw==", - "dev": true, - "requires": { - "normalize-path": "^3.0.0", - "picomatch": "^2.0.4" - } - }, - "argparse": { - "version": "1.0.10", - "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz", - "integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==", - "dev": true, - "requires": { - "sprintf-js": "~1.0.2" - } - }, - "array-buffer-byte-length": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/array-buffer-byte-length/-/array-buffer-byte-length-1.0.0.tgz", - "integrity": "sha512-LPuwb2P+NrQw3XhxGc36+XSvuBPopovXYTR9Ew++Du9Yb/bx5AzBfrIsBoj0EZUifjQU+sHL21sseZ3jerWO/A==", - "dev": true, - "requires": { - "call-bind": "^1.0.2", - "is-array-buffer": "^3.0.1" - } - }, - "array-includes": { - "version": "3.1.7", - "resolved": "https://registry.npmjs.org/array-includes/-/array-includes-3.1.7.tgz", - "integrity": "sha512-dlcsNBIiWhPkHdOEEKnehA+RNUWDc4UqFtnIXU4uuYDPtA4LDkr7qip2p0VvFAEXNDr0yWZ9PJyIRiGjRLQzwQ==", - "dev": true, - "requires": { - "call-bind": "^1.0.2", - "define-properties": "^1.2.0", - "es-abstract": "^1.22.1", - "get-intrinsic": "^1.2.1", - "is-string": "^1.0.7" - } - }, - "array.prototype.findlastindex": { - "version": "1.2.3", - "resolved": "https://registry.npmjs.org/array.prototype.findlastindex/-/array.prototype.findlastindex-1.2.3.tgz", - "integrity": "sha512-LzLoiOMAxvy+Gd3BAq3B7VeIgPdo+Q8hthvKtXybMvRV0jrXfJM/t8mw7nNlpEcVlVUnCnM2KSX4XU5HmpodOA==", - "dev": true, - "requires": { - "call-bind": "^1.0.2", - "define-properties": "^1.2.0", - "es-abstract": "^1.22.1", - "es-shim-unscopables": "^1.0.0", - "get-intrinsic": "^1.2.1" - } - }, - "array.prototype.flat": { - "version": "1.3.2", - "resolved": "https://registry.npmjs.org/array.prototype.flat/-/array.prototype.flat-1.3.2.tgz", - "integrity": "sha512-djYB+Zx2vLewY8RWlNCUdHjDXs2XOgm602S9E7P/UpHgfeHL00cRiIF+IN/G/aUJ7kGPb6yO/ErDI5V2s8iycA==", - "dev": true, - "requires": { - "call-bind": "^1.0.2", - "define-properties": "^1.2.0", - "es-abstract": "^1.22.1", - "es-shim-unscopables": "^1.0.0" - } - }, - "array.prototype.flatmap": { - "version": "1.3.2", - "resolved": "https://registry.npmjs.org/array.prototype.flatmap/-/array.prototype.flatmap-1.3.2.tgz", - "integrity": "sha512-Ewyx0c9PmpcsByhSW4r+9zDU7sGjFc86qf/kKtuSCRdhfbk0SNLLkaT5qvcHnRGgc5NP/ly/y+qkXkqONX54CQ==", - "dev": true, - "requires": { - "call-bind": "^1.0.2", - "define-properties": "^1.2.0", - "es-abstract": "^1.22.1", - "es-shim-unscopables": "^1.0.0" - } - }, - "array.prototype.tosorted": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/array.prototype.tosorted/-/array.prototype.tosorted-1.1.2.tgz", - "integrity": "sha512-HuQCHOlk1Weat5jzStICBCd83NxiIMwqDg/dHEsoefabn/hJRj5pVdWcPUSpRrwhwxZOsQassMpgN/xRYFBMIg==", - "dev": true, - "requires": { - "call-bind": "^1.0.2", - "define-properties": "^1.2.0", - "es-abstract": "^1.22.1", - "es-shim-unscopables": "^1.0.0", - "get-intrinsic": "^1.2.1" - } - }, - "arraybuffer.prototype.slice": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/arraybuffer.prototype.slice/-/arraybuffer.prototype.slice-1.0.2.tgz", - "integrity": "sha512-yMBKppFur/fbHu9/6USUe03bZ4knMYiwFBcyiaXB8Go0qNehwX6inYPzK9U0NeQvGxKthcmHcaR8P5MStSRBAw==", - "dev": true, - "requires": { - "array-buffer-byte-length": "^1.0.0", - "call-bind": "^1.0.2", - "define-properties": "^1.2.0", - "es-abstract": "^1.22.1", - "get-intrinsic": "^1.2.1", - "is-array-buffer": "^3.0.2", - "is-shared-array-buffer": "^1.0.2" - } - }, - "asynciterator.prototype": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/asynciterator.prototype/-/asynciterator.prototype-1.0.0.tgz", - "integrity": "sha512-wwHYEIS0Q80f5mosx3L/dfG5t5rjEa9Ft51GTaNt862EnpyGHpgz2RkZvLPp1oF5TnAiTohkEKVEu8pQPJI7Vg==", - "dev": true, - "requires": { - "has-symbols": "^1.0.3" - } - }, - "asynckit": { - "version": "0.4.0", - "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", - "integrity": "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==" - }, - "available-typed-arrays": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/available-typed-arrays/-/available-typed-arrays-1.0.5.tgz", - "integrity": "sha512-DMD0KiN46eipeziST1LPP/STfDU0sufISXmjSgvVsoU2tqxctQeASejWcfNtxYKqETM1UxQ8sp2OrSBWpHY6sw==", - "dev": true - }, - "axios": { - "version": "1.7.4", - "resolved": "https://registry.npmjs.org/axios/-/axios-1.7.4.tgz", - "integrity": "sha512-DukmaFRnY6AzAALSH4J2M3k6PkaC+MfaAGdEERRWcC9q3/TWQwLpHR8ZRLKTdQ3aBDL64EdluRDjJqKw+BPZEw==", - "requires": { - "follow-redirects": "^1.15.6", - "form-data": "^4.0.0", - "proxy-from-env": "^1.1.0" - } - }, - "babel-jest": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/babel-jest/-/babel-jest-29.7.0.tgz", - "integrity": "sha512-BrvGY3xZSwEcCzKvKsCi2GgHqDqsYkOP4/by5xCgIwGXQxIEh+8ew3gmrE1y7XRR6LHZIj6yLYnUi/mm2KXKBg==", - "dev": true, - "requires": { - "@jest/transform": "^29.7.0", - "@types/babel__core": "^7.1.14", - "babel-plugin-istanbul": "^6.1.1", - "babel-preset-jest": "^29.6.3", - "chalk": "^4.0.0", - "graceful-fs": "^4.2.9", - "slash": "^3.0.0" - } - }, - "babel-plugin-istanbul": { - "version": "6.1.1", - "resolved": "https://registry.npmjs.org/babel-plugin-istanbul/-/babel-plugin-istanbul-6.1.1.tgz", - "integrity": "sha512-Y1IQok9821cC9onCx5otgFfRm7Lm+I+wwxOx738M/WLPZ9Q42m4IG5W0FNX8WLL2gYMZo3JkuXIH2DOpWM+qwA==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.0.0", - "@istanbuljs/load-nyc-config": "^1.0.0", - "@istanbuljs/schema": "^0.1.2", - "istanbul-lib-instrument": "^5.0.4", - "test-exclude": "^6.0.0" - }, - "dependencies": { - "istanbul-lib-instrument": { - "version": "5.2.1", - "resolved": "https://registry.npmjs.org/istanbul-lib-instrument/-/istanbul-lib-instrument-5.2.1.tgz", - "integrity": "sha512-pzqtp31nLv/XFOzXGuvhCb8qhjmTVo5vjVk19XE4CRlSWz0KoeJ3bw9XsA7nOp9YBf4qHjwBxkDzKcME/J29Yg==", - "dev": true, - "requires": { - "@babel/core": "^7.12.3", - "@babel/parser": "^7.14.7", - "@istanbuljs/schema": "^0.1.2", - "istanbul-lib-coverage": "^3.2.0", - "semver": "^6.3.0" - } - } - } - }, - "babel-plugin-jest-hoist": { - "version": "29.6.3", - "resolved": "https://registry.npmjs.org/babel-plugin-jest-hoist/-/babel-plugin-jest-hoist-29.6.3.tgz", - "integrity": "sha512-ESAc/RJvGTFEzRwOTT4+lNDk/GNHMkKbNzsvT0qKRfDyyYTskxB5rnU2njIDYVxXCBHHEI1c0YwHob3WaYujOg==", - "dev": true, - "requires": { - "@babel/template": "^7.3.3", - "@babel/types": "^7.3.3", - "@types/babel__core": "^7.1.14", - "@types/babel__traverse": "^7.0.6" - } - }, - "babel-preset-current-node-syntax": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/babel-preset-current-node-syntax/-/babel-preset-current-node-syntax-1.1.0.tgz", - "integrity": "sha512-ldYss8SbBlWva1bs28q78Ju5Zq1F+8BrqBZZ0VFhLBvhh6lCpC2o3gDJi/5DRLs9FgYZCnmPYIVFU4lRXCkyUw==", - "dev": true, - "requires": { - "@babel/plugin-syntax-async-generators": "^7.8.4", - "@babel/plugin-syntax-bigint": "^7.8.3", - "@babel/plugin-syntax-class-properties": "^7.12.13", - "@babel/plugin-syntax-class-static-block": "^7.14.5", - "@babel/plugin-syntax-import-attributes": "^7.24.7", - "@babel/plugin-syntax-import-meta": "^7.10.4", - "@babel/plugin-syntax-json-strings": "^7.8.3", - "@babel/plugin-syntax-logical-assignment-operators": "^7.10.4", - "@babel/plugin-syntax-nullish-coalescing-operator": "^7.8.3", - "@babel/plugin-syntax-numeric-separator": "^7.10.4", - "@babel/plugin-syntax-object-rest-spread": "^7.8.3", - "@babel/plugin-syntax-optional-catch-binding": "^7.8.3", - "@babel/plugin-syntax-optional-chaining": "^7.8.3", - "@babel/plugin-syntax-private-property-in-object": "^7.14.5", - "@babel/plugin-syntax-top-level-await": "^7.14.5" - } - }, - "babel-preset-jest": { - "version": "29.6.3", - "resolved": "https://registry.npmjs.org/babel-preset-jest/-/babel-preset-jest-29.6.3.tgz", - "integrity": "sha512-0B3bhxR6snWXJZtR/RliHTDPRgn1sNHOR0yVtq/IiQFyuOVjFS+wuio/R4gSNkyYmKmJB4wGZv2NZanmKmTnNA==", - "dev": true, - "requires": { - "babel-plugin-jest-hoist": "^29.6.3", - "babel-preset-current-node-syntax": "^1.0.0" - } - }, - "balanced-match": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", - "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==", - "dev": true - }, - "brace-expansion": { - "version": "1.1.11", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", - "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", - "dev": true, - "requires": { - "balanced-match": "^1.0.0", - "concat-map": "0.0.1" - } - }, - "braces": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.3.tgz", - "integrity": "sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==", - "dev": true, - "requires": { - "fill-range": "^7.1.1" - } - }, - "browserslist": { - "version": "4.23.3", - "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.23.3.tgz", - "integrity": "sha512-btwCFJVjI4YWDNfau8RhZ+B1Q/VLoUITrm3RlP6y1tYGWIOa+InuYiRGXUBXo8nA1qKmHMyLB/iVQg5TT4eFoA==", - "dev": true, - "requires": { - "caniuse-lite": "^1.0.30001646", - "electron-to-chromium": "^1.5.4", - "node-releases": "^2.0.18", - "update-browserslist-db": "^1.1.0" - } - }, - "bser": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/bser/-/bser-2.1.1.tgz", - "integrity": "sha512-gQxTNE/GAfIIrmHLUE3oJyp5FO6HRBfhjnw4/wMmA63ZGDJnWBmgY/lyQBpnDUkGmAhbSe39tx2d/iTOAfglwQ==", - "dev": true, - "requires": { - "node-int64": "^0.4.0" - } - }, - "buffer-from": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.2.tgz", - "integrity": "sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==", - "dev": true - }, - "builtins": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/builtins/-/builtins-5.0.1.tgz", - "integrity": "sha512-qwVpFEHNfhYJIzNRBvd2C1kyo6jz3ZSMPyyuR47OPdiKWlbYnZNyDWuyR175qDnAJLiCo5fBBqPb3RiXgWlkOQ==", - "dev": true, - "requires": { - "semver": "^7.0.0" - }, - "dependencies": { - "semver": { - "version": "7.5.4", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.5.4.tgz", - "integrity": "sha512-1bCSESV6Pv+i21Hvpxp3Dx+pSD8lIPt8uVjRrxAUt/nbswYc+tK6Y2btiULjd4+fnq15PX+nqQDC7Oft7WkwcA==", - "dev": true, - "requires": { - "lru-cache": "^6.0.0" - } - } - } - }, - "call-bind": { - "version": "1.0.7", - "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.7.tgz", - "integrity": "sha512-GHTSNSYICQ7scH7sZ+M2rFopRoLh8t2bLSW6BbgrtLsahOIB5iyAVJf9GjWK3cYTDaMj4XdBpM1cA6pIS0Kv2w==", - "requires": { - "es-define-property": "^1.0.0", - "es-errors": "^1.3.0", - "function-bind": "^1.1.2", - "get-intrinsic": "^1.2.4", - "set-function-length": "^1.2.1" - } - }, - "callsites": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz", - "integrity": "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==", - "dev": true - }, - "camelcase": { - "version": "5.3.1", - "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-5.3.1.tgz", - "integrity": "sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==", - "dev": true - }, - "caniuse-lite": { - "version": "1.0.30001651", - "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001651.tgz", - "integrity": "sha512-9Cf+Xv1jJNe1xPZLGuUXLNkE1BoDkqRqYyFJ9TDYSqhduqA4hu4oR9HluGoWYQC/aj8WHjsGVV+bwkh0+tegRg==", - "dev": true - }, - "chalk": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", - "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", - "dev": true, - "requires": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" - } - }, - "char-regex": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/char-regex/-/char-regex-1.0.2.tgz", - "integrity": "sha512-kWWXztvZ5SBQV+eRgKFeh8q5sLuZY2+8WUIzlxWVTg+oGwY14qylx1KbKzHd8P6ZYkAg0xyIDU9JMHhyJMZ1jw==", - "dev": true - }, - "ci-info": { - "version": "3.9.0", - "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-3.9.0.tgz", - "integrity": "sha512-NIxF55hv4nSqQswkAeiOi1r83xy8JldOFDTWiug55KBu9Jnblncd2U6ViHmYgHf01TPZS77NJBhBMKdWj9HQMQ==", - "dev": true - }, - "cjs-module-lexer": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/cjs-module-lexer/-/cjs-module-lexer-1.3.1.tgz", - "integrity": "sha512-a3KdPAANPbNE4ZUv9h6LckSl9zLsYOP4MBmhIPkRaeyybt+r4UghLvq+xw/YwUcC1gqylCkL4rdVs3Lwupjm4Q==", - "dev": true - }, - "cliui": { - "version": "8.0.1", - "resolved": "https://registry.npmjs.org/cliui/-/cliui-8.0.1.tgz", - "integrity": "sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ==", - "dev": true, - "requires": { - "string-width": "^4.2.0", - "strip-ansi": "^6.0.1", - "wrap-ansi": "^7.0.0" - } - }, - "co": { - "version": "4.6.0", - "resolved": "https://registry.npmjs.org/co/-/co-4.6.0.tgz", - "integrity": "sha512-QVb0dM5HvG+uaxitm8wONl7jltx8dqhfU33DcqtOZcLSVIKSDDLDi7+0LbAKiyI8hD9u42m2YxXSkMGWThaecQ==", - "dev": true - }, - "collect-v8-coverage": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/collect-v8-coverage/-/collect-v8-coverage-1.0.2.tgz", - "integrity": "sha512-lHl4d5/ONEbLlJvaJNtsF/Lz+WvB07u2ycqTYbdrq7UypDXailES4valYb2eWiJFxZlVmpGekfqoxQhzyFdT4Q==", - "dev": true - }, - "color-convert": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", - "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", - "dev": true, - "requires": { - "color-name": "~1.1.4" - } - }, - "color-name": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", - "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", - "dev": true - }, - "combined-stream": { - "version": "1.0.8", - "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz", - "integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==", - "requires": { - "delayed-stream": "~1.0.0" - } - }, - "concat-map": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", - "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==", - "dev": true - }, - "convert-source-map": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-2.0.0.tgz", - "integrity": "sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg==", - "dev": true - }, - "create-jest": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/create-jest/-/create-jest-29.7.0.tgz", - "integrity": "sha512-Adz2bdH0Vq3F53KEMJOoftQFutWCukm6J24wbPWRO4k1kMY7gS7ds/uoJkNuV8wDCtWWnuwGcJwpWcih+zEW1Q==", - "dev": true, - "requires": { - "@jest/types": "^29.6.3", - "chalk": "^4.0.0", - "exit": "^0.1.2", - "graceful-fs": "^4.2.9", - "jest-config": "^29.7.0", - "jest-util": "^29.7.0", - "prompts": "^2.0.1" - } - }, - "cross-spawn": { - "version": "7.0.3", - "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz", - "integrity": "sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==", - "dev": true, - "requires": { - "path-key": "^3.1.0", - "shebang-command": "^2.0.0", - "which": "^2.0.1" - } - }, - "debug": { - "version": "4.3.1", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.1.tgz", - "integrity": "sha512-doEwdvm4PCeK4K3RQN2ZC2BYUBaxwLARCqZmMjtF8a51J2Rb0xpVloFRnCODwqjpwnAoao4pelN8l3RJdv3gRQ==", - "dev": true, - "requires": { - "ms": "2.1.2" - } - }, - "dedent": { - "version": "1.5.3", - "resolved": "https://registry.npmjs.org/dedent/-/dedent-1.5.3.tgz", - "integrity": "sha512-NHQtfOOW68WD8lgypbLA5oT+Bt0xXJhiYvoR6SmmNXZfpzOGXwdKWmcwG8N7PwVVWV3eF/68nmD9BaJSsTBhyQ==", - "dev": true, - "requires": {} - }, - "deep-is": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.4.tgz", - "integrity": "sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==", - "dev": true - }, - "deepmerge": { - "version": "4.3.1", - "resolved": "https://registry.npmjs.org/deepmerge/-/deepmerge-4.3.1.tgz", - "integrity": "sha512-3sUqbMEc77XqpdNO7FRyRog+eW3ph+GYCbj+rK+uYyRMuwsVy0rMiVtPn+QJlKFvWP/1PYpapqYn0Me2knFn+A==", - "dev": true - }, - "define-data-property": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/define-data-property/-/define-data-property-1.1.4.tgz", - "integrity": "sha512-rBMvIzlpA8v6E+SJZoo++HAYqsLrkg7MSfIinMPFhmkorw7X+dOXVJQs+QT69zGkzMyfDnIMN2Wid1+NbL3T+A==", - "requires": { - "es-define-property": "^1.0.0", - "es-errors": "^1.3.0", - "gopd": "^1.0.1" - } - }, - "define-properties": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.2.1.tgz", - "integrity": "sha512-8QmQKqEASLd5nx0U1B1okLElbUuuttJ/AnYmRXbbbGDWh6uS208EjD4Xqq/I9wK7u0v6O08XhTWnt5XtEbR6Dg==", - "dev": true, - "requires": { - "define-data-property": "^1.0.1", - "has-property-descriptors": "^1.0.0", - "object-keys": "^1.1.1" - } - }, - "delayed-stream": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", - "integrity": "sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==" - }, - "detect-newline": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/detect-newline/-/detect-newline-3.1.0.tgz", - "integrity": "sha512-TLz+x/vEXm/Y7P7wn1EJFNLxYpUD4TgMosxY6fAVJUnJMbupHBOncxyWUG9OpTaH9EBD7uFI5LfEgmMOc54DsA==", - "dev": true - }, - "diff-sequences": { - "version": "29.6.3", - "resolved": "https://registry.npmjs.org/diff-sequences/-/diff-sequences-29.6.3.tgz", - "integrity": "sha512-EjePK1srD3P08o2j4f0ExnylqRs5B9tJjcp9t1krH2qRi8CCdsYfwe9JgSLurFBWwq4uOlipzfk5fHNvwFKr8Q==", - "dev": true - }, - "doctrine": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-3.0.0.tgz", - "integrity": "sha512-yS+Q5i3hBf7GBkd4KG8a7eBNNWNGLTaEwwYWUijIYM7zrlYDM0BFXHjjPWlWZ1Rg7UaddZeIDmi9jF3HmqiQ2w==", - "dev": true, - "requires": { - "esutils": "^2.0.2" - } - }, - "electron-to-chromium": { - "version": "1.5.7", - "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.7.tgz", - "integrity": "sha512-6FTNWIWMxMy/ZY6799nBlPtF1DFDQ6VQJ7yyDP27SJNt5lwtQ5ufqVvHylb3fdQefvRcgA3fKcFMJi9OLwBRNw==", - "dev": true - }, - "emittery": { - "version": "0.13.1", - "resolved": "https://registry.npmjs.org/emittery/-/emittery-0.13.1.tgz", - "integrity": "sha512-DeWwawk6r5yR9jFgnDKYt4sLS0LmHJJi3ZOnb5/JdbYwj3nW+FxQnHIjhBKz8YLC7oRNPVM9NQ47I3CVx34eqQ==", - "dev": true - }, - "emoji-regex": { - "version": "8.0.0", - "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", - "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", - "dev": true - }, - "error-ex": { - "version": "1.3.2", - "resolved": "https://registry.npmjs.org/error-ex/-/error-ex-1.3.2.tgz", - "integrity": "sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g==", - "dev": true, - "requires": { - "is-arrayish": "^0.2.1" - } - }, - "es-abstract": { - "version": "1.22.3", - "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.22.3.tgz", - "integrity": "sha512-eiiY8HQeYfYH2Con2berK+To6GrK2RxbPawDkGq4UiCQQfZHb6wX9qQqkbpPqaxQFcl8d9QzZqo0tGE0VcrdwA==", - "dev": true, - "requires": { - "array-buffer-byte-length": "^1.0.0", - "arraybuffer.prototype.slice": "^1.0.2", - "available-typed-arrays": "^1.0.5", - "call-bind": "^1.0.5", - "es-set-tostringtag": "^2.0.1", - "es-to-primitive": "^1.2.1", - "function.prototype.name": "^1.1.6", - "get-intrinsic": "^1.2.2", - "get-symbol-description": "^1.0.0", - "globalthis": "^1.0.3", - "gopd": "^1.0.1", - "has-property-descriptors": "^1.0.0", - "has-proto": "^1.0.1", - "has-symbols": "^1.0.3", - "hasown": "^2.0.0", - "internal-slot": "^1.0.5", - "is-array-buffer": "^3.0.2", - "is-callable": "^1.2.7", - "is-negative-zero": "^2.0.2", - "is-regex": "^1.1.4", - "is-shared-array-buffer": "^1.0.2", - "is-string": "^1.0.7", - "is-typed-array": "^1.1.12", - "is-weakref": "^1.0.2", - "object-inspect": "^1.13.1", - "object-keys": "^1.1.1", - "object.assign": "^4.1.4", - "regexp.prototype.flags": "^1.5.1", - "safe-array-concat": "^1.0.1", - "safe-regex-test": "^1.0.0", - "string.prototype.trim": "^1.2.8", - "string.prototype.trimend": "^1.0.7", - "string.prototype.trimstart": "^1.0.7", - "typed-array-buffer": "^1.0.0", - "typed-array-byte-length": "^1.0.0", - "typed-array-byte-offset": "^1.0.0", - "typed-array-length": "^1.0.4", - "unbox-primitive": "^1.0.2", - "which-typed-array": "^1.1.13" - } - }, - "es-define-property": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/es-define-property/-/es-define-property-1.0.0.tgz", - "integrity": "sha512-jxayLKShrEqqzJ0eumQbVhTYQM27CfT1T35+gCgDFoL82JLsXqTJ76zv6A0YLOgEnLUMvLzsDsGIrl8NFpT2gQ==", - "requires": { - "get-intrinsic": "^1.2.4" - } - }, - "es-errors": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/es-errors/-/es-errors-1.3.0.tgz", - "integrity": "sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==" - }, - "es-iterator-helpers": { - "version": "1.0.15", - "resolved": "https://registry.npmjs.org/es-iterator-helpers/-/es-iterator-helpers-1.0.15.tgz", - "integrity": "sha512-GhoY8uYqd6iwUl2kgjTm4CZAf6oo5mHK7BPqx3rKgx893YSsy0LGHV6gfqqQvZt/8xM8xeOnfXBCfqclMKkJ5g==", - "dev": true, - "requires": { - "asynciterator.prototype": "^1.0.0", - "call-bind": "^1.0.2", - "define-properties": "^1.2.1", - "es-abstract": "^1.22.1", - "es-set-tostringtag": "^2.0.1", - "function-bind": "^1.1.1", - "get-intrinsic": "^1.2.1", - "globalthis": "^1.0.3", - "has-property-descriptors": "^1.0.0", - "has-proto": "^1.0.1", - "has-symbols": "^1.0.3", - "internal-slot": "^1.0.5", - "iterator.prototype": "^1.1.2", - "safe-array-concat": "^1.0.1" - } - }, - "es-set-tostringtag": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/es-set-tostringtag/-/es-set-tostringtag-2.0.2.tgz", - "integrity": "sha512-BuDyupZt65P9D2D2vA/zqcI3G5xRsklm5N3xCwuiy+/vKy8i0ifdsQP1sLgO4tZDSCaQUSnmC48khknGMV3D2Q==", - "dev": true, - "requires": { - "get-intrinsic": "^1.2.2", - "has-tostringtag": "^1.0.0", - "hasown": "^2.0.0" - } - }, - "es-shim-unscopables": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/es-shim-unscopables/-/es-shim-unscopables-1.0.0.tgz", - "integrity": "sha512-Jm6GPcCdC30eMLbZ2x8z2WuRwAws3zTBBKuusffYVUrNj/GVSUAZ+xKMaUpfNDR5IbyNA5LJbaecoUVbmUcB1w==", - "dev": true, - "requires": { - "has": "^1.0.3" - } - }, - "es-to-primitive": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/es-to-primitive/-/es-to-primitive-1.2.1.tgz", - "integrity": "sha512-QCOllgZJtaUo9miYBcLChTUaHNjJF3PYs1VidD7AwiEj1kYxKeQTctLAezAOH5ZKRH0g2IgPn6KwB4IT8iRpvA==", - "dev": true, - "requires": { - "is-callable": "^1.1.4", - "is-date-object": "^1.0.1", - "is-symbol": "^1.0.2" - } - }, - "escalade": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.1.2.tgz", - "integrity": "sha512-ErCHMCae19vR8vQGe50xIsVomy19rg6gFu3+r3jkEO46suLMWBksvVyoGgQV+jOfl84ZSOSlmv6Gxa89PmTGmA==", - "dev": true - }, - "escape-string-regexp": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-2.0.0.tgz", - "integrity": "sha512-UpzcLCXolUWcNu5HtVMHYdXJjArjsF9C0aNnquZYY4uW/Vu0miy5YoWvbV345HauVvcAUnpRuhMMcqTcGOY2+w==", - "dev": true - }, - "eslint": { - "version": "8.53.0", - "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.53.0.tgz", - "integrity": "sha512-N4VuiPjXDUa4xVeV/GC/RV3hQW9Nw+Y463lkWaKKXKYMvmRiRDAtfpuPFLN+E1/6ZhyR8J2ig+eVREnYgUsiag==", - "dev": true, - "requires": { - "@eslint-community/eslint-utils": "^4.2.0", - "@eslint-community/regexpp": "^4.6.1", - "@eslint/eslintrc": "^2.1.3", - "@eslint/js": "8.53.0", - "@humanwhocodes/config-array": "^0.11.13", - "@humanwhocodes/module-importer": "^1.0.1", - "@nodelib/fs.walk": "^1.2.8", - "@ungap/structured-clone": "^1.2.0", - "ajv": "^6.12.4", - "chalk": "^4.0.0", - "cross-spawn": "^7.0.2", - "debug": "^4.3.2", - "doctrine": "^3.0.0", - "escape-string-regexp": "^4.0.0", - "eslint-scope": "^7.2.2", - "eslint-visitor-keys": "^3.4.3", - "espree": "^9.6.1", - "esquery": "^1.4.2", - "esutils": "^2.0.2", - "fast-deep-equal": "^3.1.3", - "file-entry-cache": "^6.0.1", - "find-up": "^5.0.0", - "glob-parent": "^6.0.2", - "globals": "^13.19.0", - "graphemer": "^1.4.0", - "ignore": "^5.2.0", - "imurmurhash": "^0.1.4", - "is-glob": "^4.0.0", - "is-path-inside": "^3.0.3", - "js-yaml": "^4.1.0", - "json-stable-stringify-without-jsonify": "^1.0.1", - "levn": "^0.4.1", - "lodash.merge": "^4.6.2", - "minimatch": "^3.1.2", - "natural-compare": "^1.4.0", - "optionator": "^0.9.3", - "strip-ansi": "^6.0.1", - "text-table": "^0.2.0" - }, - "dependencies": { - "argparse": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", - "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==", - "dev": true - }, - "debug": { - "version": "4.3.4", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", - "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", - "dev": true, - "requires": { - "ms": "2.1.2" - } - }, - "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 - }, - "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, - "requires": { - "locate-path": "^6.0.0", - "path-exists": "^4.0.0" - } - }, - "globals": { - "version": "13.23.0", - "resolved": "https://registry.npmjs.org/globals/-/globals-13.23.0.tgz", - "integrity": "sha512-XAmF0RjlrjY23MA51q3HltdlGxUpXPvg0GioKiD9X6HD28iMjo2dKC8Vqwm7lne4GNr78+RHTfliktR6ZH09wA==", - "dev": true, - "requires": { - "type-fest": "^0.20.2" - } - }, - "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, - "requires": { - "argparse": "^2.0.1" - } - }, - "locate-path": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz", - "integrity": "sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==", - "dev": true, - "requires": { - "p-locate": "^5.0.0" - } - }, - "p-locate": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-5.0.0.tgz", - "integrity": "sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==", - "dev": true, - "requires": { - "p-limit": "^3.0.2" - } - }, - "type-fest": { - "version": "0.20.2", - "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.20.2.tgz", - "integrity": "sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ==", - "dev": true - } - } - }, - "eslint-config-standard": { - "version": "17.1.0", - "resolved": "https://registry.npmjs.org/eslint-config-standard/-/eslint-config-standard-17.1.0.tgz", - "integrity": "sha512-IwHwmaBNtDK4zDHQukFDW5u/aTb8+meQWZvNFWkiGmbWjD6bqyuSSBxxXKkCftCUzc1zwCH2m/baCNDLGmuO5Q==", - "dev": true, - "requires": {} - }, - "eslint-config-standard-jsx": { - "version": "11.0.0", - "resolved": "https://registry.npmjs.org/eslint-config-standard-jsx/-/eslint-config-standard-jsx-11.0.0.tgz", - "integrity": "sha512-+1EV/R0JxEK1L0NGolAr8Iktm3Rgotx3BKwgaX+eAuSX8D952LULKtjgZD3F+e6SvibONnhLwoTi9DPxN5LvvQ==", - "dev": true, - "requires": {} - }, - "eslint-import-resolver-node": { - "version": "0.3.9", - "resolved": "https://registry.npmjs.org/eslint-import-resolver-node/-/eslint-import-resolver-node-0.3.9.tgz", - "integrity": "sha512-WFj2isz22JahUv+B788TlO3N6zL3nNJGU8CcZbPZvVEkBPaJdCV4vy5wyghty5ROFbCRnm132v8BScu5/1BQ8g==", - "dev": true, - "requires": { - "debug": "^3.2.7", - "is-core-module": "^2.13.0", - "resolve": "^1.22.4" - }, - "dependencies": { - "debug": { - "version": "3.2.7", - "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz", - "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==", - "dev": true, - "requires": { - "ms": "^2.1.1" - } - } - } - }, - "eslint-module-utils": { - "version": "2.8.0", - "resolved": "https://registry.npmjs.org/eslint-module-utils/-/eslint-module-utils-2.8.0.tgz", - "integrity": "sha512-aWajIYfsqCKRDgUfjEXNN/JlrzauMuSEy5sbd7WXbtW3EH6A6MpwEh42c7qD+MqQo9QMJ6fWLAeIJynx0g6OAw==", - "dev": true, - "requires": { - "debug": "^3.2.7" - }, - "dependencies": { - "debug": { - "version": "3.2.7", - "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz", - "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==", - "dev": true, - "requires": { - "ms": "^2.1.1" - } - } - } - }, - "eslint-plugin-es": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/eslint-plugin-es/-/eslint-plugin-es-4.1.0.tgz", - "integrity": "sha512-GILhQTnjYE2WorX5Jyi5i4dz5ALWxBIdQECVQavL6s7cI76IZTDWleTHkxz/QT3kvcs2QlGHvKLYsSlPOlPXnQ==", - "dev": true, - "requires": { - "eslint-utils": "^2.0.0", - "regexpp": "^3.0.0" - }, - "dependencies": { - "eslint-utils": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/eslint-utils/-/eslint-utils-2.1.0.tgz", - "integrity": "sha512-w94dQYoauyvlDc43XnGB8lU3Zt713vNChgt4EWwhXAP2XkBvndfxF0AgIqKOOasjPIPzj9JqgwkwbCYD0/V3Zg==", - "dev": true, - "requires": { - "eslint-visitor-keys": "^1.1.0" - } - }, - "eslint-visitor-keys": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-1.3.0.tgz", - "integrity": "sha512-6J72N8UNa462wa/KFODt/PJ3IU60SDpC3QXC1Hjc1BXXpfL2C9R5+AU7jhe0F6GREqVMh4Juu+NY7xn+6dipUQ==", - "dev": true - } - } - }, - "eslint-plugin-import": { - "version": "2.29.0", - "resolved": "https://registry.npmjs.org/eslint-plugin-import/-/eslint-plugin-import-2.29.0.tgz", - "integrity": "sha512-QPOO5NO6Odv5lpoTkddtutccQjysJuFxoPS7fAHO+9m9udNHvTCPSAMW9zGAYj8lAIdr40I8yPCdUYrncXtrwg==", - "dev": true, - "requires": { - "array-includes": "^3.1.7", - "array.prototype.findlastindex": "^1.2.3", - "array.prototype.flat": "^1.3.2", - "array.prototype.flatmap": "^1.3.2", - "debug": "^3.2.7", - "doctrine": "^2.1.0", - "eslint-import-resolver-node": "^0.3.9", - "eslint-module-utils": "^2.8.0", - "hasown": "^2.0.0", - "is-core-module": "^2.13.1", - "is-glob": "^4.0.3", - "minimatch": "^3.1.2", - "object.fromentries": "^2.0.7", - "object.groupby": "^1.0.1", - "object.values": "^1.1.7", - "semver": "^6.3.1", - "tsconfig-paths": "^3.14.2" - }, - "dependencies": { - "debug": { - "version": "3.2.7", - "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz", - "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==", - "dev": true, - "requires": { - "ms": "^2.1.1" - } - }, - "doctrine": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-2.1.0.tgz", - "integrity": "sha512-35mSku4ZXK0vfCuHEDAwt55dg2jNajHZ1odvF+8SSr82EsZY4QmXfuWso8oEd8zRhVObSN18aM0CjSdoBX7zIw==", - "dev": true, - "requires": { - "esutils": "^2.0.2" - } - } - } - }, - "eslint-plugin-n": { - "version": "15.7.0", - "resolved": "https://registry.npmjs.org/eslint-plugin-n/-/eslint-plugin-n-15.7.0.tgz", - "integrity": "sha512-jDex9s7D/Qial8AGVIHq4W7NswpUD5DPDL2RH8Lzd9EloWUuvUkHfv4FRLMipH5q2UtyurorBkPeNi1wVWNh3Q==", - "dev": true, - "requires": { - "builtins": "^5.0.1", - "eslint-plugin-es": "^4.1.0", - "eslint-utils": "^3.0.0", - "ignore": "^5.1.1", - "is-core-module": "^2.11.0", - "minimatch": "^3.1.2", - "resolve": "^1.22.1", - "semver": "^7.3.8" - }, - "dependencies": { - "semver": { - "version": "7.5.4", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.5.4.tgz", - "integrity": "sha512-1bCSESV6Pv+i21Hvpxp3Dx+pSD8lIPt8uVjRrxAUt/nbswYc+tK6Y2btiULjd4+fnq15PX+nqQDC7Oft7WkwcA==", - "dev": true, - "requires": { - "lru-cache": "^6.0.0" - } - } - } - }, - "eslint-plugin-promise": { - "version": "6.1.1", - "resolved": "https://registry.npmjs.org/eslint-plugin-promise/-/eslint-plugin-promise-6.1.1.tgz", - "integrity": "sha512-tjqWDwVZQo7UIPMeDReOpUgHCmCiH+ePnVT+5zVapL0uuHnegBUs2smM13CzOs2Xb5+MHMRFTs9v24yjba4Oig==", - "dev": true, - "requires": {} - }, - "eslint-plugin-react": { - "version": "7.33.2", - "resolved": "https://registry.npmjs.org/eslint-plugin-react/-/eslint-plugin-react-7.33.2.tgz", - "integrity": "sha512-73QQMKALArI8/7xGLNI/3LylrEYrlKZSb5C9+q3OtOewTnMQi5cT+aE9E41sLCmli3I9PGGmD1yiZydyo4FEPw==", - "dev": true, - "requires": { - "array-includes": "^3.1.6", - "array.prototype.flatmap": "^1.3.1", - "array.prototype.tosorted": "^1.1.1", - "doctrine": "^2.1.0", - "es-iterator-helpers": "^1.0.12", - "estraverse": "^5.3.0", - "jsx-ast-utils": "^2.4.1 || ^3.0.0", - "minimatch": "^3.1.2", - "object.entries": "^1.1.6", - "object.fromentries": "^2.0.6", - "object.hasown": "^1.1.2", - "object.values": "^1.1.6", - "prop-types": "^15.8.1", - "resolve": "^2.0.0-next.4", - "semver": "^6.3.1", - "string.prototype.matchall": "^4.0.8" - }, - "dependencies": { - "doctrine": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-2.1.0.tgz", - "integrity": "sha512-35mSku4ZXK0vfCuHEDAwt55dg2jNajHZ1odvF+8SSr82EsZY4QmXfuWso8oEd8zRhVObSN18aM0CjSdoBX7zIw==", - "dev": true, - "requires": { - "esutils": "^2.0.2" - } - }, - "resolve": { - "version": "2.0.0-next.4", - "resolved": "https://registry.npmjs.org/resolve/-/resolve-2.0.0-next.4.tgz", - "integrity": "sha512-iMDbmAWtfU+MHpxt/I5iWI7cY6YVEZUQ3MBgPQ++XD1PELuJHIl82xBmObyP2KyQmkNB2dsqF7seoQQiAn5yDQ==", - "dev": true, - "requires": { - "is-core-module": "^2.9.0", - "path-parse": "^1.0.7", - "supports-preserve-symlinks-flag": "^1.0.0" - } - } - } - }, - "eslint-scope": { - "version": "7.2.2", - "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-7.2.2.tgz", - "integrity": "sha512-dOt21O7lTMhDM+X9mB4GX+DZrZtCUJPL/wlcTqxyrx5IvO0IYtILdtrQGQp+8n5S0gwSVmOf9NQrjMOgfQZlIg==", - "dev": true, - "requires": { - "esrecurse": "^4.3.0", - "estraverse": "^5.2.0" - } - }, - "eslint-utils": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/eslint-utils/-/eslint-utils-3.0.0.tgz", - "integrity": "sha512-uuQC43IGctw68pJA1RgbQS8/NP7rch6Cwd4j3ZBtgo4/8Flj4eGE7ZYSZRN3iq5pVUv6GPdW5Z1RFleo84uLDA==", - "dev": true, - "requires": { - "eslint-visitor-keys": "^2.0.0" - }, - "dependencies": { - "eslint-visitor-keys": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-2.1.0.tgz", - "integrity": "sha512-0rSmRBzXgDzIsD6mGdJgevzgezI534Cer5L/vyMX0kHzT/jiB43jRhd9YUlMGYLQy2zprNmoT8qasCGtY+QaKw==", - "dev": true - } - } - }, - "eslint-visitor-keys": { - "version": "3.4.3", - "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.4.3.tgz", - "integrity": "sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag==", - "dev": true - }, - "espree": { - "version": "9.6.1", - "resolved": "https://registry.npmjs.org/espree/-/espree-9.6.1.tgz", - "integrity": "sha512-oruZaFkjorTpF32kDSI5/75ViwGeZginGGy2NoOSg3Q9bnwlnmDm4HLnkl0RE3n+njDXR037aY1+x58Z/zFdwQ==", - "dev": true, - "requires": { - "acorn": "^8.9.0", - "acorn-jsx": "^5.3.2", - "eslint-visitor-keys": "^3.4.1" - } - }, - "esprima": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz", - "integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==", - "dev": true - }, - "esquery": { - "version": "1.5.0", - "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.5.0.tgz", - "integrity": "sha512-YQLXUplAwJgCydQ78IMJywZCceoqk1oH01OERdSAJc/7U2AylwjhSCLDEtqwg811idIS/9fIU5GjG73IgjKMVg==", - "dev": true, - "requires": { - "estraverse": "^5.1.0" - } - }, - "esrecurse": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.3.0.tgz", - "integrity": "sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==", - "dev": true, - "requires": { - "estraverse": "^5.2.0" - } - }, - "estraverse": { - "version": "5.3.0", - "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz", - "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==", - "dev": true - }, - "esutils": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz", - "integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==", - "dev": true - }, - "execa": { - "version": "5.1.1", - "resolved": "https://registry.npmjs.org/execa/-/execa-5.1.1.tgz", - "integrity": "sha512-8uSpZZocAZRBAPIEINJj3Lo9HyGitllczc27Eh5YYojjMFMn8yHMDMaUHE2Jqfq05D/wucwI4JGURyXt1vchyg==", - "dev": true, - "requires": { - "cross-spawn": "^7.0.3", - "get-stream": "^6.0.0", - "human-signals": "^2.1.0", - "is-stream": "^2.0.0", - "merge-stream": "^2.0.0", - "npm-run-path": "^4.0.1", - "onetime": "^5.1.2", - "signal-exit": "^3.0.3", - "strip-final-newline": "^2.0.0" - } - }, - "exit": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/exit/-/exit-0.1.2.tgz", - "integrity": "sha512-Zk/eNKV2zbjpKzrsQ+n1G6poVbErQxJ0LBOJXaKZ1EViLzH+hrLu9cdXI4zw9dBQJslwBEpbQ2P1oS7nDxs6jQ==", - "dev": true - }, - "expect": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/expect/-/expect-29.7.0.tgz", - "integrity": "sha512-2Zks0hf1VLFYI1kbh0I5jP3KHHyCHpkfyHBzsSXRFgl/Bg9mWYfMW8oD+PdMPlEwy5HNsR9JutYy6pMeOh61nw==", - "dev": true, - "requires": { - "@jest/expect-utils": "^29.7.0", - "jest-get-type": "^29.6.3", - "jest-matcher-utils": "^29.7.0", - "jest-message-util": "^29.7.0", - "jest-util": "^29.7.0" - } - }, - "fast-deep-equal": { - "version": "3.1.3", - "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", - "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==", - "dev": true - }, - "fast-json-stable-stringify": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz", - "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==", - "dev": true - }, - "fast-levenshtein": { - "version": "2.0.6", - "resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz", - "integrity": "sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==", - "dev": true - }, - "fastq": { - "version": "1.13.0", - "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.13.0.tgz", - "integrity": "sha512-YpkpUnK8od0o1hmeSc7UUs/eB/vIPWJYjKck2QKIzAf71Vm1AAQ3EbuZB3g2JIy+pg+ERD0vqI79KyZiB2e2Nw==", - "dev": true, - "requires": { - "reusify": "^1.0.4" - } - }, - "fb-watchman": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/fb-watchman/-/fb-watchman-2.0.2.tgz", - "integrity": "sha512-p5161BqbuCaSnB8jIbzQHOlpgsPmK5rJVDfDKO91Axs5NC1uu3HRQm6wt9cd9/+GtQQIO53JdGXXoyDpTAsgYA==", - "dev": true, - "requires": { - "bser": "2.1.1" - } - }, - "file-entry-cache": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-6.0.1.tgz", - "integrity": "sha512-7Gps/XWymbLk2QLYK4NzpMOrYjMhdIxXuIvy2QBsLE6ljuodKvdkWs/cpyJJ3CVIVpH0Oi1Hvg1ovbMzLdFBBg==", - "dev": true, - "requires": { - "flat-cache": "^3.0.4" - } - }, - "fill-range": { - "version": "7.1.1", - "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.1.1.tgz", - "integrity": "sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==", - "dev": true, - "requires": { - "to-regex-range": "^5.0.1" - } - }, - "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, - "requires": { - "locate-path": "^5.0.0", - "path-exists": "^4.0.0" - } - }, - "flat-cache": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-3.0.4.tgz", - "integrity": "sha512-dm9s5Pw7Jc0GvMYbshN6zchCA9RgQlzzEZX3vylR9IqFfS8XciblUXOKfW6SiuJ0e13eDYZoZV5wdrev7P3Nwg==", - "dev": true, - "requires": { - "flatted": "^3.1.0", - "rimraf": "^3.0.2" - } - }, - "flatted": { - "version": "3.2.7", - "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.2.7.tgz", - "integrity": "sha512-5nqDSxl8nn5BSNxyR3n4I6eDmbolI6WT+QqR547RwxQapgjQBmtktdP+HTBb/a/zLsbzERTONyUB5pefh5TtjQ==", - "dev": true - }, - "follow-redirects": { - "version": "1.15.6", - "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.6.tgz", - "integrity": "sha512-wWN62YITEaOpSK584EZXJafH1AGpO8RVgElfkuXbTOrPX4fIfOyEpW/CsiNd8JdYrAoOvafRTOEnvsO++qCqFA==" - }, - "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, - "requires": { - "is-callable": "^1.1.3" - } - }, - "form-data": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.0.tgz", - "integrity": "sha512-ETEklSGi5t0QMZuiXoA/Q6vcnxcLQP5vdugSpuAyi6SVGi2clPPp+xgEhuMaHC+zGgn31Kd235W35f7Hykkaww==", - "requires": { - "asynckit": "^0.4.0", - "combined-stream": "^1.0.8", - "mime-types": "^2.1.12" - } - }, - "fs.realpath": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", - "integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==", - "dev": true - }, - "fsevents": { - "version": "2.3.3", - "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz", - "integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==", - "dev": true, - "optional": true - }, - "function-bind": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz", - "integrity": "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==" - }, - "function.prototype.name": { - "version": "1.1.6", - "resolved": "https://registry.npmjs.org/function.prototype.name/-/function.prototype.name-1.1.6.tgz", - "integrity": "sha512-Z5kx79swU5P27WEayXM1tBi5Ze/lbIyiNgU3qyXUOf9b2rgXYyF9Dy9Cx+IQv/Lc8WCG6L82zwUPpSS9hGehIg==", - "dev": true, - "requires": { - "call-bind": "^1.0.2", - "define-properties": "^1.2.0", - "es-abstract": "^1.22.1", - "functions-have-names": "^1.2.3" - } - }, - "functions-have-names": { - "version": "1.2.3", - "resolved": "https://registry.npmjs.org/functions-have-names/-/functions-have-names-1.2.3.tgz", - "integrity": "sha512-xckBUXyTIqT97tq2x2AMb+g163b5JFysYk0x4qxNFwbfQkmNZoiRHb6sPzI9/QV33WeuvVYBUIiD4NzNIyqaRQ==", - "dev": true - }, - "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 - }, - "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 - }, - "get-intrinsic": { - "version": "1.2.4", - "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.2.4.tgz", - "integrity": "sha512-5uYhsJH8VJBTv7oslg4BznJYhDoRI6waYCxMmCdnTrcCrHA/fCFKoTFz2JKKE0HdDFUF7/oQuhzumXJK7paBRQ==", - "requires": { - "es-errors": "^1.3.0", - "function-bind": "^1.1.2", - "has-proto": "^1.0.1", - "has-symbols": "^1.0.3", - "hasown": "^2.0.0" - } - }, - "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==", - "dev": true - }, - "get-stdin": { - "version": "8.0.0", - "resolved": "https://registry.npmjs.org/get-stdin/-/get-stdin-8.0.0.tgz", - "integrity": "sha512-sY22aA6xchAzprjyqmSEQv4UbAAzRN0L2dQB0NlN5acTTK9Don6nhoc3eAbUnpZiCANAMfd/+40kVdKfFygohg==", - "dev": true - }, - "get-stream": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-6.0.1.tgz", - "integrity": "sha512-ts6Wi+2j3jQjqi70w5AlN8DFnkSwC+MqmxEzdEALB2qXZYV3X/b1CTfgPLGJNMeAWxdPfU8FO1ms3NUfaHCPYg==", - "dev": true - }, - "get-symbol-description": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/get-symbol-description/-/get-symbol-description-1.0.0.tgz", - "integrity": "sha512-2EmdH1YvIQiZpltCNgkuiUnyukzxM/R6NDJX31Ke3BG1Nq5b0S2PhX59UKi9vZpPDQVdqn+1IcaAwnzTT5vCjw==", - "dev": true, - "requires": { - "call-bind": "^1.0.2", - "get-intrinsic": "^1.1.1" - } - }, - "glob": { - "version": "7.2.3", - "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", - "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", - "dev": true, - "requires": { - "fs.realpath": "^1.0.0", - "inflight": "^1.0.4", - "inherits": "2", - "minimatch": "^3.1.1", - "once": "^1.3.0", - "path-is-absolute": "^1.0.0" - } - }, - "glob-parent": { - "version": "6.0.2", - "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-6.0.2.tgz", - "integrity": "sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==", - "dev": true, - "requires": { - "is-glob": "^4.0.3" - } - }, - "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 - }, - "globalthis": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/globalthis/-/globalthis-1.0.3.tgz", - "integrity": "sha512-sFdI5LyBiNTHjRd7cGPWapiHWMOXKyuBNX/cWJ3NfzrZQVa8GI/8cofCl74AOVqq9W5kNmguTIzJ/1s2gyI9wA==", - "dev": true, - "requires": { - "define-properties": "^1.1.3" - } - }, - "gopd": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/gopd/-/gopd-1.0.1.tgz", - "integrity": "sha512-d65bNlIadxvpb/A2abVdlqKqV563juRnZ1Wtk6s1sIR8uNsXR70xqIzVqxVf1eTqDunwT2MkczEeaezCKTZhwA==", - "requires": { - "get-intrinsic": "^1.1.3" - } - }, - "graceful-fs": { - "version": "4.2.10", - "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.10.tgz", - "integrity": "sha512-9ByhssR2fPVsNZj478qUUbKfmL0+t5BDVyjShtyZZLiK7ZDAArFFfopyOTj0M05wE2tJPisA4iTnnXl2YoPvOA==", - "dev": true - }, - "graphemer": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/graphemer/-/graphemer-1.4.0.tgz", - "integrity": "sha512-EtKwoO6kxCL9WO5xipiHTZlSzBm7WLT627TqC/uVRd0HKmq8NXyebnNYxDoBi7wt8eTWrUrKXCOVaFq9x1kgag==", - "dev": true - }, - "has": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz", - "integrity": "sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==", - "dev": true, - "requires": { - "function-bind": "^1.1.1" - } - }, - "has-bigints": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/has-bigints/-/has-bigints-1.0.2.tgz", - "integrity": "sha512-tSvCKtBr9lkF0Ex0aQiP9N+OpV4zi2r/Nee5VkRDbaqv35RLYMzbwQfFSZZH0kR+Rd6302UJZ2p/bJCEoR3VoQ==", - "dev": true - }, - "has-flag": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", - "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", - "dev": true - }, - "has-property-descriptors": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/has-property-descriptors/-/has-property-descriptors-1.0.2.tgz", - "integrity": "sha512-55JNKuIW+vq4Ke1BjOTjM2YctQIvCT7GFzHwmfZPGo5wnrgkid0YQtnAleFSqumZm4az3n2BS+erby5ipJdgrg==", - "requires": { - "es-define-property": "^1.0.0" - } - }, - "has-proto": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/has-proto/-/has-proto-1.0.1.tgz", - "integrity": "sha512-7qE+iP+O+bgF9clE5+UoBFzE65mlBiVj3tKCrlNQ0Ogwm0BjpT/gK4SlLYDMybDh5I3TCTKnPPa0oMG7JDYrhg==" - }, - "has-symbols": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.3.tgz", - "integrity": "sha512-l3LCuF6MgDNwTDKkdYGEihYjt5pRPbEg46rtlmnSPlUbgmB8LOIrKJbYYFBSbnPaJexMKtiPO8hmeRjRz2Td+A==" - }, - "has-tostringtag": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/has-tostringtag/-/has-tostringtag-1.0.0.tgz", - "integrity": "sha512-kFjcSNhnlGV1kyoGk7OXKSawH5JOb/LzUc5w9B02hOTO0dfFRjbHQKvg1d6cf3HbeUmtU9VbbV3qzZ2Teh97WQ==", - "dev": true, - "requires": { - "has-symbols": "^1.0.2" - } - }, - "hasown": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.0.tgz", - "integrity": "sha512-vUptKVTpIJhcczKBbgnS+RtcuYMB8+oNzPK2/Hp3hanz8JmpATdmmgLgSaadVREkDm+e2giHwY3ZRkyjSIDDFA==", - "requires": { - "function-bind": "^1.1.2" - } - }, - "html-escaper": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/html-escaper/-/html-escaper-2.0.2.tgz", - "integrity": "sha512-H2iMtd0I4Mt5eYiapRdIDjp+XzelXQ0tFE4JS7YFwFevXXMmOp9myNrUvCg0D6ws8iqkRPBfKHgbwig1SmlLfg==", - "dev": true - }, - "human-signals": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/human-signals/-/human-signals-2.1.0.tgz", - "integrity": "sha512-B4FFZ6q/T2jhhksgkbEW3HBvWIfDW85snkQgawt07S7J5QXTk6BkNV+0yAeZrM5QpMAdYlocGoljn0sJ/WQkFw==", - "dev": true - }, - "ignore": { - "version": "5.2.4", - "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.2.4.tgz", - "integrity": "sha512-MAb38BcSbH0eHNBxn7ql2NH/kX33OkB3lZ1BNdh7ENeRChHTYsTvWrMubiIAMNS2llXEEgZ1MUOBtXChP3kaFQ==", - "dev": true - }, - "import-fresh": { - "version": "3.3.0", - "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.0.tgz", - "integrity": "sha512-veYYhQa+D1QBKznvhUHxb8faxlrwUnxseDAbAp457E0wLNio2bOSKnjYDhMj+YiAq61xrMGhQk9iXVk5FzgQMw==", - "dev": true, - "requires": { - "parent-module": "^1.0.0", - "resolve-from": "^4.0.0" - }, - "dependencies": { - "resolve-from": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz", - "integrity": "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==", - "dev": true - } - } - }, - "import-local": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/import-local/-/import-local-3.2.0.tgz", - "integrity": "sha512-2SPlun1JUPWoM6t3F0dw0FkCF/jWY8kttcY4f599GLTSjh2OCuuhdTkJQsEcZzBqbXZGKMK2OqW1oZsjtf/gQA==", - "dev": true, - "requires": { - "pkg-dir": "^4.2.0", - "resolve-cwd": "^3.0.0" - } - }, - "imurmurhash": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz", - "integrity": "sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==", - "dev": true - }, - "inflight": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", - "integrity": "sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==", - "dev": true, - "requires": { - "once": "^1.3.0", - "wrappy": "1" - } - }, - "inherits": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", - "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", - "dev": true - }, - "internal-slot": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/internal-slot/-/internal-slot-1.0.6.tgz", - "integrity": "sha512-Xj6dv+PsbtwyPpEflsejS+oIZxmMlV44zAhG479uYu89MsjcYOhCFnNyKrkJrihbsiasQyY0afoCl/9BLR65bg==", - "dev": true, - "requires": { - "get-intrinsic": "^1.2.2", - "hasown": "^2.0.0", - "side-channel": "^1.0.4" - } - }, - "is-array-buffer": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/is-array-buffer/-/is-array-buffer-3.0.2.tgz", - "integrity": "sha512-y+FyyR/w8vfIRq4eQcM1EYgSTnmHXPqaF+IgzgraytCFq5Xh8lllDVmAZolPJiZttZLeFSINPYMaEJ7/vWUa1w==", - "dev": true, - "requires": { - "call-bind": "^1.0.2", - "get-intrinsic": "^1.2.0", - "is-typed-array": "^1.1.10" - } - }, - "is-arrayish": { - "version": "0.2.1", - "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz", - "integrity": "sha512-zz06S8t0ozoDXMG+ube26zeCTNXcKIPJZJi8hBrF4idCLms4CG9QtK7qBl1boi5ODzFpjswb5JPmHCbMpjaYzg==", - "dev": true - }, - "is-async-function": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/is-async-function/-/is-async-function-2.0.0.tgz", - "integrity": "sha512-Y1JXKrfykRJGdlDwdKlLpLyMIiWqWvuSd17TvZk68PLAOGOoF4Xyav1z0Xhoi+gCYjZVeC5SI+hYFOfvXmGRCA==", - "dev": true, - "requires": { - "has-tostringtag": "^1.0.0" - } - }, - "is-bigint": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/is-bigint/-/is-bigint-1.0.4.tgz", - "integrity": "sha512-zB9CruMamjym81i2JZ3UMn54PKGsQzsJeo6xvN3HJJ4CAsQNB6iRutp2To77OfCNuoxspsIhzaPoO1zyCEhFOg==", - "dev": true, - "requires": { - "has-bigints": "^1.0.1" - } - }, - "is-boolean-object": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/is-boolean-object/-/is-boolean-object-1.1.2.tgz", - "integrity": "sha512-gDYaKHJmnj4aWxyj6YHyXVpdQawtVLHU5cb+eztPGczf6cjuTdwve5ZIEfgXqH4e57An1D1AKf8CZ3kYrQRqYA==", - "dev": true, - "requires": { - "call-bind": "^1.0.2", - "has-tostringtag": "^1.0.0" - } - }, - "is-callable": { - "version": "1.2.7", - "resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.2.7.tgz", - "integrity": "sha512-1BC0BVFhS/p0qtw6enp8e+8OD0UrK0oFLztSjNzhcKA3WDuJxxAPXzPuPtKkjEY9UUoEWlX/8fgKeu2S8i9JTA==", - "dev": true - }, - "is-core-module": { - "version": "2.13.1", - "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.13.1.tgz", - "integrity": "sha512-hHrIjvZsftOsvKSn2TRYl63zvxsgE0K+0mYMoH6gD4omR5IWB2KynivBQczo3+wF1cCkjzvptnI9Q0sPU66ilw==", - "dev": true, - "requires": { - "hasown": "^2.0.0" - } - }, - "is-date-object": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/is-date-object/-/is-date-object-1.0.5.tgz", - "integrity": "sha512-9YQaSxsAiSwcvS33MBk3wTCVnWK+HhF8VZR2jRxehM16QcVOdHqPn4VPHmRK4lSr38n9JriurInLcP90xsYNfQ==", - "dev": true, - "requires": { - "has-tostringtag": "^1.0.0" - } - }, - "is-extglob": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", - "integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==", - "dev": true - }, - "is-finalizationregistry": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/is-finalizationregistry/-/is-finalizationregistry-1.0.2.tgz", - "integrity": "sha512-0by5vtUJs8iFQb5TYUHHPudOR+qXYIMKtiUzvLIZITZUjknFmziyBJuLhVRc+Ds0dREFlskDNJKYIdIzu/9pfw==", - "dev": true, - "requires": { - "call-bind": "^1.0.2" - } - }, - "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 - }, - "is-generator-fn": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/is-generator-fn/-/is-generator-fn-2.1.0.tgz", - "integrity": "sha512-cTIB4yPYL/Grw0EaSzASzg6bBy9gqCofvWN8okThAYIxKJZC+udlRAmGbM0XLeniEJSs8uEgHPGuHSe1XsOLSQ==", - "dev": true - }, - "is-generator-function": { - "version": "1.0.10", - "resolved": "https://registry.npmjs.org/is-generator-function/-/is-generator-function-1.0.10.tgz", - "integrity": "sha512-jsEjy9l3yiXEQ+PsXdmBwEPcOxaXWLspKdplFUVI9vq1iZgIekeC0L167qeu86czQaxed3q/Uzuw0swL0irL8A==", - "dev": true, - "requires": { - "has-tostringtag": "^1.0.0" - } - }, - "is-glob": { - "version": "4.0.3", - "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz", - "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==", - "dev": true, - "requires": { - "is-extglob": "^2.1.1" - } - }, - "is-map": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/is-map/-/is-map-2.0.2.tgz", - "integrity": "sha512-cOZFQQozTha1f4MxLFzlgKYPTyj26picdZTx82hbc/Xf4K/tZOOXSCkMvU4pKioRXGDLJRn0GM7Upe7kR721yg==", - "dev": true - }, - "is-negative-zero": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/is-negative-zero/-/is-negative-zero-2.0.2.tgz", - "integrity": "sha512-dqJvarLawXsFbNDeJW7zAz8ItJ9cd28YufuuFzh0G8pNHjJMnY08Dv7sYX2uF5UpQOwieAeOExEYAWWfu7ZZUA==", - "dev": true - }, - "is-number": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", - "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", - "dev": true - }, - "is-number-object": { - "version": "1.0.7", - "resolved": "https://registry.npmjs.org/is-number-object/-/is-number-object-1.0.7.tgz", - "integrity": "sha512-k1U0IRzLMo7ZlYIfzRu23Oh6MiIFasgpb9X76eqfFZAqwH44UI4KTBvBYIZ1dSL9ZzChTB9ShHfLkR4pdW5krQ==", - "dev": true, - "requires": { - "has-tostringtag": "^1.0.0" - } - }, - "is-path-inside": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/is-path-inside/-/is-path-inside-3.0.3.tgz", - "integrity": "sha512-Fd4gABb+ycGAmKou8eMftCupSir5lRxqf4aD/vd0cD2qc4HL07OjCeuHMr8Ro4CoMaeCKDB0/ECBOVWjTwUvPQ==", - "dev": true - }, - "is-regex": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.1.4.tgz", - "integrity": "sha512-kvRdxDsxZjhzUX07ZnLydzS1TU/TJlTUHHY4YLL87e37oUA49DfkLqgy+VjFocowy29cKvcSiu+kIv728jTTVg==", - "dev": true, - "requires": { - "call-bind": "^1.0.2", - "has-tostringtag": "^1.0.0" - } - }, - "is-set": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/is-set/-/is-set-2.0.2.tgz", - "integrity": "sha512-+2cnTEZeY5z/iXGbLhPrOAaK/Mau5k5eXq9j14CpRTftq0pAJu2MwVRSZhyZWBzx3o6X795Lz6Bpb6R0GKf37g==", - "dev": true - }, - "is-shared-array-buffer": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/is-shared-array-buffer/-/is-shared-array-buffer-1.0.2.tgz", - "integrity": "sha512-sqN2UDu1/0y6uvXyStCOzyhAjCSlHceFoMKJW8W9EU9cvic/QdsZ0kEU93HEy3IUEFZIiH/3w+AH/UQbPHNdhA==", - "dev": true, - "requires": { - "call-bind": "^1.0.2" - } - }, - "is-stream": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-2.0.1.tgz", - "integrity": "sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg==", - "dev": true - }, - "is-string": { - "version": "1.0.7", - "resolved": "https://registry.npmjs.org/is-string/-/is-string-1.0.7.tgz", - "integrity": "sha512-tE2UXzivje6ofPW7l23cjDOMa09gb7xlAqG6jG5ej6uPV32TlWP3NKPigtaGeHNu9fohccRYvIiZMfOOnOYUtg==", - "dev": true, - "requires": { - "has-tostringtag": "^1.0.0" - } - }, - "is-symbol": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/is-symbol/-/is-symbol-1.0.4.tgz", - "integrity": "sha512-C/CPBqKWnvdcxqIARxyOh4v1UUEOCHpgDa0WYgpKDFMszcrPcffg5uhwSgPCLD2WWxmq6isisz87tzT01tuGhg==", - "dev": true, - "requires": { - "has-symbols": "^1.0.2" - } - }, - "is-typed-array": { - "version": "1.1.12", - "resolved": "https://registry.npmjs.org/is-typed-array/-/is-typed-array-1.1.12.tgz", - "integrity": "sha512-Z14TF2JNG8Lss5/HMqt0//T9JeHXttXy5pH/DBU4vi98ozO2btxzq9MwYDZYnKwU8nRsz/+GVFVRDq3DkVuSPg==", - "dev": true, - "requires": { - "which-typed-array": "^1.1.11" - } - }, - "is-weakmap": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/is-weakmap/-/is-weakmap-2.0.1.tgz", - "integrity": "sha512-NSBR4kH5oVj1Uwvv970ruUkCV7O1mzgVFO4/rev2cLRda9Tm9HrL70ZPut4rOHgY0FNrUu9BCbXA2sdQ+x0chA==", - "dev": true - }, - "is-weakref": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/is-weakref/-/is-weakref-1.0.2.tgz", - "integrity": "sha512-qctsuLZmIQ0+vSSMfoVvyFe2+GSEvnmZ2ezTup1SBse9+twCCeial6EEi3Nc2KFcf6+qz2FBPnjXsk8xhKSaPQ==", - "dev": true, - "requires": { - "call-bind": "^1.0.2" - } - }, - "is-weakset": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/is-weakset/-/is-weakset-2.0.2.tgz", - "integrity": "sha512-t2yVvttHkQktwnNNmBQ98AhENLdPUTDTE21uPqAQ0ARwQfGeQKRVS0NNurH7bTf7RrvcVn1OOge45CnBeHCSmg==", - "dev": true, - "requires": { - "call-bind": "^1.0.2", - "get-intrinsic": "^1.1.1" - } - }, - "isarray": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-2.0.5.tgz", - "integrity": "sha512-xHjhDr3cNBK0BzdUJSPXZntQUx/mwMS5Rw4A7lPJ90XGAO6ISP/ePDNuo0vhqOZU+UD5JoodwCAAoZQd3FeAKw==", - "dev": true - }, - "isexe": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", - "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==", - "dev": true - }, - "istanbul-lib-coverage": { - "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 - }, - "istanbul-lib-instrument": { - "version": "6.0.3", - "resolved": "https://registry.npmjs.org/istanbul-lib-instrument/-/istanbul-lib-instrument-6.0.3.tgz", - "integrity": "sha512-Vtgk7L/R2JHyyGW07spoFlB8/lpjiOLTjMdms6AFMraYt3BaJauod/NGrfnVG/y4Ix1JEuMRPDPEj2ua+zz1/Q==", - "dev": true, - "requires": { - "@babel/core": "^7.23.9", - "@babel/parser": "^7.23.9", - "@istanbuljs/schema": "^0.1.3", - "istanbul-lib-coverage": "^3.2.0", - "semver": "^7.5.4" - }, - "dependencies": { - "semver": { - "version": "7.6.3", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.3.tgz", - "integrity": "sha512-oVekP1cKtI+CTDvHWYFUcMtsK/00wmAEfyqKfNdARm8u1wNVhSgaX7A8d4UuIlUI5e84iEwOhs7ZPYRmzU9U6A==", - "dev": true - } - } - }, - "istanbul-lib-report": { - "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, - "requires": { - "istanbul-lib-coverage": "^3.0.0", - "make-dir": "^4.0.0", - "supports-color": "^7.1.0" - } - }, - "istanbul-lib-source-maps": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/istanbul-lib-source-maps/-/istanbul-lib-source-maps-4.0.1.tgz", - "integrity": "sha512-n3s8EwkdFIJCG3BPKBYvskgXGoy88ARzvegkitk60NxRdwltLOTaH7CUiMRXvwYorl0Q712iEjcWB+fK/MrWVw==", - "dev": true, - "requires": { - "debug": "^4.1.1", - "istanbul-lib-coverage": "^3.0.0", - "source-map": "^0.6.1" - } - }, - "istanbul-reports": { - "version": "3.1.7", - "resolved": "https://registry.npmjs.org/istanbul-reports/-/istanbul-reports-3.1.7.tgz", - "integrity": "sha512-BewmUXImeuRk2YY0PVbxgKAysvhRPUQE0h5QRM++nVWyubKGV0l8qQ5op8+B2DOmwSe63Jivj0BjkPQVf8fP5g==", - "dev": true, - "requires": { - "html-escaper": "^2.0.0", - "istanbul-lib-report": "^3.0.0" - } - }, - "iterator.prototype": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/iterator.prototype/-/iterator.prototype-1.1.2.tgz", - "integrity": "sha512-DR33HMMr8EzwuRL8Y9D3u2BMj8+RqSE850jfGu59kS7tbmPLzGkZmVSfyCFSDxuZiEY6Rzt3T2NA/qU+NwVj1w==", - "dev": true, - "requires": { - "define-properties": "^1.2.1", - "get-intrinsic": "^1.2.1", - "has-symbols": "^1.0.3", - "reflect.getprototypeof": "^1.0.4", - "set-function-name": "^2.0.1" - } - }, - "jest": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/jest/-/jest-29.7.0.tgz", - "integrity": "sha512-NIy3oAFp9shda19hy4HK0HRTWKtPJmGdnvywu01nOqNC2vZg+Z+fvJDxpMQA88eb2I9EcafcdjYgsDthnYTvGw==", - "dev": true, - "requires": { - "@jest/core": "^29.7.0", - "@jest/types": "^29.6.3", - "import-local": "^3.0.2", - "jest-cli": "^29.7.0" - } - }, - "jest-changed-files": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/jest-changed-files/-/jest-changed-files-29.7.0.tgz", - "integrity": "sha512-fEArFiwf1BpQ+4bXSprcDc3/x4HSzL4al2tozwVpDFpsxALjLYdyiIK4e5Vz66GQJIbXJ82+35PtysofptNX2w==", - "dev": true, - "requires": { - "execa": "^5.0.0", - "jest-util": "^29.7.0", - "p-limit": "^3.1.0" - } - }, - "jest-circus": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/jest-circus/-/jest-circus-29.7.0.tgz", - "integrity": "sha512-3E1nCMgipcTkCocFwM90XXQab9bS+GMsjdpmPrlelaxwD93Ad8iVEjX/vvHPdLPnFf+L40u+5+iutRdA1N9myw==", - "dev": true, - "requires": { - "@jest/environment": "^29.7.0", - "@jest/expect": "^29.7.0", - "@jest/test-result": "^29.7.0", - "@jest/types": "^29.6.3", - "@types/node": "*", - "chalk": "^4.0.0", - "co": "^4.6.0", - "dedent": "^1.0.0", - "is-generator-fn": "^2.0.0", - "jest-each": "^29.7.0", - "jest-matcher-utils": "^29.7.0", - "jest-message-util": "^29.7.0", - "jest-runtime": "^29.7.0", - "jest-snapshot": "^29.7.0", - "jest-util": "^29.7.0", - "p-limit": "^3.1.0", - "pretty-format": "^29.7.0", - "pure-rand": "^6.0.0", - "slash": "^3.0.0", - "stack-utils": "^2.0.3" - } - }, - "jest-cli": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/jest-cli/-/jest-cli-29.7.0.tgz", - "integrity": "sha512-OVVobw2IubN/GSYsxETi+gOe7Ka59EFMR/twOU3Jb2GnKKeMGJB5SGUUrEz3SFVmJASUdZUzy83sLNNQ2gZslg==", - "dev": true, - "requires": { - "@jest/core": "^29.7.0", - "@jest/test-result": "^29.7.0", - "@jest/types": "^29.6.3", - "chalk": "^4.0.0", - "create-jest": "^29.7.0", - "exit": "^0.1.2", - "import-local": "^3.0.2", - "jest-config": "^29.7.0", - "jest-util": "^29.7.0", - "jest-validate": "^29.7.0", - "yargs": "^17.3.1" - } - }, - "jest-config": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/jest-config/-/jest-config-29.7.0.tgz", - "integrity": "sha512-uXbpfeQ7R6TZBqI3/TxCU4q4ttk3u0PJeC+E0zbfSoSjq6bJ7buBPxzQPL0ifrkY4DNu4JUdk0ImlBUYi840eQ==", - "dev": true, - "requires": { - "@babel/core": "^7.11.6", - "@jest/test-sequencer": "^29.7.0", - "@jest/types": "^29.6.3", - "babel-jest": "^29.7.0", - "chalk": "^4.0.0", - "ci-info": "^3.2.0", - "deepmerge": "^4.2.2", - "glob": "^7.1.3", - "graceful-fs": "^4.2.9", - "jest-circus": "^29.7.0", - "jest-environment-node": "^29.7.0", - "jest-get-type": "^29.6.3", - "jest-regex-util": "^29.6.3", - "jest-resolve": "^29.7.0", - "jest-runner": "^29.7.0", - "jest-util": "^29.7.0", - "jest-validate": "^29.7.0", - "micromatch": "^4.0.4", - "parse-json": "^5.2.0", - "pretty-format": "^29.7.0", - "slash": "^3.0.0", - "strip-json-comments": "^3.1.1" - } - }, - "jest-diff": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/jest-diff/-/jest-diff-29.7.0.tgz", - "integrity": "sha512-LMIgiIrhigmPrs03JHpxUh2yISK3vLFPkAodPeo0+BuF7wA2FoQbkEg1u8gBYBThncu7e1oEDUfIXVuTqLRUjw==", - "dev": true, - "requires": { - "chalk": "^4.0.0", - "diff-sequences": "^29.6.3", - "jest-get-type": "^29.6.3", - "pretty-format": "^29.7.0" - } - }, - "jest-docblock": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/jest-docblock/-/jest-docblock-29.7.0.tgz", - "integrity": "sha512-q617Auw3A612guyaFgsbFeYpNP5t2aoUNLwBUbc/0kD1R4t9ixDbyFTHd1nok4epoVFpr7PmeWHrhvuV3XaJ4g==", - "dev": true, - "requires": { - "detect-newline": "^3.0.0" - } - }, - "jest-each": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/jest-each/-/jest-each-29.7.0.tgz", - "integrity": "sha512-gns+Er14+ZrEoC5fhOfYCY1LOHHr0TI+rQUHZS8Ttw2l7gl+80eHc/gFf2Ktkw0+SIACDTeWvpFcv3B04VembQ==", - "dev": true, - "requires": { - "@jest/types": "^29.6.3", - "chalk": "^4.0.0", - "jest-get-type": "^29.6.3", - "jest-util": "^29.7.0", - "pretty-format": "^29.7.0" - } - }, - "jest-environment-node": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/jest-environment-node/-/jest-environment-node-29.7.0.tgz", - "integrity": "sha512-DOSwCRqXirTOyheM+4d5YZOrWcdu0LNZ87ewUoywbcb2XR4wKgqiG8vNeYwhjFMbEkfju7wx2GYH0P2gevGvFw==", - "dev": true, - "requires": { - "@jest/environment": "^29.7.0", - "@jest/fake-timers": "^29.7.0", - "@jest/types": "^29.6.3", - "@types/node": "*", - "jest-mock": "^29.7.0", - "jest-util": "^29.7.0" - } - }, - "jest-get-type": { - "version": "29.6.3", - "resolved": "https://registry.npmjs.org/jest-get-type/-/jest-get-type-29.6.3.tgz", - "integrity": "sha512-zrteXnqYxfQh7l5FHyL38jL39di8H8rHoecLH3JNxH3BwOrBsNeabdap5e0I23lD4HHI8W5VFBZqG4Eaq5LNcw==", - "dev": true - }, - "jest-haste-map": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/jest-haste-map/-/jest-haste-map-29.7.0.tgz", - "integrity": "sha512-fP8u2pyfqx0K1rGn1R9pyE0/KTn+G7PxktWidOBTqFPLYX0b9ksaMFkhK5vrS3DVun09pckLdlx90QthlW7AmA==", - "dev": true, - "requires": { - "@jest/types": "^29.6.3", - "@types/graceful-fs": "^4.1.3", - "@types/node": "*", - "anymatch": "^3.0.3", - "fb-watchman": "^2.0.0", - "fsevents": "^2.3.2", - "graceful-fs": "^4.2.9", - "jest-regex-util": "^29.6.3", - "jest-util": "^29.7.0", - "jest-worker": "^29.7.0", - "micromatch": "^4.0.4", - "walker": "^1.0.8" - } - }, - "jest-leak-detector": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/jest-leak-detector/-/jest-leak-detector-29.7.0.tgz", - "integrity": "sha512-kYA8IJcSYtST2BY9I+SMC32nDpBT3J2NvWJx8+JCuCdl/CR1I4EKUJROiP8XtCcxqgTTBGJNdbB1A8XRKbTetw==", - "dev": true, - "requires": { - "jest-get-type": "^29.6.3", - "pretty-format": "^29.7.0" - } - }, - "jest-matcher-utils": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/jest-matcher-utils/-/jest-matcher-utils-29.7.0.tgz", - "integrity": "sha512-sBkD+Xi9DtcChsI3L3u0+N0opgPYnCRPtGcQYrgXmR+hmt/fYfWAL0xRXYU8eWOdfuLgBe0YCW3AFtnRLagq/g==", - "dev": true, - "requires": { - "chalk": "^4.0.0", - "jest-diff": "^29.7.0", - "jest-get-type": "^29.6.3", - "pretty-format": "^29.7.0" - } - }, - "jest-message-util": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/jest-message-util/-/jest-message-util-29.7.0.tgz", - "integrity": "sha512-GBEV4GRADeP+qtB2+6u61stea8mGcOT4mCtrYISZwfu9/ISHFJ/5zOMXYbpBE9RsS5+Gb63DW4FgmnKJ79Kf6w==", - "dev": true, - "requires": { - "@babel/code-frame": "^7.12.13", - "@jest/types": "^29.6.3", - "@types/stack-utils": "^2.0.0", - "chalk": "^4.0.0", - "graceful-fs": "^4.2.9", - "micromatch": "^4.0.4", - "pretty-format": "^29.7.0", - "slash": "^3.0.0", - "stack-utils": "^2.0.3" - } - }, - "jest-mock": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/jest-mock/-/jest-mock-29.7.0.tgz", - "integrity": "sha512-ITOMZn+UkYS4ZFh83xYAOzWStloNzJFO2s8DWrE4lhtGD+AorgnbkiKERe4wQVBydIGPx059g6riW5Btp6Llnw==", - "dev": true, - "requires": { - "@jest/types": "^29.6.3", - "@types/node": "*", - "jest-util": "^29.7.0" - } - }, - "jest-pnp-resolver": { - "version": "1.2.3", - "resolved": "https://registry.npmjs.org/jest-pnp-resolver/-/jest-pnp-resolver-1.2.3.tgz", - "integrity": "sha512-+3NpwQEnRoIBtx4fyhblQDPgJI0H1IEIkX7ShLUjPGA7TtUTvI1oiKi3SR4oBR0hQhQR80l4WAe5RrXBwWMA8w==", - "dev": true, - "requires": {} - }, - "jest-regex-util": { - "version": "29.6.3", - "resolved": "https://registry.npmjs.org/jest-regex-util/-/jest-regex-util-29.6.3.tgz", - "integrity": "sha512-KJJBsRCyyLNWCNBOvZyRDnAIfUiRJ8v+hOBQYGn8gDyF3UegwiP4gwRR3/SDa42g1YbVycTidUF3rKjyLFDWbg==", - "dev": true - }, - "jest-resolve": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/jest-resolve/-/jest-resolve-29.7.0.tgz", - "integrity": "sha512-IOVhZSrg+UvVAshDSDtHyFCCBUl/Q3AAJv8iZ6ZjnZ74xzvwuzLXid9IIIPgTnY62SJjfuupMKZsZQRsCvxEgA==", - "dev": true, - "requires": { - "chalk": "^4.0.0", - "graceful-fs": "^4.2.9", - "jest-haste-map": "^29.7.0", - "jest-pnp-resolver": "^1.2.2", - "jest-util": "^29.7.0", - "jest-validate": "^29.7.0", - "resolve": "^1.20.0", - "resolve.exports": "^2.0.0", - "slash": "^3.0.0" - } - }, - "jest-resolve-dependencies": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/jest-resolve-dependencies/-/jest-resolve-dependencies-29.7.0.tgz", - "integrity": "sha512-un0zD/6qxJ+S0et7WxeI3H5XSe9lTBBR7bOHCHXkKR6luG5mwDDlIzVQ0V5cZCuoTgEdcdwzTghYkTWfubi+nA==", - "dev": true, - "requires": { - "jest-regex-util": "^29.6.3", - "jest-snapshot": "^29.7.0" - } - }, - "jest-runner": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/jest-runner/-/jest-runner-29.7.0.tgz", - "integrity": "sha512-fsc4N6cPCAahybGBfTRcq5wFR6fpLznMg47sY5aDpsoejOcVYFb07AHuSnR0liMcPTgBsA3ZJL6kFOjPdoNipQ==", - "dev": true, - "requires": { - "@jest/console": "^29.7.0", - "@jest/environment": "^29.7.0", - "@jest/test-result": "^29.7.0", - "@jest/transform": "^29.7.0", - "@jest/types": "^29.6.3", - "@types/node": "*", - "chalk": "^4.0.0", - "emittery": "^0.13.1", - "graceful-fs": "^4.2.9", - "jest-docblock": "^29.7.0", - "jest-environment-node": "^29.7.0", - "jest-haste-map": "^29.7.0", - "jest-leak-detector": "^29.7.0", - "jest-message-util": "^29.7.0", - "jest-resolve": "^29.7.0", - "jest-runtime": "^29.7.0", - "jest-util": "^29.7.0", - "jest-watcher": "^29.7.0", - "jest-worker": "^29.7.0", - "p-limit": "^3.1.0", - "source-map-support": "0.5.13" - } - }, - "jest-runtime": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/jest-runtime/-/jest-runtime-29.7.0.tgz", - "integrity": "sha512-gUnLjgwdGqW7B4LvOIkbKs9WGbn+QLqRQQ9juC6HndeDiezIwhDP+mhMwHWCEcfQ5RUXa6OPnFF8BJh5xegwwQ==", - "dev": true, - "requires": { - "@jest/environment": "^29.7.0", - "@jest/fake-timers": "^29.7.0", - "@jest/globals": "^29.7.0", - "@jest/source-map": "^29.6.3", - "@jest/test-result": "^29.7.0", - "@jest/transform": "^29.7.0", - "@jest/types": "^29.6.3", - "@types/node": "*", - "chalk": "^4.0.0", - "cjs-module-lexer": "^1.0.0", - "collect-v8-coverage": "^1.0.0", - "glob": "^7.1.3", - "graceful-fs": "^4.2.9", - "jest-haste-map": "^29.7.0", - "jest-message-util": "^29.7.0", - "jest-mock": "^29.7.0", - "jest-regex-util": "^29.6.3", - "jest-resolve": "^29.7.0", - "jest-snapshot": "^29.7.0", - "jest-util": "^29.7.0", - "slash": "^3.0.0", - "strip-bom": "^4.0.0" - } - }, - "jest-snapshot": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/jest-snapshot/-/jest-snapshot-29.7.0.tgz", - "integrity": "sha512-Rm0BMWtxBcioHr1/OX5YCP8Uov4riHvKPknOGs804Zg9JGZgmIBkbtlxJC/7Z4msKYVbIJtfU+tKb8xlYNfdkw==", - "dev": true, - "requires": { - "@babel/core": "^7.11.6", - "@babel/generator": "^7.7.2", - "@babel/plugin-syntax-jsx": "^7.7.2", - "@babel/plugin-syntax-typescript": "^7.7.2", - "@babel/types": "^7.3.3", - "@jest/expect-utils": "^29.7.0", - "@jest/transform": "^29.7.0", - "@jest/types": "^29.6.3", - "babel-preset-current-node-syntax": "^1.0.0", - "chalk": "^4.0.0", - "expect": "^29.7.0", - "graceful-fs": "^4.2.9", - "jest-diff": "^29.7.0", - "jest-get-type": "^29.6.3", - "jest-matcher-utils": "^29.7.0", - "jest-message-util": "^29.7.0", - "jest-util": "^29.7.0", - "natural-compare": "^1.4.0", - "pretty-format": "^29.7.0", - "semver": "^7.5.3" - }, - "dependencies": { - "semver": { - "version": "7.6.3", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.3.tgz", - "integrity": "sha512-oVekP1cKtI+CTDvHWYFUcMtsK/00wmAEfyqKfNdARm8u1wNVhSgaX7A8d4UuIlUI5e84iEwOhs7ZPYRmzU9U6A==", - "dev": true - } - } - }, - "jest-util": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/jest-util/-/jest-util-29.7.0.tgz", - "integrity": "sha512-z6EbKajIpqGKU56y5KBUgy1dt1ihhQJgWzUlZHArA/+X2ad7Cb5iF+AK1EWVL/Bo7Rz9uurpqw6SiBCefUbCGA==", - "dev": true, - "requires": { - "@jest/types": "^29.6.3", - "@types/node": "*", - "chalk": "^4.0.0", - "ci-info": "^3.2.0", - "graceful-fs": "^4.2.9", - "picomatch": "^2.2.3" - } - }, - "jest-validate": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/jest-validate/-/jest-validate-29.7.0.tgz", - "integrity": "sha512-ZB7wHqaRGVw/9hST/OuFUReG7M8vKeq0/J2egIGLdvjHCmYqGARhzXmtgi+gVeZ5uXFF219aOc3Ls2yLg27tkw==", - "dev": true, - "requires": { - "@jest/types": "^29.6.3", - "camelcase": "^6.2.0", - "chalk": "^4.0.0", - "jest-get-type": "^29.6.3", - "leven": "^3.1.0", - "pretty-format": "^29.7.0" - }, - "dependencies": { - "camelcase": { - "version": "6.3.0", - "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-6.3.0.tgz", - "integrity": "sha512-Gmy6FhYlCY7uOElZUSbxo2UCDH8owEk996gkbrpsgGtrJLM3J7jGxl9Ic7Qwwj4ivOE5AWZWRMecDdF7hqGjFA==", - "dev": true - } - } - }, - "jest-watcher": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/jest-watcher/-/jest-watcher-29.7.0.tgz", - "integrity": "sha512-49Fg7WXkU3Vl2h6LbLtMQ/HyB6rXSIX7SqvBLQmssRBGN9I0PNvPmAmCWSOY6SOvrjhI/F7/bGAv9RtnsPA03g==", - "dev": true, - "requires": { - "@jest/test-result": "^29.7.0", - "@jest/types": "^29.6.3", - "@types/node": "*", - "ansi-escapes": "^4.2.1", - "chalk": "^4.0.0", - "emittery": "^0.13.1", - "jest-util": "^29.7.0", - "string-length": "^4.0.1" - } - }, - "jest-worker": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/jest-worker/-/jest-worker-29.7.0.tgz", - "integrity": "sha512-eIz2msL/EzL9UFTFFx7jBTkeZfku0yUAyZZZmJ93H2TYEiroIx2PQjEXcwYtYl8zXCxb+PAmA2hLIt/6ZEkPHw==", - "dev": true, - "requires": { - "@types/node": "*", - "jest-util": "^29.7.0", - "merge-stream": "^2.0.0", - "supports-color": "^8.0.0" - }, - "dependencies": { - "supports-color": { - "version": "8.1.1", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-8.1.1.tgz", - "integrity": "sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==", - "dev": true, - "requires": { - "has-flag": "^4.0.0" - } - } - } - }, - "js-tokens": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", - "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==", - "dev": true - }, - "js-yaml": { - "version": "3.14.1", - "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.14.1.tgz", - "integrity": "sha512-okMH7OXXJ7YrN9Ok3/SXrnu4iX9yOk+25nqX4imS2npuvTYDmo/QEZoqwZkYaIDk3jVvBOTOIEgEhaLOynBS9g==", - "dev": true, - "requires": { - "argparse": "^1.0.7", - "esprima": "^4.0.0" - } - }, - "jsesc": { - "version": "2.5.2", - "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-2.5.2.tgz", - "integrity": "sha512-OYu7XEzjkCQ3C5Ps3QIZsQfNpqoJyZZA99wd9aWd05NCtC5pWOkShK2mkL6HXQR6/Cy2lbNdPlZBpuQHXE63gA==", - "dev": true - }, - "json-parse-better-errors": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/json-parse-better-errors/-/json-parse-better-errors-1.0.2.tgz", - "integrity": "sha512-mrqyZKfX5EhL7hvqcV6WG1yYjnjeuYDzDhhcAAUrq8Po85NBQBJP+ZDUT75qZQ98IkUoBqdkExkukOU7Ts2wrw==", - "dev": true - }, - "json-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", - "integrity": "sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w==", - "dev": true - }, - "json-schema-traverse": { - "version": "0.4.1", - "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", - "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", - "dev": true - }, - "json-stable-stringify-without-jsonify": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz", - "integrity": "sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw==", - "dev": true - }, - "json-stringify-safe": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz", - "integrity": "sha1-Epai1Y/UXxmg9s4B1lcB4sc1tus=", - "dev": true - }, - "json5": { - "version": "2.2.3", - "resolved": "https://registry.npmjs.org/json5/-/json5-2.2.3.tgz", - "integrity": "sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg==", - "dev": true - }, - "jsx-ast-utils": { - "version": "3.3.3", - "resolved": "https://registry.npmjs.org/jsx-ast-utils/-/jsx-ast-utils-3.3.3.tgz", - "integrity": "sha512-fYQHZTZ8jSfmWZ0iyzfwiU4WDX4HpHbMCZ3gPlWYiCl3BoeOTsqKBqnTVfH2rYT7eP5c3sVbeSPHnnJOaTrWiw==", - "dev": true, - "requires": { - "array-includes": "^3.1.5", - "object.assign": "^4.1.3" - } - }, - "kleur": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/kleur/-/kleur-3.0.3.tgz", - "integrity": "sha512-eTIzlVOSUR+JxdDFepEYcBMtZ9Qqdef+rnzWdRZuMbOywu5tO2w2N7rqjoANZ5k9vywhL6Br1VRjUIgTQx4E8w==", - "dev": true - }, - "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==", - "dev": true - }, - "levn": { - "version": "0.4.1", - "resolved": "https://registry.npmjs.org/levn/-/levn-0.4.1.tgz", - "integrity": "sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==", - "dev": true, - "requires": { - "prelude-ls": "^1.2.1", - "type-check": "~0.4.0" - } - }, - "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 - }, - "load-json-file": { - "version": "5.3.0", - "resolved": "https://registry.npmjs.org/load-json-file/-/load-json-file-5.3.0.tgz", - "integrity": "sha512-cJGP40Jc/VXUsp8/OrnyKyTZ1y6v/dphm3bioS+RrKXjK2BB6wHUd6JptZEFDGgGahMT+InnZO5i1Ei9mpC8Bw==", - "dev": true, - "requires": { - "graceful-fs": "^4.1.15", - "parse-json": "^4.0.0", - "pify": "^4.0.1", - "strip-bom": "^3.0.0", - "type-fest": "^0.3.0" - }, - "dependencies": { - "parse-json": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-4.0.0.tgz", - "integrity": "sha512-aOIos8bujGN93/8Ox/jPLh7RwVnPEysynVFE+fQZyg6jKELEHwzgKdLRFHUgXJL6kylijVSBC4BvN9OmsB48Rw==", - "dev": true, - "requires": { - "error-ex": "^1.3.1", - "json-parse-better-errors": "^1.0.1" - } - }, - "strip-bom": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-3.0.0.tgz", - "integrity": "sha512-vavAMRXOgBVNF6nyEEmL3DBK19iRpDcoIwW+swQ+CbGiu7lju6t+JklA1MHweoWtadgt4ISVUsXLyDq34ddcwA==", - "dev": true - }, - "type-fest": { - "version": "0.3.1", - "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.3.1.tgz", - "integrity": "sha512-cUGJnCdr4STbePCgqNFbpVNCepa+kAVohJs1sLhxzdH+gnEoOd8VhbYa7pD3zZYGiURWM2xzEII3fQcRizDkYQ==", - "dev": true - } - } - }, - "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, - "requires": { - "p-locate": "^4.1.0" - } - }, - "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 - }, - "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, - "requires": { - "js-tokens": "^3.0.0 || ^4.0.0" - } - }, - "lru-cache": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", - "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", - "dev": true, - "requires": { - "yallist": "^4.0.0" - } - }, - "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, - "requires": { - "semver": "^7.5.3" - }, - "dependencies": { - "semver": { - "version": "7.6.3", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.3.tgz", - "integrity": "sha512-oVekP1cKtI+CTDvHWYFUcMtsK/00wmAEfyqKfNdARm8u1wNVhSgaX7A8d4UuIlUI5e84iEwOhs7ZPYRmzU9U6A==", - "dev": true - } - } - }, - "makeerror": { - "version": "1.0.12", - "resolved": "https://registry.npmjs.org/makeerror/-/makeerror-1.0.12.tgz", - "integrity": "sha512-JmqCvUhmt43madlpFzG4BQzG2Z3m6tvQDNKdClZnO3VbIudJYmxsT0FNJMeiB2+JTSlTQTSbU8QdesVmwJcmLg==", - "dev": true, - "requires": { - "tmpl": "1.0.5" - } - }, - "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 - }, - "micromatch": { - "version": "4.0.7", - "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.7.tgz", - "integrity": "sha512-LPP/3KorzCwBxfeUuZmaR6bG2kdeHSbe0P2tY3FLRU4vYrjYz5hI4QZwV0njUx3jeuKe67YukQ1LSPZBKDqO/Q==", - "dev": true, - "requires": { - "braces": "^3.0.3", - "picomatch": "^2.3.1" - } - }, - "mime-db": { - "version": "1.52.0", - "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz", - "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==" - }, - "mime-types": { - "version": "2.1.35", - "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz", - "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==", - "requires": { - "mime-db": "1.52.0" - } - }, - "mimic-fn": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-2.1.0.tgz", - "integrity": "sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==", - "dev": true - }, - "minimatch": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", - "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", - "dev": true, - "requires": { - "brace-expansion": "^1.1.7" - } - }, - "minimist": { - "version": "1.2.7", - "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.7.tgz", - "integrity": "sha512-bzfL1YUZsP41gmu/qjrEk0Q6i2ix/cVeAhbCbqH9u3zYutS1cLg00qhrD0M2MVdCcx4Sc0UpP2eBWo9rotpq6g==", - "dev": true - }, - "ms": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", - "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", - "dev": true - }, - "natural-compare": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz", - "integrity": "sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==", - "dev": true - }, - "nock": { - "version": "13.5.4", - "resolved": "https://registry.npmjs.org/nock/-/nock-13.5.4.tgz", - "integrity": "sha512-yAyTfdeNJGGBFxWdzSKCBYxs5FxLbCg5X5Q4ets974hcQzG1+qCxvIyOo4j2Ry6MUlhWVMX4OoYDefAIIwupjw==", - "dev": true, - "requires": { - "debug": "^4.1.0", - "json-stringify-safe": "^5.0.1", - "propagate": "^2.0.0" - } - }, - "node-abort-controller": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/node-abort-controller/-/node-abort-controller-3.1.1.tgz", - "integrity": "sha512-AGK2yQKIjRuqnc6VkX2Xj5d+QW8xZ87pa1UK6yA6ouUyuxfHuMP6umE5QK7UmTeOAymo+Zx1Fxiuw9rVx8taHQ==" - }, - "node-int64": { - "version": "0.4.0", - "resolved": "https://registry.npmjs.org/node-int64/-/node-int64-0.4.0.tgz", - "integrity": "sha512-O5lz91xSOeoXP6DulyHfllpq+Eg00MWitZIbtPfoSEvqIHdl5gfcY6hYzDWnj0qD5tz52PI08u9qUvSVeUBeHw==", - "dev": true - }, - "node-releases": { - "version": "2.0.18", - "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.18.tgz", - "integrity": "sha512-d9VeXT4SJ7ZeOqGX6R5EM022wpL+eWPooLI+5UpWn2jCT1aosUQEhQP214x33Wkwx3JQMvIm+tIoVOdodFS40g==", - "dev": true - }, - "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 - }, - "npm-run-path": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-4.0.1.tgz", - "integrity": "sha512-S48WzZW777zhNIrn7gxOlISNAqi9ZC/uQFnRdbeIHhZhCA6UqpkOT8T1G7BvfdgP4Er8gF4sUbaS0i7QvIfCWw==", - "dev": true, - "requires": { - "path-key": "^3.0.0" - } - }, - "object-assign": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", - "integrity": "sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==", - "dev": true - }, - "object-inspect": { - "version": "1.13.1", - "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.13.1.tgz", - "integrity": "sha512-5qoj1RUiKOMsCCNLV1CBiPYE10sziTsnmNxkAI/rZhiD63CF7IqdFGC/XzjWjpSgLf0LxXX3bDFIh0E18f6UhQ==" - }, - "object-keys": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.1.1.tgz", - "integrity": "sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==", - "dev": true - }, - "object.assign": { - "version": "4.1.4", - "resolved": "https://registry.npmjs.org/object.assign/-/object.assign-4.1.4.tgz", - "integrity": "sha512-1mxKf0e58bvyjSCtKYY4sRe9itRk3PJpquJOjeIkz885CczcI4IvJJDLPS72oowuSh+pBxUFROpX+TU++hxhZQ==", - "dev": true, - "requires": { - "call-bind": "^1.0.2", - "define-properties": "^1.1.4", - "has-symbols": "^1.0.3", - "object-keys": "^1.1.1" - } - }, - "object.entries": { - "version": "1.1.7", - "resolved": "https://registry.npmjs.org/object.entries/-/object.entries-1.1.7.tgz", - "integrity": "sha512-jCBs/0plmPsOnrKAfFQXRG2NFjlhZgjjcBLSmTnEhU8U6vVTsVe8ANeQJCHTl3gSsI4J+0emOoCgoKlmQPMgmA==", - "dev": true, - "requires": { - "call-bind": "^1.0.2", - "define-properties": "^1.2.0", - "es-abstract": "^1.22.1" - } - }, - "object.fromentries": { - "version": "2.0.7", - "resolved": "https://registry.npmjs.org/object.fromentries/-/object.fromentries-2.0.7.tgz", - "integrity": "sha512-UPbPHML6sL8PI/mOqPwsH4G6iyXcCGzLin8KvEPenOZN5lpCNBZZQ+V62vdjB1mQHrmqGQt5/OJzemUA+KJmEA==", - "dev": true, - "requires": { - "call-bind": "^1.0.2", - "define-properties": "^1.2.0", - "es-abstract": "^1.22.1" - } - }, - "object.groupby": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/object.groupby/-/object.groupby-1.0.1.tgz", - "integrity": "sha512-HqaQtqLnp/8Bn4GL16cj+CUYbnpe1bh0TtEaWvybszDG4tgxCJuRpV8VGuvNaI1fAnI4lUJzDG55MXcOH4JZcQ==", - "dev": true, - "requires": { - "call-bind": "^1.0.2", - "define-properties": "^1.2.0", - "es-abstract": "^1.22.1", - "get-intrinsic": "^1.2.1" - } - }, - "object.hasown": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/object.hasown/-/object.hasown-1.1.3.tgz", - "integrity": "sha512-fFI4VcYpRHvSLXxP7yiZOMAd331cPfd2p7PFDVbgUsYOfCT3tICVqXWngbjr4m49OvsBwUBQ6O2uQoJvy3RexA==", - "dev": true, - "requires": { - "define-properties": "^1.2.0", - "es-abstract": "^1.22.1" - } - }, - "object.values": { - "version": "1.1.7", - "resolved": "https://registry.npmjs.org/object.values/-/object.values-1.1.7.tgz", - "integrity": "sha512-aU6xnDFYT3x17e/f0IiiwlGPTy2jzMySGfUB4fq6z7CV8l85CWHDk5ErhyhpfDHhrOMwGFhSQkhMGHaIotA6Ng==", - "dev": true, - "requires": { - "call-bind": "^1.0.2", - "define-properties": "^1.2.0", - "es-abstract": "^1.22.1" - } - }, - "once": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", - "integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==", - "dev": true, - "requires": { - "wrappy": "1" - } - }, - "onetime": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/onetime/-/onetime-5.1.2.tgz", - "integrity": "sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg==", - "dev": true, - "requires": { - "mimic-fn": "^2.1.0" - } - }, - "optionator": { - "version": "0.9.3", - "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.9.3.tgz", - "integrity": "sha512-JjCoypp+jKn1ttEFExxhetCKeJt9zhAgAve5FXHixTvFDW/5aEktX9bufBKLRRMdU7bNtpLfcGu94B3cdEJgjg==", - "dev": true, - "requires": { - "@aashutoshrathi/word-wrap": "^1.2.3", - "deep-is": "^0.1.3", - "fast-levenshtein": "^2.0.6", - "levn": "^0.4.1", - "prelude-ls": "^1.2.1", - "type-check": "^0.4.0" - } - }, - "p-limit": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz", - "integrity": "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==", - "dev": true, - "requires": { - "yocto-queue": "^0.1.0" - } - }, - "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, - "requires": { - "p-limit": "^2.2.0" - }, - "dependencies": { - "p-limit": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", - "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", - "dev": true, - "requires": { - "p-try": "^2.0.0" - } - } - } - }, - "p-try": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz", - "integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==", - "dev": true - }, - "parent-module": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz", - "integrity": "sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==", - "dev": true, - "requires": { - "callsites": "^3.0.0" - } - }, - "parse-json": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-5.2.0.tgz", - "integrity": "sha512-ayCKvm/phCGxOkYRSCM82iDwct8/EonSEgCSxWxD7ve6jHggsFl4fZVQBPRNgQoKiuV/odhFrGzQXZwbifC8Rg==", - "dev": true, - "requires": { - "@babel/code-frame": "^7.0.0", - "error-ex": "^1.3.1", - "json-parse-even-better-errors": "^2.3.0", - "lines-and-columns": "^1.1.6" - } - }, - "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 - }, - "path-is-absolute": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", - "integrity": "sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==", - "dev": true - }, - "path-key": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", - "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==", - "dev": true - }, - "path-parse": { - "version": "1.0.7", - "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz", - "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==", - "dev": true - }, - "picocolors": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.0.1.tgz", - "integrity": "sha512-anP1Z8qwhkbmu7MFP5iTt+wQKXgwzf7zTyGlcdzabySa9vd0Xt392U0rVmz9poOaBj0uHJKyyo9/upk0HrEQew==", - "dev": true - }, - "picomatch": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", - "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==", - "dev": true - }, - "pify": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/pify/-/pify-4.0.1.tgz", - "integrity": "sha512-uB80kBFb/tfd68bVleG9T5GGsGPjJrLAUpR5PZIrhBnIaRTQRjqdJSsIKkOP6OAIFbj7GOrcudc5pNjZ+geV2g==", - "dev": true - }, - "pirates": { - "version": "4.0.6", - "resolved": "https://registry.npmjs.org/pirates/-/pirates-4.0.6.tgz", - "integrity": "sha512-saLsH7WeYYPiD25LDuLRRY/i+6HaPYr6G1OUlN39otzkSTxKnubR9RTxS3/Kk50s1g2JTgFwWQDQyplC5/SHZg==", - "dev": true - }, - "pkg-conf": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/pkg-conf/-/pkg-conf-3.1.0.tgz", - "integrity": "sha512-m0OTbR/5VPNPqO1ph6Fqbj7Hv6QU7gR/tQW40ZqrL1rjgCU85W6C1bJn0BItuJqnR98PWzw7Z8hHeChD1WrgdQ==", - "dev": true, - "requires": { - "find-up": "^3.0.0", - "load-json-file": "^5.2.0" - }, - "dependencies": { - "find-up": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/find-up/-/find-up-3.0.0.tgz", - "integrity": "sha512-1yD6RmLI1XBfxugvORwlck6f75tYL+iR0jqwsOrOxMZyGYqUuDhJ0l4AXdO1iX/FTs9cBAMEk1gWSEx1kSbylg==", - "dev": true, - "requires": { - "locate-path": "^3.0.0" - } - }, - "locate-path": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-3.0.0.tgz", - "integrity": "sha512-7AO748wWnIhNqAuaty2ZWHkQHRSNfPVIsPIfwEOWO22AmaoVrWavlOcMR5nzTLNYvp36X220/maaRsrec1G65A==", - "dev": true, - "requires": { - "p-locate": "^3.0.0", - "path-exists": "^3.0.0" - } - }, - "p-limit": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", - "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", - "dev": true, - "requires": { - "p-try": "^2.0.0" - } - }, - "p-locate": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-3.0.0.tgz", - "integrity": "sha512-x+12w/To+4GFfgJhBEpiDcLozRJGegY+Ei7/z0tSLkMmxGZNybVMSfWj9aJn8Z5Fc7dBUNJOOVgPv2H7IwulSQ==", - "dev": true, - "requires": { - "p-limit": "^2.0.0" - } - }, - "path-exists": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-3.0.0.tgz", - "integrity": "sha512-bpC7GYwiDYQ4wYLe+FA8lhRjhQCMcQGuSgGGqDkg/QerRWw9CmGRT0iSOVRSZJ29NMLZgIzqaljJ63oaL4NIJQ==", - "dev": true - } - } - }, - "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==", - "dev": true, - "requires": { - "find-up": "^4.0.0" - } - }, - "prelude-ls": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.2.1.tgz", - "integrity": "sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==", - "dev": true - }, - "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, - "requires": { - "@jest/schemas": "^29.6.3", - "ansi-styles": "^5.0.0", - "react-is": "^18.0.0" - }, - "dependencies": { - "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 - } - } - }, - "prompts": { - "version": "2.4.2", - "resolved": "https://registry.npmjs.org/prompts/-/prompts-2.4.2.tgz", - "integrity": "sha512-NxNv/kLguCA7p3jE8oL2aEBsrJWgAakBpgmgK6lpPWV+WuOmY6r2/zbAVnP+T8bQlA0nzHXSJSJW0Hq7ylaD2Q==", - "dev": true, - "requires": { - "kleur": "^3.0.3", - "sisteransi": "^1.0.5" - } - }, - "prop-types": { - "version": "15.8.1", - "resolved": "https://registry.npmjs.org/prop-types/-/prop-types-15.8.1.tgz", - "integrity": "sha512-oj87CgZICdulUohogVAR7AjlC0327U4el4L6eAvOqCeudMDVU0NThNaV+b9Df4dXgSP1gXMTnPdhfe/2qDH5cg==", - "dev": true, - "requires": { - "loose-envify": "^1.4.0", - "object-assign": "^4.1.1", - "react-is": "^16.13.1" - }, - "dependencies": { - "react-is": { - "version": "16.13.1", - "resolved": "https://registry.npmjs.org/react-is/-/react-is-16.13.1.tgz", - "integrity": "sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==", - "dev": true - } - } - }, - "propagate": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/propagate/-/propagate-2.0.1.tgz", - "integrity": "sha512-vGrhOavPSTz4QVNuBNdcNXePNdNMaO1xj9yBeH1ScQPjk/rhg9sSlCXPhMkFuaNNW/syTvYqsnbIJxMBfRbbag==", - "dev": true - }, - "proxy-from-env": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/proxy-from-env/-/proxy-from-env-1.1.0.tgz", - "integrity": "sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg==" - }, - "punycode": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.1.tgz", - "integrity": "sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==", - "dev": true - }, - "pure-rand": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/pure-rand/-/pure-rand-6.1.0.tgz", - "integrity": "sha512-bVWawvoZoBYpp6yIoQtQXHZjmz35RSVHnUOTefl8Vcjr8snTPY1wnpSPMWekcFwbxI6gtmT7rSYPFvz71ldiOA==", - "dev": true - }, - "qs": { - "version": "6.13.0", - "resolved": "https://registry.npmjs.org/qs/-/qs-6.13.0.tgz", - "integrity": "sha512-+38qI9SOr8tfZ4QmJNplMUxqjbe7LKvvZgWdExBOmd+egZTtjLB67Gu0HRX3u/XOq7UU2Nx6nsjvS16Z9uwfpg==", - "requires": { - "side-channel": "^1.0.6" - } - }, - "queue-microtask": { - "version": "1.2.3", - "resolved": "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.3.tgz", - "integrity": "sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==", - "dev": true - }, - "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 - }, - "reflect.getprototypeof": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/reflect.getprototypeof/-/reflect.getprototypeof-1.0.4.tgz", - "integrity": "sha512-ECkTw8TmJwW60lOTR+ZkODISW6RQ8+2CL3COqtiJKLd6MmB45hN51HprHFziKLGkAuTGQhBb91V8cy+KHlaCjw==", - "dev": true, - "requires": { - "call-bind": "^1.0.2", - "define-properties": "^1.2.0", - "es-abstract": "^1.22.1", - "get-intrinsic": "^1.2.1", - "globalthis": "^1.0.3", - "which-builtin-type": "^1.1.3" - } - }, - "regexp.prototype.flags": { - "version": "1.5.1", - "resolved": "https://registry.npmjs.org/regexp.prototype.flags/-/regexp.prototype.flags-1.5.1.tgz", - "integrity": "sha512-sy6TXMN+hnP/wMy+ISxg3krXx7BAtWVO4UouuCN/ziM9UEne0euamVNafDfvC83bRNr95y0V5iijeDQFUNpvrg==", - "dev": true, - "requires": { - "call-bind": "^1.0.2", - "define-properties": "^1.2.0", - "set-function-name": "^2.0.0" - } - }, - "regexpp": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/regexpp/-/regexpp-3.2.0.tgz", - "integrity": "sha512-pq2bWo9mVD43nbts2wGv17XLiNLya+GklZ8kaDLV2Z08gDCsGpnKn9BFMepvWuHCbyVvY7J5o5+BVvoQbmlJLg==", - "dev": true - }, - "require-directory": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz", - "integrity": "sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q==", - "dev": true - }, - "resolve": { - "version": "1.22.8", - "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.8.tgz", - "integrity": "sha512-oKWePCxqpd6FlLvGV1VU0x7bkPmmCNolxzjMf4NczoDnQcIWrAF+cPtZn5i6n+RfD2d9i0tzpKnG6Yk168yIyw==", - "dev": true, - "requires": { - "is-core-module": "^2.13.0", - "path-parse": "^1.0.7", - "supports-preserve-symlinks-flag": "^1.0.0" - } - }, - "resolve-cwd": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/resolve-cwd/-/resolve-cwd-3.0.0.tgz", - "integrity": "sha512-OrZaX2Mb+rJCpH/6CpSqt9xFVpN++x01XnN2ie9g6P5/3xelLAkXWVADpdz1IHD/KFfEXyE6V0U01OQ3UO2rEg==", - "dev": true, - "requires": { - "resolve-from": "^5.0.0" - } - }, - "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 - }, - "resolve.exports": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/resolve.exports/-/resolve.exports-2.0.2.tgz", - "integrity": "sha512-X2UW6Nw3n/aMgDVy+0rSqgHlv39WZAlZrXCdnbyEiKm17DSqHX4MmQMaST3FbeWR5FTuRcUwYAziZajji0Y7mg==", - "dev": true - }, - "reusify": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/reusify/-/reusify-1.0.4.tgz", - "integrity": "sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw==", - "dev": true - }, - "rimraf": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", - "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==", - "dev": true, - "requires": { - "glob": "^7.1.3" - } - }, - "run-parallel": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/run-parallel/-/run-parallel-1.2.0.tgz", - "integrity": "sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==", - "dev": true, - "requires": { - "queue-microtask": "^1.2.2" - } - }, - "safe-array-concat": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/safe-array-concat/-/safe-array-concat-1.0.1.tgz", - "integrity": "sha512-6XbUAseYE2KtOuGueyeobCySj9L4+66Tn6KQMOPQJrAJEowYKW/YR/MGJZl7FdydUdaFu4LYyDZjxf4/Nmo23Q==", - "dev": true, - "requires": { - "call-bind": "^1.0.2", - "get-intrinsic": "^1.2.1", - "has-symbols": "^1.0.3", - "isarray": "^2.0.5" - } - }, - "safe-regex-test": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/safe-regex-test/-/safe-regex-test-1.0.0.tgz", - "integrity": "sha512-JBUUzyOgEwXQY1NuPtvcj/qcBDbDmEvWufhlnXZIm75DEHp+afM1r1ujJpJsV/gSM4t59tpDyPi1sd6ZaPFfsA==", - "dev": true, - "requires": { - "call-bind": "^1.0.2", - "get-intrinsic": "^1.1.3", - "is-regex": "^1.1.4" - } - }, - "semver": { - "version": "6.3.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", - "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", - "dev": true - }, - "set-function-length": { - "version": "1.2.2", - "resolved": "https://registry.npmjs.org/set-function-length/-/set-function-length-1.2.2.tgz", - "integrity": "sha512-pgRc4hJ4/sNjWCSS9AmnS40x3bNMDTknHgL5UaMBTMyJnU90EgWh1Rz+MC9eFu4BuN/UwZjKQuY/1v3rM7HMfg==", - "requires": { - "define-data-property": "^1.1.4", - "es-errors": "^1.3.0", - "function-bind": "^1.1.2", - "get-intrinsic": "^1.2.4", - "gopd": "^1.0.1", - "has-property-descriptors": "^1.0.2" - } - }, - "set-function-name": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/set-function-name/-/set-function-name-2.0.1.tgz", - "integrity": "sha512-tMNCiqYVkXIZgc2Hnoy2IvC/f8ezc5koaRFkCjrpWzGpCd3qbZXPzVy9MAZzK1ch/X0jvSkojys3oqJN0qCmdA==", - "dev": true, - "requires": { - "define-data-property": "^1.0.1", - "functions-have-names": "^1.2.3", - "has-property-descriptors": "^1.0.0" - } - }, - "shebang-command": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", - "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", - "dev": true, - "requires": { - "shebang-regex": "^3.0.0" - } - }, - "shebang-regex": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz", - "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==", - "dev": true - }, - "side-channel": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.0.6.tgz", - "integrity": "sha512-fDW/EZ6Q9RiO8eFG8Hj+7u/oW+XrPTIChwCOM2+th2A6OblDtYYIpve9m+KvI9Z4C9qSEXlaGR6bTEYHReuglA==", - "requires": { - "call-bind": "^1.0.7", - "es-errors": "^1.3.0", - "get-intrinsic": "^1.2.4", - "object-inspect": "^1.13.1" - } - }, - "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==", - "dev": true - }, - "sisteransi": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/sisteransi/-/sisteransi-1.0.5.tgz", - "integrity": "sha512-bLGGlR1QxBcynn2d5YmDX4MGjlZvy2MRBDRNHLJ8VI6l6+9FUiyTFNJ0IveOSP0bcXgVDPRcfGqA0pjaqUpfVg==", - "dev": true - }, - "slash": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/slash/-/slash-3.0.0.tgz", - "integrity": "sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==", - "dev": true - }, - "source-map": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", - "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", - "dev": true - }, - "source-map-support": { - "version": "0.5.13", - "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.13.tgz", - "integrity": "sha512-SHSKFHadjVA5oR4PPqhtAVdcBWwRYVd6g6cAXnIbRiIwc2EhPrTuKUBdSLvlEKyIP3GCf89fltvcZiP9MMFA1w==", - "dev": true, - "requires": { - "buffer-from": "^1.0.0", - "source-map": "^0.6.0" - } - }, - "sprintf-js": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz", - "integrity": "sha512-D9cPgkvLlV3t3IzL0D0YLvGA9Ahk4PcvVwUbN0dSGr1aP0Nrt4AEnTUbuGvquEC0mA64Gqt1fzirlRs5ibXx8g==", - "dev": true - }, - "stack-utils": { - "version": "2.0.6", - "resolved": "https://registry.npmjs.org/stack-utils/-/stack-utils-2.0.6.tgz", - "integrity": "sha512-XlkWvfIm6RmsWtNJx+uqtKLS8eqFbxUg0ZzLXqY0caEy9l7hruX8IpiDnjsLavoBgqCCR71TqWO8MaXYheJ3RQ==", - "dev": true, - "requires": { - "escape-string-regexp": "^2.0.0" - } - }, - "standard": { - "version": "17.1.0", - "resolved": "https://registry.npmjs.org/standard/-/standard-17.1.0.tgz", - "integrity": "sha512-jaDqlNSzLtWYW4lvQmU0EnxWMUGQiwHasZl5ZEIwx3S/ijZDjZOzs1y1QqKwKs5vqnFpGtizo4NOYX2s0Voq/g==", - "dev": true, - "requires": { - "eslint": "^8.41.0", - "eslint-config-standard": "17.1.0", - "eslint-config-standard-jsx": "^11.0.0", - "eslint-plugin-import": "^2.27.5", - "eslint-plugin-n": "^15.7.0", - "eslint-plugin-promise": "^6.1.1", - "eslint-plugin-react": "^7.32.2", - "standard-engine": "^15.0.0", - "version-guard": "^1.1.1" - } - }, - "standard-engine": { - "version": "15.0.0", - "resolved": "https://registry.npmjs.org/standard-engine/-/standard-engine-15.0.0.tgz", - "integrity": "sha512-4xwUhJNo1g/L2cleysUqUv7/btn7GEbYJvmgKrQ2vd/8pkTmN8cpqAZg+BT8Z1hNeEH787iWUdOpL8fmApLtxA==", - "dev": true, - "requires": { - "get-stdin": "^8.0.0", - "minimist": "^1.2.6", - "pkg-conf": "^3.1.0", - "xdg-basedir": "^4.0.0" - } - }, - "string-length": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/string-length/-/string-length-4.0.2.tgz", - "integrity": "sha512-+l6rNN5fYHNhZZy41RXsYptCjA2Igmq4EG7kZAYFQI1E1VTXarr6ZPXBg6eq7Y6eK4FEhY6AJlyuFIb/v/S0VQ==", - "dev": true, - "requires": { - "char-regex": "^1.0.2", - "strip-ansi": "^6.0.0" - } - }, - "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, - "requires": { - "emoji-regex": "^8.0.0", - "is-fullwidth-code-point": "^3.0.0", - "strip-ansi": "^6.0.1" - } - }, - "string.prototype.matchall": { - "version": "4.0.10", - "resolved": "https://registry.npmjs.org/string.prototype.matchall/-/string.prototype.matchall-4.0.10.tgz", - "integrity": "sha512-rGXbGmOEosIQi6Qva94HUjgPs9vKW+dkG7Y8Q5O2OYkWL6wFaTRZO8zM4mhP94uX55wgyrXzfS2aGtGzUL7EJQ==", - "dev": true, - "requires": { - "call-bind": "^1.0.2", - "define-properties": "^1.2.0", - "es-abstract": "^1.22.1", - "get-intrinsic": "^1.2.1", - "has-symbols": "^1.0.3", - "internal-slot": "^1.0.5", - "regexp.prototype.flags": "^1.5.0", - "set-function-name": "^2.0.0", - "side-channel": "^1.0.4" - } - }, - "string.prototype.trim": { - "version": "1.2.8", - "resolved": "https://registry.npmjs.org/string.prototype.trim/-/string.prototype.trim-1.2.8.tgz", - "integrity": "sha512-lfjY4HcixfQXOfaqCvcBuOIapyaroTXhbkfJN3gcB1OtyupngWK4sEET9Knd0cXd28kTUqu/kHoV4HKSJdnjiQ==", - "dev": true, - "requires": { - "call-bind": "^1.0.2", - "define-properties": "^1.2.0", - "es-abstract": "^1.22.1" - } - }, - "string.prototype.trimend": { - "version": "1.0.7", - "resolved": "https://registry.npmjs.org/string.prototype.trimend/-/string.prototype.trimend-1.0.7.tgz", - "integrity": "sha512-Ni79DqeB72ZFq1uH/L6zJ+DKZTkOtPIHovb3YZHQViE+HDouuU4mBrLOLDn5Dde3RF8qw5qVETEjhu9locMLvA==", - "dev": true, - "requires": { - "call-bind": "^1.0.2", - "define-properties": "^1.2.0", - "es-abstract": "^1.22.1" - } - }, - "string.prototype.trimstart": { - "version": "1.0.7", - "resolved": "https://registry.npmjs.org/string.prototype.trimstart/-/string.prototype.trimstart-1.0.7.tgz", - "integrity": "sha512-NGhtDFu3jCEm7B4Fy0DpLewdJQOZcQ0rGbwQ/+stjnrp2i+rlKeCvos9hOIeCmqwratM47OBxY7uFZzjxHXmrg==", - "dev": true, - "requires": { - "call-bind": "^1.0.2", - "define-properties": "^1.2.0", - "es-abstract": "^1.22.1" - } - }, - "strip-ansi": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", - "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", - "dev": true, - "requires": { - "ansi-regex": "^5.0.1" - } - }, - "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 - }, - "strip-final-newline": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/strip-final-newline/-/strip-final-newline-2.0.0.tgz", - "integrity": "sha512-BrpvfNAE3dcvq7ll3xVumzjKjZQ5tI1sEUIKr3Uoks0XUl45St3FlatVqef9prk4jRDzhW6WZg+3bk93y6pLjA==", - "dev": true - }, - "strip-json-comments": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz", - "integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==", - "dev": true - }, - "supports-color": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", - "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", - "dev": true, - "requires": { - "has-flag": "^4.0.0" - } - }, - "supports-preserve-symlinks-flag": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz", - "integrity": "sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==", - "dev": true - }, - "test-exclude": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/test-exclude/-/test-exclude-6.0.0.tgz", - "integrity": "sha512-cAGWPIyOHU6zlmg88jwm7VRyXnMN7iV68OGAbYDk/Mh/xC/pzVPlQtY6ngoIH/5/tciuhGfvESU8GrHrcxD56w==", - "dev": true, - "requires": { - "@istanbuljs/schema": "^0.1.2", - "glob": "^7.1.4", - "minimatch": "^3.0.4" - } - }, - "text-table": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz", - "integrity": "sha512-N+8UisAXDGk8PFXP4HAzVR9nbfmVJ3zYLAWiTIoqC5v5isinhr+r5uaO8+7r3BMfuNIufIsA7RdpVgacC2cSpw==", - "dev": true - }, - "tmpl": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/tmpl/-/tmpl-1.0.5.tgz", - "integrity": "sha512-3f0uOEAQwIqGuWW2MVzYg8fV/QNnc/IpuJNG837rLuczAaLVHslWHZQj4IGiEl5Hs3kkbhwL9Ab7Hrsmuj+Smw==", - "dev": true - }, - "to-fast-properties": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/to-fast-properties/-/to-fast-properties-2.0.0.tgz", - "integrity": "sha512-/OaKK0xYrs3DmxRYqL/yDc+FxFUVYhDlXMhRmv3z915w2HF1tnN1omB354j8VUGO/hbRzyD6Y3sA7v7GS/ceog==", - "dev": true - }, - "to-regex-range": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", - "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", - "dev": true, - "requires": { - "is-number": "^7.0.0" - } - }, - "tsconfig-paths": { - "version": "3.14.2", - "resolved": "https://registry.npmjs.org/tsconfig-paths/-/tsconfig-paths-3.14.2.tgz", - "integrity": "sha512-o/9iXgCYc5L/JxCHPe3Hvh8Q/2xm5Z+p18PESBU6Ff33695QnCHBEjcytY2q19ua7Mbl/DavtBOLq+oG0RCL+g==", - "dev": true, - "requires": { - "@types/json5": "^0.0.29", - "json5": "^1.0.2", - "minimist": "^1.2.6", - "strip-bom": "^3.0.0" - }, - "dependencies": { - "json5": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/json5/-/json5-1.0.2.tgz", - "integrity": "sha512-g1MWMLBiz8FKi1e4w0UyVL3w+iJceWAFBAaBnnGKOpNa5f8TLktkbre1+s6oICydWAm+HRUGTmI+//xv2hvXYA==", - "dev": true, - "requires": { - "minimist": "^1.2.0" - } - }, - "strip-bom": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-3.0.0.tgz", - "integrity": "sha512-vavAMRXOgBVNF6nyEEmL3DBK19iRpDcoIwW+swQ+CbGiu7lju6t+JklA1MHweoWtadgt4ISVUsXLyDq34ddcwA==", - "dev": true - } - } - }, - "type-check": { - "version": "0.4.0", - "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.4.0.tgz", - "integrity": "sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==", - "dev": true, - "requires": { - "prelude-ls": "^1.2.1" - } - }, - "type-detect": { - "version": "4.0.8", - "resolved": "https://registry.npmjs.org/type-detect/-/type-detect-4.0.8.tgz", - "integrity": "sha512-0fr/mIH1dlO+x7TlcMy+bIDqKPsw/70tVyeHW787goQjhmqaZe10uwLujubK9q9Lg6Fiho1KUKDYz0Z7k7g5/g==", - "dev": true - }, - "type-fest": { - "version": "0.21.3", - "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.21.3.tgz", - "integrity": "sha512-t0rzBq87m3fVcduHDUFhKmyyX+9eo6WQjZvf51Ea/M0Q7+T374Jp1aUiyUl0GKxp8M/OETVHSDvmkyPgvX+X2w==", - "dev": true - }, - "typed-array-buffer": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/typed-array-buffer/-/typed-array-buffer-1.0.0.tgz", - "integrity": "sha512-Y8KTSIglk9OZEr8zywiIHG/kmQ7KWyjseXs1CbSo8vC42w7hg2HgYTxSWwP0+is7bWDc1H+Fo026CpHFwm8tkw==", - "dev": true, - "requires": { - "call-bind": "^1.0.2", - "get-intrinsic": "^1.2.1", - "is-typed-array": "^1.1.10" - } - }, - "typed-array-byte-length": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/typed-array-byte-length/-/typed-array-byte-length-1.0.0.tgz", - "integrity": "sha512-Or/+kvLxNpeQ9DtSydonMxCx+9ZXOswtwJn17SNLvhptaXYDJvkFFP5zbfU/uLmvnBJlI4yrnXRxpdWH/M5tNA==", - "dev": true, - "requires": { - "call-bind": "^1.0.2", - "for-each": "^0.3.3", - "has-proto": "^1.0.1", - "is-typed-array": "^1.1.10" - } - }, - "typed-array-byte-offset": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/typed-array-byte-offset/-/typed-array-byte-offset-1.0.0.tgz", - "integrity": "sha512-RD97prjEt9EL8YgAgpOkf3O4IF9lhJFr9g0htQkm0rchFp/Vx7LW5Q8fSXXub7BXAODyUQohRMyOc3faCPd0hg==", - "dev": true, - "requires": { - "available-typed-arrays": "^1.0.5", - "call-bind": "^1.0.2", - "for-each": "^0.3.3", - "has-proto": "^1.0.1", - "is-typed-array": "^1.1.10" - } - }, - "typed-array-length": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/typed-array-length/-/typed-array-length-1.0.4.tgz", - "integrity": "sha512-KjZypGq+I/H7HI5HlOoGHkWUUGq+Q0TPhQurLbyrVrvnKTBgzLhIJ7j6J/XTQOi0d1RjyZ0wdas8bKs2p0x3Ng==", - "dev": true, - "requires": { - "call-bind": "^1.0.2", - "for-each": "^0.3.3", - "is-typed-array": "^1.1.9" - } - }, - "typescript": { - "version": "5.5.4", - "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.5.4.tgz", - "integrity": "sha512-Mtq29sKDAEYP7aljRgtPOpTvOfbwRWlS6dPRzwjdE+C0R4brX/GUyhHSecbHMFLNBLcJIPt9nl9yG5TZ1weH+Q==", - "dev": true - }, - "unbox-primitive": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/unbox-primitive/-/unbox-primitive-1.0.2.tgz", - "integrity": "sha512-61pPlCD9h51VoreyJ0BReideM3MDKMKnh6+V9L08331ipq6Q8OFXZYiqP6n/tbHx4s5I9uRhcye6BrbkizkBDw==", - "dev": true, - "requires": { - "call-bind": "^1.0.2", - "has-bigints": "^1.0.2", - "has-symbols": "^1.0.3", - "which-boxed-primitive": "^1.0.2" - } - }, - "undici-types": { + "node_modules/undici-types": { "version": "6.18.2", "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-6.18.2.tgz", "integrity": "sha512-5ruQbENj95yDYJNS3TvcaxPMshV7aizdv/hWYjGIKoANWKjhWNBsr2YEuYZKodQulB1b8l7ILOuDQep3afowQQ==", "dev": true - }, - "update-browserslist-db": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.1.0.tgz", - "integrity": "sha512-EdRAaAyk2cUE1wOf2DkEhzxqOQvFOoRJFNS6NeyJ01Gp2beMRpBAINjM2iDXE3KCuKhwnvHIQCJm6ThL2Z+HzQ==", - "dev": true, - "requires": { - "escalade": "^3.1.2", - "picocolors": "^1.0.1" - } - }, - "uri-js": { - "version": "4.4.1", - "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz", - "integrity": "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==", - "dev": true, - "requires": { - "punycode": "^2.1.0" - } - }, - "v8-to-istanbul": { - "version": "9.3.0", - "resolved": "https://registry.npmjs.org/v8-to-istanbul/-/v8-to-istanbul-9.3.0.tgz", - "integrity": "sha512-kiGUalWN+rgBJ/1OHZsBtU4rXZOfj/7rKQxULKlIzwzQSvMJUUNgPwJEEh7gU6xEVxC0ahoOBvN2YI8GH6FNgA==", - "dev": true, - "requires": { - "@jridgewell/trace-mapping": "^0.3.12", - "@types/istanbul-lib-coverage": "^2.0.1", - "convert-source-map": "^2.0.0" - } - }, - "version-guard": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/version-guard/-/version-guard-1.1.1.tgz", - "integrity": "sha512-MGQLX89UxmYHgDvcXyjBI0cbmoW+t/dANDppNPrno64rYr8nH4SHSuElQuSYdXGEs0mUzdQe1BY+FhVPNsAmJQ==", - "dev": true - }, - "walker": { - "version": "1.0.8", - "resolved": "https://registry.npmjs.org/walker/-/walker-1.0.8.tgz", - "integrity": "sha512-ts/8E8l5b7kY0vlWLewOkDXMmPdLcVV4GmOQLyxuSswIJsweeFZtAsMF7k1Nszz+TYBQrlYRmzOnr398y1JemQ==", - "dev": true, - "requires": { - "makeerror": "1.0.12" - } - }, - "which": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", - "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", - "dev": true, - "requires": { - "isexe": "^2.0.0" - } - }, - "which-boxed-primitive": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/which-boxed-primitive/-/which-boxed-primitive-1.0.2.tgz", - "integrity": "sha512-bwZdv0AKLpplFY2KZRX6TvyuN7ojjr7lwkg6ml0roIy9YeuSr7JS372qlNW18UQYzgYK9ziGcerWqZOmEn9VNg==", - "dev": true, - "requires": { - "is-bigint": "^1.0.1", - "is-boolean-object": "^1.1.0", - "is-number-object": "^1.0.4", - "is-string": "^1.0.5", - "is-symbol": "^1.0.3" - } - }, - "which-builtin-type": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/which-builtin-type/-/which-builtin-type-1.1.3.tgz", - "integrity": "sha512-YmjsSMDBYsM1CaFiayOVT06+KJeXf0o5M/CAd4o1lTadFAtacTUM49zoYxr/oroopFDfhvN6iEcBxUyc3gvKmw==", - "dev": true, - "requires": { - "function.prototype.name": "^1.1.5", - "has-tostringtag": "^1.0.0", - "is-async-function": "^2.0.0", - "is-date-object": "^1.0.5", - "is-finalizationregistry": "^1.0.2", - "is-generator-function": "^1.0.10", - "is-regex": "^1.1.4", - "is-weakref": "^1.0.2", - "isarray": "^2.0.5", - "which-boxed-primitive": "^1.0.2", - "which-collection": "^1.0.1", - "which-typed-array": "^1.1.9" - } - }, - "which-collection": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/which-collection/-/which-collection-1.0.1.tgz", - "integrity": "sha512-W8xeTUwaln8i3K/cY1nGXzdnVZlidBcagyNFtBdD5kxnb4TvGKR7FfSIS3mYpwWS1QUCutfKz8IY8RjftB0+1A==", - "dev": true, - "requires": { - "is-map": "^2.0.1", - "is-set": "^2.0.1", - "is-weakmap": "^2.0.1", - "is-weakset": "^2.0.1" - } - }, - "which-typed-array": { - "version": "1.1.13", - "resolved": "https://registry.npmjs.org/which-typed-array/-/which-typed-array-1.1.13.tgz", - "integrity": "sha512-P5Nra0qjSncduVPEAr7xhoF5guty49ArDTwzJ/yNuPIbZppyRxFQsRCWrocxIY+CnMVG+qfbU2FmDKyvSGClow==", - "dev": true, - "requires": { - "available-typed-arrays": "^1.0.5", - "call-bind": "^1.0.4", - "for-each": "^0.3.3", - "gopd": "^1.0.1", - "has-tostringtag": "^1.0.0" - } - }, - "wrap-ansi": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", - "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", - "dev": true, - "requires": { - "ansi-styles": "^4.0.0", - "string-width": "^4.1.0", - "strip-ansi": "^6.0.0" - } - }, - "wrappy": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", - "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==", - "dev": true - }, - "write-file-atomic": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/write-file-atomic/-/write-file-atomic-4.0.2.tgz", - "integrity": "sha512-7KxauUdBmSdWnmpaGFg+ppNjKF8uNLry8LyzjauQDOVONfFLNKrKvQOxZ/VuTIcS/gge/YNahf5RIIQWTSarlg==", - "dev": true, - "requires": { - "imurmurhash": "^0.1.4", - "signal-exit": "^3.0.7" - } - }, - "xdg-basedir": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/xdg-basedir/-/xdg-basedir-4.0.0.tgz", - "integrity": "sha512-PSNhEJDejZYV7h50BohL09Er9VaIefr2LMAf3OEmpCkjOi34eYyQYAXUTjEQtZJTKcF0E2UKTh+osDLsgNim9Q==", - "dev": true - }, - "y18n": { - "version": "5.0.8", - "resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz", - "integrity": "sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==", - "dev": true - }, - "yallist": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", - "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", - "dev": true - }, - "yargs": { - "version": "17.7.2", - "resolved": "https://registry.npmjs.org/yargs/-/yargs-17.7.2.tgz", - "integrity": "sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w==", - "dev": true, - "requires": { - "cliui": "^8.0.1", - "escalade": "^3.1.1", - "get-caller-file": "^2.0.5", - "require-directory": "^2.1.1", - "string-width": "^4.2.3", - "y18n": "^5.0.5", - "yargs-parser": "^21.1.1" - } - }, - "yargs-parser": { - "version": "21.1.1", - "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-21.1.1.tgz", - "integrity": "sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw==", - "dev": true - }, - "yocto-queue": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz", - "integrity": "sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==", - "dev": true } } } diff --git a/package.json b/package.json index ccd8c0fc..cf9a67f7 100644 --- a/package.json +++ b/package.json @@ -4,7 +4,7 @@ "license": "Apache-2.0", "homepage": "http://github.com/apache/couchdb-nano", "repository": "http://github.com/apache/couchdb-nano", - "version": "10.1.4", + "version": "11.0.0", "author": "Apache CouchDB (http://couchdb.apache.org)", "keywords": [ "couchdb", @@ -17,33 +17,21 @@ "database" ], "dependencies": { - "axios": "^1.7.4", - "qs": "^6.13.0", - "node-abort-controller": "^3.1.1" }, "devDependencies": { + "undici": "^6.2.1", "@types/node": "^22.3.0", - "jest": "^29.7.0", - "nock": "^13.5.4", - "standard": "^17.1.0", "typescript": "^5.5.4" }, "scripts": { - "standard": "standard --fix", - "test": "standard && tsc lib/nano.d.ts && npm run jest", - "jest": "jest test/* --coverage --env node" + "test": "tsc lib/nano.d.ts && node --test ./test/*.test.js" }, "main": "./lib/nano.js", "types": "./lib/nano.d.ts", "engines": { - "node": ">=14" + "node": ">=18.0" }, "pre-commit": [ "test" - ], - "standard": { - "env": [ - "jest" - ] - } + ] } diff --git a/test/attachment.destroy.test.js b/test/attachment.destroy.test.js index d390a93e..bb5bbf22 100644 --- a/test/attachment.destroy.test.js +++ b/test/attachment.destroy.test.js @@ -10,27 +10,25 @@ // License for the specific language governing permissions and limitations under // the License. +const test = require('node:test') +const assert = require('node:assert/strict') +const { COUCH_URL, mockAgent, mockPool, JSON_HEADERS } = require('./mock.js') const Nano = require('..') -const COUCH_URL = 'http://localhost:5984' const nano = Nano(COUCH_URL) -const nock = require('nock') - -afterEach(() => { - nock.cleanAll() -}) test('should be able to destroy an attachment - DELETE /db/id/attname - db.attachment.destroy', async () => { // mocks const response = { ok: true, id: 'id', rev: '2-456' } - const scope = nock(COUCH_URL) - .delete('/db/id/logo.jpg?rev=1-123') - .reply(200, response) + mockPool.intercept({ + method: 'delete', + path: '/db/id/logo.jpg?rev=1-123' + }).reply(200, response, JSON_HEADERS) // test DELETE DELETE /db/id/attname const db = nano.db.use('db') const p = await db.attachment.destroy('id', 'logo.jpg', { rev: '1-123' }) - expect(p).toStrictEqual(response) - expect(scope.isDone()).toBe(true) + assert.deepEqual(p, response) + mockAgent.assertNoPendingInterceptors() }) test('should be able to handle 409 conflicts - DELETE /db/id/attname- db.attachment.destroy', async () => { @@ -39,30 +37,22 @@ test('should be able to handle 409 conflicts - DELETE /db/id/attname- db.attachm error: 'conflict', reason: 'Document update conflict.' } - const scope = nock(COUCH_URL) - .delete('/db/id/logo.jpg?rev=1-123') - .reply(409, response) + mockPool.intercept({ + method: 'delete', + path: '/db/id/logo.jpg?rev=1-123' + }).reply(409, response, JSON_HEADERS) // test DELETE /db/id/attname const db = nano.db.use('db') - await expect(db.attachment.destroy('id', 'logo.jpg', { rev: '1-123' })).rejects.toThrow('Document update conflict.') - expect(scope.isDone()).toBe(true) + await assert.rejects(db.attachment.destroy('id', 'logo.jpg', { rev: '1-123' }), { message: 'Document update conflict.' }) + mockAgent.assertNoPendingInterceptors() }) test('should detect missing doc id - db.attachment.destroy', async () => { const db = nano.db.use('db') - await expect(db.attachment.destroy()).rejects.toThrow('Invalid parameters') - await expect(db.attachment.destroy('id')).rejects.toThrow('Invalid parameters') - await expect(db.attachment.destroy('id', '')).rejects.toThrow('Invalid parameters') - await expect(db.attachment.destroy('', 'logo.jpg')).rejects.toThrow('Invalid parameters') + await assert.rejects(db.attachment.destroy(), { message: 'Invalid parameters' }) + await assert.rejects(db.attachment.destroy('id'), { message: 'Invalid parameters' }) + await assert.rejects(db.attachment.destroy('id', ''), { message: 'Invalid parameters' }) + await assert.rejects(db.attachment.destroy('', 'logo.jpg'), { message: 'Invalid parameters' }) }) -test('should detect missing parameters (callback) - db.attachment.destroy', () => { - const db = nano.db.use('db') - return new Promise((resolve, reject) => { - db.attachment.destroy(undefined, undefined, undefined, (err, data) => { - expect(err).not.toBeNull() - resolve() - }) - }) -}) diff --git a/test/attachment.get.test.js b/test/attachment.get.test.js index ef862e80..fcb70c46 100644 --- a/test/attachment.get.test.js +++ b/test/attachment.get.test.js @@ -10,56 +10,44 @@ // License for the specific language governing permissions and limitations under // the License. +const test = require('node:test') +const assert = require('node:assert/strict') +const { COUCH_URL, mockAgent, mockPool } = require('./mock.js') const Nano = require('..') -const COUCH_URL = 'http://localhost:5984' const nano = Nano(COUCH_URL) -const nock = require('nock') const image = Buffer.from('R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7', 'base64') -afterEach(() => { - nock.cleanAll() -}) - test('should be able to get an attachment - GET /db/id/attname - db.attachment.get', async () => { // mocks - const scope = nock(COUCH_URL) - .get('/db/id/transparent.gif') - .reply(200, image, { 'content-type': 'image/gif' }) + mockPool + .intercept({ path: '/db/id/transparent.gif' }) + .reply(200, image, { headers: { 'content-type': 'image/gif' } }) // test GET /db/id/attname const db = nano.db.use('db') const p = await db.attachment.get('id', 'transparent.gif') - expect(p).toStrictEqual(image) - expect(scope.isDone()).toBe(true) + assert.equal(p.toString('base64'), image.toString('base64')) + mockAgent.assertNoPendingInterceptors() }) test('should be able to get an attachment with opts - GET /db/id/attname - db.attachment.get', async () => { // mocks - const scope = nock(COUCH_URL) - .get('/db/id/transparent.gif?r=1') - .reply(200, image, { 'content-type': 'image/gif' }) + mockPool + .intercept({ path: '/db/id/transparent.gif?r=1' }) + .reply(200, image, { headers: { 'content-type': 'image/gif' } }) // test GET /db/id/attname const db = nano.db.use('db') const p = await db.attachment.get('id', 'transparent.gif', { r: 1 }) - expect(p).toStrictEqual(image) - expect(scope.isDone()).toBe(true) + assert.equal(p.toString('base64'), image.toString('base64')) + mockAgent.assertNoPendingInterceptors() }) test('should detect missing parameters - db.attachment.get', async () => { const db = nano.db.use('db') - await expect(db.attachment.get()).rejects.toThrow('Invalid parameters') - await expect(db.attachment.get('id')).rejects.toThrow('Invalid parameters') - await expect(db.attachment.get('id', '')).rejects.toThrow('Invalid parameters') - await expect(db.attachment.get('', 'transparent.gif')).rejects.toThrow('Invalid parameters') + await assert.rejects(db.attachment.get(), { message: 'Invalid parameters' }) + await assert.rejects(db.attachment.get('id'), { message: 'Invalid parameters' }) + await assert.rejects(db.attachment.get('id', ''), { message: 'Invalid parameters' }) + await assert.rejects(db.attachment.get('', 'transparent.gif'), { message: 'Invalid parameters' }) }) -test('should detect missing parameters (callback) - db.attachment.get', () => { - const db = nano.db.use('db') - return new Promise((resolve, reject) => { - db.attachment.get(undefined, undefined, undefined, (err, data) => { - expect(err).not.toBeNull() - resolve() - }) - }) -}) diff --git a/test/attachment.getAsStream.test.js b/test/attachment.getAsStream.test.js index 6d80b3b4..35909b86 100644 --- a/test/attachment.getAsStream.test.js +++ b/test/attachment.getAsStream.test.js @@ -10,21 +10,18 @@ // License for the specific language governing permissions and limitations under // the License. +const test = require('node:test') +const assert = require('node:assert/strict') +const { COUCH_URL, mockAgent, mockPool, JSON_HEADERS } = require('./mock.js') const Nano = require('..') -const COUCH_URL = 'http://localhost:5984' const nano = Nano(COUCH_URL) -const nock = require('nock') const image = Buffer.from('R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7', 'base64') -afterEach(() => { - nock.cleanAll() -}) - test('should be able to get an attachment as a stream - GET /db/id/attname - db.attachment.getAsStream', () => { // mocks - const scope = nock(COUCH_URL) - .get('/db/id/transparent.gif') - .reply(200, image, { 'content-type': 'image/gif' }) + mockPool + .intercept({ path: '/db/id/transparent.gif' }) + .reply(200, image, { headers: { 'content-type': 'image/gif' } }) // test GET /db/id/attname return new Promise((resolve, reject) => { @@ -35,24 +32,25 @@ test('should be able to get an attachment as a stream - GET /db/id/attname - db. response = Buffer.concat([response, data]) }) .on('end', () => { - expect(response).toStrictEqual(image) - expect(scope.isDone()).toBe(true) + assert.equal(response.toString('base64'), image.toString('base64')) + mockAgent.assertNoPendingInterceptors() resolve() }) }) }) -test('should emit an error when stream attachment does not exist - GET /db/id/attname - db.attachment.getAsStream', () => { +test('should emit an error when stream attachment does not exist - GET /db/id/attname - db.attachment.getAsStream', async () => { // test GET /db/id/attname - nock(COUCH_URL) - .get('/db/id/notexists.gif') - .reply(404, 'Object Not Found', { 'content-type': 'application/json' }) + const response = { error: 'not_found', reason: 'Document is missing attachment' } + mockPool + .intercept({ path: '/db/id/notexist.gif' }) + .reply(404, response, JSON_HEADERS) - return new Promise((resolve, reject) => { + await new Promise((resolve, reject) => { const db = nano.db.use('db') db.attachment.getAsStream('id', 'notexist.gif') .on('error', (e) => { - expect(e.statusCode).toStrictEqual(404) + assert.equal(e.statusCode, 404) resolve() }) }) diff --git a/test/attachment.insert.test.js b/test/attachment.insert.test.js index 8619e2d9..af9c9ec2 100644 --- a/test/attachment.insert.test.js +++ b/test/attachment.insert.test.js @@ -10,39 +10,34 @@ // License for the specific language governing permissions and limitations under // the License. +const test = require('node:test') +const assert = require('node:assert/strict') +const { COUCH_URL, mockAgent, mockPool, JSON_HEADERS } = require('./mock.js') const Nano = require('..') -const COUCH_URL = 'http://localhost:5984' const nano = Nano(COUCH_URL) -const nock = require('nock') const fs = require('fs') const image = Buffer.from('R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7', 'base64') -const image2 = Buffer.from(''.concat( - 'iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAMAAAAoLQ9TAAAAsV', - 'BMVEUAAAD////////////////////////5ur3rEBn////////////////wDBL/', - 'AADuBAe9EB3IEBz/7+//X1/qBQn2AgP/f3/ilpzsDxfpChDtDhXeCA76AQH/v7', - '/84eLyWV/uc3bJPEf/Dw/uw8bRWmP1h4zxSlD6YGHuQ0f6g4XyQkXvCA36MDH6', - 'wMH/z8/yAwX64ODeh47BHiv/Ly/20dLQLTj98PDXWmP/Pz//39/wGyJ7Iy9JAA', - 'AADHRSTlMAbw8vf08/bz+Pv19jK/W3AAAAg0lEQVR4Xp3LRQ4DQRBD0QqTm4Y5', - 'zMxw/4OleiJlHeUtv2X6RbNO1Uqj9g0RMCuQO0vBIg4vMFeOpCWIWmDOw82fZx', - 'vaND1c8OG4vrdOqD8YwgpDYDxRgkSm5rwu0nQVBJuMg++pLXZyr5jnc1BaH4GT', - 'LvEliY253nA3pVhQqdPt0f/erJkMGMB8xucAAAAASUVORK5CYII='), 'base64') - -afterEach(() => { - nock.cleanAll() -}) test('should be able to insert document attachment - PUT /db/docname/attachment - db.attachment.insert', async () => { // mocks const response = { ok: true, id: 'docname', rev: '2-456' } - const scope = nock(COUCH_URL, { reqheaders: { 'content-type': 'image/gif' } }) - .put('/db/docname/transparent.gif?rev=1-150', image) - .reply(200, response) + mockPool.intercept({ + method: 'put', + path: '/db/docname/transparent.gif?rev=1-150', + body: (value) => { + const buff = Buffer.from(value) + return buff.equals(image) + }, + headers: { + 'content-type': 'image/gif' + } + }).reply(200, response, JSON_HEADERS) // test PUT /db/docname/attachment const db = nano.db.use('db') const p = await db.attachment.insert('docname', 'transparent.gif', image, 'image/gif', { rev: '1-150' }) - expect(p).toStrictEqual(response) - expect(scope.isDone()).toBe(true) + assert.deepEqual(p, response) + mockAgent.assertNoPendingInterceptors() }) test('should be able to handle 404 - db.attachment.insert', async () => { @@ -51,55 +46,67 @@ test('should be able to handle 404 - db.attachment.insert', async () => { error: 'not_found', reason: 'missing' } - const scope = nock(COUCH_URL, { reqheaders: { 'content-type': 'image/gif' } }) - .put('/db/docname/transparent.gif?rev=1-150', image) - .reply(404, response) + mockPool.intercept({ + method: 'put', + path: '/db/docname/transparent.gif?rev=1-150', + body: (value) => { + const buff = Buffer.from(value) + return buff.equals(image) + }, + headers: { + 'content-type': 'image/gif' + } + }).reply(404, response, JSON_HEADERS) // test PUT /db/docname/attachment const db = nano.db.use('db') - await expect(db.attachment.insert('docname', 'transparent.gif', image, 'image/gif', { rev: '1-150' })).rejects.toThrow('missing') - expect(scope.isDone()).toBe(true) + await assert.rejects(db.attachment.insert('docname', 'transparent.gif', image, 'image/gif', { rev: '1-150' }), { message: 'missing' }) + mockAgent.assertNoPendingInterceptors() }) test('should detect missing parameters - db.attachment.insert', async () => { const db = nano.db.use('db') - await expect(db.attachment.insert()).rejects.toThrow('Invalid parameters') - await expect(db.attachment.insert('docname')).rejects.toThrow('Invalid parameters') - await expect(db.attachment.insert('docname', 't.gif')).rejects.toThrow('Invalid parameters') - await expect(db.attachment.insert('docname', 't.gif', image)).rejects.toThrow('Invalid parameters') -}) - -test('should detect missing parameters (callback) - db.attachment.insert', () => { - const db = nano.db.use('db') - return new Promise((resolve, reject) => { - db.attachment.insert(undefined, undefined, undefined, undefined, undefined, (err, data) => { - expect(err).not.toBeNull() - resolve() - }) - }) + await assert.rejects(db.attachment.insert(), { message: 'Invalid parameters' }) + await assert.rejects(db.attachment.insert('docname'), { message: 'Invalid parameters' }) + await assert.rejects(db.attachment.insert('docname', 't.gif'), { message: 'Invalid parameters' }) + await assert.rejects(db.attachment.insert('docname', 't.gif', image), { message: 'Invalid parameters' }) }) test('should be able to insert document attachment as stream - PUT /db/docname/attachment - db.attachment.insert', async () => { // mocks const response = { ok: true, id: 'docname', rev: '2-456' } - const scope = nock(COUCH_URL, { reqheaders: { 'content-type': 'image/jpg' } }) - .put('/db/docname/logo.jpg?rev=1-150', image2) - .reply(200, response) + mockPool.intercept({ + method: 'put', + path: '/db/docname/logo.jpg?rev=1-150', + body: (value) => { + return true + }, + headers: { + 'content-type': 'image/jpg' + } + }).reply(200, response, JSON_HEADERS) // test PUT /db/docname/attachment const rs = fs.createReadStream('./test/logo.jpg') const db = nano.db.use('db') const reply = await db.attachment.insert('docname', 'logo.jpg', rs, 'image/jpg', { rev: '1-150' }) - expect(reply).toStrictEqual(response) - expect(scope.isDone()).toBe(true) + assert.deepEqual(reply, response) + mockAgent.assertNoPendingInterceptors() }) test('should be able to insert document attachment as stream with circular reference - PUT /db/docname/attachment - db.attachment.insert', async () => { // mocks const response = { ok: true, id: 'docname', rev: '2-456' } - const scope = nock(COUCH_URL, { reqheaders: { 'content-type': 'image/jpg' } }) - .put('/db/docname/logo2.jpg?rev=1-150', image2) - .reply(200, response) + mockPool.intercept({ + method: 'put', + path: '/db/docname/logo2.jpg?rev=1-150', + body: (value) => { + return true + }, + headers: { + 'content-type': 'image/jpg' + } + }).reply(200, response, JSON_HEADERS) // test PUT /db/docname/attachment const rs = fs.createReadStream('./test/logo.jpg') @@ -107,6 +114,6 @@ test('should be able to insert document attachment as stream with circular refer rs.test = rs const db = nano.db.use('db') const reply = await db.attachment.insert('docname', 'logo2.jpg', rs, 'image/jpg', { rev: '1-150' }) - expect(reply).toStrictEqual(response) - expect(scope.isDone()).toBe(true) + assert.deepEqual(reply, response) + mockAgent.assertNoPendingInterceptors() }) diff --git a/test/cookie.test.js b/test/cookie.test.js index 6df66fe2..32ba0629 100644 --- a/test/cookie.test.js +++ b/test/cookie.test.js @@ -10,7 +10,8 @@ // License for the specific language governing permissions and limitations under // the License. -const assert = require('assert') +const test = require('node:test') +const assert = require('node:assert/strict') const CookieJar = require('../lib/cookie.js') @@ -194,7 +195,7 @@ const sleep = async (ms) => { test('should expire cookies correctly', async () => { const cj = new CookieJar() - const expiry = new Date().getTime() + 1000 * 4 + const expiry = new Date().getTime() + 1000 * 5 const expiryStr = new Date(expiry).toGMTString() const n = 'AuthSession' const v = `${n}=YWRtaW46NjM5ODgzQ0Y6TuB66MczvkZ7axEJq6Fz0gOdhKY` @@ -203,7 +204,7 @@ test('should expire cookies correctly', async () => { cj.parse(sc, url) assert.equal(cj.jar.length, 1) assert.notEqual(cj.getCookieString(url).length, 0) - await sleep(4000) + await sleep(5000) assert.equal(cj.getCookieString(url).length, 0) assert.equal(cj.getCookieString(url).length, 0) }) diff --git a/test/database.changes.test.js b/test/database.changes.test.js index 3b791577..44506b8f 100644 --- a/test/database.changes.test.js +++ b/test/database.changes.test.js @@ -10,10 +10,12 @@ // License for the specific language governing permissions and limitations under // the License. +const test = require('node:test') +const assert = require('node:assert/strict') +const { COUCH_URL, mockAgent, mockPool, JSON_HEADERS } = require('./mock.js') const Nano = require('..') -const COUCH_URL = 'http://localhost:5984' const nano = Nano(COUCH_URL) -const nock = require('nock') + const response = { results: [ { @@ -34,70 +36,56 @@ const errResponse = { reason: 'Database does not exist.' } -afterEach(() => { - nock.cleanAll() -}) - test('should be able to fetch the changes - GET /db/_changes - nano.db.changes', async () => { // mocks - const scope = nock(COUCH_URL) - .get('/db/_changes') - .reply(200, response) + mockPool + .intercept({ path: '/db/_changes' }) + .reply(200, response, JSON_HEADERS) // test GET /db/_changes const p = await nano.db.changes('db') - expect(p).toStrictEqual(response) - expect(scope.isDone()).toBe(true) + assert.deepEqual(p, response) + mockAgent.assertNoPendingInterceptors() }) test('should be able to fetch the changes with opts - GET /db/_changes - nano.db.changes', async () => { // mocks const opts = { include_docs: true, feed: 'continuous' } - const scope = nock(COUCH_URL) - .get('/db/_changes') - .query(opts) - .reply(200, response) + mockPool + .intercept({ path: '/db/_changes?include_docs=true&feed=continuous' }) + .reply(200, response, JSON_HEADERS) // test GET /db/_changes const p = await nano.db.changes('db', opts) - expect(p).toStrictEqual(response) - expect(scope.isDone()).toBe(true) + assert.deepEqual(p, response) + mockAgent.assertNoPendingInterceptors() }) test('should be able to handle a missing database - GET /db/_changes - nano.db.changes', async () => { // mocks - const scope = nock(COUCH_URL) - .get('/db/_changes') - .reply(404, errResponse) + mockPool + .intercept({ path: '/db/_changes' }) + .reply(404, errResponse, JSON_HEADERS) // test GET /db/_changes - await expect(nano.db.changes('db')).rejects.toThrow('Database does not exist') - expect(scope.isDone()).toBe(true) + await assert.rejects(nano.db.changes('db'), { message: 'Database does not exist.' }) + mockAgent.assertNoPendingInterceptors() }) test('should not attempt invalid parameters - nano.db.changes', async () => { - await expect(nano.db.changes()).rejects.toThrowError('Invalid parameters') - await expect(nano.db.changes('')).rejects.toThrowError('Invalid parameters') -}) - -test('should detect missing parameters (callback) - nano.db.changes', () => { - return new Promise((resolve, reject) => { - nano.db.changes(undefined, undefined, (err, data) => { - expect(err).not.toBeNull() - resolve() - }) - }) + await assert.rejects(nano.db.changes(), { message: 'Invalid parameters' }) + await assert.rejects(nano.db.changes(''), { message: 'Invalid parameters' }) }) test('should be able to fetch the changes from db.changes - GET /db/_changes - db.changes', async () => { // mocks - const scope = nock(COUCH_URL) - .get('/db/_changes') - .reply(200, response) + mockPool + .intercept({ path: '/db/_changes' }) + .reply(200, response, JSON_HEADERS) // test GET /db/_changes const db = nano.db.use('db') const p = await db.changes() - expect(p).toStrictEqual(response) - expect(scope.isDone()).toBe(true) + assert.deepEqual(p, response) + mockAgent.assertNoPendingInterceptors() }) diff --git a/test/database.changesAsStream.test.js b/test/database.changesAsStream.test.js index c307cc53..149f3af8 100644 --- a/test/database.changesAsStream.test.js +++ b/test/database.changesAsStream.test.js @@ -10,10 +10,11 @@ // License for the specific language governing permissions and limitations under // the License. +const test = require('node:test') +const assert = require('node:assert/strict') +const { COUCH_URL, mockAgent, mockPool, JSON_HEADERS } = require('./mock.js') const Nano = require('..') -const COUCH_URL = 'http://localhost:5984' const nano = Nano(COUCH_URL) -const nock = require('nock') const response = { results: [ { @@ -30,53 +31,48 @@ const response = { pending: 0 } -afterEach(() => { - nock.cleanAll() -}) - -test('should get a streamed list of changes - GET /_changes - nano.db.changesAsStream', () => { +test('should get a streamed list of changes - GET /_changes - nano.db.changesAsStream', async () => { // mocks - const scope = nock(COUCH_URL) - .get('/db/_changes') - .reply(200, response) + mockPool + .intercept({ path: '/db/_changes' }) + .reply(200, response, JSON_HEADERS) - return new Promise((resolve, reject) => { + await new Promise((resolve, reject) => { // test GET /db/_changes const db = nano.db.use('db') const s = db.changesAsStream() - expect(typeof s).toBe('object') + assert.equal(typeof s, 'object') let buffer = '' s.on('data', (chunk) => { buffer += chunk.toString() }) s.on('end', () => { - expect(buffer).toBe(JSON.stringify(response)) - expect(scope.isDone()).toBe(true) + assert.equal(buffer, JSON.stringify(response)) + mockAgent.assertNoPendingInterceptors() resolve() }) }) }) -test('should get a streamed list of changes with opts - GET /_changes - nano.db.changesAsStream', () => { +test('should get a streamed list of changes with opts - GET /_changes - nano.db.changesAsStream', async () => { // mocks const opts = { include_docs: true } - const scope = nock(COUCH_URL) - .get('/db/_changes') - .query(opts) - .reply(200, response) + mockPool + .intercept({ path: '/db/_changes?include_docs=true' }) + .reply(200, response, JSON_HEADERS) - return new Promise((resolve, reject) => { + await new Promise((resolve, reject) => { // test GET /db/_changes const db = nano.db.use('db') const s = db.changesAsStream(opts) - expect(typeof s).toBe('object') + assert.equal(typeof s, 'object') let buffer = '' s.on('data', (chunk) => { buffer += chunk.toString() }) s.on('end', () => { - expect(buffer).toBe(JSON.stringify(response)) - expect(scope.isDone()).toBe(true) + assert.equal(buffer, JSON.stringify(response)) + mockAgent.assertNoPendingInterceptors() resolve() }) }) diff --git a/test/database.compact.test.js b/test/database.compact.test.js index 83c5c915..38c7a8f9 100644 --- a/test/database.compact.test.js +++ b/test/database.compact.test.js @@ -10,76 +10,64 @@ // License for the specific language governing permissions and limitations under // the License. +const test = require('node:test') +const assert = require('node:assert/strict') +const { COUCH_URL, mockAgent, mockPool, JSON_HEADERS } = require('./mock.js') const Nano = require('..') -const COUCH_URL = 'http://localhost:5984' const nano = Nano(COUCH_URL) -const nock = require('nock') const response = { ok: true } -afterEach(() => { - nock.cleanAll() -}) - test('should be able to send compaction request - POST /db/_compact - nano.db.compact', async () => { // mocks - const scope = nock(COUCH_URL) - .post('/db/_compact') - .reply(200, response) + mockPool + .intercept({ method: 'post', path: '/db/_compact' }) + .reply(200, response, JSON_HEADERS) // test POST /db/_compact const p = await nano.db.compact('db') - expect(p).toEqual(response) - expect(scope.isDone()).toBe(true) + assert.deepEqual(p, response) + mockAgent.assertNoPendingInterceptors() }) test('should be able to send compaction request with design doc - POST /db/_compact/ddoc - nano.db.compact', async () => { // mocks - const scope = nock(COUCH_URL) - .post('/db/_compact/ddoc') - .reply(200, response) + mockPool + .intercept({ method: 'post', path: '/db/_compact/ddoc' }) + .reply(200, response, JSON_HEADERS) // test POST /db/_compact/ddoc const p = await nano.db.compact('db', 'ddoc') - expect(p).toEqual(response) - expect(scope.isDone()).toBe(true) + assert.deepEqual(p, response) + mockAgent.assertNoPendingInterceptors() }) test('should not attempt compact with invalid parameters - nano.db.compact', async () => { - await expect(nano.db.compact('')).rejects.toThrowError('Invalid parameters') - await expect(nano.db.compact()).rejects.toThrowError('Invalid parameters') -}) - -test('should detect missing parameters (callback) - nano.db.compact', () => { - return new Promise((resolve, reject) => { - nano.db.compact(undefined, (err, data) => { - expect(err).not.toBeNull() - resolve() - }) - }) + await assert.rejects(nano.db.compact(''), { message: 'Invalid parameters' }) + await assert.rejects(nano.db.compact(), { message: 'Invalid parameters' }) }) test('should be able to send compaction request from db.compact - POST /db/_compact - db.compact', async () => { // mocks - const scope = nock(COUCH_URL) - .post('/db/_compact') - .reply(200, response) + mockPool + .intercept({ method: 'post', path: '/db/_compact' }) + .reply(200, response, JSON_HEADERS) // test POST /db/_compact const db = nano.db.use('db') const p = await db.compact() - expect(p).toEqual(response) - expect(scope.isDone()).toBe(true) + assert.deepEqual(p, response) + mockAgent.assertNoPendingInterceptors() }) test('should be able to send compaction request with design doc from db.view.compact - POST /db/_compact/ddoc - db.view.compact', async () => { // mocks - const scope = nock(COUCH_URL) - .post('/db/_compact/ddoc') - .reply(200, response) + mockPool + .intercept({ method: 'post', path: '/db/_compact/ddoc' }) + .reply(200, response, JSON_HEADERS) // test POST /db/_compact/ddoc const db = nano.db.use('db') const p = await db.view.compact('ddoc') - expect(p).toEqual(response) - expect(scope.isDone()).toBe(true) + assert.deepEqual(p, response) + mockAgent.assertNoPendingInterceptors() }) diff --git a/test/database.create.test.js b/test/database.create.test.js index e0717dc2..fef1795a 100644 --- a/test/database.create.test.js +++ b/test/database.create.test.js @@ -10,67 +10,57 @@ // License for the specific language governing permissions and limitations under // the License. +const test = require('node:test') +const assert = require('node:assert/strict') +const { COUCH_URL, mockAgent, mockPool, JSON_HEADERS } = require('./mock.js') const Nano = require('..') -const COUCH_URL = 'http://localhost:5984' const nano = Nano(COUCH_URL) -const nock = require('nock') const response = { ok: true } -afterEach(() => { - nock.cleanAll() -}) - test('should create a database - PUT /db - nano.db.create', async () => { // mocks - const scope = nock(COUCH_URL) - .put('/db') - .reply(200, response) + mockPool + .intercept({ method: 'put', path: '/db' }) + .reply(200, response, JSON_HEADERS) // test GET /db const p = await nano.db.create('db') - expect(typeof p).toBe('object') - expect(p.ok).toBe(true) - expect(scope.isDone()).toBe(true) + assert.equal(typeof p, 'object') + assert.equal(p.ok, true) + mockAgent.assertNoPendingInterceptors() }) test('should create a database with parameters - PUT /db?partitioned=true - nano.db.create', async () => { // mocks - const scope = nock(COUCH_URL) - .put('/db') - .query({ partitioned: 'true', q: '1' }) - .reply(200, response) + mockPool.intercept({ + method: 'put', + path: '/db?partitioned=true&q=1' + }).reply(200, response, JSON_HEADERS) // test GET /db const p = await nano.db.create('db', { partitioned: true, q: 1 }) - expect(typeof p).toBe('object') - expect(p.ok).toBe(true) - expect(scope.isDone()).toBe(true) + assert.equal(typeof p, 'object') + assert.equal(p.ok, true) + mockAgent.assertNoPendingInterceptors() }) test('should handle pre-existing database - PUT /db - nano.db.create', async () => { // mocks - const scope = nock(COUCH_URL) - .put('/db') - .reply(412, { - error: 'file_exists', - reason: 'The database could not be created, the file already exists.' - }) + mockPool.intercept({ + method: 'put', + path: '/db' + }).reply(412, { + error: 'file_exists', + reason: 'The database could not be created, the file already exists.' + }, JSON_HEADERS) // test PUT /db - await expect(nano.db.create('db')).rejects.toThrow('The database could not be created') - expect(scope.isDone()).toBe(true) + await assert.rejects(nano.db.create('db'), { message: 'The database could not be created, the file already exists.' }) + mockAgent.assertNoPendingInterceptors() }) test('should not attempt to create database with invalid parameters - nano.db.create', async () => { - await expect(nano.db.create()).rejects.toThrowError('Invalid parameters') - await expect(nano.db.create('')).rejects.toThrowError('Invalid parameters') + await assert.rejects(nano.db.create(), { message: 'Invalid parameters' }) + await assert.rejects(nano.db.create(''), { message: 'Invalid parameters' }) }) -test('should detect missing parameters (callback) - nano.db.create', () => { - return new Promise((resolve, reject) => { - nano.db.create(undefined, undefined, (err, data) => { - expect(err).not.toBeNull() - resolve() - }) - }) -}) diff --git a/test/database.destroy.test.js b/test/database.destroy.test.js index 3e1fdd0e..835d0573 100644 --- a/test/database.destroy.test.js +++ b/test/database.destroy.test.js @@ -10,53 +10,41 @@ // License for the specific language governing permissions and limitations under // the License. +const test = require('node:test') +const assert = require('node:assert/strict') +const { COUCH_URL, mockAgent, mockPool, JSON_HEADERS } = require('./mock.js') const Nano = require('..') -const COUCH_URL = 'http://localhost:5984' const nano = Nano(COUCH_URL) -const nock = require('nock') -const response = { ok: true } -afterEach(() => { - nock.cleanAll() -}) +const response = { ok: true } test('should destroy a database - DELETE /db - nano.db.destroy', async () => { // mocks - const scope = nock(COUCH_URL) - .delete('/db') - .reply(200, response) + mockPool + .intercept({ method: 'delete', path: '/db' }) + .reply(200, response, JSON_HEADERS) // test DELETE /db const p = await nano.db.destroy('db') - expect(typeof p).toBe('object') - expect(p.ok).toBe(true) - expect(scope.isDone()).toBe(true) + assert.equal(typeof p, 'object') + assert.deepEqual(p, response) + mockAgent.assertNoPendingInterceptors() }) test('should handle non-existant database - DELETE /db - nano.db.destroy', async () => { // mocks - const scope = nock(COUCH_URL) - .delete('/db') - .reply(404, { - error: 'not_found', - reason: 'Database does not exist.' - }) + mockPool.intercept({ method: 'delete', path: '/db' }).reply(404, { + error: 'not_found', + reason: 'Database does not exist.' + }, JSON_HEADERS) // test DELETE /db - await expect(nano.db.destroy('db')).rejects.toThrow('Database does not exist') - expect(scope.isDone()).toBe(true) + await assert.rejects(nano.db.destroy('db'), 'Database does not exist') + mockAgent.assertNoPendingInterceptors() }) test('should not attempt to destroy database with empty database name - nano.db.destroy', async () => { - await expect(nano.db.destroy()).rejects.toThrowError('Invalid parameters') - await expect(nano.db.destroy('')).rejects.toThrowError('Invalid parameters') + await assert.rejects(nano.db.destroy(), { message: 'Invalid parameters' }) + await assert.rejects(nano.db.destroy(''), { message: 'Invalid parameters' }) }) -test('should detect missing parameters (callback) - nano.db.destroy', () => { - return new Promise((resolve, reject) => { - nano.db.destroy(undefined, (err, data) => { - expect(err).not.toBeNull() - resolve() - }) - }) -}) diff --git a/test/database.get.test.js b/test/database.get.test.js index a63c2ab4..290834e2 100644 --- a/test/database.get.test.js +++ b/test/database.get.test.js @@ -10,10 +10,12 @@ // License for the specific language governing permissions and limitations under // the License. +const test = require('node:test') +const assert = require('node:assert/strict') +const { COUCH_URL, mockAgent, mockPool, JSON_HEADERS } = require('./mock.js') + const Nano = require('..') -const COUCH_URL = 'http://localhost:5984' const nano = Nano(COUCH_URL) -const nock = require('nock') const response = { db_name: 'db', purge_seq: '0-8KhNZEiqhyjKAgBm5Rxs', @@ -41,63 +43,49 @@ const response = { instance_start_time: '0' } -afterEach(() => { - nock.cleanAll() -}) - test('should be able to fetch the database info - GET /db - nano.db.get', async () => { // mocks - const scope = nock(COUCH_URL) - .get('/db') - .reply(200, response) + mockPool + .intercept({ path: '/db' }) + .reply(200, response, JSON_HEADERS) // test GET /db const p = await nano.db.get('db') - expect(typeof p).toBe('object') - expect(p.doc_count).toBe(0) - expect(p.db_name).toBe('db') - expect(scope.isDone()).toBe(true) + assert.strictEqual(typeof p, 'object') + assert.strictEqual(p.doc_count, 0) + assert.strictEqual(p.db_name, 'db') + mockAgent.assertNoPendingInterceptors() }) test('should be able to fetch the database info - GET /db - db.info', async () => { // mocks - const scope = nock(COUCH_URL) - .get('/db') - .reply(200, response) + mockPool + .intercept({ path: '/db' }) + .reply(200, response, JSON_HEADERS) // test GET /db const db = nano.db.use('db') const p = await db.info() - expect(typeof p).toBe('object') - expect(p.doc_count).toBe(0) - expect(p.db_name).toBe('db') - expect(scope.isDone()).toBe(true) + assert.strictEqual(typeof p, 'object') + assert.strictEqual(p.doc_count, 0) + assert.strictEqual(p.db_name, 'db') + mockAgent.assertNoPendingInterceptors() }) test('should handle missing database - GET /db - nano.db.get', async () => { // mocks - const scope = nock(COUCH_URL) - .get('/db') - .reply(404, { - error: 'not_found', - reason: 'Database does not exist.' - }) + mockPool.intercept({ path: '/db' }).reply(404, { + error: 'not_found', + reason: 'Database does not exist.' + }, JSON_HEADERS) // test GET /db - await expect(nano.db.get('db')).rejects.toThrow('Database does not exist') - expect(scope.isDone()).toBe(true) + await assert.rejects(nano.db.get('db'), { message: 'Database does not exist.' }) + mockAgent.assertNoPendingInterceptors() }) test('should not attempt info fetch with missing parameters - nano.db.get', async () => { - await expect(nano.db.get()).rejects.toThrowError('Invalid parameters') - await expect(nano.db.get('')).rejects.toThrowError('Invalid parameters') + await assert.rejects(nano.db.get(), { message: 'Invalid parameters' }) + await assert.rejects(nano.db.get(''), { message: 'Invalid parameters' }) }) -test('should detect missing parameters (callback) - nano.db.get', () => { - return new Promise((resolve, reject) => { - nano.db.get(undefined, (err, data) => { - expect(err).not.toBeNull() - resolve() - }) - }) -}) diff --git a/test/database.list.test.js b/test/database.list.test.js index abe6e102..6c670da2 100644 --- a/test/database.list.test.js +++ b/test/database.list.test.js @@ -10,24 +10,22 @@ // License for the specific language governing permissions and limitations under // the License. +const test = require('node:test') +const assert = require('node:assert/strict') +const { COUCH_URL, mockAgent, mockPool, JSON_HEADERS } = require('./mock.js') const Nano = require('..') -const COUCH_URL = 'http://localhost:5984' const nano = Nano(COUCH_URL) -const nock = require('nock') const response = ['rita', 'sue', 'bob'] -afterEach(() => { - nock.cleanAll() -}) - test('should be to get list of databases - GET /_all_dbs - nano.db.list', async () => { // mocks - const scope = nock(COUCH_URL) - .get('/_all_dbs') - .reply(200, response) + mockPool + .intercept({ path: '/_all_dbs' }) + .reply(200, response, JSON_HEADERS) // test GET /_all_dbs const p = await nano.db.list() - expect(p).toStrictEqual(response) - expect(scope.isDone()).toBe(true) + assert.equal(typeof p, 'object') + assert.deepEqual(p, response) + mockAgent.assertNoPendingInterceptors() }) diff --git a/test/database.listAsStream.test.js b/test/database.listAsStream.test.js index d10f53b8..f8525d53 100644 --- a/test/database.listAsStream.test.js +++ b/test/database.listAsStream.test.js @@ -10,33 +10,30 @@ // License for the specific language governing permissions and limitations under // the License. +const test = require('node:test') +const assert = require('node:assert/strict') +const { COUCH_URL, mockAgent, mockPool, JSON_HEADERS } = require('./mock.js') const Nano = require('..') -const COUCH_URL = 'http://localhost:5984' const nano = Nano(COUCH_URL) -const nock = require('nock') const response = ['rita', 'sue', 'bob'] -afterEach(() => { - nock.cleanAll() -}) - -test('should get a streamed list of databases - GET /_all_dbs - nano.db.listAsStream', () => { +test('should get a streamed list of databases - GET /_all_dbs - nano.db.listAsStream', async () => { // mocks - const scope = nock(COUCH_URL) - .get('/_all_dbs') - .reply(200, response) + mockPool + .intercept({ path: '/_all_dbs' }) + .reply(200, response, JSON_HEADERS) - return new Promise((resolve, reject) => { + await new Promise((resolve, reject) => { // test GET /_all_dbs const s = nano.db.listAsStream() - expect(typeof s).toBe('object') + assert.equal(typeof s, 'object') let buffer = '' s.on('data', (chunk) => { buffer += chunk.toString() }) s.on('end', () => { - expect(buffer).toBe(JSON.stringify(response)) - expect(scope.isDone()).toBe(true) + assert.equal(buffer, JSON.stringify(response)) + mockAgent.assertNoPendingInterceptors() resolve() }) }) diff --git a/test/database.replicate.test.js b/test/database.replicate.test.js index e15095d7..14d332b7 100644 --- a/test/database.replicate.test.js +++ b/test/database.replicate.test.js @@ -10,10 +10,12 @@ // License for the specific language governing permissions and limitations under // the License. +const test = require('node:test') +const assert = require('node:assert/strict') +const { COUCH_URL, mockAgent, mockPool, JSON_HEADERS } = require('./mock.js') + const Nano = require('..') -const COUCH_URL = 'http://localhost:5984' const nano = Nano(COUCH_URL) -const nock = require('nock') const response = { history: [], ok: true, @@ -22,34 +24,34 @@ const response = { source_last_seq: 28 } -afterEach(() => { - nock.cleanAll() -}) - test('should be able to send replication request with local database names - POST /_replicate - nano.db.replicate', async () => { // mocks - const scope = nock(COUCH_URL) - .post('/_replicate', { source: COUCH_URL + '/source', target: COUCH_URL + '/target' }) - .reply(200, response) + mockPool.intercept({ + method: 'post', + path: '/_replicate', + body: JSON.stringify({ source: COUCH_URL + '/source', target: COUCH_URL + '/target' }) + }).reply(200, response, JSON_HEADERS) // test POST /_replicate const p = await nano.db.replicate('source', 'target') - expect(p).toEqual(response) - expect(scope.isDone()).toBe(true) + assert.deepEqual(p, response) + mockAgent.assertNoPendingInterceptors() }) test('should be able to send replication request with URLs - POST /_replicate - nano.db.replicate', async () => { // mocks const source = 'http://mydomain1.com/source' const target = 'https://mydomain2.com/target' - const scope = nock(COUCH_URL) - .post('/_replicate', { source, target }) - .reply(200, response) + mockPool.intercept({ + method: 'post', + path: '/_replicate', + body: JSON.stringify({ source, target }) + }).reply(200, response, JSON_HEADERS) // test POST /_replicate const p = await nano.db.replicate(source, target) - expect(p).toEqual(response) - expect(scope.isDone()).toBe(true) + assert.deepEqual(p, response) + mockAgent.assertNoPendingInterceptors() }) test('should be able to supply additional parameters - POST /_replicate - nano.db.replicate', async () => { @@ -57,40 +59,35 @@ test('should be able to supply additional parameters - POST /_replicate - nano.d const source = 'http://mydomain1.com/source' const target = 'https://mydomain2.com/target' const opts = { filter: 'ddoc/func', continuous: true } - const scope = nock(COUCH_URL) - .post('/_replicate', Object.assign(opts, { source, target })) - .reply(200, response) + mockPool.intercept({ + method: 'post', + path: '/_replicate', + body: JSON.stringify(Object.assign(opts, { source, target })) + }).reply(200, response, JSON_HEADERS) // test POST /_replicate const p = await nano.db.replicate(source, target, opts) - expect(p).toEqual(response) - expect(scope.isDone()).toBe(true) + assert.deepEqual(p, response) + mockAgent.assertNoPendingInterceptors() }) test('should not attempt compact invalid parameters - nano.db.replicate', async () => { - await expect(nano.db.replicate('')).rejects.toThrowError('Invalid parameters') - await expect(nano.db.replicate(undefined, 'target')).rejects.toThrowError('Invalid parameters') - await expect(nano.db.replicate('', 'target')).rejects.toThrowError('Invalid parameters') -}) - -test('should detect missing parameters (callback) - nano.db.replicate', () => { - return new Promise((resolve, reject) => { - nano.db.replicate(undefined, undefined, undefined, (err, data) => { - expect(err).not.toBeNull() - resolve() - }) - }) + await assert.rejects(nano.db.replicate(''), { message: 'Invalid parameters' }) + await assert.rejects(nano.db.replicate(undefined, 'target'), { message: 'Invalid parameters' }) + await assert.rejects(nano.db.replicate('', 'target'), { message: 'Invalid parameters' }) }) test('should be replicate from db.replicate - POST /_replicate - db.replicate', async () => { // mocks - const scope = nock(COUCH_URL) - .post('/_replicate', { source: COUCH_URL + '/source', target: COUCH_URL + '/target' }) - .reply(200, response) + mockPool.intercept({ + method: 'post', + path: '/_replicate', + body: JSON.stringify({ source: COUCH_URL + '/source', target: COUCH_URL + '/target' }) + }).reply(200, response, JSON_HEADERS) // test POST /_replicate const db = nano.db.use('source') const p = await db.replicate('target') - expect(p).toEqual(response) - expect(scope.isDone()).toBe(true) + assert.deepEqual(p, response) + mockAgent.assertNoPendingInterceptors() }) diff --git a/test/database.replication.disable.test.js b/test/database.replication.disable.test.js index 273d734d..04e1f9b0 100644 --- a/test/database.replication.disable.test.js +++ b/test/database.replication.disable.test.js @@ -10,70 +10,59 @@ // License for the specific language governing permissions and limitations under // the License. +const test = require('node:test') +const assert = require('node:assert/strict') +const { COUCH_URL, mockAgent, mockPool, JSON_HEADERS } = require('./mock.js') + const Nano = require('..') -const COUCH_URL = 'http://localhost:5984' const nano = Nano(COUCH_URL) -const nock = require('nock') const response = { ok: true, id: 'rep1', rev: '2-123' } const errResponse = { error: 'not_found', reason: 'missing' } -afterEach(() => { - nock.cleanAll() -}) - test('should be able to delete a replication - DELETE /_replicator/id - nano.db.replication.disable', async () => { // mocks - const scope = nock(COUCH_URL) - .delete('/_replicator/rep1') - .query({ rev: '1-456' }) - .reply(200, response) + mockPool.intercept({ + method: 'delete', + path: '/_replicator/rep1?rev=1-456' + }).reply(200, response, JSON_HEADERS) // test DELETE /_replicator/id const p = await nano.db.replication.disable('rep1', '1-456') - expect(p).toEqual(response) - expect(scope.isDone()).toBe(true) + assert.deepEqual(p, response) + mockAgent.assertNoPendingInterceptors() }) test('should be able to handle a 404 - DELETE /_replicator/id - nano.db.replication.disable', async () => { // mocks - const scope = nock(COUCH_URL) - .delete('/_replicator/rep1') - .query({ rev: '1-456' }) - .reply(404, errResponse) + mockPool.intercept({ + method: 'delete', + path: '/_replicator/rep1?rev=1-456' + }).reply(404, errResponse, JSON_HEADERS) // test DELETE /_replicator/id - await expect(nano.db.replication.disable('rep1', '1-456')).rejects.toThrow('missing') - expect(scope.isDone()).toBe(true) + await assert.rejects(nano.db.replication.disable('rep1', '1-456'), { message: 'missing' }) + mockAgent.assertNoPendingInterceptors() }) test('should not to try to disable with invalid parameters - nano.db.replication.disable', async () => { - await expect(nano.db.replication.disable(undefined, '1-456')).rejects.toThrowError('Invalid parameters') - await expect(nano.db.replication.disable('', '1-456')).rejects.toThrowError('Invalid parameters') - await expect(nano.db.replication.disable('rep1')).rejects.toThrowError('Invalid parameters') -}) - -test('should detect missing parameters (callback) - nano.db.replication.disable', () => { - return new Promise((resolve, reject) => { - nano.db.replication.disable(undefined, undefined, (err, data) => { - expect(err).not.toBeNull() - resolve() - }) - }) + await assert.rejects(nano.db.replication.disable(undefined, '1-456'), { message: 'Invalid parameters' }) + await assert.rejects(nano.db.replication.disable('', '1-456'), { message: 'Invalid parameters' }) + await assert.rejects(nano.db.replication.disable('rep1'), { message: 'Invalid parameters' }) }) test('should be able to delete a replication from db.replication.disable - DELETE /_replicator/id - db.replication.disable', async () => { // mocks - const scope = nock(COUCH_URL) - .delete('/_replicator/rep1') - .query({ rev: '1-456' }) - .reply(200, response) + mockPool.intercept({ + method: 'delete', + path: '/_replicator/rep1?rev=1-456' + }).reply(200, response, JSON_HEADERS) // test DELETE /_replicator/id const db = nano.db.use('db') const p = await db.replication.disable('rep1', '1-456') - expect(p).toEqual(response) - expect(scope.isDone()).toBe(true) + assert.deepEqual(p, response) + mockAgent.assertNoPendingInterceptors() }) diff --git a/test/database.replication.enable.test.js b/test/database.replication.enable.test.js index e887a3fa..38b64bc2 100644 --- a/test/database.replication.enable.test.js +++ b/test/database.replication.enable.test.js @@ -10,54 +10,58 @@ // License for the specific language governing permissions and limitations under // the License. +const test = require('node:test') +const assert = require('node:assert/strict') +const { COUCH_URL, mockAgent, mockPool, JSON_HEADERS } = require('./mock.js') + const Nano = require('..') -const COUCH_URL = 'http://localhost:5984' const nano = Nano(COUCH_URL) -const nock = require('nock') const response = { ok: true, id: 'abc', rev: '1-123' } -afterEach(() => { - nock.cleanAll() -}) - test('should be able to send replication request with local database names - POST /_replicator - nano.db.replication.enable', async () => { // mocks - const scope = nock(COUCH_URL) - .post('/_replicator', { source: COUCH_URL + '/source', target: COUCH_URL + '/target' }) - .reply(200, response) + mockPool.intercept({ + method: 'post', + path: '/_replicator', + body: JSON.stringify({ source: COUCH_URL + '/source', target: COUCH_URL + '/target' }) + }).reply(200, response, JSON_HEADERS) // test POST /_replicator const p = await nano.db.replication.enable('source', 'target') - expect(p).toEqual(response) - expect(scope.isDone()).toBe(true) + assert.deepEqual(p, response) + mockAgent.assertNoPendingInterceptors() }) test('should be able to send replication request with URLs - POST /_replicator - nano.db.replication.enable', async () => { // mocks const source = 'http://mydomain1.com/source' const target = 'https://mydomain2.com/target' - const scope = nock(COUCH_URL) - .post('/_replicator', { source, target }) - .reply(200, response) + mockPool.intercept({ + method: 'post', + path: '/_replicator', + body: JSON.stringify({ source, target }) + }).reply(200, response, JSON_HEADERS) // test POST /_replicator const p = await nano.db.replication.enable(source, target) - expect(p).toEqual(response) - expect(scope.isDone()).toBe(true) + assert.deepEqual(p, response) + mockAgent.assertNoPendingInterceptors() }) test('should be able to send replication request with objects - POST /_replicator - nano.db.replication.enable', async () => { // mocks const source = { config: { url: 'http://mydomain1.com', db: 'source' } } const target = { config: { url: 'https://mydomain2.com', db: 'target' } } - const scope = nock(COUCH_URL) - .post('/_replicator', { source: 'http://mydomain1.com/source', target: 'https://mydomain2.com/target' }) - .reply(200, response) + mockPool.intercept({ + method: 'post', + path: '/_replicator', + body: JSON.stringify({ source: 'http://mydomain1.com/source', target: 'https://mydomain2.com/target' }) + }).reply(200, response, JSON_HEADERS) // test POST /_replicator const p = await nano.db.replication.enable(source, target) - expect(p).toEqual(response) - expect(scope.isDone()).toBe(true) + assert.deepEqual(p, response) + mockAgent.assertNoPendingInterceptors() }) test('should be able to supply additional parameters - POST /_replicator - nano.db.replication.enable', async () => { @@ -65,41 +69,36 @@ test('should be able to supply additional parameters - POST /_replicator - nano. const source = 'http://mydomain1.com/source' const target = 'https://mydomain2.com/target' const opts = { filter: 'ddoc/func', continuous: true } - const scope = nock(COUCH_URL) - .post('/_replicator', Object.assign(opts, { source, target })) - .reply(200, response) + mockPool.intercept({ + method: 'post', + path: '/_replicator', + body: JSON.stringify(Object.assign(opts, { source, target })) + }).reply(200, response, JSON_HEADERS) // test POST /_replicator const p = await nano.db.replication.enable(source, target, opts) - expect(p).toEqual(response) - expect(scope.isDone()).toBe(true) + assert.deepEqual(p, response) + mockAgent.assertNoPendingInterceptors() }) test('should not attempt compact with invalid parameters - nano.db.replication.enable', async () => { - await expect(nano.db.replication.enable(undefined, 'target')).rejects.toThrowError('Invalid parameters') - await expect(nano.db.replication.enable()).rejects.toThrowError('Invalid parameters') - await expect(nano.db.replication.enable('source')).rejects.toThrowError('Invalid parameters') - await expect(nano.db.replication.enable('source', '')).rejects.toThrowError('Invalid parameters') -}) - -test('should detect missing parameters (callback) - nano.db.replication.enable', () => { - return new Promise((resolve, reject) => { - nano.db.replication.enable(undefined, undefined, undefined, (err, data) => { - expect(err).not.toBeNull() - resolve() - }) - }) + await assert.rejects(nano.db.replication.enable(undefined, 'target'), { message: 'Invalid parameters' }) + await assert.rejects(nano.db.replication.enable(), { message: 'Invalid parameters' }) + await assert.rejects(nano.db.replication.enable('source'), { message: 'Invalid parameters' }) + await assert.rejects(nano.db.replication.enable('source', ''), { message: 'Invalid parameters' }) }) test('should be able to send replication request db.replication.enable - POST /_replicator - db.replication.enable', async () => { // mocks - const scope = nock(COUCH_URL) - .post('/_replicator', { source: COUCH_URL + '/source', target: COUCH_URL + '/target' }) - .reply(200, response) + mockPool.intercept({ + method: 'post', + path: '/_replicator', + body: JSON.stringify({ source: COUCH_URL + '/source', target: COUCH_URL + '/target' }) + }).reply(200, response, JSON_HEADERS) // test POST /_replicator const db = nano.db.use('source') const p = await db.replication.enable('target') - expect(p).toEqual(response) - expect(scope.isDone()).toBe(true) + assert.deepEqual(p, response) + mockAgent.assertNoPendingInterceptors() }) diff --git a/test/database.replication.query.test.js b/test/database.replication.query.test.js index 26b8fedf..e15d016e 100644 --- a/test/database.replication.query.test.js +++ b/test/database.replication.query.test.js @@ -10,15 +10,16 @@ // License for the specific language governing permissions and limitations under // the License. +const test = require('node:test') +const assert = require('node:assert/strict') +const { COUCH_URL, mockAgent, mockPool, JSON_HEADERS } = require('./mock.js') const Nano = require('..') -const COUCH_URL = 'http://localhost:5984' const nano = Nano(COUCH_URL) -const nock = require('nock') const response = { _id: 'rep1', _rev: '2-05a9e090e2bb0977c06b870c870153c5', - source: 'http://localhost:5984/cities', - target: 'http://localhost:5984/cities2', + source: 'http://127.0.0.1:5984/cities', + target: 'http://127.0.0.1:5984/cities2', create_target: true, continuous: false, owner: 'admin', @@ -40,70 +41,56 @@ const errResponse = { reason: 'missing' } -afterEach(() => { - nock.cleanAll() -}) - test('should be able to query a replication - GET /_replicator/id - nano.db.replication.query', async () => { // mocks - const scope = nock(COUCH_URL) - .get('/_replicator/rep1') - .reply(200, response) + mockPool + .intercept({ path: '/_replicator/rep1' }) + .reply(200, response, JSON_HEADERS) // test GET /_replicator/id const p = await nano.db.replication.query('rep1') - expect(p).toEqual(response) - expect(scope.isDone()).toBe(true) + assert.deepEqual(p, response) + mockAgent.assertNoPendingInterceptors() }) test('should be able to query a replication with opts - GET /_replicator/id?confilicts=true - nano.db.replication.query', async () => { // mocks const opts = { conflicts: true } - const scope = nock(COUCH_URL) - .get('/_replicator/rep1') - .query(opts) - .reply(200, response) + mockPool.intercept({ + path: '/_replicator/rep1?conflicts=true' + }).reply(200, response, JSON_HEADERS) // test GET /_replicator/id const p = await nano.db.replication.query('rep1', opts) - expect(p).toEqual(response) - expect(scope.isDone()).toBe(true) + assert.deepEqual(p, response) + mockAgent.assertNoPendingInterceptors() }) test('should be able to query a replication and handle 404 - GET /_replicator/id - nano.db.replication.query', async () => { // mocks - const scope = nock(COUCH_URL) - .get('/_replicator/rep1') - .reply(404, errResponse) + mockPool.intercept({ + path: '/_replicator/rep1' + }).reply(404, errResponse, JSON_HEADERS) // test GET /_replicator/id - await expect(nano.db.replication.query('rep1')).rejects.toThrow('missing') - expect(scope.isDone()).toBe(true) + await assert.rejects(nano.db.replication.query('rep1'), { message: 'missing' }) + mockAgent.assertNoPendingInterceptors() }) test('should not attempt info fetch with invalid parameters - nano.db.replication.query', async () => { - await expect(nano.db.replication.query('')).rejects.toThrowError('Invalid parameters') - await expect(nano.db.replication.query()).rejects.toThrowError('Invalid parameters') -}) - -test('should detect missing parameters (callback) - nano.db.replication.query', () => { - return new Promise((resolve, reject) => { - nano.db.replication.query(undefined, undefined, (err, data) => { - expect(err).not.toBeNull() - resolve() - }) - }) + await assert.rejects(nano.db.replication.query(''), { message: 'Invalid parameters' }) + await assert.rejects(nano.db.replication.query(), { message: 'Invalid parameters' }) }) test('should be able to query a replication from db.replication.quey - GET /_replicator/id - db.replication.query', async () => { // mocks - const scope = nock(COUCH_URL) - .get('/_replicator/rep1') - .reply(200, response) + mockPool.intercept({ + path: '/_replicator/rep1' + }).reply(200, response, JSON_HEADERS) // test GET /_replicator/id const db = nano.db.use('db') const p = await db.replication.query('rep1') - expect(p).toEqual(response) - expect(scope.isDone()).toBe(true) + assert.deepEqual(p, response) + mockAgent.assertNoPendingInterceptors() }) diff --git a/test/design.atomic.test.js b/test/design.atomic.test.js index 8087edd5..a471b7bc 100644 --- a/test/design.atomic.test.js +++ b/test/design.atomic.test.js @@ -10,14 +10,11 @@ // License for the specific language governing permissions and limitations under // the License. +const test = require('node:test') +const assert = require('node:assert/strict') +const { COUCH_URL, mockAgent, mockPool, JSON_HEADERS } = require('./mock.js') const Nano = require('..') -const COUCH_URL = 'http://localhost:5984' const nano = Nano(COUCH_URL) -const nock = require('nock') - -afterEach(() => { - nock.cleanAll() -}) test('should be able to use an update function - PUT /db/_design/ddoc/_update/updatename/docid - db.atomic', async () => { const updateFunction = function (doc, req) { @@ -29,15 +26,18 @@ test('should be able to use an update function - PUT /db/_design/ddoc/_update/up const response = updateFunction({})[1].json // mocks - const scope = nock(COUCH_URL) - .put('/db/_design/ddoc/_update/updatename/docid') - .reply(200, response) + mockPool + .intercept({ + method: 'put', + path: '/db/_design/ddoc/_update/updatename/docid' + }) + .reply(200, response, JSON_HEADERS) // test PUT /db/_design/ddoc/_update/updatename/docid const db = nano.db.use('db') const p = await db.atomic('ddoc', 'updatename', 'docid') - expect(p).toStrictEqual(response) - expect(scope.isDone()).toBe(true) + assert.deepEqual(p, response) + mockAgent.assertNoPendingInterceptors() }) test('should be able to use an update function with body - PUT /db/_design/ddoc/_update/updatename/docid - db.atomic', async () => { @@ -51,15 +51,19 @@ test('should be able to use an update function with body - PUT /db/_design/ddoc/ const response = updateFunction({})[1].json // mocks - const scope = nock(COUCH_URL) - .put('/db/_design/ddoc/_update/updatename/docid', body) - .reply(200, response) + mockPool + .intercept({ + method: 'put', + path: '/db/_design/ddoc/_update/updatename/docid', + body: JSON.stringify(body) + }) + .reply(200, response, JSON_HEADERS) // test PUT /db/_design/ddoc/_update/updatename/docid const db = nano.db.use('db') const p = await db.atomic('ddoc', 'updatename', 'docid', body) - expect(p).toStrictEqual(response) - expect(scope.isDone()).toBe(true) + assert.deepEqual(p, response) + mockAgent.assertNoPendingInterceptors() }) test('should be able to handle 404 - db.atomic', async () => { @@ -69,40 +73,24 @@ test('should be able to handle 404 - db.atomic', async () => { reason: 'missing' } const body = { a: 1, b: 2 } - const scope = nock(COUCH_URL) - .put('/db/_design/ddoc/_update/updatename/docid', body) - .reply(404, response) + mockPool + .intercept({ + method: 'put', + path: '/db/_design/ddoc/_update/updatename/docid', + body: JSON.stringify(body) + }) + .reply(404, response, JSON_HEADERS) // test PUT /db/_design/ddoc/_update/updatename/docid const db = nano.db.use('db') - await expect(db.atomic('ddoc', 'updatename', 'docid', body)).rejects.toThrow('missing') - expect(scope.isDone()).toBe(true) + await assert.rejects(db.atomic('ddoc', 'updatename', 'docid', body), { message: 'missing' }) + mockAgent.assertNoPendingInterceptors() }) test('should detect missing parameters - db.update', async () => { const db = nano.db.use('db') - await expect(db.atomic()).rejects.toThrow('Invalid parameters') - await expect(db.atomic('ddoc')).rejects.toThrow('Invalid parameters') - await expect(db.atomic('ddoc', 'updatename')).rejects.toThrow('Invalid parameters') - await expect(db.atomic('', 'updatename', 'docid')).rejects.toThrow('Invalid parameters') -}) - -test('should detect missing parameters (callback) - db.update', () => { - const db = nano.db.use('db') - return new Promise((resolve, reject) => { - db.atomic('', '', '', {}, (err, data) => { - expect(err).not.toBeNull() - resolve() - }) - }) -}) - -test('should detect missing parameters (callback no body) - db.update', () => { - const db = nano.db.use('db') - return new Promise((resolve, reject) => { - db.atomic('', '', '', (err, data) => { - expect(err).not.toBeNull() - resolve() - }) - }) + await assert.rejects(db.atomic(), { message: 'Invalid parameters' }) + await assert.rejects(db.atomic('ddoc'), { message: 'Invalid parameters' }) + await assert.rejects(db.atomic('ddoc', 'updatename'), { message: 'Invalid parameters' }) + await assert.rejects(db.atomic('', 'updatename', 'docid'), { message: 'Invalid parameters' }) }) diff --git a/test/design.createIndex.test.js b/test/design.createIndex.test.js index a26e1ab6..48028631 100644 --- a/test/design.createIndex.test.js +++ b/test/design.createIndex.test.js @@ -10,14 +10,11 @@ // License for the specific language governing permissions and limitations under // the License. +const test = require('node:test') +const assert = require('node:assert/strict') +const { COUCH_URL, mockAgent, mockPool, JSON_HEADERS } = require('./mock.js') const Nano = require('..') -const COUCH_URL = 'http://localhost:5984' const nano = Nano(COUCH_URL) -const nock = require('nock') - -afterEach(() => { - nock.cleanAll() -}) test('should be able to create an index - POST /db/_index - db.createIndex', async () => { // mocks @@ -34,15 +31,19 @@ test('should be able to create an index - POST /db/_index - db.createIndex', asy id: '_design/a5f4711fc9448864a13c81dc71e660b524d7410c', name: 'foo-index' } - const scope = nock(COUCH_URL) - .post('/db/_index', indexDef) - .reply(200, response) + mockPool + .intercept({ + method: 'post', + path: '/db/_index', + body: JSON.stringify(indexDef) + }) + .reply(200, response, JSON_HEADERS) // test POST /db/_index const db = nano.db.use('db') const p = await db.createIndex(indexDef) - expect(p).toStrictEqual(response) - expect(scope.isDone()).toBe(true) + assert.deepEqual(p, response) + mockAgent.assertNoPendingInterceptors() }) test('should handle 404 - POST /db/_index - db.createIndex', async () => { @@ -59,28 +60,23 @@ test('should handle 404 - POST /db/_index - db.createIndex', async () => { error: 'not_found', reason: 'missing' } - const scope = nock(COUCH_URL) - .post('/db/_index', indexDef) - .reply(404, response) + mockPool + .intercept({ + method: 'post', + path: '/db/_index', + body: JSON.stringify(indexDef) + }) + .reply(404, response, JSON_HEADERS) // test POST /db/_index const db = nano.db.use('db') - await expect(db.createIndex(indexDef)).rejects.toThrow('missing') - expect(scope.isDone()).toBe(true) + await assert.rejects(db.createIndex(indexDef), { message: 'missing' }) + mockAgent.assertNoPendingInterceptors() }) test('should detect missing index - db.createIndex', async () => { const db = nano.db.use('db') - await expect(db.createIndex()).rejects.toThrow('Invalid parameters') - await expect(db.createIndex('myindex')).rejects.toThrow('Invalid parameters') + await assert.rejects(db.createIndex(), { message: 'Invalid parameters' }) + await assert.rejects(db.createIndex('myindex'), { message: 'Invalid parameters' }) }) -test('should detect missing index (callback) - db.createIndex', () => { - const db = nano.db.use('db') - return new Promise((resolve, reject) => { - db.createIndex('', (err, data) => { - expect(err).not.toBeNull() - resolve() - }) - }) -}) diff --git a/test/design.find.test.js b/test/design.find.test.js index 354f9060..07895823 100644 --- a/test/design.find.test.js +++ b/test/design.find.test.js @@ -10,14 +10,11 @@ // License for the specific language governing permissions and limitations under // the License. +const test = require('node:test') +const assert = require('node:assert/strict') +const { COUCH_URL, mockAgent, mockPool, JSON_HEADERS } = require('./mock.js') const Nano = require('..') -const COUCH_URL = 'http://localhost:5984' const nano = Nano(COUCH_URL) -const nock = require('nock') - -afterEach(() => { - nock.cleanAll() -}) test('should be able to query an index - POST /db/_find - db.find', async () => { // mocks @@ -38,15 +35,19 @@ test('should be able to query an index - POST /db/_find - db.find', async () => { name: 'Susan', date: '2019-01-03', orderid: '8523' } ] } - const scope = nock(COUCH_URL) - .post('/db/_find', query) - .reply(200, response) + mockPool + .intercept({ + method: 'post', + path: '/db/_find', + body: JSON.stringify(query) + }) + .reply(200, response, JSON_HEADERS) // test POST /db/_find const db = nano.db.use('db') const p = await db.find(query) - expect(p).toStrictEqual(response) - expect(scope.isDone()).toBe(true) + assert.deepEqual(p, response) + mockAgent.assertNoPendingInterceptors() }) test('should handle 404 - POST /db/_find - db.find', async () => { @@ -60,28 +61,23 @@ test('should handle 404 - POST /db/_find - db.find', async () => { error: 'not_found', reason: 'missing' } - const scope = nock(COUCH_URL) - .post('/db/_find', query) - .reply(404, response) + mockPool + .intercept({ + method: 'post', + path: '/db/_find', + body: JSON.stringify(query) + }) + .reply(404, response, JSON_HEADERS) // test POST /db/_find const db = nano.db.use('db') - await expect(db.find(query)).rejects.toThrow('missing') - expect(scope.isDone()).toBe(true) + await assert.rejects(db.find(query), { message: 'missing' }) + mockAgent.assertNoPendingInterceptors() }) test('should detect missing query - db.find', async () => { const db = nano.db.use('db') - await expect(db.find()).rejects.toThrow('Invalid parameters') - await expect(db.find('susan')).rejects.toThrow('Invalid parameters') + await assert.rejects(db.find(), { message: 'Invalid parameters' }) + await assert.rejects(db.find('susan'), { message: 'Invalid parameters' }) }) -test('should detect missing query (callback) - db.find', () => { - const db = nano.db.use('db') - return new Promise((resolve, reject) => { - db.find('', (err, data) => { - expect(err).not.toBeNull() - resolve() - }) - }) -}) diff --git a/test/design.findAsStream.test.js b/test/design.findAsStream.test.js index cb1aca8d..3a317ce8 100644 --- a/test/design.findAsStream.test.js +++ b/test/design.findAsStream.test.js @@ -10,16 +10,13 @@ // License for the specific language governing permissions and limitations under // the License. +const test = require('node:test') +const assert = require('node:assert/strict') +const { COUCH_URL, mockAgent, mockPool, JSON_HEADERS } = require('./mock.js') const Nano = require('..') -const COUCH_URL = 'http://localhost:5984' const nano = Nano(COUCH_URL) -const nock = require('nock') -afterEach(() => { - nock.cleanAll() -}) - -test('should be able to query an index as a stream- POST /db/_find - db.findAsStream', () => { +test('should be able to query an index as a stream- POST /db/_find - db.findAsStream', async () => { // mocks const query = { selector: { @@ -38,22 +35,26 @@ test('should be able to query an index as a stream- POST /db/_find - db.findAsSt { name: 'Susan', date: '2019-01-03', orderid: '8523' } ] } - const scope = nock(COUCH_URL) - .post('/db/_find', query) - .reply(200, response) + mockPool + .intercept({ + method: 'post', + path: '/db/_find', + body: JSON.stringify(query) + }) + .reply(200, response, JSON_HEADERS) - return new Promise((resolve, reject) => { + await new Promise((resolve, reject) => { // test POST /db/_find const db = nano.db.use('db') const s = db.findAsStream(query) - expect(typeof s).toBe('object') + assert.equal(typeof s, 'object') let buffer = '' s.on('data', (chunk) => { buffer += chunk.toString() }) s.on('end', () => { - expect(buffer).toBe(JSON.stringify(response)) - expect(scope.isDone()).toBe(true) + assert.equal(buffer, JSON.stringify(response)) + mockAgent.assertNoPendingInterceptors() resolve() }) }) diff --git a/test/design.search.test.js b/test/design.search.test.js index 1cc22311..ac02f85c 100644 --- a/test/design.search.test.js +++ b/test/design.search.test.js @@ -10,14 +10,11 @@ // License for the specific language governing permissions and limitations under // the License. +const test = require('node:test') +const assert = require('node:assert/strict') +const { COUCH_URL, mockAgent, mockPool, JSON_HEADERS } = require('./mock.js') const Nano = require('..') -const COUCH_URL = 'http://localhost:5984' const nano = Nano(COUCH_URL) -const nock = require('nock') - -afterEach(() => { - nock.cleanAll() -}) test('should be able to access a search index - POST /db/_design/ddoc/_search/searchname - db.search', async () => { // mocks @@ -29,15 +26,19 @@ test('should be able to access a search index - POST /db/_design/ddoc/_search/se ] } const params = { q: '*:*' } - const scope = nock(COUCH_URL) - .post('/db/_design/ddoc/_search/searchname', params) - .reply(200, response) + mockPool + .intercept({ + method: 'post', + path: '/db/_design/ddoc/_search/searchname', + body: JSON.stringify(params) + }) + .reply(200, response, JSON_HEADERS) // test POST /db/_design/ddoc/_search/searchnameGET /db const db = nano.db.use('db') const p = await db.search('ddoc', 'searchname', params) - expect(p).toStrictEqual(response) - expect(scope.isDone()).toBe(true) + assert.deepEqual(p, response) + mockAgent.assertNoPendingInterceptors() }) test('should be able to handle 404 - db.search', async () => { @@ -47,30 +48,25 @@ test('should be able to handle 404 - db.search', async () => { reason: 'missing' } const params = { q: '*:*' } - const scope = nock(COUCH_URL) - .post('/db/_design/ddoc/_search/searchname', params) - .reply(404, response) + mockPool + .intercept({ + method: 'post', + path: '/db/_design/ddoc/_search/searchname', + body: JSON.stringify(params) + }) + .reply(404, response, JSON_HEADERS) // test POST /db/_design/ddoc/_search/searchname const db = nano.db.use('db') - await expect(db.search('ddoc', 'searchname', params)).rejects.toThrow('missing') - expect(scope.isDone()).toBe(true) + await assert.rejects(db.search('ddoc', 'searchname', params), { message: 'missing' }) + mockAgent.assertNoPendingInterceptors() }) test('should detect missing parameters - db.search', async () => { const db = nano.db.use('db') - await expect(db.search()).rejects.toThrow('Invalid parameters') - await expect(db.search('susan')).rejects.toThrow('Invalid parameters') - await expect(db.search('susan', '')).rejects.toThrow('Invalid parameters') - await expect(db.search('', 'susan')).rejects.toThrow('Invalid parameters') + await assert.rejects(db.search(), { message: 'Invalid parameters' }) + await assert.rejects(db.search('susan'), { message: 'Invalid parameters' }) + await assert.rejects(db.search('susan', ''), { message: 'Invalid parameters' }) + await assert.rejects(db.search('', 'susan'), { message: 'Invalid parameters' }) }) -test('should detect missing parameters (callback) - db.search', () => { - const db = nano.db.use('db') - return new Promise((resolve, reject) => { - db.search('', '', (err, data) => { - expect(err).not.toBeNull() - resolve() - }) - }) -}) diff --git a/test/design.searchAsStream.test.js b/test/design.searchAsStream.test.js index b2c4af20..0d1348f9 100644 --- a/test/design.searchAsStream.test.js +++ b/test/design.searchAsStream.test.js @@ -10,16 +10,13 @@ // License for the specific language governing permissions and limitations under // the License. +const test = require('node:test') +const assert = require('node:assert/strict') +const { COUCH_URL, mockAgent, mockPool, JSON_HEADERS } = require('./mock.js') const Nano = require('..') -const COUCH_URL = 'http://localhost:5984' const nano = Nano(COUCH_URL) -const nock = require('nock') -afterEach(() => { - nock.cleanAll() -}) - -test('should be able to access a search index as a stream - POST /db/_design/ddoc/_search/searchname - db.searchAsStream', () => { +test('should be able to access a search index as a stream - POST /db/_design/ddoc/_search/searchname - db.searchAsStream', async () => { // mocks const response = { total_rows: 100000, @@ -29,21 +26,25 @@ test('should be able to access a search index as a stream - POST /db/_design/ddo ] } const params = { q: '*:*' } - const scope = nock(COUCH_URL) - .post('/db/_design/ddoc/_search/searchname', params) - .reply(200, response) + mockPool + .intercept({ + method: 'post', + path: '/db/_design/ddoc/_search/searchname', + body: JSON.stringify(params) + }) + .reply(200, response, JSON_HEADERS) - return new Promise((resolve, reject) => { + await new Promise((resolve, reject) => { const db = nano.db.use('db') const s = db.searchAsStream('ddoc', 'searchname', params) - expect(typeof s).toBe('object') + assert.equal(typeof s, 'object') let buffer = '' s.on('data', (chunk) => { buffer += chunk.toString() }) s.on('end', () => { - expect(buffer).toBe(JSON.stringify(response)) - expect(scope.isDone()).toBe(true) + assert.equal(buffer, JSON.stringify(response)) + mockAgent.assertNoPendingInterceptors() resolve() }) }) diff --git a/test/design.show.test.js b/test/design.show.test.js index 92ad4c99..90d6847f 100644 --- a/test/design.show.test.js +++ b/test/design.show.test.js @@ -10,29 +10,26 @@ // License for the specific language governing permissions and limitations under // the License. +const test = require('node:test') +const assert = require('node:assert/strict') +const { COUCH_URL, mockAgent, mockPool, JSON_HEADERS } = require('./mock.js') const Nano = require('..') -const COUCH_URL = 'http://localhost:5984' const nano = Nano(COUCH_URL) -const nock = require('nock') - -afterEach(() => { - nock.cleanAll() -}) test('should be able to use a show function - GET /db/_design/ddoc/_show/showname/docid - db.show', async () => { const showFunction = function (doc, req) { return 'Hello, world!' } // mocks - const scope = nock(COUCH_URL) - .get('/db/_design/ddoc/_show/showname/docid') - .reply(200, showFunction(), { 'Content-type': 'text/plain' }) + mockPool + .intercept({ path: '/db/_design/ddoc/_show/showname/docid' }) + .reply(200, showFunction(), { headers: { 'content-type': 'text/plain' } }) // test GET /db/_design/ddoc/_show/showname/docid const db = nano.db.use('db') const p = await db.show('ddoc', 'showname', 'docid') - expect(p).toStrictEqual(showFunction()) - expect(scope.isDone()).toBe(true) + assert.equal(p, showFunction()) + mockAgent.assertNoPendingInterceptors() }) test('should be able to handle 404 - db.show', async () => { @@ -41,30 +38,21 @@ test('should be able to handle 404 - db.show', async () => { error: 'not_found', reason: 'missing' } - const scope = nock(COUCH_URL) - .get('/db/_design/ddoc/_show/showname/docid') - .reply(404, response) + mockPool + .intercept({ path: '/db/_design/ddoc/_show/showname/docid' }) + .reply(404, response, JSON_HEADERS) // test GET /db/_design/ddoc/_show/showname/docid const db = nano.db.use('db') - await expect(db.show('ddoc', 'showname', 'docid')).rejects.toThrow('missing') - expect(scope.isDone()).toBe(true) + await assert.rejects(db.show('ddoc', 'showname', 'docid'), { message: 'missing' }) + mockAgent.assertNoPendingInterceptors() }) test('should detect missing parameters - db.show', async () => { const db = nano.db.use('db') - await expect(db.show()).rejects.toThrow('Invalid parameters') - await expect(db.show('ddoc')).rejects.toThrow('Invalid parameters') - await expect(db.show('ddoc', 'showname')).rejects.toThrow('Invalid parameters') - await expect(db.show('', 'showname', 'docid')).rejects.toThrow('Invalid parameters') + await assert.rejects(db.show(), { message: 'Invalid parameters' }) + await assert.rejects(db.show('ddoc'), { message: 'Invalid parameters' }) + await assert.rejects(db.show('ddoc', 'showname'), { message: 'Invalid parameters' }) + await assert.rejects(db.show('', 'showname', 'docid'), { message: 'Invalid parameters' }) }) -test('should detect missing parameters (callback) - db.show', () => { - const db = nano.db.use('db') - return new Promise((resolve, reject) => { - db.show('', '', '', {}, (err, data) => { - expect(err).not.toBeNull() - resolve() - }) - }) -}) diff --git a/test/design.view.test.js b/test/design.view.test.js index 0e8310eb..a36f24a3 100644 --- a/test/design.view.test.js +++ b/test/design.view.test.js @@ -10,14 +10,11 @@ // License for the specific language governing permissions and limitations under // the License. +const test = require('node:test') +const assert = require('node:assert/strict') +const { COUCH_URL, mockAgent, mockPool, JSON_HEADERS } = require('./mock.js') const Nano = require('..') -const COUCH_URL = 'http://localhost:5984' const nano = Nano(COUCH_URL) -const nock = require('nock') - -afterEach(() => { - nock.cleanAll() -}) test('should be able to access a MapReduce view - GET /db/_design/ddoc/_view/viewname - db.view', async () => { // mocks @@ -26,15 +23,15 @@ test('should be able to access a MapReduce view - GET /db/_design/ddoc/_view/vie { key: null, value: 23515 } ] } - const scope = nock(COUCH_URL) - .get('/db/_design/ddoc/_view/viewname') - .reply(200, response) + mockPool + .intercept({ path: '/db/_design/ddoc/_view/viewname' }) + .reply(200, response, JSON_HEADERS) // test GET /db/_design/ddoc/_view/viewname const db = nano.db.use('db') const p = await db.view('ddoc', 'viewname') - expect(p).toStrictEqual(response) - expect(scope.isDone()).toBe(true) + assert.deepEqual(p, response) + mockAgent.assertNoPendingInterceptors() }) test('should be able to access a MapReduce view with opts - GET /db/_design/ddoc/_view/viewname - db.view', async () => { @@ -57,15 +54,15 @@ test('should be able to access a MapReduce view with opts - GET /db/_design/ddoc { key: 'BQ', value: 1 } ] } - const scope = nock(COUCH_URL) - .get('/db/_design/ddoc/_view/viewname?group=true&startkey="BA"&endkey="BQ"') - .reply(200, response) + mockPool + .intercept({ path: '/db/_design/ddoc/_view/viewname?group=true&startkey="BA"&endkey="BQ"' }) + .reply(200, response, JSON_HEADERS) // test GET /db/_design/ddoc/_view/viewname const db = nano.db.use('db') const p = await db.view('ddoc', 'viewname', { group: true, startkey: 'BA', endkey: 'BQ' }) - expect(p).toStrictEqual(response) - expect(scope.isDone()).toBe(true) + assert.deepEqual(p, response) + mockAgent.assertNoPendingInterceptors() }) test('should be able to access a MapReduce view with keys - POST /db/_design/ddoc/_view/viewname - db.view', async () => { @@ -77,15 +74,19 @@ test('should be able to access a MapReduce view with keys - POST /db/_design/ddo { key: 'BB', value: 1 } ] } - const scope = nock(COUCH_URL) - .post('/db/_design/ddoc/_view/viewname', { keys }) - .reply(200, response) + mockPool + .intercept({ + method: 'post', + path: '/db/_design/ddoc/_view/viewname', + body: JSON.stringify({ keys }) + }) + .reply(200, response, JSON_HEADERS) // test POST /db/_design/ddoc/_view/viewname const db = nano.db.use('db') const p = await db.view('ddoc', 'viewname', { keys }) - expect(p).toStrictEqual(response) - expect(scope.isDone()).toBe(true) + assert.deepEqual(p, response) + mockAgent.assertNoPendingInterceptors() }) test('should be able to access a MapReduce view with queries - POST /db/_design/ddoc/_view/viewname - db.view', async () => { @@ -122,15 +123,19 @@ test('should be able to access a MapReduce view with queries - POST /db/_design/ } ] } - const scope = nock(COUCH_URL) - .post('/db/_design/ddoc/_view/viewname', { queries: opts.queries }) - .reply(200, response) + mockPool + .intercept({ + method: 'post', + path: '/db/_design/ddoc/_view/viewname', + body: JSON.stringify({ queries: opts.queries }) + }) + .reply(200, response, JSON_HEADERS) // test POST /db/_design/ddoc/_view/viewname const db = nano.db.use('db') const p = await db.view('ddoc', 'viewname', opts) - expect(p).toStrictEqual(response) - expect(scope.isDone()).toBe(true) + assert.deepEqual(p, response) + mockAgent.assertNoPendingInterceptors() }) test('should be able to handle 404 - db.view', async () => { @@ -139,30 +144,23 @@ test('should be able to handle 404 - db.view', async () => { error: 'not_found', reason: 'missing' } - const scope = nock(COUCH_URL) - .get('/db/_design/ddoc/_view/viewname?group=true&startkey="BA"&endkey="BQ"') - .reply(404, response) + mockPool + .intercept({ + path: '/db/_design/ddoc/_view/viewname?group=true&startkey="BA"&endkey="BQ"' + }) + .reply(404, response, JSON_HEADERS) // test GET /db/_design/ddoc/_view/viewname const db = nano.db.use('db') - await expect(db.view('ddoc', 'viewname', { group: true, startkey: 'BA', endkey: 'BQ' })).rejects.toThrow('missing') - expect(scope.isDone()).toBe(true) + await assert.rejects(db.view('ddoc', 'viewname', { group: true, startkey: 'BA', endkey: 'BQ' }), { message: 'missing' }) + mockAgent.assertNoPendingInterceptors() }) test('should detect missing parameters - db.view', async () => { const db = nano.db.use('db') - await expect(db.view()).rejects.toThrow('Invalid parameters') - await expect(db.view('susan')).rejects.toThrow('Invalid parameters') - await expect(db.view('susan', '')).rejects.toThrow('Invalid parameters') - await expect(db.view('', 'susan')).rejects.toThrow('Invalid parameters') + await assert.rejects(db.view(), { message: 'Invalid parameters' }) + await assert.rejects(db.view('susan'), { message: 'Invalid parameters' }) + await assert.rejects(db.view('susan', ''), { message: 'Invalid parameters' }) + await assert.rejects(db.view('', 'susan'), { message: 'Invalid parameters' }) }) -test('should detect missing parameters (callback) - db.view', () => { - const db = nano.db.use('db') - return new Promise((resolve, reject) => { - db.view('', '', (err, data) => { - expect(err).not.toBeNull() - resolve() - }) - }) -}) diff --git a/test/design.viewAsStream.test.js b/test/design.viewAsStream.test.js index df5c1abb..44ac2aa2 100644 --- a/test/design.viewAsStream.test.js +++ b/test/design.viewAsStream.test.js @@ -10,37 +10,34 @@ // License for the specific language governing permissions and limitations under // the License. +const test = require('node:test') +const assert = require('node:assert/strict') +const { COUCH_URL, mockAgent, mockPool, JSON_HEADERS } = require('./mock.js') const Nano = require('..') -const COUCH_URL = 'http://localhost:5984' const nano = Nano(COUCH_URL) -const nock = require('nock') -afterEach(() => { - nock.cleanAll() -}) - -test('should be able to access a MapReduce view as a stream - GET /db/_design/ddoc/_view/viewname - db.viewAsStream', () => { +test('should be able to access a MapReduce view as a stream - GET /db/_design/ddoc/_view/viewname - db.viewAsStream', async () => { // mocks const response = { rows: [ { key: null, value: 23515 } ] } - const scope = nock(COUCH_URL) - .get('/db/_design/ddoc/_view/viewname') - .reply(200, response) + mockPool + .intercept({ path: '/db/_design/ddoc/_view/viewname' }) + .reply(200, response, JSON_HEADERS) - return new Promise((resolve, reject) => { + await new Promise((resolve, reject) => { const db = nano.db.use('db') const s = db.viewAsStream('ddoc', 'viewname') - expect(typeof s).toBe('object') + assert.equal(typeof s, 'object') let buffer = '' s.on('data', (chunk) => { buffer += chunk.toString() }) s.on('end', () => { - expect(buffer).toBe(JSON.stringify(response)) - expect(scope.isDone()).toBe(true) + assert.equal(buffer, JSON.stringify(response)) + mockAgent.assertNoPendingInterceptors() resolve() }) }) diff --git a/test/design.viewWithList.test.js b/test/design.viewWithList.test.js index 53c4a920..07d48bc4 100644 --- a/test/design.viewWithList.test.js +++ b/test/design.viewWithList.test.js @@ -10,25 +10,22 @@ // License for the specific language governing permissions and limitations under // the License. +const test = require('node:test') +const assert = require('node:assert/strict') +const { COUCH_URL, mockAgent, mockPool } = require('./mock.js') const Nano = require('..') -const COUCH_URL = 'http://localhost:5984' const nano = Nano(COUCH_URL) -const nock = require('nock') - -afterEach(() => { - nock.cleanAll() -}) test('should be able to access a MapReduce view with a list - GET /db/_design/ddoc/_list/listname/viewname - db.viewWithList', async () => { // mocks const response = '1,2,3\n4,5,6\n7,8,9\n' - const scope = nock(COUCH_URL) - .get('/db/_design/ddoc/_list/listname/viewname') - .reply(200, response, { 'Content-type': 'text/csv' }) + mockPool + .intercept({ path: '/db/_design/ddoc/_list/listname/viewname' }) + .reply(200, response, { headers: { 'content-type': 'text/csv' } }) // test GET /db/_design/ddoc/_list/listname/viewname const db = nano.db.use('db') const p = await db.viewWithList('ddoc', 'viewname', 'listname') - expect(p).toStrictEqual(response) - expect(scope.isDone()).toBe(true) + assert.equal(p, response) + mockAgent.assertNoPendingInterceptors() }) diff --git a/test/design.viewWithListAsStream.test.js b/test/design.viewWithListAsStream.test.js index 927301ee..053b739d 100644 --- a/test/design.viewWithListAsStream.test.js +++ b/test/design.viewWithListAsStream.test.js @@ -10,37 +10,30 @@ // License for the specific language governing permissions and limitations under // the License. +const test = require('node:test') +const assert = require('node:assert/strict') +const { COUCH_URL, mockAgent, mockPool } = require('./mock.js') const Nano = require('..') -const COUCH_URL = 'http://localhost:5984' const nano = Nano(COUCH_URL) -const nock = require('nock') - -afterEach(() => { - nock.cleanAll() -}) test('should be able to access a MapReduce view with a list as a stream - GET /db/_design/ddoc/_list/listname/viewname - db.viewWithListAsStream', async () => { // mocks - const response = { - rows: [ - { key: null, value: 23515 } - ] - } - const scope = nock(COUCH_URL) - .get('/db/_design/ddoc/_list/listname/viewname') - .reply(200, response) + const response = '1,2,3\n4,5,6\n7,8,9\n' + mockPool + .intercept({ path: '/db/_design/ddoc/_list/listname/viewname' }) + .reply(200, response, { headers: { 'content-type': 'text/csv' } }) - return new Promise((resolve, reject) => { + await new Promise((resolve, reject) => { const db = nano.db.use('db') const s = db.viewWithListAsStream('ddoc', 'viewname', 'listname') - expect(typeof s).toBe('object') + assert.equal(typeof s, 'object') let buffer = '' s.on('data', (chunk) => { buffer += chunk.toString() }) s.on('end', () => { - expect(buffer).toBe(JSON.stringify(response)) - expect(scope.isDone()).toBe(true) + assert.equal(buffer, response) + mockAgent.assertNoPendingInterceptors() resolve() }) }) diff --git a/test/document.bulk.test.js b/test/document.bulk.test.js index d868beb5..237b395b 100644 --- a/test/document.bulk.test.js +++ b/test/document.bulk.test.js @@ -10,14 +10,11 @@ // License for the specific language governing permissions and limitations under // the License. +const test = require('node:test') +const assert = require('node:assert/strict') +const { COUCH_URL, mockAgent, mockPool, JSON_HEADERS } = require('./mock.js') const Nano = require('..') -const COUCH_URL = 'http://localhost:5984' const nano = Nano(COUCH_URL) -const nock = require('nock') - -afterEach(() => { - nock.cleanAll() -}) test('should be able to insert documents in bulk - POST /db/_bulk_docs - db.bulk', async () => { // mocks @@ -27,15 +24,19 @@ test('should be able to insert documents in bulk - POST /db/_bulk_docs - db.bulk { ok: true, id: 'y', rev: '1-456' }, { ok: true, id: 'z', rev: '1-789' } ] - const scope = nock(COUCH_URL) - .post('/db/_bulk_docs', { docs }) - .reply(200, response) + mockPool + .intercept({ + method: 'post', + path: '/db/_bulk_docs', + body: JSON.stringify({ docs }) + }) + .reply(200, response, JSON_HEADERS) // test POST /db/_bulk_docs const db = nano.db.use('db') const p = await db.bulk({ docs }) - expect(p).toStrictEqual(response) - expect(scope.isDone()).toBe(true) + assert.deepEqual(p, response) + mockAgent.assertNoPendingInterceptors() }) test('should be able to handle missing database - POST /db/_bulk_docs - db.bulk', async () => { @@ -45,12 +46,16 @@ test('should be able to handle missing database - POST /db/_bulk_docs - db.bulk' error: 'not_found', reason: 'Database does not exist.' } - const scope = nock(COUCH_URL) - .post('/db/_bulk_docs', { docs }) - .reply(404, response) + mockPool + .intercept({ + method: 'post', + path: '/db/_bulk_docs', + body: JSON.stringify({ docs }) + }) + .reply(404, response, JSON_HEADERS) // test POST /db/_bulk_docs const db = nano.db.use('db') - await expect(db.bulk({ docs })).rejects.toThrow('Database does not exist.') - expect(scope.isDone()).toBe(true) + await assert.rejects(db.bulk({ docs }), { message: 'Database does not exist.' }) + mockAgent.assertNoPendingInterceptors() }) diff --git a/test/document.changesreader.test.js b/test/document.changesreader.test.js index 09fd2a72..f22a947a 100644 --- a/test/document.changesreader.test.js +++ b/test/document.changesreader.test.js @@ -10,89 +10,94 @@ // License for the specific language governing permissions and limitations under // the License. +const test = require('node:test') +const assert = require('node:assert/strict') +const { COUCH_URL, mockAgent, mockPool, JSON_HEADERS } = require('./mock.js') const Nano = require('..') -const COUCH_URL = 'http://localhost:5984' const nano = Nano(COUCH_URL) -const nock = require('nock') const DBNAME = 'db' -afterEach(() => { - nock.cleanAll() -}) - test('should be able to follow changes feed - db.changesReader.start', async () => { - const changeURL = `/${DBNAME}/_changes` - nock(COUCH_URL) - .post(changeURL) - .query({ feed: 'longpoll', timeout: 60000, since: 'now', limit: 100, include_docs: false }) - .reply(200, { results: [], last_seq: '1-0', pending: 0 }) - .post(changeURL) - .delay(2000) - .reply(500) + const changesResponse = { results: [], last_seq: '1-0', pending: 0 } + mockPool + .intercept({ + method: 'post', + path: '/db/_changes?feed=longpoll&include_docs=false&limit=100&since=now&timeout=60000' + }) + .reply(200, changesResponse, JSON_HEADERS) + const db = nano.db.use(DBNAME) const cr = db.changesReader.start() - return new Promise((resolve, reject) => { + await new Promise((resolve, reject) => { cr.on('seq', function (seq) { // after our initial call with since=now, we should get a reply with last_seq=0-1 - expect(seq).toBe('1-0') + assert.equal(seq, '1-0') db.changesReader.stop() + mockAgent.assertNoPendingInterceptors() resolve() }) }) }) test('should respect the fastChanges flag - db.changesReader.start', async () => { - const changeURL = `/${DBNAME}/_changes` - nock(COUCH_URL) - .post(changeURL) - .query({ feed: 'longpoll', timeout: 60000, since: 'now', limit: 100, include_docs: false, seq_interval: 100 }) - .reply(200, { results: [], last_seq: '1-0', pending: 0 }) - .post(changeURL) - .delay(2000) - .reply(500) + const changesResponse = { results: [], last_seq: '1-0', pending: 0 } + mockPool + .intercept({ + method: 'post', + path: '/db/_changes?feed=longpoll&include_docs=false&limit=100&since=now&timeout=60000&seq_interval=100' + }) + .reply(200, changesResponse, JSON_HEADERS) + const db = nano.db.use(DBNAME) const cr = db.changesReader.start({ fastChanges: true }) - return new Promise((resolve, reject) => { + await new Promise((resolve, reject) => { cr.on('seq', function (seq) { // after our initial call with since=now, we should get a reply with last_seq=0-1 - expect(seq).toBe('1-0') + assert.equal(seq, '1-0') db.changesReader.stop() + mockAgent.assertNoPendingInterceptors() resolve() }) }) }) test('should respect the selector parameter - db.changesReader.start', async () => { - const changeURL = `/${DBNAME}/_changes` - nock(COUCH_URL) - .post(changeURL, { selector: { name: 'fred' } }) - .query({ feed: 'longpoll', timeout: 60000, since: 'now', limit: 100, include_docs: false, filter: '_selector' }) - .reply(200, { results: [], last_seq: '1-0', pending: 0 }) - .post(changeURL) - .delay(2000) - .reply(500) + const changesResponse = { results: [], last_seq: '1-0', pending: 0 } + const selector = { name: 'fred' } + mockPool + .intercept({ + method: 'post', + path: '/db/_changes?feed=longpoll&filter=_selector&include_docs=false&limit=100&since=now&timeout=60000', + body: JSON.stringify({ selector }) + }) + .reply(200, changesResponse, JSON_HEADERS) const db = nano.db.use(DBNAME) - const cr = db.changesReader.start({ selector: { name: 'fred' } }) + const cr = db.changesReader.start({ selector }) return new Promise((resolve, reject) => { cr.on('seq', function (seq) { // after our initial call with since=now, we should get a reply with last_seq=0-1 - expect(seq).toBe('1-0') + assert.equal(seq, '1-0') db.changesReader.stop() + mockAgent.assertNoPendingInterceptors() resolve() }) }) }) test('should respect the selector parameter - db.changesReader.spool', async () => { - const changeURL = `/${DBNAME}/_changes` - nock(COUCH_URL) - .post(changeURL, { selector: { name: 'fred' } }) - .query({ since: 'now', seq_interval: 100, include_docs: false, filter: '_selector' }) - .reply(200, { results: [], last_seq: '1-0', pending: 0 }) + const changesResponse = { results: [], last_seq: '1-0', pending: 0 } + const selector = { name: 'fred' } + mockPool + .intercept({ + method: 'post', + path: '/db/_changes?filter=_selector&include_docs=false&seq_interval=100&since=now', + body: JSON.stringify({ selector }) + }) + .reply(200, changesResponse, JSON_HEADERS) const db = nano.db.use(DBNAME) - const cr = db.changesReader.spool({ since: 'now', selector: { name: 'fred' } }) - return new Promise((resolve, reject) => { + const cr = db.changesReader.spool({ since: 'now', selector }) + await new Promise((resolve, reject) => { cr.on('end', function (data) { resolve() }) @@ -100,87 +105,97 @@ test('should respect the selector parameter - db.changesReader.spool', async () }) test('should emit change and batch events - db.changesReader.start', async () => { - const changeURL = `/${DBNAME}/_changes` - const changes = [{ seq: null, id: '1', changes: ['1-1'] }, + const changes = [ + { seq: null, id: '1', changes: ['1-1'] }, { seq: null, id: '2', changes: ['1-1'] }, { seq: null, id: '3', changes: ['1-1'] }, { seq: null, id: '4', changes: ['1-1'] }, - { seq: null, id: '5', changes: ['1-1'] }] - nock(COUCH_URL) - .post(changeURL) - .query({ feed: 'longpoll', timeout: 60000, since: 'now', limit: 100, include_docs: false }) - .reply(200, { results: changes, last_seq: '1-0', pending: 0 }) - .post(changeURL) - .delay(2000) - .reply(500) + { seq: null, id: '5', changes: ['1-1'] } + ] + mockPool + .intercept({ + method: 'post', + path: '/db/_changes?feed=longpoll&include_docs=false&limit=100&since=now&timeout=60000' + }) + .reply(200, { results: changes, last_seq: '1-0', pending: 0 }, JSON_HEADERS) const db = nano.db.use(DBNAME) const cr = db.changesReader.start() let i = 0 - return new Promise((resolve, reject) => { + await new Promise((resolve, reject) => { cr.on('change', function (c) { - expect(c).toStrictEqual(changes[i++]) + assert.equal(c, changes[i++]) }).on('batch', function (b) { - expect(b).toStrictEqual(changes) + assert.deepEqual(b, changes) }).on('seq', function (seq) { // after our initial call with since=now, we should get a reply with last_seq=0-1 - expect(seq).toBe('1-0') + assert.equal(seq, '1-0') db.changesReader.stop() resolve() - }) + }).on('error', reject) }) }) -it('should keep polling the changes feed - db.changesReader.start', async () => { - const changeURL = `/${DBNAME}/_changes` +test('should keep polling the changes feed - db.changesReader.start', async () => { const change = { seq: null, id: 'a', changes: ['1-1'] } - nock(COUCH_URL) - .post(changeURL) - .query({ feed: 'longpoll', timeout: 1000, since: 'now', limit: 100, include_docs: false }) - .reply(200, { results: [], last_seq: '1-0', pending: 0 }) - .post(changeURL) - .query({ feed: 'longpoll', timeout: 1000, since: '1-0', limit: 100, include_docs: false }) - .reply(200, { results: [], last_seq: '1-0', pending: 0 }) - .post(changeURL) - .query({ feed: 'longpoll', timeout: 1000, since: '1-0', limit: 100, include_docs: false }) - .reply(200, { results: [change], last_seq: '2-0', pending: 0 }) - .post(changeURL) - .delay(2000) - .reply(500) + mockPool + .intercept({ + method: 'post', + path: '/db/_changes?feed=longpoll&include_docs=false&limit=100&since=now&timeout=1000' + }) + .reply(200, { results: [], last_seq: '1-0', pending: 0 }, JSON_HEADERS) + mockPool + .intercept({ + method: 'post', + path: '/db/_changes?feed=longpoll&include_docs=false&limit=100&since=1-0&timeout=1000' + }) + .reply(200, { results: [], last_seq: '1-0', pending: 0 }, JSON_HEADERS) + mockPool + .intercept({ + method: 'post', + path: '/db/_changes?feed=longpoll&include_docs=false&limit=100&since=1-0&timeout=1000' + }) + .reply(200, { results: [change], last_seq: '2-0', pending: 0 }, JSON_HEADERS) + const db = nano.db.use(DBNAME) const cr = db.changesReader.start({ timeout: 1000 }) - return new Promise((resolve, reject) => { + await new Promise((resolve, reject) => { cr.on('change', function (c) { // ensure we get a change on the third poll - expect(c).toStrictEqual(change) + assert.deepEqual(c, change) db.changesReader.stop() resolve() }) }) -}, 10000) +}) -it('should keep polling the changes feed (wait: true) - db.changesReader.start', async () => { - const changeURL = `/${DBNAME}/_changes` +test('should keep polling the changes feed (wait: true) - db.changesReader.start', async () => { const change = { seq: null, id: 'a', changes: ['1-1'] } - nock(COUCH_URL) - .post(changeURL) - .query({ feed: 'longpoll', timeout: 1000, since: 'now', limit: 100, include_docs: false }) - .reply(200, { results: [], last_seq: '1-0', pending: 0 }) - .post(changeURL) - .query({ feed: 'longpoll', timeout: 1000, since: '1-0', limit: 100, include_docs: false }) - .reply(200, { results: [], last_seq: '1-0', pending: 0 }) - .post(changeURL) - .query({ feed: 'longpoll', timeout: 1000, since: '1-0', limit: 100, include_docs: false }) - .reply(200, { results: [change], last_seq: '2-0', pending: 0 }) - .post(changeURL) - .delay(2000) - .reply(500) + mockPool + .intercept({ + method: 'post', + path: '/db/_changes?feed=longpoll&include_docs=false&limit=100&since=now&timeout=1000' + }) + .reply(200, { results: [], last_seq: '1-0', pending: 0 }, JSON_HEADERS) + mockPool + .intercept({ + method: 'post', + path: '/db/_changes?feed=longpoll&include_docs=false&limit=100&since=1-0&timeout=1000' + }) + .reply(200, { results: [], last_seq: '1-0', pending: 0 }, JSON_HEADERS) + mockPool + .intercept({ + method: 'post', + path: '/db/_changes?feed=longpoll&include_docs=false&limit=100&since=1-0&timeout=1000' + }) + .reply(200, { results: [change], last_seq: '2-0', pending: 0 }, JSON_HEADERS) + const db = nano.db.use(DBNAME) const cr = db.changesReader.start({ timeout: 1000, wait: true }) - return new Promise((resolve, reject) => { + await new Promise((resolve, reject) => { cr.on('change', function (c) { // ensure we get a change on the third poll - expect(c).toStrictEqual(change) + assert.deepEqual(c, change) db.changesReader.stop() resolve() }) @@ -188,69 +203,69 @@ it('should keep polling the changes feed (wait: true) - db.changesReader.start', db.changesReader.resume() }) }) -}, 10000) +}) test('spooling changes - db.changesReader.spool', async () => { - const changeURL = `/${DBNAME}/_changes` const fs = require('fs') const reply = fs.readFileSync('./test/changes.json') const replyObj = JSON.parse(reply) - nock(COUCH_URL) - .post(changeURL) - .query({ since: '0', include_docs: false, seq_interval: 100 }) - .reply(200, reply) + mockPool + .intercept({ + method: 'post', + path: '/db/_changes?include_docs=false&seq_interval=100&since=0' + }) + .reply(200, reply, JSON_HEADERS) const db = nano.db.use(DBNAME) const cr = db.changesReader.spool({ since: 0 }) - return new Promise((resolve, reject) => { + await new Promise((resolve, reject) => { cr.on('batch', function (batch) { - expect(JSON.stringify(batch)).toBe(JSON.stringify(replyObj.results)) + assert.equal(JSON.stringify(batch), JSON.stringify(replyObj.results)) }).on('end', (lastSeq) => { - expect(lastSeq).toBe(replyObj.last_seq) + assert.equal(lastSeq, replyObj.last_seq) resolve() }) }) }) test('spooling changes - numeric seq - db.changesReader.spool', async () => { - const changeURL = `/${DBNAME}/_changes` const fs = require('fs') const reply = fs.readFileSync('./test/changes_numeric.json') const replyObj = JSON.parse(reply) - nock(COUCH_URL) - .post(changeURL) - .query({ since: 0, include_docs: false, seq_interval: 100 }) - .reply(200, reply) + mockPool + .intercept({ + method: 'post', + path: '/db/_changes?include_docs=false&seq_interval=100&since=0' + }) + .reply(200, reply, JSON_HEADERS) const db = nano.db.use(DBNAME) const cr = db.changesReader.spool({ since: 0 }) return new Promise((resolve, reject) => { cr.on('batch', function (batch) { - expect(JSON.stringify(batch)).toBe(JSON.stringify(replyObj.results)) + assert.equal(JSON.stringify(batch), JSON.stringify(replyObj.results)) }).on('end', (lastSeq) => { - expect(lastSeq).toBe(replyObj.last_seq) + assert.equal(lastSeq, replyObj.last_seq) resolve() }) }) }) test('should handle the batchSize parameter - db.changesReader.start', async () => { - const changeURL = `/${DBNAME}/_changes` const limit = 44 - nock(COUCH_URL) - .post(changeURL) - .query({ feed: 'longpoll', timeout: 60000, since: 'now', limit, include_docs: false }) - .reply(200, { results: [], last_seq: '1-0', pending: 0 }) - .post(changeURL) - .delay(2000) - .reply(500) + mockPool + .intercept({ + method: 'post', + path: `/db/_changes?feed=longpoll&include_docs=false&limit=${limit}&since=now&timeout=60000` + }) + .reply(200, { results: [], last_seq: '1-0', pending: 0 }, JSON_HEADERS) const db = nano.db.use(DBNAME) const cr = db.changesReader.start({ batchSize: limit }) - return new Promise((resolve, reject) => { + await new Promise((resolve, reject) => { cr.on('seq', function (seq) { // after our initial call with since=now, we should get a reply with last_seq=0-1 - expect(seq).toBe('1-0') + assert.equal(seq, '1-0') db.changesReader.stop() resolve() }) @@ -258,22 +273,21 @@ test('should handle the batchSize parameter - db.changesReader.start', async () }) test('should respect the since parameter db.changesReader.start', async () => { - const changeURL = `/${DBNAME}/_changes` const limit = 44 const since = 'thedawnoftime' - nock(COUCH_URL) - .post(changeURL) - .query({ feed: 'longpoll', timeout: 60000, since, limit, include_docs: false }) - .reply(200, { results: [], last_seq: '1-0', pending: 0 }) - .post(changeURL) - .delay(2000) - .reply(500) + mockPool + .intercept({ + method: 'post', + path: `/db/_changes?feed=longpoll&include_docs=false&limit=${limit}&since=${since}&timeout=60000` + }) + .reply(200, { results: [], last_seq: '1-0', pending: 0 }, JSON_HEADERS) + const db = nano.db.use(DBNAME) const cr = db.changesReader.start({ batchSize: limit, since }) - return new Promise((resolve, reject) => { + await new Promise((resolve, reject) => { cr.on('seq', function (seq) { // after our initial call with since=thedawnoftime, we should get a reply with last_seq=0-1 - expect(seq).toBe('1-0') + assert.equal(seq, '1-0') db.changesReader.stop() resolve() }) @@ -281,22 +295,21 @@ test('should respect the since parameter db.changesReader.start', async () => { }) test('should stop on no changes - db.changesReader.get', async () => { - const changeURL = `/${DBNAME}/_changes` const since = 'thedawnoftime' const batchSize = 45 - nock(COUCH_URL) - .post(changeURL) - .query({ feed: 'longpoll', timeout: 60000, since, limit: batchSize, include_docs: false }) - .reply(200, { results: [], last_seq: '1-0', pending: 0 }) - .post(changeURL) - .delay(2000) - .reply(500) + mockPool + .intercept({ + method: 'post', + path: `/db/_changes?feed=longpoll&include_docs=false&limit=${batchSize}&since=${since}&timeout=60000` + }) + .reply(200, { results: [], last_seq: '1-0', pending: 0 }, JSON_HEADERS) + const db = nano.db.use(DBNAME) const cr = db.changesReader.get({ batchSize, since }) - return new Promise((resolve, reject) => { + await new Promise((resolve, reject) => { cr.on('seq', function (seq) { // after our initial call with since=now, we should get a reply with last_seq=0-1 - expect(seq).toBe('1-0') + assert.equal(seq, '1-0') }).on('end', function () { resolve() }) @@ -304,7 +317,6 @@ test('should stop on no changes - db.changesReader.get', async () => { }) test('stop after multiple batches - small batch stop - db.changesReader.get', async () => { - const changeURL = `/${DBNAME}/_changes` const since = 'now' const batchSize = 45 const batch1 = [] @@ -315,37 +327,50 @@ test('stop after multiple batches - small batch stop - db.changesReader.get', as for (let i = 0; i < 5; i++) { batch2.push({ seq: (45 + i + 1) + '-0', id: 'b' + i, changes: ['1-1'] }) } - nock(COUCH_URL) - .post(changeURL) - .query({ feed: 'longpoll', timeout: 60000, since, limit: batchSize, include_docs: false }) - .reply(200, { results: batch1, last_seq: '45-0', pending: 2 }) - .post(changeURL) - .query({ feed: 'longpoll', timeout: 60000, since: '45-0', limit: batchSize, include_docs: false }) - .reply(200, { results: batch2, last_seq: '50-0', pending: 0 }) - .post(changeURL) - .query({ feed: 'longpoll', timeout: 60000, since: '50-0', limit: batchSize, include_docs: false }) - .reply(200, { results: [], last_seq: '50-0', pending: 0 }) + mockPool + .intercept({ + method: 'post', + path: `/db/_changes?feed=longpoll&include_docs=false&limit=${batchSize}&since=${since}&timeout=60000` + }) + .reply(200, { results: batch1, last_seq: '45-0', pending: 2 }, JSON_HEADERS) + mockPool + .intercept({ + method: 'post', + path: `/db/_changes?feed=longpoll&include_docs=false&limit=${batchSize}&since=45-0&timeout=60000` + }) + .reply(200, { results: batch2, last_seq: '50-0', pending: 0 }, JSON_HEADERS) + mockPool + .intercept({ + method: 'post', + path: `/db/_changes?feed=longpoll&include_docs=false&limit=${batchSize}&since=50-0&timeout=60000` + }) + .reply(200, { results: [], last_seq: '50-0', pending: 0 }, JSON_HEADERS) const db = nano.db.use(DBNAME) const cr = db.changesReader.get({ batchSize, since }) let batchCount = 0 - return new Promise((resolve, reject) => { + await new Promise((resolve, reject) => { cr.on('seq', function (seq) { switch (batchCount) { - case 0: expect(seq).toBe('45-0'); break - case 1: expect(seq).toBe('50-0'); break - case 2: expect(seq).toBe('50-0'); break + case 0: + assert.equal(seq, '45-0') + break + case 1: + assert.equal(seq, '50-0') + break + case 2: + assert.equal(seq, '50-0') + break } batchCount++ }).on('end', function (lastSeq) { - expect(lastSeq).toBe('50-0') + assert.equal(lastSeq, '50-0') resolve() }) }) }) test('stop after multiple batches - zero stop - db.changesReader.get', async () => { - const changeURL = `/${DBNAME}/_changes` const since = 'now' const batchSize = 45 const batch1 = [] @@ -353,30 +378,38 @@ test('stop after multiple batches - zero stop - db.changesReader.get', async () for (let i = 0; i < batchSize; i++) { batch1.push({ seq: null, id: 'a' + i, changes: ['1-1'] }) } - for (let i = 0; i < 5; i++) { + for (let i = 0; i < batchSize; i++) { batch2.push({ seq: null, id: 'b' + i, changes: ['1-1'] }) } - nock(COUCH_URL) - .post(changeURL) - .query({ feed: 'longpoll', timeout: 60000, since, limit: batchSize, include_docs: false }) - .reply(200, { results: batch1, last_seq: '45-0', pending: 2 }) - .post(changeURL) - .query({ feed: 'longpoll', timeout: 60000, since: '45-0', limit: batchSize, include_docs: false }) - .reply(200, { results: batch2, last_seq: '90-0', pending: 0 }) - .post(changeURL) - .query({ feed: 'longpoll', timeout: 60000, since: '90-0', limit: batchSize, include_docs: false }) - .reply(200, { results: [], last_seq: '90-0', pending: 0 }) + mockPool + .intercept({ + method: 'post', + path: `/db/_changes?feed=longpoll&include_docs=false&limit=${batchSize}&since=${since}&timeout=60000` + }) + .reply(200, { results: batch1, last_seq: '45-0', pending: 2 }, JSON_HEADERS) + mockPool + .intercept({ + method: 'post', + path: `/db/_changes?feed=longpoll&include_docs=false&limit=${batchSize}&since=45-0&timeout=60000` + }) + .reply(200, { results: batch2, last_seq: '90-0', pending: 0 }, JSON_HEADERS) + mockPool + .intercept({ + method: 'post', + path: `/db/_changes?feed=longpoll&include_docs=false&limit=${batchSize}&since=90-0&timeout=60000` + }) + .reply(200, { results: [], last_seq: '90-0', pending: 0 }, JSON_HEADERS) const db = nano.db.use(DBNAME) const cr = db.changesReader.get({ batchSize, since }) let batchCount = 0 - return new Promise((resolve, reject) => { + await new Promise((resolve, reject) => { cr.on('seq', function (seq) { if (batchCount === 0) { - expect(seq).toBe('45-0') + assert.equal(seq, '45-0') batchCount++ } else { - expect(seq).toBe('90-0') + assert.equal(seq, '90-0') } }).on('end', function () { resolve() @@ -385,145 +418,165 @@ test('stop after multiple batches - zero stop - db.changesReader.get', async () }) test('on bad credentials - db.changesReader.start', async () => { - const changeURL = `/${DBNAME}/_changes` - nock(COUCH_URL) - .post(changeURL) - .query({ feed: 'longpoll', timeout: 60000, since: 'now', limit: 100, include_docs: false }) - .reply(401) + const response = { error: 'unauthorized', reason: 'You are not authorized to access this db.' } + mockPool + .intercept({ + method: 'post', + path: '/db/_changes?feed=longpoll&include_docs=false&limit=100&since=now&timeout=60000' + }) + .reply(401, response, JSON_HEADERS) + const db = nano.db.use(DBNAME) const cr = db.changesReader.start() - return new Promise((resolve, reject) => { + await new Promise((resolve, reject) => { cr.on('error', function (err) { - expect(err.statusCode).toBe(401) + assert.equal(err.statusCode, 401) resolve() }) }) }) test('on bad since value - db.changesReader.start', async () => { - const changeURL = `/${DBNAME}/_changes` - nock(COUCH_URL) - .post(changeURL) - .query({ feed: 'longpoll', timeout: 60000, since: 'badtoken', limit: 100, include_docs: false }) - .reply(400, { error: 'bad_request', reason: 'Malformed sequence supplied in \'since\' parameter.' }) + const response = { error: 'bad_request', reason: 'Malformed sequence supplied in \'since\' parameter.' } + mockPool + .intercept({ + method: 'post', + path: '/db/_changes?feed=longpoll&include_docs=false&limit=100&since=badtoken&timeout=60000' + }) + .reply(400, response, JSON_HEADERS) const db = nano.db.use(DBNAME) const cr = db.changesReader.start({ since: 'badtoken' }) - return new Promise((resolve, reject) => { + await new Promise((resolve, reject) => { cr.on('error', function (err) { - expect(err.statusCode).toBe(400) + assert.equal(err.statusCode, 400) resolve() }) }) }) test('should survive a HTTP 500 response - db.changesReader.start', async () => { - const changeURL = `/${DBNAME}/_changes` const change = { seq: null, id: 'a', changes: ['1-1'] } - nock(COUCH_URL) - .post(changeURL) - .query({ feed: 'longpoll', timeout: 1000, since: 'now', limit: 100, include_docs: false }) - .reply(200, { results: [], last_seq: '1-0', pending: 0 }) - .post(changeURL) - .query({ feed: 'longpoll', timeout: 1000, since: '1-0', limit: 100, include_docs: false }) - .reply(500) - .post(changeURL) - .query({ feed: 'longpoll', timeout: 1000, since: '1-0', limit: 100, include_docs: false }) - .reply(200, { results: [change], last_seq: '2-0', pending: 0 }) - .post(changeURL) - .delay(2000) + mockPool + .intercept({ + method: 'post', + path: '/db/_changes?feed=longpoll&include_docs=false&limit=100&since=now&timeout=1000' + }) + .reply(200, { results: [], last_seq: '1-0', pending: 0 }, JSON_HEADERS) + mockPool + .intercept({ + method: 'post', + path: '/db/_changes?feed=longpoll&include_docs=false&limit=100&since=1-0&timeout=1000' + }) .reply(500) + mockPool + .intercept({ + method: 'post', + path: '/db/_changes?feed=longpoll&include_docs=false&limit=100&since=1-0&timeout=1000' + }) + .reply(200, { results: [change], last_seq: '2-0', pending: 0 }, JSON_HEADERS) + const db = nano.db.use(DBNAME) const cr = db.changesReader.start({ timeout: 1000 }) - return new Promise((resolve, reject) => { + await new Promise((resolve, reject) => { cr.on('change', function (c) { // ensure we get a change on the third poll - expect(c).toStrictEqual(change) + assert.deepEqual(c, change) db.changesReader.stop() resolve() }).on('error', function (err) { - expect(err.statusCode).toBe(500) + assert.equal(err.statusCode, 500) }) }) -}, 10000) +}) test('should survive HTTP 429 response - db.changesReader.start', async () => { - const changeURL = `/${DBNAME}/_changes` const change = { seq: null, id: 'a', changes: ['1-1'] } - nock(COUCH_URL) - .post(changeURL) - .query({ feed: 'longpoll', timeout: 1000, since: 'now', limit: 100, include_docs: false }) - .reply(200, { results: [], last_seq: '1-0', pending: 0 }) - .post(changeURL) - .query({ feed: 'longpoll', timeout: 1000, since: '1-0', limit: 100, include_docs: false }) - .reply(429, { error: 'too_many_requests', reason: 'You\'ve exceeded your current limit of x requests per second for x class. Please try later.', class: 'x', rate: 1 }) - .post(changeURL) - .query({ feed: 'longpoll', timeout: 1000, since: '1-0', limit: 100, include_docs: false }) - .reply(200, { results: [change], last_seq: '2-0', pending: 0 }) - .post(changeURL) - .delay(2000) - .reply(500) + const response429 = { error: 'too_many_requests', reason: 'You\'ve exceeded your current limit of x requests per second for x class. Please try later.', class: 'x', rate: 1 } + mockPool + .intercept({ + method: 'post', + path: '/db/_changes?feed=longpoll&include_docs=false&limit=100&since=now&timeout=1000' + }) + .reply(200, { results: [], last_seq: '1-0', pending: 0 }, JSON_HEADERS) + mockPool + .intercept({ + method: 'post', + path: '/db/_changes?feed=longpoll&include_docs=false&limit=100&since=1-0&timeout=1000' + }) + .reply(429, response429, JSON_HEADERS) + mockPool + .intercept({ + method: 'post', + path: '/db/_changes?feed=longpoll&include_docs=false&limit=100&since=1-0&timeout=1000' + }) + .reply(200, { results: [change], last_seq: '2-0', pending: 0 }, JSON_HEADERS) + const db = nano.db.use(DBNAME) const cr = db.changesReader.start({ timeout: 1000 }) - return new Promise((resolve, reject) => { + await new Promise((resolve, reject) => { cr.on('change', function (c) { // ensure we get a change on the third poll - expect(c).toStrictEqual(change) + assert.deepEqual(c, change) db.changesReader.stop() resolve() }).on('error', function (err) { - expect(err.statusCode).toBe(429) + assert.equal(err.statusCode, 429) }) }) -}, 10000) +}) test('should survive malformed JSON - db.changesReader.start', async () => { - const changeURL = `/${DBNAME}/_changes` const change = { seq: null, id: 'a', changes: ['1-1'] } - nock(COUCH_URL) - .post(changeURL) - .query({ feed: 'longpoll', timeout: 1000, since: 'now', limit: 100, include_docs: false }) - .reply(200, '{ results: [], last_seq: "1-0", pending: 0') // missing bracket } - malformed JSON - .post(changeURL) - .query({ feed: 'longpoll', timeout: 1000, since: 'now', limit: 100, include_docs: false }) - .reply(200, { results: [change], last_seq: '1-0', pending: 0 }) - .post(changeURL) - .delay(2000) - .reply(500) + mockPool + .intercept({ + method: 'post', + path: '/db/_changes?feed=longpoll&include_docs=false&limit=100&since=now&timeout=1000' + }) + .reply(200, '{ results: [], last_seq: "1-0", pending: 0', JSON_HEADERS) + mockPool + .intercept({ + method: 'post', + path: '/db/_changes?feed=longpoll&include_docs=false&limit=100&since=now&timeout=1000' + }) + .reply(200, { results: [change], last_seq: '1-0', pending: 0 }, JSON_HEADERS) + const db = nano.db.use(DBNAME) const cr = db.changesReader.start({ timeout: 1000 }) - return new Promise((resolve, reject) => { + await new Promise((resolve, reject) => { cr.on('change', function (c) { - expect(c).toStrictEqual(change) + assert.deepEqual(c, change) db.changesReader.stop() resolve() }).on('error', function (err) { if (err) { // shouldn't get here - expect(true).toBe(false) + assert(true, false) } }) }) -}, 10000) +}) test('should cancel HTTP connection as soon as stop is called', async () => { - const changeURL = `/${DBNAME}/_changes` - nock(COUCH_URL) - .post(changeURL) - .query({ feed: 'longpoll', timeout: 60000, since: 'now', limit: 100, include_docs: false }) - .reply(200, { results: [], last_seq: '1-0', pending: 0 }) - .post(changeURL) - .query({ feed: 'longpoll', timeout: 60000, since: '1-0', limit: 100, include_docs: false }) - .delay(60000) - .reply(500) + const response = { results: [], last_seq: '1-0', pending: 0 } + mockPool + .intercept({ + method: 'post', + path: '/db/_changes?feed=longpoll&include_docs=false&limit=100&since=now&timeout=60000' + }) + .reply(200, response, JSON_HEADERS) + mockPool + .intercept({ + method: 'post', + path: '/db/_changes?feed=longpoll&include_docs=false&limit=100&since=now&timeout=60000' + }) + .reply(200, response, JSON_HEADERS) + const db = nano.db.use(DBNAME) const cr = db.changesReader.start() await new Promise((resolve, reject) => { cr.on('seq', function (seq) { - setTimeout(function () { - // give the next http connection a chance to be established - db.changesReader.stop() - }, 200) + db.changesReader.stop() }) cr.on('end', function () { diff --git a/test/document.destroy.test.js b/test/document.destroy.test.js index 45b8f48c..82f2d3fe 100644 --- a/test/document.destroy.test.js +++ b/test/document.destroy.test.js @@ -10,27 +10,27 @@ // License for the specific language governing permissions and limitations under // the License. +const test = require('node:test') +const assert = require('node:assert/strict') +const { COUCH_URL, mockAgent, mockPool, JSON_HEADERS } = require('./mock.js') const Nano = require('..') -const COUCH_URL = 'http://localhost:5984' const nano = Nano(COUCH_URL) -const nock = require('nock') - -afterEach(() => { - nock.cleanAll() -}) test('should be able to destroy a document - DELETE /db/id - db.destroy', async () => { // mocks const response = { ok: true, id: 'id', rev: '2-456' } - const scope = nock(COUCH_URL) - .delete('/db/id?rev=1-123') - .reply(200, response) + mockPool + .intercept({ + method: 'delete', + path: '/db/id?rev=1-123' + }) + .reply(200, response, JSON_HEADERS) // test DELETE /db/id const db = nano.db.use('db') const p = await db.destroy('id', '1-123') - expect(p).toStrictEqual(response) - expect(scope.isDone()).toBe(true) + assert.deepEqual(p, response) + mockAgent.assertNoPendingInterceptors() }) test('should be able to handle 409 conflicts - DELETE /db/id - db.destroy', async () => { @@ -39,27 +39,21 @@ test('should be able to handle 409 conflicts - DELETE /db/id - db.destroy', asyn error: 'conflict', reason: 'Document update conflict.' } - const scope = nock(COUCH_URL) - .delete('/db/id?rev=1-123') - .reply(409, response) + mockPool + .intercept({ + method: 'delete', + path: '/db/id?rev=1-123' + }) + .reply(409, response, JSON_HEADERS) // test DELETE /db/id const db = nano.db.use('db') - await expect(db.destroy('id', '1-123')).rejects.toThrow('Document update conflict.') - expect(scope.isDone()).toBe(true) + await assert.rejects(db.destroy('id', '1-123'), { message: 'Document update conflict.' }) + mockAgent.assertNoPendingInterceptors() }) test('should detect missing parameters - db.destroy', async () => { const db = nano.db.use('db') - await expect(db.destroy(undefined, '1-123')).rejects.toThrow('Invalid parameters') + await assert.rejects(db.destroy(undefined, '1-123'), { message: 'Invalid parameters' }) }) -test('should detect missing parameters (callback) - db.destroy', () => { - return new Promise((resolve, reject) => { - const db = nano.db.use('db') - db.destroy(undefined, undefined, (err, data) => { - expect(err).not.toBeNull() - resolve() - }) - }) -}) diff --git a/test/document.fetch.test.js b/test/document.fetch.test.js index 02ae7c06..97df61ff 100644 --- a/test/document.fetch.test.js +++ b/test/document.fetch.test.js @@ -10,14 +10,11 @@ // License for the specific language governing permissions and limitations under // the License. +const test = require('node:test') +const assert = require('node:assert/strict') +const { COUCH_URL, mockAgent, mockPool, JSON_HEADERS } = require('./mock.js') const Nano = require('..') -const COUCH_URL = 'http://localhost:5984' -const nano = Nano(COUCH_URL) -const nock = require('nock') - -afterEach(() => { - nock.cleanAll() -}) +const nano = Nano({ url: COUCH_URL }) test('should be able to fetch a list of documents - POST /db/_all_docs - db.fetch', async () => { // mocks @@ -67,15 +64,19 @@ test('should be able to fetch a list of documents - POST /db/_all_docs - db.fetc } ] } - const scope = nock(COUCH_URL) - .post('/db/_all_docs?include_docs=true', { keys }) - .reply(200, response) + mockPool + .intercept({ + method: 'post', + path: '/db/_all_docs?include_docs=true', + body: JSON.stringify({ keys }) + }) + .reply(200, response, JSON_HEADERS) // test POST /db/_all_docs const db = nano.db.use('db') const p = await db.fetch({ keys }) - expect(p).toStrictEqual(response) - expect(scope.isDone()).toBe(true) + assert.deepEqual(p, response) + mockAgent.assertNoPendingInterceptors() }) test('should be able to fetch a list of documents with opts - POST /db/_all_docs - db.fetch', async () => { @@ -126,15 +127,19 @@ test('should be able to fetch a list of documents with opts - POST /db/_all_docs } ] } - const scope = nock(COUCH_URL) - .post('/db/_all_docs?include_docs=true&descending=true', { keys }) - .reply(200, response) + mockPool + .intercept({ + method: 'post', + path: '/db/_all_docs?include_docs=true&descending=true', + body: JSON.stringify({ keys }) + }) + .reply(200, response, JSON_HEADERS) // test POST /db/_all_docs const db = nano.db.use('db') const p = await db.fetch({ keys }, { descending: true }) - expect(p).toStrictEqual(response) - expect(scope.isDone()).toBe(true) + assert.deepEqual(p, response) + mockAgent.assertNoPendingInterceptors() }) test('should be able to handle 404 - POST /db/_all_docs - db.fetch', async () => { @@ -144,31 +149,26 @@ test('should be able to handle 404 - POST /db/_all_docs - db.fetch', async () => error: 'not_found', reason: 'missing' } - const scope = nock(COUCH_URL) - .post('/db/_all_docs?include_docs=true', { keys }) - .reply(404, response) + mockPool + .intercept({ + method: 'post', + path: '/db/_all_docs?include_docs=true', + body: JSON.stringify({ keys }) + }) + .reply(404, response, JSON_HEADERS) // test POST /db/_all_docs const db = nano.db.use('db') - await expect(db.fetch({ keys })).rejects.toThrow('missing') - expect(scope.isDone()).toBe(true) + await assert.rejects(db.fetch({ keys }), { message: 'missing' }) + mockAgent.assertNoPendingInterceptors() }) test('should detect invalid parameters - db.fetch', async () => { const db = nano.db.use('db') - await expect(db.fetch()).rejects.toThrow('Invalid parameters') - await expect(db.fetch({})).rejects.toThrow('Invalid parameters') - await expect(db.fetch({ keys: {} })).rejects.toThrow('Invalid parameters') - await expect(db.fetch({ keys: '123' })).rejects.toThrow('Invalid parameters') - await expect(db.fetch({ keys: [] })).rejects.toThrow('Invalid parameters') + await assert.rejects(db.fetch(), { message: 'Invalid parameters' }) + await assert.rejects(db.fetch({}), { message: 'Invalid parameters' }) + await assert.rejects(db.fetch({ keys: {} }), { message: 'Invalid parameters' }) + await assert.rejects(db.fetch({ keys: '123' }), { message: 'Invalid parameters' }) + await assert.rejects(db.fetch({ keys: [] }), { message: 'Invalid parameters' }) }) -test('should detect missing parameters (callback) - db.fetch', () => { - return new Promise((resolve, reject) => { - const db = nano.db.use('db') - db.fetch(undefined, (err, data) => { - expect(err).not.toBeNull() - resolve() - }) - }) -}) diff --git a/test/document.fetchRevs.test.js b/test/document.fetchRevs.test.js index 1d6bb729..5d5771da 100644 --- a/test/document.fetchRevs.test.js +++ b/test/document.fetchRevs.test.js @@ -10,14 +10,11 @@ // License for the specific language governing permissions and limitations under // the License. +const test = require('node:test') +const assert = require('node:assert/strict') +const { COUCH_URL, mockAgent, mockPool, JSON_HEADERS } = require('./mock.js') const Nano = require('..') -const COUCH_URL = 'http://localhost:5984' const nano = Nano(COUCH_URL) -const nock = require('nock') - -afterEach(() => { - nock.cleanAll() -}) test('should be able to fetch a list of document revisions - POST /db/_all_docs - db.fetchRevs', async () => { // mocks @@ -49,15 +46,19 @@ test('should be able to fetch a list of document revisions - POST /db/_all_docs } ] } - const scope = nock(COUCH_URL) - .post('/db/_all_docs', { keys }) - .reply(200, response) + mockPool + .intercept({ + method: 'post', + path: '/db/_all_docs', + body: JSON.stringify({ keys }) + }) + .reply(200, response, JSON_HEADERS) // test POST /db/_all_docs const db = nano.db.use('db') const p = await db.fetchRevs({ keys }) - expect(p).toStrictEqual(response) - expect(scope.isDone()).toBe(true) + assert.deepEqual(p, response) + mockAgent.assertNoPendingInterceptors() }) test('should be able to fetch a list of document revisions with opts - POST /db/_all_docs - db.fetchRevs', async () => { @@ -90,15 +91,19 @@ test('should be able to fetch a list of document revisions with opts - POST /db } ] } - const scope = nock(COUCH_URL) - .post('/db/_all_docs?descending=true', { keys }) - .reply(200, response) + mockPool + .intercept({ + method: 'post', + path: '/db/_all_docs?descending=true', + body: JSON.stringify({ keys }) + }) + .reply(200, response, JSON_HEADERS) // test POST /db/_all_docs const db = nano.db.use('db') const p = await db.fetchRevs({ keys }, { descending: true }) - expect(p).toStrictEqual(response) - expect(scope.isDone()).toBe(true) + assert.deepEqual(p, response) + mockAgent.assertNoPendingInterceptors() }) test('should be able to handle 404 - POST /db/_all_docs - db.fetchRevs', async () => { @@ -108,31 +113,26 @@ test('should be able to handle 404 - POST /db/_all_docs - db.fetchRevs', async ( error: 'not_found', reason: 'missing' } - const scope = nock(COUCH_URL) - .post('/db/_all_docs', { keys }) - .reply(404, response) + mockPool + .intercept({ + method: 'post', + path: '/db/_all_docs', + body: JSON.stringify({ keys }) + }) + .reply(404, response, JSON_HEADERS) // test POST /db/_all_docs const db = nano.db.use('db') - await expect(db.fetchRevs({ keys })).rejects.toThrow('missing') - expect(scope.isDone()).toBe(true) + await assert.rejects(db.fetchRevs({ keys }), { message: 'missing' }) + mockAgent.assertNoPendingInterceptors() }) test('should detect missing parameters - db.fetchRevs', async () => { const db = nano.db.use('db') - await expect(db.fetchRevs()).rejects.toThrow('Invalid parameters') - await expect(db.fetchRevs({})).rejects.toThrow('Invalid parameters') - await expect(db.fetchRevs({ keys: {} })).rejects.toThrow('Invalid parameters') - await expect(db.fetchRevs({ keys: '123' })).rejects.toThrow('Invalid parameters') - await expect(db.fetchRevs({ keys: [] })).rejects.toThrow('Invalid parameters') + await assert.rejects(db.fetchRevs(), { message: 'Invalid parameters' }) + await assert.rejects(db.fetchRevs({}), { message: 'Invalid parameters' }) + await assert.rejects(db.fetchRevs({ keys: {} }), { message: 'Invalid parameters' }) + await assert.rejects(db.fetchRevs({ keys: '123' }), { message: 'Invalid parameters' }) + await assert.rejects(db.fetchRevs({ keys: [] }), { message: 'Invalid parameters' }) }) -test('should detect missing parameters (callback) - db.fetchRevs', () => { - return new Promise((resolve, reject) => { - const db = nano.db.use('db') - db.fetchRevs(undefined, (err, data) => { - expect(err).not.toBeNull() - resolve() - }) - }) -}) diff --git a/test/document.get.test.js b/test/document.get.test.js index 93443cb9..1babced1 100644 --- a/test/document.get.test.js +++ b/test/document.get.test.js @@ -10,55 +10,52 @@ // License for the specific language governing permissions and limitations under // the License. +const test = require('node:test') +const assert = require('node:assert/strict') +const { COUCH_URL, mockAgent, mockPool, JSON_HEADERS } = require('./mock.js') const Nano = require('..') -const COUCH_URL = 'http://localhost:5984' const nano = Nano(COUCH_URL) -const nock = require('nock') - -afterEach(() => { - nock.cleanAll() -}) test('should be able to get a document - GET /db/id - db.get', async () => { // mocks const response = { _id: 'id', rev: '1-123', a: 1, b: 'two', c: true } - const scope = nock(COUCH_URL) - .get('/db/id') - .reply(200, response) + mockPool + .intercept({ path: '/db/id' }) + .reply(200, response, JSON_HEADERS) // test GET /db/id const db = nano.db.use('db') const p = await db.get('id') - expect(p).toStrictEqual(response) - expect(scope.isDone()).toBe(true) + assert.deepEqual(p, response) + mockAgent.assertNoPendingInterceptors() }) test('should be able to get a document from a partition - GET /db/pkey:id - db.get', async () => { // mocks const response = { _id: 'partkey:id', rev: '1-123', a: 1, b: 'two', c: true } - const scope = nock(COUCH_URL) - .get('/db/partkey%3Aid') - .reply(200, response) + mockPool + .intercept({ path: '/db/partkey%3Aid' }) + .reply(200, response, JSON_HEADERS) // test GET /db/pkey:id const db = nano.db.use('db') const p = await db.get('partkey:id') - expect(p).toStrictEqual(response) - expect(scope.isDone()).toBe(true) + assert.deepEqual(p, response) + mockAgent.assertNoPendingInterceptors() }) test('should be able to get a document with options - GET /db/id?conflicts=true - db.get', async () => { // mocks const response = { _id: 'id', rev: '1-123', a: 1, b: 'two', c: true } - const scope = nock(COUCH_URL) - .get('/db/id?conflicts=true') - .reply(200, response) + mockPool + .intercept({ path: '/db/id?conflicts=true' }) + .reply(200, response, JSON_HEADERS) // test GET /db/id?x=y const db = nano.db.use('db') const p = await db.get('id', { conflicts: true }) - expect(p).toStrictEqual(response) - expect(scope.isDone()).toBe(true) + assert.deepEqual(p, response) + mockAgent.assertNoPendingInterceptors() }) test('should be able to handle 404 - GET /db/id - db.get', async () => { @@ -67,41 +64,31 @@ test('should be able to handle 404 - GET /db/id - db.get', async () => { error: 'not_found', reason: 'missing' } - const scope = nock(COUCH_URL) - .get('/db/id') - .reply(404, response) + mockPool + .intercept({ path: '/db/id' }) + .reply(404, response, JSON_HEADERS) // test GET /db/id const db = nano.db.use('db') - await expect(db.get('id')).rejects.toThrow('missing') - expect(scope.isDone()).toBe(true) + await assert.rejects(db.get('id'), { message: 'missing' }) + mockAgent.assertNoPendingInterceptors() }) test('should detect missing doc id - db.get', async () => { const db = nano.db.use('db') - await expect(db.get()).rejects.toThrow('Invalid parameters') -}) - -test('should detect missing parameters (callback) - db.get', () => { - return new Promise((resolve, reject) => { - const db = nano.db.use('db') - db.get(undefined, undefined, (err, data) => { - expect(err).not.toBeNull() - resolve() - }) - }) + await assert.rejects(db.get(), { message: 'Invalid parameters' }) }) test('check request can fetch local documents - db.get', async () => { // mocks const response = { _id: '_local/id', _rev: '1-123', a: 1 } - const scope = nock(COUCH_URL) - .get('/db/_local/id') - .reply(200, response) + mockPool + .intercept({ path: '/db/_local/id' }) + .reply(200, response, JSON_HEADERS) // test GET /db/_local/id const db = nano.db.use('db') const p = await db.get('_local/id') - expect(p).toStrictEqual(response) - expect(scope.isDone()).toBe(true) + assert.deepEqual(p, response) + mockAgent.assertNoPendingInterceptors() }) diff --git a/test/document.head.test.js b/test/document.head.test.js index 40eb1cb0..70941cea 100644 --- a/test/document.head.test.js +++ b/test/document.head.test.js @@ -10,71 +10,50 @@ // License for the specific language governing permissions and limitations under // the License. +const test = require('node:test') +const assert = require('node:assert/strict') +const { COUCH_URL, mockAgent, mockPool, JSON_HEADERS } = require('./mock.js') const Nano = require('..') -const COUCH_URL = 'http://localhost:5984' const nano = Nano(COUCH_URL) -const nock = require('nock') - -afterEach(() => { - nock.cleanAll() -}) test('should be able to head a document - HEAD /db/id - db.head', async () => { // mocks - const scope = nock(COUCH_URL) - .head('/db/id') - .reply(200, '', { ETag: '1-123' }) + const headers = { + 'content-type': 'application/json', + etag: '1-123' + } + mockPool + .intercept({ + method: 'head', + path: '/db/id' + }) + .reply(200, '', { headers }) // test HEAD /db const db = nano.db.use('db') const p = await db.head('id') // headers get lowercased - expect(p.etag).toBe('1-123') - expect(scope.isDone()).toBe(true) -}) - -test('should be able to head a document with callback - HEAD /db/id - db.head', () => { - // mocks - const scope = nock(COUCH_URL) - .head('/db/id') - .reply(200, '', { ETag: '1-123' }) - - // test HEAD /db - return new Promise((resolve, reject) => { - const db = nano.db.use('db') - db.head('id', (err, data, headers) => { - // headers get lowercased - expect(err).toBeNull() - expect(headers.etag).toBe('1-123') - expect(scope.isDone()).toBe(true) - resolve() - }) - }) + assert.equal(p.etag, '1-123') + mockAgent.assertNoPendingInterceptors() }) test('should be able to head a missing document - HEAD /db/id - db.head', async () => { // mocks - const scope = nock(COUCH_URL) - .head('/db/id') - .reply(404, '') + mockPool + .intercept({ + method: 'head', + path: '/db/id' + }) + .reply(404, '', JSON_HEADERS) // test HEAD /db const db = nano.db.use('db') - await expect(db.head('id')).rejects.toThrow('couch returned 404') - expect(scope.isDone()).toBe(true) + await assert.rejects(db.head('id'), { message: 'couch returned 404' }) + mockAgent.assertNoPendingInterceptors() }) test('should detect missing parameters - db.head', async () => { const db = nano.db.use('db') - await expect(db.head()).rejects.toThrow('Invalid parameters') + await assert.rejects(db.head(), { message: 'Invalid parameters' }) }) -test('should detect missing parameters (callback) - db.head', () => { - return new Promise((resolve, reject) => { - const db = nano.db.use('db') - db.head(undefined, (err, data) => { - expect(err).not.toBeNull() - resolve() - }) - }) -}) diff --git a/test/document.insert.test.js b/test/document.insert.test.js index c4532d70..6895a2fe 100644 --- a/test/document.insert.test.js +++ b/test/document.insert.test.js @@ -10,91 +10,105 @@ // License for the specific language governing permissions and limitations under // the License. +const test = require('node:test') +const assert = require('node:assert/strict') +const { COUCH_URL, mockAgent, mockPool, JSON_HEADERS } = require('./mock.js') const Nano = require('..') -const COUCH_URL = 'http://localhost:5984' const nano = Nano(COUCH_URL) -const nock = require('nock') - -afterEach(() => { - nock.cleanAll() -}) test('should be able to insert document - POST /db - db.insert', async () => { // mocks const doc = { a: 1, b: 2 } const response = { ok: true, id: '8s8g8h8h9', rev: '1-123' } - const scope = nock(COUCH_URL) - .post('/db', doc) - .reply(200, response) + mockPool + .intercept({ + method: 'post', + path: '/db', + body: JSON.stringify(doc) + }) + .reply(200, response, JSON_HEADERS) // test POST /db const db = nano.db.use('db') const p = await db.insert(doc) - expect(p).toStrictEqual(response) - expect(scope.isDone()).toBe(true) + assert.deepEqual(p, response) + mockAgent.assertNoPendingInterceptors() }) test('should be able to insert document with opts - POST /db?batch=ok - db.insert', async () => { // mocks const doc = { a: 1, b: 2 } const response = { ok: true, id: '8s8g8h8h9', rev: '1-123' } - const scope = nock(COUCH_URL) - .post('/db?batch=ok', doc) - .reply(200, response) + mockPool + .intercept({ + method: 'post', + path: '/db?batch=ok', + body: JSON.stringify(doc) + }) + .reply(200, response, JSON_HEADERS) // test POST /db const db = nano.db.use('db') const p = await db.insert(doc, { batch: 'ok' }) - expect(p).toStrictEqual(response) - expect(scope.isDone()).toBe(true) + assert.deepEqual(p, response) + mockAgent.assertNoPendingInterceptors() }) test('should be able to insert document with known id - PUT /db/id - db.insert', async () => { // mocks const doc = { a: 1, b: 2 } const response = { ok: true, id: 'myid', rev: '1-123' } - - const scope = nock(COUCH_URL) - .put('/db/myid', doc) - .reply(200, response) + mockPool + .intercept({ + method: 'put', + path: '/db/myid', + body: JSON.stringify(doc) + }) + .reply(200, response, JSON_HEADERS) // test PUT /db const db = nano.db.use('db') const p = await db.insert(doc, 'myid') - expect(p).toStrictEqual(response) - expect(scope.isDone()).toBe(true) + assert.deepEqual(p, response) + mockAgent.assertNoPendingInterceptors() }) test('should be able to insert document with id in object - POST /db - db.insert', async () => { // mocks const doc = { _id: 'myid', a: 1, b: 2 } const response = { ok: true, id: 'myid', rev: '1-123' } - - const scope = nock(COUCH_URL) - .post('/db', doc) - .reply(200, response) + mockPool + .intercept({ + method: 'post', + path: '/db', + body: JSON.stringify(doc) + }) + .reply(200, response, JSON_HEADERS) // test POST /db const db = nano.db.use('db') const p = await db.insert(doc) - expect(p).toStrictEqual(response) - expect(scope.isDone()).toBe(true) + assert.deepEqual(p, response) + mockAgent.assertNoPendingInterceptors() }) test('should be able to update document with id/rev in object - POST /db - db.insert', async () => { // mocks const doc = { _id: 'myid', _rev: '1-123', a: 2, b: 2 } const response = { ok: true, id: 'myid', rev: '2-456' } - - const scope = nock(COUCH_URL) - .post('/db', doc) - .reply(200, response) + mockPool + .intercept({ + method: 'post', + path: '/db', + body: JSON.stringify(doc) + }) + .reply(200, response, JSON_HEADERS) // test POST /db const db = nano.db.use('db') const p = await db.insert(doc) - expect(p).toStrictEqual(response) - expect(scope.isDone()).toBe(true) + assert.deepEqual(p, response) + mockAgent.assertNoPendingInterceptors() }) test('should be able to handle 409 conflicts - POST /db - db.insert', async () => { @@ -104,14 +118,18 @@ test('should be able to handle 409 conflicts - POST /db - db.insert', async () = error: 'conflict', reason: 'Document update conflict.' } - const scope = nock(COUCH_URL) - .post('/db', doc) - .reply(409, response) + mockPool + .intercept({ + method: 'post', + path: '/db', + body: JSON.stringify(doc) + }) + .reply(409, response, JSON_HEADERS) // test POST /db const db = nano.db.use('db') - await expect(db.insert(doc)).rejects.toThrow('Document update conflict.') - expect(scope.isDone()).toBe(true) + await assert.rejects(db.insert(doc), { message: 'Document update conflict.' }) + mockAgent.assertNoPendingInterceptors() }) test('should be able to handle missing database - POST /db - db.insert', async () => { @@ -121,44 +139,54 @@ test('should be able to handle missing database - POST /db - db.insert', async ( error: 'not_found', reason: 'Database does not exist.' } - const scope = nock(COUCH_URL) - .post('/db', doc) - .reply(404, response) + mockPool + .intercept({ + method: 'post', + path: '/db', + body: JSON.stringify(doc) + }) + .reply(404, response, JSON_HEADERS) // test POST /db const db = nano.db.use('db') - await expect(db.insert(doc)).rejects.toThrow('Database does not exist.') - expect(scope.isDone()).toBe(true) + await assert.rejects(db.insert(doc), { message: 'Database does not exist.' }) + mockAgent.assertNoPendingInterceptors() }) test('should be able to insert document with _local id - PUT /db/_local/id - db.insert', async () => { // mocks const doc = { a: 1, b: 2 } const response = { ok: true, id: '_local/myid', rev: '1-123' } - - const scope = nock(COUCH_URL) - .put('/db/_local/myid', doc) - .reply(200, response) + mockPool + .intercept({ + method: 'put', + path: '/db/_local/myid', + body: JSON.stringify(doc) + }) + .reply(200, response, JSON_HEADERS) // test PUT /db const db = nano.db.use('db') const p = await db.insert(doc, '_local/myid') - expect(p).toStrictEqual(response) - expect(scope.isDone()).toBe(true) + assert.deepEqual(p, response) + mockAgent.assertNoPendingInterceptors() }) test('should be able to insert document with local id in object - POST /db - db.insert', async () => { // mocks const doc = { _id: '_local/myid', a: 1, b: 2 } const response = { ok: true, id: '_local/myid', rev: '1-123' } - - const scope = nock(COUCH_URL) - .post('/db', doc) - .reply(200, response) + mockPool + .intercept({ + method: 'post', + path: '/db', + body: JSON.stringify(doc) + }) + .reply(200, response, JSON_HEADERS) // test POST /db const db = nano.db.use('db') const p = await db.insert(doc) - expect(p).toStrictEqual(response) - expect(scope.isDone()).toBe(true) + assert.deepEqual(p, response) + mockAgent.assertNoPendingInterceptors() }) diff --git a/test/document.list.test.js b/test/document.list.test.js index 53fc2450..175d4606 100644 --- a/test/document.list.test.js +++ b/test/document.list.test.js @@ -10,14 +10,11 @@ // License for the specific language governing permissions and limitations under // the License. +const test = require('node:test') +const assert = require('node:assert/strict') +const { COUCH_URL, mockAgent, mockPool, JSON_HEADERS } = require('./mock.js') const Nano = require('..') -const COUCH_URL = 'http://localhost:5984' const nano = Nano(COUCH_URL) -const nock = require('nock') - -afterEach(() => { - nock.cleanAll() -}) test('should be able to get a list of documents - GET /db/_all_docs - db.list', async () => { // mocks @@ -48,15 +45,15 @@ test('should be able to get a list of documents - GET /db/_all_docs - db.list', } ] } - const scope = nock(COUCH_URL) - .get('/db/_all_docs') - .reply(200, response) + mockPool + .intercept({ path: '/db/_all_docs' }) + .reply(200, response, JSON_HEADERS) // test GET /db/_all_docs const db = nano.db.use('db') const p = await db.list() - expect(p).toStrictEqual(response) - expect(scope.isDone()).toBe(true) + assert.deepEqual(p, response) + mockAgent.assertNoPendingInterceptors() }) test('should be able to get a list of documents with opts - GET /db/_all_docs - db.list', async () => { @@ -80,15 +77,15 @@ test('should be able to get a list of documents with opts - GET /db/_all_docs - } ] } - const scope = nock(COUCH_URL) - .get('/db/_all_docs?include_docs=true&limit=1') - .reply(200, response) + mockPool + .intercept({ path: '/db/_all_docs?include_docs=true&limit=1' }) + .reply(200, response, JSON_HEADERS) // test GET /db/_all_docs const db = nano.db.use('db') const p = await db.list({ include_docs: true, limit: 1 }) - expect(p).toStrictEqual(response) - expect(scope.isDone()).toBe(true) + assert.deepEqual(p, response) + mockAgent.assertNoPendingInterceptors() }) test('should be able to handle 404 - GET /db/_all_docs - db.list', async () => { @@ -97,12 +94,12 @@ test('should be able to handle 404 - GET /db/_all_docs - db.list', async () => { error: 'not_found', reason: 'missing' } - const scope = nock(COUCH_URL) - .get('/db/_all_docs') - .reply(404, response) + mockPool + .intercept({ path: '/db/_all_docs' }) + .reply(404, response, JSON_HEADERS) // test GET /db/_all_docs const db = nano.db.use('db') - await expect(db.list()).rejects.toThrow('missing') - expect(scope.isDone()).toBe(true) + await assert.rejects(db.list(), { message: 'missing' }) + mockAgent.assertNoPendingInterceptors() }) diff --git a/test/document.listAsStream.test.js b/test/document.listAsStream.test.js index cdeac804..e3590f64 100644 --- a/test/document.listAsStream.test.js +++ b/test/document.listAsStream.test.js @@ -10,14 +10,11 @@ // License for the specific language governing permissions and limitations under // the License. +const test = require('node:test') +const assert = require('node:assert/strict') +const { COUCH_URL, mockAgent, mockPool, JSON_HEADERS } = require('./mock.js') const Nano = require('..') -const COUCH_URL = 'http://localhost:5984' const nano = Nano(COUCH_URL) -const nock = require('nock') - -afterEach(() => { - nock.cleanAll() -}) test('should get a streamed list of documents - GET /db/_all_docs - db.listAsStream', async () => { // mocks @@ -48,28 +45,28 @@ test('should get a streamed list of documents - GET /db/_all_docs - db.listAsStr } ] } - const scope = nock(COUCH_URL) - .get('/db/_all_docs') - .reply(200, response) + mockPool + .intercept({ path: '/db/_all_docs' }) + .reply(200, response, JSON_HEADERS) - return new Promise((resolve, reject) => { + await new Promise((resolve, reject) => { // test GET /db/_all_docs const db = nano.db.use('db') const s = db.listAsStream() - expect(typeof s).toBe('object') + assert.equal(typeof s, 'object') let buffer = '' s.on('data', (chunk) => { buffer += chunk.toString() }) s.on('end', () => { - expect(buffer).toBe(JSON.stringify(response)) - expect(scope.isDone()).toBe(true) + assert.equal(buffer, JSON.stringify(response)) + mockAgent.assertNoPendingInterceptors() resolve() }) }) }) -test('should get a streamed list of documents with opts- GET /db/_all_docs - db.listAsStream', () => { +test('should get a streamed list of documents with opts- GET /db/_all_docs - db.listAsStream', async () => { // mocks const response = { total_rows: 23516, @@ -90,22 +87,22 @@ test('should get a streamed list of documents with opts- GET /db/_all_docs - db. } ] } - const scope = nock(COUCH_URL) - .get('/db/_all_docs?limit=1&include_docs=true') - .reply(200, response) + mockPool + .intercept({ path: '/db/_all_docs?limit=1&include_docs=true' }) + .reply(200, response, JSON_HEADERS) - return new Promise((resolve, reject) => { + await new Promise((resolve, reject) => { // test GET /db/_all_docs const db = nano.db.use('db') const s = db.listAsStream({ limit: 1, include_docs: true }) - expect(typeof s).toBe('object') + assert.equal(typeof s, 'object') let buffer = '' s.on('data', (chunk) => { buffer += chunk.toString() }) s.on('end', () => { - expect(buffer).toBe(JSON.stringify(response)) - expect(scope.isDone()).toBe(true) + assert.equal(buffer, JSON.stringify(response)) + mockAgent.assertNoPendingInterceptors() resolve() }) }) diff --git a/test/mock.js b/test/mock.js new file mode 100644 index 00000000..d793f950 --- /dev/null +++ b/test/mock.js @@ -0,0 +1,14 @@ +const COUCH_URL = 'http://127.0.0.1:5984' +const JSON_HEADERS = { headers: { 'content-type': 'application/json' } } +const { MockAgent, setGlobalDispatcher } = require('undici') +const mockAgent = new MockAgent() +mockAgent.disableNetConnect() +const mockPool = mockAgent.get(COUCH_URL) +setGlobalDispatcher(mockAgent) + +module.exports = { + COUCH_URL, + JSON_HEADERS, + mockAgent, + mockPool +} diff --git a/test/multipart.get.test.js b/test/multipart.get.test.js index d00d52de..5b6056a2 100644 --- a/test/multipart.get.test.js +++ b/test/multipart.get.test.js @@ -10,10 +10,12 @@ // License for the specific language governing permissions and limitations under // the License. +const test = require('node:test') +const assert = require('node:assert/strict') +const { COUCH_URL, mockAgent, mockPool, JSON_HEADERS } = require('./mock.js') const Nano = require('..') -const COUCH_URL = 'http://localhost:5984' const nano = Nano(COUCH_URL) -const nock = require('nock') + const multipartResponse = ''.concat( '--e89b3e29388aef23453450d10e5aaed0', 'Content-Type: application/json', @@ -32,34 +34,40 @@ const multipartResponse = ''.concat( '', '--e89b3e29388aef23453450d10e5aaed0--') -afterEach(() => { - nock.cleanAll() -}) - test('should be able to fetch a document with attachments - multipart GET /db - db.multipart.get', async () => { // mocks - const scope = nock(COUCH_URL, { reqheaders: { accept: 'multipart/related' } }) - .get('/db/docid?attachments=true') - .reply(200, multipartResponse, { 'content-type': 'multipart/related; boundary="e89b3e29388aef23453450d10e5aaed0"' }) + mockPool + .intercept({ + path: '/db/docid?attachments=true', + headers: { + accept: 'multipart/related' + } + }) + .reply(200, multipartResponse, { headers: { 'content-type': 'multipart/related; boundary="e89b3e29388aef23453450d10e5aaed0"' } }) // test GET /db/id?attachments=true const db = nano.db.use('db') const p = await db.multipart.get('docid') - expect(p.toString()).toStrictEqual(multipartResponse) - expect(scope.isDone()).toBe(true) + assert.deepEqual(p, multipartResponse) + mockAgent.assertNoPendingInterceptors() }) test('should be able to fetch a document with attachments with opts - multipart GET /db - db.multipart.get', async () => { // mocks - const scope = nock(COUCH_URL, { reqheaders: { accept: 'multipart/related' } }) - .get('/db/docid?attachments=true&conflicts=true') - .reply(200, multipartResponse, { 'content-type': 'multipart/related; boundary="e89b3e29388aef23453450d10e5aaed0"' }) + mockPool + .intercept({ + path: '/db/docid?attachments=true&conflicts=true', + headers: { + accept: 'multipart/related' + } + }) + .reply(200, multipartResponse, { headers: { 'content-type': 'multipart/related; boundary="e89b3e29388aef23453450d10e5aaed0"' } }) // test GET /db/id?attachments=true&x=y const db = nano.db.use('db') const p = await db.multipart.get('docid', { conflicts: true }) - expect(p.toString()).toStrictEqual(multipartResponse) - expect(scope.isDone()).toBe(true) + assert.deepEqual(p, multipartResponse) + mockAgent.assertNoPendingInterceptors() }) test('should be able to handle 404 - db.multipart.get', async () => { @@ -68,29 +76,25 @@ test('should be able to handle 404 - db.multipart.get', async () => { error: 'not_found', reason: 'missing' } - const scope = nock(COUCH_URL, { reqheaders: { accept: 'multipart/related' } }) - .get('/db/docid?attachments=true') - .reply(404, response) + mockPool + .intercept({ + path: '/db/docid?attachments=true', + headers: { + accept: 'multipart/related' + } + }) + .reply(404, response, JSON_HEADERS) // test GET /db const db = nano.db.use('db') - await expect(db.multipart.get('docid')).rejects.toThrow('missing') - expect(scope.isDone()).toBe(true) + await assert.rejects(db.multipart.get('docid'), { message: 'missing' }) + mockAgent.assertNoPendingInterceptors() }) test('should detect missing docName - db.multipart.get', async () => { const db = nano.db.use('db') - await expect(db.multipart.get()).rejects.toThrow('Invalid parameters') - await expect(db.multipart.get('')).rejects.toThrow('Invalid parameters') - await expect(db.multipart.get(undefined, { conflicts: true })).rejects.toThrow('Invalid parameters') + await assert.rejects(db.multipart.get(), { message: 'Invalid parameters' }) + await assert.rejects(db.multipart.get(''), { message: 'Invalid parameters' }) + await assert.rejects(db.multipart.get(undefined, { conflicts: true }), { message: 'Invalid parameters' }) }) -test('should detect missing parameters (callback) - db.multipart.get', () => { - const db = nano.db.use('db') - return new Promise((resolve, reject) => { - db.multipart.get(undefined, undefined, (err, data) => { - expect(err).not.toBeNull() - resolve() - }) - }) -}) diff --git a/test/multipart.insert.test.js b/test/multipart.insert.test.js index 4f84462f..38dce827 100644 --- a/test/multipart.insert.test.js +++ b/test/multipart.insert.test.js @@ -10,10 +10,11 @@ // License for the specific language governing permissions and limitations under // the License. +const test = require('node:test') +const assert = require('node:assert/strict') +const { COUCH_URL, mockAgent, mockPool, JSON_HEADERS } = require('./mock.js') const Nano = require('..') -const COUCH_URL = 'http://localhost:5984' const nano = Nano(COUCH_URL) -const nock = require('nock') const image1 = Buffer.from(''.concat( 'iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAMAAAAoLQ9TAAAAsV', 'BMVEUAAAD////////////////////////5ur3rEBn////////////////wDBL/', @@ -46,37 +47,49 @@ const doc = { } } -afterEach(() => { - nock.cleanAll() -}) - test('should be able to insert a document with attachments #1 - multipart PUT /db/id - db.multipart.insert', async () => { // mocks const response = { ok: true, id: '8s8g8h8h9', rev: '1-123' } - const scope = nock(COUCH_URL) - .matchHeader('content-type', h => h.includes('multipart/related')) - .put('/db/docid') - .reply(200, response) + mockPool + .intercept({ + method: 'put', + path: '/db/docid', + headers: { + 'content-type': /^multipart\/related; .*/ + }, + body: (value) => { + return true + } + }) + .reply(200, response, JSON_HEADERS) // test PUT /db/id const db = nano.db.use('db') const p = await db.multipart.insert(doc, images, 'docid') - expect(p).toStrictEqual(response) - expect(scope.isDone()).toBe(true) + assert.deepEqual(p, response) + mockAgent.assertNoPendingInterceptors() }) test('should be able to insert a document with attachments #2 - multipart PUT /db/id - db.multipart.insert', async () => { const response = { ok: true, id: '8s8g8h8h9', rev: '1-123' } - const scope = nock(COUCH_URL) - .matchHeader('content-type', h => h.includes('multipart/related')) - .put('/db/docid') - .reply(200, response) + mockPool + .intercept({ + method: 'put', + path: '/db/docid', + headers: { + 'content-type': /^multipart\/related; .*/ + }, + body: (value) => { + return true + } + }) + .reply(200, response, JSON_HEADERS) // test PUT /db/id const db = nano.db.use('db') const p = await db.multipart.insert(doc, images, { docName: 'docid' }) - expect(p).toStrictEqual(response) - expect(scope.isDone()).toBe(true) + assert.deepEqual(p, response) + mockAgent.assertNoPendingInterceptors() }) test('should be able to handle 404 - db.multipart.insert', async () => { @@ -85,30 +98,29 @@ test('should be able to handle 404 - db.multipart.insert', async () => { error: 'not_found', reason: 'missing' } - const scope = nock(COUCH_URL) - .matchHeader('content-type', h => h.includes('multipart/related')) - .put('/db/docid') - .reply(404, response) + mockPool + .intercept({ + method: 'put', + path: '/db/docid', + headers: { + 'content-type': /^multipart\/related; .*/ + }, + body: (value) => { + return true + } + }) + .reply(404, response, JSON_HEADERS) // test PUT /db/id const db = nano.db.use('db') - await expect(db.multipart.insert(doc, images, { docName: 'docid' })).rejects.toThrow('missing') - expect(scope.isDone()).toBe(true) + await assert.rejects(db.multipart.insert(doc, images, { docName: 'docid' }), { message: 'missing' }) + mockAgent.assertNoPendingInterceptors() }) test('should detect missing docName - db.multipart.insert', async () => { const db = nano.db.use('db') - await expect(db.multipart.insert()).rejects.toThrow('Invalid parameters') - await expect(db.multipart.insert({ a: 1 }, [{}])).rejects.toThrow('Invalid parameters') - await expect(db.multipart.insert({ a: 1 }, [{}], {})).rejects.toThrow('Invalid parameters') + await assert.rejects(db.multipart.insert(), { message: 'Invalid parameters' }) + await assert.rejects(db.multipart.insert({ a: 1 }, [{}]), { message: 'Invalid parameters' }) + await assert.rejects(db.multipart.insert({ a: 1 }, [{}], {}), { message: 'Invalid parameters' }) }) -test('should detect missing parameters (callback) - db.multipart.insert', () => { - const db = nano.db.use('db') - return new Promise((resolve, reject) => { - db.multipart.insert(undefined, undefined, undefined, (err, data) => { - expect(err).not.toBeNull() - resolve() - }) - }) -}) diff --git a/test/multipart.test.js b/test/multipart.test.js index f1173f85..32d08705 100644 --- a/test/multipart.test.js +++ b/test/multipart.test.js @@ -1,3 +1,5 @@ +const test = require('node:test') +const assert = require('node:assert/strict') const MultiPartFactory = require('../lib/multipart.js') const textAttachment = { name: 'test.txt', data: 'Hello\r\nWorld!', content_type: 'text/plain' } const anotherTextAttachment = { name: 'test2.txt', data: 'the quick brown fox', content_type: 'text/plain' } @@ -7,50 +9,51 @@ test('should return different boundary each time', async () => { const mf2 = new MultiPartFactory([]) const mf3 = new MultiPartFactory([]) - expect(typeof mf1.boundary).toBe('string') - expect(typeof mf2.boundary).toBe('string') - expect(typeof mf3.boundary).toBe('string') - expect(mf1.boundary.length).toBe(16) - expect(mf2.boundary.length).toBe(16) - expect(mf3.boundary.length).toBe(16) - expect(mf1).not.toEqual(mf2) - expect(mf1).not.toEqual(mf3) - expect(mf2).not.toEqual(mf3) + assert.equal(typeof mf1.boundary, 'string') + assert.equal(typeof mf2.boundary, 'string') + assert.equal(typeof mf3.boundary, 'string') + assert.equal(mf1.boundary.length, 16) + assert.equal(mf2.boundary.length, 16) + assert.equal(mf3.boundary.length, 16) + assert.notEqual(mf1, mf2) + assert.notEqual(mf1, mf3) + assert.notEqual(mf2, mf3) }) test('should return boundary in header', async () => { const mf1 = new MultiPartFactory([]) const boundary = mf1.boundary const header = mf1.header - expect(header).toEqual(`multipart/related; boundary=${boundary}`) + assert.equal(header, `multipart/related; boundary=${boundary}`) }) test('should handle single attachments', async () => { const mf1 = new MultiPartFactory([textAttachment]) - expect(typeof mf1.data).toEqual('object') - expect(Buffer.isBuffer(mf1.data)).toEqual(true) + + assert.equal(typeof mf1.data, 'object') + assert.equal(Buffer.isBuffer(mf1.data), true) const lines = mf1.data.toString().split('\r\n') - expect(lines).toContain(`--${mf1.boundary}`) - expect(lines).toContain('content-type: text/plain') - expect(lines).toContain('content-length: 13') - expect(lines).toContain('') - expect(lines).toContain('Hello') - expect(lines).toContain('World!') - expect(lines).toContain(`--${mf1.boundary}--`) + assert.equal(lines.includes(`--${mf1.boundary}`), true) + assert.equal(lines.includes('content-type: text/plain'), true) + assert.equal(lines.includes('content-length: 13'), true) + assert.equal(lines.includes(''), true) + assert.equal(lines.includes('Hello'), true) + assert.equal(lines.includes('World!'), true) + assert.equal(lines.includes(`--${mf1.boundary}--`), true) }) test('should handle two attachments', async () => { const mf1 = new MultiPartFactory([textAttachment, anotherTextAttachment]) - expect(typeof mf1.data).toEqual('object') - expect(Buffer.isBuffer(mf1.data)).toEqual(true) + assert.equal(typeof mf1.data, 'object') + assert.equal(Buffer.isBuffer(mf1.data), true) const lines = mf1.data.toString().split('\r\n') - expect(lines).toContain(`--${mf1.boundary}`) - expect(lines).toContain('content-type: text/plain') - expect(lines).toContain('content-length: 13') - expect(lines).toContain('') - expect(lines).toContain('Hello') - expect(lines).toContain('World!') - expect(lines).toContain('content-length: 19') - expect(lines).toContain('the quick brown fox') - expect(lines).toContain(`--${mf1.boundary}--`) + assert.equal(lines.includes(`--${mf1.boundary}`), true) + assert.equal(lines.includes('content-type: text/plain'), true) + assert.equal(lines.includes('content-length: 13'), true) + assert.equal(lines.includes(''), true) + assert.equal(lines.includes('Hello'), true) + assert.equal(lines.includes('World!'), true) + assert.equal(lines.includes('content-length: 19'), true) + assert.equal(lines.includes('the quick brown fox'), true) + assert.equal(lines.includes(`--${mf1.boundary}`), true) }) diff --git a/test/nano.agent.test.js b/test/nano.agent.test.js index 88cd1e22..a124b0d9 100644 --- a/test/nano.agent.test.js +++ b/test/nano.agent.test.js @@ -1,48 +1,19 @@ -// Licensed under the Apache License, Version 2.0 (the 'License'); you may not -// use this file except in compliance with the License. You may obtain a copy of -// the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an 'AS IS' BASIS, WITHOUT -// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -// License for the specific language governing permissions and limitations under -// the License. +const test = require('node:test') +const assert = require('node:assert/strict') +const { COUCH_URL, mockAgent } = require('./mock.js') +const Nano = require('../lib/nano') +const undici = require('undici') -const nock = require('nock') -const Nano = require('..') -const COUCH_URL = 'http://localhost:5984' -const http = require('http') -const httpAgent = new http.Agent() - -afterEach(() => { - nock.cleanAll() +test('should be able to supply a custom agent parameters', async () => { + const agentOptions = { + bodyTimeout: 10000 + } + const undiciOptions = new undici.Agent(agentOptions) + const nano = Nano({ url: COUCH_URL, undiciOptions }) + assert.equal(nano.config.agent, nano.config.agent) }) -test('should be able to log output with a user-supplied http agent', async () => { - // setup Nano with custom logger - const logs = [] - const nano = Nano({ - url: COUCH_URL, - log: (data) => { - logs.push(data) - }, - requestDefaults: { - agent: httpAgent - } - }) - - // mocks - const response = { _id: 'id', rev: '1-123', a: 1, b: 'two', c: true } - const scope = nock(COUCH_URL) - .get('/db/id') - .reply(200, response) - - // test GET /db/id - const db = nano.db.use('db') - const p = await db.get('id') - expect(p).toStrictEqual(response) - expect(logs.length).toBe(2) - expect(scope.isDone()).toBe(true) +test('should be able to supply a custom agent', async () => { + const nano = Nano({ url: COUCH_URL, agentOptions: mockAgent }) + assert.equal(nano.config.agent, mockAgent) }) diff --git a/test/nano.auth.test.js b/test/nano.auth.test.js index 70182758..2e5cd3b9 100644 --- a/test/nano.auth.test.js +++ b/test/nano.auth.test.js @@ -10,14 +10,11 @@ // License for the specific language governing permissions and limitations under // the License. +const test = require('node:test') +const assert = require('node:assert/strict') +const { COUCH_URL, mockAgent, mockPool, JSON_HEADERS } = require('./mock.js') const Nano = require('..') -const COUCH_URL = 'http://localhost:5984' -const nano = Nano({ url: COUCH_URL, jar: true }) -const nock = require('nock') - -afterEach(() => { - nock.cleanAll() -}) +const nano = Nano({ url: COUCH_URL }) test('should be able to authenticate - POST /_session - nano.auth', async () => { // mocks @@ -26,15 +23,92 @@ test('should be able to authenticate - POST /_session - nano.auth', async () => const response = { ok: true, name: 'admin', roles: ['_admin', 'admin'] } const c = 'AuthSession=YWRtaW46NUU0MTFBMDE6stHsxYnlDy4mYxwZEcnXHn4fm5w' const cookie = `${c}; Version=1; Expires=Mon, 10-Feb-2050 09:03:21 GMT; Max-Age=600; Path=/; HttpOnly` - const scope = nock(COUCH_URL) - .post('/_session', 'name=u&password=p', { 'content-type': 'application/x-www-form-urlencoded; charset=utf-8' }) - .reply(200, response, { 'Set-Cookie': cookie }) - .get('/_all_dbs', undefined, { headers: { cookie: c } }) - .reply(200, ['a']) + + mockPool + .intercept({ + method: 'post', + path: '/_session', + body: 'name=u&password=p', + headers: { + 'content-type': 'application/x-www-form-urlencoded; charset=utf-8' + } + }) + .reply(200, response, { + headers: { + 'content-type': 'application/json', + 'Set-Cookie': cookie + } + }) + + mockPool + .intercept({ + path: '/_all_dbs', + headers: { + cookie: c + } + }) + .reply(200, ['a'], JSON_HEADERS) // test POST /_session const p = await nano.auth(username, password) - expect(p).toStrictEqual(response) - await nano.db.list() - expect(scope.isDone()).toBe(true) + assert.deepEqual(p, response) + const q = await nano.db.list() + assert.deepEqual(q, ['a']) + mockAgent.assertNoPendingInterceptors() +}) + +test('should be able to handle cookie refresh - POST /_session - nano.auth', async () => { + // mocks + const username = 'u' + const password = 'p' + const response = { ok: true, name: 'admin', roles: ['_admin', 'admin'] } + const c1 = 'AuthSession=YWRtaW46NUU0MTFBMDE6stHsxYnlDy4mYxwZEcnXHn4fm5w' + const cookie1 = `${c1}; Version=1; Expires=Mon, 10-Feb-2050 09:03:21 GMT; Max-Age=600; Path=/; HttpOnly` + const c2 = 'AuthSession=DE6stHsxYnlDy4YWRtaW46NUU0MTFBMmYxwZEcnXHn4fm5w' + const cookie2 = `${c2}; Version=1; Expires=Mon, 10-Feb-2050 09:05:21 GMT; Max-Age=600; Path=/; HttpOnly` + mockPool + .intercept({ + method: 'post', + path: '/_session', + body: 'name=u&password=p', + headers: { + 'content-type': 'application/x-www-form-urlencoded; charset=utf-8' + } + }) + .reply(200, response, { + headers: { + 'content-type': 'application/json', + 'Set-Cookie': cookie1 + } + }) + mockPool + .intercept({ + path: '/_all_dbs', + headers: { + cookie: c1 + } + }) + .reply(200, ['a'], { + headers: { + 'content-type': 'application/json', + 'Set-Cookie': cookie2 + } + }) + mockPool + .intercept({ + path: '/_all_dbs', + headers: { + cookie: c2 + } + }) + .reply(200, ['a'], JSON_HEADERS) + + // test POST /_session + const p1 = await nano.auth(username, password) + assert.deepEqual(p1, response) + const p2 = await nano.db.list() + assert.deepEqual(p2, ['a']) + const p3 = await nano.db.list() + assert.deepEqual(p3, ['a']) + mockAgent.assertNoPendingInterceptors() }) diff --git a/test/nano.config.test.js b/test/nano.config.test.js index 16c02b5d..3209dd79 100644 --- a/test/nano.config.test.js +++ b/test/nano.config.test.js @@ -11,46 +11,47 @@ // the License. const Nano = require('..') -const assert = require('assert') +const test = require('node:test') +const assert = require('node:assert/strict') test('should be able to supply HTTP url - nano.config', () => { - const HTTP_URL = 'http://localhost:5984' + const HTTP_URL = 'http://127.0.0.1:5984' const nano = Nano(HTTP_URL) - expect(nano.config.url).toBe(HTTP_URL) + assert.equal(nano.config.url, HTTP_URL) }) test('should be able to supply URL with database name - nano.config', () => { - const HTTP_URL = 'http://localhost:5984/db' + const HTTP_URL = 'http://127.0.0.1:5984/db' const nano = Nano(HTTP_URL) - expect(nano.config.url).toBe('http://localhost:5984') - expect(nano.config.db).toBe('db') + assert.equal(nano.config.url, 'http://127.0.0.1:5984') + assert.equal(nano.config.db, 'db') }) test('should be able to supply HTTPS url - nano.config', () => { const HTTPS_URL = 'https://mydomain.com' const nano = Nano(HTTPS_URL) - expect(nano.config.url).toBe(HTTPS_URL) + assert.equal(nano.config.url, HTTPS_URL) }) test('should be able to supply HTTP url with cookie jar - nano.config', () => { - const HTTP_URL = 'http://localhost:5984' + const HTTP_URL = 'http://127.0.0.1:5984' const nano = Nano({ url: HTTP_URL, jar: true }) - expect(nano.config.url).toBe(HTTP_URL) - expect(nano.config.jar).toBe(true) + assert.equal(nano.config.url, HTTP_URL) + assert.equal(nano.config.jar, true) }) test('should be able to supply HTTPS url with auth credentials - nano.config', () => { const HTTPS_URL = 'https://myusername:mypassword@mydomain.com' const nano = Nano(HTTPS_URL) - expect(nano.config.url).toBe(HTTPS_URL) + assert.equal(nano.config.url, HTTPS_URL) }) test('should be able to supply requestDefaults - nano.config', () => { const HTTPS_URL = 'https://myusername:mypassword@mydomain.com' const defaults = { proxy: 'http://localproxy.com' } const nano = Nano({ url: HTTPS_URL, requestDefaults: defaults }) - expect(nano.config.url).toBe(HTTPS_URL) - expect(nano.config.requestDefaults).toBe(defaults) + assert.equal(nano.config.url, HTTPS_URL) + assert.equal(nano.config.requestDefaults, defaults) }) test('should be able to supply logging function - nano.config', () => { @@ -59,16 +60,15 @@ test('should be able to supply logging function - nano.config', () => { console.log(id, args) } const nano = Nano({ url: HTTPS_URL, log: logger }) - expect(nano.config.url).toBe(HTTPS_URL) - expect(typeof nano.config.log).toBe('function') + assert.equal(nano.config.url, HTTPS_URL) + assert.equal(typeof nano.config.log, 'function') }) test('should be able to handle missing URL - nano.config', () => { try { Nano() } catch (e) { - expect(e instanceof assert.AssertionError) - expect(e.message).toBe('You must specify the endpoint url when invoking this module') + assert(e instanceof assert.AssertionError) } }) @@ -77,8 +77,7 @@ test('should be able to handle invalid URL #1 - nano.config', () => { try { Nano(INVALID_URL) } catch (e) { - expect(e instanceof assert.AssertionError) - expect(e.message).toBe('url is not valid') + assert(e instanceof assert.AssertionError) } }) @@ -87,16 +86,15 @@ test('should be able to handle invalid URL #2 - nano.config', () => { try { Nano({ url: INVALID_URL }) } catch (e) { - expect(e instanceof assert.AssertionError) - expect(e.message).toBe('url is not valid') + assert(e instanceof assert.AssertionError) } }) test('exercise the parseUrl feature for proxies etc - nano.config', () => { - const HTTP_URL = 'http://localhost:5984/prefix' + const HTTP_URL = 'http://127.0.0.1:5984/prefix' const nano = Nano({ url: HTTP_URL, parseUrl: false }) - expect(nano.config.url).toBe(HTTP_URL) + assert.equal(nano.config.url, HTTP_URL) }) diff --git a/test/nano.customheaders.test.js b/test/nano.customheaders.test.js index d6f0c720..38131f84 100644 --- a/test/nano.customheaders.test.js +++ b/test/nano.customheaders.test.js @@ -10,18 +10,17 @@ // License for the specific language governing permissions and limitations under // the License. +const test = require('node:test') +const assert = require('node:assert/strict') +const { COUCH_URL, mockAgent, mockPool, JSON_HEADERS } = require('./mock.js') const Nano = require('..') -const COUCH_URL = 'http://localhost:5984' const CUSTOM_HEADER = 'thequickbrownfox' const nano = Nano({ url: COUCH_URL, - requestDefaults: { - headers: { - customheader: CUSTOM_HEADER - } + headers: { + customheader: CUSTOM_HEADER } }) -const nock = require('nock') const response = { db_name: 'db', purge_seq: '0-8KhNZEiqhyjKAgBm5Rxs', @@ -49,21 +48,19 @@ const response = { instance_start_time: '0' } -afterEach(() => { - nock.cleanAll() -}) - test('should be able to fetch the database info - GET /db - nano.db.get', async () => { // mocks - const scope = nock(COUCH_URL) - .matchHeader('customheader', CUSTOM_HEADER) - .get('/db') - .reply(200, response) + mockPool + .intercept({ + path: '/db', + headers: { + customheader: CUSTOM_HEADER + } + }) + .reply(200, response, JSON_HEADERS) // test GET /db const p = await nano.db.get('db') - expect(typeof p).toBe('object') - expect(p.doc_count).toBe(0) - expect(p.db_name).toBe('db') - expect(scope.isDone()).toBe(true) + assert.deepEqual(p, response) + mockAgent.assertNoPendingInterceptors() }) diff --git a/test/nano.info.test.js b/test/nano.info.test.js index 6cb87173..1e97dff3 100644 --- a/test/nano.info.test.js +++ b/test/nano.info.test.js @@ -10,14 +10,11 @@ // License for the specific language governing permissions and limitations under // the License. +const test = require('node:test') +const assert = require('node:assert/strict') +const { COUCH_URL, mockAgent, mockPool, JSON_HEADERS } = require('./mock.js') const Nano = require('../lib/nano') -const COUCH_URL = 'http://localhost:5984' const nano = Nano(COUCH_URL) -const nock = require('nock') - -afterEach(() => { - nock.cleanAll() -}) test('should be able to get info - GET / - nano.info', async () => { // mocks @@ -30,12 +27,12 @@ test('should be able to get info - GET / - nano.info', async () => { features: ['access-ready', 'partitioned', 'pluggable-storage-engines', 'reshard', 'scheduler'], vendor: { name: 'The Apache Software Foundation' } } - const scope = nock(COUCH_URL) - .get('/') - .reply(200, response) + mockPool + .intercept({ path: '/' }) + .reply(200, response, JSON_HEADERS) // test GET /_session const p = await nano.info() - expect(p).toStrictEqual(response) - expect(scope.isDone()).toBe(true) + assert.deepEqual(p, response) + mockAgent.assertNoPendingInterceptors() }) diff --git a/test/nano.logger.test.js b/test/nano.logger.test.js index 0c212e59..1db53c79 100644 --- a/test/nano.logger.test.js +++ b/test/nano.logger.test.js @@ -10,13 +10,10 @@ // License for the specific language governing permissions and limitations under // the License. -const nock = require('nock') +const test = require('node:test') +const assert = require('node:assert/strict') +const { COUCH_URL, mockAgent, mockPool, JSON_HEADERS } = require('./mock.js') const Nano = require('..') -const COUCH_URL = 'http://localhost:5984' - -afterEach(() => { - nock.cleanAll() -}) test('should be able to log output with user-defined function', async () => { // setup Nano with custom logger @@ -30,14 +27,14 @@ test('should be able to log output with user-defined function', async () => { // mocks const response = { _id: 'id', rev: '1-123', a: 1, b: 'two', c: true } - const scope = nock(COUCH_URL) - .get('/db/id') - .reply(200, response) + mockPool + .intercept({ path: '/db/id' }) + .reply(200, response, JSON_HEADERS) // test GET /db/id const db = nano.db.use('db') const p = await db.get('id') - expect(p).toStrictEqual(response) - expect(logs.length).toBe(2) - expect(scope.isDone()).toBe(true) + assert.deepEqual(p, response) + assert.equal(logs.length, 2) + mockAgent.assertNoPendingInterceptors() }) diff --git a/test/nano.request.test.js b/test/nano.request.test.js index eebf2b35..02954a60 100644 --- a/test/nano.request.test.js +++ b/test/nano.request.test.js @@ -10,21 +10,18 @@ // License for the specific language governing permissions and limitations under // the License. +const test = require('node:test') +const assert = require('node:assert/strict') +const { COUCH_URL, mockAgent, mockPool, JSON_HEADERS } = require('./mock.js') const Nano = require('..') -const COUCH_URL = 'http://localhost:59804' -const nano = Nano({ url: COUCH_URL, cookie: true }) -const nock = require('nock') - -afterEach(() => { - nock.cleanAll() -}) +const nano = Nano({ url: COUCH_URL }) test('check request can do GET requests - nano.request', async () => { // mocks const response = { ok: true } - const scope = nock(COUCH_URL) - .get('/db?a=1&b=2') - .reply(200, response) + mockPool + .intercept({ path: '/db?a=1&b=2' }) + .reply(200, response, JSON_HEADERS) // test GET /db?a=1&b=2 const req = { @@ -33,17 +30,21 @@ test('check request can do GET requests - nano.request', async () => { qs: { a: 1, b: 2 } } const p = await nano.request(req) - expect(p).toStrictEqual(response) - expect(scope.isDone()).toBe(true) + assert.deepEqual(p, response) + mockAgent.assertNoPendingInterceptors() }) test('check request can do POST requests - nano.request', async () => { // mocks const response = { ok: true } const doc = { _id: '_design/myddoc', a: true } - const scope = nock(COUCH_URL) - .post('/db', doc) - .reply(200, response) + mockPool + .intercept({ + method: 'post', + path: '/db', + body: JSON.stringify(doc) + }) + .reply(200, response, JSON_HEADERS) // test POST /db const req = { @@ -52,16 +53,21 @@ test('check request can do POST requests - nano.request', async () => { body: doc } const p = await nano.request(req) - expect(p).toStrictEqual(response) - expect(scope.isDone()).toBe(true) + assert.deepEqual(p, response) + mockAgent.assertNoPendingInterceptors() }) test('check request can do PUT requests - nano.request', async () => { // mocks const response = { ok: true } - const scope = nock(COUCH_URL) - .put('/db/1', { _id: '1', a: true }) - .reply(200, response) + const doc = { _id: '1', a: true } + mockPool + .intercept({ + method: 'put', + path: '/db/1', + body: JSON.stringify(doc) + }) + .reply(200, response, JSON_HEADERS) // test PUT /db const req = { @@ -71,17 +77,19 @@ test('check request can do PUT requests - nano.request', async () => { body: { _id: '1', a: true } } const p = await nano.request(req) - expect(p).toStrictEqual(response) - expect(scope.isDone()).toBe(true) + assert.deepEqual(p, response) + mockAgent.assertNoPendingInterceptors() }) test('check request can do DELETE requests - nano.request', async () => { // mocks const response = { ok: true } - const scope = nock(COUCH_URL) - .delete('/db/mydoc') - .query({ rev: '1-123' }) - .reply(200, response) + mockPool + .intercept({ + method: 'delete', + path: '/db/mydoc?rev=1-123' + }) + .reply(200, response, JSON_HEADERS) // test DELETE /db const req = { @@ -89,19 +97,25 @@ test('check request can do DELETE requests - nano.request', async () => { db: 'db', path: 'mydoc', qs: { rev: '1-123' } - } const p = await nano.request(req) - expect(p).toStrictEqual(response) - expect(scope.isDone()).toBe(true) + assert.deepEqual(p, response) + mockAgent.assertNoPendingInterceptors() }) test('check request can do HEAD requests - nano.request', async () => { // mocks const response = '' - const scope = nock(COUCH_URL) - .head('/db/mydoc') - .reply(200, '') + const headers = { + 'content-type': 'text/plain', + myheader: '2442' + } + mockPool + .intercept({ + method: 'head', + path: '/db/mydoc' + }) + .reply(200, response, { headers }) // test HEAD /db/mydoc const req = { @@ -110,66 +124,17 @@ test('check request can do HEAD requests - nano.request', async () => { path: 'mydoc' } const p = await nano.request(req) - expect(p).toStrictEqual(response) - expect(scope.isDone()).toBe(true) -}) - -test('check request can do GET requests with callback - nano.request', () => { - // mocks - const response = { ok: true } - const scope = nock(COUCH_URL) - .get('/db?a=1&b=2') - .reply(200, response) - - // test GET /db?a=1&b=2 - const req = { - method: 'get', - db: 'db', - qs: { a: 1, b: 2 } - } - return new Promise((resolve, reject) => { - nano.request(req, (err, data) => { - expect(err).toBe(null) - expect(data).toStrictEqual(response) - expect(scope.isDone()).toBe(true) - resolve() - }) - }) -}) - -test('check request can do failed GET requests with callback - nano.request', () => { - // mocks - const response = { - error: 'not_found', - reason: 'missing' - } - const scope = nock(COUCH_URL) - .get('/db/a') - .reply(404, response) - - // test GET /db/a - const req = { - method: 'get', - db: 'db', - path: 'a' - } - return new Promise((resolve, reject) => { - nano.request(req, (err, data) => { - expect(err).not.toBe(null) - expect(scope.isDone()).toBe(true) - resolve() - }) - }) + assert.deepEqual(p, headers) + mockAgent.assertNoPendingInterceptors() }) test('check request formats keys properly - nano.request', async () => { // mocks const response = { ok: true } const arr = ['a', 'b', 'c'] - const scope = nock(COUCH_URL) - .get('/db/_all_docs') - .query({ keys: JSON.stringify(arr) }) - .reply(200, response) + mockPool + .intercept({ path: '/db/_all_docs?keys=["a","b","c"]' }) + .reply(200, response, JSON_HEADERS) // test GET /db/_all_docs?keys=[] const req = { @@ -179,18 +144,17 @@ test('check request formats keys properly - nano.request', async () => { qs: { keys: arr } } const p = await nano.request(req) - expect(p).toStrictEqual(response) - expect(scope.isDone()).toBe(true) + assert.deepEqual(p, response) + mockAgent.assertNoPendingInterceptors() }) test('check request formats startkey properly - nano.request', async () => { // mocks const response = { ok: true } const val = 'x' - const scope = nock(COUCH_URL) - .get('/db/_all_docs') - .query({ startkey: JSON.stringify(val) }) - .reply(200, response) + mockPool + .intercept({ path: '/db/_all_docs?startkey="x"' }) + .reply(200, response, JSON_HEADERS) // test GET /db/_all_docs?startkey= const req = { @@ -200,18 +164,17 @@ test('check request formats startkey properly - nano.request', async () => { qs: { startkey: val } } const p = await nano.request(req) - expect(p).toStrictEqual(response) - expect(scope.isDone()).toBe(true) + assert.deepEqual(p, response) + mockAgent.assertNoPendingInterceptors() }) test('check request formats start_key properly - nano.request', async () => { // mocks const response = { ok: true } const val = 'x' - const scope = nock(COUCH_URL) - .get('/db/_all_docs') - .query({ start_key: JSON.stringify(val) }) - .reply(200, response) + mockPool + .intercept({ path: '/db/_all_docs?start_key="x"' }) + .reply(200, response, JSON_HEADERS) // test GET /db/_all_docs?start_key= const req = { @@ -221,18 +184,17 @@ test('check request formats start_key properly - nano.request', async () => { qs: { start_key: val } } const p = await nano.request(req) - expect(p).toStrictEqual(response) - expect(scope.isDone()).toBe(true) + assert.deepEqual(p, response) + mockAgent.assertNoPendingInterceptors() }) test('check request formats endkey properly - nano.request', async () => { // mocks const response = { ok: true } const val = 'x' - const scope = nock(COUCH_URL) - .get('/db/_all_docs') - .query({ endkey: JSON.stringify(val) }) - .reply(200, response) + mockPool + .intercept({ path: '/db/_all_docs?endkey="x"' }) + .reply(200, response, JSON_HEADERS) // test GET /db/_all_docs?endkey= const req = { @@ -242,18 +204,17 @@ test('check request formats endkey properly - nano.request', async () => { qs: { endkey: val } } const p = await nano.request(req) - expect(p).toStrictEqual(response) - expect(scope.isDone()).toBe(true) + assert.deepEqual(p, response) + mockAgent.assertNoPendingInterceptors() }) test('check request formats end_key properly - nano.request', async () => { // mocks const response = { ok: true } const val = 'x' - const scope = nock(COUCH_URL) - .get('/db/_all_docs') - .query({ end_key: JSON.stringify(val) }) - .reply(200, response) + mockPool + .intercept({ path: '/db/_all_docs?end_key="x"' }) + .reply(200, response, JSON_HEADERS) // test GET /db/_all_docs?end_key= const req = { @@ -263,18 +224,17 @@ test('check request formats end_key properly - nano.request', async () => { qs: { end_key: val } } const p = await nano.request(req) - expect(p).toStrictEqual(response) - expect(scope.isDone()).toBe(true) + assert.deepEqual(p, response) + mockAgent.assertNoPendingInterceptors() }) test('check request formats key properly - nano.request', async () => { // mocks const response = { ok: true } const val = 'x' - const scope = nock(COUCH_URL) - .get('/db/_all_docs') - .query({ key: JSON.stringify(val) }) - .reply(200, response) + mockPool + .intercept({ path: '/db/_all_docs?key="x"' }) + .reply(200, response, JSON_HEADERS) // test GET /db/_all_docs?key= const req = { @@ -284,32 +244,15 @@ test('check request formats key properly - nano.request', async () => { qs: { key: val } } const p = await nano.request(req) - expect(p).toStrictEqual(response) - expect(scope.isDone()).toBe(true) + assert.deepEqual(p, response) + mockAgent.assertNoPendingInterceptors() }) test('check request can do 500s - nano.request', async () => { // mocks const errorMessage = 'Internal server error' - const scope = nock(COUCH_URL) - .get('/db?a=1&b=2') - .reply(500, errorMessage) - - // test GET /db?a=1&b=2 - const req = { - method: 'get', - db: 'db', - qs: { a: 1, b: 2 } - } - await expect(nano.request(req)).rejects.toThrow(errorMessage) - expect(scope.isDone()).toBe(true) -}) - -test('check request can do 500s with callback - nano.request', () => { - // mocks - const errorMessage = 'Internal server error' - const scope = nock(COUCH_URL) - .get('/db?a=1&b=2') + mockPool + .intercept({ path: '/db?a=1&b=2' }) .reply(500, errorMessage) // test GET /db?a=1&b=2 @@ -318,14 +261,8 @@ test('check request can do 500s with callback - nano.request', () => { db: 'db', qs: { a: 1, b: 2 } } - - return new Promise((resolve, reject) => { - nano.request(req, (err, data) => { - expect(err).not.toBe(null) - expect(scope.isDone()).toBe(true) - resolve() - }) - }) + await assert.rejects(nano.request(req), { message: 'couch returned 500' }) + mockAgent.assertNoPendingInterceptors() }) test('check request handle empty parameter list - nano.request', async () => { @@ -343,44 +280,14 @@ test('check request handle empty parameter list - nano.request', async () => { name: 'The Apache Software Foundation' } } - const scope = nock(COUCH_URL) - .get('/') - .reply(200, response) + mockPool + .intercept({ path: '/' }) + .reply(200, response, JSON_HEADERS) // test GET / const p = await nano.request() - expect(p).toStrictEqual(response) - expect(scope.isDone()).toBe(true) -}) - -test('check request handle empty parameter list (callback) - nano.request', () => { - // mocks - const response = { - couchdb: 'Welcome', - version: '2.3.1', - git_sha: 'c298091a4', - uuid: '865f5b0c258c5749012ce7807b4b0622', - features: [ - 'pluggable-storage-engines', - 'scheduler' - ], - vendor: { - name: 'The Apache Software Foundation' - } - } - const scope = nock(COUCH_URL) - .get('/') - .reply(200, response) - - // test GET / - return new Promise((resolve, reject) => { - nano.request((err, data) => { - expect(err).toBeNull() - expect(data).toStrictEqual(response) - expect(scope.isDone()).toBe(true) - resolve() - }) - }) + assert.deepEqual(p, response) + mockAgent.assertNoPendingInterceptors() }) test('check request handles single string parameter - nano.request', async () => { @@ -395,14 +302,14 @@ test('check request handles single string parameter - nano.request', async () => active: 6727596 } } - const scope = nock(COUCH_URL) - .get('/db') - .reply(200, response) + mockPool + .intercept({ path: '/db' }) + .reply(200, response, JSON_HEADERS) // test GET / const p = await nano.request('db') - expect(p).toStrictEqual(response) - expect(scope.isDone()).toBe(true) + assert.deepEqual(p, response) + mockAgent.assertNoPendingInterceptors() }) test('check request handles cookies - nano.request', async () => { @@ -410,9 +317,21 @@ test('check request handles cookies - nano.request', async () => { const username = 'u' const password = 'p' const response = { ok: true, name: 'admin', roles: ['_admin', 'admin'] } - const scope = nock(COUCH_URL) - .post('/_session', 'name=u&password=p', { 'content-type': 'application/x-www-form-urlencoded; charset=utf-8' }) - .reply(200, response, { 'Set-Cookie': 'AuthSession=YWRtaW46NUU0MTFBMDE6stHsxYnlDy4mYxwZEcnXHn4fm5w; Version=1; Expires=Mon, 10-Feb-2050 09:03:21 GMT; Max-Age=600; Path=/; HttpOnly' }) + mockPool + .intercept({ + method: 'post', + path: '/_session', + body: 'name=u&password=p', + headers: { + 'content-type': 'application/x-www-form-urlencoded; charset=utf-8' + } + }) + .reply(200, response, { + headers: { + 'content-type': 'application/json', + 'Set-Cookie': 'AuthSession=YWRtaW46NUU0MTFBMDE6stHsxYnlDy4mYxwZEcnXHn4fm5w; Version=1; Expires=Mon, 10-Feb-2050 09:03:21 GMT; Max-Age=600; Path=/; HttpOnly' + } + }) // test GET /_uuids const req = { @@ -421,20 +340,19 @@ test('check request handles cookies - nano.request', async () => { form: { name: username, password - }, - jar: true + } } const p = await nano.request(req) - expect(p).toStrictEqual(response) - expect(scope.isDone()).toBe(true) + assert.deepEqual(p, response) + mockAgent.assertNoPendingInterceptors() }) test('check request can do GET a doc - nano.request', async () => { // mocks const response = { _id: 'docname/design', _rev: '1-123', ok: true } - const scope = nock(COUCH_URL) - .get('/db/_design/docname?a=1&b=2') - .reply(200, response) + mockPool + .intercept({ path: '/db/_design/docname?a=1&b=2' }) + .reply(200, response, JSON_HEADERS) // test GET /db?a=1&b=2 const req = { @@ -444,8 +362,8 @@ test('check request can do GET a doc - nano.request', async () => { qs: { a: 1, b: 2 } } const p = await nano.request(req) - expect(p).toStrictEqual(response) - expect(scope.isDone()).toBe(true) + assert.deepEqual(p, response) + mockAgent.assertNoPendingInterceptors() }) test('check request doesn\'t mangle bodies containing functions - nano.request', async () => { @@ -455,14 +373,18 @@ test('check request doesn\'t mangle bodies containing functions - nano.request', a: 1, views: { bytime: { - map: function () { emit(doc.ts, true) } + map: function () { emit(doc.ts, true) }.toString() } } } const response = { id: 'jfjfjf', rev: '1-123', ok: true } - const scope = nock(COUCH_URL) - .post('/db', { a: 1, views: { bytime: { map: 'function () {\n emit(doc.ts, true);\n }' } } }) - .reply(200, response) + mockPool + .intercept({ + method: 'post', + path: '/db', + body: JSON.stringify(doc) + }) + .reply(200, response, JSON_HEADERS) // test POST /db const req = { @@ -471,16 +393,21 @@ test('check request doesn\'t mangle bodies containing functions - nano.request', body: doc } const p = await nano.request(req) - expect(p).toStrictEqual(response) - expect(scope.isDone()).toBe(true) + assert.deepEqual(p, response) + mockAgent.assertNoPendingInterceptors() }) test('check request sends user-agent header - nano.request', async () => { // mocks const response = { ok: true } - const scope = nock(COUCH_URL, { reqheaders: { 'user-agent': /^nano/ } }) - .get('/db?a=1&b=2') - .reply(200, response) + mockPool + .intercept({ + path: '/db?a=1&b=2', + headers: { + 'user-agent': /^nano/ + } + }) + .reply(200, response, JSON_HEADERS) // test GET /db?a=1&b=2 const req = { @@ -489,16 +416,21 @@ test('check request sends user-agent header - nano.request', async () => { qs: { a: 1, b: 2 } } const p = await nano.request(req) - expect(p).toStrictEqual(response) - expect(scope.isDone()).toBe(true) + assert.deepEqual(p, response) + mockAgent.assertNoPendingInterceptors() }) test('check request sends headers for gzipped responses - nano.request', async () => { // mocks const response = { ok: true } - const scope = nock(COUCH_URL, { reqheaders: { 'accept-encoding': /gzip/ } }) - .get('/db?a=1&b=2') - .reply(200, response) + mockPool + .intercept({ + path: '/db?a=1&b=2', + headers: { + 'accept-encoding': /gzip/ + } + }) + .reply(200, response, JSON_HEADERS) // test GET /db?a=1&b=2 const req = { @@ -507,6 +439,6 @@ test('check request sends headers for gzipped responses - nano.request', async ( qs: { a: 1, b: 2 } } const p = await nano.request(req) - expect(p).toStrictEqual(response) - expect(scope.isDone()).toBe(true) + assert.deepEqual(p, response) + mockAgent.assertNoPendingInterceptors() }) diff --git a/test/nano.session.test.js b/test/nano.session.test.js index 7c3d1ee2..71908343 100644 --- a/test/nano.session.test.js +++ b/test/nano.session.test.js @@ -10,24 +10,21 @@ // License for the specific language governing permissions and limitations under // the License. +const test = require('node:test') +const assert = require('node:assert/strict') +const { COUCH_URL, mockAgent, mockPool, JSON_HEADERS } = require('./mock.js') const Nano = require('..') -const COUCH_URL = 'http://localhost:5984' const nano = Nano(COUCH_URL) -const nock = require('nock') - -afterEach(() => { - nock.cleanAll() -}) test('should be able to check your session - GET /_session - nano.auth', async () => { // mocks const response = { ok: true, userCtx: { name: null, roles: [] }, info: { authentication_db: '_users', authentication_handlers: ['cookie', 'default'] } } - const scope = nock(COUCH_URL) - .get('/_session') - .reply(200, response) + mockPool + .intercept({ path: '/_session' }) + .reply(200, response, JSON_HEADERS) // test GET /_session const p = await nano.session() - expect(p).toStrictEqual(response) - expect(scope.isDone()).toBe(true) + assert.deepEqual(p, response) + mockAgent.assertNoPendingInterceptors() }) diff --git a/test/nano.timeout.test.js b/test/nano.timeout.test.js deleted file mode 100644 index 8c5eaebf..00000000 --- a/test/nano.timeout.test.js +++ /dev/null @@ -1,64 +0,0 @@ -// Licensed under the Apache License, Version 2.0 (the 'License'); you may not -// use this file except in compliance with the License. You may obtain a copy of -// the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an 'AS IS' BASIS, WITHOUT -// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -// License for the specific language governing permissions and limitations under -// the License. - -const Nano = require('..') -const COUCH_URL = 'http://localhost:59804' -const nano = Nano({ - url: COUCH_URL, - requestDefaults: { - timeout: 500 - } -}) -const nock = require('nock') - -afterEach(() => { - nock.cleanAll() -}) - -test('check requests timeout - nano.request', async () => { - // mocks - const response = { ok: true } - nock(COUCH_URL) - .get('/db?a=1&b=2') - .delay(1000) - .reply(200, response) - - // test GET /db?a=1&b=2 - const req = { - method: 'get', - db: 'db', - qs: { a: 1, b: 2 } - } - await expect(nano.request(req)).rejects.toThrow('error happened in your connection. Reason: timeout of 500ms exceeded') -}) - -test('check request timeout (callback) - nano.request', () => { - // mocks - const response = { ok: true } - nock(COUCH_URL) - .get('/db?a=1&b=2') - .delay(1000) - .reply(200, response) - - // test GET /db?a=1&b=2 - const req = { - method: 'get', - db: 'db', - qs: { a: 1, b: 2 } - } - return new Promise((resolve, reject) => { - nano.request(req, (err, data) => { - expect(err).not.toBeNull() - resolve() - }) - }) -}) diff --git a/test/nano.updates.test.js b/test/nano.updates.test.js index eca355b9..7058fa48 100644 --- a/test/nano.updates.test.js +++ b/test/nano.updates.test.js @@ -10,10 +10,12 @@ // License for the specific language governing permissions and limitations under // the License. +const test = require('node:test') +const assert = require('node:assert/strict') +const { COUCH_URL, mockAgent, mockPool, JSON_HEADERS } = require('./mock.js') const Nano = require('..') -const COUCH_URL = 'http://localhost:5984' const nano = Nano(COUCH_URL) -const nock = require('nock') + const response = { results: [ { @@ -39,41 +41,37 @@ const errResponse = { reason: 'Database does not exist.' } -afterEach(() => { - nock.cleanAll() -}) - test('should be able to fetch db updates - GET /_db_updates - nano.updates', async () => { // mocks - const scope = nock(COUCH_URL) - .get('/_db_updates') - .reply(200, response) + mockPool + .intercept({ path: '/_db_updates' }) + .reply(200, response, JSON_HEADERS) // test GET /_db_updates const p = await nano.updates() - expect(p).toStrictEqual(response) - expect(scope.isDone()).toBe(true) + assert.deepEqual(p, response) + mockAgent.assertNoPendingInterceptors() }) test('should be able to fetch db updates with options - GET /_db_updates - nano.updates', async () => { // mocks - const scope = nock(COUCH_URL) - .get('/_db_updates?timeout=10000') - .reply(200, response) + mockPool + .intercept({ path: '/_db_updates?timeout=10000' }) + .reply(200, response, JSON_HEADERS) // test GET /_db_updates const p = await nano.updates({ timeout: 10000 }) - expect(p).toStrictEqual(response) - expect(scope.isDone()).toBe(true) + assert.deepEqual(p, response) + mockAgent.assertNoPendingInterceptors() }) test('should handle 404 - GET /_db_updates - nano.updates', async () => { // mocks - const scope = nock(COUCH_URL) - .get('/_db_updates') - .reply(404, errResponse) + mockPool + .intercept({ path: '/_db_updates' }) + .reply(404, errResponse, JSON_HEADERS) // test GET /_db_updates - await expect(nano.db.updates()).rejects.toThrow('Database does not exist.') - expect(scope.isDone()).toBe(true) + await assert.rejects(nano.db.updates(), { message: 'Database does not exist.' }) + mockAgent.assertNoPendingInterceptors() }) diff --git a/test/nano.use.test.js b/test/nano.use.test.js index ba730447..d867bbd7 100644 --- a/test/nano.use.test.js +++ b/test/nano.use.test.js @@ -10,22 +10,23 @@ // License for the specific language governing permissions and limitations under // the License. +const test = require('node:test') +const assert = require('node:assert/strict') const Nano = require('..') -const COUCH_URL = 'http://localhost:5984' -const nano = Nano(COUCH_URL) +const nano = Nano('http://myurl.com') test('should be able to use a database - nano.db.use', () => { const db = nano.db.use('db1') - expect(typeof db).toBe('object') - expect(typeof db.get).toBe('function') - expect(typeof db.replication).toBe('object') - expect(db.config.db).toBe('db1') + assert.equal(typeof db, 'object') + assert.equal(typeof db.get, 'function') + assert.equal(typeof db.replication, 'object') + assert.equal(db.config.db, 'db1') }) test('should be able to use a database - nano.use', () => { const db = nano.use('db2') - expect(typeof db).toBe('object') - expect(typeof db.get).toBe('function') - expect(typeof db.replication).toBe('object') - expect(db.config.db).toBe('db2') + assert.equal(typeof db, 'object') + assert.equal(typeof db.get, 'function') + assert.equal(typeof db.replication, 'object') + assert.equal(db.config.db, 'db2') }) diff --git a/test/nano.uuids.test.js b/test/nano.uuids.test.js index f2ad76e2..26ffb2df 100644 --- a/test/nano.uuids.test.js +++ b/test/nano.uuids.test.js @@ -10,14 +10,11 @@ // License for the specific language governing permissions and limitations under // the License. +const test = require('node:test') +const assert = require('node:assert/strict') +const { COUCH_URL, mockAgent, mockPool, JSON_HEADERS } = require('./mock.js') const Nano = require('..') -const COUCH_URL = 'http://localhost:5984' const nano = Nano(COUCH_URL) -const nock = require('nock') - -afterEach(() => { - nock.cleanAll() -}) test('should be able to fetch uuids - GET /_uuids - nano.uuids', async () => { // mocks @@ -26,14 +23,14 @@ test('should be able to fetch uuids - GET /_uuids - nano.uuids', async () => { 'c42ddf1272c7d05b2dc45b696200145f' ] } - const scope = nock(COUCH_URL) - .get('/_uuids?count=1') - .reply(200, response) + mockPool + .intercept({ path: '/_uuids?count=1' }) + .reply(200, response, JSON_HEADERS) // test GET /_uuids const p = await nano.uuids() - expect(p).toStrictEqual(response) - expect(scope.isDone()).toBe(true) + assert.deepEqual(p, response) + mockAgent.assertNoPendingInterceptors() }) test('should be able to fetch more uuids - GET /_uuids?count=3 - nano.uuids', async () => { @@ -45,34 +42,12 @@ test('should be able to fetch more uuids - GET /_uuids?count=3 - nano.uuids', as 'c42ddf1272c7d05b2dc45b69620028cf' ] } - const scope = nock(COUCH_URL) - .get('/_uuids?count=3') - .reply(200, response) + mockPool + .intercept({ path: '/_uuids?count=3' }) + .reply(200, response, JSON_HEADERS) // test GET /_uuids const p = await nano.uuids(3) - expect(p).toStrictEqual(response) - expect(scope.isDone()).toBe(true) -}) - -test('should be able to fetch uuids callback - GET /_uuids - nano.uuids', () => { - // mocks - const response = { - uuids: [ - 'c42ddf1272c7d05b2dc45b696200145f' - ] - } - const scope = nock(COUCH_URL) - .get('/_uuids?count=1') - .reply(200, response) - - // test GET /_uuids - return new Promise((resolve, reject) => { - nano.uuids((err, data) => { - expect(err).toBe(null) - expect(data).toStrictEqual(response) - expect(scope.isDone()).toBe(true) - resolve() - }) - }) + assert.deepEqual(p, response) + mockAgent.assertNoPendingInterceptors() }) diff --git a/test/notnocked.test.js b/test/notnocked.test.js index 3bf64e65..f017d2f5 100644 --- a/test/notnocked.test.js +++ b/test/notnocked.test.js @@ -10,8 +10,10 @@ // License for the specific language governing permissions and limitations under // the License. +const test = require('node:test') +const assert = require('node:assert/strict') const Nano = require('..') -const COUCH_URL = 'http://admin:admin@localhost:5984' +const COUCH_URL = 'http://admin:admin@127.0.0.1:5984' const nano = Nano(COUCH_URL) const dbName = 'notnocked' + new Date().getTime() let db @@ -20,7 +22,7 @@ const emit = (k, v) => { } test('should be able to create a database string', () => { - expect(typeof dbName).toBe('string') + assert(typeof dbName, 'string') }) // this section only runs if the TRAVIS environment variable is set. @@ -48,15 +50,15 @@ if (process.env.TRAVIS) { test('should be able to get database info - nano.db.bulk', async () => { const info = await db.info(dbName) - expect(info.doc_count).toBe(7) + assert.equal(info.doc_count, 7) }) test('should be able to delete a document', async () => { const doc = await db.get('dummy') await db.destroy('dummy', doc._rev) const info = await db.info(dbName) - expect(info.doc_count).toBe(6) - expect(info.doc_del_count).toBe(1) + assert.equal(info.doc_count, 6) + assert.equal(info.doc_del_count, 1) }) test('should be able to update a document', async () => { @@ -64,13 +66,13 @@ if (process.env.TRAVIS) { doc.newfield = true await db.insert(doc) const info = await db.info(dbName) - expect(info.doc_count).toBe(6) + assert.equal(info.doc_count, 6) }) test('should be able to list documents in a database', async () => { const data = await db.list({ limit: 1, descending: true }) - expect(data.rows.length).toBe(1) - expect(data.rows[0].id).toBe('snowbell') + assert.equal(data.rows.length, 1) + assert.equal(data.rows[0].id, 'snowbell') }) test('should be able to create a view', async () => { @@ -102,7 +104,7 @@ if (process.env.TRAVIS) { { id: 'crookshanks', key: 2004, value: 'Crookshanks' } ] } - expect(response).toStrictEqual(data) + assert.deepEqual(response, data) }) test('should be able to destroy a database - nano.db.destroy', async () => { diff --git a/test/partition.find.test.js b/test/partition.find.test.js index 806f9479..86043078 100644 --- a/test/partition.find.test.js +++ b/test/partition.find.test.js @@ -10,14 +10,11 @@ // License for the specific language governing permissions and limitations under // the License. +const test = require('node:test') +const assert = require('node:assert/strict') +const { COUCH_URL, mockAgent, mockPool, JSON_HEADERS } = require('./mock.js') const Nano = require('..') -const COUCH_URL = 'http://localhost:5984' const nano = Nano(COUCH_URL) -const nock = require('nock') - -afterEach(() => { - nock.cleanAll() -}) test('should be able to query a partitioned index - POST /db/_partition/partition/_find - db.partitionedFind', async () => { // mocks @@ -38,15 +35,19 @@ test('should be able to query a partitioned index - POST /db/_partition/partitio { name: 'Susan', date: '2019-01-03', orderid: '8523' } ] } - const scope = nock(COUCH_URL) - .post('/db/_partition/partition/_find', query) - .reply(200, response) + mockPool + .intercept({ + method: 'post', + path: '/db/_partition/partition/_find', + body: JSON.stringify(query) + }) + .reply(200, response, JSON_HEADERS) // test POST /db/_partition/partition/_find const db = nano.db.use('db') const p = await db.partitionedFind('partition', query) - expect(p).toStrictEqual(response) - expect(scope.isDone()).toBe(true) + assert.deepEqual(p, response) + mockAgent.assertNoPendingInterceptors() }) test('should handle 404 - POST /db/_partition/partition/_find - db.partitionedFind', async () => { @@ -60,28 +61,23 @@ test('should handle 404 - POST /db/_partition/partition/_find - db.partitionedFi error: 'not_found', reason: 'missing' } - const scope = nock(COUCH_URL) - .post('/db/_partition/partition/_find', query) - .reply(404, response) + mockPool + .intercept({ + method: 'post', + path: '/db/_partition/partition/_find', + body: JSON.stringify(query) + }) + .reply(404, response, JSON_HEADERS) // test POST /db/_partition/partition/_find const db = nano.db.use('db') - await expect(db.partitionedFind('partition', query)).rejects.toThrow('missing') - expect(scope.isDone()).toBe(true) + await assert.rejects(db.partitionedFind('partition', query), { message: 'missing' }) + mockAgent.assertNoPendingInterceptors() }) test('should detect missing query - db.partitionedFind', async () => { const db = nano.db.use('db') - await expect(db.partitionedFind()).rejects.toThrow('Invalid parameters') - await expect(db.partitionedFind('partition', 'susan')).rejects.toThrow('Invalid parameters') + await assert.rejects(db.partitionedFind(), { message: 'Invalid parameters' }) + await assert.rejects(db.partitionedFind('partition', 'susan'), { message: 'Invalid parameters' }) }) -test('should detect missing query (callback) - db.partitionedFind', async () => { - const db = nano.db.use('db') - return new Promise((resolve, reject) => { - db.partitionedFind(undefined, '', (err, data) => { - expect(err).not.toBeNull() - resolve() - }) - }) -}) diff --git a/test/partition.findAsStream.test.js b/test/partition.findAsStream.test.js index 9e53c908..4df17487 100644 --- a/test/partition.findAsStream.test.js +++ b/test/partition.findAsStream.test.js @@ -10,14 +10,11 @@ // License for the specific language governing permissions and limitations under // the License. +const test = require('node:test') +const assert = require('node:assert/strict') +const { COUCH_URL, mockAgent, mockPool, JSON_HEADERS } = require('./mock.js') const Nano = require('..') -const COUCH_URL = 'http://localhost:5984' const nano = Nano(COUCH_URL) -const nock = require('nock') - -afterEach(() => { - nock.cleanAll() -}) test('should get a queried streamed list of documents from a partition- POST /db/_partition/partition/_find - db.partitionedFindAsStream', async () => { // mocks @@ -38,22 +35,26 @@ test('should get a queried streamed list of documents from a partition- POST /db { name: 'Susan', date: '2019-01-03', orderid: '8523' } ] } - const scope = nock(COUCH_URL) - .post('/db/_partition/partition/_find') - .reply(200, response) + mockPool + .intercept({ + method: 'post', + path: '/db/_partition/partition/_find', + body: JSON.stringify(query) + }) + .reply(200, response, JSON_HEADERS) - return new Promise((resolve, reject) => { + await new Promise((resolve, reject) => { // test /db/_partition/partition/_find const db = nano.db.use('db') const s = db.partitionedFindAsStream('partition', query) - expect(typeof s).toBe('object') + assert.equal(typeof s, 'object') let buffer = '' s.on('data', (chunk) => { buffer += chunk.toString() }) s.on('end', () => { - expect(buffer).toBe(JSON.stringify(response)) - expect(scope.isDone()).toBe(true) + assert.equal(buffer, JSON.stringify(response)) + mockAgent.assertNoPendingInterceptors() resolve() }) }) diff --git a/test/partition.info.test.js b/test/partition.info.test.js index 2d9e8f5c..5724aae9 100644 --- a/test/partition.info.test.js +++ b/test/partition.info.test.js @@ -10,11 +10,13 @@ // License for the specific language governing permissions and limitations under // the License. +const test = require('node:test') +const assert = require('node:assert/strict') +const { COUCH_URL, mockAgent, mockPool, JSON_HEADERS } = require('./mock.js') const Nano = require('..') -const COUCH_URL = 'http://localhost:5984' const nano = Nano(COUCH_URL) const db = nano.db.use('db') -const nock = require('nock') + const response = { db_name: 'db', sizes: { @@ -26,63 +28,35 @@ const response = { doc_del_count: 0 } -afterEach(() => { - nock.cleanAll() -}) - test('should be able to fetch partition info info - GET /db/_partition/partition - db.partitionInfo', async () => { // mocks - const scope = nock(COUCH_URL) - .get('/db/_partition/partition') - .reply(200, response) + mockPool + .intercept({ path: '/db/_partition/partition' }) + .reply(200, response, JSON_HEADERS) // test GET /db/_partition/partition const p = await db.partitionInfo('partition') - expect(p).toStrictEqual(response) - expect(scope.isDone()).toBe(true) -}) - -test('should be able to fetch partition info info (callback) - GET /db/_partition/partition - db.partitionInfo', async () => { - // mocks - const scope = nock(COUCH_URL) - .get('/db/_partition/partition') - .reply(200, response) - - // test GET /db/_partition/partition - return new Promise((resolve, reject) => { - db.partitionInfo('partition', (err, data) => { - expect(err).toBeNull() - expect(data).toStrictEqual(response) - expect(scope.isDone()).toBe(true) - resolve() - }) - }) + assert.deepEqual(p, response) + mockAgent.assertNoPendingInterceptors() }) test('should handle missing database - PUT /db - nano.db.create', async () => { // mocks - const scope = nock(COUCH_URL) - .get('/db/_partition/partition') - .reply(404, { - error: 'not_found', - reason: 'Database does not exist.' - }) + const response = { + error: 'not_found', + reason: 'Database does not exist.' + } + mockPool + .intercept({ path: '/db/_partition/partition' }) + .reply(404, response, JSON_HEADERS) // test GET /db/_partition/partition - await expect(db.partitionInfo('partition')).rejects.toThrow('Database does not exist') - expect(scope.isDone()).toBe(true) + await assert.rejects(db.partitionInfo('partition'), { message: response.reason }) + mockAgent.assertNoPendingInterceptors() }) test('should not attempt info fetch with missing parameters - nano.db.get', async () => { - await expect(db.partitionInfo()).rejects.toThrowError('Invalid parameters') - await expect(db.partitionInfo('')).rejects.toThrowError('Invalid parameters') + await assert.rejects(db.partitionInfo(), { message: 'Invalid parameters' }) + await assert.rejects(db.partitionInfo(''), { message: 'Invalid parameters' }) }) -test('should detect missing parameters (callback) - nano.db.get', async () => { - return new Promise((resolve, reject) => { - db.partitionInfo(undefined, (err, data) => { - expect(err).not.toBeNull() - resolve() - }) - }) -}) diff --git a/test/partition.list.test.js b/test/partition.list.test.js index 6e970715..4bb52d33 100644 --- a/test/partition.list.test.js +++ b/test/partition.list.test.js @@ -10,11 +10,13 @@ // License for the specific language governing permissions and limitations under // the License. +const test = require('node:test') +const assert = require('node:assert/strict') +const { COUCH_URL, mockAgent, mockPool, JSON_HEADERS } = require('./mock.js') const Nano = require('..') -const COUCH_URL = 'http://localhost:5984' const nano = Nano(COUCH_URL) const db = nano.db.use('db') -const nock = require('nock') + const response = { total_rows: 1215, offset: 0, @@ -57,20 +59,16 @@ const response = { ] } -afterEach(() => { - nock.cleanAll() -}) - test('should be list documents form a partition - GET /db/_partition/_all_docs - db.partitionedList', async () => { // mocks - const scope = nock(COUCH_URL) - .get('/db/_partition/partition/_all_docs') - .reply(200, response) + mockPool + .intercept({ path: '/db/_partition/partition/_all_docs' }) + .reply(200, response, JSON_HEADERS) // test GET /db/_partition/_all_docs const p = await db.partitionedList('partition') - expect(p).toStrictEqual(response) - expect(scope.isDone()).toBe(true) + assert.deepEqual(p, response) + mockAgent.assertNoPendingInterceptors() }) test('should be list documents form a partition with opts - GET /db/_partition/_all_docs - db.partitionedList', async () => { @@ -94,74 +92,45 @@ test('should be list documents form a partition with opts - GET /db/_partition/_ } ] } - const scope = nock(COUCH_URL) - .get('/db/_partition/partition/_all_docs?limit=1&include_docs=true') - .reply(200, optsResponse) + mockPool + .intercept({ path: '/db/_partition/partition/_all_docs?limit=1&include_docs=true' }) + .reply(200, optsResponse, JSON_HEADERS) // test GET /db/_partition/_all_docs const p = await db.partitionedList('partition', { limit: 1, include_docs: true }) - expect(p).toStrictEqual(optsResponse) - expect(scope.isDone()).toBe(true) -}) - -test('should be able to list partition docs (callback) - GET /db/_partition/_all_docs - db.partitionedList', async () => { - // mocks - const scope = nock(COUCH_URL) - .get('/db/_partition/partition/_all_docs') - .reply(200, response) - - // test GET /db/_partition/_all_docs - return new Promise((resolve, reject) => { - db.partitionedList('partition', (err, data) => { - expect(err).toBeNull() - expect(data).toStrictEqual(response) - expect(scope.isDone()).toBe(true) - resolve() - }) - }) + assert.deepEqual(p, optsResponse) + mockAgent.assertNoPendingInterceptors() }) test('should escape unusual characters - GET /db/_partition/a+b/_all_docs - db.partitionedList', async () => { // mocks - const scope = nock(COUCH_URL) - .get('/db/_partition/a%2Bb/_all_docs') - .reply(200, response) + mockPool + .intercept({ path: '/db/_partition/a%2Bb/_all_docs' }) + .reply(200, response, JSON_HEADERS) // test GET /db/_partition/_all_docs - return new Promise((resolve, reject) => { - db.partitionedList('a+b', (err, data) => { - expect(err).toBeNull() - expect(data).toStrictEqual(response) - expect(scope.isDone()).toBe(true) - resolve() - }) - }) + const p = await db.partitionedList('a+b') + assert.deepEqual(p, response) + mockAgent.assertNoPendingInterceptors() }) test('should handle missing database - GET /db/_partition/_all_docs - db.partitionedList', async () => { // mocks - const scope = nock(COUCH_URL) - .get('/db/_partition/partition/_all_docs') - .reply(404, { - error: 'not_found', - reason: 'Database does not exist.' - }) + const errResponse = { + error: 'not_found', + reason: 'Database does not exist.' + } + mockPool + .intercept({ path: '/db/_partition/partition/_all_docs' }) + .reply(404, errResponse, JSON_HEADERS) // test GET /db/_partition/_all_docs - await expect(db.partitionedList('partition')).rejects.toThrow('Database does not exist') - expect(scope.isDone()).toBe(true) + await assert.rejects(db.partitionedList('partition'), { message: errResponse.reason }) + mockAgent.assertNoPendingInterceptors() }) test('should not attempt info fetch with missing parameters - db.partitionedList', async () => { - await expect(db.partitionedList()).rejects.toThrowError('Invalid parameters') - await expect(db.partitionedList('')).rejects.toThrowError('Invalid parameters') + await assert.rejects(db.partitionedList(), { message: 'Invalid parameters' }) + await assert.rejects(db.partitionedList(''), { message: 'Invalid parameters' }) }) -test('should detect missing parameters (callback) - db.partitionedList', async () => { - return new Promise((resolve, reject) => { - db.partitionedList(undefined, (err, data) => { - expect(err).not.toBeNull() - resolve() - }) - }) -}) diff --git a/test/partition.listAsStream.test.js b/test/partition.listAsStream.test.js index b45c5be5..9313fa18 100644 --- a/test/partition.listAsStream.test.js +++ b/test/partition.listAsStream.test.js @@ -10,14 +10,11 @@ // License for the specific language governing permissions and limitations under // the License. +const test = require('node:test') +const assert = require('node:assert/strict') +const { COUCH_URL, mockAgent, mockPool, JSON_HEADERS } = require('./mock.js') const Nano = require('..') -const COUCH_URL = 'http://localhost:5984' const nano = Nano(COUCH_URL) -const nock = require('nock') - -afterEach(() => { - nock.cleanAll() -}) test('should get a streamed list of documents from a partition- GET /db/_partition/partition/_all_docs - db.partitionedListAsStream', async () => { // mocks @@ -48,22 +45,22 @@ test('should get a streamed list of documents from a partition- GET /db/_partiti } ] } - const scope = nock(COUCH_URL) - .get('/db/_partition/partition/_all_docs') - .reply(200, response) + mockPool + .intercept({ path: '/db/_partition/partition/_all_docs' }) + .reply(200, response, JSON_HEADERS) - return new Promise((resolve, reject) => { + await new Promise((resolve, reject) => { // test GET /db/_partition/_all_docs const db = nano.db.use('db') const s = db.partitionedListAsStream('partition') - expect(typeof s).toBe('object') + assert(typeof s, 'object') let buffer = '' s.on('data', (chunk) => { buffer += chunk.toString() }) s.on('end', () => { - expect(buffer).toBe(JSON.stringify(response)) - expect(scope.isDone()).toBe(true) + assert.equal(buffer, JSON.stringify(response)) + mockAgent.assertNoPendingInterceptors() resolve() }) }) @@ -90,22 +87,22 @@ test('should get a streamed list of documents from a partition with opts- GET /d } ] } - const scope = nock(COUCH_URL) - .get('/db/_partition/partition/_all_docs?limit=1&include_docs=true') - .reply(200, response) + mockPool + .intercept({ path: '/db/_partition/partition/_all_docs?limit=1&include_docs=true' }) + .reply(200, response, JSON_HEADERS) - return new Promise((resolve, reject) => { + await new Promise((resolve, reject) => { // test GET /db/_partition/_all_docs const db = nano.db.use('db') const s = db.partitionedListAsStream('partition', { limit: 1, include_docs: true }) - expect(typeof s).toBe('object') + assert.equal(typeof s, 'object') let buffer = '' s.on('data', (chunk) => { buffer += chunk.toString() }) s.on('end', () => { - expect(buffer).toBe(JSON.stringify(response)) - expect(scope.isDone()).toBe(true) + assert.equal(buffer, JSON.stringify(response)) + mockAgent.assertNoPendingInterceptors() resolve() }) }) diff --git a/test/partition.search.test.js b/test/partition.search.test.js index a54ed368..1de358a7 100644 --- a/test/partition.search.test.js +++ b/test/partition.search.test.js @@ -10,14 +10,11 @@ // License for the specific language governing permissions and limitations under // the License. +const test = require('node:test') +const assert = require('node:assert/strict') +const { COUCH_URL, mockAgent, mockPool, JSON_HEADERS } = require('./mock.js') const Nano = require('..') -const COUCH_URL = 'http://localhost:5984' const nano = Nano(COUCH_URL) -const nock = require('nock') - -afterEach(() => { - nock.cleanAll() -}) test('should be able to access a partitioned search index - GET /db/_partition/partition/_design/ddoc/_search/searchname - db.partitionedSearch', async () => { // mocks @@ -29,15 +26,15 @@ test('should be able to access a partitioned search index - GET /db/_partition/p ] } const params = { q: '*:*' } - const scope = nock(COUCH_URL) - .get('/db/_partition/partition/_design/ddoc/_search/searchname?q=*:*') - .reply(200, response) + mockPool + .intercept({ path: '/db/_partition/partition/_design/ddoc/_search/searchname?q=*:*' }) + .reply(200, response, JSON_HEADERS) // test GET /db/_partition/partition/_design/ddoc/_search/searchname const db = nano.db.use('db') const p = await db.partitionedSearch('partition', 'ddoc', 'searchname', params) - expect(p).toStrictEqual(response) - expect(scope.isDone()).toBe(true) + assert.deepEqual(p, response) + mockAgent.assertNoPendingInterceptors() }) test('should be able to handle 404 - db.partitionedSearch', async () => { @@ -47,32 +44,23 @@ test('should be able to handle 404 - db.partitionedSearch', async () => { reason: 'missing' } const params = { q: '*:*' } - const scope = nock(COUCH_URL) - .get('/db/_partition/partition/_design/ddoc/_search/searchname?q=*:*') - .reply(404, response) + mockPool + .intercept({ path: '/db/_partition/partition/_design/ddoc/_search/searchname?q=*:*' }) + .reply(404, response, JSON_HEADERS) // test GET /db/_partition/partition/_design/ddoc/_search/searchname const db = nano.db.use('db') - await expect(db.partitionedSearch('partition', 'ddoc', 'searchname', params)).rejects.toThrow('missing') - expect(scope.isDone()).toBe(true) + await assert.rejects(db.partitionedSearch('partition', 'ddoc', 'searchname', params), { message: response.reason }) + mockAgent.assertNoPendingInterceptors() }) test('should detect missing parameters - db.partitionedSearch', async () => { const db = nano.db.use('db') - await expect(db.partitionedSearch()).rejects.toThrow('Invalid parameters') - await expect(db.partitionedSearch('partition', 'susan')).rejects.toThrow('Invalid parameters') - await expect(db.partitionedSearch('partition', 'susan', '')).rejects.toThrow('Invalid parameters') - await expect(db.partitionedSearch('partition', '', 'susan')).rejects.toThrow('Invalid parameters') - await expect(db.partitionedSearch('partition', 'susan', '', undefined)).rejects.toThrow('Invalid parameters') - await expect(db.partitionedSearch('partition', '', 'susan')).rejects.toThrow('Invalid parameters') + await assert.rejects(db.partitionedSearch(), { message: 'Invalid parameters' }) + await assert.rejects(db.partitionedSearch('partition', 'susan'), { message: 'Invalid parameters' }) + await assert.rejects(db.partitionedSearch('partition', 'susan', ''), { message: 'Invalid parameters' }) + await assert.rejects(db.partitionedSearch('partition', '', 'susan'), { message: 'Invalid parameters' }) + await assert.rejects(db.partitionedSearch('partition', 'susan', '', undefined), { message: 'Invalid parameters' }) + await assert.rejects(db.partitionedSearch('partition', '', 'susan'), { message: 'Invalid parameters' }) }) -test('should detect missing parameters (callback) - db.partitionedSearch', async () => { - const db = nano.db.use('db') - return new Promise((resolve, reject) => { - db.partitionedSearch('', '', '', '', (err, data) => { - expect(err).not.toBeNull() - resolve() - }) - }) -}) diff --git a/test/partition.searchAsStream.test.js b/test/partition.searchAsStream.test.js index ec90bc05..f53a724b 100644 --- a/test/partition.searchAsStream.test.js +++ b/test/partition.searchAsStream.test.js @@ -10,14 +10,11 @@ // License for the specific language governing permissions and limitations under // the License. +const test = require('node:test') +const assert = require('node:assert/strict') +const { COUCH_URL, mockAgent, mockPool, JSON_HEADERS } = require('./mock.js') const Nano = require('..') -const COUCH_URL = 'http://localhost:5984' const nano = Nano(COUCH_URL) -const nock = require('nock') - -afterEach(() => { - nock.cleanAll() -}) test('should get a searched streamed list of documents from a partition- GET /db/_partition/partition/_design/ddoc/_search/searchname - db.partitionedSearchAsStream', async () => { // mocks @@ -29,22 +26,22 @@ test('should get a searched streamed list of documents from a partition- GET /db ] } const params = { q: '*:*' } - const scope = nock(COUCH_URL) - .get('/db/_partition/partition/_design/ddoc/_search/searchname?q=*:*') - .reply(200, response) + mockPool + .intercept({ path: '/db/_partition/partition/_design/ddoc/_search/searchname?q=*:*' }) + .reply(200, response, JSON_HEADERS) - return new Promise((resolve, reject) => { + await new Promise((resolve, reject) => { // test GET /db/_partition/partition/_design/ddoc/_search/searchname const db = nano.db.use('db') const s = db.partitionedSearchAsStream('partition', 'ddoc', 'searchname', params) - expect(typeof s).toBe('object') + assert.equal(typeof s, 'object') let buffer = '' s.on('data', (chunk) => { buffer += chunk.toString() }) s.on('end', () => { - expect(buffer).toBe(JSON.stringify(response)) - expect(scope.isDone()).toBe(true) + assert.equal(buffer, JSON.stringify(response)) + mockAgent.assertNoPendingInterceptors() resolve() }) }) diff --git a/test/partition.view.test.js b/test/partition.view.test.js index 4b532fd7..a6fd0c09 100644 --- a/test/partition.view.test.js +++ b/test/partition.view.test.js @@ -10,14 +10,11 @@ // License for the specific language governing permissions and limitations under // the License. +const test = require('node:test') +const assert = require('node:assert/strict') +const { COUCH_URL, mockAgent, mockPool, JSON_HEADERS } = require('./mock.js') const Nano = require('..') -const COUCH_URL = 'http://localhost:5984' const nano = Nano(COUCH_URL) -const nock = require('nock') - -afterEach(() => { - nock.cleanAll() -}) test('should be able to access a partitioned view index - GET /db/_partition/partition/_design/ddoc/_view/viewname - db.partitionedView', async () => { // mocks @@ -26,15 +23,15 @@ test('should be able to access a partitioned view index - GET /db/_partition/par { key: null, value: 23515 } ] } - const scope = nock(COUCH_URL) - .get('/db/_partition/partition/_design/ddoc/_view/viewname') - .reply(200, response) + mockPool + .intercept({ path: '/db/_partition/partition/_design/ddoc/_view/viewname' }) + .reply(200, response, JSON_HEADERS) // test GET /db/_partition/partition/_design/ddoc/_view/viewname const db = nano.db.use('db') const p = await db.partitionedView('partition', 'ddoc', 'viewname') - expect(p).toStrictEqual(response) - expect(scope.isDone()).toBe(true) + assert.deepEqual(p, response) + mockAgent.assertNoPendingInterceptors() }) test('should be able to access a partitioned view index with opts - GET /db/_partition/partition/_design/ddoc/_view/viewname - db.partitionedView', async () => { @@ -50,15 +47,15 @@ test('should be able to access a partitioned view index with opts - GET /db/_par endkey: 'b', limit: 1 } - const scope = nock(COUCH_URL) - .get('/db/_partition/partition/_design/ddoc/_view/viewname?reduce=false&startkey=%22a%22&endkey=%22b%22&limit=1') - .reply(200, response) + mockPool + .intercept({ path: '/db/_partition/partition/_design/ddoc/_view/viewname?reduce=false&startkey=%22a%22&endkey=%22b%22&limit=1' }) + .reply(200, response, JSON_HEADERS) // test GET /db/_partition/partition/_design/ddoc/_view/viewname const db = nano.db.use('db') const p = await db.partitionedView('partition', 'ddoc', 'viewname', params) - expect(p).toStrictEqual(response) - expect(scope.isDone()).toBe(true) + assert.deepEqual(p, response) + mockAgent.assertNoPendingInterceptors() }) test('should be able to handle 404 - db.partitionedView', async () => { @@ -67,32 +64,23 @@ test('should be able to handle 404 - db.partitionedView', async () => { error: 'not_found', reason: 'missing' } - const scope = nock(COUCH_URL) - .get('/db/_partition/partition/_design/ddoc/_view/viewname') - .reply(404, response) + mockPool + .intercept({ path: '/db/_partition/partition/_design/ddoc/_view/viewname' }) + .reply(404, response, JSON_HEADERS) // test GET /db/_partition/partition/_design/ddoc/_view/viewname const db = nano.db.use('db') - await expect(db.partitionedView('partition', 'ddoc', 'viewname')).rejects.toThrow('missing') - expect(scope.isDone()).toBe(true) + await assert.rejects(db.partitionedView('partition', 'ddoc', 'viewname'), { message: response.reason }) + mockAgent.assertNoPendingInterceptors() }) test('should detect missing parameters - db.partitionedView', async () => { const db = nano.db.use('db') - await expect(db.partitionedView()).rejects.toThrow('Invalid parameters') - await expect(db.partitionedView('partition', 'susan')).rejects.toThrow('Invalid parameters') - await expect(db.partitionedView('partition', 'susan', '')).rejects.toThrow('Invalid parameters') - await expect(db.partitionedView('partition', '', 'susan')).rejects.toThrow('Invalid parameters') - await expect(db.partitionedView('partition', 'susan', '', undefined)).rejects.toThrow('Invalid parameters') - await expect(db.partitionedView('partition', '', 'susan')).rejects.toThrow('Invalid parameters') + await assert.rejects(db.partitionedView(), { message: 'Invalid parameters' }) + await assert.rejects(db.partitionedView('partition', 'susan'), { message: 'Invalid parameters' }) + await assert.rejects(db.partitionedView('partition', 'susan', ''), { message: 'Invalid parameters' }) + await assert.rejects(db.partitionedView('partition', '', 'susan'), { message: 'Invalid parameters' }) + await assert.rejects(db.partitionedView('partition', 'susan', '', undefined), { message: 'Invalid parameters' }) + await assert.rejects(db.partitionedView('partition', '', 'susan'), { message: 'Invalid parameters' }) }) -test('should detect missing parameters (callback) - db.partitionedView', async () => { - const db = nano.db.use('db') - return new Promise((resolve, reject) => { - db.partitionedView('', '', '', '', (err, data) => { - expect(err).not.toBeNull() - resolve() - }) - }) -}) diff --git a/test/partition.viewAsStream.test.js b/test/partition.viewAsStream.test.js index 97663dbe..1b15805b 100644 --- a/test/partition.viewAsStream.test.js +++ b/test/partition.viewAsStream.test.js @@ -10,14 +10,11 @@ // License for the specific language governing permissions and limitations under // the License. +const test = require('node:test') +const assert = require('node:assert/strict') +const { COUCH_URL, mockAgent, mockPool, JSON_HEADERS } = require('./mock.js') const Nano = require('..') -const COUCH_URL = 'http://localhost:5984' const nano = Nano(COUCH_URL) -const nock = require('nock') - -afterEach(() => { - nock.cleanAll() -}) test('should get a streamed list of documents from a view from partition - GET /db/_partition/partition/_design/ddoc/_view/viewname - db.partitionedViewAsStream', async () => { // mocks @@ -32,22 +29,22 @@ test('should get a streamed list of documents from a view from partition - GET endkey: 'b', limit: 1 } - const scope = nock(COUCH_URL) - .get('/db/_partition/partition/_design/ddoc/_view/viewname?reduce=false&startkey=%22a%22&endkey=%22b%22&limit=1') - .reply(200, response) + mockPool + .intercept({ path: '/db/_partition/partition/_design/ddoc/_view/viewname?reduce=false&startkey=%22a%22&endkey=%22b%22&limit=1' }) + .reply(200, response, JSON_HEADERS) - return new Promise((resolve, reject) => { + await new Promise((resolve, reject) => { // test GET /db/_partition/partition/_design/ddoc/_view/viewnameGET /db/_all_docs const db = nano.db.use('db') const s = db.partitionedViewAsStream('partition', 'ddoc', 'viewname', params) - expect(typeof s).toBe('object') + assert.equal(typeof s, 'object') let buffer = '' s.on('data', (chunk) => { buffer += chunk.toString() }) s.on('end', () => { - expect(buffer).toBe(JSON.stringify(response)) - expect(scope.isDone()).toBe(true) + assert.equal(buffer, JSON.stringify(response)) + mockAgent.assertNoPendingInterceptors() resolve() }) })