From fb9c3c5d8e21d86bbb2e92670b97ea0d2bdf0056 Mon Sep 17 00:00:00 2001 From: winjolu Date: Thu, 22 Aug 2024 14:21:57 -0400 Subject: [PATCH 001/357] git cheat sheet in readme --- README.md | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/README.md b/README.md index 8b137891..2893eb6f 100644 --- a/README.md +++ b/README.md @@ -1 +1,21 @@ +// to sync w both origin/dev and upstream/dev: +git fetch upstream +git rebase upstream/dev +git push origin dev + + +// to check which remote branches are tracked: +git branch -vv + +// to make a PR fron GitHub CLI +gh pr create --base upstream/dev --head origin/dev --title "PR Title goes here" --body "Description of your changes goes here" + + +//install GH CLI (mac): +brew install gh + +// install GH CLI (windows): +winget install --id GitHub.cli + + From d748924945ec75782287471f7c1e66f4a76b2f76 Mon Sep 17 00:00:00 2001 From: winjolu Date: Thu, 22 Aug 2024 14:22:04 -0400 Subject: [PATCH 002/357] git cheat sheet in readme --- README.md | 23 +++++++++++++++++++++-- 1 file changed, 21 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 2893eb6f..1ca98b1a 100644 --- a/README.md +++ b/README.md @@ -9,13 +9,32 @@ git push origin dev git branch -vv // to make a PR fron GitHub CLI -gh pr create --base upstream/dev --head origin/dev --title "PR Title goes here" --body "Description of your changes goes here" + // login to GH CLI (if you're not): + gh auth login + // make PR: + gh pr create --base upstream/dev --head origin/dev --title "PR Title goes here" --body "Description of your changes goes here" -//install GH CLI (mac): + +// install GH CLI (mac): brew install gh // install GH CLI (windows): winget install --id GitHub.cli +// linux (debian): + + //add the repository: + curl -fsSL https://cli.github.com/packages/githubcli-archive-keyring.gpg | sudo dd of=/usr/share/keyrings/githubcli-archive-keyring.gpg + sudo chmod go+r /usr/share/keyrings/githubcli-archive-keyring.gpg + echo "deb [arch=$(dpkg --print-architecture) signed-by=/usr/share/keyrings/githubcli-archive-keyring.gpg] https://cli.github.com/packages stable main" | sudo tee /etc/apt/sources.list.d/github-cli.list > /dev/null + + // update package list: + sudo apt update + + // install GH CLI: + sudo apt install gh + + + From 2e0de7a57a2dc86485aca7903821163def06d82a Mon Sep 17 00:00:00 2001 From: winjolu Date: Thu, 22 Aug 2024 14:32:54 -0400 Subject: [PATCH 003/357] test --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 1ca98b1a..88d81fe2 100644 --- a/README.md +++ b/README.md @@ -35,6 +35,6 @@ winget install --id GitHub.cli // install GH CLI: sudo apt install gh - +// test text From 1ea872accf21f207db282bc296c9ca586c644236 Mon Sep 17 00:00:00 2001 From: Austin Fraser Date: Sat, 24 Aug 2024 13:51:13 -0700 Subject: [PATCH 004/357] installing fetch and defining file structures --- Model_registry/model_registry_management.js | 0 Model_registry/model_version_management.js | 0 Tracking_server/artifact_management.js | 0 Tracking_server/experiment_management.js | 0 Tracking_server/run_management.js | 0 node_modules/.package-lock.json | 46 + node_modules/node-fetch/LICENSE.md | 22 + node_modules/node-fetch/README.md | 634 ++++++ node_modules/node-fetch/browser.js | 25 + node_modules/node-fetch/lib/index.es.js | 1777 ++++++++++++++++ node_modules/node-fetch/lib/index.js | 1787 +++++++++++++++++ node_modules/node-fetch/lib/index.mjs | 1775 ++++++++++++++++ node_modules/node-fetch/package.json | 89 + node_modules/tr46/.npmignore | 4 + node_modules/tr46/index.js | 193 ++ node_modules/tr46/lib/.gitkeep | 0 node_modules/tr46/lib/mappingTable.json | 1 + node_modules/tr46/package.json | 31 + node_modules/webidl-conversions/LICENSE.md | 12 + node_modules/webidl-conversions/README.md | 53 + node_modules/webidl-conversions/lib/index.js | 189 ++ node_modules/webidl-conversions/package.json | 23 + node_modules/whatwg-url/LICENSE.txt | 21 + node_modules/whatwg-url/README.md | 67 + node_modules/whatwg-url/lib/URL-impl.js | 200 ++ node_modules/whatwg-url/lib/URL.js | 196 ++ node_modules/whatwg-url/lib/public-api.js | 11 + .../whatwg-url/lib/url-state-machine.js | 1297 ++++++++++++ node_modules/whatwg-url/lib/utils.js | 20 + node_modules/whatwg-url/package.json | 32 + package-lock.json | 54 + package.json | 14 + 32 files changed, 8573 insertions(+) create mode 100644 Model_registry/model_registry_management.js create mode 100644 Model_registry/model_version_management.js create mode 100644 Tracking_server/artifact_management.js create mode 100644 Tracking_server/experiment_management.js create mode 100644 Tracking_server/run_management.js create mode 100644 node_modules/.package-lock.json create mode 100644 node_modules/node-fetch/LICENSE.md create mode 100644 node_modules/node-fetch/README.md create mode 100644 node_modules/node-fetch/browser.js create mode 100644 node_modules/node-fetch/lib/index.es.js create mode 100644 node_modules/node-fetch/lib/index.js create mode 100644 node_modules/node-fetch/lib/index.mjs create mode 100644 node_modules/node-fetch/package.json create mode 100644 node_modules/tr46/.npmignore create mode 100644 node_modules/tr46/index.js create mode 100644 node_modules/tr46/lib/.gitkeep create mode 100644 node_modules/tr46/lib/mappingTable.json create mode 100644 node_modules/tr46/package.json create mode 100644 node_modules/webidl-conversions/LICENSE.md create mode 100644 node_modules/webidl-conversions/README.md create mode 100644 node_modules/webidl-conversions/lib/index.js create mode 100644 node_modules/webidl-conversions/package.json create mode 100644 node_modules/whatwg-url/LICENSE.txt create mode 100644 node_modules/whatwg-url/README.md create mode 100644 node_modules/whatwg-url/lib/URL-impl.js create mode 100644 node_modules/whatwg-url/lib/URL.js create mode 100644 node_modules/whatwg-url/lib/public-api.js create mode 100644 node_modules/whatwg-url/lib/url-state-machine.js create mode 100644 node_modules/whatwg-url/lib/utils.js create mode 100644 node_modules/whatwg-url/package.json create mode 100644 package-lock.json create mode 100644 package.json diff --git a/Model_registry/model_registry_management.js b/Model_registry/model_registry_management.js new file mode 100644 index 00000000..e69de29b diff --git a/Model_registry/model_version_management.js b/Model_registry/model_version_management.js new file mode 100644 index 00000000..e69de29b diff --git a/Tracking_server/artifact_management.js b/Tracking_server/artifact_management.js new file mode 100644 index 00000000..e69de29b diff --git a/Tracking_server/experiment_management.js b/Tracking_server/experiment_management.js new file mode 100644 index 00000000..e69de29b diff --git a/Tracking_server/run_management.js b/Tracking_server/run_management.js new file mode 100644 index 00000000..e69de29b diff --git a/node_modules/.package-lock.json b/node_modules/.package-lock.json new file mode 100644 index 00000000..cf73c43f --- /dev/null +++ b/node_modules/.package-lock.json @@ -0,0 +1,46 @@ +{ + "name": "mlflow", + "version": "1.0.0", + "lockfileVersion": 3, + "requires": true, + "packages": { + "node_modules/node-fetch": { + "version": "2.7.0", + "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.7.0.tgz", + "integrity": "sha512-c4FRfUm/dbcWZ7U+1Wq0AwCyFL+3nt2bEw05wfxSz+DWpWsitgmSgYmy2dQdWyKC1694ELPqMs/YzUSNozLt8A==", + "dependencies": { + "whatwg-url": "^5.0.0" + }, + "engines": { + "node": "4.x || >=6.0.0" + }, + "peerDependencies": { + "encoding": "^0.1.0" + }, + "peerDependenciesMeta": { + "encoding": { + "optional": true + } + } + }, + "node_modules/tr46": { + "version": "0.0.3", + "resolved": "https://registry.npmjs.org/tr46/-/tr46-0.0.3.tgz", + "integrity": "sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw==" + }, + "node_modules/webidl-conversions": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-3.0.1.tgz", + "integrity": "sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ==" + }, + "node_modules/whatwg-url": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-5.0.0.tgz", + "integrity": "sha512-saE57nupxk6v3HY35+jzBwYa0rKSy0XR8JSxZPwgLr7ys0IBzhGviA1/TUGJLmSVqs8pb9AnvICXEuOHLprYTw==", + "dependencies": { + "tr46": "~0.0.3", + "webidl-conversions": "^3.0.0" + } + } + } +} diff --git a/node_modules/node-fetch/LICENSE.md b/node_modules/node-fetch/LICENSE.md new file mode 100644 index 00000000..660ffecb --- /dev/null +++ b/node_modules/node-fetch/LICENSE.md @@ -0,0 +1,22 @@ +The MIT License (MIT) + +Copyright (c) 2016 David Frank + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. + diff --git a/node_modules/node-fetch/README.md b/node_modules/node-fetch/README.md new file mode 100644 index 00000000..55f09b7f --- /dev/null +++ b/node_modules/node-fetch/README.md @@ -0,0 +1,634 @@ +node-fetch +========== + +[![npm version][npm-image]][npm-url] +[![build status][travis-image]][travis-url] +[![coverage status][codecov-image]][codecov-url] +[![install size][install-size-image]][install-size-url] +[![Discord][discord-image]][discord-url] + +A light-weight module that brings `window.fetch` to Node.js + +(We are looking for [v2 maintainers and collaborators](https://github.com/bitinn/node-fetch/issues/567)) + +[![Backers][opencollective-image]][opencollective-url] + + + +- [Motivation](#motivation) +- [Features](#features) +- [Difference from client-side fetch](#difference-from-client-side-fetch) +- [Installation](#installation) +- [Loading and configuring the module](#loading-and-configuring-the-module) +- [Common Usage](#common-usage) + - [Plain text or HTML](#plain-text-or-html) + - [JSON](#json) + - [Simple Post](#simple-post) + - [Post with JSON](#post-with-json) + - [Post with form parameters](#post-with-form-parameters) + - [Handling exceptions](#handling-exceptions) + - [Handling client and server errors](#handling-client-and-server-errors) +- [Advanced Usage](#advanced-usage) + - [Streams](#streams) + - [Buffer](#buffer) + - [Accessing Headers and other Meta data](#accessing-headers-and-other-meta-data) + - [Extract Set-Cookie Header](#extract-set-cookie-header) + - [Post data using a file stream](#post-data-using-a-file-stream) + - [Post with form-data (detect multipart)](#post-with-form-data-detect-multipart) + - [Request cancellation with AbortSignal](#request-cancellation-with-abortsignal) +- [API](#api) + - [fetch(url[, options])](#fetchurl-options) + - [Options](#options) + - [Class: Request](#class-request) + - [Class: Response](#class-response) + - [Class: Headers](#class-headers) + - [Interface: Body](#interface-body) + - [Class: FetchError](#class-fetcherror) +- [License](#license) +- [Acknowledgement](#acknowledgement) + + + +## Motivation + +Instead of implementing `XMLHttpRequest` in Node.js to run browser-specific [Fetch polyfill](https://github.com/github/fetch), why not go from native `http` to `fetch` API directly? Hence, `node-fetch`, minimal code for a `window.fetch` compatible API on Node.js runtime. + +See Matt Andrews' [isomorphic-fetch](https://github.com/matthew-andrews/isomorphic-fetch) or Leonardo Quixada's [cross-fetch](https://github.com/lquixada/cross-fetch) for isomorphic usage (exports `node-fetch` for server-side, `whatwg-fetch` for client-side). + +## Features + +- Stay consistent with `window.fetch` API. +- Make conscious trade-off when following [WHATWG fetch spec][whatwg-fetch] and [stream spec](https://streams.spec.whatwg.org/) implementation details, document known differences. +- Use native promise but allow substituting it with [insert your favorite promise library]. +- Use native Node streams for body on both request and response. +- Decode content encoding (gzip/deflate) properly and convert string output (such as `res.text()` and `res.json()`) to UTF-8 automatically. +- Useful extensions such as timeout, redirect limit, response size limit, [explicit errors](ERROR-HANDLING.md) for troubleshooting. + +## Difference from client-side fetch + +- See [Known Differences](LIMITS.md) for details. +- If you happen to use a missing feature that `window.fetch` offers, feel free to open an issue. +- Pull requests are welcomed too! + +## Installation + +Current stable release (`2.x`) + +```sh +$ npm install node-fetch +``` + +## Loading and configuring the module +We suggest you load the module via `require` until the stabilization of ES modules in node: +```js +const fetch = require('node-fetch'); +``` + +If you are using a Promise library other than native, set it through `fetch.Promise`: +```js +const Bluebird = require('bluebird'); + +fetch.Promise = Bluebird; +``` + +## Common Usage + +NOTE: The documentation below is up-to-date with `2.x` releases; see the [`1.x` readme](https://github.com/bitinn/node-fetch/blob/1.x/README.md), [changelog](https://github.com/bitinn/node-fetch/blob/1.x/CHANGELOG.md) and [2.x upgrade guide](UPGRADE-GUIDE.md) for the differences. + +#### Plain text or HTML +```js +fetch('https://github.com/') + .then(res => res.text()) + .then(body => console.log(body)); +``` + +#### JSON + +```js + +fetch('https://api.github.com/users/github') + .then(res => res.json()) + .then(json => console.log(json)); +``` + +#### Simple Post +```js +fetch('https://httpbin.org/post', { method: 'POST', body: 'a=1' }) + .then(res => res.json()) // expecting a json response + .then(json => console.log(json)); +``` + +#### Post with JSON + +```js +const body = { a: 1 }; + +fetch('https://httpbin.org/post', { + method: 'post', + body: JSON.stringify(body), + headers: { 'Content-Type': 'application/json' }, + }) + .then(res => res.json()) + .then(json => console.log(json)); +``` + +#### Post with form parameters +`URLSearchParams` is available in Node.js as of v7.5.0. See [official documentation](https://nodejs.org/api/url.html#url_class_urlsearchparams) for more usage methods. + +NOTE: The `Content-Type` header is only set automatically to `x-www-form-urlencoded` when an instance of `URLSearchParams` is given as such: + +```js +const { URLSearchParams } = require('url'); + +const params = new URLSearchParams(); +params.append('a', 1); + +fetch('https://httpbin.org/post', { method: 'POST', body: params }) + .then(res => res.json()) + .then(json => console.log(json)); +``` + +#### Handling exceptions +NOTE: 3xx-5xx responses are *NOT* exceptions and should be handled in `then()`; see the next section for more information. + +Adding a catch to the fetch promise chain will catch *all* exceptions, such as errors originating from node core libraries, network errors and operational errors, which are instances of FetchError. See the [error handling document](ERROR-HANDLING.md) for more details. + +```js +fetch('https://domain.invalid/') + .catch(err => console.error(err)); +``` + +#### Handling client and server errors +It is common to create a helper function to check that the response contains no client (4xx) or server (5xx) error responses: + +```js +function checkStatus(res) { + if (res.ok) { // res.status >= 200 && res.status < 300 + return res; + } else { + throw MyCustomError(res.statusText); + } +} + +fetch('https://httpbin.org/status/400') + .then(checkStatus) + .then(res => console.log('will not get here...')) +``` + +## Advanced Usage + +#### Streams +The "Node.js way" is to use streams when possible: + +```js +fetch('https://assets-cdn.github.com/images/modules/logos_page/Octocat.png') + .then(res => { + const dest = fs.createWriteStream('./octocat.png'); + res.body.pipe(dest); + }); +``` + +In Node.js 14 you can also use async iterators to read `body`; however, be careful to catch +errors -- the longer a response runs, the more likely it is to encounter an error. + +```js +const fetch = require('node-fetch'); +const response = await fetch('https://httpbin.org/stream/3'); +try { + for await (const chunk of response.body) { + console.dir(JSON.parse(chunk.toString())); + } +} catch (err) { + console.error(err.stack); +} +``` + +In Node.js 12 you can also use async iterators to read `body`; however, async iterators with streams +did not mature until Node.js 14, so you need to do some extra work to ensure you handle errors +directly from the stream and wait on it response to fully close. + +```js +const fetch = require('node-fetch'); +const read = async body => { + let error; + body.on('error', err => { + error = err; + }); + for await (const chunk of body) { + console.dir(JSON.parse(chunk.toString())); + } + return new Promise((resolve, reject) => { + body.on('close', () => { + error ? reject(error) : resolve(); + }); + }); +}; +try { + const response = await fetch('https://httpbin.org/stream/3'); + await read(response.body); +} catch (err) { + console.error(err.stack); +} +``` + +#### Buffer +If you prefer to cache binary data in full, use buffer(). (NOTE: `buffer()` is a `node-fetch`-only API) + +```js +const fileType = require('file-type'); + +fetch('https://assets-cdn.github.com/images/modules/logos_page/Octocat.png') + .then(res => res.buffer()) + .then(buffer => fileType(buffer)) + .then(type => { /* ... */ }); +``` + +#### Accessing Headers and other Meta data +```js +fetch('https://github.com/') + .then(res => { + console.log(res.ok); + console.log(res.status); + console.log(res.statusText); + console.log(res.headers.raw()); + console.log(res.headers.get('content-type')); + }); +``` + +#### Extract Set-Cookie Header + +Unlike browsers, you can access raw `Set-Cookie` headers manually using `Headers.raw()`. This is a `node-fetch` only API. + +```js +fetch(url).then(res => { + // returns an array of values, instead of a string of comma-separated values + console.log(res.headers.raw()['set-cookie']); +}); +``` + +#### Post data using a file stream + +```js +const { createReadStream } = require('fs'); + +const stream = createReadStream('input.txt'); + +fetch('https://httpbin.org/post', { method: 'POST', body: stream }) + .then(res => res.json()) + .then(json => console.log(json)); +``` + +#### Post with form-data (detect multipart) + +```js +const FormData = require('form-data'); + +const form = new FormData(); +form.append('a', 1); + +fetch('https://httpbin.org/post', { method: 'POST', body: form }) + .then(res => res.json()) + .then(json => console.log(json)); + +// OR, using custom headers +// NOTE: getHeaders() is non-standard API + +const form = new FormData(); +form.append('a', 1); + +const options = { + method: 'POST', + body: form, + headers: form.getHeaders() +} + +fetch('https://httpbin.org/post', options) + .then(res => res.json()) + .then(json => console.log(json)); +``` + +#### Request cancellation with AbortSignal + +> NOTE: You may cancel streamed requests only on Node >= v8.0.0 + +You may cancel requests with `AbortController`. A suggested implementation is [`abort-controller`](https://www.npmjs.com/package/abort-controller). + +An example of timing out a request after 150ms could be achieved as the following: + +```js +import AbortController from 'abort-controller'; + +const controller = new AbortController(); +const timeout = setTimeout( + () => { controller.abort(); }, + 150, +); + +fetch(url, { signal: controller.signal }) + .then(res => res.json()) + .then( + data => { + useData(data) + }, + err => { + if (err.name === 'AbortError') { + // request was aborted + } + }, + ) + .finally(() => { + clearTimeout(timeout); + }); +``` + +See [test cases](https://github.com/bitinn/node-fetch/blob/master/test/test.js) for more examples. + + +## API + +### fetch(url[, options]) + +- `url` A string representing the URL for fetching +- `options` [Options](#fetch-options) for the HTTP(S) request +- Returns: Promise<[Response](#class-response)> + +Perform an HTTP(S) fetch. + +`url` should be an absolute url, such as `https://example.com/`. A path-relative URL (`/file/under/root`) or protocol-relative URL (`//can-be-http-or-https.com/`) will result in a rejected `Promise`. + + +### Options + +The default values are shown after each option key. + +```js +{ + // These properties are part of the Fetch Standard + method: 'GET', + headers: {}, // request headers. format is the identical to that accepted by the Headers constructor (see below) + body: null, // request body. can be null, a string, a Buffer, a Blob, or a Node.js Readable stream + redirect: 'follow', // set to `manual` to extract redirect headers, `error` to reject redirect + signal: null, // pass an instance of AbortSignal to optionally abort requests + + // The following properties are node-fetch extensions + follow: 20, // maximum redirect count. 0 to not follow redirect + timeout: 0, // req/res timeout in ms, it resets on redirect. 0 to disable (OS limit applies). Signal is recommended instead. + compress: true, // support gzip/deflate content encoding. false to disable + size: 0, // maximum response body size in bytes. 0 to disable + agent: null // http(s).Agent instance or function that returns an instance (see below) +} +``` + +##### Default Headers + +If no values are set, the following request headers will be sent automatically: + +Header | Value +------------------- | -------------------------------------------------------- +`Accept-Encoding` | `gzip,deflate` _(when `options.compress === true`)_ +`Accept` | `*/*` +`Content-Length` | _(automatically calculated, if possible)_ +`Transfer-Encoding` | `chunked` _(when `req.body` is a stream)_ +`User-Agent` | `node-fetch/1.0 (+https://github.com/bitinn/node-fetch)` + +Note: when `body` is a `Stream`, `Content-Length` is not set automatically. + +##### Custom Agent + +The `agent` option allows you to specify networking related options which are out of the scope of Fetch, including and not limited to the following: + +- Support self-signed certificate +- Use only IPv4 or IPv6 +- Custom DNS Lookup + +See [`http.Agent`](https://nodejs.org/api/http.html#http_new_agent_options) for more information. + +If no agent is specified, the default agent provided by Node.js is used. Note that [this changed in Node.js 19](https://github.com/nodejs/node/blob/4267b92604ad78584244488e7f7508a690cb80d0/lib/_http_agent.js#L564) to have `keepalive` true by default. If you wish to enable `keepalive` in an earlier version of Node.js, you can override the agent as per the following code sample. + +In addition, the `agent` option accepts a function that returns `http`(s)`.Agent` instance given current [URL](https://nodejs.org/api/url.html), this is useful during a redirection chain across HTTP and HTTPS protocol. + +```js +const httpAgent = new http.Agent({ + keepAlive: true +}); +const httpsAgent = new https.Agent({ + keepAlive: true +}); + +const options = { + agent: function (_parsedURL) { + if (_parsedURL.protocol == 'http:') { + return httpAgent; + } else { + return httpsAgent; + } + } +} +``` + + +### Class: Request + +An HTTP(S) request containing information about URL, method, headers, and the body. This class implements the [Body](#iface-body) interface. + +Due to the nature of Node.js, the following properties are not implemented at this moment: + +- `type` +- `destination` +- `referrer` +- `referrerPolicy` +- `mode` +- `credentials` +- `cache` +- `integrity` +- `keepalive` + +The following node-fetch extension properties are provided: + +- `follow` +- `compress` +- `counter` +- `agent` + +See [options](#fetch-options) for exact meaning of these extensions. + +#### new Request(input[, options]) + +*(spec-compliant)* + +- `input` A string representing a URL, or another `Request` (which will be cloned) +- `options` [Options][#fetch-options] for the HTTP(S) request + +Constructs a new `Request` object. The constructor is identical to that in the [browser](https://developer.mozilla.org/en-US/docs/Web/API/Request/Request). + +In most cases, directly `fetch(url, options)` is simpler than creating a `Request` object. + + +### Class: Response + +An HTTP(S) response. This class implements the [Body](#iface-body) interface. + +The following properties are not implemented in node-fetch at this moment: + +- `Response.error()` +- `Response.redirect()` +- `type` +- `trailer` + +#### new Response([body[, options]]) + +*(spec-compliant)* + +- `body` A `String` or [`Readable` stream][node-readable] +- `options` A [`ResponseInit`][response-init] options dictionary + +Constructs a new `Response` object. The constructor is identical to that in the [browser](https://developer.mozilla.org/en-US/docs/Web/API/Response/Response). + +Because Node.js does not implement service workers (for which this class was designed), one rarely has to construct a `Response` directly. + +#### response.ok + +*(spec-compliant)* + +Convenience property representing if the request ended normally. Will evaluate to true if the response status was greater than or equal to 200 but smaller than 300. + +#### response.redirected + +*(spec-compliant)* + +Convenience property representing if the request has been redirected at least once. Will evaluate to true if the internal redirect counter is greater than 0. + + +### Class: Headers + +This class allows manipulating and iterating over a set of HTTP headers. All methods specified in the [Fetch Standard][whatwg-fetch] are implemented. + +#### new Headers([init]) + +*(spec-compliant)* + +- `init` Optional argument to pre-fill the `Headers` object + +Construct a new `Headers` object. `init` can be either `null`, a `Headers` object, an key-value map object or any iterable object. + +```js +// Example adapted from https://fetch.spec.whatwg.org/#example-headers-class + +const meta = { + 'Content-Type': 'text/xml', + 'Breaking-Bad': '<3' +}; +const headers = new Headers(meta); + +// The above is equivalent to +const meta = [ + [ 'Content-Type', 'text/xml' ], + [ 'Breaking-Bad', '<3' ] +]; +const headers = new Headers(meta); + +// You can in fact use any iterable objects, like a Map or even another Headers +const meta = new Map(); +meta.set('Content-Type', 'text/xml'); +meta.set('Breaking-Bad', '<3'); +const headers = new Headers(meta); +const copyOfHeaders = new Headers(headers); +``` + + +### Interface: Body + +`Body` is an abstract interface with methods that are applicable to both `Request` and `Response` classes. + +The following methods are not yet implemented in node-fetch at this moment: + +- `formData()` + +#### body.body + +*(deviation from spec)* + +* Node.js [`Readable` stream][node-readable] + +Data are encapsulated in the `Body` object. Note that while the [Fetch Standard][whatwg-fetch] requires the property to always be a WHATWG `ReadableStream`, in node-fetch it is a Node.js [`Readable` stream][node-readable]. + +#### body.bodyUsed + +*(spec-compliant)* + +* `Boolean` + +A boolean property for if this body has been consumed. Per the specs, a consumed body cannot be used again. + +#### body.arrayBuffer() +#### body.blob() +#### body.json() +#### body.text() + +*(spec-compliant)* + +* Returns: Promise + +Consume the body and return a promise that will resolve to one of these formats. + +#### body.buffer() + +*(node-fetch extension)* + +* Returns: Promise<Buffer> + +Consume the body and return a promise that will resolve to a Buffer. + +#### body.textConverted() + +*(node-fetch extension)* + +* Returns: Promise<String> + +Identical to `body.text()`, except instead of always converting to UTF-8, encoding sniffing will be performed and text converted to UTF-8 if possible. + +(This API requires an optional dependency of the npm package [encoding](https://www.npmjs.com/package/encoding), which you need to install manually. `webpack` users may see [a warning message](https://github.com/bitinn/node-fetch/issues/412#issuecomment-379007792) due to this optional dependency.) + + +### Class: FetchError + +*(node-fetch extension)* + +An operational error in the fetching process. See [ERROR-HANDLING.md][] for more info. + + +### Class: AbortError + +*(node-fetch extension)* + +An Error thrown when the request is aborted in response to an `AbortSignal`'s `abort` event. It has a `name` property of `AbortError`. See [ERROR-HANDLING.MD][] for more info. + +## Acknowledgement + +Thanks to [github/fetch](https://github.com/github/fetch) for providing a solid implementation reference. + +`node-fetch` v1 was maintained by [@bitinn](https://github.com/bitinn); v2 was maintained by [@TimothyGu](https://github.com/timothygu), [@bitinn](https://github.com/bitinn) and [@jimmywarting](https://github.com/jimmywarting); v2 readme is written by [@jkantr](https://github.com/jkantr). + +## License + +MIT + +[npm-image]: https://flat.badgen.net/npm/v/node-fetch +[npm-url]: https://www.npmjs.com/package/node-fetch +[travis-image]: https://flat.badgen.net/travis/bitinn/node-fetch +[travis-url]: https://travis-ci.org/bitinn/node-fetch +[codecov-image]: https://flat.badgen.net/codecov/c/github/bitinn/node-fetch/master +[codecov-url]: https://codecov.io/gh/bitinn/node-fetch +[install-size-image]: https://flat.badgen.net/packagephobia/install/node-fetch +[install-size-url]: https://packagephobia.now.sh/result?p=node-fetch +[discord-image]: https://img.shields.io/discord/619915844268326952?color=%237289DA&label=Discord&style=flat-square +[discord-url]: https://discord.gg/Zxbndcm +[opencollective-image]: https://opencollective.com/node-fetch/backers.svg +[opencollective-url]: https://opencollective.com/node-fetch +[whatwg-fetch]: https://fetch.spec.whatwg.org/ +[response-init]: https://fetch.spec.whatwg.org/#responseinit +[node-readable]: https://nodejs.org/api/stream.html#stream_readable_streams +[mdn-headers]: https://developer.mozilla.org/en-US/docs/Web/API/Headers +[LIMITS.md]: https://github.com/bitinn/node-fetch/blob/master/LIMITS.md +[ERROR-HANDLING.md]: https://github.com/bitinn/node-fetch/blob/master/ERROR-HANDLING.md +[UPGRADE-GUIDE.md]: https://github.com/bitinn/node-fetch/blob/master/UPGRADE-GUIDE.md diff --git a/node_modules/node-fetch/browser.js b/node_modules/node-fetch/browser.js new file mode 100644 index 00000000..ee86265a --- /dev/null +++ b/node_modules/node-fetch/browser.js @@ -0,0 +1,25 @@ +"use strict"; + +// ref: https://github.com/tc39/proposal-global +var getGlobal = function () { + // the only reliable means to get the global object is + // `Function('return this')()` + // However, this causes CSP violations in Chrome apps. + if (typeof self !== 'undefined') { return self; } + if (typeof window !== 'undefined') { return window; } + if (typeof global !== 'undefined') { return global; } + throw new Error('unable to locate global object'); +} + +var globalObject = getGlobal(); + +module.exports = exports = globalObject.fetch; + +// Needed for TypeScript and Webpack. +if (globalObject.fetch) { + exports.default = globalObject.fetch.bind(globalObject); +} + +exports.Headers = globalObject.Headers; +exports.Request = globalObject.Request; +exports.Response = globalObject.Response; diff --git a/node_modules/node-fetch/lib/index.es.js b/node_modules/node-fetch/lib/index.es.js new file mode 100644 index 00000000..aae9799c --- /dev/null +++ b/node_modules/node-fetch/lib/index.es.js @@ -0,0 +1,1777 @@ +process.emitWarning("The .es.js file is deprecated. Use .mjs instead."); + +import Stream from 'stream'; +import http from 'http'; +import Url from 'url'; +import whatwgUrl from 'whatwg-url'; +import https from 'https'; +import zlib from 'zlib'; + +// Based on https://github.com/tmpvar/jsdom/blob/aa85b2abf07766ff7bf5c1f6daafb3726f2f2db5/lib/jsdom/living/blob.js + +// fix for "Readable" isn't a named export issue +const Readable = Stream.Readable; + +const BUFFER = Symbol('buffer'); +const TYPE = Symbol('type'); + +class Blob { + constructor() { + this[TYPE] = ''; + + const blobParts = arguments[0]; + const options = arguments[1]; + + const buffers = []; + let size = 0; + + if (blobParts) { + const a = blobParts; + const length = Number(a.length); + for (let i = 0; i < length; i++) { + const element = a[i]; + let buffer; + if (element instanceof Buffer) { + buffer = element; + } else if (ArrayBuffer.isView(element)) { + buffer = Buffer.from(element.buffer, element.byteOffset, element.byteLength); + } else if (element instanceof ArrayBuffer) { + buffer = Buffer.from(element); + } else if (element instanceof Blob) { + buffer = element[BUFFER]; + } else { + buffer = Buffer.from(typeof element === 'string' ? element : String(element)); + } + size += buffer.length; + buffers.push(buffer); + } + } + + this[BUFFER] = Buffer.concat(buffers); + + let type = options && options.type !== undefined && String(options.type).toLowerCase(); + if (type && !/[^\u0020-\u007E]/.test(type)) { + this[TYPE] = type; + } + } + get size() { + return this[BUFFER].length; + } + get type() { + return this[TYPE]; + } + text() { + return Promise.resolve(this[BUFFER].toString()); + } + arrayBuffer() { + const buf = this[BUFFER]; + const ab = buf.buffer.slice(buf.byteOffset, buf.byteOffset + buf.byteLength); + return Promise.resolve(ab); + } + stream() { + const readable = new Readable(); + readable._read = function () {}; + readable.push(this[BUFFER]); + readable.push(null); + return readable; + } + toString() { + return '[object Blob]'; + } + slice() { + const size = this.size; + + const start = arguments[0]; + const end = arguments[1]; + let relativeStart, relativeEnd; + if (start === undefined) { + relativeStart = 0; + } else if (start < 0) { + relativeStart = Math.max(size + start, 0); + } else { + relativeStart = Math.min(start, size); + } + if (end === undefined) { + relativeEnd = size; + } else if (end < 0) { + relativeEnd = Math.max(size + end, 0); + } else { + relativeEnd = Math.min(end, size); + } + const span = Math.max(relativeEnd - relativeStart, 0); + + const buffer = this[BUFFER]; + const slicedBuffer = buffer.slice(relativeStart, relativeStart + span); + const blob = new Blob([], { type: arguments[2] }); + blob[BUFFER] = slicedBuffer; + return blob; + } +} + +Object.defineProperties(Blob.prototype, { + size: { enumerable: true }, + type: { enumerable: true }, + slice: { enumerable: true } +}); + +Object.defineProperty(Blob.prototype, Symbol.toStringTag, { + value: 'Blob', + writable: false, + enumerable: false, + configurable: true +}); + +/** + * fetch-error.js + * + * FetchError interface for operational errors + */ + +/** + * Create FetchError instance + * + * @param String message Error message for human + * @param String type Error type for machine + * @param String systemError For Node.js system error + * @return FetchError + */ +function FetchError(message, type, systemError) { + Error.call(this, message); + + this.message = message; + this.type = type; + + // when err.type is `system`, err.code contains system error code + if (systemError) { + this.code = this.errno = systemError.code; + } + + // hide custom error implementation details from end-users + Error.captureStackTrace(this, this.constructor); +} + +FetchError.prototype = Object.create(Error.prototype); +FetchError.prototype.constructor = FetchError; +FetchError.prototype.name = 'FetchError'; + +let convert; +try { + convert = require('encoding').convert; +} catch (e) {} + +const INTERNALS = Symbol('Body internals'); + +// fix an issue where "PassThrough" isn't a named export for node <10 +const PassThrough = Stream.PassThrough; + +/** + * Body mixin + * + * Ref: https://fetch.spec.whatwg.org/#body + * + * @param Stream body Readable stream + * @param Object opts Response options + * @return Void + */ +function Body(body) { + var _this = this; + + var _ref = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {}, + _ref$size = _ref.size; + + let size = _ref$size === undefined ? 0 : _ref$size; + var _ref$timeout = _ref.timeout; + let timeout = _ref$timeout === undefined ? 0 : _ref$timeout; + + if (body == null) { + // body is undefined or null + body = null; + } else if (isURLSearchParams(body)) { + // body is a URLSearchParams + body = Buffer.from(body.toString()); + } else if (isBlob(body)) ; else if (Buffer.isBuffer(body)) ; else if (Object.prototype.toString.call(body) === '[object ArrayBuffer]') { + // body is ArrayBuffer + body = Buffer.from(body); + } else if (ArrayBuffer.isView(body)) { + // body is ArrayBufferView + body = Buffer.from(body.buffer, body.byteOffset, body.byteLength); + } else if (body instanceof Stream) ; else { + // none of the above + // coerce to string then buffer + body = Buffer.from(String(body)); + } + this[INTERNALS] = { + body, + disturbed: false, + error: null + }; + this.size = size; + this.timeout = timeout; + + if (body instanceof Stream) { + body.on('error', function (err) { + const error = err.name === 'AbortError' ? err : new FetchError(`Invalid response body while trying to fetch ${_this.url}: ${err.message}`, 'system', err); + _this[INTERNALS].error = error; + }); + } +} + +Body.prototype = { + get body() { + return this[INTERNALS].body; + }, + + get bodyUsed() { + return this[INTERNALS].disturbed; + }, + + /** + * Decode response as ArrayBuffer + * + * @return Promise + */ + arrayBuffer() { + return consumeBody.call(this).then(function (buf) { + return buf.buffer.slice(buf.byteOffset, buf.byteOffset + buf.byteLength); + }); + }, + + /** + * Return raw response as Blob + * + * @return Promise + */ + blob() { + let ct = this.headers && this.headers.get('content-type') || ''; + return consumeBody.call(this).then(function (buf) { + return Object.assign( + // Prevent copying + new Blob([], { + type: ct.toLowerCase() + }), { + [BUFFER]: buf + }); + }); + }, + + /** + * Decode response as json + * + * @return Promise + */ + json() { + var _this2 = this; + + return consumeBody.call(this).then(function (buffer) { + try { + return JSON.parse(buffer.toString()); + } catch (err) { + return Body.Promise.reject(new FetchError(`invalid json response body at ${_this2.url} reason: ${err.message}`, 'invalid-json')); + } + }); + }, + + /** + * Decode response as text + * + * @return Promise + */ + text() { + return consumeBody.call(this).then(function (buffer) { + return buffer.toString(); + }); + }, + + /** + * Decode response as buffer (non-spec api) + * + * @return Promise + */ + buffer() { + return consumeBody.call(this); + }, + + /** + * Decode response as text, while automatically detecting the encoding and + * trying to decode to UTF-8 (non-spec api) + * + * @return Promise + */ + textConverted() { + var _this3 = this; + + return consumeBody.call(this).then(function (buffer) { + return convertBody(buffer, _this3.headers); + }); + } +}; + +// In browsers, all properties are enumerable. +Object.defineProperties(Body.prototype, { + body: { enumerable: true }, + bodyUsed: { enumerable: true }, + arrayBuffer: { enumerable: true }, + blob: { enumerable: true }, + json: { enumerable: true }, + text: { enumerable: true } +}); + +Body.mixIn = function (proto) { + for (const name of Object.getOwnPropertyNames(Body.prototype)) { + // istanbul ignore else: future proof + if (!(name in proto)) { + const desc = Object.getOwnPropertyDescriptor(Body.prototype, name); + Object.defineProperty(proto, name, desc); + } + } +}; + +/** + * Consume and convert an entire Body to a Buffer. + * + * Ref: https://fetch.spec.whatwg.org/#concept-body-consume-body + * + * @return Promise + */ +function consumeBody() { + var _this4 = this; + + if (this[INTERNALS].disturbed) { + return Body.Promise.reject(new TypeError(`body used already for: ${this.url}`)); + } + + this[INTERNALS].disturbed = true; + + if (this[INTERNALS].error) { + return Body.Promise.reject(this[INTERNALS].error); + } + + let body = this.body; + + // body is null + if (body === null) { + return Body.Promise.resolve(Buffer.alloc(0)); + } + + // body is blob + if (isBlob(body)) { + body = body.stream(); + } + + // body is buffer + if (Buffer.isBuffer(body)) { + return Body.Promise.resolve(body); + } + + // istanbul ignore if: should never happen + if (!(body instanceof Stream)) { + return Body.Promise.resolve(Buffer.alloc(0)); + } + + // body is stream + // get ready to actually consume the body + let accum = []; + let accumBytes = 0; + let abort = false; + + return new Body.Promise(function (resolve, reject) { + let resTimeout; + + // allow timeout on slow response body + if (_this4.timeout) { + resTimeout = setTimeout(function () { + abort = true; + reject(new FetchError(`Response timeout while trying to fetch ${_this4.url} (over ${_this4.timeout}ms)`, 'body-timeout')); + }, _this4.timeout); + } + + // handle stream errors + body.on('error', function (err) { + if (err.name === 'AbortError') { + // if the request was aborted, reject with this Error + abort = true; + reject(err); + } else { + // other errors, such as incorrect content-encoding + reject(new FetchError(`Invalid response body while trying to fetch ${_this4.url}: ${err.message}`, 'system', err)); + } + }); + + body.on('data', function (chunk) { + if (abort || chunk === null) { + return; + } + + if (_this4.size && accumBytes + chunk.length > _this4.size) { + abort = true; + reject(new FetchError(`content size at ${_this4.url} over limit: ${_this4.size}`, 'max-size')); + return; + } + + accumBytes += chunk.length; + accum.push(chunk); + }); + + body.on('end', function () { + if (abort) { + return; + } + + clearTimeout(resTimeout); + + try { + resolve(Buffer.concat(accum, accumBytes)); + } catch (err) { + // handle streams that have accumulated too much data (issue #414) + reject(new FetchError(`Could not create Buffer from response body for ${_this4.url}: ${err.message}`, 'system', err)); + } + }); + }); +} + +/** + * Detect buffer encoding and convert to target encoding + * ref: http://www.w3.org/TR/2011/WD-html5-20110113/parsing.html#determining-the-character-encoding + * + * @param Buffer buffer Incoming buffer + * @param String encoding Target encoding + * @return String + */ +function convertBody(buffer, headers) { + if (typeof convert !== 'function') { + throw new Error('The package `encoding` must be installed to use the textConverted() function'); + } + + const ct = headers.get('content-type'); + let charset = 'utf-8'; + let res, str; + + // header + if (ct) { + res = /charset=([^;]*)/i.exec(ct); + } + + // no charset in content type, peek at response body for at most 1024 bytes + str = buffer.slice(0, 1024).toString(); + + // html5 + if (!res && str) { + res = / 0 && arguments[0] !== undefined ? arguments[0] : undefined; + + this[MAP] = Object.create(null); + + if (init instanceof Headers) { + const rawHeaders = init.raw(); + const headerNames = Object.keys(rawHeaders); + + for (const headerName of headerNames) { + for (const value of rawHeaders[headerName]) { + this.append(headerName, value); + } + } + + return; + } + + // We don't worry about converting prop to ByteString here as append() + // will handle it. + if (init == null) ; else if (typeof init === 'object') { + const method = init[Symbol.iterator]; + if (method != null) { + if (typeof method !== 'function') { + throw new TypeError('Header pairs must be iterable'); + } + + // sequence> + // Note: per spec we have to first exhaust the lists then process them + const pairs = []; + for (const pair of init) { + if (typeof pair !== 'object' || typeof pair[Symbol.iterator] !== 'function') { + throw new TypeError('Each header pair must be iterable'); + } + pairs.push(Array.from(pair)); + } + + for (const pair of pairs) { + if (pair.length !== 2) { + throw new TypeError('Each header pair must be a name/value tuple'); + } + this.append(pair[0], pair[1]); + } + } else { + // record + for (const key of Object.keys(init)) { + const value = init[key]; + this.append(key, value); + } + } + } else { + throw new TypeError('Provided initializer must be an object'); + } + } + + /** + * Return combined header value given name + * + * @param String name Header name + * @return Mixed + */ + get(name) { + name = `${name}`; + validateName(name); + const key = find(this[MAP], name); + if (key === undefined) { + return null; + } + + return this[MAP][key].join(', '); + } + + /** + * Iterate over all headers + * + * @param Function callback Executed for each item with parameters (value, name, thisArg) + * @param Boolean thisArg `this` context for callback function + * @return Void + */ + forEach(callback) { + let thisArg = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : undefined; + + let pairs = getHeaders(this); + let i = 0; + while (i < pairs.length) { + var _pairs$i = pairs[i]; + const name = _pairs$i[0], + value = _pairs$i[1]; + + callback.call(thisArg, value, name, this); + pairs = getHeaders(this); + i++; + } + } + + /** + * Overwrite header values given name + * + * @param String name Header name + * @param String value Header value + * @return Void + */ + set(name, value) { + name = `${name}`; + value = `${value}`; + validateName(name); + validateValue(value); + const key = find(this[MAP], name); + this[MAP][key !== undefined ? key : name] = [value]; + } + + /** + * Append a value onto existing header + * + * @param String name Header name + * @param String value Header value + * @return Void + */ + append(name, value) { + name = `${name}`; + value = `${value}`; + validateName(name); + validateValue(value); + const key = find(this[MAP], name); + if (key !== undefined) { + this[MAP][key].push(value); + } else { + this[MAP][name] = [value]; + } + } + + /** + * Check for header name existence + * + * @param String name Header name + * @return Boolean + */ + has(name) { + name = `${name}`; + validateName(name); + return find(this[MAP], name) !== undefined; + } + + /** + * Delete all header values given name + * + * @param String name Header name + * @return Void + */ + delete(name) { + name = `${name}`; + validateName(name); + const key = find(this[MAP], name); + if (key !== undefined) { + delete this[MAP][key]; + } + } + + /** + * Return raw headers (non-spec api) + * + * @return Object + */ + raw() { + return this[MAP]; + } + + /** + * Get an iterator on keys. + * + * @return Iterator + */ + keys() { + return createHeadersIterator(this, 'key'); + } + + /** + * Get an iterator on values. + * + * @return Iterator + */ + values() { + return createHeadersIterator(this, 'value'); + } + + /** + * Get an iterator on entries. + * + * This is the default iterator of the Headers object. + * + * @return Iterator + */ + [Symbol.iterator]() { + return createHeadersIterator(this, 'key+value'); + } +} +Headers.prototype.entries = Headers.prototype[Symbol.iterator]; + +Object.defineProperty(Headers.prototype, Symbol.toStringTag, { + value: 'Headers', + writable: false, + enumerable: false, + configurable: true +}); + +Object.defineProperties(Headers.prototype, { + get: { enumerable: true }, + forEach: { enumerable: true }, + set: { enumerable: true }, + append: { enumerable: true }, + has: { enumerable: true }, + delete: { enumerable: true }, + keys: { enumerable: true }, + values: { enumerable: true }, + entries: { enumerable: true } +}); + +function getHeaders(headers) { + let kind = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 'key+value'; + + const keys = Object.keys(headers[MAP]).sort(); + return keys.map(kind === 'key' ? function (k) { + return k.toLowerCase(); + } : kind === 'value' ? function (k) { + return headers[MAP][k].join(', '); + } : function (k) { + return [k.toLowerCase(), headers[MAP][k].join(', ')]; + }); +} + +const INTERNAL = Symbol('internal'); + +function createHeadersIterator(target, kind) { + const iterator = Object.create(HeadersIteratorPrototype); + iterator[INTERNAL] = { + target, + kind, + index: 0 + }; + return iterator; +} + +const HeadersIteratorPrototype = Object.setPrototypeOf({ + next() { + // istanbul ignore if + if (!this || Object.getPrototypeOf(this) !== HeadersIteratorPrototype) { + throw new TypeError('Value of `this` is not a HeadersIterator'); + } + + var _INTERNAL = this[INTERNAL]; + const target = _INTERNAL.target, + kind = _INTERNAL.kind, + index = _INTERNAL.index; + + const values = getHeaders(target, kind); + const len = values.length; + if (index >= len) { + return { + value: undefined, + done: true + }; + } + + this[INTERNAL].index = index + 1; + + return { + value: values[index], + done: false + }; + } +}, Object.getPrototypeOf(Object.getPrototypeOf([][Symbol.iterator]()))); + +Object.defineProperty(HeadersIteratorPrototype, Symbol.toStringTag, { + value: 'HeadersIterator', + writable: false, + enumerable: false, + configurable: true +}); + +/** + * Export the Headers object in a form that Node.js can consume. + * + * @param Headers headers + * @return Object + */ +function exportNodeCompatibleHeaders(headers) { + const obj = Object.assign({ __proto__: null }, headers[MAP]); + + // http.request() only supports string as Host header. This hack makes + // specifying custom Host header possible. + const hostHeaderKey = find(headers[MAP], 'Host'); + if (hostHeaderKey !== undefined) { + obj[hostHeaderKey] = obj[hostHeaderKey][0]; + } + + return obj; +} + +/** + * Create a Headers object from an object of headers, ignoring those that do + * not conform to HTTP grammar productions. + * + * @param Object obj Object of headers + * @return Headers + */ +function createHeadersLenient(obj) { + const headers = new Headers(); + for (const name of Object.keys(obj)) { + if (invalidTokenRegex.test(name)) { + continue; + } + if (Array.isArray(obj[name])) { + for (const val of obj[name]) { + if (invalidHeaderCharRegex.test(val)) { + continue; + } + if (headers[MAP][name] === undefined) { + headers[MAP][name] = [val]; + } else { + headers[MAP][name].push(val); + } + } + } else if (!invalidHeaderCharRegex.test(obj[name])) { + headers[MAP][name] = [obj[name]]; + } + } + return headers; +} + +const INTERNALS$1 = Symbol('Response internals'); + +// fix an issue where "STATUS_CODES" aren't a named export for node <10 +const STATUS_CODES = http.STATUS_CODES; + +/** + * Response class + * + * @param Stream body Readable stream + * @param Object opts Response options + * @return Void + */ +class Response { + constructor() { + let body = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : null; + let opts = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {}; + + Body.call(this, body, opts); + + const status = opts.status || 200; + const headers = new Headers(opts.headers); + + if (body != null && !headers.has('Content-Type')) { + const contentType = extractContentType(body); + if (contentType) { + headers.append('Content-Type', contentType); + } + } + + this[INTERNALS$1] = { + url: opts.url, + status, + statusText: opts.statusText || STATUS_CODES[status], + headers, + counter: opts.counter + }; + } + + get url() { + return this[INTERNALS$1].url || ''; + } + + get status() { + return this[INTERNALS$1].status; + } + + /** + * Convenience property representing if the request ended normally + */ + get ok() { + return this[INTERNALS$1].status >= 200 && this[INTERNALS$1].status < 300; + } + + get redirected() { + return this[INTERNALS$1].counter > 0; + } + + get statusText() { + return this[INTERNALS$1].statusText; + } + + get headers() { + return this[INTERNALS$1].headers; + } + + /** + * Clone this response + * + * @return Response + */ + clone() { + return new Response(clone(this), { + url: this.url, + status: this.status, + statusText: this.statusText, + headers: this.headers, + ok: this.ok, + redirected: this.redirected + }); + } +} + +Body.mixIn(Response.prototype); + +Object.defineProperties(Response.prototype, { + url: { enumerable: true }, + status: { enumerable: true }, + ok: { enumerable: true }, + redirected: { enumerable: true }, + statusText: { enumerable: true }, + headers: { enumerable: true }, + clone: { enumerable: true } +}); + +Object.defineProperty(Response.prototype, Symbol.toStringTag, { + value: 'Response', + writable: false, + enumerable: false, + configurable: true +}); + +const INTERNALS$2 = Symbol('Request internals'); +const URL = Url.URL || whatwgUrl.URL; + +// fix an issue where "format", "parse" aren't a named export for node <10 +const parse_url = Url.parse; +const format_url = Url.format; + +/** + * Wrapper around `new URL` to handle arbitrary URLs + * + * @param {string} urlStr + * @return {void} + */ +function parseURL(urlStr) { + /* + Check whether the URL is absolute or not + Scheme: https://tools.ietf.org/html/rfc3986#section-3.1 + Absolute URL: https://tools.ietf.org/html/rfc3986#section-4.3 + */ + if (/^[a-zA-Z][a-zA-Z\d+\-.]*:/.exec(urlStr)) { + urlStr = new URL(urlStr).toString(); + } + + // Fallback to old implementation for arbitrary URLs + return parse_url(urlStr); +} + +const streamDestructionSupported = 'destroy' in Stream.Readable.prototype; + +/** + * Check if a value is an instance of Request. + * + * @param Mixed input + * @return Boolean + */ +function isRequest(input) { + return typeof input === 'object' && typeof input[INTERNALS$2] === 'object'; +} + +function isAbortSignal(signal) { + const proto = signal && typeof signal === 'object' && Object.getPrototypeOf(signal); + return !!(proto && proto.constructor.name === 'AbortSignal'); +} + +/** + * Request class + * + * @param Mixed input Url or Request instance + * @param Object init Custom options + * @return Void + */ +class Request { + constructor(input) { + let init = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {}; + + let parsedURL; + + // normalize input + if (!isRequest(input)) { + if (input && input.href) { + // in order to support Node.js' Url objects; though WHATWG's URL objects + // will fall into this branch also (since their `toString()` will return + // `href` property anyway) + parsedURL = parseURL(input.href); + } else { + // coerce input to a string before attempting to parse + parsedURL = parseURL(`${input}`); + } + input = {}; + } else { + parsedURL = parseURL(input.url); + } + + let method = init.method || input.method || 'GET'; + method = method.toUpperCase(); + + if ((init.body != null || isRequest(input) && input.body !== null) && (method === 'GET' || method === 'HEAD')) { + throw new TypeError('Request with GET/HEAD method cannot have body'); + } + + let inputBody = init.body != null ? init.body : isRequest(input) && input.body !== null ? clone(input) : null; + + Body.call(this, inputBody, { + timeout: init.timeout || input.timeout || 0, + size: init.size || input.size || 0 + }); + + const headers = new Headers(init.headers || input.headers || {}); + + if (inputBody != null && !headers.has('Content-Type')) { + const contentType = extractContentType(inputBody); + if (contentType) { + headers.append('Content-Type', contentType); + } + } + + let signal = isRequest(input) ? input.signal : null; + if ('signal' in init) signal = init.signal; + + if (signal != null && !isAbortSignal(signal)) { + throw new TypeError('Expected signal to be an instanceof AbortSignal'); + } + + this[INTERNALS$2] = { + method, + redirect: init.redirect || input.redirect || 'follow', + headers, + parsedURL, + signal + }; + + // node-fetch-only options + this.follow = init.follow !== undefined ? init.follow : input.follow !== undefined ? input.follow : 20; + this.compress = init.compress !== undefined ? init.compress : input.compress !== undefined ? input.compress : true; + this.counter = init.counter || input.counter || 0; + this.agent = init.agent || input.agent; + } + + get method() { + return this[INTERNALS$2].method; + } + + get url() { + return format_url(this[INTERNALS$2].parsedURL); + } + + get headers() { + return this[INTERNALS$2].headers; + } + + get redirect() { + return this[INTERNALS$2].redirect; + } + + get signal() { + return this[INTERNALS$2].signal; + } + + /** + * Clone this request + * + * @return Request + */ + clone() { + return new Request(this); + } +} + +Body.mixIn(Request.prototype); + +Object.defineProperty(Request.prototype, Symbol.toStringTag, { + value: 'Request', + writable: false, + enumerable: false, + configurable: true +}); + +Object.defineProperties(Request.prototype, { + method: { enumerable: true }, + url: { enumerable: true }, + headers: { enumerable: true }, + redirect: { enumerable: true }, + clone: { enumerable: true }, + signal: { enumerable: true } +}); + +/** + * Convert a Request to Node.js http request options. + * + * @param Request A Request instance + * @return Object The options object to be passed to http.request + */ +function getNodeRequestOptions(request) { + const parsedURL = request[INTERNALS$2].parsedURL; + const headers = new Headers(request[INTERNALS$2].headers); + + // fetch step 1.3 + if (!headers.has('Accept')) { + headers.set('Accept', '*/*'); + } + + // Basic fetch + if (!parsedURL.protocol || !parsedURL.hostname) { + throw new TypeError('Only absolute URLs are supported'); + } + + if (!/^https?:$/.test(parsedURL.protocol)) { + throw new TypeError('Only HTTP(S) protocols are supported'); + } + + if (request.signal && request.body instanceof Stream.Readable && !streamDestructionSupported) { + throw new Error('Cancellation of streamed requests with AbortSignal is not supported in node < 8'); + } + + // HTTP-network-or-cache fetch steps 2.4-2.7 + let contentLengthValue = null; + if (request.body == null && /^(POST|PUT)$/i.test(request.method)) { + contentLengthValue = '0'; + } + if (request.body != null) { + const totalBytes = getTotalBytes(request); + if (typeof totalBytes === 'number') { + contentLengthValue = String(totalBytes); + } + } + if (contentLengthValue) { + headers.set('Content-Length', contentLengthValue); + } + + // HTTP-network-or-cache fetch step 2.11 + if (!headers.has('User-Agent')) { + headers.set('User-Agent', 'node-fetch/1.0 (+https://github.com/bitinn/node-fetch)'); + } + + // HTTP-network-or-cache fetch step 2.15 + if (request.compress && !headers.has('Accept-Encoding')) { + headers.set('Accept-Encoding', 'gzip,deflate'); + } + + let agent = request.agent; + if (typeof agent === 'function') { + agent = agent(parsedURL); + } + + // HTTP-network fetch step 4.2 + // chunked encoding is handled by Node.js + + return Object.assign({}, parsedURL, { + method: request.method, + headers: exportNodeCompatibleHeaders(headers), + agent + }); +} + +/** + * abort-error.js + * + * AbortError interface for cancelled requests + */ + +/** + * Create AbortError instance + * + * @param String message Error message for human + * @return AbortError + */ +function AbortError(message) { + Error.call(this, message); + + this.type = 'aborted'; + this.message = message; + + // hide custom error implementation details from end-users + Error.captureStackTrace(this, this.constructor); +} + +AbortError.prototype = Object.create(Error.prototype); +AbortError.prototype.constructor = AbortError; +AbortError.prototype.name = 'AbortError'; + +const URL$1 = Url.URL || whatwgUrl.URL; + +// fix an issue where "PassThrough", "resolve" aren't a named export for node <10 +const PassThrough$1 = Stream.PassThrough; + +const isDomainOrSubdomain = function isDomainOrSubdomain(destination, original) { + const orig = new URL$1(original).hostname; + const dest = new URL$1(destination).hostname; + + return orig === dest || orig[orig.length - dest.length - 1] === '.' && orig.endsWith(dest); +}; + +/** + * isSameProtocol reports whether the two provided URLs use the same protocol. + * + * Both domains must already be in canonical form. + * @param {string|URL} original + * @param {string|URL} destination + */ +const isSameProtocol = function isSameProtocol(destination, original) { + const orig = new URL$1(original).protocol; + const dest = new URL$1(destination).protocol; + + return orig === dest; +}; + +/** + * Fetch function + * + * @param Mixed url Absolute url or Request instance + * @param Object opts Fetch options + * @return Promise + */ +function fetch(url, opts) { + + // allow custom promise + if (!fetch.Promise) { + throw new Error('native promise missing, set fetch.Promise to your favorite alternative'); + } + + Body.Promise = fetch.Promise; + + // wrap http.request into fetch + return new fetch.Promise(function (resolve, reject) { + // build request object + const request = new Request(url, opts); + const options = getNodeRequestOptions(request); + + const send = (options.protocol === 'https:' ? https : http).request; + const signal = request.signal; + + let response = null; + + const abort = function abort() { + let error = new AbortError('The user aborted a request.'); + reject(error); + if (request.body && request.body instanceof Stream.Readable) { + destroyStream(request.body, error); + } + if (!response || !response.body) return; + response.body.emit('error', error); + }; + + if (signal && signal.aborted) { + abort(); + return; + } + + const abortAndFinalize = function abortAndFinalize() { + abort(); + finalize(); + }; + + // send request + const req = send(options); + let reqTimeout; + + if (signal) { + signal.addEventListener('abort', abortAndFinalize); + } + + function finalize() { + req.abort(); + if (signal) signal.removeEventListener('abort', abortAndFinalize); + clearTimeout(reqTimeout); + } + + if (request.timeout) { + req.once('socket', function (socket) { + reqTimeout = setTimeout(function () { + reject(new FetchError(`network timeout at: ${request.url}`, 'request-timeout')); + finalize(); + }, request.timeout); + }); + } + + req.on('error', function (err) { + reject(new FetchError(`request to ${request.url} failed, reason: ${err.message}`, 'system', err)); + + if (response && response.body) { + destroyStream(response.body, err); + } + + finalize(); + }); + + fixResponseChunkedTransferBadEnding(req, function (err) { + if (signal && signal.aborted) { + return; + } + + if (response && response.body) { + destroyStream(response.body, err); + } + }); + + /* c8 ignore next 18 */ + if (parseInt(process.version.substring(1)) < 14) { + // Before Node.js 14, pipeline() does not fully support async iterators and does not always + // properly handle when the socket close/end events are out of order. + req.on('socket', function (s) { + s.addListener('close', function (hadError) { + // if a data listener is still present we didn't end cleanly + const hasDataListener = s.listenerCount('data') > 0; + + // if end happened before close but the socket didn't emit an error, do it now + if (response && hasDataListener && !hadError && !(signal && signal.aborted)) { + const err = new Error('Premature close'); + err.code = 'ERR_STREAM_PREMATURE_CLOSE'; + response.body.emit('error', err); + } + }); + }); + } + + req.on('response', function (res) { + clearTimeout(reqTimeout); + + const headers = createHeadersLenient(res.headers); + + // HTTP fetch step 5 + if (fetch.isRedirect(res.statusCode)) { + // HTTP fetch step 5.2 + const location = headers.get('Location'); + + // HTTP fetch step 5.3 + let locationURL = null; + try { + locationURL = location === null ? null : new URL$1(location, request.url).toString(); + } catch (err) { + // error here can only be invalid URL in Location: header + // do not throw when options.redirect == manual + // let the user extract the errorneous redirect URL + if (request.redirect !== 'manual') { + reject(new FetchError(`uri requested responds with an invalid redirect URL: ${location}`, 'invalid-redirect')); + finalize(); + return; + } + } + + // HTTP fetch step 5.5 + switch (request.redirect) { + case 'error': + reject(new FetchError(`uri requested responds with a redirect, redirect mode is set to error: ${request.url}`, 'no-redirect')); + finalize(); + return; + case 'manual': + // node-fetch-specific step: make manual redirect a bit easier to use by setting the Location header value to the resolved URL. + if (locationURL !== null) { + // handle corrupted header + try { + headers.set('Location', locationURL); + } catch (err) { + // istanbul ignore next: nodejs server prevent invalid response headers, we can't test this through normal request + reject(err); + } + } + break; + case 'follow': + // HTTP-redirect fetch step 2 + if (locationURL === null) { + break; + } + + // HTTP-redirect fetch step 5 + if (request.counter >= request.follow) { + reject(new FetchError(`maximum redirect reached at: ${request.url}`, 'max-redirect')); + finalize(); + return; + } + + // HTTP-redirect fetch step 6 (counter increment) + // Create a new Request object. + const requestOpts = { + headers: new Headers(request.headers), + follow: request.follow, + counter: request.counter + 1, + agent: request.agent, + compress: request.compress, + method: request.method, + body: request.body, + signal: request.signal, + timeout: request.timeout, + size: request.size + }; + + if (!isDomainOrSubdomain(request.url, locationURL) || !isSameProtocol(request.url, locationURL)) { + for (const name of ['authorization', 'www-authenticate', 'cookie', 'cookie2']) { + requestOpts.headers.delete(name); + } + } + + // HTTP-redirect fetch step 9 + if (res.statusCode !== 303 && request.body && getTotalBytes(request) === null) { + reject(new FetchError('Cannot follow redirect with body being a readable stream', 'unsupported-redirect')); + finalize(); + return; + } + + // HTTP-redirect fetch step 11 + if (res.statusCode === 303 || (res.statusCode === 301 || res.statusCode === 302) && request.method === 'POST') { + requestOpts.method = 'GET'; + requestOpts.body = undefined; + requestOpts.headers.delete('content-length'); + } + + // HTTP-redirect fetch step 15 + resolve(fetch(new Request(locationURL, requestOpts))); + finalize(); + return; + } + } + + // prepare response + res.once('end', function () { + if (signal) signal.removeEventListener('abort', abortAndFinalize); + }); + let body = res.pipe(new PassThrough$1()); + + const response_options = { + url: request.url, + status: res.statusCode, + statusText: res.statusMessage, + headers: headers, + size: request.size, + timeout: request.timeout, + counter: request.counter + }; + + // HTTP-network fetch step 12.1.1.3 + const codings = headers.get('Content-Encoding'); + + // HTTP-network fetch step 12.1.1.4: handle content codings + + // in following scenarios we ignore compression support + // 1. compression support is disabled + // 2. HEAD request + // 3. no Content-Encoding header + // 4. no content response (204) + // 5. content not modified response (304) + if (!request.compress || request.method === 'HEAD' || codings === null || res.statusCode === 204 || res.statusCode === 304) { + response = new Response(body, response_options); + resolve(response); + return; + } + + // For Node v6+ + // Be less strict when decoding compressed responses, since sometimes + // servers send slightly invalid responses that are still accepted + // by common browsers. + // Always using Z_SYNC_FLUSH is what cURL does. + const zlibOptions = { + flush: zlib.Z_SYNC_FLUSH, + finishFlush: zlib.Z_SYNC_FLUSH + }; + + // for gzip + if (codings == 'gzip' || codings == 'x-gzip') { + body = body.pipe(zlib.createGunzip(zlibOptions)); + response = new Response(body, response_options); + resolve(response); + return; + } + + // for deflate + if (codings == 'deflate' || codings == 'x-deflate') { + // handle the infamous raw deflate response from old servers + // a hack for old IIS and Apache servers + const raw = res.pipe(new PassThrough$1()); + raw.once('data', function (chunk) { + // see http://stackoverflow.com/questions/37519828 + if ((chunk[0] & 0x0F) === 0x08) { + body = body.pipe(zlib.createInflate()); + } else { + body = body.pipe(zlib.createInflateRaw()); + } + response = new Response(body, response_options); + resolve(response); + }); + raw.on('end', function () { + // some old IIS servers return zero-length OK deflate responses, so 'data' is never emitted. + if (!response) { + response = new Response(body, response_options); + resolve(response); + } + }); + return; + } + + // for br + if (codings == 'br' && typeof zlib.createBrotliDecompress === 'function') { + body = body.pipe(zlib.createBrotliDecompress()); + response = new Response(body, response_options); + resolve(response); + return; + } + + // otherwise, use response as-is + response = new Response(body, response_options); + resolve(response); + }); + + writeToStream(req, request); + }); +} +function fixResponseChunkedTransferBadEnding(request, errorCallback) { + let socket; + + request.on('socket', function (s) { + socket = s; + }); + + request.on('response', function (response) { + const headers = response.headers; + + if (headers['transfer-encoding'] === 'chunked' && !headers['content-length']) { + response.once('close', function (hadError) { + // tests for socket presence, as in some situations the + // the 'socket' event is not triggered for the request + // (happens in deno), avoids `TypeError` + // if a data listener is still present we didn't end cleanly + const hasDataListener = socket && socket.listenerCount('data') > 0; + + if (hasDataListener && !hadError) { + const err = new Error('Premature close'); + err.code = 'ERR_STREAM_PREMATURE_CLOSE'; + errorCallback(err); + } + }); + } + }); +} + +function destroyStream(stream, err) { + if (stream.destroy) { + stream.destroy(err); + } else { + // node < 8 + stream.emit('error', err); + stream.end(); + } +} + +/** + * Redirect code matching + * + * @param Number code Status code + * @return Boolean + */ +fetch.isRedirect = function (code) { + return code === 301 || code === 302 || code === 303 || code === 307 || code === 308; +}; + +// expose Promise +fetch.Promise = global.Promise; + +export default fetch; +export { Headers, Request, Response, FetchError, AbortError }; diff --git a/node_modules/node-fetch/lib/index.js b/node_modules/node-fetch/lib/index.js new file mode 100644 index 00000000..567ff5da --- /dev/null +++ b/node_modules/node-fetch/lib/index.js @@ -0,0 +1,1787 @@ +'use strict'; + +Object.defineProperty(exports, '__esModule', { value: true }); + +function _interopDefault (ex) { return (ex && (typeof ex === 'object') && 'default' in ex) ? ex['default'] : ex; } + +var Stream = _interopDefault(require('stream')); +var http = _interopDefault(require('http')); +var Url = _interopDefault(require('url')); +var whatwgUrl = _interopDefault(require('whatwg-url')); +var https = _interopDefault(require('https')); +var zlib = _interopDefault(require('zlib')); + +// Based on https://github.com/tmpvar/jsdom/blob/aa85b2abf07766ff7bf5c1f6daafb3726f2f2db5/lib/jsdom/living/blob.js + +// fix for "Readable" isn't a named export issue +const Readable = Stream.Readable; + +const BUFFER = Symbol('buffer'); +const TYPE = Symbol('type'); + +class Blob { + constructor() { + this[TYPE] = ''; + + const blobParts = arguments[0]; + const options = arguments[1]; + + const buffers = []; + let size = 0; + + if (blobParts) { + const a = blobParts; + const length = Number(a.length); + for (let i = 0; i < length; i++) { + const element = a[i]; + let buffer; + if (element instanceof Buffer) { + buffer = element; + } else if (ArrayBuffer.isView(element)) { + buffer = Buffer.from(element.buffer, element.byteOffset, element.byteLength); + } else if (element instanceof ArrayBuffer) { + buffer = Buffer.from(element); + } else if (element instanceof Blob) { + buffer = element[BUFFER]; + } else { + buffer = Buffer.from(typeof element === 'string' ? element : String(element)); + } + size += buffer.length; + buffers.push(buffer); + } + } + + this[BUFFER] = Buffer.concat(buffers); + + let type = options && options.type !== undefined && String(options.type).toLowerCase(); + if (type && !/[^\u0020-\u007E]/.test(type)) { + this[TYPE] = type; + } + } + get size() { + return this[BUFFER].length; + } + get type() { + return this[TYPE]; + } + text() { + return Promise.resolve(this[BUFFER].toString()); + } + arrayBuffer() { + const buf = this[BUFFER]; + const ab = buf.buffer.slice(buf.byteOffset, buf.byteOffset + buf.byteLength); + return Promise.resolve(ab); + } + stream() { + const readable = new Readable(); + readable._read = function () {}; + readable.push(this[BUFFER]); + readable.push(null); + return readable; + } + toString() { + return '[object Blob]'; + } + slice() { + const size = this.size; + + const start = arguments[0]; + const end = arguments[1]; + let relativeStart, relativeEnd; + if (start === undefined) { + relativeStart = 0; + } else if (start < 0) { + relativeStart = Math.max(size + start, 0); + } else { + relativeStart = Math.min(start, size); + } + if (end === undefined) { + relativeEnd = size; + } else if (end < 0) { + relativeEnd = Math.max(size + end, 0); + } else { + relativeEnd = Math.min(end, size); + } + const span = Math.max(relativeEnd - relativeStart, 0); + + const buffer = this[BUFFER]; + const slicedBuffer = buffer.slice(relativeStart, relativeStart + span); + const blob = new Blob([], { type: arguments[2] }); + blob[BUFFER] = slicedBuffer; + return blob; + } +} + +Object.defineProperties(Blob.prototype, { + size: { enumerable: true }, + type: { enumerable: true }, + slice: { enumerable: true } +}); + +Object.defineProperty(Blob.prototype, Symbol.toStringTag, { + value: 'Blob', + writable: false, + enumerable: false, + configurable: true +}); + +/** + * fetch-error.js + * + * FetchError interface for operational errors + */ + +/** + * Create FetchError instance + * + * @param String message Error message for human + * @param String type Error type for machine + * @param String systemError For Node.js system error + * @return FetchError + */ +function FetchError(message, type, systemError) { + Error.call(this, message); + + this.message = message; + this.type = type; + + // when err.type is `system`, err.code contains system error code + if (systemError) { + this.code = this.errno = systemError.code; + } + + // hide custom error implementation details from end-users + Error.captureStackTrace(this, this.constructor); +} + +FetchError.prototype = Object.create(Error.prototype); +FetchError.prototype.constructor = FetchError; +FetchError.prototype.name = 'FetchError'; + +let convert; +try { + convert = require('encoding').convert; +} catch (e) {} + +const INTERNALS = Symbol('Body internals'); + +// fix an issue where "PassThrough" isn't a named export for node <10 +const PassThrough = Stream.PassThrough; + +/** + * Body mixin + * + * Ref: https://fetch.spec.whatwg.org/#body + * + * @param Stream body Readable stream + * @param Object opts Response options + * @return Void + */ +function Body(body) { + var _this = this; + + var _ref = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {}, + _ref$size = _ref.size; + + let size = _ref$size === undefined ? 0 : _ref$size; + var _ref$timeout = _ref.timeout; + let timeout = _ref$timeout === undefined ? 0 : _ref$timeout; + + if (body == null) { + // body is undefined or null + body = null; + } else if (isURLSearchParams(body)) { + // body is a URLSearchParams + body = Buffer.from(body.toString()); + } else if (isBlob(body)) ; else if (Buffer.isBuffer(body)) ; else if (Object.prototype.toString.call(body) === '[object ArrayBuffer]') { + // body is ArrayBuffer + body = Buffer.from(body); + } else if (ArrayBuffer.isView(body)) { + // body is ArrayBufferView + body = Buffer.from(body.buffer, body.byteOffset, body.byteLength); + } else if (body instanceof Stream) ; else { + // none of the above + // coerce to string then buffer + body = Buffer.from(String(body)); + } + this[INTERNALS] = { + body, + disturbed: false, + error: null + }; + this.size = size; + this.timeout = timeout; + + if (body instanceof Stream) { + body.on('error', function (err) { + const error = err.name === 'AbortError' ? err : new FetchError(`Invalid response body while trying to fetch ${_this.url}: ${err.message}`, 'system', err); + _this[INTERNALS].error = error; + }); + } +} + +Body.prototype = { + get body() { + return this[INTERNALS].body; + }, + + get bodyUsed() { + return this[INTERNALS].disturbed; + }, + + /** + * Decode response as ArrayBuffer + * + * @return Promise + */ + arrayBuffer() { + return consumeBody.call(this).then(function (buf) { + return buf.buffer.slice(buf.byteOffset, buf.byteOffset + buf.byteLength); + }); + }, + + /** + * Return raw response as Blob + * + * @return Promise + */ + blob() { + let ct = this.headers && this.headers.get('content-type') || ''; + return consumeBody.call(this).then(function (buf) { + return Object.assign( + // Prevent copying + new Blob([], { + type: ct.toLowerCase() + }), { + [BUFFER]: buf + }); + }); + }, + + /** + * Decode response as json + * + * @return Promise + */ + json() { + var _this2 = this; + + return consumeBody.call(this).then(function (buffer) { + try { + return JSON.parse(buffer.toString()); + } catch (err) { + return Body.Promise.reject(new FetchError(`invalid json response body at ${_this2.url} reason: ${err.message}`, 'invalid-json')); + } + }); + }, + + /** + * Decode response as text + * + * @return Promise + */ + text() { + return consumeBody.call(this).then(function (buffer) { + return buffer.toString(); + }); + }, + + /** + * Decode response as buffer (non-spec api) + * + * @return Promise + */ + buffer() { + return consumeBody.call(this); + }, + + /** + * Decode response as text, while automatically detecting the encoding and + * trying to decode to UTF-8 (non-spec api) + * + * @return Promise + */ + textConverted() { + var _this3 = this; + + return consumeBody.call(this).then(function (buffer) { + return convertBody(buffer, _this3.headers); + }); + } +}; + +// In browsers, all properties are enumerable. +Object.defineProperties(Body.prototype, { + body: { enumerable: true }, + bodyUsed: { enumerable: true }, + arrayBuffer: { enumerable: true }, + blob: { enumerable: true }, + json: { enumerable: true }, + text: { enumerable: true } +}); + +Body.mixIn = function (proto) { + for (const name of Object.getOwnPropertyNames(Body.prototype)) { + // istanbul ignore else: future proof + if (!(name in proto)) { + const desc = Object.getOwnPropertyDescriptor(Body.prototype, name); + Object.defineProperty(proto, name, desc); + } + } +}; + +/** + * Consume and convert an entire Body to a Buffer. + * + * Ref: https://fetch.spec.whatwg.org/#concept-body-consume-body + * + * @return Promise + */ +function consumeBody() { + var _this4 = this; + + if (this[INTERNALS].disturbed) { + return Body.Promise.reject(new TypeError(`body used already for: ${this.url}`)); + } + + this[INTERNALS].disturbed = true; + + if (this[INTERNALS].error) { + return Body.Promise.reject(this[INTERNALS].error); + } + + let body = this.body; + + // body is null + if (body === null) { + return Body.Promise.resolve(Buffer.alloc(0)); + } + + // body is blob + if (isBlob(body)) { + body = body.stream(); + } + + // body is buffer + if (Buffer.isBuffer(body)) { + return Body.Promise.resolve(body); + } + + // istanbul ignore if: should never happen + if (!(body instanceof Stream)) { + return Body.Promise.resolve(Buffer.alloc(0)); + } + + // body is stream + // get ready to actually consume the body + let accum = []; + let accumBytes = 0; + let abort = false; + + return new Body.Promise(function (resolve, reject) { + let resTimeout; + + // allow timeout on slow response body + if (_this4.timeout) { + resTimeout = setTimeout(function () { + abort = true; + reject(new FetchError(`Response timeout while trying to fetch ${_this4.url} (over ${_this4.timeout}ms)`, 'body-timeout')); + }, _this4.timeout); + } + + // handle stream errors + body.on('error', function (err) { + if (err.name === 'AbortError') { + // if the request was aborted, reject with this Error + abort = true; + reject(err); + } else { + // other errors, such as incorrect content-encoding + reject(new FetchError(`Invalid response body while trying to fetch ${_this4.url}: ${err.message}`, 'system', err)); + } + }); + + body.on('data', function (chunk) { + if (abort || chunk === null) { + return; + } + + if (_this4.size && accumBytes + chunk.length > _this4.size) { + abort = true; + reject(new FetchError(`content size at ${_this4.url} over limit: ${_this4.size}`, 'max-size')); + return; + } + + accumBytes += chunk.length; + accum.push(chunk); + }); + + body.on('end', function () { + if (abort) { + return; + } + + clearTimeout(resTimeout); + + try { + resolve(Buffer.concat(accum, accumBytes)); + } catch (err) { + // handle streams that have accumulated too much data (issue #414) + reject(new FetchError(`Could not create Buffer from response body for ${_this4.url}: ${err.message}`, 'system', err)); + } + }); + }); +} + +/** + * Detect buffer encoding and convert to target encoding + * ref: http://www.w3.org/TR/2011/WD-html5-20110113/parsing.html#determining-the-character-encoding + * + * @param Buffer buffer Incoming buffer + * @param String encoding Target encoding + * @return String + */ +function convertBody(buffer, headers) { + if (typeof convert !== 'function') { + throw new Error('The package `encoding` must be installed to use the textConverted() function'); + } + + const ct = headers.get('content-type'); + let charset = 'utf-8'; + let res, str; + + // header + if (ct) { + res = /charset=([^;]*)/i.exec(ct); + } + + // no charset in content type, peek at response body for at most 1024 bytes + str = buffer.slice(0, 1024).toString(); + + // html5 + if (!res && str) { + res = / 0 && arguments[0] !== undefined ? arguments[0] : undefined; + + this[MAP] = Object.create(null); + + if (init instanceof Headers) { + const rawHeaders = init.raw(); + const headerNames = Object.keys(rawHeaders); + + for (const headerName of headerNames) { + for (const value of rawHeaders[headerName]) { + this.append(headerName, value); + } + } + + return; + } + + // We don't worry about converting prop to ByteString here as append() + // will handle it. + if (init == null) ; else if (typeof init === 'object') { + const method = init[Symbol.iterator]; + if (method != null) { + if (typeof method !== 'function') { + throw new TypeError('Header pairs must be iterable'); + } + + // sequence> + // Note: per spec we have to first exhaust the lists then process them + const pairs = []; + for (const pair of init) { + if (typeof pair !== 'object' || typeof pair[Symbol.iterator] !== 'function') { + throw new TypeError('Each header pair must be iterable'); + } + pairs.push(Array.from(pair)); + } + + for (const pair of pairs) { + if (pair.length !== 2) { + throw new TypeError('Each header pair must be a name/value tuple'); + } + this.append(pair[0], pair[1]); + } + } else { + // record + for (const key of Object.keys(init)) { + const value = init[key]; + this.append(key, value); + } + } + } else { + throw new TypeError('Provided initializer must be an object'); + } + } + + /** + * Return combined header value given name + * + * @param String name Header name + * @return Mixed + */ + get(name) { + name = `${name}`; + validateName(name); + const key = find(this[MAP], name); + if (key === undefined) { + return null; + } + + return this[MAP][key].join(', '); + } + + /** + * Iterate over all headers + * + * @param Function callback Executed for each item with parameters (value, name, thisArg) + * @param Boolean thisArg `this` context for callback function + * @return Void + */ + forEach(callback) { + let thisArg = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : undefined; + + let pairs = getHeaders(this); + let i = 0; + while (i < pairs.length) { + var _pairs$i = pairs[i]; + const name = _pairs$i[0], + value = _pairs$i[1]; + + callback.call(thisArg, value, name, this); + pairs = getHeaders(this); + i++; + } + } + + /** + * Overwrite header values given name + * + * @param String name Header name + * @param String value Header value + * @return Void + */ + set(name, value) { + name = `${name}`; + value = `${value}`; + validateName(name); + validateValue(value); + const key = find(this[MAP], name); + this[MAP][key !== undefined ? key : name] = [value]; + } + + /** + * Append a value onto existing header + * + * @param String name Header name + * @param String value Header value + * @return Void + */ + append(name, value) { + name = `${name}`; + value = `${value}`; + validateName(name); + validateValue(value); + const key = find(this[MAP], name); + if (key !== undefined) { + this[MAP][key].push(value); + } else { + this[MAP][name] = [value]; + } + } + + /** + * Check for header name existence + * + * @param String name Header name + * @return Boolean + */ + has(name) { + name = `${name}`; + validateName(name); + return find(this[MAP], name) !== undefined; + } + + /** + * Delete all header values given name + * + * @param String name Header name + * @return Void + */ + delete(name) { + name = `${name}`; + validateName(name); + const key = find(this[MAP], name); + if (key !== undefined) { + delete this[MAP][key]; + } + } + + /** + * Return raw headers (non-spec api) + * + * @return Object + */ + raw() { + return this[MAP]; + } + + /** + * Get an iterator on keys. + * + * @return Iterator + */ + keys() { + return createHeadersIterator(this, 'key'); + } + + /** + * Get an iterator on values. + * + * @return Iterator + */ + values() { + return createHeadersIterator(this, 'value'); + } + + /** + * Get an iterator on entries. + * + * This is the default iterator of the Headers object. + * + * @return Iterator + */ + [Symbol.iterator]() { + return createHeadersIterator(this, 'key+value'); + } +} +Headers.prototype.entries = Headers.prototype[Symbol.iterator]; + +Object.defineProperty(Headers.prototype, Symbol.toStringTag, { + value: 'Headers', + writable: false, + enumerable: false, + configurable: true +}); + +Object.defineProperties(Headers.prototype, { + get: { enumerable: true }, + forEach: { enumerable: true }, + set: { enumerable: true }, + append: { enumerable: true }, + has: { enumerable: true }, + delete: { enumerable: true }, + keys: { enumerable: true }, + values: { enumerable: true }, + entries: { enumerable: true } +}); + +function getHeaders(headers) { + let kind = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 'key+value'; + + const keys = Object.keys(headers[MAP]).sort(); + return keys.map(kind === 'key' ? function (k) { + return k.toLowerCase(); + } : kind === 'value' ? function (k) { + return headers[MAP][k].join(', '); + } : function (k) { + return [k.toLowerCase(), headers[MAP][k].join(', ')]; + }); +} + +const INTERNAL = Symbol('internal'); + +function createHeadersIterator(target, kind) { + const iterator = Object.create(HeadersIteratorPrototype); + iterator[INTERNAL] = { + target, + kind, + index: 0 + }; + return iterator; +} + +const HeadersIteratorPrototype = Object.setPrototypeOf({ + next() { + // istanbul ignore if + if (!this || Object.getPrototypeOf(this) !== HeadersIteratorPrototype) { + throw new TypeError('Value of `this` is not a HeadersIterator'); + } + + var _INTERNAL = this[INTERNAL]; + const target = _INTERNAL.target, + kind = _INTERNAL.kind, + index = _INTERNAL.index; + + const values = getHeaders(target, kind); + const len = values.length; + if (index >= len) { + return { + value: undefined, + done: true + }; + } + + this[INTERNAL].index = index + 1; + + return { + value: values[index], + done: false + }; + } +}, Object.getPrototypeOf(Object.getPrototypeOf([][Symbol.iterator]()))); + +Object.defineProperty(HeadersIteratorPrototype, Symbol.toStringTag, { + value: 'HeadersIterator', + writable: false, + enumerable: false, + configurable: true +}); + +/** + * Export the Headers object in a form that Node.js can consume. + * + * @param Headers headers + * @return Object + */ +function exportNodeCompatibleHeaders(headers) { + const obj = Object.assign({ __proto__: null }, headers[MAP]); + + // http.request() only supports string as Host header. This hack makes + // specifying custom Host header possible. + const hostHeaderKey = find(headers[MAP], 'Host'); + if (hostHeaderKey !== undefined) { + obj[hostHeaderKey] = obj[hostHeaderKey][0]; + } + + return obj; +} + +/** + * Create a Headers object from an object of headers, ignoring those that do + * not conform to HTTP grammar productions. + * + * @param Object obj Object of headers + * @return Headers + */ +function createHeadersLenient(obj) { + const headers = new Headers(); + for (const name of Object.keys(obj)) { + if (invalidTokenRegex.test(name)) { + continue; + } + if (Array.isArray(obj[name])) { + for (const val of obj[name]) { + if (invalidHeaderCharRegex.test(val)) { + continue; + } + if (headers[MAP][name] === undefined) { + headers[MAP][name] = [val]; + } else { + headers[MAP][name].push(val); + } + } + } else if (!invalidHeaderCharRegex.test(obj[name])) { + headers[MAP][name] = [obj[name]]; + } + } + return headers; +} + +const INTERNALS$1 = Symbol('Response internals'); + +// fix an issue where "STATUS_CODES" aren't a named export for node <10 +const STATUS_CODES = http.STATUS_CODES; + +/** + * Response class + * + * @param Stream body Readable stream + * @param Object opts Response options + * @return Void + */ +class Response { + constructor() { + let body = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : null; + let opts = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {}; + + Body.call(this, body, opts); + + const status = opts.status || 200; + const headers = new Headers(opts.headers); + + if (body != null && !headers.has('Content-Type')) { + const contentType = extractContentType(body); + if (contentType) { + headers.append('Content-Type', contentType); + } + } + + this[INTERNALS$1] = { + url: opts.url, + status, + statusText: opts.statusText || STATUS_CODES[status], + headers, + counter: opts.counter + }; + } + + get url() { + return this[INTERNALS$1].url || ''; + } + + get status() { + return this[INTERNALS$1].status; + } + + /** + * Convenience property representing if the request ended normally + */ + get ok() { + return this[INTERNALS$1].status >= 200 && this[INTERNALS$1].status < 300; + } + + get redirected() { + return this[INTERNALS$1].counter > 0; + } + + get statusText() { + return this[INTERNALS$1].statusText; + } + + get headers() { + return this[INTERNALS$1].headers; + } + + /** + * Clone this response + * + * @return Response + */ + clone() { + return new Response(clone(this), { + url: this.url, + status: this.status, + statusText: this.statusText, + headers: this.headers, + ok: this.ok, + redirected: this.redirected + }); + } +} + +Body.mixIn(Response.prototype); + +Object.defineProperties(Response.prototype, { + url: { enumerable: true }, + status: { enumerable: true }, + ok: { enumerable: true }, + redirected: { enumerable: true }, + statusText: { enumerable: true }, + headers: { enumerable: true }, + clone: { enumerable: true } +}); + +Object.defineProperty(Response.prototype, Symbol.toStringTag, { + value: 'Response', + writable: false, + enumerable: false, + configurable: true +}); + +const INTERNALS$2 = Symbol('Request internals'); +const URL = Url.URL || whatwgUrl.URL; + +// fix an issue where "format", "parse" aren't a named export for node <10 +const parse_url = Url.parse; +const format_url = Url.format; + +/** + * Wrapper around `new URL` to handle arbitrary URLs + * + * @param {string} urlStr + * @return {void} + */ +function parseURL(urlStr) { + /* + Check whether the URL is absolute or not + Scheme: https://tools.ietf.org/html/rfc3986#section-3.1 + Absolute URL: https://tools.ietf.org/html/rfc3986#section-4.3 + */ + if (/^[a-zA-Z][a-zA-Z\d+\-.]*:/.exec(urlStr)) { + urlStr = new URL(urlStr).toString(); + } + + // Fallback to old implementation for arbitrary URLs + return parse_url(urlStr); +} + +const streamDestructionSupported = 'destroy' in Stream.Readable.prototype; + +/** + * Check if a value is an instance of Request. + * + * @param Mixed input + * @return Boolean + */ +function isRequest(input) { + return typeof input === 'object' && typeof input[INTERNALS$2] === 'object'; +} + +function isAbortSignal(signal) { + const proto = signal && typeof signal === 'object' && Object.getPrototypeOf(signal); + return !!(proto && proto.constructor.name === 'AbortSignal'); +} + +/** + * Request class + * + * @param Mixed input Url or Request instance + * @param Object init Custom options + * @return Void + */ +class Request { + constructor(input) { + let init = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {}; + + let parsedURL; + + // normalize input + if (!isRequest(input)) { + if (input && input.href) { + // in order to support Node.js' Url objects; though WHATWG's URL objects + // will fall into this branch also (since their `toString()` will return + // `href` property anyway) + parsedURL = parseURL(input.href); + } else { + // coerce input to a string before attempting to parse + parsedURL = parseURL(`${input}`); + } + input = {}; + } else { + parsedURL = parseURL(input.url); + } + + let method = init.method || input.method || 'GET'; + method = method.toUpperCase(); + + if ((init.body != null || isRequest(input) && input.body !== null) && (method === 'GET' || method === 'HEAD')) { + throw new TypeError('Request with GET/HEAD method cannot have body'); + } + + let inputBody = init.body != null ? init.body : isRequest(input) && input.body !== null ? clone(input) : null; + + Body.call(this, inputBody, { + timeout: init.timeout || input.timeout || 0, + size: init.size || input.size || 0 + }); + + const headers = new Headers(init.headers || input.headers || {}); + + if (inputBody != null && !headers.has('Content-Type')) { + const contentType = extractContentType(inputBody); + if (contentType) { + headers.append('Content-Type', contentType); + } + } + + let signal = isRequest(input) ? input.signal : null; + if ('signal' in init) signal = init.signal; + + if (signal != null && !isAbortSignal(signal)) { + throw new TypeError('Expected signal to be an instanceof AbortSignal'); + } + + this[INTERNALS$2] = { + method, + redirect: init.redirect || input.redirect || 'follow', + headers, + parsedURL, + signal + }; + + // node-fetch-only options + this.follow = init.follow !== undefined ? init.follow : input.follow !== undefined ? input.follow : 20; + this.compress = init.compress !== undefined ? init.compress : input.compress !== undefined ? input.compress : true; + this.counter = init.counter || input.counter || 0; + this.agent = init.agent || input.agent; + } + + get method() { + return this[INTERNALS$2].method; + } + + get url() { + return format_url(this[INTERNALS$2].parsedURL); + } + + get headers() { + return this[INTERNALS$2].headers; + } + + get redirect() { + return this[INTERNALS$2].redirect; + } + + get signal() { + return this[INTERNALS$2].signal; + } + + /** + * Clone this request + * + * @return Request + */ + clone() { + return new Request(this); + } +} + +Body.mixIn(Request.prototype); + +Object.defineProperty(Request.prototype, Symbol.toStringTag, { + value: 'Request', + writable: false, + enumerable: false, + configurable: true +}); + +Object.defineProperties(Request.prototype, { + method: { enumerable: true }, + url: { enumerable: true }, + headers: { enumerable: true }, + redirect: { enumerable: true }, + clone: { enumerable: true }, + signal: { enumerable: true } +}); + +/** + * Convert a Request to Node.js http request options. + * + * @param Request A Request instance + * @return Object The options object to be passed to http.request + */ +function getNodeRequestOptions(request) { + const parsedURL = request[INTERNALS$2].parsedURL; + const headers = new Headers(request[INTERNALS$2].headers); + + // fetch step 1.3 + if (!headers.has('Accept')) { + headers.set('Accept', '*/*'); + } + + // Basic fetch + if (!parsedURL.protocol || !parsedURL.hostname) { + throw new TypeError('Only absolute URLs are supported'); + } + + if (!/^https?:$/.test(parsedURL.protocol)) { + throw new TypeError('Only HTTP(S) protocols are supported'); + } + + if (request.signal && request.body instanceof Stream.Readable && !streamDestructionSupported) { + throw new Error('Cancellation of streamed requests with AbortSignal is not supported in node < 8'); + } + + // HTTP-network-or-cache fetch steps 2.4-2.7 + let contentLengthValue = null; + if (request.body == null && /^(POST|PUT)$/i.test(request.method)) { + contentLengthValue = '0'; + } + if (request.body != null) { + const totalBytes = getTotalBytes(request); + if (typeof totalBytes === 'number') { + contentLengthValue = String(totalBytes); + } + } + if (contentLengthValue) { + headers.set('Content-Length', contentLengthValue); + } + + // HTTP-network-or-cache fetch step 2.11 + if (!headers.has('User-Agent')) { + headers.set('User-Agent', 'node-fetch/1.0 (+https://github.com/bitinn/node-fetch)'); + } + + // HTTP-network-or-cache fetch step 2.15 + if (request.compress && !headers.has('Accept-Encoding')) { + headers.set('Accept-Encoding', 'gzip,deflate'); + } + + let agent = request.agent; + if (typeof agent === 'function') { + agent = agent(parsedURL); + } + + // HTTP-network fetch step 4.2 + // chunked encoding is handled by Node.js + + return Object.assign({}, parsedURL, { + method: request.method, + headers: exportNodeCompatibleHeaders(headers), + agent + }); +} + +/** + * abort-error.js + * + * AbortError interface for cancelled requests + */ + +/** + * Create AbortError instance + * + * @param String message Error message for human + * @return AbortError + */ +function AbortError(message) { + Error.call(this, message); + + this.type = 'aborted'; + this.message = message; + + // hide custom error implementation details from end-users + Error.captureStackTrace(this, this.constructor); +} + +AbortError.prototype = Object.create(Error.prototype); +AbortError.prototype.constructor = AbortError; +AbortError.prototype.name = 'AbortError'; + +const URL$1 = Url.URL || whatwgUrl.URL; + +// fix an issue where "PassThrough", "resolve" aren't a named export for node <10 +const PassThrough$1 = Stream.PassThrough; + +const isDomainOrSubdomain = function isDomainOrSubdomain(destination, original) { + const orig = new URL$1(original).hostname; + const dest = new URL$1(destination).hostname; + + return orig === dest || orig[orig.length - dest.length - 1] === '.' && orig.endsWith(dest); +}; + +/** + * isSameProtocol reports whether the two provided URLs use the same protocol. + * + * Both domains must already be in canonical form. + * @param {string|URL} original + * @param {string|URL} destination + */ +const isSameProtocol = function isSameProtocol(destination, original) { + const orig = new URL$1(original).protocol; + const dest = new URL$1(destination).protocol; + + return orig === dest; +}; + +/** + * Fetch function + * + * @param Mixed url Absolute url or Request instance + * @param Object opts Fetch options + * @return Promise + */ +function fetch(url, opts) { + + // allow custom promise + if (!fetch.Promise) { + throw new Error('native promise missing, set fetch.Promise to your favorite alternative'); + } + + Body.Promise = fetch.Promise; + + // wrap http.request into fetch + return new fetch.Promise(function (resolve, reject) { + // build request object + const request = new Request(url, opts); + const options = getNodeRequestOptions(request); + + const send = (options.protocol === 'https:' ? https : http).request; + const signal = request.signal; + + let response = null; + + const abort = function abort() { + let error = new AbortError('The user aborted a request.'); + reject(error); + if (request.body && request.body instanceof Stream.Readable) { + destroyStream(request.body, error); + } + if (!response || !response.body) return; + response.body.emit('error', error); + }; + + if (signal && signal.aborted) { + abort(); + return; + } + + const abortAndFinalize = function abortAndFinalize() { + abort(); + finalize(); + }; + + // send request + const req = send(options); + let reqTimeout; + + if (signal) { + signal.addEventListener('abort', abortAndFinalize); + } + + function finalize() { + req.abort(); + if (signal) signal.removeEventListener('abort', abortAndFinalize); + clearTimeout(reqTimeout); + } + + if (request.timeout) { + req.once('socket', function (socket) { + reqTimeout = setTimeout(function () { + reject(new FetchError(`network timeout at: ${request.url}`, 'request-timeout')); + finalize(); + }, request.timeout); + }); + } + + req.on('error', function (err) { + reject(new FetchError(`request to ${request.url} failed, reason: ${err.message}`, 'system', err)); + + if (response && response.body) { + destroyStream(response.body, err); + } + + finalize(); + }); + + fixResponseChunkedTransferBadEnding(req, function (err) { + if (signal && signal.aborted) { + return; + } + + if (response && response.body) { + destroyStream(response.body, err); + } + }); + + /* c8 ignore next 18 */ + if (parseInt(process.version.substring(1)) < 14) { + // Before Node.js 14, pipeline() does not fully support async iterators and does not always + // properly handle when the socket close/end events are out of order. + req.on('socket', function (s) { + s.addListener('close', function (hadError) { + // if a data listener is still present we didn't end cleanly + const hasDataListener = s.listenerCount('data') > 0; + + // if end happened before close but the socket didn't emit an error, do it now + if (response && hasDataListener && !hadError && !(signal && signal.aborted)) { + const err = new Error('Premature close'); + err.code = 'ERR_STREAM_PREMATURE_CLOSE'; + response.body.emit('error', err); + } + }); + }); + } + + req.on('response', function (res) { + clearTimeout(reqTimeout); + + const headers = createHeadersLenient(res.headers); + + // HTTP fetch step 5 + if (fetch.isRedirect(res.statusCode)) { + // HTTP fetch step 5.2 + const location = headers.get('Location'); + + // HTTP fetch step 5.3 + let locationURL = null; + try { + locationURL = location === null ? null : new URL$1(location, request.url).toString(); + } catch (err) { + // error here can only be invalid URL in Location: header + // do not throw when options.redirect == manual + // let the user extract the errorneous redirect URL + if (request.redirect !== 'manual') { + reject(new FetchError(`uri requested responds with an invalid redirect URL: ${location}`, 'invalid-redirect')); + finalize(); + return; + } + } + + // HTTP fetch step 5.5 + switch (request.redirect) { + case 'error': + reject(new FetchError(`uri requested responds with a redirect, redirect mode is set to error: ${request.url}`, 'no-redirect')); + finalize(); + return; + case 'manual': + // node-fetch-specific step: make manual redirect a bit easier to use by setting the Location header value to the resolved URL. + if (locationURL !== null) { + // handle corrupted header + try { + headers.set('Location', locationURL); + } catch (err) { + // istanbul ignore next: nodejs server prevent invalid response headers, we can't test this through normal request + reject(err); + } + } + break; + case 'follow': + // HTTP-redirect fetch step 2 + if (locationURL === null) { + break; + } + + // HTTP-redirect fetch step 5 + if (request.counter >= request.follow) { + reject(new FetchError(`maximum redirect reached at: ${request.url}`, 'max-redirect')); + finalize(); + return; + } + + // HTTP-redirect fetch step 6 (counter increment) + // Create a new Request object. + const requestOpts = { + headers: new Headers(request.headers), + follow: request.follow, + counter: request.counter + 1, + agent: request.agent, + compress: request.compress, + method: request.method, + body: request.body, + signal: request.signal, + timeout: request.timeout, + size: request.size + }; + + if (!isDomainOrSubdomain(request.url, locationURL) || !isSameProtocol(request.url, locationURL)) { + for (const name of ['authorization', 'www-authenticate', 'cookie', 'cookie2']) { + requestOpts.headers.delete(name); + } + } + + // HTTP-redirect fetch step 9 + if (res.statusCode !== 303 && request.body && getTotalBytes(request) === null) { + reject(new FetchError('Cannot follow redirect with body being a readable stream', 'unsupported-redirect')); + finalize(); + return; + } + + // HTTP-redirect fetch step 11 + if (res.statusCode === 303 || (res.statusCode === 301 || res.statusCode === 302) && request.method === 'POST') { + requestOpts.method = 'GET'; + requestOpts.body = undefined; + requestOpts.headers.delete('content-length'); + } + + // HTTP-redirect fetch step 15 + resolve(fetch(new Request(locationURL, requestOpts))); + finalize(); + return; + } + } + + // prepare response + res.once('end', function () { + if (signal) signal.removeEventListener('abort', abortAndFinalize); + }); + let body = res.pipe(new PassThrough$1()); + + const response_options = { + url: request.url, + status: res.statusCode, + statusText: res.statusMessage, + headers: headers, + size: request.size, + timeout: request.timeout, + counter: request.counter + }; + + // HTTP-network fetch step 12.1.1.3 + const codings = headers.get('Content-Encoding'); + + // HTTP-network fetch step 12.1.1.4: handle content codings + + // in following scenarios we ignore compression support + // 1. compression support is disabled + // 2. HEAD request + // 3. no Content-Encoding header + // 4. no content response (204) + // 5. content not modified response (304) + if (!request.compress || request.method === 'HEAD' || codings === null || res.statusCode === 204 || res.statusCode === 304) { + response = new Response(body, response_options); + resolve(response); + return; + } + + // For Node v6+ + // Be less strict when decoding compressed responses, since sometimes + // servers send slightly invalid responses that are still accepted + // by common browsers. + // Always using Z_SYNC_FLUSH is what cURL does. + const zlibOptions = { + flush: zlib.Z_SYNC_FLUSH, + finishFlush: zlib.Z_SYNC_FLUSH + }; + + // for gzip + if (codings == 'gzip' || codings == 'x-gzip') { + body = body.pipe(zlib.createGunzip(zlibOptions)); + response = new Response(body, response_options); + resolve(response); + return; + } + + // for deflate + if (codings == 'deflate' || codings == 'x-deflate') { + // handle the infamous raw deflate response from old servers + // a hack for old IIS and Apache servers + const raw = res.pipe(new PassThrough$1()); + raw.once('data', function (chunk) { + // see http://stackoverflow.com/questions/37519828 + if ((chunk[0] & 0x0F) === 0x08) { + body = body.pipe(zlib.createInflate()); + } else { + body = body.pipe(zlib.createInflateRaw()); + } + response = new Response(body, response_options); + resolve(response); + }); + raw.on('end', function () { + // some old IIS servers return zero-length OK deflate responses, so 'data' is never emitted. + if (!response) { + response = new Response(body, response_options); + resolve(response); + } + }); + return; + } + + // for br + if (codings == 'br' && typeof zlib.createBrotliDecompress === 'function') { + body = body.pipe(zlib.createBrotliDecompress()); + response = new Response(body, response_options); + resolve(response); + return; + } + + // otherwise, use response as-is + response = new Response(body, response_options); + resolve(response); + }); + + writeToStream(req, request); + }); +} +function fixResponseChunkedTransferBadEnding(request, errorCallback) { + let socket; + + request.on('socket', function (s) { + socket = s; + }); + + request.on('response', function (response) { + const headers = response.headers; + + if (headers['transfer-encoding'] === 'chunked' && !headers['content-length']) { + response.once('close', function (hadError) { + // tests for socket presence, as in some situations the + // the 'socket' event is not triggered for the request + // (happens in deno), avoids `TypeError` + // if a data listener is still present we didn't end cleanly + const hasDataListener = socket && socket.listenerCount('data') > 0; + + if (hasDataListener && !hadError) { + const err = new Error('Premature close'); + err.code = 'ERR_STREAM_PREMATURE_CLOSE'; + errorCallback(err); + } + }); + } + }); +} + +function destroyStream(stream, err) { + if (stream.destroy) { + stream.destroy(err); + } else { + // node < 8 + stream.emit('error', err); + stream.end(); + } +} + +/** + * Redirect code matching + * + * @param Number code Status code + * @return Boolean + */ +fetch.isRedirect = function (code) { + return code === 301 || code === 302 || code === 303 || code === 307 || code === 308; +}; + +// expose Promise +fetch.Promise = global.Promise; + +module.exports = exports = fetch; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.default = exports; +exports.Headers = Headers; +exports.Request = Request; +exports.Response = Response; +exports.FetchError = FetchError; +exports.AbortError = AbortError; diff --git a/node_modules/node-fetch/lib/index.mjs b/node_modules/node-fetch/lib/index.mjs new file mode 100644 index 00000000..2863dd9c --- /dev/null +++ b/node_modules/node-fetch/lib/index.mjs @@ -0,0 +1,1775 @@ +import Stream from 'stream'; +import http from 'http'; +import Url from 'url'; +import whatwgUrl from 'whatwg-url'; +import https from 'https'; +import zlib from 'zlib'; + +// Based on https://github.com/tmpvar/jsdom/blob/aa85b2abf07766ff7bf5c1f6daafb3726f2f2db5/lib/jsdom/living/blob.js + +// fix for "Readable" isn't a named export issue +const Readable = Stream.Readable; + +const BUFFER = Symbol('buffer'); +const TYPE = Symbol('type'); + +class Blob { + constructor() { + this[TYPE] = ''; + + const blobParts = arguments[0]; + const options = arguments[1]; + + const buffers = []; + let size = 0; + + if (blobParts) { + const a = blobParts; + const length = Number(a.length); + for (let i = 0; i < length; i++) { + const element = a[i]; + let buffer; + if (element instanceof Buffer) { + buffer = element; + } else if (ArrayBuffer.isView(element)) { + buffer = Buffer.from(element.buffer, element.byteOffset, element.byteLength); + } else if (element instanceof ArrayBuffer) { + buffer = Buffer.from(element); + } else if (element instanceof Blob) { + buffer = element[BUFFER]; + } else { + buffer = Buffer.from(typeof element === 'string' ? element : String(element)); + } + size += buffer.length; + buffers.push(buffer); + } + } + + this[BUFFER] = Buffer.concat(buffers); + + let type = options && options.type !== undefined && String(options.type).toLowerCase(); + if (type && !/[^\u0020-\u007E]/.test(type)) { + this[TYPE] = type; + } + } + get size() { + return this[BUFFER].length; + } + get type() { + return this[TYPE]; + } + text() { + return Promise.resolve(this[BUFFER].toString()); + } + arrayBuffer() { + const buf = this[BUFFER]; + const ab = buf.buffer.slice(buf.byteOffset, buf.byteOffset + buf.byteLength); + return Promise.resolve(ab); + } + stream() { + const readable = new Readable(); + readable._read = function () {}; + readable.push(this[BUFFER]); + readable.push(null); + return readable; + } + toString() { + return '[object Blob]'; + } + slice() { + const size = this.size; + + const start = arguments[0]; + const end = arguments[1]; + let relativeStart, relativeEnd; + if (start === undefined) { + relativeStart = 0; + } else if (start < 0) { + relativeStart = Math.max(size + start, 0); + } else { + relativeStart = Math.min(start, size); + } + if (end === undefined) { + relativeEnd = size; + } else if (end < 0) { + relativeEnd = Math.max(size + end, 0); + } else { + relativeEnd = Math.min(end, size); + } + const span = Math.max(relativeEnd - relativeStart, 0); + + const buffer = this[BUFFER]; + const slicedBuffer = buffer.slice(relativeStart, relativeStart + span); + const blob = new Blob([], { type: arguments[2] }); + blob[BUFFER] = slicedBuffer; + return blob; + } +} + +Object.defineProperties(Blob.prototype, { + size: { enumerable: true }, + type: { enumerable: true }, + slice: { enumerable: true } +}); + +Object.defineProperty(Blob.prototype, Symbol.toStringTag, { + value: 'Blob', + writable: false, + enumerable: false, + configurable: true +}); + +/** + * fetch-error.js + * + * FetchError interface for operational errors + */ + +/** + * Create FetchError instance + * + * @param String message Error message for human + * @param String type Error type for machine + * @param String systemError For Node.js system error + * @return FetchError + */ +function FetchError(message, type, systemError) { + Error.call(this, message); + + this.message = message; + this.type = type; + + // when err.type is `system`, err.code contains system error code + if (systemError) { + this.code = this.errno = systemError.code; + } + + // hide custom error implementation details from end-users + Error.captureStackTrace(this, this.constructor); +} + +FetchError.prototype = Object.create(Error.prototype); +FetchError.prototype.constructor = FetchError; +FetchError.prototype.name = 'FetchError'; + +let convert; +try { + convert = require('encoding').convert; +} catch (e) {} + +const INTERNALS = Symbol('Body internals'); + +// fix an issue where "PassThrough" isn't a named export for node <10 +const PassThrough = Stream.PassThrough; + +/** + * Body mixin + * + * Ref: https://fetch.spec.whatwg.org/#body + * + * @param Stream body Readable stream + * @param Object opts Response options + * @return Void + */ +function Body(body) { + var _this = this; + + var _ref = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {}, + _ref$size = _ref.size; + + let size = _ref$size === undefined ? 0 : _ref$size; + var _ref$timeout = _ref.timeout; + let timeout = _ref$timeout === undefined ? 0 : _ref$timeout; + + if (body == null) { + // body is undefined or null + body = null; + } else if (isURLSearchParams(body)) { + // body is a URLSearchParams + body = Buffer.from(body.toString()); + } else if (isBlob(body)) ; else if (Buffer.isBuffer(body)) ; else if (Object.prototype.toString.call(body) === '[object ArrayBuffer]') { + // body is ArrayBuffer + body = Buffer.from(body); + } else if (ArrayBuffer.isView(body)) { + // body is ArrayBufferView + body = Buffer.from(body.buffer, body.byteOffset, body.byteLength); + } else if (body instanceof Stream) ; else { + // none of the above + // coerce to string then buffer + body = Buffer.from(String(body)); + } + this[INTERNALS] = { + body, + disturbed: false, + error: null + }; + this.size = size; + this.timeout = timeout; + + if (body instanceof Stream) { + body.on('error', function (err) { + const error = err.name === 'AbortError' ? err : new FetchError(`Invalid response body while trying to fetch ${_this.url}: ${err.message}`, 'system', err); + _this[INTERNALS].error = error; + }); + } +} + +Body.prototype = { + get body() { + return this[INTERNALS].body; + }, + + get bodyUsed() { + return this[INTERNALS].disturbed; + }, + + /** + * Decode response as ArrayBuffer + * + * @return Promise + */ + arrayBuffer() { + return consumeBody.call(this).then(function (buf) { + return buf.buffer.slice(buf.byteOffset, buf.byteOffset + buf.byteLength); + }); + }, + + /** + * Return raw response as Blob + * + * @return Promise + */ + blob() { + let ct = this.headers && this.headers.get('content-type') || ''; + return consumeBody.call(this).then(function (buf) { + return Object.assign( + // Prevent copying + new Blob([], { + type: ct.toLowerCase() + }), { + [BUFFER]: buf + }); + }); + }, + + /** + * Decode response as json + * + * @return Promise + */ + json() { + var _this2 = this; + + return consumeBody.call(this).then(function (buffer) { + try { + return JSON.parse(buffer.toString()); + } catch (err) { + return Body.Promise.reject(new FetchError(`invalid json response body at ${_this2.url} reason: ${err.message}`, 'invalid-json')); + } + }); + }, + + /** + * Decode response as text + * + * @return Promise + */ + text() { + return consumeBody.call(this).then(function (buffer) { + return buffer.toString(); + }); + }, + + /** + * Decode response as buffer (non-spec api) + * + * @return Promise + */ + buffer() { + return consumeBody.call(this); + }, + + /** + * Decode response as text, while automatically detecting the encoding and + * trying to decode to UTF-8 (non-spec api) + * + * @return Promise + */ + textConverted() { + var _this3 = this; + + return consumeBody.call(this).then(function (buffer) { + return convertBody(buffer, _this3.headers); + }); + } +}; + +// In browsers, all properties are enumerable. +Object.defineProperties(Body.prototype, { + body: { enumerable: true }, + bodyUsed: { enumerable: true }, + arrayBuffer: { enumerable: true }, + blob: { enumerable: true }, + json: { enumerable: true }, + text: { enumerable: true } +}); + +Body.mixIn = function (proto) { + for (const name of Object.getOwnPropertyNames(Body.prototype)) { + // istanbul ignore else: future proof + if (!(name in proto)) { + const desc = Object.getOwnPropertyDescriptor(Body.prototype, name); + Object.defineProperty(proto, name, desc); + } + } +}; + +/** + * Consume and convert an entire Body to a Buffer. + * + * Ref: https://fetch.spec.whatwg.org/#concept-body-consume-body + * + * @return Promise + */ +function consumeBody() { + var _this4 = this; + + if (this[INTERNALS].disturbed) { + return Body.Promise.reject(new TypeError(`body used already for: ${this.url}`)); + } + + this[INTERNALS].disturbed = true; + + if (this[INTERNALS].error) { + return Body.Promise.reject(this[INTERNALS].error); + } + + let body = this.body; + + // body is null + if (body === null) { + return Body.Promise.resolve(Buffer.alloc(0)); + } + + // body is blob + if (isBlob(body)) { + body = body.stream(); + } + + // body is buffer + if (Buffer.isBuffer(body)) { + return Body.Promise.resolve(body); + } + + // istanbul ignore if: should never happen + if (!(body instanceof Stream)) { + return Body.Promise.resolve(Buffer.alloc(0)); + } + + // body is stream + // get ready to actually consume the body + let accum = []; + let accumBytes = 0; + let abort = false; + + return new Body.Promise(function (resolve, reject) { + let resTimeout; + + // allow timeout on slow response body + if (_this4.timeout) { + resTimeout = setTimeout(function () { + abort = true; + reject(new FetchError(`Response timeout while trying to fetch ${_this4.url} (over ${_this4.timeout}ms)`, 'body-timeout')); + }, _this4.timeout); + } + + // handle stream errors + body.on('error', function (err) { + if (err.name === 'AbortError') { + // if the request was aborted, reject with this Error + abort = true; + reject(err); + } else { + // other errors, such as incorrect content-encoding + reject(new FetchError(`Invalid response body while trying to fetch ${_this4.url}: ${err.message}`, 'system', err)); + } + }); + + body.on('data', function (chunk) { + if (abort || chunk === null) { + return; + } + + if (_this4.size && accumBytes + chunk.length > _this4.size) { + abort = true; + reject(new FetchError(`content size at ${_this4.url} over limit: ${_this4.size}`, 'max-size')); + return; + } + + accumBytes += chunk.length; + accum.push(chunk); + }); + + body.on('end', function () { + if (abort) { + return; + } + + clearTimeout(resTimeout); + + try { + resolve(Buffer.concat(accum, accumBytes)); + } catch (err) { + // handle streams that have accumulated too much data (issue #414) + reject(new FetchError(`Could not create Buffer from response body for ${_this4.url}: ${err.message}`, 'system', err)); + } + }); + }); +} + +/** + * Detect buffer encoding and convert to target encoding + * ref: http://www.w3.org/TR/2011/WD-html5-20110113/parsing.html#determining-the-character-encoding + * + * @param Buffer buffer Incoming buffer + * @param String encoding Target encoding + * @return String + */ +function convertBody(buffer, headers) { + if (typeof convert !== 'function') { + throw new Error('The package `encoding` must be installed to use the textConverted() function'); + } + + const ct = headers.get('content-type'); + let charset = 'utf-8'; + let res, str; + + // header + if (ct) { + res = /charset=([^;]*)/i.exec(ct); + } + + // no charset in content type, peek at response body for at most 1024 bytes + str = buffer.slice(0, 1024).toString(); + + // html5 + if (!res && str) { + res = / 0 && arguments[0] !== undefined ? arguments[0] : undefined; + + this[MAP] = Object.create(null); + + if (init instanceof Headers) { + const rawHeaders = init.raw(); + const headerNames = Object.keys(rawHeaders); + + for (const headerName of headerNames) { + for (const value of rawHeaders[headerName]) { + this.append(headerName, value); + } + } + + return; + } + + // We don't worry about converting prop to ByteString here as append() + // will handle it. + if (init == null) ; else if (typeof init === 'object') { + const method = init[Symbol.iterator]; + if (method != null) { + if (typeof method !== 'function') { + throw new TypeError('Header pairs must be iterable'); + } + + // sequence> + // Note: per spec we have to first exhaust the lists then process them + const pairs = []; + for (const pair of init) { + if (typeof pair !== 'object' || typeof pair[Symbol.iterator] !== 'function') { + throw new TypeError('Each header pair must be iterable'); + } + pairs.push(Array.from(pair)); + } + + for (const pair of pairs) { + if (pair.length !== 2) { + throw new TypeError('Each header pair must be a name/value tuple'); + } + this.append(pair[0], pair[1]); + } + } else { + // record + for (const key of Object.keys(init)) { + const value = init[key]; + this.append(key, value); + } + } + } else { + throw new TypeError('Provided initializer must be an object'); + } + } + + /** + * Return combined header value given name + * + * @param String name Header name + * @return Mixed + */ + get(name) { + name = `${name}`; + validateName(name); + const key = find(this[MAP], name); + if (key === undefined) { + return null; + } + + return this[MAP][key].join(', '); + } + + /** + * Iterate over all headers + * + * @param Function callback Executed for each item with parameters (value, name, thisArg) + * @param Boolean thisArg `this` context for callback function + * @return Void + */ + forEach(callback) { + let thisArg = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : undefined; + + let pairs = getHeaders(this); + let i = 0; + while (i < pairs.length) { + var _pairs$i = pairs[i]; + const name = _pairs$i[0], + value = _pairs$i[1]; + + callback.call(thisArg, value, name, this); + pairs = getHeaders(this); + i++; + } + } + + /** + * Overwrite header values given name + * + * @param String name Header name + * @param String value Header value + * @return Void + */ + set(name, value) { + name = `${name}`; + value = `${value}`; + validateName(name); + validateValue(value); + const key = find(this[MAP], name); + this[MAP][key !== undefined ? key : name] = [value]; + } + + /** + * Append a value onto existing header + * + * @param String name Header name + * @param String value Header value + * @return Void + */ + append(name, value) { + name = `${name}`; + value = `${value}`; + validateName(name); + validateValue(value); + const key = find(this[MAP], name); + if (key !== undefined) { + this[MAP][key].push(value); + } else { + this[MAP][name] = [value]; + } + } + + /** + * Check for header name existence + * + * @param String name Header name + * @return Boolean + */ + has(name) { + name = `${name}`; + validateName(name); + return find(this[MAP], name) !== undefined; + } + + /** + * Delete all header values given name + * + * @param String name Header name + * @return Void + */ + delete(name) { + name = `${name}`; + validateName(name); + const key = find(this[MAP], name); + if (key !== undefined) { + delete this[MAP][key]; + } + } + + /** + * Return raw headers (non-spec api) + * + * @return Object + */ + raw() { + return this[MAP]; + } + + /** + * Get an iterator on keys. + * + * @return Iterator + */ + keys() { + return createHeadersIterator(this, 'key'); + } + + /** + * Get an iterator on values. + * + * @return Iterator + */ + values() { + return createHeadersIterator(this, 'value'); + } + + /** + * Get an iterator on entries. + * + * This is the default iterator of the Headers object. + * + * @return Iterator + */ + [Symbol.iterator]() { + return createHeadersIterator(this, 'key+value'); + } +} +Headers.prototype.entries = Headers.prototype[Symbol.iterator]; + +Object.defineProperty(Headers.prototype, Symbol.toStringTag, { + value: 'Headers', + writable: false, + enumerable: false, + configurable: true +}); + +Object.defineProperties(Headers.prototype, { + get: { enumerable: true }, + forEach: { enumerable: true }, + set: { enumerable: true }, + append: { enumerable: true }, + has: { enumerable: true }, + delete: { enumerable: true }, + keys: { enumerable: true }, + values: { enumerable: true }, + entries: { enumerable: true } +}); + +function getHeaders(headers) { + let kind = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 'key+value'; + + const keys = Object.keys(headers[MAP]).sort(); + return keys.map(kind === 'key' ? function (k) { + return k.toLowerCase(); + } : kind === 'value' ? function (k) { + return headers[MAP][k].join(', '); + } : function (k) { + return [k.toLowerCase(), headers[MAP][k].join(', ')]; + }); +} + +const INTERNAL = Symbol('internal'); + +function createHeadersIterator(target, kind) { + const iterator = Object.create(HeadersIteratorPrototype); + iterator[INTERNAL] = { + target, + kind, + index: 0 + }; + return iterator; +} + +const HeadersIteratorPrototype = Object.setPrototypeOf({ + next() { + // istanbul ignore if + if (!this || Object.getPrototypeOf(this) !== HeadersIteratorPrototype) { + throw new TypeError('Value of `this` is not a HeadersIterator'); + } + + var _INTERNAL = this[INTERNAL]; + const target = _INTERNAL.target, + kind = _INTERNAL.kind, + index = _INTERNAL.index; + + const values = getHeaders(target, kind); + const len = values.length; + if (index >= len) { + return { + value: undefined, + done: true + }; + } + + this[INTERNAL].index = index + 1; + + return { + value: values[index], + done: false + }; + } +}, Object.getPrototypeOf(Object.getPrototypeOf([][Symbol.iterator]()))); + +Object.defineProperty(HeadersIteratorPrototype, Symbol.toStringTag, { + value: 'HeadersIterator', + writable: false, + enumerable: false, + configurable: true +}); + +/** + * Export the Headers object in a form that Node.js can consume. + * + * @param Headers headers + * @return Object + */ +function exportNodeCompatibleHeaders(headers) { + const obj = Object.assign({ __proto__: null }, headers[MAP]); + + // http.request() only supports string as Host header. This hack makes + // specifying custom Host header possible. + const hostHeaderKey = find(headers[MAP], 'Host'); + if (hostHeaderKey !== undefined) { + obj[hostHeaderKey] = obj[hostHeaderKey][0]; + } + + return obj; +} + +/** + * Create a Headers object from an object of headers, ignoring those that do + * not conform to HTTP grammar productions. + * + * @param Object obj Object of headers + * @return Headers + */ +function createHeadersLenient(obj) { + const headers = new Headers(); + for (const name of Object.keys(obj)) { + if (invalidTokenRegex.test(name)) { + continue; + } + if (Array.isArray(obj[name])) { + for (const val of obj[name]) { + if (invalidHeaderCharRegex.test(val)) { + continue; + } + if (headers[MAP][name] === undefined) { + headers[MAP][name] = [val]; + } else { + headers[MAP][name].push(val); + } + } + } else if (!invalidHeaderCharRegex.test(obj[name])) { + headers[MAP][name] = [obj[name]]; + } + } + return headers; +} + +const INTERNALS$1 = Symbol('Response internals'); + +// fix an issue where "STATUS_CODES" aren't a named export for node <10 +const STATUS_CODES = http.STATUS_CODES; + +/** + * Response class + * + * @param Stream body Readable stream + * @param Object opts Response options + * @return Void + */ +class Response { + constructor() { + let body = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : null; + let opts = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {}; + + Body.call(this, body, opts); + + const status = opts.status || 200; + const headers = new Headers(opts.headers); + + if (body != null && !headers.has('Content-Type')) { + const contentType = extractContentType(body); + if (contentType) { + headers.append('Content-Type', contentType); + } + } + + this[INTERNALS$1] = { + url: opts.url, + status, + statusText: opts.statusText || STATUS_CODES[status], + headers, + counter: opts.counter + }; + } + + get url() { + return this[INTERNALS$1].url || ''; + } + + get status() { + return this[INTERNALS$1].status; + } + + /** + * Convenience property representing if the request ended normally + */ + get ok() { + return this[INTERNALS$1].status >= 200 && this[INTERNALS$1].status < 300; + } + + get redirected() { + return this[INTERNALS$1].counter > 0; + } + + get statusText() { + return this[INTERNALS$1].statusText; + } + + get headers() { + return this[INTERNALS$1].headers; + } + + /** + * Clone this response + * + * @return Response + */ + clone() { + return new Response(clone(this), { + url: this.url, + status: this.status, + statusText: this.statusText, + headers: this.headers, + ok: this.ok, + redirected: this.redirected + }); + } +} + +Body.mixIn(Response.prototype); + +Object.defineProperties(Response.prototype, { + url: { enumerable: true }, + status: { enumerable: true }, + ok: { enumerable: true }, + redirected: { enumerable: true }, + statusText: { enumerable: true }, + headers: { enumerable: true }, + clone: { enumerable: true } +}); + +Object.defineProperty(Response.prototype, Symbol.toStringTag, { + value: 'Response', + writable: false, + enumerable: false, + configurable: true +}); + +const INTERNALS$2 = Symbol('Request internals'); +const URL = Url.URL || whatwgUrl.URL; + +// fix an issue where "format", "parse" aren't a named export for node <10 +const parse_url = Url.parse; +const format_url = Url.format; + +/** + * Wrapper around `new URL` to handle arbitrary URLs + * + * @param {string} urlStr + * @return {void} + */ +function parseURL(urlStr) { + /* + Check whether the URL is absolute or not + Scheme: https://tools.ietf.org/html/rfc3986#section-3.1 + Absolute URL: https://tools.ietf.org/html/rfc3986#section-4.3 + */ + if (/^[a-zA-Z][a-zA-Z\d+\-.]*:/.exec(urlStr)) { + urlStr = new URL(urlStr).toString(); + } + + // Fallback to old implementation for arbitrary URLs + return parse_url(urlStr); +} + +const streamDestructionSupported = 'destroy' in Stream.Readable.prototype; + +/** + * Check if a value is an instance of Request. + * + * @param Mixed input + * @return Boolean + */ +function isRequest(input) { + return typeof input === 'object' && typeof input[INTERNALS$2] === 'object'; +} + +function isAbortSignal(signal) { + const proto = signal && typeof signal === 'object' && Object.getPrototypeOf(signal); + return !!(proto && proto.constructor.name === 'AbortSignal'); +} + +/** + * Request class + * + * @param Mixed input Url or Request instance + * @param Object init Custom options + * @return Void + */ +class Request { + constructor(input) { + let init = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {}; + + let parsedURL; + + // normalize input + if (!isRequest(input)) { + if (input && input.href) { + // in order to support Node.js' Url objects; though WHATWG's URL objects + // will fall into this branch also (since their `toString()` will return + // `href` property anyway) + parsedURL = parseURL(input.href); + } else { + // coerce input to a string before attempting to parse + parsedURL = parseURL(`${input}`); + } + input = {}; + } else { + parsedURL = parseURL(input.url); + } + + let method = init.method || input.method || 'GET'; + method = method.toUpperCase(); + + if ((init.body != null || isRequest(input) && input.body !== null) && (method === 'GET' || method === 'HEAD')) { + throw new TypeError('Request with GET/HEAD method cannot have body'); + } + + let inputBody = init.body != null ? init.body : isRequest(input) && input.body !== null ? clone(input) : null; + + Body.call(this, inputBody, { + timeout: init.timeout || input.timeout || 0, + size: init.size || input.size || 0 + }); + + const headers = new Headers(init.headers || input.headers || {}); + + if (inputBody != null && !headers.has('Content-Type')) { + const contentType = extractContentType(inputBody); + if (contentType) { + headers.append('Content-Type', contentType); + } + } + + let signal = isRequest(input) ? input.signal : null; + if ('signal' in init) signal = init.signal; + + if (signal != null && !isAbortSignal(signal)) { + throw new TypeError('Expected signal to be an instanceof AbortSignal'); + } + + this[INTERNALS$2] = { + method, + redirect: init.redirect || input.redirect || 'follow', + headers, + parsedURL, + signal + }; + + // node-fetch-only options + this.follow = init.follow !== undefined ? init.follow : input.follow !== undefined ? input.follow : 20; + this.compress = init.compress !== undefined ? init.compress : input.compress !== undefined ? input.compress : true; + this.counter = init.counter || input.counter || 0; + this.agent = init.agent || input.agent; + } + + get method() { + return this[INTERNALS$2].method; + } + + get url() { + return format_url(this[INTERNALS$2].parsedURL); + } + + get headers() { + return this[INTERNALS$2].headers; + } + + get redirect() { + return this[INTERNALS$2].redirect; + } + + get signal() { + return this[INTERNALS$2].signal; + } + + /** + * Clone this request + * + * @return Request + */ + clone() { + return new Request(this); + } +} + +Body.mixIn(Request.prototype); + +Object.defineProperty(Request.prototype, Symbol.toStringTag, { + value: 'Request', + writable: false, + enumerable: false, + configurable: true +}); + +Object.defineProperties(Request.prototype, { + method: { enumerable: true }, + url: { enumerable: true }, + headers: { enumerable: true }, + redirect: { enumerable: true }, + clone: { enumerable: true }, + signal: { enumerable: true } +}); + +/** + * Convert a Request to Node.js http request options. + * + * @param Request A Request instance + * @return Object The options object to be passed to http.request + */ +function getNodeRequestOptions(request) { + const parsedURL = request[INTERNALS$2].parsedURL; + const headers = new Headers(request[INTERNALS$2].headers); + + // fetch step 1.3 + if (!headers.has('Accept')) { + headers.set('Accept', '*/*'); + } + + // Basic fetch + if (!parsedURL.protocol || !parsedURL.hostname) { + throw new TypeError('Only absolute URLs are supported'); + } + + if (!/^https?:$/.test(parsedURL.protocol)) { + throw new TypeError('Only HTTP(S) protocols are supported'); + } + + if (request.signal && request.body instanceof Stream.Readable && !streamDestructionSupported) { + throw new Error('Cancellation of streamed requests with AbortSignal is not supported in node < 8'); + } + + // HTTP-network-or-cache fetch steps 2.4-2.7 + let contentLengthValue = null; + if (request.body == null && /^(POST|PUT)$/i.test(request.method)) { + contentLengthValue = '0'; + } + if (request.body != null) { + const totalBytes = getTotalBytes(request); + if (typeof totalBytes === 'number') { + contentLengthValue = String(totalBytes); + } + } + if (contentLengthValue) { + headers.set('Content-Length', contentLengthValue); + } + + // HTTP-network-or-cache fetch step 2.11 + if (!headers.has('User-Agent')) { + headers.set('User-Agent', 'node-fetch/1.0 (+https://github.com/bitinn/node-fetch)'); + } + + // HTTP-network-or-cache fetch step 2.15 + if (request.compress && !headers.has('Accept-Encoding')) { + headers.set('Accept-Encoding', 'gzip,deflate'); + } + + let agent = request.agent; + if (typeof agent === 'function') { + agent = agent(parsedURL); + } + + // HTTP-network fetch step 4.2 + // chunked encoding is handled by Node.js + + return Object.assign({}, parsedURL, { + method: request.method, + headers: exportNodeCompatibleHeaders(headers), + agent + }); +} + +/** + * abort-error.js + * + * AbortError interface for cancelled requests + */ + +/** + * Create AbortError instance + * + * @param String message Error message for human + * @return AbortError + */ +function AbortError(message) { + Error.call(this, message); + + this.type = 'aborted'; + this.message = message; + + // hide custom error implementation details from end-users + Error.captureStackTrace(this, this.constructor); +} + +AbortError.prototype = Object.create(Error.prototype); +AbortError.prototype.constructor = AbortError; +AbortError.prototype.name = 'AbortError'; + +const URL$1 = Url.URL || whatwgUrl.URL; + +// fix an issue where "PassThrough", "resolve" aren't a named export for node <10 +const PassThrough$1 = Stream.PassThrough; + +const isDomainOrSubdomain = function isDomainOrSubdomain(destination, original) { + const orig = new URL$1(original).hostname; + const dest = new URL$1(destination).hostname; + + return orig === dest || orig[orig.length - dest.length - 1] === '.' && orig.endsWith(dest); +}; + +/** + * isSameProtocol reports whether the two provided URLs use the same protocol. + * + * Both domains must already be in canonical form. + * @param {string|URL} original + * @param {string|URL} destination + */ +const isSameProtocol = function isSameProtocol(destination, original) { + const orig = new URL$1(original).protocol; + const dest = new URL$1(destination).protocol; + + return orig === dest; +}; + +/** + * Fetch function + * + * @param Mixed url Absolute url or Request instance + * @param Object opts Fetch options + * @return Promise + */ +function fetch(url, opts) { + + // allow custom promise + if (!fetch.Promise) { + throw new Error('native promise missing, set fetch.Promise to your favorite alternative'); + } + + Body.Promise = fetch.Promise; + + // wrap http.request into fetch + return new fetch.Promise(function (resolve, reject) { + // build request object + const request = new Request(url, opts); + const options = getNodeRequestOptions(request); + + const send = (options.protocol === 'https:' ? https : http).request; + const signal = request.signal; + + let response = null; + + const abort = function abort() { + let error = new AbortError('The user aborted a request.'); + reject(error); + if (request.body && request.body instanceof Stream.Readable) { + destroyStream(request.body, error); + } + if (!response || !response.body) return; + response.body.emit('error', error); + }; + + if (signal && signal.aborted) { + abort(); + return; + } + + const abortAndFinalize = function abortAndFinalize() { + abort(); + finalize(); + }; + + // send request + const req = send(options); + let reqTimeout; + + if (signal) { + signal.addEventListener('abort', abortAndFinalize); + } + + function finalize() { + req.abort(); + if (signal) signal.removeEventListener('abort', abortAndFinalize); + clearTimeout(reqTimeout); + } + + if (request.timeout) { + req.once('socket', function (socket) { + reqTimeout = setTimeout(function () { + reject(new FetchError(`network timeout at: ${request.url}`, 'request-timeout')); + finalize(); + }, request.timeout); + }); + } + + req.on('error', function (err) { + reject(new FetchError(`request to ${request.url} failed, reason: ${err.message}`, 'system', err)); + + if (response && response.body) { + destroyStream(response.body, err); + } + + finalize(); + }); + + fixResponseChunkedTransferBadEnding(req, function (err) { + if (signal && signal.aborted) { + return; + } + + if (response && response.body) { + destroyStream(response.body, err); + } + }); + + /* c8 ignore next 18 */ + if (parseInt(process.version.substring(1)) < 14) { + // Before Node.js 14, pipeline() does not fully support async iterators and does not always + // properly handle when the socket close/end events are out of order. + req.on('socket', function (s) { + s.addListener('close', function (hadError) { + // if a data listener is still present we didn't end cleanly + const hasDataListener = s.listenerCount('data') > 0; + + // if end happened before close but the socket didn't emit an error, do it now + if (response && hasDataListener && !hadError && !(signal && signal.aborted)) { + const err = new Error('Premature close'); + err.code = 'ERR_STREAM_PREMATURE_CLOSE'; + response.body.emit('error', err); + } + }); + }); + } + + req.on('response', function (res) { + clearTimeout(reqTimeout); + + const headers = createHeadersLenient(res.headers); + + // HTTP fetch step 5 + if (fetch.isRedirect(res.statusCode)) { + // HTTP fetch step 5.2 + const location = headers.get('Location'); + + // HTTP fetch step 5.3 + let locationURL = null; + try { + locationURL = location === null ? null : new URL$1(location, request.url).toString(); + } catch (err) { + // error here can only be invalid URL in Location: header + // do not throw when options.redirect == manual + // let the user extract the errorneous redirect URL + if (request.redirect !== 'manual') { + reject(new FetchError(`uri requested responds with an invalid redirect URL: ${location}`, 'invalid-redirect')); + finalize(); + return; + } + } + + // HTTP fetch step 5.5 + switch (request.redirect) { + case 'error': + reject(new FetchError(`uri requested responds with a redirect, redirect mode is set to error: ${request.url}`, 'no-redirect')); + finalize(); + return; + case 'manual': + // node-fetch-specific step: make manual redirect a bit easier to use by setting the Location header value to the resolved URL. + if (locationURL !== null) { + // handle corrupted header + try { + headers.set('Location', locationURL); + } catch (err) { + // istanbul ignore next: nodejs server prevent invalid response headers, we can't test this through normal request + reject(err); + } + } + break; + case 'follow': + // HTTP-redirect fetch step 2 + if (locationURL === null) { + break; + } + + // HTTP-redirect fetch step 5 + if (request.counter >= request.follow) { + reject(new FetchError(`maximum redirect reached at: ${request.url}`, 'max-redirect')); + finalize(); + return; + } + + // HTTP-redirect fetch step 6 (counter increment) + // Create a new Request object. + const requestOpts = { + headers: new Headers(request.headers), + follow: request.follow, + counter: request.counter + 1, + agent: request.agent, + compress: request.compress, + method: request.method, + body: request.body, + signal: request.signal, + timeout: request.timeout, + size: request.size + }; + + if (!isDomainOrSubdomain(request.url, locationURL) || !isSameProtocol(request.url, locationURL)) { + for (const name of ['authorization', 'www-authenticate', 'cookie', 'cookie2']) { + requestOpts.headers.delete(name); + } + } + + // HTTP-redirect fetch step 9 + if (res.statusCode !== 303 && request.body && getTotalBytes(request) === null) { + reject(new FetchError('Cannot follow redirect with body being a readable stream', 'unsupported-redirect')); + finalize(); + return; + } + + // HTTP-redirect fetch step 11 + if (res.statusCode === 303 || (res.statusCode === 301 || res.statusCode === 302) && request.method === 'POST') { + requestOpts.method = 'GET'; + requestOpts.body = undefined; + requestOpts.headers.delete('content-length'); + } + + // HTTP-redirect fetch step 15 + resolve(fetch(new Request(locationURL, requestOpts))); + finalize(); + return; + } + } + + // prepare response + res.once('end', function () { + if (signal) signal.removeEventListener('abort', abortAndFinalize); + }); + let body = res.pipe(new PassThrough$1()); + + const response_options = { + url: request.url, + status: res.statusCode, + statusText: res.statusMessage, + headers: headers, + size: request.size, + timeout: request.timeout, + counter: request.counter + }; + + // HTTP-network fetch step 12.1.1.3 + const codings = headers.get('Content-Encoding'); + + // HTTP-network fetch step 12.1.1.4: handle content codings + + // in following scenarios we ignore compression support + // 1. compression support is disabled + // 2. HEAD request + // 3. no Content-Encoding header + // 4. no content response (204) + // 5. content not modified response (304) + if (!request.compress || request.method === 'HEAD' || codings === null || res.statusCode === 204 || res.statusCode === 304) { + response = new Response(body, response_options); + resolve(response); + return; + } + + // For Node v6+ + // Be less strict when decoding compressed responses, since sometimes + // servers send slightly invalid responses that are still accepted + // by common browsers. + // Always using Z_SYNC_FLUSH is what cURL does. + const zlibOptions = { + flush: zlib.Z_SYNC_FLUSH, + finishFlush: zlib.Z_SYNC_FLUSH + }; + + // for gzip + if (codings == 'gzip' || codings == 'x-gzip') { + body = body.pipe(zlib.createGunzip(zlibOptions)); + response = new Response(body, response_options); + resolve(response); + return; + } + + // for deflate + if (codings == 'deflate' || codings == 'x-deflate') { + // handle the infamous raw deflate response from old servers + // a hack for old IIS and Apache servers + const raw = res.pipe(new PassThrough$1()); + raw.once('data', function (chunk) { + // see http://stackoverflow.com/questions/37519828 + if ((chunk[0] & 0x0F) === 0x08) { + body = body.pipe(zlib.createInflate()); + } else { + body = body.pipe(zlib.createInflateRaw()); + } + response = new Response(body, response_options); + resolve(response); + }); + raw.on('end', function () { + // some old IIS servers return zero-length OK deflate responses, so 'data' is never emitted. + if (!response) { + response = new Response(body, response_options); + resolve(response); + } + }); + return; + } + + // for br + if (codings == 'br' && typeof zlib.createBrotliDecompress === 'function') { + body = body.pipe(zlib.createBrotliDecompress()); + response = new Response(body, response_options); + resolve(response); + return; + } + + // otherwise, use response as-is + response = new Response(body, response_options); + resolve(response); + }); + + writeToStream(req, request); + }); +} +function fixResponseChunkedTransferBadEnding(request, errorCallback) { + let socket; + + request.on('socket', function (s) { + socket = s; + }); + + request.on('response', function (response) { + const headers = response.headers; + + if (headers['transfer-encoding'] === 'chunked' && !headers['content-length']) { + response.once('close', function (hadError) { + // tests for socket presence, as in some situations the + // the 'socket' event is not triggered for the request + // (happens in deno), avoids `TypeError` + // if a data listener is still present we didn't end cleanly + const hasDataListener = socket && socket.listenerCount('data') > 0; + + if (hasDataListener && !hadError) { + const err = new Error('Premature close'); + err.code = 'ERR_STREAM_PREMATURE_CLOSE'; + errorCallback(err); + } + }); + } + }); +} + +function destroyStream(stream, err) { + if (stream.destroy) { + stream.destroy(err); + } else { + // node < 8 + stream.emit('error', err); + stream.end(); + } +} + +/** + * Redirect code matching + * + * @param Number code Status code + * @return Boolean + */ +fetch.isRedirect = function (code) { + return code === 301 || code === 302 || code === 303 || code === 307 || code === 308; +}; + +// expose Promise +fetch.Promise = global.Promise; + +export default fetch; +export { Headers, Request, Response, FetchError, AbortError }; diff --git a/node_modules/node-fetch/package.json b/node_modules/node-fetch/package.json new file mode 100644 index 00000000..e0be1768 --- /dev/null +++ b/node_modules/node-fetch/package.json @@ -0,0 +1,89 @@ +{ + "name": "node-fetch", + "version": "2.7.0", + "description": "A light-weight module that brings window.fetch to node.js", + "main": "lib/index.js", + "browser": "./browser.js", + "module": "lib/index.mjs", + "files": [ + "lib/index.js", + "lib/index.mjs", + "lib/index.es.js", + "browser.js" + ], + "engines": { + "node": "4.x || >=6.0.0" + }, + "scripts": { + "build": "cross-env BABEL_ENV=rollup rollup -c", + "prepare": "npm run build", + "test": "cross-env BABEL_ENV=test mocha --require babel-register --throw-deprecation test/test.js", + "report": "cross-env BABEL_ENV=coverage nyc --reporter lcov --reporter text mocha -R spec test/test.js", + "coverage": "cross-env BABEL_ENV=coverage nyc --reporter json --reporter text mocha -R spec test/test.js && codecov -f coverage/coverage-final.json" + }, + "repository": { + "type": "git", + "url": "https://github.com/bitinn/node-fetch.git" + }, + "keywords": [ + "fetch", + "http", + "promise" + ], + "author": "David Frank", + "license": "MIT", + "bugs": { + "url": "https://github.com/bitinn/node-fetch/issues" + }, + "homepage": "https://github.com/bitinn/node-fetch", + "dependencies": { + "whatwg-url": "^5.0.0" + }, + "peerDependencies": { + "encoding": "^0.1.0" + }, + "peerDependenciesMeta": { + "encoding": { + "optional": true + } + }, + "devDependencies": { + "@ungap/url-search-params": "^0.1.2", + "abort-controller": "^1.1.0", + "abortcontroller-polyfill": "^1.3.0", + "babel-core": "^6.26.3", + "babel-plugin-istanbul": "^4.1.6", + "babel-plugin-transform-async-generator-functions": "^6.24.1", + "babel-polyfill": "^6.26.0", + "babel-preset-env": "1.4.0", + "babel-register": "^6.16.3", + "chai": "^3.5.0", + "chai-as-promised": "^7.1.1", + "chai-iterator": "^1.1.1", + "chai-string": "~1.3.0", + "codecov": "3.3.0", + "cross-env": "^5.2.0", + "form-data": "^2.3.3", + "is-builtin-module": "^1.0.0", + "mocha": "^5.0.0", + "nyc": "11.9.0", + "parted": "^0.1.1", + "promise": "^8.0.3", + "resumer": "0.0.0", + "rollup": "^0.63.4", + "rollup-plugin-babel": "^3.0.7", + "string-to-arraybuffer": "^1.0.2", + "teeny-request": "3.7.0" + }, + "release": { + "branches": [ + "+([0-9]).x", + "main", + "next", + { + "name": "beta", + "prerelease": true + } + ] + } +} diff --git a/node_modules/tr46/.npmignore b/node_modules/tr46/.npmignore new file mode 100644 index 00000000..96e9161f --- /dev/null +++ b/node_modules/tr46/.npmignore @@ -0,0 +1,4 @@ +scripts/ +test/ + +!lib/mapping_table.json diff --git a/node_modules/tr46/index.js b/node_modules/tr46/index.js new file mode 100644 index 00000000..9ce12ca2 --- /dev/null +++ b/node_modules/tr46/index.js @@ -0,0 +1,193 @@ +"use strict"; + +var punycode = require("punycode"); +var mappingTable = require("./lib/mappingTable.json"); + +var PROCESSING_OPTIONS = { + TRANSITIONAL: 0, + NONTRANSITIONAL: 1 +}; + +function normalize(str) { // fix bug in v8 + return str.split('\u0000').map(function (s) { return s.normalize('NFC'); }).join('\u0000'); +} + +function findStatus(val) { + var start = 0; + var end = mappingTable.length - 1; + + while (start <= end) { + var mid = Math.floor((start + end) / 2); + + var target = mappingTable[mid]; + if (target[0][0] <= val && target[0][1] >= val) { + return target; + } else if (target[0][0] > val) { + end = mid - 1; + } else { + start = mid + 1; + } + } + + return null; +} + +var regexAstralSymbols = /[\uD800-\uDBFF][\uDC00-\uDFFF]/g; + +function countSymbols(string) { + return string + // replace every surrogate pair with a BMP symbol + .replace(regexAstralSymbols, '_') + // then get the length + .length; +} + +function mapChars(domain_name, useSTD3, processing_option) { + var hasError = false; + var processed = ""; + + var len = countSymbols(domain_name); + for (var i = 0; i < len; ++i) { + var codePoint = domain_name.codePointAt(i); + var status = findStatus(codePoint); + + switch (status[1]) { + case "disallowed": + hasError = true; + processed += String.fromCodePoint(codePoint); + break; + case "ignored": + break; + case "mapped": + processed += String.fromCodePoint.apply(String, status[2]); + break; + case "deviation": + if (processing_option === PROCESSING_OPTIONS.TRANSITIONAL) { + processed += String.fromCodePoint.apply(String, status[2]); + } else { + processed += String.fromCodePoint(codePoint); + } + break; + case "valid": + processed += String.fromCodePoint(codePoint); + break; + case "disallowed_STD3_mapped": + if (useSTD3) { + hasError = true; + processed += String.fromCodePoint(codePoint); + } else { + processed += String.fromCodePoint.apply(String, status[2]); + } + break; + case "disallowed_STD3_valid": + if (useSTD3) { + hasError = true; + } + + processed += String.fromCodePoint(codePoint); + break; + } + } + + return { + string: processed, + error: hasError + }; +} + +var combiningMarksRegex = /[\u0300-\u036F\u0483-\u0489\u0591-\u05BD\u05BF\u05C1\u05C2\u05C4\u05C5\u05C7\u0610-\u061A\u064B-\u065F\u0670\u06D6-\u06DC\u06DF-\u06E4\u06E7\u06E8\u06EA-\u06ED\u0711\u0730-\u074A\u07A6-\u07B0\u07EB-\u07F3\u0816-\u0819\u081B-\u0823\u0825-\u0827\u0829-\u082D\u0859-\u085B\u08E4-\u0903\u093A-\u093C\u093E-\u094F\u0951-\u0957\u0962\u0963\u0981-\u0983\u09BC\u09BE-\u09C4\u09C7\u09C8\u09CB-\u09CD\u09D7\u09E2\u09E3\u0A01-\u0A03\u0A3C\u0A3E-\u0A42\u0A47\u0A48\u0A4B-\u0A4D\u0A51\u0A70\u0A71\u0A75\u0A81-\u0A83\u0ABC\u0ABE-\u0AC5\u0AC7-\u0AC9\u0ACB-\u0ACD\u0AE2\u0AE3\u0B01-\u0B03\u0B3C\u0B3E-\u0B44\u0B47\u0B48\u0B4B-\u0B4D\u0B56\u0B57\u0B62\u0B63\u0B82\u0BBE-\u0BC2\u0BC6-\u0BC8\u0BCA-\u0BCD\u0BD7\u0C00-\u0C03\u0C3E-\u0C44\u0C46-\u0C48\u0C4A-\u0C4D\u0C55\u0C56\u0C62\u0C63\u0C81-\u0C83\u0CBC\u0CBE-\u0CC4\u0CC6-\u0CC8\u0CCA-\u0CCD\u0CD5\u0CD6\u0CE2\u0CE3\u0D01-\u0D03\u0D3E-\u0D44\u0D46-\u0D48\u0D4A-\u0D4D\u0D57\u0D62\u0D63\u0D82\u0D83\u0DCA\u0DCF-\u0DD4\u0DD6\u0DD8-\u0DDF\u0DF2\u0DF3\u0E31\u0E34-\u0E3A\u0E47-\u0E4E\u0EB1\u0EB4-\u0EB9\u0EBB\u0EBC\u0EC8-\u0ECD\u0F18\u0F19\u0F35\u0F37\u0F39\u0F3E\u0F3F\u0F71-\u0F84\u0F86\u0F87\u0F8D-\u0F97\u0F99-\u0FBC\u0FC6\u102B-\u103E\u1056-\u1059\u105E-\u1060\u1062-\u1064\u1067-\u106D\u1071-\u1074\u1082-\u108D\u108F\u109A-\u109D\u135D-\u135F\u1712-\u1714\u1732-\u1734\u1752\u1753\u1772\u1773\u17B4-\u17D3\u17DD\u180B-\u180D\u18A9\u1920-\u192B\u1930-\u193B\u19B0-\u19C0\u19C8\u19C9\u1A17-\u1A1B\u1A55-\u1A5E\u1A60-\u1A7C\u1A7F\u1AB0-\u1ABE\u1B00-\u1B04\u1B34-\u1B44\u1B6B-\u1B73\u1B80-\u1B82\u1BA1-\u1BAD\u1BE6-\u1BF3\u1C24-\u1C37\u1CD0-\u1CD2\u1CD4-\u1CE8\u1CED\u1CF2-\u1CF4\u1CF8\u1CF9\u1DC0-\u1DF5\u1DFC-\u1DFF\u20D0-\u20F0\u2CEF-\u2CF1\u2D7F\u2DE0-\u2DFF\u302A-\u302F\u3099\u309A\uA66F-\uA672\uA674-\uA67D\uA69F\uA6F0\uA6F1\uA802\uA806\uA80B\uA823-\uA827\uA880\uA881\uA8B4-\uA8C4\uA8E0-\uA8F1\uA926-\uA92D\uA947-\uA953\uA980-\uA983\uA9B3-\uA9C0\uA9E5\uAA29-\uAA36\uAA43\uAA4C\uAA4D\uAA7B-\uAA7D\uAAB0\uAAB2-\uAAB4\uAAB7\uAAB8\uAABE\uAABF\uAAC1\uAAEB-\uAAEF\uAAF5\uAAF6\uABE3-\uABEA\uABEC\uABED\uFB1E\uFE00-\uFE0F\uFE20-\uFE2D]|\uD800[\uDDFD\uDEE0\uDF76-\uDF7A]|\uD802[\uDE01-\uDE03\uDE05\uDE06\uDE0C-\uDE0F\uDE38-\uDE3A\uDE3F\uDEE5\uDEE6]|\uD804[\uDC00-\uDC02\uDC38-\uDC46\uDC7F-\uDC82\uDCB0-\uDCBA\uDD00-\uDD02\uDD27-\uDD34\uDD73\uDD80-\uDD82\uDDB3-\uDDC0\uDE2C-\uDE37\uDEDF-\uDEEA\uDF01-\uDF03\uDF3C\uDF3E-\uDF44\uDF47\uDF48\uDF4B-\uDF4D\uDF57\uDF62\uDF63\uDF66-\uDF6C\uDF70-\uDF74]|\uD805[\uDCB0-\uDCC3\uDDAF-\uDDB5\uDDB8-\uDDC0\uDE30-\uDE40\uDEAB-\uDEB7]|\uD81A[\uDEF0-\uDEF4\uDF30-\uDF36]|\uD81B[\uDF51-\uDF7E\uDF8F-\uDF92]|\uD82F[\uDC9D\uDC9E]|\uD834[\uDD65-\uDD69\uDD6D-\uDD72\uDD7B-\uDD82\uDD85-\uDD8B\uDDAA-\uDDAD\uDE42-\uDE44]|\uD83A[\uDCD0-\uDCD6]|\uDB40[\uDD00-\uDDEF]/; + +function validateLabel(label, processing_option) { + if (label.substr(0, 4) === "xn--") { + label = punycode.toUnicode(label); + processing_option = PROCESSING_OPTIONS.NONTRANSITIONAL; + } + + var error = false; + + if (normalize(label) !== label || + (label[3] === "-" && label[4] === "-") || + label[0] === "-" || label[label.length - 1] === "-" || + label.indexOf(".") !== -1 || + label.search(combiningMarksRegex) === 0) { + error = true; + } + + var len = countSymbols(label); + for (var i = 0; i < len; ++i) { + var status = findStatus(label.codePointAt(i)); + if ((processing === PROCESSING_OPTIONS.TRANSITIONAL && status[1] !== "valid") || + (processing === PROCESSING_OPTIONS.NONTRANSITIONAL && + status[1] !== "valid" && status[1] !== "deviation")) { + error = true; + break; + } + } + + return { + label: label, + error: error + }; +} + +function processing(domain_name, useSTD3, processing_option) { + var result = mapChars(domain_name, useSTD3, processing_option); + result.string = normalize(result.string); + + var labels = result.string.split("."); + for (var i = 0; i < labels.length; ++i) { + try { + var validation = validateLabel(labels[i]); + labels[i] = validation.label; + result.error = result.error || validation.error; + } catch(e) { + result.error = true; + } + } + + return { + string: labels.join("."), + error: result.error + }; +} + +module.exports.toASCII = function(domain_name, useSTD3, processing_option, verifyDnsLength) { + var result = processing(domain_name, useSTD3, processing_option); + var labels = result.string.split("."); + labels = labels.map(function(l) { + try { + return punycode.toASCII(l); + } catch(e) { + result.error = true; + return l; + } + }); + + if (verifyDnsLength) { + var total = labels.slice(0, labels.length - 1).join(".").length; + if (total.length > 253 || total.length === 0) { + result.error = true; + } + + for (var i=0; i < labels.length; ++i) { + if (labels.length > 63 || labels.length === 0) { + result.error = true; + break; + } + } + } + + if (result.error) return null; + return labels.join("."); +}; + +module.exports.toUnicode = function(domain_name, useSTD3) { + var result = processing(domain_name, useSTD3, PROCESSING_OPTIONS.NONTRANSITIONAL); + + return { + domain: result.string, + error: result.error + }; +}; + +module.exports.PROCESSING_OPTIONS = PROCESSING_OPTIONS; diff --git a/node_modules/tr46/lib/.gitkeep b/node_modules/tr46/lib/.gitkeep new file mode 100644 index 00000000..e69de29b diff --git a/node_modules/tr46/lib/mappingTable.json b/node_modules/tr46/lib/mappingTable.json new file mode 100644 index 00000000..89cf19a7 --- /dev/null +++ b/node_modules/tr46/lib/mappingTable.json @@ -0,0 +1 @@ +[[[0,44],"disallowed_STD3_valid"],[[45,46],"valid"],[[47,47],"disallowed_STD3_valid"],[[48,57],"valid"],[[58,64],"disallowed_STD3_valid"],[[65,65],"mapped",[97]],[[66,66],"mapped",[98]],[[67,67],"mapped",[99]],[[68,68],"mapped",[100]],[[69,69],"mapped",[101]],[[70,70],"mapped",[102]],[[71,71],"mapped",[103]],[[72,72],"mapped",[104]],[[73,73],"mapped",[105]],[[74,74],"mapped",[106]],[[75,75],"mapped",[107]],[[76,76],"mapped",[108]],[[77,77],"mapped",[109]],[[78,78],"mapped",[110]],[[79,79],"mapped",[111]],[[80,80],"mapped",[112]],[[81,81],"mapped",[113]],[[82,82],"mapped",[114]],[[83,83],"mapped",[115]],[[84,84],"mapped",[116]],[[85,85],"mapped",[117]],[[86,86],"mapped",[118]],[[87,87],"mapped",[119]],[[88,88],"mapped",[120]],[[89,89],"mapped",[121]],[[90,90],"mapped",[122]],[[91,96],"disallowed_STD3_valid"],[[97,122],"valid"],[[123,127],"disallowed_STD3_valid"],[[128,159],"disallowed"],[[160,160],"disallowed_STD3_mapped",[32]],[[161,167],"valid",[],"NV8"],[[168,168],"disallowed_STD3_mapped",[32,776]],[[169,169],"valid",[],"NV8"],[[170,170],"mapped",[97]],[[171,172],"valid",[],"NV8"],[[173,173],"ignored"],[[174,174],"valid",[],"NV8"],[[175,175],"disallowed_STD3_mapped",[32,772]],[[176,177],"valid",[],"NV8"],[[178,178],"mapped",[50]],[[179,179],"mapped",[51]],[[180,180],"disallowed_STD3_mapped",[32,769]],[[181,181],"mapped",[956]],[[182,182],"valid",[],"NV8"],[[183,183],"valid"],[[184,184],"disallowed_STD3_mapped",[32,807]],[[185,185],"mapped",[49]],[[186,186],"mapped",[111]],[[187,187],"valid",[],"NV8"],[[188,188],"mapped",[49,8260,52]],[[189,189],"mapped",[49,8260,50]],[[190,190],"mapped",[51,8260,52]],[[191,191],"valid",[],"NV8"],[[192,192],"mapped",[224]],[[193,193],"mapped",[225]],[[194,194],"mapped",[226]],[[195,195],"mapped",[227]],[[196,196],"mapped",[228]],[[197,197],"mapped",[229]],[[198,198],"mapped",[230]],[[199,199],"mapped",[231]],[[200,200],"mapped",[232]],[[201,201],"mapped",[233]],[[202,202],"mapped",[234]],[[203,203],"mapped",[235]],[[204,204],"mapped",[236]],[[205,205],"mapped",[237]],[[206,206],"mapped",[238]],[[207,207],"mapped",[239]],[[208,208],"mapped",[240]],[[209,209],"mapped",[241]],[[210,210],"mapped",[242]],[[211,211],"mapped",[243]],[[212,212],"mapped",[244]],[[213,213],"mapped",[245]],[[214,214],"mapped",[246]],[[215,215],"valid",[],"NV8"],[[216,216],"mapped",[248]],[[217,217],"mapped",[249]],[[218,218],"mapped",[250]],[[219,219],"mapped",[251]],[[220,220],"mapped",[252]],[[221,221],"mapped",[253]],[[222,222],"mapped",[254]],[[223,223],"deviation",[115,115]],[[224,246],"valid"],[[247,247],"valid",[],"NV8"],[[248,255],"valid"],[[256,256],"mapped",[257]],[[257,257],"valid"],[[258,258],"mapped",[259]],[[259,259],"valid"],[[260,260],"mapped",[261]],[[261,261],"valid"],[[262,262],"mapped",[263]],[[263,263],"valid"],[[264,264],"mapped",[265]],[[265,265],"valid"],[[266,266],"mapped",[267]],[[267,267],"valid"],[[268,268],"mapped",[269]],[[269,269],"valid"],[[270,270],"mapped",[271]],[[271,271],"valid"],[[272,272],"mapped",[273]],[[273,273],"valid"],[[274,274],"mapped",[275]],[[275,275],"valid"],[[276,276],"mapped",[277]],[[277,277],"valid"],[[278,278],"mapped",[279]],[[279,279],"valid"],[[280,280],"mapped",[281]],[[281,281],"valid"],[[282,282],"mapped",[283]],[[283,283],"valid"],[[284,284],"mapped",[285]],[[285,285],"valid"],[[286,286],"mapped",[287]],[[287,287],"valid"],[[288,288],"mapped",[289]],[[289,289],"valid"],[[290,290],"mapped",[291]],[[291,291],"valid"],[[292,292],"mapped",[293]],[[293,293],"valid"],[[294,294],"mapped",[295]],[[295,295],"valid"],[[296,296],"mapped",[297]],[[297,297],"valid"],[[298,298],"mapped",[299]],[[299,299],"valid"],[[300,300],"mapped",[301]],[[301,301],"valid"],[[302,302],"mapped",[303]],[[303,303],"valid"],[[304,304],"mapped",[105,775]],[[305,305],"valid"],[[306,307],"mapped",[105,106]],[[308,308],"mapped",[309]],[[309,309],"valid"],[[310,310],"mapped",[311]],[[311,312],"valid"],[[313,313],"mapped",[314]],[[314,314],"valid"],[[315,315],"mapped",[316]],[[316,316],"valid"],[[317,317],"mapped",[318]],[[318,318],"valid"],[[319,320],"mapped",[108,183]],[[321,321],"mapped",[322]],[[322,322],"valid"],[[323,323],"mapped",[324]],[[324,324],"valid"],[[325,325],"mapped",[326]],[[326,326],"valid"],[[327,327],"mapped",[328]],[[328,328],"valid"],[[329,329],"mapped",[700,110]],[[330,330],"mapped",[331]],[[331,331],"valid"],[[332,332],"mapped",[333]],[[333,333],"valid"],[[334,334],"mapped",[335]],[[335,335],"valid"],[[336,336],"mapped",[337]],[[337,337],"valid"],[[338,338],"mapped",[339]],[[339,339],"valid"],[[340,340],"mapped",[341]],[[341,341],"valid"],[[342,342],"mapped",[343]],[[343,343],"valid"],[[344,344],"mapped",[345]],[[345,345],"valid"],[[346,346],"mapped",[347]],[[347,347],"valid"],[[348,348],"mapped",[349]],[[349,349],"valid"],[[350,350],"mapped",[351]],[[351,351],"valid"],[[352,352],"mapped",[353]],[[353,353],"valid"],[[354,354],"mapped",[355]],[[355,355],"valid"],[[356,356],"mapped",[357]],[[357,357],"valid"],[[358,358],"mapped",[359]],[[359,359],"valid"],[[360,360],"mapped",[361]],[[361,361],"valid"],[[362,362],"mapped",[363]],[[363,363],"valid"],[[364,364],"mapped",[365]],[[365,365],"valid"],[[366,366],"mapped",[367]],[[367,367],"valid"],[[368,368],"mapped",[369]],[[369,369],"valid"],[[370,370],"mapped",[371]],[[371,371],"valid"],[[372,372],"mapped",[373]],[[373,373],"valid"],[[374,374],"mapped",[375]],[[375,375],"valid"],[[376,376],"mapped",[255]],[[377,377],"mapped",[378]],[[378,378],"valid"],[[379,379],"mapped",[380]],[[380,380],"valid"],[[381,381],"mapped",[382]],[[382,382],"valid"],[[383,383],"mapped",[115]],[[384,384],"valid"],[[385,385],"mapped",[595]],[[386,386],"mapped",[387]],[[387,387],"valid"],[[388,388],"mapped",[389]],[[389,389],"valid"],[[390,390],"mapped",[596]],[[391,391],"mapped",[392]],[[392,392],"valid"],[[393,393],"mapped",[598]],[[394,394],"mapped",[599]],[[395,395],"mapped",[396]],[[396,397],"valid"],[[398,398],"mapped",[477]],[[399,399],"mapped",[601]],[[400,400],"mapped",[603]],[[401,401],"mapped",[402]],[[402,402],"valid"],[[403,403],"mapped",[608]],[[404,404],"mapped",[611]],[[405,405],"valid"],[[406,406],"mapped",[617]],[[407,407],"mapped",[616]],[[408,408],"mapped",[409]],[[409,411],"valid"],[[412,412],"mapped",[623]],[[413,413],"mapped",[626]],[[414,414],"valid"],[[415,415],"mapped",[629]],[[416,416],"mapped",[417]],[[417,417],"valid"],[[418,418],"mapped",[419]],[[419,419],"valid"],[[420,420],"mapped",[421]],[[421,421],"valid"],[[422,422],"mapped",[640]],[[423,423],"mapped",[424]],[[424,424],"valid"],[[425,425],"mapped",[643]],[[426,427],"valid"],[[428,428],"mapped",[429]],[[429,429],"valid"],[[430,430],"mapped",[648]],[[431,431],"mapped",[432]],[[432,432],"valid"],[[433,433],"mapped",[650]],[[434,434],"mapped",[651]],[[435,435],"mapped",[436]],[[436,436],"valid"],[[437,437],"mapped",[438]],[[438,438],"valid"],[[439,439],"mapped",[658]],[[440,440],"mapped",[441]],[[441,443],"valid"],[[444,444],"mapped",[445]],[[445,451],"valid"],[[452,454],"mapped",[100,382]],[[455,457],"mapped",[108,106]],[[458,460],"mapped",[110,106]],[[461,461],"mapped",[462]],[[462,462],"valid"],[[463,463],"mapped",[464]],[[464,464],"valid"],[[465,465],"mapped",[466]],[[466,466],"valid"],[[467,467],"mapped",[468]],[[468,468],"valid"],[[469,469],"mapped",[470]],[[470,470],"valid"],[[471,471],"mapped",[472]],[[472,472],"valid"],[[473,473],"mapped",[474]],[[474,474],"valid"],[[475,475],"mapped",[476]],[[476,477],"valid"],[[478,478],"mapped",[479]],[[479,479],"valid"],[[480,480],"mapped",[481]],[[481,481],"valid"],[[482,482],"mapped",[483]],[[483,483],"valid"],[[484,484],"mapped",[485]],[[485,485],"valid"],[[486,486],"mapped",[487]],[[487,487],"valid"],[[488,488],"mapped",[489]],[[489,489],"valid"],[[490,490],"mapped",[491]],[[491,491],"valid"],[[492,492],"mapped",[493]],[[493,493],"valid"],[[494,494],"mapped",[495]],[[495,496],"valid"],[[497,499],"mapped",[100,122]],[[500,500],"mapped",[501]],[[501,501],"valid"],[[502,502],"mapped",[405]],[[503,503],"mapped",[447]],[[504,504],"mapped",[505]],[[505,505],"valid"],[[506,506],"mapped",[507]],[[507,507],"valid"],[[508,508],"mapped",[509]],[[509,509],"valid"],[[510,510],"mapped",[511]],[[511,511],"valid"],[[512,512],"mapped",[513]],[[513,513],"valid"],[[514,514],"mapped",[515]],[[515,515],"valid"],[[516,516],"mapped",[517]],[[517,517],"valid"],[[518,518],"mapped",[519]],[[519,519],"valid"],[[520,520],"mapped",[521]],[[521,521],"valid"],[[522,522],"mapped",[523]],[[523,523],"valid"],[[524,524],"mapped",[525]],[[525,525],"valid"],[[526,526],"mapped",[527]],[[527,527],"valid"],[[528,528],"mapped",[529]],[[529,529],"valid"],[[530,530],"mapped",[531]],[[531,531],"valid"],[[532,532],"mapped",[533]],[[533,533],"valid"],[[534,534],"mapped",[535]],[[535,535],"valid"],[[536,536],"mapped",[537]],[[537,537],"valid"],[[538,538],"mapped",[539]],[[539,539],"valid"],[[540,540],"mapped",[541]],[[541,541],"valid"],[[542,542],"mapped",[543]],[[543,543],"valid"],[[544,544],"mapped",[414]],[[545,545],"valid"],[[546,546],"mapped",[547]],[[547,547],"valid"],[[548,548],"mapped",[549]],[[549,549],"valid"],[[550,550],"mapped",[551]],[[551,551],"valid"],[[552,552],"mapped",[553]],[[553,553],"valid"],[[554,554],"mapped",[555]],[[555,555],"valid"],[[556,556],"mapped",[557]],[[557,557],"valid"],[[558,558],"mapped",[559]],[[559,559],"valid"],[[560,560],"mapped",[561]],[[561,561],"valid"],[[562,562],"mapped",[563]],[[563,563],"valid"],[[564,566],"valid"],[[567,569],"valid"],[[570,570],"mapped",[11365]],[[571,571],"mapped",[572]],[[572,572],"valid"],[[573,573],"mapped",[410]],[[574,574],"mapped",[11366]],[[575,576],"valid"],[[577,577],"mapped",[578]],[[578,578],"valid"],[[579,579],"mapped",[384]],[[580,580],"mapped",[649]],[[581,581],"mapped",[652]],[[582,582],"mapped",[583]],[[583,583],"valid"],[[584,584],"mapped",[585]],[[585,585],"valid"],[[586,586],"mapped",[587]],[[587,587],"valid"],[[588,588],"mapped",[589]],[[589,589],"valid"],[[590,590],"mapped",[591]],[[591,591],"valid"],[[592,680],"valid"],[[681,685],"valid"],[[686,687],"valid"],[[688,688],"mapped",[104]],[[689,689],"mapped",[614]],[[690,690],"mapped",[106]],[[691,691],"mapped",[114]],[[692,692],"mapped",[633]],[[693,693],"mapped",[635]],[[694,694],"mapped",[641]],[[695,695],"mapped",[119]],[[696,696],"mapped",[121]],[[697,705],"valid"],[[706,709],"valid",[],"NV8"],[[710,721],"valid"],[[722,727],"valid",[],"NV8"],[[728,728],"disallowed_STD3_mapped",[32,774]],[[729,729],"disallowed_STD3_mapped",[32,775]],[[730,730],"disallowed_STD3_mapped",[32,778]],[[731,731],"disallowed_STD3_mapped",[32,808]],[[732,732],"disallowed_STD3_mapped",[32,771]],[[733,733],"disallowed_STD3_mapped",[32,779]],[[734,734],"valid",[],"NV8"],[[735,735],"valid",[],"NV8"],[[736,736],"mapped",[611]],[[737,737],"mapped",[108]],[[738,738],"mapped",[115]],[[739,739],"mapped",[120]],[[740,740],"mapped",[661]],[[741,745],"valid",[],"NV8"],[[746,747],"valid",[],"NV8"],[[748,748],"valid"],[[749,749],"valid",[],"NV8"],[[750,750],"valid"],[[751,767],"valid",[],"NV8"],[[768,831],"valid"],[[832,832],"mapped",[768]],[[833,833],"mapped",[769]],[[834,834],"valid"],[[835,835],"mapped",[787]],[[836,836],"mapped",[776,769]],[[837,837],"mapped",[953]],[[838,846],"valid"],[[847,847],"ignored"],[[848,855],"valid"],[[856,860],"valid"],[[861,863],"valid"],[[864,865],"valid"],[[866,866],"valid"],[[867,879],"valid"],[[880,880],"mapped",[881]],[[881,881],"valid"],[[882,882],"mapped",[883]],[[883,883],"valid"],[[884,884],"mapped",[697]],[[885,885],"valid"],[[886,886],"mapped",[887]],[[887,887],"valid"],[[888,889],"disallowed"],[[890,890],"disallowed_STD3_mapped",[32,953]],[[891,893],"valid"],[[894,894],"disallowed_STD3_mapped",[59]],[[895,895],"mapped",[1011]],[[896,899],"disallowed"],[[900,900],"disallowed_STD3_mapped",[32,769]],[[901,901],"disallowed_STD3_mapped",[32,776,769]],[[902,902],"mapped",[940]],[[903,903],"mapped",[183]],[[904,904],"mapped",[941]],[[905,905],"mapped",[942]],[[906,906],"mapped",[943]],[[907,907],"disallowed"],[[908,908],"mapped",[972]],[[909,909],"disallowed"],[[910,910],"mapped",[973]],[[911,911],"mapped",[974]],[[912,912],"valid"],[[913,913],"mapped",[945]],[[914,914],"mapped",[946]],[[915,915],"mapped",[947]],[[916,916],"mapped",[948]],[[917,917],"mapped",[949]],[[918,918],"mapped",[950]],[[919,919],"mapped",[951]],[[920,920],"mapped",[952]],[[921,921],"mapped",[953]],[[922,922],"mapped",[954]],[[923,923],"mapped",[955]],[[924,924],"mapped",[956]],[[925,925],"mapped",[957]],[[926,926],"mapped",[958]],[[927,927],"mapped",[959]],[[928,928],"mapped",[960]],[[929,929],"mapped",[961]],[[930,930],"disallowed"],[[931,931],"mapped",[963]],[[932,932],"mapped",[964]],[[933,933],"mapped",[965]],[[934,934],"mapped",[966]],[[935,935],"mapped",[967]],[[936,936],"mapped",[968]],[[937,937],"mapped",[969]],[[938,938],"mapped",[970]],[[939,939],"mapped",[971]],[[940,961],"valid"],[[962,962],"deviation",[963]],[[963,974],"valid"],[[975,975],"mapped",[983]],[[976,976],"mapped",[946]],[[977,977],"mapped",[952]],[[978,978],"mapped",[965]],[[979,979],"mapped",[973]],[[980,980],"mapped",[971]],[[981,981],"mapped",[966]],[[982,982],"mapped",[960]],[[983,983],"valid"],[[984,984],"mapped",[985]],[[985,985],"valid"],[[986,986],"mapped",[987]],[[987,987],"valid"],[[988,988],"mapped",[989]],[[989,989],"valid"],[[990,990],"mapped",[991]],[[991,991],"valid"],[[992,992],"mapped",[993]],[[993,993],"valid"],[[994,994],"mapped",[995]],[[995,995],"valid"],[[996,996],"mapped",[997]],[[997,997],"valid"],[[998,998],"mapped",[999]],[[999,999],"valid"],[[1000,1000],"mapped",[1001]],[[1001,1001],"valid"],[[1002,1002],"mapped",[1003]],[[1003,1003],"valid"],[[1004,1004],"mapped",[1005]],[[1005,1005],"valid"],[[1006,1006],"mapped",[1007]],[[1007,1007],"valid"],[[1008,1008],"mapped",[954]],[[1009,1009],"mapped",[961]],[[1010,1010],"mapped",[963]],[[1011,1011],"valid"],[[1012,1012],"mapped",[952]],[[1013,1013],"mapped",[949]],[[1014,1014],"valid",[],"NV8"],[[1015,1015],"mapped",[1016]],[[1016,1016],"valid"],[[1017,1017],"mapped",[963]],[[1018,1018],"mapped",[1019]],[[1019,1019],"valid"],[[1020,1020],"valid"],[[1021,1021],"mapped",[891]],[[1022,1022],"mapped",[892]],[[1023,1023],"mapped",[893]],[[1024,1024],"mapped",[1104]],[[1025,1025],"mapped",[1105]],[[1026,1026],"mapped",[1106]],[[1027,1027],"mapped",[1107]],[[1028,1028],"mapped",[1108]],[[1029,1029],"mapped",[1109]],[[1030,1030],"mapped",[1110]],[[1031,1031],"mapped",[1111]],[[1032,1032],"mapped",[1112]],[[1033,1033],"mapped",[1113]],[[1034,1034],"mapped",[1114]],[[1035,1035],"mapped",[1115]],[[1036,1036],"mapped",[1116]],[[1037,1037],"mapped",[1117]],[[1038,1038],"mapped",[1118]],[[1039,1039],"mapped",[1119]],[[1040,1040],"mapped",[1072]],[[1041,1041],"mapped",[1073]],[[1042,1042],"mapped",[1074]],[[1043,1043],"mapped",[1075]],[[1044,1044],"mapped",[1076]],[[1045,1045],"mapped",[1077]],[[1046,1046],"mapped",[1078]],[[1047,1047],"mapped",[1079]],[[1048,1048],"mapped",[1080]],[[1049,1049],"mapped",[1081]],[[1050,1050],"mapped",[1082]],[[1051,1051],"mapped",[1083]],[[1052,1052],"mapped",[1084]],[[1053,1053],"mapped",[1085]],[[1054,1054],"mapped",[1086]],[[1055,1055],"mapped",[1087]],[[1056,1056],"mapped",[1088]],[[1057,1057],"mapped",[1089]],[[1058,1058],"mapped",[1090]],[[1059,1059],"mapped",[1091]],[[1060,1060],"mapped",[1092]],[[1061,1061],"mapped",[1093]],[[1062,1062],"mapped",[1094]],[[1063,1063],"mapped",[1095]],[[1064,1064],"mapped",[1096]],[[1065,1065],"mapped",[1097]],[[1066,1066],"mapped",[1098]],[[1067,1067],"mapped",[1099]],[[1068,1068],"mapped",[1100]],[[1069,1069],"mapped",[1101]],[[1070,1070],"mapped",[1102]],[[1071,1071],"mapped",[1103]],[[1072,1103],"valid"],[[1104,1104],"valid"],[[1105,1116],"valid"],[[1117,1117],"valid"],[[1118,1119],"valid"],[[1120,1120],"mapped",[1121]],[[1121,1121],"valid"],[[1122,1122],"mapped",[1123]],[[1123,1123],"valid"],[[1124,1124],"mapped",[1125]],[[1125,1125],"valid"],[[1126,1126],"mapped",[1127]],[[1127,1127],"valid"],[[1128,1128],"mapped",[1129]],[[1129,1129],"valid"],[[1130,1130],"mapped",[1131]],[[1131,1131],"valid"],[[1132,1132],"mapped",[1133]],[[1133,1133],"valid"],[[1134,1134],"mapped",[1135]],[[1135,1135],"valid"],[[1136,1136],"mapped",[1137]],[[1137,1137],"valid"],[[1138,1138],"mapped",[1139]],[[1139,1139],"valid"],[[1140,1140],"mapped",[1141]],[[1141,1141],"valid"],[[1142,1142],"mapped",[1143]],[[1143,1143],"valid"],[[1144,1144],"mapped",[1145]],[[1145,1145],"valid"],[[1146,1146],"mapped",[1147]],[[1147,1147],"valid"],[[1148,1148],"mapped",[1149]],[[1149,1149],"valid"],[[1150,1150],"mapped",[1151]],[[1151,1151],"valid"],[[1152,1152],"mapped",[1153]],[[1153,1153],"valid"],[[1154,1154],"valid",[],"NV8"],[[1155,1158],"valid"],[[1159,1159],"valid"],[[1160,1161],"valid",[],"NV8"],[[1162,1162],"mapped",[1163]],[[1163,1163],"valid"],[[1164,1164],"mapped",[1165]],[[1165,1165],"valid"],[[1166,1166],"mapped",[1167]],[[1167,1167],"valid"],[[1168,1168],"mapped",[1169]],[[1169,1169],"valid"],[[1170,1170],"mapped",[1171]],[[1171,1171],"valid"],[[1172,1172],"mapped",[1173]],[[1173,1173],"valid"],[[1174,1174],"mapped",[1175]],[[1175,1175],"valid"],[[1176,1176],"mapped",[1177]],[[1177,1177],"valid"],[[1178,1178],"mapped",[1179]],[[1179,1179],"valid"],[[1180,1180],"mapped",[1181]],[[1181,1181],"valid"],[[1182,1182],"mapped",[1183]],[[1183,1183],"valid"],[[1184,1184],"mapped",[1185]],[[1185,1185],"valid"],[[1186,1186],"mapped",[1187]],[[1187,1187],"valid"],[[1188,1188],"mapped",[1189]],[[1189,1189],"valid"],[[1190,1190],"mapped",[1191]],[[1191,1191],"valid"],[[1192,1192],"mapped",[1193]],[[1193,1193],"valid"],[[1194,1194],"mapped",[1195]],[[1195,1195],"valid"],[[1196,1196],"mapped",[1197]],[[1197,1197],"valid"],[[1198,1198],"mapped",[1199]],[[1199,1199],"valid"],[[1200,1200],"mapped",[1201]],[[1201,1201],"valid"],[[1202,1202],"mapped",[1203]],[[1203,1203],"valid"],[[1204,1204],"mapped",[1205]],[[1205,1205],"valid"],[[1206,1206],"mapped",[1207]],[[1207,1207],"valid"],[[1208,1208],"mapped",[1209]],[[1209,1209],"valid"],[[1210,1210],"mapped",[1211]],[[1211,1211],"valid"],[[1212,1212],"mapped",[1213]],[[1213,1213],"valid"],[[1214,1214],"mapped",[1215]],[[1215,1215],"valid"],[[1216,1216],"disallowed"],[[1217,1217],"mapped",[1218]],[[1218,1218],"valid"],[[1219,1219],"mapped",[1220]],[[1220,1220],"valid"],[[1221,1221],"mapped",[1222]],[[1222,1222],"valid"],[[1223,1223],"mapped",[1224]],[[1224,1224],"valid"],[[1225,1225],"mapped",[1226]],[[1226,1226],"valid"],[[1227,1227],"mapped",[1228]],[[1228,1228],"valid"],[[1229,1229],"mapped",[1230]],[[1230,1230],"valid"],[[1231,1231],"valid"],[[1232,1232],"mapped",[1233]],[[1233,1233],"valid"],[[1234,1234],"mapped",[1235]],[[1235,1235],"valid"],[[1236,1236],"mapped",[1237]],[[1237,1237],"valid"],[[1238,1238],"mapped",[1239]],[[1239,1239],"valid"],[[1240,1240],"mapped",[1241]],[[1241,1241],"valid"],[[1242,1242],"mapped",[1243]],[[1243,1243],"valid"],[[1244,1244],"mapped",[1245]],[[1245,1245],"valid"],[[1246,1246],"mapped",[1247]],[[1247,1247],"valid"],[[1248,1248],"mapped",[1249]],[[1249,1249],"valid"],[[1250,1250],"mapped",[1251]],[[1251,1251],"valid"],[[1252,1252],"mapped",[1253]],[[1253,1253],"valid"],[[1254,1254],"mapped",[1255]],[[1255,1255],"valid"],[[1256,1256],"mapped",[1257]],[[1257,1257],"valid"],[[1258,1258],"mapped",[1259]],[[1259,1259],"valid"],[[1260,1260],"mapped",[1261]],[[1261,1261],"valid"],[[1262,1262],"mapped",[1263]],[[1263,1263],"valid"],[[1264,1264],"mapped",[1265]],[[1265,1265],"valid"],[[1266,1266],"mapped",[1267]],[[1267,1267],"valid"],[[1268,1268],"mapped",[1269]],[[1269,1269],"valid"],[[1270,1270],"mapped",[1271]],[[1271,1271],"valid"],[[1272,1272],"mapped",[1273]],[[1273,1273],"valid"],[[1274,1274],"mapped",[1275]],[[1275,1275],"valid"],[[1276,1276],"mapped",[1277]],[[1277,1277],"valid"],[[1278,1278],"mapped",[1279]],[[1279,1279],"valid"],[[1280,1280],"mapped",[1281]],[[1281,1281],"valid"],[[1282,1282],"mapped",[1283]],[[1283,1283],"valid"],[[1284,1284],"mapped",[1285]],[[1285,1285],"valid"],[[1286,1286],"mapped",[1287]],[[1287,1287],"valid"],[[1288,1288],"mapped",[1289]],[[1289,1289],"valid"],[[1290,1290],"mapped",[1291]],[[1291,1291],"valid"],[[1292,1292],"mapped",[1293]],[[1293,1293],"valid"],[[1294,1294],"mapped",[1295]],[[1295,1295],"valid"],[[1296,1296],"mapped",[1297]],[[1297,1297],"valid"],[[1298,1298],"mapped",[1299]],[[1299,1299],"valid"],[[1300,1300],"mapped",[1301]],[[1301,1301],"valid"],[[1302,1302],"mapped",[1303]],[[1303,1303],"valid"],[[1304,1304],"mapped",[1305]],[[1305,1305],"valid"],[[1306,1306],"mapped",[1307]],[[1307,1307],"valid"],[[1308,1308],"mapped",[1309]],[[1309,1309],"valid"],[[1310,1310],"mapped",[1311]],[[1311,1311],"valid"],[[1312,1312],"mapped",[1313]],[[1313,1313],"valid"],[[1314,1314],"mapped",[1315]],[[1315,1315],"valid"],[[1316,1316],"mapped",[1317]],[[1317,1317],"valid"],[[1318,1318],"mapped",[1319]],[[1319,1319],"valid"],[[1320,1320],"mapped",[1321]],[[1321,1321],"valid"],[[1322,1322],"mapped",[1323]],[[1323,1323],"valid"],[[1324,1324],"mapped",[1325]],[[1325,1325],"valid"],[[1326,1326],"mapped",[1327]],[[1327,1327],"valid"],[[1328,1328],"disallowed"],[[1329,1329],"mapped",[1377]],[[1330,1330],"mapped",[1378]],[[1331,1331],"mapped",[1379]],[[1332,1332],"mapped",[1380]],[[1333,1333],"mapped",[1381]],[[1334,1334],"mapped",[1382]],[[1335,1335],"mapped",[1383]],[[1336,1336],"mapped",[1384]],[[1337,1337],"mapped",[1385]],[[1338,1338],"mapped",[1386]],[[1339,1339],"mapped",[1387]],[[1340,1340],"mapped",[1388]],[[1341,1341],"mapped",[1389]],[[1342,1342],"mapped",[1390]],[[1343,1343],"mapped",[1391]],[[1344,1344],"mapped",[1392]],[[1345,1345],"mapped",[1393]],[[1346,1346],"mapped",[1394]],[[1347,1347],"mapped",[1395]],[[1348,1348],"mapped",[1396]],[[1349,1349],"mapped",[1397]],[[1350,1350],"mapped",[1398]],[[1351,1351],"mapped",[1399]],[[1352,1352],"mapped",[1400]],[[1353,1353],"mapped",[1401]],[[1354,1354],"mapped",[1402]],[[1355,1355],"mapped",[1403]],[[1356,1356],"mapped",[1404]],[[1357,1357],"mapped",[1405]],[[1358,1358],"mapped",[1406]],[[1359,1359],"mapped",[1407]],[[1360,1360],"mapped",[1408]],[[1361,1361],"mapped",[1409]],[[1362,1362],"mapped",[1410]],[[1363,1363],"mapped",[1411]],[[1364,1364],"mapped",[1412]],[[1365,1365],"mapped",[1413]],[[1366,1366],"mapped",[1414]],[[1367,1368],"disallowed"],[[1369,1369],"valid"],[[1370,1375],"valid",[],"NV8"],[[1376,1376],"disallowed"],[[1377,1414],"valid"],[[1415,1415],"mapped",[1381,1410]],[[1416,1416],"disallowed"],[[1417,1417],"valid",[],"NV8"],[[1418,1418],"valid",[],"NV8"],[[1419,1420],"disallowed"],[[1421,1422],"valid",[],"NV8"],[[1423,1423],"valid",[],"NV8"],[[1424,1424],"disallowed"],[[1425,1441],"valid"],[[1442,1442],"valid"],[[1443,1455],"valid"],[[1456,1465],"valid"],[[1466,1466],"valid"],[[1467,1469],"valid"],[[1470,1470],"valid",[],"NV8"],[[1471,1471],"valid"],[[1472,1472],"valid",[],"NV8"],[[1473,1474],"valid"],[[1475,1475],"valid",[],"NV8"],[[1476,1476],"valid"],[[1477,1477],"valid"],[[1478,1478],"valid",[],"NV8"],[[1479,1479],"valid"],[[1480,1487],"disallowed"],[[1488,1514],"valid"],[[1515,1519],"disallowed"],[[1520,1524],"valid"],[[1525,1535],"disallowed"],[[1536,1539],"disallowed"],[[1540,1540],"disallowed"],[[1541,1541],"disallowed"],[[1542,1546],"valid",[],"NV8"],[[1547,1547],"valid",[],"NV8"],[[1548,1548],"valid",[],"NV8"],[[1549,1551],"valid",[],"NV8"],[[1552,1557],"valid"],[[1558,1562],"valid"],[[1563,1563],"valid",[],"NV8"],[[1564,1564],"disallowed"],[[1565,1565],"disallowed"],[[1566,1566],"valid",[],"NV8"],[[1567,1567],"valid",[],"NV8"],[[1568,1568],"valid"],[[1569,1594],"valid"],[[1595,1599],"valid"],[[1600,1600],"valid",[],"NV8"],[[1601,1618],"valid"],[[1619,1621],"valid"],[[1622,1624],"valid"],[[1625,1630],"valid"],[[1631,1631],"valid"],[[1632,1641],"valid"],[[1642,1645],"valid",[],"NV8"],[[1646,1647],"valid"],[[1648,1652],"valid"],[[1653,1653],"mapped",[1575,1652]],[[1654,1654],"mapped",[1608,1652]],[[1655,1655],"mapped",[1735,1652]],[[1656,1656],"mapped",[1610,1652]],[[1657,1719],"valid"],[[1720,1721],"valid"],[[1722,1726],"valid"],[[1727,1727],"valid"],[[1728,1742],"valid"],[[1743,1743],"valid"],[[1744,1747],"valid"],[[1748,1748],"valid",[],"NV8"],[[1749,1756],"valid"],[[1757,1757],"disallowed"],[[1758,1758],"valid",[],"NV8"],[[1759,1768],"valid"],[[1769,1769],"valid",[],"NV8"],[[1770,1773],"valid"],[[1774,1775],"valid"],[[1776,1785],"valid"],[[1786,1790],"valid"],[[1791,1791],"valid"],[[1792,1805],"valid",[],"NV8"],[[1806,1806],"disallowed"],[[1807,1807],"disallowed"],[[1808,1836],"valid"],[[1837,1839],"valid"],[[1840,1866],"valid"],[[1867,1868],"disallowed"],[[1869,1871],"valid"],[[1872,1901],"valid"],[[1902,1919],"valid"],[[1920,1968],"valid"],[[1969,1969],"valid"],[[1970,1983],"disallowed"],[[1984,2037],"valid"],[[2038,2042],"valid",[],"NV8"],[[2043,2047],"disallowed"],[[2048,2093],"valid"],[[2094,2095],"disallowed"],[[2096,2110],"valid",[],"NV8"],[[2111,2111],"disallowed"],[[2112,2139],"valid"],[[2140,2141],"disallowed"],[[2142,2142],"valid",[],"NV8"],[[2143,2207],"disallowed"],[[2208,2208],"valid"],[[2209,2209],"valid"],[[2210,2220],"valid"],[[2221,2226],"valid"],[[2227,2228],"valid"],[[2229,2274],"disallowed"],[[2275,2275],"valid"],[[2276,2302],"valid"],[[2303,2303],"valid"],[[2304,2304],"valid"],[[2305,2307],"valid"],[[2308,2308],"valid"],[[2309,2361],"valid"],[[2362,2363],"valid"],[[2364,2381],"valid"],[[2382,2382],"valid"],[[2383,2383],"valid"],[[2384,2388],"valid"],[[2389,2389],"valid"],[[2390,2391],"valid"],[[2392,2392],"mapped",[2325,2364]],[[2393,2393],"mapped",[2326,2364]],[[2394,2394],"mapped",[2327,2364]],[[2395,2395],"mapped",[2332,2364]],[[2396,2396],"mapped",[2337,2364]],[[2397,2397],"mapped",[2338,2364]],[[2398,2398],"mapped",[2347,2364]],[[2399,2399],"mapped",[2351,2364]],[[2400,2403],"valid"],[[2404,2405],"valid",[],"NV8"],[[2406,2415],"valid"],[[2416,2416],"valid",[],"NV8"],[[2417,2418],"valid"],[[2419,2423],"valid"],[[2424,2424],"valid"],[[2425,2426],"valid"],[[2427,2428],"valid"],[[2429,2429],"valid"],[[2430,2431],"valid"],[[2432,2432],"valid"],[[2433,2435],"valid"],[[2436,2436],"disallowed"],[[2437,2444],"valid"],[[2445,2446],"disallowed"],[[2447,2448],"valid"],[[2449,2450],"disallowed"],[[2451,2472],"valid"],[[2473,2473],"disallowed"],[[2474,2480],"valid"],[[2481,2481],"disallowed"],[[2482,2482],"valid"],[[2483,2485],"disallowed"],[[2486,2489],"valid"],[[2490,2491],"disallowed"],[[2492,2492],"valid"],[[2493,2493],"valid"],[[2494,2500],"valid"],[[2501,2502],"disallowed"],[[2503,2504],"valid"],[[2505,2506],"disallowed"],[[2507,2509],"valid"],[[2510,2510],"valid"],[[2511,2518],"disallowed"],[[2519,2519],"valid"],[[2520,2523],"disallowed"],[[2524,2524],"mapped",[2465,2492]],[[2525,2525],"mapped",[2466,2492]],[[2526,2526],"disallowed"],[[2527,2527],"mapped",[2479,2492]],[[2528,2531],"valid"],[[2532,2533],"disallowed"],[[2534,2545],"valid"],[[2546,2554],"valid",[],"NV8"],[[2555,2555],"valid",[],"NV8"],[[2556,2560],"disallowed"],[[2561,2561],"valid"],[[2562,2562],"valid"],[[2563,2563],"valid"],[[2564,2564],"disallowed"],[[2565,2570],"valid"],[[2571,2574],"disallowed"],[[2575,2576],"valid"],[[2577,2578],"disallowed"],[[2579,2600],"valid"],[[2601,2601],"disallowed"],[[2602,2608],"valid"],[[2609,2609],"disallowed"],[[2610,2610],"valid"],[[2611,2611],"mapped",[2610,2620]],[[2612,2612],"disallowed"],[[2613,2613],"valid"],[[2614,2614],"mapped",[2616,2620]],[[2615,2615],"disallowed"],[[2616,2617],"valid"],[[2618,2619],"disallowed"],[[2620,2620],"valid"],[[2621,2621],"disallowed"],[[2622,2626],"valid"],[[2627,2630],"disallowed"],[[2631,2632],"valid"],[[2633,2634],"disallowed"],[[2635,2637],"valid"],[[2638,2640],"disallowed"],[[2641,2641],"valid"],[[2642,2648],"disallowed"],[[2649,2649],"mapped",[2582,2620]],[[2650,2650],"mapped",[2583,2620]],[[2651,2651],"mapped",[2588,2620]],[[2652,2652],"valid"],[[2653,2653],"disallowed"],[[2654,2654],"mapped",[2603,2620]],[[2655,2661],"disallowed"],[[2662,2676],"valid"],[[2677,2677],"valid"],[[2678,2688],"disallowed"],[[2689,2691],"valid"],[[2692,2692],"disallowed"],[[2693,2699],"valid"],[[2700,2700],"valid"],[[2701,2701],"valid"],[[2702,2702],"disallowed"],[[2703,2705],"valid"],[[2706,2706],"disallowed"],[[2707,2728],"valid"],[[2729,2729],"disallowed"],[[2730,2736],"valid"],[[2737,2737],"disallowed"],[[2738,2739],"valid"],[[2740,2740],"disallowed"],[[2741,2745],"valid"],[[2746,2747],"disallowed"],[[2748,2757],"valid"],[[2758,2758],"disallowed"],[[2759,2761],"valid"],[[2762,2762],"disallowed"],[[2763,2765],"valid"],[[2766,2767],"disallowed"],[[2768,2768],"valid"],[[2769,2783],"disallowed"],[[2784,2784],"valid"],[[2785,2787],"valid"],[[2788,2789],"disallowed"],[[2790,2799],"valid"],[[2800,2800],"valid",[],"NV8"],[[2801,2801],"valid",[],"NV8"],[[2802,2808],"disallowed"],[[2809,2809],"valid"],[[2810,2816],"disallowed"],[[2817,2819],"valid"],[[2820,2820],"disallowed"],[[2821,2828],"valid"],[[2829,2830],"disallowed"],[[2831,2832],"valid"],[[2833,2834],"disallowed"],[[2835,2856],"valid"],[[2857,2857],"disallowed"],[[2858,2864],"valid"],[[2865,2865],"disallowed"],[[2866,2867],"valid"],[[2868,2868],"disallowed"],[[2869,2869],"valid"],[[2870,2873],"valid"],[[2874,2875],"disallowed"],[[2876,2883],"valid"],[[2884,2884],"valid"],[[2885,2886],"disallowed"],[[2887,2888],"valid"],[[2889,2890],"disallowed"],[[2891,2893],"valid"],[[2894,2901],"disallowed"],[[2902,2903],"valid"],[[2904,2907],"disallowed"],[[2908,2908],"mapped",[2849,2876]],[[2909,2909],"mapped",[2850,2876]],[[2910,2910],"disallowed"],[[2911,2913],"valid"],[[2914,2915],"valid"],[[2916,2917],"disallowed"],[[2918,2927],"valid"],[[2928,2928],"valid",[],"NV8"],[[2929,2929],"valid"],[[2930,2935],"valid",[],"NV8"],[[2936,2945],"disallowed"],[[2946,2947],"valid"],[[2948,2948],"disallowed"],[[2949,2954],"valid"],[[2955,2957],"disallowed"],[[2958,2960],"valid"],[[2961,2961],"disallowed"],[[2962,2965],"valid"],[[2966,2968],"disallowed"],[[2969,2970],"valid"],[[2971,2971],"disallowed"],[[2972,2972],"valid"],[[2973,2973],"disallowed"],[[2974,2975],"valid"],[[2976,2978],"disallowed"],[[2979,2980],"valid"],[[2981,2983],"disallowed"],[[2984,2986],"valid"],[[2987,2989],"disallowed"],[[2990,2997],"valid"],[[2998,2998],"valid"],[[2999,3001],"valid"],[[3002,3005],"disallowed"],[[3006,3010],"valid"],[[3011,3013],"disallowed"],[[3014,3016],"valid"],[[3017,3017],"disallowed"],[[3018,3021],"valid"],[[3022,3023],"disallowed"],[[3024,3024],"valid"],[[3025,3030],"disallowed"],[[3031,3031],"valid"],[[3032,3045],"disallowed"],[[3046,3046],"valid"],[[3047,3055],"valid"],[[3056,3058],"valid",[],"NV8"],[[3059,3066],"valid",[],"NV8"],[[3067,3071],"disallowed"],[[3072,3072],"valid"],[[3073,3075],"valid"],[[3076,3076],"disallowed"],[[3077,3084],"valid"],[[3085,3085],"disallowed"],[[3086,3088],"valid"],[[3089,3089],"disallowed"],[[3090,3112],"valid"],[[3113,3113],"disallowed"],[[3114,3123],"valid"],[[3124,3124],"valid"],[[3125,3129],"valid"],[[3130,3132],"disallowed"],[[3133,3133],"valid"],[[3134,3140],"valid"],[[3141,3141],"disallowed"],[[3142,3144],"valid"],[[3145,3145],"disallowed"],[[3146,3149],"valid"],[[3150,3156],"disallowed"],[[3157,3158],"valid"],[[3159,3159],"disallowed"],[[3160,3161],"valid"],[[3162,3162],"valid"],[[3163,3167],"disallowed"],[[3168,3169],"valid"],[[3170,3171],"valid"],[[3172,3173],"disallowed"],[[3174,3183],"valid"],[[3184,3191],"disallowed"],[[3192,3199],"valid",[],"NV8"],[[3200,3200],"disallowed"],[[3201,3201],"valid"],[[3202,3203],"valid"],[[3204,3204],"disallowed"],[[3205,3212],"valid"],[[3213,3213],"disallowed"],[[3214,3216],"valid"],[[3217,3217],"disallowed"],[[3218,3240],"valid"],[[3241,3241],"disallowed"],[[3242,3251],"valid"],[[3252,3252],"disallowed"],[[3253,3257],"valid"],[[3258,3259],"disallowed"],[[3260,3261],"valid"],[[3262,3268],"valid"],[[3269,3269],"disallowed"],[[3270,3272],"valid"],[[3273,3273],"disallowed"],[[3274,3277],"valid"],[[3278,3284],"disallowed"],[[3285,3286],"valid"],[[3287,3293],"disallowed"],[[3294,3294],"valid"],[[3295,3295],"disallowed"],[[3296,3297],"valid"],[[3298,3299],"valid"],[[3300,3301],"disallowed"],[[3302,3311],"valid"],[[3312,3312],"disallowed"],[[3313,3314],"valid"],[[3315,3328],"disallowed"],[[3329,3329],"valid"],[[3330,3331],"valid"],[[3332,3332],"disallowed"],[[3333,3340],"valid"],[[3341,3341],"disallowed"],[[3342,3344],"valid"],[[3345,3345],"disallowed"],[[3346,3368],"valid"],[[3369,3369],"valid"],[[3370,3385],"valid"],[[3386,3386],"valid"],[[3387,3388],"disallowed"],[[3389,3389],"valid"],[[3390,3395],"valid"],[[3396,3396],"valid"],[[3397,3397],"disallowed"],[[3398,3400],"valid"],[[3401,3401],"disallowed"],[[3402,3405],"valid"],[[3406,3406],"valid"],[[3407,3414],"disallowed"],[[3415,3415],"valid"],[[3416,3422],"disallowed"],[[3423,3423],"valid"],[[3424,3425],"valid"],[[3426,3427],"valid"],[[3428,3429],"disallowed"],[[3430,3439],"valid"],[[3440,3445],"valid",[],"NV8"],[[3446,3448],"disallowed"],[[3449,3449],"valid",[],"NV8"],[[3450,3455],"valid"],[[3456,3457],"disallowed"],[[3458,3459],"valid"],[[3460,3460],"disallowed"],[[3461,3478],"valid"],[[3479,3481],"disallowed"],[[3482,3505],"valid"],[[3506,3506],"disallowed"],[[3507,3515],"valid"],[[3516,3516],"disallowed"],[[3517,3517],"valid"],[[3518,3519],"disallowed"],[[3520,3526],"valid"],[[3527,3529],"disallowed"],[[3530,3530],"valid"],[[3531,3534],"disallowed"],[[3535,3540],"valid"],[[3541,3541],"disallowed"],[[3542,3542],"valid"],[[3543,3543],"disallowed"],[[3544,3551],"valid"],[[3552,3557],"disallowed"],[[3558,3567],"valid"],[[3568,3569],"disallowed"],[[3570,3571],"valid"],[[3572,3572],"valid",[],"NV8"],[[3573,3584],"disallowed"],[[3585,3634],"valid"],[[3635,3635],"mapped",[3661,3634]],[[3636,3642],"valid"],[[3643,3646],"disallowed"],[[3647,3647],"valid",[],"NV8"],[[3648,3662],"valid"],[[3663,3663],"valid",[],"NV8"],[[3664,3673],"valid"],[[3674,3675],"valid",[],"NV8"],[[3676,3712],"disallowed"],[[3713,3714],"valid"],[[3715,3715],"disallowed"],[[3716,3716],"valid"],[[3717,3718],"disallowed"],[[3719,3720],"valid"],[[3721,3721],"disallowed"],[[3722,3722],"valid"],[[3723,3724],"disallowed"],[[3725,3725],"valid"],[[3726,3731],"disallowed"],[[3732,3735],"valid"],[[3736,3736],"disallowed"],[[3737,3743],"valid"],[[3744,3744],"disallowed"],[[3745,3747],"valid"],[[3748,3748],"disallowed"],[[3749,3749],"valid"],[[3750,3750],"disallowed"],[[3751,3751],"valid"],[[3752,3753],"disallowed"],[[3754,3755],"valid"],[[3756,3756],"disallowed"],[[3757,3762],"valid"],[[3763,3763],"mapped",[3789,3762]],[[3764,3769],"valid"],[[3770,3770],"disallowed"],[[3771,3773],"valid"],[[3774,3775],"disallowed"],[[3776,3780],"valid"],[[3781,3781],"disallowed"],[[3782,3782],"valid"],[[3783,3783],"disallowed"],[[3784,3789],"valid"],[[3790,3791],"disallowed"],[[3792,3801],"valid"],[[3802,3803],"disallowed"],[[3804,3804],"mapped",[3755,3737]],[[3805,3805],"mapped",[3755,3745]],[[3806,3807],"valid"],[[3808,3839],"disallowed"],[[3840,3840],"valid"],[[3841,3850],"valid",[],"NV8"],[[3851,3851],"valid"],[[3852,3852],"mapped",[3851]],[[3853,3863],"valid",[],"NV8"],[[3864,3865],"valid"],[[3866,3871],"valid",[],"NV8"],[[3872,3881],"valid"],[[3882,3892],"valid",[],"NV8"],[[3893,3893],"valid"],[[3894,3894],"valid",[],"NV8"],[[3895,3895],"valid"],[[3896,3896],"valid",[],"NV8"],[[3897,3897],"valid"],[[3898,3901],"valid",[],"NV8"],[[3902,3906],"valid"],[[3907,3907],"mapped",[3906,4023]],[[3908,3911],"valid"],[[3912,3912],"disallowed"],[[3913,3916],"valid"],[[3917,3917],"mapped",[3916,4023]],[[3918,3921],"valid"],[[3922,3922],"mapped",[3921,4023]],[[3923,3926],"valid"],[[3927,3927],"mapped",[3926,4023]],[[3928,3931],"valid"],[[3932,3932],"mapped",[3931,4023]],[[3933,3944],"valid"],[[3945,3945],"mapped",[3904,4021]],[[3946,3946],"valid"],[[3947,3948],"valid"],[[3949,3952],"disallowed"],[[3953,3954],"valid"],[[3955,3955],"mapped",[3953,3954]],[[3956,3956],"valid"],[[3957,3957],"mapped",[3953,3956]],[[3958,3958],"mapped",[4018,3968]],[[3959,3959],"mapped",[4018,3953,3968]],[[3960,3960],"mapped",[4019,3968]],[[3961,3961],"mapped",[4019,3953,3968]],[[3962,3968],"valid"],[[3969,3969],"mapped",[3953,3968]],[[3970,3972],"valid"],[[3973,3973],"valid",[],"NV8"],[[3974,3979],"valid"],[[3980,3983],"valid"],[[3984,3986],"valid"],[[3987,3987],"mapped",[3986,4023]],[[3988,3989],"valid"],[[3990,3990],"valid"],[[3991,3991],"valid"],[[3992,3992],"disallowed"],[[3993,3996],"valid"],[[3997,3997],"mapped",[3996,4023]],[[3998,4001],"valid"],[[4002,4002],"mapped",[4001,4023]],[[4003,4006],"valid"],[[4007,4007],"mapped",[4006,4023]],[[4008,4011],"valid"],[[4012,4012],"mapped",[4011,4023]],[[4013,4013],"valid"],[[4014,4016],"valid"],[[4017,4023],"valid"],[[4024,4024],"valid"],[[4025,4025],"mapped",[3984,4021]],[[4026,4028],"valid"],[[4029,4029],"disallowed"],[[4030,4037],"valid",[],"NV8"],[[4038,4038],"valid"],[[4039,4044],"valid",[],"NV8"],[[4045,4045],"disallowed"],[[4046,4046],"valid",[],"NV8"],[[4047,4047],"valid",[],"NV8"],[[4048,4049],"valid",[],"NV8"],[[4050,4052],"valid",[],"NV8"],[[4053,4056],"valid",[],"NV8"],[[4057,4058],"valid",[],"NV8"],[[4059,4095],"disallowed"],[[4096,4129],"valid"],[[4130,4130],"valid"],[[4131,4135],"valid"],[[4136,4136],"valid"],[[4137,4138],"valid"],[[4139,4139],"valid"],[[4140,4146],"valid"],[[4147,4149],"valid"],[[4150,4153],"valid"],[[4154,4159],"valid"],[[4160,4169],"valid"],[[4170,4175],"valid",[],"NV8"],[[4176,4185],"valid"],[[4186,4249],"valid"],[[4250,4253],"valid"],[[4254,4255],"valid",[],"NV8"],[[4256,4293],"disallowed"],[[4294,4294],"disallowed"],[[4295,4295],"mapped",[11559]],[[4296,4300],"disallowed"],[[4301,4301],"mapped",[11565]],[[4302,4303],"disallowed"],[[4304,4342],"valid"],[[4343,4344],"valid"],[[4345,4346],"valid"],[[4347,4347],"valid",[],"NV8"],[[4348,4348],"mapped",[4316]],[[4349,4351],"valid"],[[4352,4441],"valid",[],"NV8"],[[4442,4446],"valid",[],"NV8"],[[4447,4448],"disallowed"],[[4449,4514],"valid",[],"NV8"],[[4515,4519],"valid",[],"NV8"],[[4520,4601],"valid",[],"NV8"],[[4602,4607],"valid",[],"NV8"],[[4608,4614],"valid"],[[4615,4615],"valid"],[[4616,4678],"valid"],[[4679,4679],"valid"],[[4680,4680],"valid"],[[4681,4681],"disallowed"],[[4682,4685],"valid"],[[4686,4687],"disallowed"],[[4688,4694],"valid"],[[4695,4695],"disallowed"],[[4696,4696],"valid"],[[4697,4697],"disallowed"],[[4698,4701],"valid"],[[4702,4703],"disallowed"],[[4704,4742],"valid"],[[4743,4743],"valid"],[[4744,4744],"valid"],[[4745,4745],"disallowed"],[[4746,4749],"valid"],[[4750,4751],"disallowed"],[[4752,4782],"valid"],[[4783,4783],"valid"],[[4784,4784],"valid"],[[4785,4785],"disallowed"],[[4786,4789],"valid"],[[4790,4791],"disallowed"],[[4792,4798],"valid"],[[4799,4799],"disallowed"],[[4800,4800],"valid"],[[4801,4801],"disallowed"],[[4802,4805],"valid"],[[4806,4807],"disallowed"],[[4808,4814],"valid"],[[4815,4815],"valid"],[[4816,4822],"valid"],[[4823,4823],"disallowed"],[[4824,4846],"valid"],[[4847,4847],"valid"],[[4848,4878],"valid"],[[4879,4879],"valid"],[[4880,4880],"valid"],[[4881,4881],"disallowed"],[[4882,4885],"valid"],[[4886,4887],"disallowed"],[[4888,4894],"valid"],[[4895,4895],"valid"],[[4896,4934],"valid"],[[4935,4935],"valid"],[[4936,4954],"valid"],[[4955,4956],"disallowed"],[[4957,4958],"valid"],[[4959,4959],"valid"],[[4960,4960],"valid",[],"NV8"],[[4961,4988],"valid",[],"NV8"],[[4989,4991],"disallowed"],[[4992,5007],"valid"],[[5008,5017],"valid",[],"NV8"],[[5018,5023],"disallowed"],[[5024,5108],"valid"],[[5109,5109],"valid"],[[5110,5111],"disallowed"],[[5112,5112],"mapped",[5104]],[[5113,5113],"mapped",[5105]],[[5114,5114],"mapped",[5106]],[[5115,5115],"mapped",[5107]],[[5116,5116],"mapped",[5108]],[[5117,5117],"mapped",[5109]],[[5118,5119],"disallowed"],[[5120,5120],"valid",[],"NV8"],[[5121,5740],"valid"],[[5741,5742],"valid",[],"NV8"],[[5743,5750],"valid"],[[5751,5759],"valid"],[[5760,5760],"disallowed"],[[5761,5786],"valid"],[[5787,5788],"valid",[],"NV8"],[[5789,5791],"disallowed"],[[5792,5866],"valid"],[[5867,5872],"valid",[],"NV8"],[[5873,5880],"valid"],[[5881,5887],"disallowed"],[[5888,5900],"valid"],[[5901,5901],"disallowed"],[[5902,5908],"valid"],[[5909,5919],"disallowed"],[[5920,5940],"valid"],[[5941,5942],"valid",[],"NV8"],[[5943,5951],"disallowed"],[[5952,5971],"valid"],[[5972,5983],"disallowed"],[[5984,5996],"valid"],[[5997,5997],"disallowed"],[[5998,6000],"valid"],[[6001,6001],"disallowed"],[[6002,6003],"valid"],[[6004,6015],"disallowed"],[[6016,6067],"valid"],[[6068,6069],"disallowed"],[[6070,6099],"valid"],[[6100,6102],"valid",[],"NV8"],[[6103,6103],"valid"],[[6104,6107],"valid",[],"NV8"],[[6108,6108],"valid"],[[6109,6109],"valid"],[[6110,6111],"disallowed"],[[6112,6121],"valid"],[[6122,6127],"disallowed"],[[6128,6137],"valid",[],"NV8"],[[6138,6143],"disallowed"],[[6144,6149],"valid",[],"NV8"],[[6150,6150],"disallowed"],[[6151,6154],"valid",[],"NV8"],[[6155,6157],"ignored"],[[6158,6158],"disallowed"],[[6159,6159],"disallowed"],[[6160,6169],"valid"],[[6170,6175],"disallowed"],[[6176,6263],"valid"],[[6264,6271],"disallowed"],[[6272,6313],"valid"],[[6314,6314],"valid"],[[6315,6319],"disallowed"],[[6320,6389],"valid"],[[6390,6399],"disallowed"],[[6400,6428],"valid"],[[6429,6430],"valid"],[[6431,6431],"disallowed"],[[6432,6443],"valid"],[[6444,6447],"disallowed"],[[6448,6459],"valid"],[[6460,6463],"disallowed"],[[6464,6464],"valid",[],"NV8"],[[6465,6467],"disallowed"],[[6468,6469],"valid",[],"NV8"],[[6470,6509],"valid"],[[6510,6511],"disallowed"],[[6512,6516],"valid"],[[6517,6527],"disallowed"],[[6528,6569],"valid"],[[6570,6571],"valid"],[[6572,6575],"disallowed"],[[6576,6601],"valid"],[[6602,6607],"disallowed"],[[6608,6617],"valid"],[[6618,6618],"valid",[],"XV8"],[[6619,6621],"disallowed"],[[6622,6623],"valid",[],"NV8"],[[6624,6655],"valid",[],"NV8"],[[6656,6683],"valid"],[[6684,6685],"disallowed"],[[6686,6687],"valid",[],"NV8"],[[6688,6750],"valid"],[[6751,6751],"disallowed"],[[6752,6780],"valid"],[[6781,6782],"disallowed"],[[6783,6793],"valid"],[[6794,6799],"disallowed"],[[6800,6809],"valid"],[[6810,6815],"disallowed"],[[6816,6822],"valid",[],"NV8"],[[6823,6823],"valid"],[[6824,6829],"valid",[],"NV8"],[[6830,6831],"disallowed"],[[6832,6845],"valid"],[[6846,6846],"valid",[],"NV8"],[[6847,6911],"disallowed"],[[6912,6987],"valid"],[[6988,6991],"disallowed"],[[6992,7001],"valid"],[[7002,7018],"valid",[],"NV8"],[[7019,7027],"valid"],[[7028,7036],"valid",[],"NV8"],[[7037,7039],"disallowed"],[[7040,7082],"valid"],[[7083,7085],"valid"],[[7086,7097],"valid"],[[7098,7103],"valid"],[[7104,7155],"valid"],[[7156,7163],"disallowed"],[[7164,7167],"valid",[],"NV8"],[[7168,7223],"valid"],[[7224,7226],"disallowed"],[[7227,7231],"valid",[],"NV8"],[[7232,7241],"valid"],[[7242,7244],"disallowed"],[[7245,7293],"valid"],[[7294,7295],"valid",[],"NV8"],[[7296,7359],"disallowed"],[[7360,7367],"valid",[],"NV8"],[[7368,7375],"disallowed"],[[7376,7378],"valid"],[[7379,7379],"valid",[],"NV8"],[[7380,7410],"valid"],[[7411,7414],"valid"],[[7415,7415],"disallowed"],[[7416,7417],"valid"],[[7418,7423],"disallowed"],[[7424,7467],"valid"],[[7468,7468],"mapped",[97]],[[7469,7469],"mapped",[230]],[[7470,7470],"mapped",[98]],[[7471,7471],"valid"],[[7472,7472],"mapped",[100]],[[7473,7473],"mapped",[101]],[[7474,7474],"mapped",[477]],[[7475,7475],"mapped",[103]],[[7476,7476],"mapped",[104]],[[7477,7477],"mapped",[105]],[[7478,7478],"mapped",[106]],[[7479,7479],"mapped",[107]],[[7480,7480],"mapped",[108]],[[7481,7481],"mapped",[109]],[[7482,7482],"mapped",[110]],[[7483,7483],"valid"],[[7484,7484],"mapped",[111]],[[7485,7485],"mapped",[547]],[[7486,7486],"mapped",[112]],[[7487,7487],"mapped",[114]],[[7488,7488],"mapped",[116]],[[7489,7489],"mapped",[117]],[[7490,7490],"mapped",[119]],[[7491,7491],"mapped",[97]],[[7492,7492],"mapped",[592]],[[7493,7493],"mapped",[593]],[[7494,7494],"mapped",[7426]],[[7495,7495],"mapped",[98]],[[7496,7496],"mapped",[100]],[[7497,7497],"mapped",[101]],[[7498,7498],"mapped",[601]],[[7499,7499],"mapped",[603]],[[7500,7500],"mapped",[604]],[[7501,7501],"mapped",[103]],[[7502,7502],"valid"],[[7503,7503],"mapped",[107]],[[7504,7504],"mapped",[109]],[[7505,7505],"mapped",[331]],[[7506,7506],"mapped",[111]],[[7507,7507],"mapped",[596]],[[7508,7508],"mapped",[7446]],[[7509,7509],"mapped",[7447]],[[7510,7510],"mapped",[112]],[[7511,7511],"mapped",[116]],[[7512,7512],"mapped",[117]],[[7513,7513],"mapped",[7453]],[[7514,7514],"mapped",[623]],[[7515,7515],"mapped",[118]],[[7516,7516],"mapped",[7461]],[[7517,7517],"mapped",[946]],[[7518,7518],"mapped",[947]],[[7519,7519],"mapped",[948]],[[7520,7520],"mapped",[966]],[[7521,7521],"mapped",[967]],[[7522,7522],"mapped",[105]],[[7523,7523],"mapped",[114]],[[7524,7524],"mapped",[117]],[[7525,7525],"mapped",[118]],[[7526,7526],"mapped",[946]],[[7527,7527],"mapped",[947]],[[7528,7528],"mapped",[961]],[[7529,7529],"mapped",[966]],[[7530,7530],"mapped",[967]],[[7531,7531],"valid"],[[7532,7543],"valid"],[[7544,7544],"mapped",[1085]],[[7545,7578],"valid"],[[7579,7579],"mapped",[594]],[[7580,7580],"mapped",[99]],[[7581,7581],"mapped",[597]],[[7582,7582],"mapped",[240]],[[7583,7583],"mapped",[604]],[[7584,7584],"mapped",[102]],[[7585,7585],"mapped",[607]],[[7586,7586],"mapped",[609]],[[7587,7587],"mapped",[613]],[[7588,7588],"mapped",[616]],[[7589,7589],"mapped",[617]],[[7590,7590],"mapped",[618]],[[7591,7591],"mapped",[7547]],[[7592,7592],"mapped",[669]],[[7593,7593],"mapped",[621]],[[7594,7594],"mapped",[7557]],[[7595,7595],"mapped",[671]],[[7596,7596],"mapped",[625]],[[7597,7597],"mapped",[624]],[[7598,7598],"mapped",[626]],[[7599,7599],"mapped",[627]],[[7600,7600],"mapped",[628]],[[7601,7601],"mapped",[629]],[[7602,7602],"mapped",[632]],[[7603,7603],"mapped",[642]],[[7604,7604],"mapped",[643]],[[7605,7605],"mapped",[427]],[[7606,7606],"mapped",[649]],[[7607,7607],"mapped",[650]],[[7608,7608],"mapped",[7452]],[[7609,7609],"mapped",[651]],[[7610,7610],"mapped",[652]],[[7611,7611],"mapped",[122]],[[7612,7612],"mapped",[656]],[[7613,7613],"mapped",[657]],[[7614,7614],"mapped",[658]],[[7615,7615],"mapped",[952]],[[7616,7619],"valid"],[[7620,7626],"valid"],[[7627,7654],"valid"],[[7655,7669],"valid"],[[7670,7675],"disallowed"],[[7676,7676],"valid"],[[7677,7677],"valid"],[[7678,7679],"valid"],[[7680,7680],"mapped",[7681]],[[7681,7681],"valid"],[[7682,7682],"mapped",[7683]],[[7683,7683],"valid"],[[7684,7684],"mapped",[7685]],[[7685,7685],"valid"],[[7686,7686],"mapped",[7687]],[[7687,7687],"valid"],[[7688,7688],"mapped",[7689]],[[7689,7689],"valid"],[[7690,7690],"mapped",[7691]],[[7691,7691],"valid"],[[7692,7692],"mapped",[7693]],[[7693,7693],"valid"],[[7694,7694],"mapped",[7695]],[[7695,7695],"valid"],[[7696,7696],"mapped",[7697]],[[7697,7697],"valid"],[[7698,7698],"mapped",[7699]],[[7699,7699],"valid"],[[7700,7700],"mapped",[7701]],[[7701,7701],"valid"],[[7702,7702],"mapped",[7703]],[[7703,7703],"valid"],[[7704,7704],"mapped",[7705]],[[7705,7705],"valid"],[[7706,7706],"mapped",[7707]],[[7707,7707],"valid"],[[7708,7708],"mapped",[7709]],[[7709,7709],"valid"],[[7710,7710],"mapped",[7711]],[[7711,7711],"valid"],[[7712,7712],"mapped",[7713]],[[7713,7713],"valid"],[[7714,7714],"mapped",[7715]],[[7715,7715],"valid"],[[7716,7716],"mapped",[7717]],[[7717,7717],"valid"],[[7718,7718],"mapped",[7719]],[[7719,7719],"valid"],[[7720,7720],"mapped",[7721]],[[7721,7721],"valid"],[[7722,7722],"mapped",[7723]],[[7723,7723],"valid"],[[7724,7724],"mapped",[7725]],[[7725,7725],"valid"],[[7726,7726],"mapped",[7727]],[[7727,7727],"valid"],[[7728,7728],"mapped",[7729]],[[7729,7729],"valid"],[[7730,7730],"mapped",[7731]],[[7731,7731],"valid"],[[7732,7732],"mapped",[7733]],[[7733,7733],"valid"],[[7734,7734],"mapped",[7735]],[[7735,7735],"valid"],[[7736,7736],"mapped",[7737]],[[7737,7737],"valid"],[[7738,7738],"mapped",[7739]],[[7739,7739],"valid"],[[7740,7740],"mapped",[7741]],[[7741,7741],"valid"],[[7742,7742],"mapped",[7743]],[[7743,7743],"valid"],[[7744,7744],"mapped",[7745]],[[7745,7745],"valid"],[[7746,7746],"mapped",[7747]],[[7747,7747],"valid"],[[7748,7748],"mapped",[7749]],[[7749,7749],"valid"],[[7750,7750],"mapped",[7751]],[[7751,7751],"valid"],[[7752,7752],"mapped",[7753]],[[7753,7753],"valid"],[[7754,7754],"mapped",[7755]],[[7755,7755],"valid"],[[7756,7756],"mapped",[7757]],[[7757,7757],"valid"],[[7758,7758],"mapped",[7759]],[[7759,7759],"valid"],[[7760,7760],"mapped",[7761]],[[7761,7761],"valid"],[[7762,7762],"mapped",[7763]],[[7763,7763],"valid"],[[7764,7764],"mapped",[7765]],[[7765,7765],"valid"],[[7766,7766],"mapped",[7767]],[[7767,7767],"valid"],[[7768,7768],"mapped",[7769]],[[7769,7769],"valid"],[[7770,7770],"mapped",[7771]],[[7771,7771],"valid"],[[7772,7772],"mapped",[7773]],[[7773,7773],"valid"],[[7774,7774],"mapped",[7775]],[[7775,7775],"valid"],[[7776,7776],"mapped",[7777]],[[7777,7777],"valid"],[[7778,7778],"mapped",[7779]],[[7779,7779],"valid"],[[7780,7780],"mapped",[7781]],[[7781,7781],"valid"],[[7782,7782],"mapped",[7783]],[[7783,7783],"valid"],[[7784,7784],"mapped",[7785]],[[7785,7785],"valid"],[[7786,7786],"mapped",[7787]],[[7787,7787],"valid"],[[7788,7788],"mapped",[7789]],[[7789,7789],"valid"],[[7790,7790],"mapped",[7791]],[[7791,7791],"valid"],[[7792,7792],"mapped",[7793]],[[7793,7793],"valid"],[[7794,7794],"mapped",[7795]],[[7795,7795],"valid"],[[7796,7796],"mapped",[7797]],[[7797,7797],"valid"],[[7798,7798],"mapped",[7799]],[[7799,7799],"valid"],[[7800,7800],"mapped",[7801]],[[7801,7801],"valid"],[[7802,7802],"mapped",[7803]],[[7803,7803],"valid"],[[7804,7804],"mapped",[7805]],[[7805,7805],"valid"],[[7806,7806],"mapped",[7807]],[[7807,7807],"valid"],[[7808,7808],"mapped",[7809]],[[7809,7809],"valid"],[[7810,7810],"mapped",[7811]],[[7811,7811],"valid"],[[7812,7812],"mapped",[7813]],[[7813,7813],"valid"],[[7814,7814],"mapped",[7815]],[[7815,7815],"valid"],[[7816,7816],"mapped",[7817]],[[7817,7817],"valid"],[[7818,7818],"mapped",[7819]],[[7819,7819],"valid"],[[7820,7820],"mapped",[7821]],[[7821,7821],"valid"],[[7822,7822],"mapped",[7823]],[[7823,7823],"valid"],[[7824,7824],"mapped",[7825]],[[7825,7825],"valid"],[[7826,7826],"mapped",[7827]],[[7827,7827],"valid"],[[7828,7828],"mapped",[7829]],[[7829,7833],"valid"],[[7834,7834],"mapped",[97,702]],[[7835,7835],"mapped",[7777]],[[7836,7837],"valid"],[[7838,7838],"mapped",[115,115]],[[7839,7839],"valid"],[[7840,7840],"mapped",[7841]],[[7841,7841],"valid"],[[7842,7842],"mapped",[7843]],[[7843,7843],"valid"],[[7844,7844],"mapped",[7845]],[[7845,7845],"valid"],[[7846,7846],"mapped",[7847]],[[7847,7847],"valid"],[[7848,7848],"mapped",[7849]],[[7849,7849],"valid"],[[7850,7850],"mapped",[7851]],[[7851,7851],"valid"],[[7852,7852],"mapped",[7853]],[[7853,7853],"valid"],[[7854,7854],"mapped",[7855]],[[7855,7855],"valid"],[[7856,7856],"mapped",[7857]],[[7857,7857],"valid"],[[7858,7858],"mapped",[7859]],[[7859,7859],"valid"],[[7860,7860],"mapped",[7861]],[[7861,7861],"valid"],[[7862,7862],"mapped",[7863]],[[7863,7863],"valid"],[[7864,7864],"mapped",[7865]],[[7865,7865],"valid"],[[7866,7866],"mapped",[7867]],[[7867,7867],"valid"],[[7868,7868],"mapped",[7869]],[[7869,7869],"valid"],[[7870,7870],"mapped",[7871]],[[7871,7871],"valid"],[[7872,7872],"mapped",[7873]],[[7873,7873],"valid"],[[7874,7874],"mapped",[7875]],[[7875,7875],"valid"],[[7876,7876],"mapped",[7877]],[[7877,7877],"valid"],[[7878,7878],"mapped",[7879]],[[7879,7879],"valid"],[[7880,7880],"mapped",[7881]],[[7881,7881],"valid"],[[7882,7882],"mapped",[7883]],[[7883,7883],"valid"],[[7884,7884],"mapped",[7885]],[[7885,7885],"valid"],[[7886,7886],"mapped",[7887]],[[7887,7887],"valid"],[[7888,7888],"mapped",[7889]],[[7889,7889],"valid"],[[7890,7890],"mapped",[7891]],[[7891,7891],"valid"],[[7892,7892],"mapped",[7893]],[[7893,7893],"valid"],[[7894,7894],"mapped",[7895]],[[7895,7895],"valid"],[[7896,7896],"mapped",[7897]],[[7897,7897],"valid"],[[7898,7898],"mapped",[7899]],[[7899,7899],"valid"],[[7900,7900],"mapped",[7901]],[[7901,7901],"valid"],[[7902,7902],"mapped",[7903]],[[7903,7903],"valid"],[[7904,7904],"mapped",[7905]],[[7905,7905],"valid"],[[7906,7906],"mapped",[7907]],[[7907,7907],"valid"],[[7908,7908],"mapped",[7909]],[[7909,7909],"valid"],[[7910,7910],"mapped",[7911]],[[7911,7911],"valid"],[[7912,7912],"mapped",[7913]],[[7913,7913],"valid"],[[7914,7914],"mapped",[7915]],[[7915,7915],"valid"],[[7916,7916],"mapped",[7917]],[[7917,7917],"valid"],[[7918,7918],"mapped",[7919]],[[7919,7919],"valid"],[[7920,7920],"mapped",[7921]],[[7921,7921],"valid"],[[7922,7922],"mapped",[7923]],[[7923,7923],"valid"],[[7924,7924],"mapped",[7925]],[[7925,7925],"valid"],[[7926,7926],"mapped",[7927]],[[7927,7927],"valid"],[[7928,7928],"mapped",[7929]],[[7929,7929],"valid"],[[7930,7930],"mapped",[7931]],[[7931,7931],"valid"],[[7932,7932],"mapped",[7933]],[[7933,7933],"valid"],[[7934,7934],"mapped",[7935]],[[7935,7935],"valid"],[[7936,7943],"valid"],[[7944,7944],"mapped",[7936]],[[7945,7945],"mapped",[7937]],[[7946,7946],"mapped",[7938]],[[7947,7947],"mapped",[7939]],[[7948,7948],"mapped",[7940]],[[7949,7949],"mapped",[7941]],[[7950,7950],"mapped",[7942]],[[7951,7951],"mapped",[7943]],[[7952,7957],"valid"],[[7958,7959],"disallowed"],[[7960,7960],"mapped",[7952]],[[7961,7961],"mapped",[7953]],[[7962,7962],"mapped",[7954]],[[7963,7963],"mapped",[7955]],[[7964,7964],"mapped",[7956]],[[7965,7965],"mapped",[7957]],[[7966,7967],"disallowed"],[[7968,7975],"valid"],[[7976,7976],"mapped",[7968]],[[7977,7977],"mapped",[7969]],[[7978,7978],"mapped",[7970]],[[7979,7979],"mapped",[7971]],[[7980,7980],"mapped",[7972]],[[7981,7981],"mapped",[7973]],[[7982,7982],"mapped",[7974]],[[7983,7983],"mapped",[7975]],[[7984,7991],"valid"],[[7992,7992],"mapped",[7984]],[[7993,7993],"mapped",[7985]],[[7994,7994],"mapped",[7986]],[[7995,7995],"mapped",[7987]],[[7996,7996],"mapped",[7988]],[[7997,7997],"mapped",[7989]],[[7998,7998],"mapped",[7990]],[[7999,7999],"mapped",[7991]],[[8000,8005],"valid"],[[8006,8007],"disallowed"],[[8008,8008],"mapped",[8000]],[[8009,8009],"mapped",[8001]],[[8010,8010],"mapped",[8002]],[[8011,8011],"mapped",[8003]],[[8012,8012],"mapped",[8004]],[[8013,8013],"mapped",[8005]],[[8014,8015],"disallowed"],[[8016,8023],"valid"],[[8024,8024],"disallowed"],[[8025,8025],"mapped",[8017]],[[8026,8026],"disallowed"],[[8027,8027],"mapped",[8019]],[[8028,8028],"disallowed"],[[8029,8029],"mapped",[8021]],[[8030,8030],"disallowed"],[[8031,8031],"mapped",[8023]],[[8032,8039],"valid"],[[8040,8040],"mapped",[8032]],[[8041,8041],"mapped",[8033]],[[8042,8042],"mapped",[8034]],[[8043,8043],"mapped",[8035]],[[8044,8044],"mapped",[8036]],[[8045,8045],"mapped",[8037]],[[8046,8046],"mapped",[8038]],[[8047,8047],"mapped",[8039]],[[8048,8048],"valid"],[[8049,8049],"mapped",[940]],[[8050,8050],"valid"],[[8051,8051],"mapped",[941]],[[8052,8052],"valid"],[[8053,8053],"mapped",[942]],[[8054,8054],"valid"],[[8055,8055],"mapped",[943]],[[8056,8056],"valid"],[[8057,8057],"mapped",[972]],[[8058,8058],"valid"],[[8059,8059],"mapped",[973]],[[8060,8060],"valid"],[[8061,8061],"mapped",[974]],[[8062,8063],"disallowed"],[[8064,8064],"mapped",[7936,953]],[[8065,8065],"mapped",[7937,953]],[[8066,8066],"mapped",[7938,953]],[[8067,8067],"mapped",[7939,953]],[[8068,8068],"mapped",[7940,953]],[[8069,8069],"mapped",[7941,953]],[[8070,8070],"mapped",[7942,953]],[[8071,8071],"mapped",[7943,953]],[[8072,8072],"mapped",[7936,953]],[[8073,8073],"mapped",[7937,953]],[[8074,8074],"mapped",[7938,953]],[[8075,8075],"mapped",[7939,953]],[[8076,8076],"mapped",[7940,953]],[[8077,8077],"mapped",[7941,953]],[[8078,8078],"mapped",[7942,953]],[[8079,8079],"mapped",[7943,953]],[[8080,8080],"mapped",[7968,953]],[[8081,8081],"mapped",[7969,953]],[[8082,8082],"mapped",[7970,953]],[[8083,8083],"mapped",[7971,953]],[[8084,8084],"mapped",[7972,953]],[[8085,8085],"mapped",[7973,953]],[[8086,8086],"mapped",[7974,953]],[[8087,8087],"mapped",[7975,953]],[[8088,8088],"mapped",[7968,953]],[[8089,8089],"mapped",[7969,953]],[[8090,8090],"mapped",[7970,953]],[[8091,8091],"mapped",[7971,953]],[[8092,8092],"mapped",[7972,953]],[[8093,8093],"mapped",[7973,953]],[[8094,8094],"mapped",[7974,953]],[[8095,8095],"mapped",[7975,953]],[[8096,8096],"mapped",[8032,953]],[[8097,8097],"mapped",[8033,953]],[[8098,8098],"mapped",[8034,953]],[[8099,8099],"mapped",[8035,953]],[[8100,8100],"mapped",[8036,953]],[[8101,8101],"mapped",[8037,953]],[[8102,8102],"mapped",[8038,953]],[[8103,8103],"mapped",[8039,953]],[[8104,8104],"mapped",[8032,953]],[[8105,8105],"mapped",[8033,953]],[[8106,8106],"mapped",[8034,953]],[[8107,8107],"mapped",[8035,953]],[[8108,8108],"mapped",[8036,953]],[[8109,8109],"mapped",[8037,953]],[[8110,8110],"mapped",[8038,953]],[[8111,8111],"mapped",[8039,953]],[[8112,8113],"valid"],[[8114,8114],"mapped",[8048,953]],[[8115,8115],"mapped",[945,953]],[[8116,8116],"mapped",[940,953]],[[8117,8117],"disallowed"],[[8118,8118],"valid"],[[8119,8119],"mapped",[8118,953]],[[8120,8120],"mapped",[8112]],[[8121,8121],"mapped",[8113]],[[8122,8122],"mapped",[8048]],[[8123,8123],"mapped",[940]],[[8124,8124],"mapped",[945,953]],[[8125,8125],"disallowed_STD3_mapped",[32,787]],[[8126,8126],"mapped",[953]],[[8127,8127],"disallowed_STD3_mapped",[32,787]],[[8128,8128],"disallowed_STD3_mapped",[32,834]],[[8129,8129],"disallowed_STD3_mapped",[32,776,834]],[[8130,8130],"mapped",[8052,953]],[[8131,8131],"mapped",[951,953]],[[8132,8132],"mapped",[942,953]],[[8133,8133],"disallowed"],[[8134,8134],"valid"],[[8135,8135],"mapped",[8134,953]],[[8136,8136],"mapped",[8050]],[[8137,8137],"mapped",[941]],[[8138,8138],"mapped",[8052]],[[8139,8139],"mapped",[942]],[[8140,8140],"mapped",[951,953]],[[8141,8141],"disallowed_STD3_mapped",[32,787,768]],[[8142,8142],"disallowed_STD3_mapped",[32,787,769]],[[8143,8143],"disallowed_STD3_mapped",[32,787,834]],[[8144,8146],"valid"],[[8147,8147],"mapped",[912]],[[8148,8149],"disallowed"],[[8150,8151],"valid"],[[8152,8152],"mapped",[8144]],[[8153,8153],"mapped",[8145]],[[8154,8154],"mapped",[8054]],[[8155,8155],"mapped",[943]],[[8156,8156],"disallowed"],[[8157,8157],"disallowed_STD3_mapped",[32,788,768]],[[8158,8158],"disallowed_STD3_mapped",[32,788,769]],[[8159,8159],"disallowed_STD3_mapped",[32,788,834]],[[8160,8162],"valid"],[[8163,8163],"mapped",[944]],[[8164,8167],"valid"],[[8168,8168],"mapped",[8160]],[[8169,8169],"mapped",[8161]],[[8170,8170],"mapped",[8058]],[[8171,8171],"mapped",[973]],[[8172,8172],"mapped",[8165]],[[8173,8173],"disallowed_STD3_mapped",[32,776,768]],[[8174,8174],"disallowed_STD3_mapped",[32,776,769]],[[8175,8175],"disallowed_STD3_mapped",[96]],[[8176,8177],"disallowed"],[[8178,8178],"mapped",[8060,953]],[[8179,8179],"mapped",[969,953]],[[8180,8180],"mapped",[974,953]],[[8181,8181],"disallowed"],[[8182,8182],"valid"],[[8183,8183],"mapped",[8182,953]],[[8184,8184],"mapped",[8056]],[[8185,8185],"mapped",[972]],[[8186,8186],"mapped",[8060]],[[8187,8187],"mapped",[974]],[[8188,8188],"mapped",[969,953]],[[8189,8189],"disallowed_STD3_mapped",[32,769]],[[8190,8190],"disallowed_STD3_mapped",[32,788]],[[8191,8191],"disallowed"],[[8192,8202],"disallowed_STD3_mapped",[32]],[[8203,8203],"ignored"],[[8204,8205],"deviation",[]],[[8206,8207],"disallowed"],[[8208,8208],"valid",[],"NV8"],[[8209,8209],"mapped",[8208]],[[8210,8214],"valid",[],"NV8"],[[8215,8215],"disallowed_STD3_mapped",[32,819]],[[8216,8227],"valid",[],"NV8"],[[8228,8230],"disallowed"],[[8231,8231],"valid",[],"NV8"],[[8232,8238],"disallowed"],[[8239,8239],"disallowed_STD3_mapped",[32]],[[8240,8242],"valid",[],"NV8"],[[8243,8243],"mapped",[8242,8242]],[[8244,8244],"mapped",[8242,8242,8242]],[[8245,8245],"valid",[],"NV8"],[[8246,8246],"mapped",[8245,8245]],[[8247,8247],"mapped",[8245,8245,8245]],[[8248,8251],"valid",[],"NV8"],[[8252,8252],"disallowed_STD3_mapped",[33,33]],[[8253,8253],"valid",[],"NV8"],[[8254,8254],"disallowed_STD3_mapped",[32,773]],[[8255,8262],"valid",[],"NV8"],[[8263,8263],"disallowed_STD3_mapped",[63,63]],[[8264,8264],"disallowed_STD3_mapped",[63,33]],[[8265,8265],"disallowed_STD3_mapped",[33,63]],[[8266,8269],"valid",[],"NV8"],[[8270,8274],"valid",[],"NV8"],[[8275,8276],"valid",[],"NV8"],[[8277,8278],"valid",[],"NV8"],[[8279,8279],"mapped",[8242,8242,8242,8242]],[[8280,8286],"valid",[],"NV8"],[[8287,8287],"disallowed_STD3_mapped",[32]],[[8288,8288],"ignored"],[[8289,8291],"disallowed"],[[8292,8292],"ignored"],[[8293,8293],"disallowed"],[[8294,8297],"disallowed"],[[8298,8303],"disallowed"],[[8304,8304],"mapped",[48]],[[8305,8305],"mapped",[105]],[[8306,8307],"disallowed"],[[8308,8308],"mapped",[52]],[[8309,8309],"mapped",[53]],[[8310,8310],"mapped",[54]],[[8311,8311],"mapped",[55]],[[8312,8312],"mapped",[56]],[[8313,8313],"mapped",[57]],[[8314,8314],"disallowed_STD3_mapped",[43]],[[8315,8315],"mapped",[8722]],[[8316,8316],"disallowed_STD3_mapped",[61]],[[8317,8317],"disallowed_STD3_mapped",[40]],[[8318,8318],"disallowed_STD3_mapped",[41]],[[8319,8319],"mapped",[110]],[[8320,8320],"mapped",[48]],[[8321,8321],"mapped",[49]],[[8322,8322],"mapped",[50]],[[8323,8323],"mapped",[51]],[[8324,8324],"mapped",[52]],[[8325,8325],"mapped",[53]],[[8326,8326],"mapped",[54]],[[8327,8327],"mapped",[55]],[[8328,8328],"mapped",[56]],[[8329,8329],"mapped",[57]],[[8330,8330],"disallowed_STD3_mapped",[43]],[[8331,8331],"mapped",[8722]],[[8332,8332],"disallowed_STD3_mapped",[61]],[[8333,8333],"disallowed_STD3_mapped",[40]],[[8334,8334],"disallowed_STD3_mapped",[41]],[[8335,8335],"disallowed"],[[8336,8336],"mapped",[97]],[[8337,8337],"mapped",[101]],[[8338,8338],"mapped",[111]],[[8339,8339],"mapped",[120]],[[8340,8340],"mapped",[601]],[[8341,8341],"mapped",[104]],[[8342,8342],"mapped",[107]],[[8343,8343],"mapped",[108]],[[8344,8344],"mapped",[109]],[[8345,8345],"mapped",[110]],[[8346,8346],"mapped",[112]],[[8347,8347],"mapped",[115]],[[8348,8348],"mapped",[116]],[[8349,8351],"disallowed"],[[8352,8359],"valid",[],"NV8"],[[8360,8360],"mapped",[114,115]],[[8361,8362],"valid",[],"NV8"],[[8363,8363],"valid",[],"NV8"],[[8364,8364],"valid",[],"NV8"],[[8365,8367],"valid",[],"NV8"],[[8368,8369],"valid",[],"NV8"],[[8370,8373],"valid",[],"NV8"],[[8374,8376],"valid",[],"NV8"],[[8377,8377],"valid",[],"NV8"],[[8378,8378],"valid",[],"NV8"],[[8379,8381],"valid",[],"NV8"],[[8382,8382],"valid",[],"NV8"],[[8383,8399],"disallowed"],[[8400,8417],"valid",[],"NV8"],[[8418,8419],"valid",[],"NV8"],[[8420,8426],"valid",[],"NV8"],[[8427,8427],"valid",[],"NV8"],[[8428,8431],"valid",[],"NV8"],[[8432,8432],"valid",[],"NV8"],[[8433,8447],"disallowed"],[[8448,8448],"disallowed_STD3_mapped",[97,47,99]],[[8449,8449],"disallowed_STD3_mapped",[97,47,115]],[[8450,8450],"mapped",[99]],[[8451,8451],"mapped",[176,99]],[[8452,8452],"valid",[],"NV8"],[[8453,8453],"disallowed_STD3_mapped",[99,47,111]],[[8454,8454],"disallowed_STD3_mapped",[99,47,117]],[[8455,8455],"mapped",[603]],[[8456,8456],"valid",[],"NV8"],[[8457,8457],"mapped",[176,102]],[[8458,8458],"mapped",[103]],[[8459,8462],"mapped",[104]],[[8463,8463],"mapped",[295]],[[8464,8465],"mapped",[105]],[[8466,8467],"mapped",[108]],[[8468,8468],"valid",[],"NV8"],[[8469,8469],"mapped",[110]],[[8470,8470],"mapped",[110,111]],[[8471,8472],"valid",[],"NV8"],[[8473,8473],"mapped",[112]],[[8474,8474],"mapped",[113]],[[8475,8477],"mapped",[114]],[[8478,8479],"valid",[],"NV8"],[[8480,8480],"mapped",[115,109]],[[8481,8481],"mapped",[116,101,108]],[[8482,8482],"mapped",[116,109]],[[8483,8483],"valid",[],"NV8"],[[8484,8484],"mapped",[122]],[[8485,8485],"valid",[],"NV8"],[[8486,8486],"mapped",[969]],[[8487,8487],"valid",[],"NV8"],[[8488,8488],"mapped",[122]],[[8489,8489],"valid",[],"NV8"],[[8490,8490],"mapped",[107]],[[8491,8491],"mapped",[229]],[[8492,8492],"mapped",[98]],[[8493,8493],"mapped",[99]],[[8494,8494],"valid",[],"NV8"],[[8495,8496],"mapped",[101]],[[8497,8497],"mapped",[102]],[[8498,8498],"disallowed"],[[8499,8499],"mapped",[109]],[[8500,8500],"mapped",[111]],[[8501,8501],"mapped",[1488]],[[8502,8502],"mapped",[1489]],[[8503,8503],"mapped",[1490]],[[8504,8504],"mapped",[1491]],[[8505,8505],"mapped",[105]],[[8506,8506],"valid",[],"NV8"],[[8507,8507],"mapped",[102,97,120]],[[8508,8508],"mapped",[960]],[[8509,8510],"mapped",[947]],[[8511,8511],"mapped",[960]],[[8512,8512],"mapped",[8721]],[[8513,8516],"valid",[],"NV8"],[[8517,8518],"mapped",[100]],[[8519,8519],"mapped",[101]],[[8520,8520],"mapped",[105]],[[8521,8521],"mapped",[106]],[[8522,8523],"valid",[],"NV8"],[[8524,8524],"valid",[],"NV8"],[[8525,8525],"valid",[],"NV8"],[[8526,8526],"valid"],[[8527,8527],"valid",[],"NV8"],[[8528,8528],"mapped",[49,8260,55]],[[8529,8529],"mapped",[49,8260,57]],[[8530,8530],"mapped",[49,8260,49,48]],[[8531,8531],"mapped",[49,8260,51]],[[8532,8532],"mapped",[50,8260,51]],[[8533,8533],"mapped",[49,8260,53]],[[8534,8534],"mapped",[50,8260,53]],[[8535,8535],"mapped",[51,8260,53]],[[8536,8536],"mapped",[52,8260,53]],[[8537,8537],"mapped",[49,8260,54]],[[8538,8538],"mapped",[53,8260,54]],[[8539,8539],"mapped",[49,8260,56]],[[8540,8540],"mapped",[51,8260,56]],[[8541,8541],"mapped",[53,8260,56]],[[8542,8542],"mapped",[55,8260,56]],[[8543,8543],"mapped",[49,8260]],[[8544,8544],"mapped",[105]],[[8545,8545],"mapped",[105,105]],[[8546,8546],"mapped",[105,105,105]],[[8547,8547],"mapped",[105,118]],[[8548,8548],"mapped",[118]],[[8549,8549],"mapped",[118,105]],[[8550,8550],"mapped",[118,105,105]],[[8551,8551],"mapped",[118,105,105,105]],[[8552,8552],"mapped",[105,120]],[[8553,8553],"mapped",[120]],[[8554,8554],"mapped",[120,105]],[[8555,8555],"mapped",[120,105,105]],[[8556,8556],"mapped",[108]],[[8557,8557],"mapped",[99]],[[8558,8558],"mapped",[100]],[[8559,8559],"mapped",[109]],[[8560,8560],"mapped",[105]],[[8561,8561],"mapped",[105,105]],[[8562,8562],"mapped",[105,105,105]],[[8563,8563],"mapped",[105,118]],[[8564,8564],"mapped",[118]],[[8565,8565],"mapped",[118,105]],[[8566,8566],"mapped",[118,105,105]],[[8567,8567],"mapped",[118,105,105,105]],[[8568,8568],"mapped",[105,120]],[[8569,8569],"mapped",[120]],[[8570,8570],"mapped",[120,105]],[[8571,8571],"mapped",[120,105,105]],[[8572,8572],"mapped",[108]],[[8573,8573],"mapped",[99]],[[8574,8574],"mapped",[100]],[[8575,8575],"mapped",[109]],[[8576,8578],"valid",[],"NV8"],[[8579,8579],"disallowed"],[[8580,8580],"valid"],[[8581,8584],"valid",[],"NV8"],[[8585,8585],"mapped",[48,8260,51]],[[8586,8587],"valid",[],"NV8"],[[8588,8591],"disallowed"],[[8592,8682],"valid",[],"NV8"],[[8683,8691],"valid",[],"NV8"],[[8692,8703],"valid",[],"NV8"],[[8704,8747],"valid",[],"NV8"],[[8748,8748],"mapped",[8747,8747]],[[8749,8749],"mapped",[8747,8747,8747]],[[8750,8750],"valid",[],"NV8"],[[8751,8751],"mapped",[8750,8750]],[[8752,8752],"mapped",[8750,8750,8750]],[[8753,8799],"valid",[],"NV8"],[[8800,8800],"disallowed_STD3_valid"],[[8801,8813],"valid",[],"NV8"],[[8814,8815],"disallowed_STD3_valid"],[[8816,8945],"valid",[],"NV8"],[[8946,8959],"valid",[],"NV8"],[[8960,8960],"valid",[],"NV8"],[[8961,8961],"valid",[],"NV8"],[[8962,9000],"valid",[],"NV8"],[[9001,9001],"mapped",[12296]],[[9002,9002],"mapped",[12297]],[[9003,9082],"valid",[],"NV8"],[[9083,9083],"valid",[],"NV8"],[[9084,9084],"valid",[],"NV8"],[[9085,9114],"valid",[],"NV8"],[[9115,9166],"valid",[],"NV8"],[[9167,9168],"valid",[],"NV8"],[[9169,9179],"valid",[],"NV8"],[[9180,9191],"valid",[],"NV8"],[[9192,9192],"valid",[],"NV8"],[[9193,9203],"valid",[],"NV8"],[[9204,9210],"valid",[],"NV8"],[[9211,9215],"disallowed"],[[9216,9252],"valid",[],"NV8"],[[9253,9254],"valid",[],"NV8"],[[9255,9279],"disallowed"],[[9280,9290],"valid",[],"NV8"],[[9291,9311],"disallowed"],[[9312,9312],"mapped",[49]],[[9313,9313],"mapped",[50]],[[9314,9314],"mapped",[51]],[[9315,9315],"mapped",[52]],[[9316,9316],"mapped",[53]],[[9317,9317],"mapped",[54]],[[9318,9318],"mapped",[55]],[[9319,9319],"mapped",[56]],[[9320,9320],"mapped",[57]],[[9321,9321],"mapped",[49,48]],[[9322,9322],"mapped",[49,49]],[[9323,9323],"mapped",[49,50]],[[9324,9324],"mapped",[49,51]],[[9325,9325],"mapped",[49,52]],[[9326,9326],"mapped",[49,53]],[[9327,9327],"mapped",[49,54]],[[9328,9328],"mapped",[49,55]],[[9329,9329],"mapped",[49,56]],[[9330,9330],"mapped",[49,57]],[[9331,9331],"mapped",[50,48]],[[9332,9332],"disallowed_STD3_mapped",[40,49,41]],[[9333,9333],"disallowed_STD3_mapped",[40,50,41]],[[9334,9334],"disallowed_STD3_mapped",[40,51,41]],[[9335,9335],"disallowed_STD3_mapped",[40,52,41]],[[9336,9336],"disallowed_STD3_mapped",[40,53,41]],[[9337,9337],"disallowed_STD3_mapped",[40,54,41]],[[9338,9338],"disallowed_STD3_mapped",[40,55,41]],[[9339,9339],"disallowed_STD3_mapped",[40,56,41]],[[9340,9340],"disallowed_STD3_mapped",[40,57,41]],[[9341,9341],"disallowed_STD3_mapped",[40,49,48,41]],[[9342,9342],"disallowed_STD3_mapped",[40,49,49,41]],[[9343,9343],"disallowed_STD3_mapped",[40,49,50,41]],[[9344,9344],"disallowed_STD3_mapped",[40,49,51,41]],[[9345,9345],"disallowed_STD3_mapped",[40,49,52,41]],[[9346,9346],"disallowed_STD3_mapped",[40,49,53,41]],[[9347,9347],"disallowed_STD3_mapped",[40,49,54,41]],[[9348,9348],"disallowed_STD3_mapped",[40,49,55,41]],[[9349,9349],"disallowed_STD3_mapped",[40,49,56,41]],[[9350,9350],"disallowed_STD3_mapped",[40,49,57,41]],[[9351,9351],"disallowed_STD3_mapped",[40,50,48,41]],[[9352,9371],"disallowed"],[[9372,9372],"disallowed_STD3_mapped",[40,97,41]],[[9373,9373],"disallowed_STD3_mapped",[40,98,41]],[[9374,9374],"disallowed_STD3_mapped",[40,99,41]],[[9375,9375],"disallowed_STD3_mapped",[40,100,41]],[[9376,9376],"disallowed_STD3_mapped",[40,101,41]],[[9377,9377],"disallowed_STD3_mapped",[40,102,41]],[[9378,9378],"disallowed_STD3_mapped",[40,103,41]],[[9379,9379],"disallowed_STD3_mapped",[40,104,41]],[[9380,9380],"disallowed_STD3_mapped",[40,105,41]],[[9381,9381],"disallowed_STD3_mapped",[40,106,41]],[[9382,9382],"disallowed_STD3_mapped",[40,107,41]],[[9383,9383],"disallowed_STD3_mapped",[40,108,41]],[[9384,9384],"disallowed_STD3_mapped",[40,109,41]],[[9385,9385],"disallowed_STD3_mapped",[40,110,41]],[[9386,9386],"disallowed_STD3_mapped",[40,111,41]],[[9387,9387],"disallowed_STD3_mapped",[40,112,41]],[[9388,9388],"disallowed_STD3_mapped",[40,113,41]],[[9389,9389],"disallowed_STD3_mapped",[40,114,41]],[[9390,9390],"disallowed_STD3_mapped",[40,115,41]],[[9391,9391],"disallowed_STD3_mapped",[40,116,41]],[[9392,9392],"disallowed_STD3_mapped",[40,117,41]],[[9393,9393],"disallowed_STD3_mapped",[40,118,41]],[[9394,9394],"disallowed_STD3_mapped",[40,119,41]],[[9395,9395],"disallowed_STD3_mapped",[40,120,41]],[[9396,9396],"disallowed_STD3_mapped",[40,121,41]],[[9397,9397],"disallowed_STD3_mapped",[40,122,41]],[[9398,9398],"mapped",[97]],[[9399,9399],"mapped",[98]],[[9400,9400],"mapped",[99]],[[9401,9401],"mapped",[100]],[[9402,9402],"mapped",[101]],[[9403,9403],"mapped",[102]],[[9404,9404],"mapped",[103]],[[9405,9405],"mapped",[104]],[[9406,9406],"mapped",[105]],[[9407,9407],"mapped",[106]],[[9408,9408],"mapped",[107]],[[9409,9409],"mapped",[108]],[[9410,9410],"mapped",[109]],[[9411,9411],"mapped",[110]],[[9412,9412],"mapped",[111]],[[9413,9413],"mapped",[112]],[[9414,9414],"mapped",[113]],[[9415,9415],"mapped",[114]],[[9416,9416],"mapped",[115]],[[9417,9417],"mapped",[116]],[[9418,9418],"mapped",[117]],[[9419,9419],"mapped",[118]],[[9420,9420],"mapped",[119]],[[9421,9421],"mapped",[120]],[[9422,9422],"mapped",[121]],[[9423,9423],"mapped",[122]],[[9424,9424],"mapped",[97]],[[9425,9425],"mapped",[98]],[[9426,9426],"mapped",[99]],[[9427,9427],"mapped",[100]],[[9428,9428],"mapped",[101]],[[9429,9429],"mapped",[102]],[[9430,9430],"mapped",[103]],[[9431,9431],"mapped",[104]],[[9432,9432],"mapped",[105]],[[9433,9433],"mapped",[106]],[[9434,9434],"mapped",[107]],[[9435,9435],"mapped",[108]],[[9436,9436],"mapped",[109]],[[9437,9437],"mapped",[110]],[[9438,9438],"mapped",[111]],[[9439,9439],"mapped",[112]],[[9440,9440],"mapped",[113]],[[9441,9441],"mapped",[114]],[[9442,9442],"mapped",[115]],[[9443,9443],"mapped",[116]],[[9444,9444],"mapped",[117]],[[9445,9445],"mapped",[118]],[[9446,9446],"mapped",[119]],[[9447,9447],"mapped",[120]],[[9448,9448],"mapped",[121]],[[9449,9449],"mapped",[122]],[[9450,9450],"mapped",[48]],[[9451,9470],"valid",[],"NV8"],[[9471,9471],"valid",[],"NV8"],[[9472,9621],"valid",[],"NV8"],[[9622,9631],"valid",[],"NV8"],[[9632,9711],"valid",[],"NV8"],[[9712,9719],"valid",[],"NV8"],[[9720,9727],"valid",[],"NV8"],[[9728,9747],"valid",[],"NV8"],[[9748,9749],"valid",[],"NV8"],[[9750,9751],"valid",[],"NV8"],[[9752,9752],"valid",[],"NV8"],[[9753,9753],"valid",[],"NV8"],[[9754,9839],"valid",[],"NV8"],[[9840,9841],"valid",[],"NV8"],[[9842,9853],"valid",[],"NV8"],[[9854,9855],"valid",[],"NV8"],[[9856,9865],"valid",[],"NV8"],[[9866,9873],"valid",[],"NV8"],[[9874,9884],"valid",[],"NV8"],[[9885,9885],"valid",[],"NV8"],[[9886,9887],"valid",[],"NV8"],[[9888,9889],"valid",[],"NV8"],[[9890,9905],"valid",[],"NV8"],[[9906,9906],"valid",[],"NV8"],[[9907,9916],"valid",[],"NV8"],[[9917,9919],"valid",[],"NV8"],[[9920,9923],"valid",[],"NV8"],[[9924,9933],"valid",[],"NV8"],[[9934,9934],"valid",[],"NV8"],[[9935,9953],"valid",[],"NV8"],[[9954,9954],"valid",[],"NV8"],[[9955,9955],"valid",[],"NV8"],[[9956,9959],"valid",[],"NV8"],[[9960,9983],"valid",[],"NV8"],[[9984,9984],"valid",[],"NV8"],[[9985,9988],"valid",[],"NV8"],[[9989,9989],"valid",[],"NV8"],[[9990,9993],"valid",[],"NV8"],[[9994,9995],"valid",[],"NV8"],[[9996,10023],"valid",[],"NV8"],[[10024,10024],"valid",[],"NV8"],[[10025,10059],"valid",[],"NV8"],[[10060,10060],"valid",[],"NV8"],[[10061,10061],"valid",[],"NV8"],[[10062,10062],"valid",[],"NV8"],[[10063,10066],"valid",[],"NV8"],[[10067,10069],"valid",[],"NV8"],[[10070,10070],"valid",[],"NV8"],[[10071,10071],"valid",[],"NV8"],[[10072,10078],"valid",[],"NV8"],[[10079,10080],"valid",[],"NV8"],[[10081,10087],"valid",[],"NV8"],[[10088,10101],"valid",[],"NV8"],[[10102,10132],"valid",[],"NV8"],[[10133,10135],"valid",[],"NV8"],[[10136,10159],"valid",[],"NV8"],[[10160,10160],"valid",[],"NV8"],[[10161,10174],"valid",[],"NV8"],[[10175,10175],"valid",[],"NV8"],[[10176,10182],"valid",[],"NV8"],[[10183,10186],"valid",[],"NV8"],[[10187,10187],"valid",[],"NV8"],[[10188,10188],"valid",[],"NV8"],[[10189,10189],"valid",[],"NV8"],[[10190,10191],"valid",[],"NV8"],[[10192,10219],"valid",[],"NV8"],[[10220,10223],"valid",[],"NV8"],[[10224,10239],"valid",[],"NV8"],[[10240,10495],"valid",[],"NV8"],[[10496,10763],"valid",[],"NV8"],[[10764,10764],"mapped",[8747,8747,8747,8747]],[[10765,10867],"valid",[],"NV8"],[[10868,10868],"disallowed_STD3_mapped",[58,58,61]],[[10869,10869],"disallowed_STD3_mapped",[61,61]],[[10870,10870],"disallowed_STD3_mapped",[61,61,61]],[[10871,10971],"valid",[],"NV8"],[[10972,10972],"mapped",[10973,824]],[[10973,11007],"valid",[],"NV8"],[[11008,11021],"valid",[],"NV8"],[[11022,11027],"valid",[],"NV8"],[[11028,11034],"valid",[],"NV8"],[[11035,11039],"valid",[],"NV8"],[[11040,11043],"valid",[],"NV8"],[[11044,11084],"valid",[],"NV8"],[[11085,11087],"valid",[],"NV8"],[[11088,11092],"valid",[],"NV8"],[[11093,11097],"valid",[],"NV8"],[[11098,11123],"valid",[],"NV8"],[[11124,11125],"disallowed"],[[11126,11157],"valid",[],"NV8"],[[11158,11159],"disallowed"],[[11160,11193],"valid",[],"NV8"],[[11194,11196],"disallowed"],[[11197,11208],"valid",[],"NV8"],[[11209,11209],"disallowed"],[[11210,11217],"valid",[],"NV8"],[[11218,11243],"disallowed"],[[11244,11247],"valid",[],"NV8"],[[11248,11263],"disallowed"],[[11264,11264],"mapped",[11312]],[[11265,11265],"mapped",[11313]],[[11266,11266],"mapped",[11314]],[[11267,11267],"mapped",[11315]],[[11268,11268],"mapped",[11316]],[[11269,11269],"mapped",[11317]],[[11270,11270],"mapped",[11318]],[[11271,11271],"mapped",[11319]],[[11272,11272],"mapped",[11320]],[[11273,11273],"mapped",[11321]],[[11274,11274],"mapped",[11322]],[[11275,11275],"mapped",[11323]],[[11276,11276],"mapped",[11324]],[[11277,11277],"mapped",[11325]],[[11278,11278],"mapped",[11326]],[[11279,11279],"mapped",[11327]],[[11280,11280],"mapped",[11328]],[[11281,11281],"mapped",[11329]],[[11282,11282],"mapped",[11330]],[[11283,11283],"mapped",[11331]],[[11284,11284],"mapped",[11332]],[[11285,11285],"mapped",[11333]],[[11286,11286],"mapped",[11334]],[[11287,11287],"mapped",[11335]],[[11288,11288],"mapped",[11336]],[[11289,11289],"mapped",[11337]],[[11290,11290],"mapped",[11338]],[[11291,11291],"mapped",[11339]],[[11292,11292],"mapped",[11340]],[[11293,11293],"mapped",[11341]],[[11294,11294],"mapped",[11342]],[[11295,11295],"mapped",[11343]],[[11296,11296],"mapped",[11344]],[[11297,11297],"mapped",[11345]],[[11298,11298],"mapped",[11346]],[[11299,11299],"mapped",[11347]],[[11300,11300],"mapped",[11348]],[[11301,11301],"mapped",[11349]],[[11302,11302],"mapped",[11350]],[[11303,11303],"mapped",[11351]],[[11304,11304],"mapped",[11352]],[[11305,11305],"mapped",[11353]],[[11306,11306],"mapped",[11354]],[[11307,11307],"mapped",[11355]],[[11308,11308],"mapped",[11356]],[[11309,11309],"mapped",[11357]],[[11310,11310],"mapped",[11358]],[[11311,11311],"disallowed"],[[11312,11358],"valid"],[[11359,11359],"disallowed"],[[11360,11360],"mapped",[11361]],[[11361,11361],"valid"],[[11362,11362],"mapped",[619]],[[11363,11363],"mapped",[7549]],[[11364,11364],"mapped",[637]],[[11365,11366],"valid"],[[11367,11367],"mapped",[11368]],[[11368,11368],"valid"],[[11369,11369],"mapped",[11370]],[[11370,11370],"valid"],[[11371,11371],"mapped",[11372]],[[11372,11372],"valid"],[[11373,11373],"mapped",[593]],[[11374,11374],"mapped",[625]],[[11375,11375],"mapped",[592]],[[11376,11376],"mapped",[594]],[[11377,11377],"valid"],[[11378,11378],"mapped",[11379]],[[11379,11379],"valid"],[[11380,11380],"valid"],[[11381,11381],"mapped",[11382]],[[11382,11383],"valid"],[[11384,11387],"valid"],[[11388,11388],"mapped",[106]],[[11389,11389],"mapped",[118]],[[11390,11390],"mapped",[575]],[[11391,11391],"mapped",[576]],[[11392,11392],"mapped",[11393]],[[11393,11393],"valid"],[[11394,11394],"mapped",[11395]],[[11395,11395],"valid"],[[11396,11396],"mapped",[11397]],[[11397,11397],"valid"],[[11398,11398],"mapped",[11399]],[[11399,11399],"valid"],[[11400,11400],"mapped",[11401]],[[11401,11401],"valid"],[[11402,11402],"mapped",[11403]],[[11403,11403],"valid"],[[11404,11404],"mapped",[11405]],[[11405,11405],"valid"],[[11406,11406],"mapped",[11407]],[[11407,11407],"valid"],[[11408,11408],"mapped",[11409]],[[11409,11409],"valid"],[[11410,11410],"mapped",[11411]],[[11411,11411],"valid"],[[11412,11412],"mapped",[11413]],[[11413,11413],"valid"],[[11414,11414],"mapped",[11415]],[[11415,11415],"valid"],[[11416,11416],"mapped",[11417]],[[11417,11417],"valid"],[[11418,11418],"mapped",[11419]],[[11419,11419],"valid"],[[11420,11420],"mapped",[11421]],[[11421,11421],"valid"],[[11422,11422],"mapped",[11423]],[[11423,11423],"valid"],[[11424,11424],"mapped",[11425]],[[11425,11425],"valid"],[[11426,11426],"mapped",[11427]],[[11427,11427],"valid"],[[11428,11428],"mapped",[11429]],[[11429,11429],"valid"],[[11430,11430],"mapped",[11431]],[[11431,11431],"valid"],[[11432,11432],"mapped",[11433]],[[11433,11433],"valid"],[[11434,11434],"mapped",[11435]],[[11435,11435],"valid"],[[11436,11436],"mapped",[11437]],[[11437,11437],"valid"],[[11438,11438],"mapped",[11439]],[[11439,11439],"valid"],[[11440,11440],"mapped",[11441]],[[11441,11441],"valid"],[[11442,11442],"mapped",[11443]],[[11443,11443],"valid"],[[11444,11444],"mapped",[11445]],[[11445,11445],"valid"],[[11446,11446],"mapped",[11447]],[[11447,11447],"valid"],[[11448,11448],"mapped",[11449]],[[11449,11449],"valid"],[[11450,11450],"mapped",[11451]],[[11451,11451],"valid"],[[11452,11452],"mapped",[11453]],[[11453,11453],"valid"],[[11454,11454],"mapped",[11455]],[[11455,11455],"valid"],[[11456,11456],"mapped",[11457]],[[11457,11457],"valid"],[[11458,11458],"mapped",[11459]],[[11459,11459],"valid"],[[11460,11460],"mapped",[11461]],[[11461,11461],"valid"],[[11462,11462],"mapped",[11463]],[[11463,11463],"valid"],[[11464,11464],"mapped",[11465]],[[11465,11465],"valid"],[[11466,11466],"mapped",[11467]],[[11467,11467],"valid"],[[11468,11468],"mapped",[11469]],[[11469,11469],"valid"],[[11470,11470],"mapped",[11471]],[[11471,11471],"valid"],[[11472,11472],"mapped",[11473]],[[11473,11473],"valid"],[[11474,11474],"mapped",[11475]],[[11475,11475],"valid"],[[11476,11476],"mapped",[11477]],[[11477,11477],"valid"],[[11478,11478],"mapped",[11479]],[[11479,11479],"valid"],[[11480,11480],"mapped",[11481]],[[11481,11481],"valid"],[[11482,11482],"mapped",[11483]],[[11483,11483],"valid"],[[11484,11484],"mapped",[11485]],[[11485,11485],"valid"],[[11486,11486],"mapped",[11487]],[[11487,11487],"valid"],[[11488,11488],"mapped",[11489]],[[11489,11489],"valid"],[[11490,11490],"mapped",[11491]],[[11491,11492],"valid"],[[11493,11498],"valid",[],"NV8"],[[11499,11499],"mapped",[11500]],[[11500,11500],"valid"],[[11501,11501],"mapped",[11502]],[[11502,11505],"valid"],[[11506,11506],"mapped",[11507]],[[11507,11507],"valid"],[[11508,11512],"disallowed"],[[11513,11519],"valid",[],"NV8"],[[11520,11557],"valid"],[[11558,11558],"disallowed"],[[11559,11559],"valid"],[[11560,11564],"disallowed"],[[11565,11565],"valid"],[[11566,11567],"disallowed"],[[11568,11621],"valid"],[[11622,11623],"valid"],[[11624,11630],"disallowed"],[[11631,11631],"mapped",[11617]],[[11632,11632],"valid",[],"NV8"],[[11633,11646],"disallowed"],[[11647,11647],"valid"],[[11648,11670],"valid"],[[11671,11679],"disallowed"],[[11680,11686],"valid"],[[11687,11687],"disallowed"],[[11688,11694],"valid"],[[11695,11695],"disallowed"],[[11696,11702],"valid"],[[11703,11703],"disallowed"],[[11704,11710],"valid"],[[11711,11711],"disallowed"],[[11712,11718],"valid"],[[11719,11719],"disallowed"],[[11720,11726],"valid"],[[11727,11727],"disallowed"],[[11728,11734],"valid"],[[11735,11735],"disallowed"],[[11736,11742],"valid"],[[11743,11743],"disallowed"],[[11744,11775],"valid"],[[11776,11799],"valid",[],"NV8"],[[11800,11803],"valid",[],"NV8"],[[11804,11805],"valid",[],"NV8"],[[11806,11822],"valid",[],"NV8"],[[11823,11823],"valid"],[[11824,11824],"valid",[],"NV8"],[[11825,11825],"valid",[],"NV8"],[[11826,11835],"valid",[],"NV8"],[[11836,11842],"valid",[],"NV8"],[[11843,11903],"disallowed"],[[11904,11929],"valid",[],"NV8"],[[11930,11930],"disallowed"],[[11931,11934],"valid",[],"NV8"],[[11935,11935],"mapped",[27597]],[[11936,12018],"valid",[],"NV8"],[[12019,12019],"mapped",[40863]],[[12020,12031],"disallowed"],[[12032,12032],"mapped",[19968]],[[12033,12033],"mapped",[20008]],[[12034,12034],"mapped",[20022]],[[12035,12035],"mapped",[20031]],[[12036,12036],"mapped",[20057]],[[12037,12037],"mapped",[20101]],[[12038,12038],"mapped",[20108]],[[12039,12039],"mapped",[20128]],[[12040,12040],"mapped",[20154]],[[12041,12041],"mapped",[20799]],[[12042,12042],"mapped",[20837]],[[12043,12043],"mapped",[20843]],[[12044,12044],"mapped",[20866]],[[12045,12045],"mapped",[20886]],[[12046,12046],"mapped",[20907]],[[12047,12047],"mapped",[20960]],[[12048,12048],"mapped",[20981]],[[12049,12049],"mapped",[20992]],[[12050,12050],"mapped",[21147]],[[12051,12051],"mapped",[21241]],[[12052,12052],"mapped",[21269]],[[12053,12053],"mapped",[21274]],[[12054,12054],"mapped",[21304]],[[12055,12055],"mapped",[21313]],[[12056,12056],"mapped",[21340]],[[12057,12057],"mapped",[21353]],[[12058,12058],"mapped",[21378]],[[12059,12059],"mapped",[21430]],[[12060,12060],"mapped",[21448]],[[12061,12061],"mapped",[21475]],[[12062,12062],"mapped",[22231]],[[12063,12063],"mapped",[22303]],[[12064,12064],"mapped",[22763]],[[12065,12065],"mapped",[22786]],[[12066,12066],"mapped",[22794]],[[12067,12067],"mapped",[22805]],[[12068,12068],"mapped",[22823]],[[12069,12069],"mapped",[22899]],[[12070,12070],"mapped",[23376]],[[12071,12071],"mapped",[23424]],[[12072,12072],"mapped",[23544]],[[12073,12073],"mapped",[23567]],[[12074,12074],"mapped",[23586]],[[12075,12075],"mapped",[23608]],[[12076,12076],"mapped",[23662]],[[12077,12077],"mapped",[23665]],[[12078,12078],"mapped",[24027]],[[12079,12079],"mapped",[24037]],[[12080,12080],"mapped",[24049]],[[12081,12081],"mapped",[24062]],[[12082,12082],"mapped",[24178]],[[12083,12083],"mapped",[24186]],[[12084,12084],"mapped",[24191]],[[12085,12085],"mapped",[24308]],[[12086,12086],"mapped",[24318]],[[12087,12087],"mapped",[24331]],[[12088,12088],"mapped",[24339]],[[12089,12089],"mapped",[24400]],[[12090,12090],"mapped",[24417]],[[12091,12091],"mapped",[24435]],[[12092,12092],"mapped",[24515]],[[12093,12093],"mapped",[25096]],[[12094,12094],"mapped",[25142]],[[12095,12095],"mapped",[25163]],[[12096,12096],"mapped",[25903]],[[12097,12097],"mapped",[25908]],[[12098,12098],"mapped",[25991]],[[12099,12099],"mapped",[26007]],[[12100,12100],"mapped",[26020]],[[12101,12101],"mapped",[26041]],[[12102,12102],"mapped",[26080]],[[12103,12103],"mapped",[26085]],[[12104,12104],"mapped",[26352]],[[12105,12105],"mapped",[26376]],[[12106,12106],"mapped",[26408]],[[12107,12107],"mapped",[27424]],[[12108,12108],"mapped",[27490]],[[12109,12109],"mapped",[27513]],[[12110,12110],"mapped",[27571]],[[12111,12111],"mapped",[27595]],[[12112,12112],"mapped",[27604]],[[12113,12113],"mapped",[27611]],[[12114,12114],"mapped",[27663]],[[12115,12115],"mapped",[27668]],[[12116,12116],"mapped",[27700]],[[12117,12117],"mapped",[28779]],[[12118,12118],"mapped",[29226]],[[12119,12119],"mapped",[29238]],[[12120,12120],"mapped",[29243]],[[12121,12121],"mapped",[29247]],[[12122,12122],"mapped",[29255]],[[12123,12123],"mapped",[29273]],[[12124,12124],"mapped",[29275]],[[12125,12125],"mapped",[29356]],[[12126,12126],"mapped",[29572]],[[12127,12127],"mapped",[29577]],[[12128,12128],"mapped",[29916]],[[12129,12129],"mapped",[29926]],[[12130,12130],"mapped",[29976]],[[12131,12131],"mapped",[29983]],[[12132,12132],"mapped",[29992]],[[12133,12133],"mapped",[30000]],[[12134,12134],"mapped",[30091]],[[12135,12135],"mapped",[30098]],[[12136,12136],"mapped",[30326]],[[12137,12137],"mapped",[30333]],[[12138,12138],"mapped",[30382]],[[12139,12139],"mapped",[30399]],[[12140,12140],"mapped",[30446]],[[12141,12141],"mapped",[30683]],[[12142,12142],"mapped",[30690]],[[12143,12143],"mapped",[30707]],[[12144,12144],"mapped",[31034]],[[12145,12145],"mapped",[31160]],[[12146,12146],"mapped",[31166]],[[12147,12147],"mapped",[31348]],[[12148,12148],"mapped",[31435]],[[12149,12149],"mapped",[31481]],[[12150,12150],"mapped",[31859]],[[12151,12151],"mapped",[31992]],[[12152,12152],"mapped",[32566]],[[12153,12153],"mapped",[32593]],[[12154,12154],"mapped",[32650]],[[12155,12155],"mapped",[32701]],[[12156,12156],"mapped",[32769]],[[12157,12157],"mapped",[32780]],[[12158,12158],"mapped",[32786]],[[12159,12159],"mapped",[32819]],[[12160,12160],"mapped",[32895]],[[12161,12161],"mapped",[32905]],[[12162,12162],"mapped",[33251]],[[12163,12163],"mapped",[33258]],[[12164,12164],"mapped",[33267]],[[12165,12165],"mapped",[33276]],[[12166,12166],"mapped",[33292]],[[12167,12167],"mapped",[33307]],[[12168,12168],"mapped",[33311]],[[12169,12169],"mapped",[33390]],[[12170,12170],"mapped",[33394]],[[12171,12171],"mapped",[33400]],[[12172,12172],"mapped",[34381]],[[12173,12173],"mapped",[34411]],[[12174,12174],"mapped",[34880]],[[12175,12175],"mapped",[34892]],[[12176,12176],"mapped",[34915]],[[12177,12177],"mapped",[35198]],[[12178,12178],"mapped",[35211]],[[12179,12179],"mapped",[35282]],[[12180,12180],"mapped",[35328]],[[12181,12181],"mapped",[35895]],[[12182,12182],"mapped",[35910]],[[12183,12183],"mapped",[35925]],[[12184,12184],"mapped",[35960]],[[12185,12185],"mapped",[35997]],[[12186,12186],"mapped",[36196]],[[12187,12187],"mapped",[36208]],[[12188,12188],"mapped",[36275]],[[12189,12189],"mapped",[36523]],[[12190,12190],"mapped",[36554]],[[12191,12191],"mapped",[36763]],[[12192,12192],"mapped",[36784]],[[12193,12193],"mapped",[36789]],[[12194,12194],"mapped",[37009]],[[12195,12195],"mapped",[37193]],[[12196,12196],"mapped",[37318]],[[12197,12197],"mapped",[37324]],[[12198,12198],"mapped",[37329]],[[12199,12199],"mapped",[38263]],[[12200,12200],"mapped",[38272]],[[12201,12201],"mapped",[38428]],[[12202,12202],"mapped",[38582]],[[12203,12203],"mapped",[38585]],[[12204,12204],"mapped",[38632]],[[12205,12205],"mapped",[38737]],[[12206,12206],"mapped",[38750]],[[12207,12207],"mapped",[38754]],[[12208,12208],"mapped",[38761]],[[12209,12209],"mapped",[38859]],[[12210,12210],"mapped",[38893]],[[12211,12211],"mapped",[38899]],[[12212,12212],"mapped",[38913]],[[12213,12213],"mapped",[39080]],[[12214,12214],"mapped",[39131]],[[12215,12215],"mapped",[39135]],[[12216,12216],"mapped",[39318]],[[12217,12217],"mapped",[39321]],[[12218,12218],"mapped",[39340]],[[12219,12219],"mapped",[39592]],[[12220,12220],"mapped",[39640]],[[12221,12221],"mapped",[39647]],[[12222,12222],"mapped",[39717]],[[12223,12223],"mapped",[39727]],[[12224,12224],"mapped",[39730]],[[12225,12225],"mapped",[39740]],[[12226,12226],"mapped",[39770]],[[12227,12227],"mapped",[40165]],[[12228,12228],"mapped",[40565]],[[12229,12229],"mapped",[40575]],[[12230,12230],"mapped",[40613]],[[12231,12231],"mapped",[40635]],[[12232,12232],"mapped",[40643]],[[12233,12233],"mapped",[40653]],[[12234,12234],"mapped",[40657]],[[12235,12235],"mapped",[40697]],[[12236,12236],"mapped",[40701]],[[12237,12237],"mapped",[40718]],[[12238,12238],"mapped",[40723]],[[12239,12239],"mapped",[40736]],[[12240,12240],"mapped",[40763]],[[12241,12241],"mapped",[40778]],[[12242,12242],"mapped",[40786]],[[12243,12243],"mapped",[40845]],[[12244,12244],"mapped",[40860]],[[12245,12245],"mapped",[40864]],[[12246,12271],"disallowed"],[[12272,12283],"disallowed"],[[12284,12287],"disallowed"],[[12288,12288],"disallowed_STD3_mapped",[32]],[[12289,12289],"valid",[],"NV8"],[[12290,12290],"mapped",[46]],[[12291,12292],"valid",[],"NV8"],[[12293,12295],"valid"],[[12296,12329],"valid",[],"NV8"],[[12330,12333],"valid"],[[12334,12341],"valid",[],"NV8"],[[12342,12342],"mapped",[12306]],[[12343,12343],"valid",[],"NV8"],[[12344,12344],"mapped",[21313]],[[12345,12345],"mapped",[21316]],[[12346,12346],"mapped",[21317]],[[12347,12347],"valid",[],"NV8"],[[12348,12348],"valid"],[[12349,12349],"valid",[],"NV8"],[[12350,12350],"valid",[],"NV8"],[[12351,12351],"valid",[],"NV8"],[[12352,12352],"disallowed"],[[12353,12436],"valid"],[[12437,12438],"valid"],[[12439,12440],"disallowed"],[[12441,12442],"valid"],[[12443,12443],"disallowed_STD3_mapped",[32,12441]],[[12444,12444],"disallowed_STD3_mapped",[32,12442]],[[12445,12446],"valid"],[[12447,12447],"mapped",[12424,12426]],[[12448,12448],"valid",[],"NV8"],[[12449,12542],"valid"],[[12543,12543],"mapped",[12467,12488]],[[12544,12548],"disallowed"],[[12549,12588],"valid"],[[12589,12589],"valid"],[[12590,12592],"disallowed"],[[12593,12593],"mapped",[4352]],[[12594,12594],"mapped",[4353]],[[12595,12595],"mapped",[4522]],[[12596,12596],"mapped",[4354]],[[12597,12597],"mapped",[4524]],[[12598,12598],"mapped",[4525]],[[12599,12599],"mapped",[4355]],[[12600,12600],"mapped",[4356]],[[12601,12601],"mapped",[4357]],[[12602,12602],"mapped",[4528]],[[12603,12603],"mapped",[4529]],[[12604,12604],"mapped",[4530]],[[12605,12605],"mapped",[4531]],[[12606,12606],"mapped",[4532]],[[12607,12607],"mapped",[4533]],[[12608,12608],"mapped",[4378]],[[12609,12609],"mapped",[4358]],[[12610,12610],"mapped",[4359]],[[12611,12611],"mapped",[4360]],[[12612,12612],"mapped",[4385]],[[12613,12613],"mapped",[4361]],[[12614,12614],"mapped",[4362]],[[12615,12615],"mapped",[4363]],[[12616,12616],"mapped",[4364]],[[12617,12617],"mapped",[4365]],[[12618,12618],"mapped",[4366]],[[12619,12619],"mapped",[4367]],[[12620,12620],"mapped",[4368]],[[12621,12621],"mapped",[4369]],[[12622,12622],"mapped",[4370]],[[12623,12623],"mapped",[4449]],[[12624,12624],"mapped",[4450]],[[12625,12625],"mapped",[4451]],[[12626,12626],"mapped",[4452]],[[12627,12627],"mapped",[4453]],[[12628,12628],"mapped",[4454]],[[12629,12629],"mapped",[4455]],[[12630,12630],"mapped",[4456]],[[12631,12631],"mapped",[4457]],[[12632,12632],"mapped",[4458]],[[12633,12633],"mapped",[4459]],[[12634,12634],"mapped",[4460]],[[12635,12635],"mapped",[4461]],[[12636,12636],"mapped",[4462]],[[12637,12637],"mapped",[4463]],[[12638,12638],"mapped",[4464]],[[12639,12639],"mapped",[4465]],[[12640,12640],"mapped",[4466]],[[12641,12641],"mapped",[4467]],[[12642,12642],"mapped",[4468]],[[12643,12643],"mapped",[4469]],[[12644,12644],"disallowed"],[[12645,12645],"mapped",[4372]],[[12646,12646],"mapped",[4373]],[[12647,12647],"mapped",[4551]],[[12648,12648],"mapped",[4552]],[[12649,12649],"mapped",[4556]],[[12650,12650],"mapped",[4558]],[[12651,12651],"mapped",[4563]],[[12652,12652],"mapped",[4567]],[[12653,12653],"mapped",[4569]],[[12654,12654],"mapped",[4380]],[[12655,12655],"mapped",[4573]],[[12656,12656],"mapped",[4575]],[[12657,12657],"mapped",[4381]],[[12658,12658],"mapped",[4382]],[[12659,12659],"mapped",[4384]],[[12660,12660],"mapped",[4386]],[[12661,12661],"mapped",[4387]],[[12662,12662],"mapped",[4391]],[[12663,12663],"mapped",[4393]],[[12664,12664],"mapped",[4395]],[[12665,12665],"mapped",[4396]],[[12666,12666],"mapped",[4397]],[[12667,12667],"mapped",[4398]],[[12668,12668],"mapped",[4399]],[[12669,12669],"mapped",[4402]],[[12670,12670],"mapped",[4406]],[[12671,12671],"mapped",[4416]],[[12672,12672],"mapped",[4423]],[[12673,12673],"mapped",[4428]],[[12674,12674],"mapped",[4593]],[[12675,12675],"mapped",[4594]],[[12676,12676],"mapped",[4439]],[[12677,12677],"mapped",[4440]],[[12678,12678],"mapped",[4441]],[[12679,12679],"mapped",[4484]],[[12680,12680],"mapped",[4485]],[[12681,12681],"mapped",[4488]],[[12682,12682],"mapped",[4497]],[[12683,12683],"mapped",[4498]],[[12684,12684],"mapped",[4500]],[[12685,12685],"mapped",[4510]],[[12686,12686],"mapped",[4513]],[[12687,12687],"disallowed"],[[12688,12689],"valid",[],"NV8"],[[12690,12690],"mapped",[19968]],[[12691,12691],"mapped",[20108]],[[12692,12692],"mapped",[19977]],[[12693,12693],"mapped",[22235]],[[12694,12694],"mapped",[19978]],[[12695,12695],"mapped",[20013]],[[12696,12696],"mapped",[19979]],[[12697,12697],"mapped",[30002]],[[12698,12698],"mapped",[20057]],[[12699,12699],"mapped",[19993]],[[12700,12700],"mapped",[19969]],[[12701,12701],"mapped",[22825]],[[12702,12702],"mapped",[22320]],[[12703,12703],"mapped",[20154]],[[12704,12727],"valid"],[[12728,12730],"valid"],[[12731,12735],"disallowed"],[[12736,12751],"valid",[],"NV8"],[[12752,12771],"valid",[],"NV8"],[[12772,12783],"disallowed"],[[12784,12799],"valid"],[[12800,12800],"disallowed_STD3_mapped",[40,4352,41]],[[12801,12801],"disallowed_STD3_mapped",[40,4354,41]],[[12802,12802],"disallowed_STD3_mapped",[40,4355,41]],[[12803,12803],"disallowed_STD3_mapped",[40,4357,41]],[[12804,12804],"disallowed_STD3_mapped",[40,4358,41]],[[12805,12805],"disallowed_STD3_mapped",[40,4359,41]],[[12806,12806],"disallowed_STD3_mapped",[40,4361,41]],[[12807,12807],"disallowed_STD3_mapped",[40,4363,41]],[[12808,12808],"disallowed_STD3_mapped",[40,4364,41]],[[12809,12809],"disallowed_STD3_mapped",[40,4366,41]],[[12810,12810],"disallowed_STD3_mapped",[40,4367,41]],[[12811,12811],"disallowed_STD3_mapped",[40,4368,41]],[[12812,12812],"disallowed_STD3_mapped",[40,4369,41]],[[12813,12813],"disallowed_STD3_mapped",[40,4370,41]],[[12814,12814],"disallowed_STD3_mapped",[40,44032,41]],[[12815,12815],"disallowed_STD3_mapped",[40,45208,41]],[[12816,12816],"disallowed_STD3_mapped",[40,45796,41]],[[12817,12817],"disallowed_STD3_mapped",[40,46972,41]],[[12818,12818],"disallowed_STD3_mapped",[40,47560,41]],[[12819,12819],"disallowed_STD3_mapped",[40,48148,41]],[[12820,12820],"disallowed_STD3_mapped",[40,49324,41]],[[12821,12821],"disallowed_STD3_mapped",[40,50500,41]],[[12822,12822],"disallowed_STD3_mapped",[40,51088,41]],[[12823,12823],"disallowed_STD3_mapped",[40,52264,41]],[[12824,12824],"disallowed_STD3_mapped",[40,52852,41]],[[12825,12825],"disallowed_STD3_mapped",[40,53440,41]],[[12826,12826],"disallowed_STD3_mapped",[40,54028,41]],[[12827,12827],"disallowed_STD3_mapped",[40,54616,41]],[[12828,12828],"disallowed_STD3_mapped",[40,51452,41]],[[12829,12829],"disallowed_STD3_mapped",[40,50724,51204,41]],[[12830,12830],"disallowed_STD3_mapped",[40,50724,54980,41]],[[12831,12831],"disallowed"],[[12832,12832],"disallowed_STD3_mapped",[40,19968,41]],[[12833,12833],"disallowed_STD3_mapped",[40,20108,41]],[[12834,12834],"disallowed_STD3_mapped",[40,19977,41]],[[12835,12835],"disallowed_STD3_mapped",[40,22235,41]],[[12836,12836],"disallowed_STD3_mapped",[40,20116,41]],[[12837,12837],"disallowed_STD3_mapped",[40,20845,41]],[[12838,12838],"disallowed_STD3_mapped",[40,19971,41]],[[12839,12839],"disallowed_STD3_mapped",[40,20843,41]],[[12840,12840],"disallowed_STD3_mapped",[40,20061,41]],[[12841,12841],"disallowed_STD3_mapped",[40,21313,41]],[[12842,12842],"disallowed_STD3_mapped",[40,26376,41]],[[12843,12843],"disallowed_STD3_mapped",[40,28779,41]],[[12844,12844],"disallowed_STD3_mapped",[40,27700,41]],[[12845,12845],"disallowed_STD3_mapped",[40,26408,41]],[[12846,12846],"disallowed_STD3_mapped",[40,37329,41]],[[12847,12847],"disallowed_STD3_mapped",[40,22303,41]],[[12848,12848],"disallowed_STD3_mapped",[40,26085,41]],[[12849,12849],"disallowed_STD3_mapped",[40,26666,41]],[[12850,12850],"disallowed_STD3_mapped",[40,26377,41]],[[12851,12851],"disallowed_STD3_mapped",[40,31038,41]],[[12852,12852],"disallowed_STD3_mapped",[40,21517,41]],[[12853,12853],"disallowed_STD3_mapped",[40,29305,41]],[[12854,12854],"disallowed_STD3_mapped",[40,36001,41]],[[12855,12855],"disallowed_STD3_mapped",[40,31069,41]],[[12856,12856],"disallowed_STD3_mapped",[40,21172,41]],[[12857,12857],"disallowed_STD3_mapped",[40,20195,41]],[[12858,12858],"disallowed_STD3_mapped",[40,21628,41]],[[12859,12859],"disallowed_STD3_mapped",[40,23398,41]],[[12860,12860],"disallowed_STD3_mapped",[40,30435,41]],[[12861,12861],"disallowed_STD3_mapped",[40,20225,41]],[[12862,12862],"disallowed_STD3_mapped",[40,36039,41]],[[12863,12863],"disallowed_STD3_mapped",[40,21332,41]],[[12864,12864],"disallowed_STD3_mapped",[40,31085,41]],[[12865,12865],"disallowed_STD3_mapped",[40,20241,41]],[[12866,12866],"disallowed_STD3_mapped",[40,33258,41]],[[12867,12867],"disallowed_STD3_mapped",[40,33267,41]],[[12868,12868],"mapped",[21839]],[[12869,12869],"mapped",[24188]],[[12870,12870],"mapped",[25991]],[[12871,12871],"mapped",[31631]],[[12872,12879],"valid",[],"NV8"],[[12880,12880],"mapped",[112,116,101]],[[12881,12881],"mapped",[50,49]],[[12882,12882],"mapped",[50,50]],[[12883,12883],"mapped",[50,51]],[[12884,12884],"mapped",[50,52]],[[12885,12885],"mapped",[50,53]],[[12886,12886],"mapped",[50,54]],[[12887,12887],"mapped",[50,55]],[[12888,12888],"mapped",[50,56]],[[12889,12889],"mapped",[50,57]],[[12890,12890],"mapped",[51,48]],[[12891,12891],"mapped",[51,49]],[[12892,12892],"mapped",[51,50]],[[12893,12893],"mapped",[51,51]],[[12894,12894],"mapped",[51,52]],[[12895,12895],"mapped",[51,53]],[[12896,12896],"mapped",[4352]],[[12897,12897],"mapped",[4354]],[[12898,12898],"mapped",[4355]],[[12899,12899],"mapped",[4357]],[[12900,12900],"mapped",[4358]],[[12901,12901],"mapped",[4359]],[[12902,12902],"mapped",[4361]],[[12903,12903],"mapped",[4363]],[[12904,12904],"mapped",[4364]],[[12905,12905],"mapped",[4366]],[[12906,12906],"mapped",[4367]],[[12907,12907],"mapped",[4368]],[[12908,12908],"mapped",[4369]],[[12909,12909],"mapped",[4370]],[[12910,12910],"mapped",[44032]],[[12911,12911],"mapped",[45208]],[[12912,12912],"mapped",[45796]],[[12913,12913],"mapped",[46972]],[[12914,12914],"mapped",[47560]],[[12915,12915],"mapped",[48148]],[[12916,12916],"mapped",[49324]],[[12917,12917],"mapped",[50500]],[[12918,12918],"mapped",[51088]],[[12919,12919],"mapped",[52264]],[[12920,12920],"mapped",[52852]],[[12921,12921],"mapped",[53440]],[[12922,12922],"mapped",[54028]],[[12923,12923],"mapped",[54616]],[[12924,12924],"mapped",[52280,44256]],[[12925,12925],"mapped",[51452,51032]],[[12926,12926],"mapped",[50864]],[[12927,12927],"valid",[],"NV8"],[[12928,12928],"mapped",[19968]],[[12929,12929],"mapped",[20108]],[[12930,12930],"mapped",[19977]],[[12931,12931],"mapped",[22235]],[[12932,12932],"mapped",[20116]],[[12933,12933],"mapped",[20845]],[[12934,12934],"mapped",[19971]],[[12935,12935],"mapped",[20843]],[[12936,12936],"mapped",[20061]],[[12937,12937],"mapped",[21313]],[[12938,12938],"mapped",[26376]],[[12939,12939],"mapped",[28779]],[[12940,12940],"mapped",[27700]],[[12941,12941],"mapped",[26408]],[[12942,12942],"mapped",[37329]],[[12943,12943],"mapped",[22303]],[[12944,12944],"mapped",[26085]],[[12945,12945],"mapped",[26666]],[[12946,12946],"mapped",[26377]],[[12947,12947],"mapped",[31038]],[[12948,12948],"mapped",[21517]],[[12949,12949],"mapped",[29305]],[[12950,12950],"mapped",[36001]],[[12951,12951],"mapped",[31069]],[[12952,12952],"mapped",[21172]],[[12953,12953],"mapped",[31192]],[[12954,12954],"mapped",[30007]],[[12955,12955],"mapped",[22899]],[[12956,12956],"mapped",[36969]],[[12957,12957],"mapped",[20778]],[[12958,12958],"mapped",[21360]],[[12959,12959],"mapped",[27880]],[[12960,12960],"mapped",[38917]],[[12961,12961],"mapped",[20241]],[[12962,12962],"mapped",[20889]],[[12963,12963],"mapped",[27491]],[[12964,12964],"mapped",[19978]],[[12965,12965],"mapped",[20013]],[[12966,12966],"mapped",[19979]],[[12967,12967],"mapped",[24038]],[[12968,12968],"mapped",[21491]],[[12969,12969],"mapped",[21307]],[[12970,12970],"mapped",[23447]],[[12971,12971],"mapped",[23398]],[[12972,12972],"mapped",[30435]],[[12973,12973],"mapped",[20225]],[[12974,12974],"mapped",[36039]],[[12975,12975],"mapped",[21332]],[[12976,12976],"mapped",[22812]],[[12977,12977],"mapped",[51,54]],[[12978,12978],"mapped",[51,55]],[[12979,12979],"mapped",[51,56]],[[12980,12980],"mapped",[51,57]],[[12981,12981],"mapped",[52,48]],[[12982,12982],"mapped",[52,49]],[[12983,12983],"mapped",[52,50]],[[12984,12984],"mapped",[52,51]],[[12985,12985],"mapped",[52,52]],[[12986,12986],"mapped",[52,53]],[[12987,12987],"mapped",[52,54]],[[12988,12988],"mapped",[52,55]],[[12989,12989],"mapped",[52,56]],[[12990,12990],"mapped",[52,57]],[[12991,12991],"mapped",[53,48]],[[12992,12992],"mapped",[49,26376]],[[12993,12993],"mapped",[50,26376]],[[12994,12994],"mapped",[51,26376]],[[12995,12995],"mapped",[52,26376]],[[12996,12996],"mapped",[53,26376]],[[12997,12997],"mapped",[54,26376]],[[12998,12998],"mapped",[55,26376]],[[12999,12999],"mapped",[56,26376]],[[13000,13000],"mapped",[57,26376]],[[13001,13001],"mapped",[49,48,26376]],[[13002,13002],"mapped",[49,49,26376]],[[13003,13003],"mapped",[49,50,26376]],[[13004,13004],"mapped",[104,103]],[[13005,13005],"mapped",[101,114,103]],[[13006,13006],"mapped",[101,118]],[[13007,13007],"mapped",[108,116,100]],[[13008,13008],"mapped",[12450]],[[13009,13009],"mapped",[12452]],[[13010,13010],"mapped",[12454]],[[13011,13011],"mapped",[12456]],[[13012,13012],"mapped",[12458]],[[13013,13013],"mapped",[12459]],[[13014,13014],"mapped",[12461]],[[13015,13015],"mapped",[12463]],[[13016,13016],"mapped",[12465]],[[13017,13017],"mapped",[12467]],[[13018,13018],"mapped",[12469]],[[13019,13019],"mapped",[12471]],[[13020,13020],"mapped",[12473]],[[13021,13021],"mapped",[12475]],[[13022,13022],"mapped",[12477]],[[13023,13023],"mapped",[12479]],[[13024,13024],"mapped",[12481]],[[13025,13025],"mapped",[12484]],[[13026,13026],"mapped",[12486]],[[13027,13027],"mapped",[12488]],[[13028,13028],"mapped",[12490]],[[13029,13029],"mapped",[12491]],[[13030,13030],"mapped",[12492]],[[13031,13031],"mapped",[12493]],[[13032,13032],"mapped",[12494]],[[13033,13033],"mapped",[12495]],[[13034,13034],"mapped",[12498]],[[13035,13035],"mapped",[12501]],[[13036,13036],"mapped",[12504]],[[13037,13037],"mapped",[12507]],[[13038,13038],"mapped",[12510]],[[13039,13039],"mapped",[12511]],[[13040,13040],"mapped",[12512]],[[13041,13041],"mapped",[12513]],[[13042,13042],"mapped",[12514]],[[13043,13043],"mapped",[12516]],[[13044,13044],"mapped",[12518]],[[13045,13045],"mapped",[12520]],[[13046,13046],"mapped",[12521]],[[13047,13047],"mapped",[12522]],[[13048,13048],"mapped",[12523]],[[13049,13049],"mapped",[12524]],[[13050,13050],"mapped",[12525]],[[13051,13051],"mapped",[12527]],[[13052,13052],"mapped",[12528]],[[13053,13053],"mapped",[12529]],[[13054,13054],"mapped",[12530]],[[13055,13055],"disallowed"],[[13056,13056],"mapped",[12450,12497,12540,12488]],[[13057,13057],"mapped",[12450,12523,12501,12449]],[[13058,13058],"mapped",[12450,12531,12506,12450]],[[13059,13059],"mapped",[12450,12540,12523]],[[13060,13060],"mapped",[12452,12491,12531,12464]],[[13061,13061],"mapped",[12452,12531,12481]],[[13062,13062],"mapped",[12454,12457,12531]],[[13063,13063],"mapped",[12456,12473,12463,12540,12489]],[[13064,13064],"mapped",[12456,12540,12459,12540]],[[13065,13065],"mapped",[12458,12531,12473]],[[13066,13066],"mapped",[12458,12540,12512]],[[13067,13067],"mapped",[12459,12452,12522]],[[13068,13068],"mapped",[12459,12521,12483,12488]],[[13069,13069],"mapped",[12459,12525,12522,12540]],[[13070,13070],"mapped",[12460,12525,12531]],[[13071,13071],"mapped",[12460,12531,12510]],[[13072,13072],"mapped",[12462,12460]],[[13073,13073],"mapped",[12462,12491,12540]],[[13074,13074],"mapped",[12461,12517,12522,12540]],[[13075,13075],"mapped",[12462,12523,12480,12540]],[[13076,13076],"mapped",[12461,12525]],[[13077,13077],"mapped",[12461,12525,12464,12521,12512]],[[13078,13078],"mapped",[12461,12525,12513,12540,12488,12523]],[[13079,13079],"mapped",[12461,12525,12527,12483,12488]],[[13080,13080],"mapped",[12464,12521,12512]],[[13081,13081],"mapped",[12464,12521,12512,12488,12531]],[[13082,13082],"mapped",[12463,12523,12476,12452,12525]],[[13083,13083],"mapped",[12463,12525,12540,12493]],[[13084,13084],"mapped",[12465,12540,12473]],[[13085,13085],"mapped",[12467,12523,12490]],[[13086,13086],"mapped",[12467,12540,12509]],[[13087,13087],"mapped",[12469,12452,12463,12523]],[[13088,13088],"mapped",[12469,12531,12481,12540,12512]],[[13089,13089],"mapped",[12471,12522,12531,12464]],[[13090,13090],"mapped",[12475,12531,12481]],[[13091,13091],"mapped",[12475,12531,12488]],[[13092,13092],"mapped",[12480,12540,12473]],[[13093,13093],"mapped",[12487,12471]],[[13094,13094],"mapped",[12489,12523]],[[13095,13095],"mapped",[12488,12531]],[[13096,13096],"mapped",[12490,12494]],[[13097,13097],"mapped",[12494,12483,12488]],[[13098,13098],"mapped",[12495,12452,12484]],[[13099,13099],"mapped",[12497,12540,12475,12531,12488]],[[13100,13100],"mapped",[12497,12540,12484]],[[13101,13101],"mapped",[12496,12540,12524,12523]],[[13102,13102],"mapped",[12500,12450,12473,12488,12523]],[[13103,13103],"mapped",[12500,12463,12523]],[[13104,13104],"mapped",[12500,12467]],[[13105,13105],"mapped",[12499,12523]],[[13106,13106],"mapped",[12501,12449,12521,12483,12489]],[[13107,13107],"mapped",[12501,12451,12540,12488]],[[13108,13108],"mapped",[12502,12483,12471,12455,12523]],[[13109,13109],"mapped",[12501,12521,12531]],[[13110,13110],"mapped",[12504,12463,12479,12540,12523]],[[13111,13111],"mapped",[12506,12477]],[[13112,13112],"mapped",[12506,12491,12498]],[[13113,13113],"mapped",[12504,12523,12484]],[[13114,13114],"mapped",[12506,12531,12473]],[[13115,13115],"mapped",[12506,12540,12472]],[[13116,13116],"mapped",[12505,12540,12479]],[[13117,13117],"mapped",[12509,12452,12531,12488]],[[13118,13118],"mapped",[12508,12523,12488]],[[13119,13119],"mapped",[12507,12531]],[[13120,13120],"mapped",[12509,12531,12489]],[[13121,13121],"mapped",[12507,12540,12523]],[[13122,13122],"mapped",[12507,12540,12531]],[[13123,13123],"mapped",[12510,12452,12463,12525]],[[13124,13124],"mapped",[12510,12452,12523]],[[13125,13125],"mapped",[12510,12483,12495]],[[13126,13126],"mapped",[12510,12523,12463]],[[13127,13127],"mapped",[12510,12531,12471,12519,12531]],[[13128,13128],"mapped",[12511,12463,12525,12531]],[[13129,13129],"mapped",[12511,12522]],[[13130,13130],"mapped",[12511,12522,12496,12540,12523]],[[13131,13131],"mapped",[12513,12460]],[[13132,13132],"mapped",[12513,12460,12488,12531]],[[13133,13133],"mapped",[12513,12540,12488,12523]],[[13134,13134],"mapped",[12516,12540,12489]],[[13135,13135],"mapped",[12516,12540,12523]],[[13136,13136],"mapped",[12518,12450,12531]],[[13137,13137],"mapped",[12522,12483,12488,12523]],[[13138,13138],"mapped",[12522,12521]],[[13139,13139],"mapped",[12523,12500,12540]],[[13140,13140],"mapped",[12523,12540,12502,12523]],[[13141,13141],"mapped",[12524,12512]],[[13142,13142],"mapped",[12524,12531,12488,12466,12531]],[[13143,13143],"mapped",[12527,12483,12488]],[[13144,13144],"mapped",[48,28857]],[[13145,13145],"mapped",[49,28857]],[[13146,13146],"mapped",[50,28857]],[[13147,13147],"mapped",[51,28857]],[[13148,13148],"mapped",[52,28857]],[[13149,13149],"mapped",[53,28857]],[[13150,13150],"mapped",[54,28857]],[[13151,13151],"mapped",[55,28857]],[[13152,13152],"mapped",[56,28857]],[[13153,13153],"mapped",[57,28857]],[[13154,13154],"mapped",[49,48,28857]],[[13155,13155],"mapped",[49,49,28857]],[[13156,13156],"mapped",[49,50,28857]],[[13157,13157],"mapped",[49,51,28857]],[[13158,13158],"mapped",[49,52,28857]],[[13159,13159],"mapped",[49,53,28857]],[[13160,13160],"mapped",[49,54,28857]],[[13161,13161],"mapped",[49,55,28857]],[[13162,13162],"mapped",[49,56,28857]],[[13163,13163],"mapped",[49,57,28857]],[[13164,13164],"mapped",[50,48,28857]],[[13165,13165],"mapped",[50,49,28857]],[[13166,13166],"mapped",[50,50,28857]],[[13167,13167],"mapped",[50,51,28857]],[[13168,13168],"mapped",[50,52,28857]],[[13169,13169],"mapped",[104,112,97]],[[13170,13170],"mapped",[100,97]],[[13171,13171],"mapped",[97,117]],[[13172,13172],"mapped",[98,97,114]],[[13173,13173],"mapped",[111,118]],[[13174,13174],"mapped",[112,99]],[[13175,13175],"mapped",[100,109]],[[13176,13176],"mapped",[100,109,50]],[[13177,13177],"mapped",[100,109,51]],[[13178,13178],"mapped",[105,117]],[[13179,13179],"mapped",[24179,25104]],[[13180,13180],"mapped",[26157,21644]],[[13181,13181],"mapped",[22823,27491]],[[13182,13182],"mapped",[26126,27835]],[[13183,13183],"mapped",[26666,24335,20250,31038]],[[13184,13184],"mapped",[112,97]],[[13185,13185],"mapped",[110,97]],[[13186,13186],"mapped",[956,97]],[[13187,13187],"mapped",[109,97]],[[13188,13188],"mapped",[107,97]],[[13189,13189],"mapped",[107,98]],[[13190,13190],"mapped",[109,98]],[[13191,13191],"mapped",[103,98]],[[13192,13192],"mapped",[99,97,108]],[[13193,13193],"mapped",[107,99,97,108]],[[13194,13194],"mapped",[112,102]],[[13195,13195],"mapped",[110,102]],[[13196,13196],"mapped",[956,102]],[[13197,13197],"mapped",[956,103]],[[13198,13198],"mapped",[109,103]],[[13199,13199],"mapped",[107,103]],[[13200,13200],"mapped",[104,122]],[[13201,13201],"mapped",[107,104,122]],[[13202,13202],"mapped",[109,104,122]],[[13203,13203],"mapped",[103,104,122]],[[13204,13204],"mapped",[116,104,122]],[[13205,13205],"mapped",[956,108]],[[13206,13206],"mapped",[109,108]],[[13207,13207],"mapped",[100,108]],[[13208,13208],"mapped",[107,108]],[[13209,13209],"mapped",[102,109]],[[13210,13210],"mapped",[110,109]],[[13211,13211],"mapped",[956,109]],[[13212,13212],"mapped",[109,109]],[[13213,13213],"mapped",[99,109]],[[13214,13214],"mapped",[107,109]],[[13215,13215],"mapped",[109,109,50]],[[13216,13216],"mapped",[99,109,50]],[[13217,13217],"mapped",[109,50]],[[13218,13218],"mapped",[107,109,50]],[[13219,13219],"mapped",[109,109,51]],[[13220,13220],"mapped",[99,109,51]],[[13221,13221],"mapped",[109,51]],[[13222,13222],"mapped",[107,109,51]],[[13223,13223],"mapped",[109,8725,115]],[[13224,13224],"mapped",[109,8725,115,50]],[[13225,13225],"mapped",[112,97]],[[13226,13226],"mapped",[107,112,97]],[[13227,13227],"mapped",[109,112,97]],[[13228,13228],"mapped",[103,112,97]],[[13229,13229],"mapped",[114,97,100]],[[13230,13230],"mapped",[114,97,100,8725,115]],[[13231,13231],"mapped",[114,97,100,8725,115,50]],[[13232,13232],"mapped",[112,115]],[[13233,13233],"mapped",[110,115]],[[13234,13234],"mapped",[956,115]],[[13235,13235],"mapped",[109,115]],[[13236,13236],"mapped",[112,118]],[[13237,13237],"mapped",[110,118]],[[13238,13238],"mapped",[956,118]],[[13239,13239],"mapped",[109,118]],[[13240,13240],"mapped",[107,118]],[[13241,13241],"mapped",[109,118]],[[13242,13242],"mapped",[112,119]],[[13243,13243],"mapped",[110,119]],[[13244,13244],"mapped",[956,119]],[[13245,13245],"mapped",[109,119]],[[13246,13246],"mapped",[107,119]],[[13247,13247],"mapped",[109,119]],[[13248,13248],"mapped",[107,969]],[[13249,13249],"mapped",[109,969]],[[13250,13250],"disallowed"],[[13251,13251],"mapped",[98,113]],[[13252,13252],"mapped",[99,99]],[[13253,13253],"mapped",[99,100]],[[13254,13254],"mapped",[99,8725,107,103]],[[13255,13255],"disallowed"],[[13256,13256],"mapped",[100,98]],[[13257,13257],"mapped",[103,121]],[[13258,13258],"mapped",[104,97]],[[13259,13259],"mapped",[104,112]],[[13260,13260],"mapped",[105,110]],[[13261,13261],"mapped",[107,107]],[[13262,13262],"mapped",[107,109]],[[13263,13263],"mapped",[107,116]],[[13264,13264],"mapped",[108,109]],[[13265,13265],"mapped",[108,110]],[[13266,13266],"mapped",[108,111,103]],[[13267,13267],"mapped",[108,120]],[[13268,13268],"mapped",[109,98]],[[13269,13269],"mapped",[109,105,108]],[[13270,13270],"mapped",[109,111,108]],[[13271,13271],"mapped",[112,104]],[[13272,13272],"disallowed"],[[13273,13273],"mapped",[112,112,109]],[[13274,13274],"mapped",[112,114]],[[13275,13275],"mapped",[115,114]],[[13276,13276],"mapped",[115,118]],[[13277,13277],"mapped",[119,98]],[[13278,13278],"mapped",[118,8725,109]],[[13279,13279],"mapped",[97,8725,109]],[[13280,13280],"mapped",[49,26085]],[[13281,13281],"mapped",[50,26085]],[[13282,13282],"mapped",[51,26085]],[[13283,13283],"mapped",[52,26085]],[[13284,13284],"mapped",[53,26085]],[[13285,13285],"mapped",[54,26085]],[[13286,13286],"mapped",[55,26085]],[[13287,13287],"mapped",[56,26085]],[[13288,13288],"mapped",[57,26085]],[[13289,13289],"mapped",[49,48,26085]],[[13290,13290],"mapped",[49,49,26085]],[[13291,13291],"mapped",[49,50,26085]],[[13292,13292],"mapped",[49,51,26085]],[[13293,13293],"mapped",[49,52,26085]],[[13294,13294],"mapped",[49,53,26085]],[[13295,13295],"mapped",[49,54,26085]],[[13296,13296],"mapped",[49,55,26085]],[[13297,13297],"mapped",[49,56,26085]],[[13298,13298],"mapped",[49,57,26085]],[[13299,13299],"mapped",[50,48,26085]],[[13300,13300],"mapped",[50,49,26085]],[[13301,13301],"mapped",[50,50,26085]],[[13302,13302],"mapped",[50,51,26085]],[[13303,13303],"mapped",[50,52,26085]],[[13304,13304],"mapped",[50,53,26085]],[[13305,13305],"mapped",[50,54,26085]],[[13306,13306],"mapped",[50,55,26085]],[[13307,13307],"mapped",[50,56,26085]],[[13308,13308],"mapped",[50,57,26085]],[[13309,13309],"mapped",[51,48,26085]],[[13310,13310],"mapped",[51,49,26085]],[[13311,13311],"mapped",[103,97,108]],[[13312,19893],"valid"],[[19894,19903],"disallowed"],[[19904,19967],"valid",[],"NV8"],[[19968,40869],"valid"],[[40870,40891],"valid"],[[40892,40899],"valid"],[[40900,40907],"valid"],[[40908,40908],"valid"],[[40909,40917],"valid"],[[40918,40959],"disallowed"],[[40960,42124],"valid"],[[42125,42127],"disallowed"],[[42128,42145],"valid",[],"NV8"],[[42146,42147],"valid",[],"NV8"],[[42148,42163],"valid",[],"NV8"],[[42164,42164],"valid",[],"NV8"],[[42165,42176],"valid",[],"NV8"],[[42177,42177],"valid",[],"NV8"],[[42178,42180],"valid",[],"NV8"],[[42181,42181],"valid",[],"NV8"],[[42182,42182],"valid",[],"NV8"],[[42183,42191],"disallowed"],[[42192,42237],"valid"],[[42238,42239],"valid",[],"NV8"],[[42240,42508],"valid"],[[42509,42511],"valid",[],"NV8"],[[42512,42539],"valid"],[[42540,42559],"disallowed"],[[42560,42560],"mapped",[42561]],[[42561,42561],"valid"],[[42562,42562],"mapped",[42563]],[[42563,42563],"valid"],[[42564,42564],"mapped",[42565]],[[42565,42565],"valid"],[[42566,42566],"mapped",[42567]],[[42567,42567],"valid"],[[42568,42568],"mapped",[42569]],[[42569,42569],"valid"],[[42570,42570],"mapped",[42571]],[[42571,42571],"valid"],[[42572,42572],"mapped",[42573]],[[42573,42573],"valid"],[[42574,42574],"mapped",[42575]],[[42575,42575],"valid"],[[42576,42576],"mapped",[42577]],[[42577,42577],"valid"],[[42578,42578],"mapped",[42579]],[[42579,42579],"valid"],[[42580,42580],"mapped",[42581]],[[42581,42581],"valid"],[[42582,42582],"mapped",[42583]],[[42583,42583],"valid"],[[42584,42584],"mapped",[42585]],[[42585,42585],"valid"],[[42586,42586],"mapped",[42587]],[[42587,42587],"valid"],[[42588,42588],"mapped",[42589]],[[42589,42589],"valid"],[[42590,42590],"mapped",[42591]],[[42591,42591],"valid"],[[42592,42592],"mapped",[42593]],[[42593,42593],"valid"],[[42594,42594],"mapped",[42595]],[[42595,42595],"valid"],[[42596,42596],"mapped",[42597]],[[42597,42597],"valid"],[[42598,42598],"mapped",[42599]],[[42599,42599],"valid"],[[42600,42600],"mapped",[42601]],[[42601,42601],"valid"],[[42602,42602],"mapped",[42603]],[[42603,42603],"valid"],[[42604,42604],"mapped",[42605]],[[42605,42607],"valid"],[[42608,42611],"valid",[],"NV8"],[[42612,42619],"valid"],[[42620,42621],"valid"],[[42622,42622],"valid",[],"NV8"],[[42623,42623],"valid"],[[42624,42624],"mapped",[42625]],[[42625,42625],"valid"],[[42626,42626],"mapped",[42627]],[[42627,42627],"valid"],[[42628,42628],"mapped",[42629]],[[42629,42629],"valid"],[[42630,42630],"mapped",[42631]],[[42631,42631],"valid"],[[42632,42632],"mapped",[42633]],[[42633,42633],"valid"],[[42634,42634],"mapped",[42635]],[[42635,42635],"valid"],[[42636,42636],"mapped",[42637]],[[42637,42637],"valid"],[[42638,42638],"mapped",[42639]],[[42639,42639],"valid"],[[42640,42640],"mapped",[42641]],[[42641,42641],"valid"],[[42642,42642],"mapped",[42643]],[[42643,42643],"valid"],[[42644,42644],"mapped",[42645]],[[42645,42645],"valid"],[[42646,42646],"mapped",[42647]],[[42647,42647],"valid"],[[42648,42648],"mapped",[42649]],[[42649,42649],"valid"],[[42650,42650],"mapped",[42651]],[[42651,42651],"valid"],[[42652,42652],"mapped",[1098]],[[42653,42653],"mapped",[1100]],[[42654,42654],"valid"],[[42655,42655],"valid"],[[42656,42725],"valid"],[[42726,42735],"valid",[],"NV8"],[[42736,42737],"valid"],[[42738,42743],"valid",[],"NV8"],[[42744,42751],"disallowed"],[[42752,42774],"valid",[],"NV8"],[[42775,42778],"valid"],[[42779,42783],"valid"],[[42784,42785],"valid",[],"NV8"],[[42786,42786],"mapped",[42787]],[[42787,42787],"valid"],[[42788,42788],"mapped",[42789]],[[42789,42789],"valid"],[[42790,42790],"mapped",[42791]],[[42791,42791],"valid"],[[42792,42792],"mapped",[42793]],[[42793,42793],"valid"],[[42794,42794],"mapped",[42795]],[[42795,42795],"valid"],[[42796,42796],"mapped",[42797]],[[42797,42797],"valid"],[[42798,42798],"mapped",[42799]],[[42799,42801],"valid"],[[42802,42802],"mapped",[42803]],[[42803,42803],"valid"],[[42804,42804],"mapped",[42805]],[[42805,42805],"valid"],[[42806,42806],"mapped",[42807]],[[42807,42807],"valid"],[[42808,42808],"mapped",[42809]],[[42809,42809],"valid"],[[42810,42810],"mapped",[42811]],[[42811,42811],"valid"],[[42812,42812],"mapped",[42813]],[[42813,42813],"valid"],[[42814,42814],"mapped",[42815]],[[42815,42815],"valid"],[[42816,42816],"mapped",[42817]],[[42817,42817],"valid"],[[42818,42818],"mapped",[42819]],[[42819,42819],"valid"],[[42820,42820],"mapped",[42821]],[[42821,42821],"valid"],[[42822,42822],"mapped",[42823]],[[42823,42823],"valid"],[[42824,42824],"mapped",[42825]],[[42825,42825],"valid"],[[42826,42826],"mapped",[42827]],[[42827,42827],"valid"],[[42828,42828],"mapped",[42829]],[[42829,42829],"valid"],[[42830,42830],"mapped",[42831]],[[42831,42831],"valid"],[[42832,42832],"mapped",[42833]],[[42833,42833],"valid"],[[42834,42834],"mapped",[42835]],[[42835,42835],"valid"],[[42836,42836],"mapped",[42837]],[[42837,42837],"valid"],[[42838,42838],"mapped",[42839]],[[42839,42839],"valid"],[[42840,42840],"mapped",[42841]],[[42841,42841],"valid"],[[42842,42842],"mapped",[42843]],[[42843,42843],"valid"],[[42844,42844],"mapped",[42845]],[[42845,42845],"valid"],[[42846,42846],"mapped",[42847]],[[42847,42847],"valid"],[[42848,42848],"mapped",[42849]],[[42849,42849],"valid"],[[42850,42850],"mapped",[42851]],[[42851,42851],"valid"],[[42852,42852],"mapped",[42853]],[[42853,42853],"valid"],[[42854,42854],"mapped",[42855]],[[42855,42855],"valid"],[[42856,42856],"mapped",[42857]],[[42857,42857],"valid"],[[42858,42858],"mapped",[42859]],[[42859,42859],"valid"],[[42860,42860],"mapped",[42861]],[[42861,42861],"valid"],[[42862,42862],"mapped",[42863]],[[42863,42863],"valid"],[[42864,42864],"mapped",[42863]],[[42865,42872],"valid"],[[42873,42873],"mapped",[42874]],[[42874,42874],"valid"],[[42875,42875],"mapped",[42876]],[[42876,42876],"valid"],[[42877,42877],"mapped",[7545]],[[42878,42878],"mapped",[42879]],[[42879,42879],"valid"],[[42880,42880],"mapped",[42881]],[[42881,42881],"valid"],[[42882,42882],"mapped",[42883]],[[42883,42883],"valid"],[[42884,42884],"mapped",[42885]],[[42885,42885],"valid"],[[42886,42886],"mapped",[42887]],[[42887,42888],"valid"],[[42889,42890],"valid",[],"NV8"],[[42891,42891],"mapped",[42892]],[[42892,42892],"valid"],[[42893,42893],"mapped",[613]],[[42894,42894],"valid"],[[42895,42895],"valid"],[[42896,42896],"mapped",[42897]],[[42897,42897],"valid"],[[42898,42898],"mapped",[42899]],[[42899,42899],"valid"],[[42900,42901],"valid"],[[42902,42902],"mapped",[42903]],[[42903,42903],"valid"],[[42904,42904],"mapped",[42905]],[[42905,42905],"valid"],[[42906,42906],"mapped",[42907]],[[42907,42907],"valid"],[[42908,42908],"mapped",[42909]],[[42909,42909],"valid"],[[42910,42910],"mapped",[42911]],[[42911,42911],"valid"],[[42912,42912],"mapped",[42913]],[[42913,42913],"valid"],[[42914,42914],"mapped",[42915]],[[42915,42915],"valid"],[[42916,42916],"mapped",[42917]],[[42917,42917],"valid"],[[42918,42918],"mapped",[42919]],[[42919,42919],"valid"],[[42920,42920],"mapped",[42921]],[[42921,42921],"valid"],[[42922,42922],"mapped",[614]],[[42923,42923],"mapped",[604]],[[42924,42924],"mapped",[609]],[[42925,42925],"mapped",[620]],[[42926,42927],"disallowed"],[[42928,42928],"mapped",[670]],[[42929,42929],"mapped",[647]],[[42930,42930],"mapped",[669]],[[42931,42931],"mapped",[43859]],[[42932,42932],"mapped",[42933]],[[42933,42933],"valid"],[[42934,42934],"mapped",[42935]],[[42935,42935],"valid"],[[42936,42998],"disallowed"],[[42999,42999],"valid"],[[43000,43000],"mapped",[295]],[[43001,43001],"mapped",[339]],[[43002,43002],"valid"],[[43003,43007],"valid"],[[43008,43047],"valid"],[[43048,43051],"valid",[],"NV8"],[[43052,43055],"disallowed"],[[43056,43065],"valid",[],"NV8"],[[43066,43071],"disallowed"],[[43072,43123],"valid"],[[43124,43127],"valid",[],"NV8"],[[43128,43135],"disallowed"],[[43136,43204],"valid"],[[43205,43213],"disallowed"],[[43214,43215],"valid",[],"NV8"],[[43216,43225],"valid"],[[43226,43231],"disallowed"],[[43232,43255],"valid"],[[43256,43258],"valid",[],"NV8"],[[43259,43259],"valid"],[[43260,43260],"valid",[],"NV8"],[[43261,43261],"valid"],[[43262,43263],"disallowed"],[[43264,43309],"valid"],[[43310,43311],"valid",[],"NV8"],[[43312,43347],"valid"],[[43348,43358],"disallowed"],[[43359,43359],"valid",[],"NV8"],[[43360,43388],"valid",[],"NV8"],[[43389,43391],"disallowed"],[[43392,43456],"valid"],[[43457,43469],"valid",[],"NV8"],[[43470,43470],"disallowed"],[[43471,43481],"valid"],[[43482,43485],"disallowed"],[[43486,43487],"valid",[],"NV8"],[[43488,43518],"valid"],[[43519,43519],"disallowed"],[[43520,43574],"valid"],[[43575,43583],"disallowed"],[[43584,43597],"valid"],[[43598,43599],"disallowed"],[[43600,43609],"valid"],[[43610,43611],"disallowed"],[[43612,43615],"valid",[],"NV8"],[[43616,43638],"valid"],[[43639,43641],"valid",[],"NV8"],[[43642,43643],"valid"],[[43644,43647],"valid"],[[43648,43714],"valid"],[[43715,43738],"disallowed"],[[43739,43741],"valid"],[[43742,43743],"valid",[],"NV8"],[[43744,43759],"valid"],[[43760,43761],"valid",[],"NV8"],[[43762,43766],"valid"],[[43767,43776],"disallowed"],[[43777,43782],"valid"],[[43783,43784],"disallowed"],[[43785,43790],"valid"],[[43791,43792],"disallowed"],[[43793,43798],"valid"],[[43799,43807],"disallowed"],[[43808,43814],"valid"],[[43815,43815],"disallowed"],[[43816,43822],"valid"],[[43823,43823],"disallowed"],[[43824,43866],"valid"],[[43867,43867],"valid",[],"NV8"],[[43868,43868],"mapped",[42791]],[[43869,43869],"mapped",[43831]],[[43870,43870],"mapped",[619]],[[43871,43871],"mapped",[43858]],[[43872,43875],"valid"],[[43876,43877],"valid"],[[43878,43887],"disallowed"],[[43888,43888],"mapped",[5024]],[[43889,43889],"mapped",[5025]],[[43890,43890],"mapped",[5026]],[[43891,43891],"mapped",[5027]],[[43892,43892],"mapped",[5028]],[[43893,43893],"mapped",[5029]],[[43894,43894],"mapped",[5030]],[[43895,43895],"mapped",[5031]],[[43896,43896],"mapped",[5032]],[[43897,43897],"mapped",[5033]],[[43898,43898],"mapped",[5034]],[[43899,43899],"mapped",[5035]],[[43900,43900],"mapped",[5036]],[[43901,43901],"mapped",[5037]],[[43902,43902],"mapped",[5038]],[[43903,43903],"mapped",[5039]],[[43904,43904],"mapped",[5040]],[[43905,43905],"mapped",[5041]],[[43906,43906],"mapped",[5042]],[[43907,43907],"mapped",[5043]],[[43908,43908],"mapped",[5044]],[[43909,43909],"mapped",[5045]],[[43910,43910],"mapped",[5046]],[[43911,43911],"mapped",[5047]],[[43912,43912],"mapped",[5048]],[[43913,43913],"mapped",[5049]],[[43914,43914],"mapped",[5050]],[[43915,43915],"mapped",[5051]],[[43916,43916],"mapped",[5052]],[[43917,43917],"mapped",[5053]],[[43918,43918],"mapped",[5054]],[[43919,43919],"mapped",[5055]],[[43920,43920],"mapped",[5056]],[[43921,43921],"mapped",[5057]],[[43922,43922],"mapped",[5058]],[[43923,43923],"mapped",[5059]],[[43924,43924],"mapped",[5060]],[[43925,43925],"mapped",[5061]],[[43926,43926],"mapped",[5062]],[[43927,43927],"mapped",[5063]],[[43928,43928],"mapped",[5064]],[[43929,43929],"mapped",[5065]],[[43930,43930],"mapped",[5066]],[[43931,43931],"mapped",[5067]],[[43932,43932],"mapped",[5068]],[[43933,43933],"mapped",[5069]],[[43934,43934],"mapped",[5070]],[[43935,43935],"mapped",[5071]],[[43936,43936],"mapped",[5072]],[[43937,43937],"mapped",[5073]],[[43938,43938],"mapped",[5074]],[[43939,43939],"mapped",[5075]],[[43940,43940],"mapped",[5076]],[[43941,43941],"mapped",[5077]],[[43942,43942],"mapped",[5078]],[[43943,43943],"mapped",[5079]],[[43944,43944],"mapped",[5080]],[[43945,43945],"mapped",[5081]],[[43946,43946],"mapped",[5082]],[[43947,43947],"mapped",[5083]],[[43948,43948],"mapped",[5084]],[[43949,43949],"mapped",[5085]],[[43950,43950],"mapped",[5086]],[[43951,43951],"mapped",[5087]],[[43952,43952],"mapped",[5088]],[[43953,43953],"mapped",[5089]],[[43954,43954],"mapped",[5090]],[[43955,43955],"mapped",[5091]],[[43956,43956],"mapped",[5092]],[[43957,43957],"mapped",[5093]],[[43958,43958],"mapped",[5094]],[[43959,43959],"mapped",[5095]],[[43960,43960],"mapped",[5096]],[[43961,43961],"mapped",[5097]],[[43962,43962],"mapped",[5098]],[[43963,43963],"mapped",[5099]],[[43964,43964],"mapped",[5100]],[[43965,43965],"mapped",[5101]],[[43966,43966],"mapped",[5102]],[[43967,43967],"mapped",[5103]],[[43968,44010],"valid"],[[44011,44011],"valid",[],"NV8"],[[44012,44013],"valid"],[[44014,44015],"disallowed"],[[44016,44025],"valid"],[[44026,44031],"disallowed"],[[44032,55203],"valid"],[[55204,55215],"disallowed"],[[55216,55238],"valid",[],"NV8"],[[55239,55242],"disallowed"],[[55243,55291],"valid",[],"NV8"],[[55292,55295],"disallowed"],[[55296,57343],"disallowed"],[[57344,63743],"disallowed"],[[63744,63744],"mapped",[35912]],[[63745,63745],"mapped",[26356]],[[63746,63746],"mapped",[36554]],[[63747,63747],"mapped",[36040]],[[63748,63748],"mapped",[28369]],[[63749,63749],"mapped",[20018]],[[63750,63750],"mapped",[21477]],[[63751,63752],"mapped",[40860]],[[63753,63753],"mapped",[22865]],[[63754,63754],"mapped",[37329]],[[63755,63755],"mapped",[21895]],[[63756,63756],"mapped",[22856]],[[63757,63757],"mapped",[25078]],[[63758,63758],"mapped",[30313]],[[63759,63759],"mapped",[32645]],[[63760,63760],"mapped",[34367]],[[63761,63761],"mapped",[34746]],[[63762,63762],"mapped",[35064]],[[63763,63763],"mapped",[37007]],[[63764,63764],"mapped",[27138]],[[63765,63765],"mapped",[27931]],[[63766,63766],"mapped",[28889]],[[63767,63767],"mapped",[29662]],[[63768,63768],"mapped",[33853]],[[63769,63769],"mapped",[37226]],[[63770,63770],"mapped",[39409]],[[63771,63771],"mapped",[20098]],[[63772,63772],"mapped",[21365]],[[63773,63773],"mapped",[27396]],[[63774,63774],"mapped",[29211]],[[63775,63775],"mapped",[34349]],[[63776,63776],"mapped",[40478]],[[63777,63777],"mapped",[23888]],[[63778,63778],"mapped",[28651]],[[63779,63779],"mapped",[34253]],[[63780,63780],"mapped",[35172]],[[63781,63781],"mapped",[25289]],[[63782,63782],"mapped",[33240]],[[63783,63783],"mapped",[34847]],[[63784,63784],"mapped",[24266]],[[63785,63785],"mapped",[26391]],[[63786,63786],"mapped",[28010]],[[63787,63787],"mapped",[29436]],[[63788,63788],"mapped",[37070]],[[63789,63789],"mapped",[20358]],[[63790,63790],"mapped",[20919]],[[63791,63791],"mapped",[21214]],[[63792,63792],"mapped",[25796]],[[63793,63793],"mapped",[27347]],[[63794,63794],"mapped",[29200]],[[63795,63795],"mapped",[30439]],[[63796,63796],"mapped",[32769]],[[63797,63797],"mapped",[34310]],[[63798,63798],"mapped",[34396]],[[63799,63799],"mapped",[36335]],[[63800,63800],"mapped",[38706]],[[63801,63801],"mapped",[39791]],[[63802,63802],"mapped",[40442]],[[63803,63803],"mapped",[30860]],[[63804,63804],"mapped",[31103]],[[63805,63805],"mapped",[32160]],[[63806,63806],"mapped",[33737]],[[63807,63807],"mapped",[37636]],[[63808,63808],"mapped",[40575]],[[63809,63809],"mapped",[35542]],[[63810,63810],"mapped",[22751]],[[63811,63811],"mapped",[24324]],[[63812,63812],"mapped",[31840]],[[63813,63813],"mapped",[32894]],[[63814,63814],"mapped",[29282]],[[63815,63815],"mapped",[30922]],[[63816,63816],"mapped",[36034]],[[63817,63817],"mapped",[38647]],[[63818,63818],"mapped",[22744]],[[63819,63819],"mapped",[23650]],[[63820,63820],"mapped",[27155]],[[63821,63821],"mapped",[28122]],[[63822,63822],"mapped",[28431]],[[63823,63823],"mapped",[32047]],[[63824,63824],"mapped",[32311]],[[63825,63825],"mapped",[38475]],[[63826,63826],"mapped",[21202]],[[63827,63827],"mapped",[32907]],[[63828,63828],"mapped",[20956]],[[63829,63829],"mapped",[20940]],[[63830,63830],"mapped",[31260]],[[63831,63831],"mapped",[32190]],[[63832,63832],"mapped",[33777]],[[63833,63833],"mapped",[38517]],[[63834,63834],"mapped",[35712]],[[63835,63835],"mapped",[25295]],[[63836,63836],"mapped",[27138]],[[63837,63837],"mapped",[35582]],[[63838,63838],"mapped",[20025]],[[63839,63839],"mapped",[23527]],[[63840,63840],"mapped",[24594]],[[63841,63841],"mapped",[29575]],[[63842,63842],"mapped",[30064]],[[63843,63843],"mapped",[21271]],[[63844,63844],"mapped",[30971]],[[63845,63845],"mapped",[20415]],[[63846,63846],"mapped",[24489]],[[63847,63847],"mapped",[19981]],[[63848,63848],"mapped",[27852]],[[63849,63849],"mapped",[25976]],[[63850,63850],"mapped",[32034]],[[63851,63851],"mapped",[21443]],[[63852,63852],"mapped",[22622]],[[63853,63853],"mapped",[30465]],[[63854,63854],"mapped",[33865]],[[63855,63855],"mapped",[35498]],[[63856,63856],"mapped",[27578]],[[63857,63857],"mapped",[36784]],[[63858,63858],"mapped",[27784]],[[63859,63859],"mapped",[25342]],[[63860,63860],"mapped",[33509]],[[63861,63861],"mapped",[25504]],[[63862,63862],"mapped",[30053]],[[63863,63863],"mapped",[20142]],[[63864,63864],"mapped",[20841]],[[63865,63865],"mapped",[20937]],[[63866,63866],"mapped",[26753]],[[63867,63867],"mapped",[31975]],[[63868,63868],"mapped",[33391]],[[63869,63869],"mapped",[35538]],[[63870,63870],"mapped",[37327]],[[63871,63871],"mapped",[21237]],[[63872,63872],"mapped",[21570]],[[63873,63873],"mapped",[22899]],[[63874,63874],"mapped",[24300]],[[63875,63875],"mapped",[26053]],[[63876,63876],"mapped",[28670]],[[63877,63877],"mapped",[31018]],[[63878,63878],"mapped",[38317]],[[63879,63879],"mapped",[39530]],[[63880,63880],"mapped",[40599]],[[63881,63881],"mapped",[40654]],[[63882,63882],"mapped",[21147]],[[63883,63883],"mapped",[26310]],[[63884,63884],"mapped",[27511]],[[63885,63885],"mapped",[36706]],[[63886,63886],"mapped",[24180]],[[63887,63887],"mapped",[24976]],[[63888,63888],"mapped",[25088]],[[63889,63889],"mapped",[25754]],[[63890,63890],"mapped",[28451]],[[63891,63891],"mapped",[29001]],[[63892,63892],"mapped",[29833]],[[63893,63893],"mapped",[31178]],[[63894,63894],"mapped",[32244]],[[63895,63895],"mapped",[32879]],[[63896,63896],"mapped",[36646]],[[63897,63897],"mapped",[34030]],[[63898,63898],"mapped",[36899]],[[63899,63899],"mapped",[37706]],[[63900,63900],"mapped",[21015]],[[63901,63901],"mapped",[21155]],[[63902,63902],"mapped",[21693]],[[63903,63903],"mapped",[28872]],[[63904,63904],"mapped",[35010]],[[63905,63905],"mapped",[35498]],[[63906,63906],"mapped",[24265]],[[63907,63907],"mapped",[24565]],[[63908,63908],"mapped",[25467]],[[63909,63909],"mapped",[27566]],[[63910,63910],"mapped",[31806]],[[63911,63911],"mapped",[29557]],[[63912,63912],"mapped",[20196]],[[63913,63913],"mapped",[22265]],[[63914,63914],"mapped",[23527]],[[63915,63915],"mapped",[23994]],[[63916,63916],"mapped",[24604]],[[63917,63917],"mapped",[29618]],[[63918,63918],"mapped",[29801]],[[63919,63919],"mapped",[32666]],[[63920,63920],"mapped",[32838]],[[63921,63921],"mapped",[37428]],[[63922,63922],"mapped",[38646]],[[63923,63923],"mapped",[38728]],[[63924,63924],"mapped",[38936]],[[63925,63925],"mapped",[20363]],[[63926,63926],"mapped",[31150]],[[63927,63927],"mapped",[37300]],[[63928,63928],"mapped",[38584]],[[63929,63929],"mapped",[24801]],[[63930,63930],"mapped",[20102]],[[63931,63931],"mapped",[20698]],[[63932,63932],"mapped",[23534]],[[63933,63933],"mapped",[23615]],[[63934,63934],"mapped",[26009]],[[63935,63935],"mapped",[27138]],[[63936,63936],"mapped",[29134]],[[63937,63937],"mapped",[30274]],[[63938,63938],"mapped",[34044]],[[63939,63939],"mapped",[36988]],[[63940,63940],"mapped",[40845]],[[63941,63941],"mapped",[26248]],[[63942,63942],"mapped",[38446]],[[63943,63943],"mapped",[21129]],[[63944,63944],"mapped",[26491]],[[63945,63945],"mapped",[26611]],[[63946,63946],"mapped",[27969]],[[63947,63947],"mapped",[28316]],[[63948,63948],"mapped",[29705]],[[63949,63949],"mapped",[30041]],[[63950,63950],"mapped",[30827]],[[63951,63951],"mapped",[32016]],[[63952,63952],"mapped",[39006]],[[63953,63953],"mapped",[20845]],[[63954,63954],"mapped",[25134]],[[63955,63955],"mapped",[38520]],[[63956,63956],"mapped",[20523]],[[63957,63957],"mapped",[23833]],[[63958,63958],"mapped",[28138]],[[63959,63959],"mapped",[36650]],[[63960,63960],"mapped",[24459]],[[63961,63961],"mapped",[24900]],[[63962,63962],"mapped",[26647]],[[63963,63963],"mapped",[29575]],[[63964,63964],"mapped",[38534]],[[63965,63965],"mapped",[21033]],[[63966,63966],"mapped",[21519]],[[63967,63967],"mapped",[23653]],[[63968,63968],"mapped",[26131]],[[63969,63969],"mapped",[26446]],[[63970,63970],"mapped",[26792]],[[63971,63971],"mapped",[27877]],[[63972,63972],"mapped",[29702]],[[63973,63973],"mapped",[30178]],[[63974,63974],"mapped",[32633]],[[63975,63975],"mapped",[35023]],[[63976,63976],"mapped",[35041]],[[63977,63977],"mapped",[37324]],[[63978,63978],"mapped",[38626]],[[63979,63979],"mapped",[21311]],[[63980,63980],"mapped",[28346]],[[63981,63981],"mapped",[21533]],[[63982,63982],"mapped",[29136]],[[63983,63983],"mapped",[29848]],[[63984,63984],"mapped",[34298]],[[63985,63985],"mapped",[38563]],[[63986,63986],"mapped",[40023]],[[63987,63987],"mapped",[40607]],[[63988,63988],"mapped",[26519]],[[63989,63989],"mapped",[28107]],[[63990,63990],"mapped",[33256]],[[63991,63991],"mapped",[31435]],[[63992,63992],"mapped",[31520]],[[63993,63993],"mapped",[31890]],[[63994,63994],"mapped",[29376]],[[63995,63995],"mapped",[28825]],[[63996,63996],"mapped",[35672]],[[63997,63997],"mapped",[20160]],[[63998,63998],"mapped",[33590]],[[63999,63999],"mapped",[21050]],[[64000,64000],"mapped",[20999]],[[64001,64001],"mapped",[24230]],[[64002,64002],"mapped",[25299]],[[64003,64003],"mapped",[31958]],[[64004,64004],"mapped",[23429]],[[64005,64005],"mapped",[27934]],[[64006,64006],"mapped",[26292]],[[64007,64007],"mapped",[36667]],[[64008,64008],"mapped",[34892]],[[64009,64009],"mapped",[38477]],[[64010,64010],"mapped",[35211]],[[64011,64011],"mapped",[24275]],[[64012,64012],"mapped",[20800]],[[64013,64013],"mapped",[21952]],[[64014,64015],"valid"],[[64016,64016],"mapped",[22618]],[[64017,64017],"valid"],[[64018,64018],"mapped",[26228]],[[64019,64020],"valid"],[[64021,64021],"mapped",[20958]],[[64022,64022],"mapped",[29482]],[[64023,64023],"mapped",[30410]],[[64024,64024],"mapped",[31036]],[[64025,64025],"mapped",[31070]],[[64026,64026],"mapped",[31077]],[[64027,64027],"mapped",[31119]],[[64028,64028],"mapped",[38742]],[[64029,64029],"mapped",[31934]],[[64030,64030],"mapped",[32701]],[[64031,64031],"valid"],[[64032,64032],"mapped",[34322]],[[64033,64033],"valid"],[[64034,64034],"mapped",[35576]],[[64035,64036],"valid"],[[64037,64037],"mapped",[36920]],[[64038,64038],"mapped",[37117]],[[64039,64041],"valid"],[[64042,64042],"mapped",[39151]],[[64043,64043],"mapped",[39164]],[[64044,64044],"mapped",[39208]],[[64045,64045],"mapped",[40372]],[[64046,64046],"mapped",[37086]],[[64047,64047],"mapped",[38583]],[[64048,64048],"mapped",[20398]],[[64049,64049],"mapped",[20711]],[[64050,64050],"mapped",[20813]],[[64051,64051],"mapped",[21193]],[[64052,64052],"mapped",[21220]],[[64053,64053],"mapped",[21329]],[[64054,64054],"mapped",[21917]],[[64055,64055],"mapped",[22022]],[[64056,64056],"mapped",[22120]],[[64057,64057],"mapped",[22592]],[[64058,64058],"mapped",[22696]],[[64059,64059],"mapped",[23652]],[[64060,64060],"mapped",[23662]],[[64061,64061],"mapped",[24724]],[[64062,64062],"mapped",[24936]],[[64063,64063],"mapped",[24974]],[[64064,64064],"mapped",[25074]],[[64065,64065],"mapped",[25935]],[[64066,64066],"mapped",[26082]],[[64067,64067],"mapped",[26257]],[[64068,64068],"mapped",[26757]],[[64069,64069],"mapped",[28023]],[[64070,64070],"mapped",[28186]],[[64071,64071],"mapped",[28450]],[[64072,64072],"mapped",[29038]],[[64073,64073],"mapped",[29227]],[[64074,64074],"mapped",[29730]],[[64075,64075],"mapped",[30865]],[[64076,64076],"mapped",[31038]],[[64077,64077],"mapped",[31049]],[[64078,64078],"mapped",[31048]],[[64079,64079],"mapped",[31056]],[[64080,64080],"mapped",[31062]],[[64081,64081],"mapped",[31069]],[[64082,64082],"mapped",[31117]],[[64083,64083],"mapped",[31118]],[[64084,64084],"mapped",[31296]],[[64085,64085],"mapped",[31361]],[[64086,64086],"mapped",[31680]],[[64087,64087],"mapped",[32244]],[[64088,64088],"mapped",[32265]],[[64089,64089],"mapped",[32321]],[[64090,64090],"mapped",[32626]],[[64091,64091],"mapped",[32773]],[[64092,64092],"mapped",[33261]],[[64093,64094],"mapped",[33401]],[[64095,64095],"mapped",[33879]],[[64096,64096],"mapped",[35088]],[[64097,64097],"mapped",[35222]],[[64098,64098],"mapped",[35585]],[[64099,64099],"mapped",[35641]],[[64100,64100],"mapped",[36051]],[[64101,64101],"mapped",[36104]],[[64102,64102],"mapped",[36790]],[[64103,64103],"mapped",[36920]],[[64104,64104],"mapped",[38627]],[[64105,64105],"mapped",[38911]],[[64106,64106],"mapped",[38971]],[[64107,64107],"mapped",[24693]],[[64108,64108],"mapped",[148206]],[[64109,64109],"mapped",[33304]],[[64110,64111],"disallowed"],[[64112,64112],"mapped",[20006]],[[64113,64113],"mapped",[20917]],[[64114,64114],"mapped",[20840]],[[64115,64115],"mapped",[20352]],[[64116,64116],"mapped",[20805]],[[64117,64117],"mapped",[20864]],[[64118,64118],"mapped",[21191]],[[64119,64119],"mapped",[21242]],[[64120,64120],"mapped",[21917]],[[64121,64121],"mapped",[21845]],[[64122,64122],"mapped",[21913]],[[64123,64123],"mapped",[21986]],[[64124,64124],"mapped",[22618]],[[64125,64125],"mapped",[22707]],[[64126,64126],"mapped",[22852]],[[64127,64127],"mapped",[22868]],[[64128,64128],"mapped",[23138]],[[64129,64129],"mapped",[23336]],[[64130,64130],"mapped",[24274]],[[64131,64131],"mapped",[24281]],[[64132,64132],"mapped",[24425]],[[64133,64133],"mapped",[24493]],[[64134,64134],"mapped",[24792]],[[64135,64135],"mapped",[24910]],[[64136,64136],"mapped",[24840]],[[64137,64137],"mapped",[24974]],[[64138,64138],"mapped",[24928]],[[64139,64139],"mapped",[25074]],[[64140,64140],"mapped",[25140]],[[64141,64141],"mapped",[25540]],[[64142,64142],"mapped",[25628]],[[64143,64143],"mapped",[25682]],[[64144,64144],"mapped",[25942]],[[64145,64145],"mapped",[26228]],[[64146,64146],"mapped",[26391]],[[64147,64147],"mapped",[26395]],[[64148,64148],"mapped",[26454]],[[64149,64149],"mapped",[27513]],[[64150,64150],"mapped",[27578]],[[64151,64151],"mapped",[27969]],[[64152,64152],"mapped",[28379]],[[64153,64153],"mapped",[28363]],[[64154,64154],"mapped",[28450]],[[64155,64155],"mapped",[28702]],[[64156,64156],"mapped",[29038]],[[64157,64157],"mapped",[30631]],[[64158,64158],"mapped",[29237]],[[64159,64159],"mapped",[29359]],[[64160,64160],"mapped",[29482]],[[64161,64161],"mapped",[29809]],[[64162,64162],"mapped",[29958]],[[64163,64163],"mapped",[30011]],[[64164,64164],"mapped",[30237]],[[64165,64165],"mapped",[30239]],[[64166,64166],"mapped",[30410]],[[64167,64167],"mapped",[30427]],[[64168,64168],"mapped",[30452]],[[64169,64169],"mapped",[30538]],[[64170,64170],"mapped",[30528]],[[64171,64171],"mapped",[30924]],[[64172,64172],"mapped",[31409]],[[64173,64173],"mapped",[31680]],[[64174,64174],"mapped",[31867]],[[64175,64175],"mapped",[32091]],[[64176,64176],"mapped",[32244]],[[64177,64177],"mapped",[32574]],[[64178,64178],"mapped",[32773]],[[64179,64179],"mapped",[33618]],[[64180,64180],"mapped",[33775]],[[64181,64181],"mapped",[34681]],[[64182,64182],"mapped",[35137]],[[64183,64183],"mapped",[35206]],[[64184,64184],"mapped",[35222]],[[64185,64185],"mapped",[35519]],[[64186,64186],"mapped",[35576]],[[64187,64187],"mapped",[35531]],[[64188,64188],"mapped",[35585]],[[64189,64189],"mapped",[35582]],[[64190,64190],"mapped",[35565]],[[64191,64191],"mapped",[35641]],[[64192,64192],"mapped",[35722]],[[64193,64193],"mapped",[36104]],[[64194,64194],"mapped",[36664]],[[64195,64195],"mapped",[36978]],[[64196,64196],"mapped",[37273]],[[64197,64197],"mapped",[37494]],[[64198,64198],"mapped",[38524]],[[64199,64199],"mapped",[38627]],[[64200,64200],"mapped",[38742]],[[64201,64201],"mapped",[38875]],[[64202,64202],"mapped",[38911]],[[64203,64203],"mapped",[38923]],[[64204,64204],"mapped",[38971]],[[64205,64205],"mapped",[39698]],[[64206,64206],"mapped",[40860]],[[64207,64207],"mapped",[141386]],[[64208,64208],"mapped",[141380]],[[64209,64209],"mapped",[144341]],[[64210,64210],"mapped",[15261]],[[64211,64211],"mapped",[16408]],[[64212,64212],"mapped",[16441]],[[64213,64213],"mapped",[152137]],[[64214,64214],"mapped",[154832]],[[64215,64215],"mapped",[163539]],[[64216,64216],"mapped",[40771]],[[64217,64217],"mapped",[40846]],[[64218,64255],"disallowed"],[[64256,64256],"mapped",[102,102]],[[64257,64257],"mapped",[102,105]],[[64258,64258],"mapped",[102,108]],[[64259,64259],"mapped",[102,102,105]],[[64260,64260],"mapped",[102,102,108]],[[64261,64262],"mapped",[115,116]],[[64263,64274],"disallowed"],[[64275,64275],"mapped",[1396,1398]],[[64276,64276],"mapped",[1396,1381]],[[64277,64277],"mapped",[1396,1387]],[[64278,64278],"mapped",[1406,1398]],[[64279,64279],"mapped",[1396,1389]],[[64280,64284],"disallowed"],[[64285,64285],"mapped",[1497,1460]],[[64286,64286],"valid"],[[64287,64287],"mapped",[1522,1463]],[[64288,64288],"mapped",[1506]],[[64289,64289],"mapped",[1488]],[[64290,64290],"mapped",[1491]],[[64291,64291],"mapped",[1492]],[[64292,64292],"mapped",[1499]],[[64293,64293],"mapped",[1500]],[[64294,64294],"mapped",[1501]],[[64295,64295],"mapped",[1512]],[[64296,64296],"mapped",[1514]],[[64297,64297],"disallowed_STD3_mapped",[43]],[[64298,64298],"mapped",[1513,1473]],[[64299,64299],"mapped",[1513,1474]],[[64300,64300],"mapped",[1513,1468,1473]],[[64301,64301],"mapped",[1513,1468,1474]],[[64302,64302],"mapped",[1488,1463]],[[64303,64303],"mapped",[1488,1464]],[[64304,64304],"mapped",[1488,1468]],[[64305,64305],"mapped",[1489,1468]],[[64306,64306],"mapped",[1490,1468]],[[64307,64307],"mapped",[1491,1468]],[[64308,64308],"mapped",[1492,1468]],[[64309,64309],"mapped",[1493,1468]],[[64310,64310],"mapped",[1494,1468]],[[64311,64311],"disallowed"],[[64312,64312],"mapped",[1496,1468]],[[64313,64313],"mapped",[1497,1468]],[[64314,64314],"mapped",[1498,1468]],[[64315,64315],"mapped",[1499,1468]],[[64316,64316],"mapped",[1500,1468]],[[64317,64317],"disallowed"],[[64318,64318],"mapped",[1502,1468]],[[64319,64319],"disallowed"],[[64320,64320],"mapped",[1504,1468]],[[64321,64321],"mapped",[1505,1468]],[[64322,64322],"disallowed"],[[64323,64323],"mapped",[1507,1468]],[[64324,64324],"mapped",[1508,1468]],[[64325,64325],"disallowed"],[[64326,64326],"mapped",[1510,1468]],[[64327,64327],"mapped",[1511,1468]],[[64328,64328],"mapped",[1512,1468]],[[64329,64329],"mapped",[1513,1468]],[[64330,64330],"mapped",[1514,1468]],[[64331,64331],"mapped",[1493,1465]],[[64332,64332],"mapped",[1489,1471]],[[64333,64333],"mapped",[1499,1471]],[[64334,64334],"mapped",[1508,1471]],[[64335,64335],"mapped",[1488,1500]],[[64336,64337],"mapped",[1649]],[[64338,64341],"mapped",[1659]],[[64342,64345],"mapped",[1662]],[[64346,64349],"mapped",[1664]],[[64350,64353],"mapped",[1658]],[[64354,64357],"mapped",[1663]],[[64358,64361],"mapped",[1657]],[[64362,64365],"mapped",[1700]],[[64366,64369],"mapped",[1702]],[[64370,64373],"mapped",[1668]],[[64374,64377],"mapped",[1667]],[[64378,64381],"mapped",[1670]],[[64382,64385],"mapped",[1671]],[[64386,64387],"mapped",[1677]],[[64388,64389],"mapped",[1676]],[[64390,64391],"mapped",[1678]],[[64392,64393],"mapped",[1672]],[[64394,64395],"mapped",[1688]],[[64396,64397],"mapped",[1681]],[[64398,64401],"mapped",[1705]],[[64402,64405],"mapped",[1711]],[[64406,64409],"mapped",[1715]],[[64410,64413],"mapped",[1713]],[[64414,64415],"mapped",[1722]],[[64416,64419],"mapped",[1723]],[[64420,64421],"mapped",[1728]],[[64422,64425],"mapped",[1729]],[[64426,64429],"mapped",[1726]],[[64430,64431],"mapped",[1746]],[[64432,64433],"mapped",[1747]],[[64434,64449],"valid",[],"NV8"],[[64450,64466],"disallowed"],[[64467,64470],"mapped",[1709]],[[64471,64472],"mapped",[1735]],[[64473,64474],"mapped",[1734]],[[64475,64476],"mapped",[1736]],[[64477,64477],"mapped",[1735,1652]],[[64478,64479],"mapped",[1739]],[[64480,64481],"mapped",[1733]],[[64482,64483],"mapped",[1737]],[[64484,64487],"mapped",[1744]],[[64488,64489],"mapped",[1609]],[[64490,64491],"mapped",[1574,1575]],[[64492,64493],"mapped",[1574,1749]],[[64494,64495],"mapped",[1574,1608]],[[64496,64497],"mapped",[1574,1735]],[[64498,64499],"mapped",[1574,1734]],[[64500,64501],"mapped",[1574,1736]],[[64502,64504],"mapped",[1574,1744]],[[64505,64507],"mapped",[1574,1609]],[[64508,64511],"mapped",[1740]],[[64512,64512],"mapped",[1574,1580]],[[64513,64513],"mapped",[1574,1581]],[[64514,64514],"mapped",[1574,1605]],[[64515,64515],"mapped",[1574,1609]],[[64516,64516],"mapped",[1574,1610]],[[64517,64517],"mapped",[1576,1580]],[[64518,64518],"mapped",[1576,1581]],[[64519,64519],"mapped",[1576,1582]],[[64520,64520],"mapped",[1576,1605]],[[64521,64521],"mapped",[1576,1609]],[[64522,64522],"mapped",[1576,1610]],[[64523,64523],"mapped",[1578,1580]],[[64524,64524],"mapped",[1578,1581]],[[64525,64525],"mapped",[1578,1582]],[[64526,64526],"mapped",[1578,1605]],[[64527,64527],"mapped",[1578,1609]],[[64528,64528],"mapped",[1578,1610]],[[64529,64529],"mapped",[1579,1580]],[[64530,64530],"mapped",[1579,1605]],[[64531,64531],"mapped",[1579,1609]],[[64532,64532],"mapped",[1579,1610]],[[64533,64533],"mapped",[1580,1581]],[[64534,64534],"mapped",[1580,1605]],[[64535,64535],"mapped",[1581,1580]],[[64536,64536],"mapped",[1581,1605]],[[64537,64537],"mapped",[1582,1580]],[[64538,64538],"mapped",[1582,1581]],[[64539,64539],"mapped",[1582,1605]],[[64540,64540],"mapped",[1587,1580]],[[64541,64541],"mapped",[1587,1581]],[[64542,64542],"mapped",[1587,1582]],[[64543,64543],"mapped",[1587,1605]],[[64544,64544],"mapped",[1589,1581]],[[64545,64545],"mapped",[1589,1605]],[[64546,64546],"mapped",[1590,1580]],[[64547,64547],"mapped",[1590,1581]],[[64548,64548],"mapped",[1590,1582]],[[64549,64549],"mapped",[1590,1605]],[[64550,64550],"mapped",[1591,1581]],[[64551,64551],"mapped",[1591,1605]],[[64552,64552],"mapped",[1592,1605]],[[64553,64553],"mapped",[1593,1580]],[[64554,64554],"mapped",[1593,1605]],[[64555,64555],"mapped",[1594,1580]],[[64556,64556],"mapped",[1594,1605]],[[64557,64557],"mapped",[1601,1580]],[[64558,64558],"mapped",[1601,1581]],[[64559,64559],"mapped",[1601,1582]],[[64560,64560],"mapped",[1601,1605]],[[64561,64561],"mapped",[1601,1609]],[[64562,64562],"mapped",[1601,1610]],[[64563,64563],"mapped",[1602,1581]],[[64564,64564],"mapped",[1602,1605]],[[64565,64565],"mapped",[1602,1609]],[[64566,64566],"mapped",[1602,1610]],[[64567,64567],"mapped",[1603,1575]],[[64568,64568],"mapped",[1603,1580]],[[64569,64569],"mapped",[1603,1581]],[[64570,64570],"mapped",[1603,1582]],[[64571,64571],"mapped",[1603,1604]],[[64572,64572],"mapped",[1603,1605]],[[64573,64573],"mapped",[1603,1609]],[[64574,64574],"mapped",[1603,1610]],[[64575,64575],"mapped",[1604,1580]],[[64576,64576],"mapped",[1604,1581]],[[64577,64577],"mapped",[1604,1582]],[[64578,64578],"mapped",[1604,1605]],[[64579,64579],"mapped",[1604,1609]],[[64580,64580],"mapped",[1604,1610]],[[64581,64581],"mapped",[1605,1580]],[[64582,64582],"mapped",[1605,1581]],[[64583,64583],"mapped",[1605,1582]],[[64584,64584],"mapped",[1605,1605]],[[64585,64585],"mapped",[1605,1609]],[[64586,64586],"mapped",[1605,1610]],[[64587,64587],"mapped",[1606,1580]],[[64588,64588],"mapped",[1606,1581]],[[64589,64589],"mapped",[1606,1582]],[[64590,64590],"mapped",[1606,1605]],[[64591,64591],"mapped",[1606,1609]],[[64592,64592],"mapped",[1606,1610]],[[64593,64593],"mapped",[1607,1580]],[[64594,64594],"mapped",[1607,1605]],[[64595,64595],"mapped",[1607,1609]],[[64596,64596],"mapped",[1607,1610]],[[64597,64597],"mapped",[1610,1580]],[[64598,64598],"mapped",[1610,1581]],[[64599,64599],"mapped",[1610,1582]],[[64600,64600],"mapped",[1610,1605]],[[64601,64601],"mapped",[1610,1609]],[[64602,64602],"mapped",[1610,1610]],[[64603,64603],"mapped",[1584,1648]],[[64604,64604],"mapped",[1585,1648]],[[64605,64605],"mapped",[1609,1648]],[[64606,64606],"disallowed_STD3_mapped",[32,1612,1617]],[[64607,64607],"disallowed_STD3_mapped",[32,1613,1617]],[[64608,64608],"disallowed_STD3_mapped",[32,1614,1617]],[[64609,64609],"disallowed_STD3_mapped",[32,1615,1617]],[[64610,64610],"disallowed_STD3_mapped",[32,1616,1617]],[[64611,64611],"disallowed_STD3_mapped",[32,1617,1648]],[[64612,64612],"mapped",[1574,1585]],[[64613,64613],"mapped",[1574,1586]],[[64614,64614],"mapped",[1574,1605]],[[64615,64615],"mapped",[1574,1606]],[[64616,64616],"mapped",[1574,1609]],[[64617,64617],"mapped",[1574,1610]],[[64618,64618],"mapped",[1576,1585]],[[64619,64619],"mapped",[1576,1586]],[[64620,64620],"mapped",[1576,1605]],[[64621,64621],"mapped",[1576,1606]],[[64622,64622],"mapped",[1576,1609]],[[64623,64623],"mapped",[1576,1610]],[[64624,64624],"mapped",[1578,1585]],[[64625,64625],"mapped",[1578,1586]],[[64626,64626],"mapped",[1578,1605]],[[64627,64627],"mapped",[1578,1606]],[[64628,64628],"mapped",[1578,1609]],[[64629,64629],"mapped",[1578,1610]],[[64630,64630],"mapped",[1579,1585]],[[64631,64631],"mapped",[1579,1586]],[[64632,64632],"mapped",[1579,1605]],[[64633,64633],"mapped",[1579,1606]],[[64634,64634],"mapped",[1579,1609]],[[64635,64635],"mapped",[1579,1610]],[[64636,64636],"mapped",[1601,1609]],[[64637,64637],"mapped",[1601,1610]],[[64638,64638],"mapped",[1602,1609]],[[64639,64639],"mapped",[1602,1610]],[[64640,64640],"mapped",[1603,1575]],[[64641,64641],"mapped",[1603,1604]],[[64642,64642],"mapped",[1603,1605]],[[64643,64643],"mapped",[1603,1609]],[[64644,64644],"mapped",[1603,1610]],[[64645,64645],"mapped",[1604,1605]],[[64646,64646],"mapped",[1604,1609]],[[64647,64647],"mapped",[1604,1610]],[[64648,64648],"mapped",[1605,1575]],[[64649,64649],"mapped",[1605,1605]],[[64650,64650],"mapped",[1606,1585]],[[64651,64651],"mapped",[1606,1586]],[[64652,64652],"mapped",[1606,1605]],[[64653,64653],"mapped",[1606,1606]],[[64654,64654],"mapped",[1606,1609]],[[64655,64655],"mapped",[1606,1610]],[[64656,64656],"mapped",[1609,1648]],[[64657,64657],"mapped",[1610,1585]],[[64658,64658],"mapped",[1610,1586]],[[64659,64659],"mapped",[1610,1605]],[[64660,64660],"mapped",[1610,1606]],[[64661,64661],"mapped",[1610,1609]],[[64662,64662],"mapped",[1610,1610]],[[64663,64663],"mapped",[1574,1580]],[[64664,64664],"mapped",[1574,1581]],[[64665,64665],"mapped",[1574,1582]],[[64666,64666],"mapped",[1574,1605]],[[64667,64667],"mapped",[1574,1607]],[[64668,64668],"mapped",[1576,1580]],[[64669,64669],"mapped",[1576,1581]],[[64670,64670],"mapped",[1576,1582]],[[64671,64671],"mapped",[1576,1605]],[[64672,64672],"mapped",[1576,1607]],[[64673,64673],"mapped",[1578,1580]],[[64674,64674],"mapped",[1578,1581]],[[64675,64675],"mapped",[1578,1582]],[[64676,64676],"mapped",[1578,1605]],[[64677,64677],"mapped",[1578,1607]],[[64678,64678],"mapped",[1579,1605]],[[64679,64679],"mapped",[1580,1581]],[[64680,64680],"mapped",[1580,1605]],[[64681,64681],"mapped",[1581,1580]],[[64682,64682],"mapped",[1581,1605]],[[64683,64683],"mapped",[1582,1580]],[[64684,64684],"mapped",[1582,1605]],[[64685,64685],"mapped",[1587,1580]],[[64686,64686],"mapped",[1587,1581]],[[64687,64687],"mapped",[1587,1582]],[[64688,64688],"mapped",[1587,1605]],[[64689,64689],"mapped",[1589,1581]],[[64690,64690],"mapped",[1589,1582]],[[64691,64691],"mapped",[1589,1605]],[[64692,64692],"mapped",[1590,1580]],[[64693,64693],"mapped",[1590,1581]],[[64694,64694],"mapped",[1590,1582]],[[64695,64695],"mapped",[1590,1605]],[[64696,64696],"mapped",[1591,1581]],[[64697,64697],"mapped",[1592,1605]],[[64698,64698],"mapped",[1593,1580]],[[64699,64699],"mapped",[1593,1605]],[[64700,64700],"mapped",[1594,1580]],[[64701,64701],"mapped",[1594,1605]],[[64702,64702],"mapped",[1601,1580]],[[64703,64703],"mapped",[1601,1581]],[[64704,64704],"mapped",[1601,1582]],[[64705,64705],"mapped",[1601,1605]],[[64706,64706],"mapped",[1602,1581]],[[64707,64707],"mapped",[1602,1605]],[[64708,64708],"mapped",[1603,1580]],[[64709,64709],"mapped",[1603,1581]],[[64710,64710],"mapped",[1603,1582]],[[64711,64711],"mapped",[1603,1604]],[[64712,64712],"mapped",[1603,1605]],[[64713,64713],"mapped",[1604,1580]],[[64714,64714],"mapped",[1604,1581]],[[64715,64715],"mapped",[1604,1582]],[[64716,64716],"mapped",[1604,1605]],[[64717,64717],"mapped",[1604,1607]],[[64718,64718],"mapped",[1605,1580]],[[64719,64719],"mapped",[1605,1581]],[[64720,64720],"mapped",[1605,1582]],[[64721,64721],"mapped",[1605,1605]],[[64722,64722],"mapped",[1606,1580]],[[64723,64723],"mapped",[1606,1581]],[[64724,64724],"mapped",[1606,1582]],[[64725,64725],"mapped",[1606,1605]],[[64726,64726],"mapped",[1606,1607]],[[64727,64727],"mapped",[1607,1580]],[[64728,64728],"mapped",[1607,1605]],[[64729,64729],"mapped",[1607,1648]],[[64730,64730],"mapped",[1610,1580]],[[64731,64731],"mapped",[1610,1581]],[[64732,64732],"mapped",[1610,1582]],[[64733,64733],"mapped",[1610,1605]],[[64734,64734],"mapped",[1610,1607]],[[64735,64735],"mapped",[1574,1605]],[[64736,64736],"mapped",[1574,1607]],[[64737,64737],"mapped",[1576,1605]],[[64738,64738],"mapped",[1576,1607]],[[64739,64739],"mapped",[1578,1605]],[[64740,64740],"mapped",[1578,1607]],[[64741,64741],"mapped",[1579,1605]],[[64742,64742],"mapped",[1579,1607]],[[64743,64743],"mapped",[1587,1605]],[[64744,64744],"mapped",[1587,1607]],[[64745,64745],"mapped",[1588,1605]],[[64746,64746],"mapped",[1588,1607]],[[64747,64747],"mapped",[1603,1604]],[[64748,64748],"mapped",[1603,1605]],[[64749,64749],"mapped",[1604,1605]],[[64750,64750],"mapped",[1606,1605]],[[64751,64751],"mapped",[1606,1607]],[[64752,64752],"mapped",[1610,1605]],[[64753,64753],"mapped",[1610,1607]],[[64754,64754],"mapped",[1600,1614,1617]],[[64755,64755],"mapped",[1600,1615,1617]],[[64756,64756],"mapped",[1600,1616,1617]],[[64757,64757],"mapped",[1591,1609]],[[64758,64758],"mapped",[1591,1610]],[[64759,64759],"mapped",[1593,1609]],[[64760,64760],"mapped",[1593,1610]],[[64761,64761],"mapped",[1594,1609]],[[64762,64762],"mapped",[1594,1610]],[[64763,64763],"mapped",[1587,1609]],[[64764,64764],"mapped",[1587,1610]],[[64765,64765],"mapped",[1588,1609]],[[64766,64766],"mapped",[1588,1610]],[[64767,64767],"mapped",[1581,1609]],[[64768,64768],"mapped",[1581,1610]],[[64769,64769],"mapped",[1580,1609]],[[64770,64770],"mapped",[1580,1610]],[[64771,64771],"mapped",[1582,1609]],[[64772,64772],"mapped",[1582,1610]],[[64773,64773],"mapped",[1589,1609]],[[64774,64774],"mapped",[1589,1610]],[[64775,64775],"mapped",[1590,1609]],[[64776,64776],"mapped",[1590,1610]],[[64777,64777],"mapped",[1588,1580]],[[64778,64778],"mapped",[1588,1581]],[[64779,64779],"mapped",[1588,1582]],[[64780,64780],"mapped",[1588,1605]],[[64781,64781],"mapped",[1588,1585]],[[64782,64782],"mapped",[1587,1585]],[[64783,64783],"mapped",[1589,1585]],[[64784,64784],"mapped",[1590,1585]],[[64785,64785],"mapped",[1591,1609]],[[64786,64786],"mapped",[1591,1610]],[[64787,64787],"mapped",[1593,1609]],[[64788,64788],"mapped",[1593,1610]],[[64789,64789],"mapped",[1594,1609]],[[64790,64790],"mapped",[1594,1610]],[[64791,64791],"mapped",[1587,1609]],[[64792,64792],"mapped",[1587,1610]],[[64793,64793],"mapped",[1588,1609]],[[64794,64794],"mapped",[1588,1610]],[[64795,64795],"mapped",[1581,1609]],[[64796,64796],"mapped",[1581,1610]],[[64797,64797],"mapped",[1580,1609]],[[64798,64798],"mapped",[1580,1610]],[[64799,64799],"mapped",[1582,1609]],[[64800,64800],"mapped",[1582,1610]],[[64801,64801],"mapped",[1589,1609]],[[64802,64802],"mapped",[1589,1610]],[[64803,64803],"mapped",[1590,1609]],[[64804,64804],"mapped",[1590,1610]],[[64805,64805],"mapped",[1588,1580]],[[64806,64806],"mapped",[1588,1581]],[[64807,64807],"mapped",[1588,1582]],[[64808,64808],"mapped",[1588,1605]],[[64809,64809],"mapped",[1588,1585]],[[64810,64810],"mapped",[1587,1585]],[[64811,64811],"mapped",[1589,1585]],[[64812,64812],"mapped",[1590,1585]],[[64813,64813],"mapped",[1588,1580]],[[64814,64814],"mapped",[1588,1581]],[[64815,64815],"mapped",[1588,1582]],[[64816,64816],"mapped",[1588,1605]],[[64817,64817],"mapped",[1587,1607]],[[64818,64818],"mapped",[1588,1607]],[[64819,64819],"mapped",[1591,1605]],[[64820,64820],"mapped",[1587,1580]],[[64821,64821],"mapped",[1587,1581]],[[64822,64822],"mapped",[1587,1582]],[[64823,64823],"mapped",[1588,1580]],[[64824,64824],"mapped",[1588,1581]],[[64825,64825],"mapped",[1588,1582]],[[64826,64826],"mapped",[1591,1605]],[[64827,64827],"mapped",[1592,1605]],[[64828,64829],"mapped",[1575,1611]],[[64830,64831],"valid",[],"NV8"],[[64832,64847],"disallowed"],[[64848,64848],"mapped",[1578,1580,1605]],[[64849,64850],"mapped",[1578,1581,1580]],[[64851,64851],"mapped",[1578,1581,1605]],[[64852,64852],"mapped",[1578,1582,1605]],[[64853,64853],"mapped",[1578,1605,1580]],[[64854,64854],"mapped",[1578,1605,1581]],[[64855,64855],"mapped",[1578,1605,1582]],[[64856,64857],"mapped",[1580,1605,1581]],[[64858,64858],"mapped",[1581,1605,1610]],[[64859,64859],"mapped",[1581,1605,1609]],[[64860,64860],"mapped",[1587,1581,1580]],[[64861,64861],"mapped",[1587,1580,1581]],[[64862,64862],"mapped",[1587,1580,1609]],[[64863,64864],"mapped",[1587,1605,1581]],[[64865,64865],"mapped",[1587,1605,1580]],[[64866,64867],"mapped",[1587,1605,1605]],[[64868,64869],"mapped",[1589,1581,1581]],[[64870,64870],"mapped",[1589,1605,1605]],[[64871,64872],"mapped",[1588,1581,1605]],[[64873,64873],"mapped",[1588,1580,1610]],[[64874,64875],"mapped",[1588,1605,1582]],[[64876,64877],"mapped",[1588,1605,1605]],[[64878,64878],"mapped",[1590,1581,1609]],[[64879,64880],"mapped",[1590,1582,1605]],[[64881,64882],"mapped",[1591,1605,1581]],[[64883,64883],"mapped",[1591,1605,1605]],[[64884,64884],"mapped",[1591,1605,1610]],[[64885,64885],"mapped",[1593,1580,1605]],[[64886,64887],"mapped",[1593,1605,1605]],[[64888,64888],"mapped",[1593,1605,1609]],[[64889,64889],"mapped",[1594,1605,1605]],[[64890,64890],"mapped",[1594,1605,1610]],[[64891,64891],"mapped",[1594,1605,1609]],[[64892,64893],"mapped",[1601,1582,1605]],[[64894,64894],"mapped",[1602,1605,1581]],[[64895,64895],"mapped",[1602,1605,1605]],[[64896,64896],"mapped",[1604,1581,1605]],[[64897,64897],"mapped",[1604,1581,1610]],[[64898,64898],"mapped",[1604,1581,1609]],[[64899,64900],"mapped",[1604,1580,1580]],[[64901,64902],"mapped",[1604,1582,1605]],[[64903,64904],"mapped",[1604,1605,1581]],[[64905,64905],"mapped",[1605,1581,1580]],[[64906,64906],"mapped",[1605,1581,1605]],[[64907,64907],"mapped",[1605,1581,1610]],[[64908,64908],"mapped",[1605,1580,1581]],[[64909,64909],"mapped",[1605,1580,1605]],[[64910,64910],"mapped",[1605,1582,1580]],[[64911,64911],"mapped",[1605,1582,1605]],[[64912,64913],"disallowed"],[[64914,64914],"mapped",[1605,1580,1582]],[[64915,64915],"mapped",[1607,1605,1580]],[[64916,64916],"mapped",[1607,1605,1605]],[[64917,64917],"mapped",[1606,1581,1605]],[[64918,64918],"mapped",[1606,1581,1609]],[[64919,64920],"mapped",[1606,1580,1605]],[[64921,64921],"mapped",[1606,1580,1609]],[[64922,64922],"mapped",[1606,1605,1610]],[[64923,64923],"mapped",[1606,1605,1609]],[[64924,64925],"mapped",[1610,1605,1605]],[[64926,64926],"mapped",[1576,1582,1610]],[[64927,64927],"mapped",[1578,1580,1610]],[[64928,64928],"mapped",[1578,1580,1609]],[[64929,64929],"mapped",[1578,1582,1610]],[[64930,64930],"mapped",[1578,1582,1609]],[[64931,64931],"mapped",[1578,1605,1610]],[[64932,64932],"mapped",[1578,1605,1609]],[[64933,64933],"mapped",[1580,1605,1610]],[[64934,64934],"mapped",[1580,1581,1609]],[[64935,64935],"mapped",[1580,1605,1609]],[[64936,64936],"mapped",[1587,1582,1609]],[[64937,64937],"mapped",[1589,1581,1610]],[[64938,64938],"mapped",[1588,1581,1610]],[[64939,64939],"mapped",[1590,1581,1610]],[[64940,64940],"mapped",[1604,1580,1610]],[[64941,64941],"mapped",[1604,1605,1610]],[[64942,64942],"mapped",[1610,1581,1610]],[[64943,64943],"mapped",[1610,1580,1610]],[[64944,64944],"mapped",[1610,1605,1610]],[[64945,64945],"mapped",[1605,1605,1610]],[[64946,64946],"mapped",[1602,1605,1610]],[[64947,64947],"mapped",[1606,1581,1610]],[[64948,64948],"mapped",[1602,1605,1581]],[[64949,64949],"mapped",[1604,1581,1605]],[[64950,64950],"mapped",[1593,1605,1610]],[[64951,64951],"mapped",[1603,1605,1610]],[[64952,64952],"mapped",[1606,1580,1581]],[[64953,64953],"mapped",[1605,1582,1610]],[[64954,64954],"mapped",[1604,1580,1605]],[[64955,64955],"mapped",[1603,1605,1605]],[[64956,64956],"mapped",[1604,1580,1605]],[[64957,64957],"mapped",[1606,1580,1581]],[[64958,64958],"mapped",[1580,1581,1610]],[[64959,64959],"mapped",[1581,1580,1610]],[[64960,64960],"mapped",[1605,1580,1610]],[[64961,64961],"mapped",[1601,1605,1610]],[[64962,64962],"mapped",[1576,1581,1610]],[[64963,64963],"mapped",[1603,1605,1605]],[[64964,64964],"mapped",[1593,1580,1605]],[[64965,64965],"mapped",[1589,1605,1605]],[[64966,64966],"mapped",[1587,1582,1610]],[[64967,64967],"mapped",[1606,1580,1610]],[[64968,64975],"disallowed"],[[64976,65007],"disallowed"],[[65008,65008],"mapped",[1589,1604,1746]],[[65009,65009],"mapped",[1602,1604,1746]],[[65010,65010],"mapped",[1575,1604,1604,1607]],[[65011,65011],"mapped",[1575,1603,1576,1585]],[[65012,65012],"mapped",[1605,1581,1605,1583]],[[65013,65013],"mapped",[1589,1604,1593,1605]],[[65014,65014],"mapped",[1585,1587,1608,1604]],[[65015,65015],"mapped",[1593,1604,1610,1607]],[[65016,65016],"mapped",[1608,1587,1604,1605]],[[65017,65017],"mapped",[1589,1604,1609]],[[65018,65018],"disallowed_STD3_mapped",[1589,1604,1609,32,1575,1604,1604,1607,32,1593,1604,1610,1607,32,1608,1587,1604,1605]],[[65019,65019],"disallowed_STD3_mapped",[1580,1604,32,1580,1604,1575,1604,1607]],[[65020,65020],"mapped",[1585,1740,1575,1604]],[[65021,65021],"valid",[],"NV8"],[[65022,65023],"disallowed"],[[65024,65039],"ignored"],[[65040,65040],"disallowed_STD3_mapped",[44]],[[65041,65041],"mapped",[12289]],[[65042,65042],"disallowed"],[[65043,65043],"disallowed_STD3_mapped",[58]],[[65044,65044],"disallowed_STD3_mapped",[59]],[[65045,65045],"disallowed_STD3_mapped",[33]],[[65046,65046],"disallowed_STD3_mapped",[63]],[[65047,65047],"mapped",[12310]],[[65048,65048],"mapped",[12311]],[[65049,65049],"disallowed"],[[65050,65055],"disallowed"],[[65056,65059],"valid"],[[65060,65062],"valid"],[[65063,65069],"valid"],[[65070,65071],"valid"],[[65072,65072],"disallowed"],[[65073,65073],"mapped",[8212]],[[65074,65074],"mapped",[8211]],[[65075,65076],"disallowed_STD3_mapped",[95]],[[65077,65077],"disallowed_STD3_mapped",[40]],[[65078,65078],"disallowed_STD3_mapped",[41]],[[65079,65079],"disallowed_STD3_mapped",[123]],[[65080,65080],"disallowed_STD3_mapped",[125]],[[65081,65081],"mapped",[12308]],[[65082,65082],"mapped",[12309]],[[65083,65083],"mapped",[12304]],[[65084,65084],"mapped",[12305]],[[65085,65085],"mapped",[12298]],[[65086,65086],"mapped",[12299]],[[65087,65087],"mapped",[12296]],[[65088,65088],"mapped",[12297]],[[65089,65089],"mapped",[12300]],[[65090,65090],"mapped",[12301]],[[65091,65091],"mapped",[12302]],[[65092,65092],"mapped",[12303]],[[65093,65094],"valid",[],"NV8"],[[65095,65095],"disallowed_STD3_mapped",[91]],[[65096,65096],"disallowed_STD3_mapped",[93]],[[65097,65100],"disallowed_STD3_mapped",[32,773]],[[65101,65103],"disallowed_STD3_mapped",[95]],[[65104,65104],"disallowed_STD3_mapped",[44]],[[65105,65105],"mapped",[12289]],[[65106,65106],"disallowed"],[[65107,65107],"disallowed"],[[65108,65108],"disallowed_STD3_mapped",[59]],[[65109,65109],"disallowed_STD3_mapped",[58]],[[65110,65110],"disallowed_STD3_mapped",[63]],[[65111,65111],"disallowed_STD3_mapped",[33]],[[65112,65112],"mapped",[8212]],[[65113,65113],"disallowed_STD3_mapped",[40]],[[65114,65114],"disallowed_STD3_mapped",[41]],[[65115,65115],"disallowed_STD3_mapped",[123]],[[65116,65116],"disallowed_STD3_mapped",[125]],[[65117,65117],"mapped",[12308]],[[65118,65118],"mapped",[12309]],[[65119,65119],"disallowed_STD3_mapped",[35]],[[65120,65120],"disallowed_STD3_mapped",[38]],[[65121,65121],"disallowed_STD3_mapped",[42]],[[65122,65122],"disallowed_STD3_mapped",[43]],[[65123,65123],"mapped",[45]],[[65124,65124],"disallowed_STD3_mapped",[60]],[[65125,65125],"disallowed_STD3_mapped",[62]],[[65126,65126],"disallowed_STD3_mapped",[61]],[[65127,65127],"disallowed"],[[65128,65128],"disallowed_STD3_mapped",[92]],[[65129,65129],"disallowed_STD3_mapped",[36]],[[65130,65130],"disallowed_STD3_mapped",[37]],[[65131,65131],"disallowed_STD3_mapped",[64]],[[65132,65135],"disallowed"],[[65136,65136],"disallowed_STD3_mapped",[32,1611]],[[65137,65137],"mapped",[1600,1611]],[[65138,65138],"disallowed_STD3_mapped",[32,1612]],[[65139,65139],"valid"],[[65140,65140],"disallowed_STD3_mapped",[32,1613]],[[65141,65141],"disallowed"],[[65142,65142],"disallowed_STD3_mapped",[32,1614]],[[65143,65143],"mapped",[1600,1614]],[[65144,65144],"disallowed_STD3_mapped",[32,1615]],[[65145,65145],"mapped",[1600,1615]],[[65146,65146],"disallowed_STD3_mapped",[32,1616]],[[65147,65147],"mapped",[1600,1616]],[[65148,65148],"disallowed_STD3_mapped",[32,1617]],[[65149,65149],"mapped",[1600,1617]],[[65150,65150],"disallowed_STD3_mapped",[32,1618]],[[65151,65151],"mapped",[1600,1618]],[[65152,65152],"mapped",[1569]],[[65153,65154],"mapped",[1570]],[[65155,65156],"mapped",[1571]],[[65157,65158],"mapped",[1572]],[[65159,65160],"mapped",[1573]],[[65161,65164],"mapped",[1574]],[[65165,65166],"mapped",[1575]],[[65167,65170],"mapped",[1576]],[[65171,65172],"mapped",[1577]],[[65173,65176],"mapped",[1578]],[[65177,65180],"mapped",[1579]],[[65181,65184],"mapped",[1580]],[[65185,65188],"mapped",[1581]],[[65189,65192],"mapped",[1582]],[[65193,65194],"mapped",[1583]],[[65195,65196],"mapped",[1584]],[[65197,65198],"mapped",[1585]],[[65199,65200],"mapped",[1586]],[[65201,65204],"mapped",[1587]],[[65205,65208],"mapped",[1588]],[[65209,65212],"mapped",[1589]],[[65213,65216],"mapped",[1590]],[[65217,65220],"mapped",[1591]],[[65221,65224],"mapped",[1592]],[[65225,65228],"mapped",[1593]],[[65229,65232],"mapped",[1594]],[[65233,65236],"mapped",[1601]],[[65237,65240],"mapped",[1602]],[[65241,65244],"mapped",[1603]],[[65245,65248],"mapped",[1604]],[[65249,65252],"mapped",[1605]],[[65253,65256],"mapped",[1606]],[[65257,65260],"mapped",[1607]],[[65261,65262],"mapped",[1608]],[[65263,65264],"mapped",[1609]],[[65265,65268],"mapped",[1610]],[[65269,65270],"mapped",[1604,1570]],[[65271,65272],"mapped",[1604,1571]],[[65273,65274],"mapped",[1604,1573]],[[65275,65276],"mapped",[1604,1575]],[[65277,65278],"disallowed"],[[65279,65279],"ignored"],[[65280,65280],"disallowed"],[[65281,65281],"disallowed_STD3_mapped",[33]],[[65282,65282],"disallowed_STD3_mapped",[34]],[[65283,65283],"disallowed_STD3_mapped",[35]],[[65284,65284],"disallowed_STD3_mapped",[36]],[[65285,65285],"disallowed_STD3_mapped",[37]],[[65286,65286],"disallowed_STD3_mapped",[38]],[[65287,65287],"disallowed_STD3_mapped",[39]],[[65288,65288],"disallowed_STD3_mapped",[40]],[[65289,65289],"disallowed_STD3_mapped",[41]],[[65290,65290],"disallowed_STD3_mapped",[42]],[[65291,65291],"disallowed_STD3_mapped",[43]],[[65292,65292],"disallowed_STD3_mapped",[44]],[[65293,65293],"mapped",[45]],[[65294,65294],"mapped",[46]],[[65295,65295],"disallowed_STD3_mapped",[47]],[[65296,65296],"mapped",[48]],[[65297,65297],"mapped",[49]],[[65298,65298],"mapped",[50]],[[65299,65299],"mapped",[51]],[[65300,65300],"mapped",[52]],[[65301,65301],"mapped",[53]],[[65302,65302],"mapped",[54]],[[65303,65303],"mapped",[55]],[[65304,65304],"mapped",[56]],[[65305,65305],"mapped",[57]],[[65306,65306],"disallowed_STD3_mapped",[58]],[[65307,65307],"disallowed_STD3_mapped",[59]],[[65308,65308],"disallowed_STD3_mapped",[60]],[[65309,65309],"disallowed_STD3_mapped",[61]],[[65310,65310],"disallowed_STD3_mapped",[62]],[[65311,65311],"disallowed_STD3_mapped",[63]],[[65312,65312],"disallowed_STD3_mapped",[64]],[[65313,65313],"mapped",[97]],[[65314,65314],"mapped",[98]],[[65315,65315],"mapped",[99]],[[65316,65316],"mapped",[100]],[[65317,65317],"mapped",[101]],[[65318,65318],"mapped",[102]],[[65319,65319],"mapped",[103]],[[65320,65320],"mapped",[104]],[[65321,65321],"mapped",[105]],[[65322,65322],"mapped",[106]],[[65323,65323],"mapped",[107]],[[65324,65324],"mapped",[108]],[[65325,65325],"mapped",[109]],[[65326,65326],"mapped",[110]],[[65327,65327],"mapped",[111]],[[65328,65328],"mapped",[112]],[[65329,65329],"mapped",[113]],[[65330,65330],"mapped",[114]],[[65331,65331],"mapped",[115]],[[65332,65332],"mapped",[116]],[[65333,65333],"mapped",[117]],[[65334,65334],"mapped",[118]],[[65335,65335],"mapped",[119]],[[65336,65336],"mapped",[120]],[[65337,65337],"mapped",[121]],[[65338,65338],"mapped",[122]],[[65339,65339],"disallowed_STD3_mapped",[91]],[[65340,65340],"disallowed_STD3_mapped",[92]],[[65341,65341],"disallowed_STD3_mapped",[93]],[[65342,65342],"disallowed_STD3_mapped",[94]],[[65343,65343],"disallowed_STD3_mapped",[95]],[[65344,65344],"disallowed_STD3_mapped",[96]],[[65345,65345],"mapped",[97]],[[65346,65346],"mapped",[98]],[[65347,65347],"mapped",[99]],[[65348,65348],"mapped",[100]],[[65349,65349],"mapped",[101]],[[65350,65350],"mapped",[102]],[[65351,65351],"mapped",[103]],[[65352,65352],"mapped",[104]],[[65353,65353],"mapped",[105]],[[65354,65354],"mapped",[106]],[[65355,65355],"mapped",[107]],[[65356,65356],"mapped",[108]],[[65357,65357],"mapped",[109]],[[65358,65358],"mapped",[110]],[[65359,65359],"mapped",[111]],[[65360,65360],"mapped",[112]],[[65361,65361],"mapped",[113]],[[65362,65362],"mapped",[114]],[[65363,65363],"mapped",[115]],[[65364,65364],"mapped",[116]],[[65365,65365],"mapped",[117]],[[65366,65366],"mapped",[118]],[[65367,65367],"mapped",[119]],[[65368,65368],"mapped",[120]],[[65369,65369],"mapped",[121]],[[65370,65370],"mapped",[122]],[[65371,65371],"disallowed_STD3_mapped",[123]],[[65372,65372],"disallowed_STD3_mapped",[124]],[[65373,65373],"disallowed_STD3_mapped",[125]],[[65374,65374],"disallowed_STD3_mapped",[126]],[[65375,65375],"mapped",[10629]],[[65376,65376],"mapped",[10630]],[[65377,65377],"mapped",[46]],[[65378,65378],"mapped",[12300]],[[65379,65379],"mapped",[12301]],[[65380,65380],"mapped",[12289]],[[65381,65381],"mapped",[12539]],[[65382,65382],"mapped",[12530]],[[65383,65383],"mapped",[12449]],[[65384,65384],"mapped",[12451]],[[65385,65385],"mapped",[12453]],[[65386,65386],"mapped",[12455]],[[65387,65387],"mapped",[12457]],[[65388,65388],"mapped",[12515]],[[65389,65389],"mapped",[12517]],[[65390,65390],"mapped",[12519]],[[65391,65391],"mapped",[12483]],[[65392,65392],"mapped",[12540]],[[65393,65393],"mapped",[12450]],[[65394,65394],"mapped",[12452]],[[65395,65395],"mapped",[12454]],[[65396,65396],"mapped",[12456]],[[65397,65397],"mapped",[12458]],[[65398,65398],"mapped",[12459]],[[65399,65399],"mapped",[12461]],[[65400,65400],"mapped",[12463]],[[65401,65401],"mapped",[12465]],[[65402,65402],"mapped",[12467]],[[65403,65403],"mapped",[12469]],[[65404,65404],"mapped",[12471]],[[65405,65405],"mapped",[12473]],[[65406,65406],"mapped",[12475]],[[65407,65407],"mapped",[12477]],[[65408,65408],"mapped",[12479]],[[65409,65409],"mapped",[12481]],[[65410,65410],"mapped",[12484]],[[65411,65411],"mapped",[12486]],[[65412,65412],"mapped",[12488]],[[65413,65413],"mapped",[12490]],[[65414,65414],"mapped",[12491]],[[65415,65415],"mapped",[12492]],[[65416,65416],"mapped",[12493]],[[65417,65417],"mapped",[12494]],[[65418,65418],"mapped",[12495]],[[65419,65419],"mapped",[12498]],[[65420,65420],"mapped",[12501]],[[65421,65421],"mapped",[12504]],[[65422,65422],"mapped",[12507]],[[65423,65423],"mapped",[12510]],[[65424,65424],"mapped",[12511]],[[65425,65425],"mapped",[12512]],[[65426,65426],"mapped",[12513]],[[65427,65427],"mapped",[12514]],[[65428,65428],"mapped",[12516]],[[65429,65429],"mapped",[12518]],[[65430,65430],"mapped",[12520]],[[65431,65431],"mapped",[12521]],[[65432,65432],"mapped",[12522]],[[65433,65433],"mapped",[12523]],[[65434,65434],"mapped",[12524]],[[65435,65435],"mapped",[12525]],[[65436,65436],"mapped",[12527]],[[65437,65437],"mapped",[12531]],[[65438,65438],"mapped",[12441]],[[65439,65439],"mapped",[12442]],[[65440,65440],"disallowed"],[[65441,65441],"mapped",[4352]],[[65442,65442],"mapped",[4353]],[[65443,65443],"mapped",[4522]],[[65444,65444],"mapped",[4354]],[[65445,65445],"mapped",[4524]],[[65446,65446],"mapped",[4525]],[[65447,65447],"mapped",[4355]],[[65448,65448],"mapped",[4356]],[[65449,65449],"mapped",[4357]],[[65450,65450],"mapped",[4528]],[[65451,65451],"mapped",[4529]],[[65452,65452],"mapped",[4530]],[[65453,65453],"mapped",[4531]],[[65454,65454],"mapped",[4532]],[[65455,65455],"mapped",[4533]],[[65456,65456],"mapped",[4378]],[[65457,65457],"mapped",[4358]],[[65458,65458],"mapped",[4359]],[[65459,65459],"mapped",[4360]],[[65460,65460],"mapped",[4385]],[[65461,65461],"mapped",[4361]],[[65462,65462],"mapped",[4362]],[[65463,65463],"mapped",[4363]],[[65464,65464],"mapped",[4364]],[[65465,65465],"mapped",[4365]],[[65466,65466],"mapped",[4366]],[[65467,65467],"mapped",[4367]],[[65468,65468],"mapped",[4368]],[[65469,65469],"mapped",[4369]],[[65470,65470],"mapped",[4370]],[[65471,65473],"disallowed"],[[65474,65474],"mapped",[4449]],[[65475,65475],"mapped",[4450]],[[65476,65476],"mapped",[4451]],[[65477,65477],"mapped",[4452]],[[65478,65478],"mapped",[4453]],[[65479,65479],"mapped",[4454]],[[65480,65481],"disallowed"],[[65482,65482],"mapped",[4455]],[[65483,65483],"mapped",[4456]],[[65484,65484],"mapped",[4457]],[[65485,65485],"mapped",[4458]],[[65486,65486],"mapped",[4459]],[[65487,65487],"mapped",[4460]],[[65488,65489],"disallowed"],[[65490,65490],"mapped",[4461]],[[65491,65491],"mapped",[4462]],[[65492,65492],"mapped",[4463]],[[65493,65493],"mapped",[4464]],[[65494,65494],"mapped",[4465]],[[65495,65495],"mapped",[4466]],[[65496,65497],"disallowed"],[[65498,65498],"mapped",[4467]],[[65499,65499],"mapped",[4468]],[[65500,65500],"mapped",[4469]],[[65501,65503],"disallowed"],[[65504,65504],"mapped",[162]],[[65505,65505],"mapped",[163]],[[65506,65506],"mapped",[172]],[[65507,65507],"disallowed_STD3_mapped",[32,772]],[[65508,65508],"mapped",[166]],[[65509,65509],"mapped",[165]],[[65510,65510],"mapped",[8361]],[[65511,65511],"disallowed"],[[65512,65512],"mapped",[9474]],[[65513,65513],"mapped",[8592]],[[65514,65514],"mapped",[8593]],[[65515,65515],"mapped",[8594]],[[65516,65516],"mapped",[8595]],[[65517,65517],"mapped",[9632]],[[65518,65518],"mapped",[9675]],[[65519,65528],"disallowed"],[[65529,65531],"disallowed"],[[65532,65532],"disallowed"],[[65533,65533],"disallowed"],[[65534,65535],"disallowed"],[[65536,65547],"valid"],[[65548,65548],"disallowed"],[[65549,65574],"valid"],[[65575,65575],"disallowed"],[[65576,65594],"valid"],[[65595,65595],"disallowed"],[[65596,65597],"valid"],[[65598,65598],"disallowed"],[[65599,65613],"valid"],[[65614,65615],"disallowed"],[[65616,65629],"valid"],[[65630,65663],"disallowed"],[[65664,65786],"valid"],[[65787,65791],"disallowed"],[[65792,65794],"valid",[],"NV8"],[[65795,65798],"disallowed"],[[65799,65843],"valid",[],"NV8"],[[65844,65846],"disallowed"],[[65847,65855],"valid",[],"NV8"],[[65856,65930],"valid",[],"NV8"],[[65931,65932],"valid",[],"NV8"],[[65933,65935],"disallowed"],[[65936,65947],"valid",[],"NV8"],[[65948,65951],"disallowed"],[[65952,65952],"valid",[],"NV8"],[[65953,65999],"disallowed"],[[66000,66044],"valid",[],"NV8"],[[66045,66045],"valid"],[[66046,66175],"disallowed"],[[66176,66204],"valid"],[[66205,66207],"disallowed"],[[66208,66256],"valid"],[[66257,66271],"disallowed"],[[66272,66272],"valid"],[[66273,66299],"valid",[],"NV8"],[[66300,66303],"disallowed"],[[66304,66334],"valid"],[[66335,66335],"valid"],[[66336,66339],"valid",[],"NV8"],[[66340,66351],"disallowed"],[[66352,66368],"valid"],[[66369,66369],"valid",[],"NV8"],[[66370,66377],"valid"],[[66378,66378],"valid",[],"NV8"],[[66379,66383],"disallowed"],[[66384,66426],"valid"],[[66427,66431],"disallowed"],[[66432,66461],"valid"],[[66462,66462],"disallowed"],[[66463,66463],"valid",[],"NV8"],[[66464,66499],"valid"],[[66500,66503],"disallowed"],[[66504,66511],"valid"],[[66512,66517],"valid",[],"NV8"],[[66518,66559],"disallowed"],[[66560,66560],"mapped",[66600]],[[66561,66561],"mapped",[66601]],[[66562,66562],"mapped",[66602]],[[66563,66563],"mapped",[66603]],[[66564,66564],"mapped",[66604]],[[66565,66565],"mapped",[66605]],[[66566,66566],"mapped",[66606]],[[66567,66567],"mapped",[66607]],[[66568,66568],"mapped",[66608]],[[66569,66569],"mapped",[66609]],[[66570,66570],"mapped",[66610]],[[66571,66571],"mapped",[66611]],[[66572,66572],"mapped",[66612]],[[66573,66573],"mapped",[66613]],[[66574,66574],"mapped",[66614]],[[66575,66575],"mapped",[66615]],[[66576,66576],"mapped",[66616]],[[66577,66577],"mapped",[66617]],[[66578,66578],"mapped",[66618]],[[66579,66579],"mapped",[66619]],[[66580,66580],"mapped",[66620]],[[66581,66581],"mapped",[66621]],[[66582,66582],"mapped",[66622]],[[66583,66583],"mapped",[66623]],[[66584,66584],"mapped",[66624]],[[66585,66585],"mapped",[66625]],[[66586,66586],"mapped",[66626]],[[66587,66587],"mapped",[66627]],[[66588,66588],"mapped",[66628]],[[66589,66589],"mapped",[66629]],[[66590,66590],"mapped",[66630]],[[66591,66591],"mapped",[66631]],[[66592,66592],"mapped",[66632]],[[66593,66593],"mapped",[66633]],[[66594,66594],"mapped",[66634]],[[66595,66595],"mapped",[66635]],[[66596,66596],"mapped",[66636]],[[66597,66597],"mapped",[66637]],[[66598,66598],"mapped",[66638]],[[66599,66599],"mapped",[66639]],[[66600,66637],"valid"],[[66638,66717],"valid"],[[66718,66719],"disallowed"],[[66720,66729],"valid"],[[66730,66815],"disallowed"],[[66816,66855],"valid"],[[66856,66863],"disallowed"],[[66864,66915],"valid"],[[66916,66926],"disallowed"],[[66927,66927],"valid",[],"NV8"],[[66928,67071],"disallowed"],[[67072,67382],"valid"],[[67383,67391],"disallowed"],[[67392,67413],"valid"],[[67414,67423],"disallowed"],[[67424,67431],"valid"],[[67432,67583],"disallowed"],[[67584,67589],"valid"],[[67590,67591],"disallowed"],[[67592,67592],"valid"],[[67593,67593],"disallowed"],[[67594,67637],"valid"],[[67638,67638],"disallowed"],[[67639,67640],"valid"],[[67641,67643],"disallowed"],[[67644,67644],"valid"],[[67645,67646],"disallowed"],[[67647,67647],"valid"],[[67648,67669],"valid"],[[67670,67670],"disallowed"],[[67671,67679],"valid",[],"NV8"],[[67680,67702],"valid"],[[67703,67711],"valid",[],"NV8"],[[67712,67742],"valid"],[[67743,67750],"disallowed"],[[67751,67759],"valid",[],"NV8"],[[67760,67807],"disallowed"],[[67808,67826],"valid"],[[67827,67827],"disallowed"],[[67828,67829],"valid"],[[67830,67834],"disallowed"],[[67835,67839],"valid",[],"NV8"],[[67840,67861],"valid"],[[67862,67865],"valid",[],"NV8"],[[67866,67867],"valid",[],"NV8"],[[67868,67870],"disallowed"],[[67871,67871],"valid",[],"NV8"],[[67872,67897],"valid"],[[67898,67902],"disallowed"],[[67903,67903],"valid",[],"NV8"],[[67904,67967],"disallowed"],[[67968,68023],"valid"],[[68024,68027],"disallowed"],[[68028,68029],"valid",[],"NV8"],[[68030,68031],"valid"],[[68032,68047],"valid",[],"NV8"],[[68048,68049],"disallowed"],[[68050,68095],"valid",[],"NV8"],[[68096,68099],"valid"],[[68100,68100],"disallowed"],[[68101,68102],"valid"],[[68103,68107],"disallowed"],[[68108,68115],"valid"],[[68116,68116],"disallowed"],[[68117,68119],"valid"],[[68120,68120],"disallowed"],[[68121,68147],"valid"],[[68148,68151],"disallowed"],[[68152,68154],"valid"],[[68155,68158],"disallowed"],[[68159,68159],"valid"],[[68160,68167],"valid",[],"NV8"],[[68168,68175],"disallowed"],[[68176,68184],"valid",[],"NV8"],[[68185,68191],"disallowed"],[[68192,68220],"valid"],[[68221,68223],"valid",[],"NV8"],[[68224,68252],"valid"],[[68253,68255],"valid",[],"NV8"],[[68256,68287],"disallowed"],[[68288,68295],"valid"],[[68296,68296],"valid",[],"NV8"],[[68297,68326],"valid"],[[68327,68330],"disallowed"],[[68331,68342],"valid",[],"NV8"],[[68343,68351],"disallowed"],[[68352,68405],"valid"],[[68406,68408],"disallowed"],[[68409,68415],"valid",[],"NV8"],[[68416,68437],"valid"],[[68438,68439],"disallowed"],[[68440,68447],"valid",[],"NV8"],[[68448,68466],"valid"],[[68467,68471],"disallowed"],[[68472,68479],"valid",[],"NV8"],[[68480,68497],"valid"],[[68498,68504],"disallowed"],[[68505,68508],"valid",[],"NV8"],[[68509,68520],"disallowed"],[[68521,68527],"valid",[],"NV8"],[[68528,68607],"disallowed"],[[68608,68680],"valid"],[[68681,68735],"disallowed"],[[68736,68736],"mapped",[68800]],[[68737,68737],"mapped",[68801]],[[68738,68738],"mapped",[68802]],[[68739,68739],"mapped",[68803]],[[68740,68740],"mapped",[68804]],[[68741,68741],"mapped",[68805]],[[68742,68742],"mapped",[68806]],[[68743,68743],"mapped",[68807]],[[68744,68744],"mapped",[68808]],[[68745,68745],"mapped",[68809]],[[68746,68746],"mapped",[68810]],[[68747,68747],"mapped",[68811]],[[68748,68748],"mapped",[68812]],[[68749,68749],"mapped",[68813]],[[68750,68750],"mapped",[68814]],[[68751,68751],"mapped",[68815]],[[68752,68752],"mapped",[68816]],[[68753,68753],"mapped",[68817]],[[68754,68754],"mapped",[68818]],[[68755,68755],"mapped",[68819]],[[68756,68756],"mapped",[68820]],[[68757,68757],"mapped",[68821]],[[68758,68758],"mapped",[68822]],[[68759,68759],"mapped",[68823]],[[68760,68760],"mapped",[68824]],[[68761,68761],"mapped",[68825]],[[68762,68762],"mapped",[68826]],[[68763,68763],"mapped",[68827]],[[68764,68764],"mapped",[68828]],[[68765,68765],"mapped",[68829]],[[68766,68766],"mapped",[68830]],[[68767,68767],"mapped",[68831]],[[68768,68768],"mapped",[68832]],[[68769,68769],"mapped",[68833]],[[68770,68770],"mapped",[68834]],[[68771,68771],"mapped",[68835]],[[68772,68772],"mapped",[68836]],[[68773,68773],"mapped",[68837]],[[68774,68774],"mapped",[68838]],[[68775,68775],"mapped",[68839]],[[68776,68776],"mapped",[68840]],[[68777,68777],"mapped",[68841]],[[68778,68778],"mapped",[68842]],[[68779,68779],"mapped",[68843]],[[68780,68780],"mapped",[68844]],[[68781,68781],"mapped",[68845]],[[68782,68782],"mapped",[68846]],[[68783,68783],"mapped",[68847]],[[68784,68784],"mapped",[68848]],[[68785,68785],"mapped",[68849]],[[68786,68786],"mapped",[68850]],[[68787,68799],"disallowed"],[[68800,68850],"valid"],[[68851,68857],"disallowed"],[[68858,68863],"valid",[],"NV8"],[[68864,69215],"disallowed"],[[69216,69246],"valid",[],"NV8"],[[69247,69631],"disallowed"],[[69632,69702],"valid"],[[69703,69709],"valid",[],"NV8"],[[69710,69713],"disallowed"],[[69714,69733],"valid",[],"NV8"],[[69734,69743],"valid"],[[69744,69758],"disallowed"],[[69759,69759],"valid"],[[69760,69818],"valid"],[[69819,69820],"valid",[],"NV8"],[[69821,69821],"disallowed"],[[69822,69825],"valid",[],"NV8"],[[69826,69839],"disallowed"],[[69840,69864],"valid"],[[69865,69871],"disallowed"],[[69872,69881],"valid"],[[69882,69887],"disallowed"],[[69888,69940],"valid"],[[69941,69941],"disallowed"],[[69942,69951],"valid"],[[69952,69955],"valid",[],"NV8"],[[69956,69967],"disallowed"],[[69968,70003],"valid"],[[70004,70005],"valid",[],"NV8"],[[70006,70006],"valid"],[[70007,70015],"disallowed"],[[70016,70084],"valid"],[[70085,70088],"valid",[],"NV8"],[[70089,70089],"valid",[],"NV8"],[[70090,70092],"valid"],[[70093,70093],"valid",[],"NV8"],[[70094,70095],"disallowed"],[[70096,70105],"valid"],[[70106,70106],"valid"],[[70107,70107],"valid",[],"NV8"],[[70108,70108],"valid"],[[70109,70111],"valid",[],"NV8"],[[70112,70112],"disallowed"],[[70113,70132],"valid",[],"NV8"],[[70133,70143],"disallowed"],[[70144,70161],"valid"],[[70162,70162],"disallowed"],[[70163,70199],"valid"],[[70200,70205],"valid",[],"NV8"],[[70206,70271],"disallowed"],[[70272,70278],"valid"],[[70279,70279],"disallowed"],[[70280,70280],"valid"],[[70281,70281],"disallowed"],[[70282,70285],"valid"],[[70286,70286],"disallowed"],[[70287,70301],"valid"],[[70302,70302],"disallowed"],[[70303,70312],"valid"],[[70313,70313],"valid",[],"NV8"],[[70314,70319],"disallowed"],[[70320,70378],"valid"],[[70379,70383],"disallowed"],[[70384,70393],"valid"],[[70394,70399],"disallowed"],[[70400,70400],"valid"],[[70401,70403],"valid"],[[70404,70404],"disallowed"],[[70405,70412],"valid"],[[70413,70414],"disallowed"],[[70415,70416],"valid"],[[70417,70418],"disallowed"],[[70419,70440],"valid"],[[70441,70441],"disallowed"],[[70442,70448],"valid"],[[70449,70449],"disallowed"],[[70450,70451],"valid"],[[70452,70452],"disallowed"],[[70453,70457],"valid"],[[70458,70459],"disallowed"],[[70460,70468],"valid"],[[70469,70470],"disallowed"],[[70471,70472],"valid"],[[70473,70474],"disallowed"],[[70475,70477],"valid"],[[70478,70479],"disallowed"],[[70480,70480],"valid"],[[70481,70486],"disallowed"],[[70487,70487],"valid"],[[70488,70492],"disallowed"],[[70493,70499],"valid"],[[70500,70501],"disallowed"],[[70502,70508],"valid"],[[70509,70511],"disallowed"],[[70512,70516],"valid"],[[70517,70783],"disallowed"],[[70784,70853],"valid"],[[70854,70854],"valid",[],"NV8"],[[70855,70855],"valid"],[[70856,70863],"disallowed"],[[70864,70873],"valid"],[[70874,71039],"disallowed"],[[71040,71093],"valid"],[[71094,71095],"disallowed"],[[71096,71104],"valid"],[[71105,71113],"valid",[],"NV8"],[[71114,71127],"valid",[],"NV8"],[[71128,71133],"valid"],[[71134,71167],"disallowed"],[[71168,71232],"valid"],[[71233,71235],"valid",[],"NV8"],[[71236,71236],"valid"],[[71237,71247],"disallowed"],[[71248,71257],"valid"],[[71258,71295],"disallowed"],[[71296,71351],"valid"],[[71352,71359],"disallowed"],[[71360,71369],"valid"],[[71370,71423],"disallowed"],[[71424,71449],"valid"],[[71450,71452],"disallowed"],[[71453,71467],"valid"],[[71468,71471],"disallowed"],[[71472,71481],"valid"],[[71482,71487],"valid",[],"NV8"],[[71488,71839],"disallowed"],[[71840,71840],"mapped",[71872]],[[71841,71841],"mapped",[71873]],[[71842,71842],"mapped",[71874]],[[71843,71843],"mapped",[71875]],[[71844,71844],"mapped",[71876]],[[71845,71845],"mapped",[71877]],[[71846,71846],"mapped",[71878]],[[71847,71847],"mapped",[71879]],[[71848,71848],"mapped",[71880]],[[71849,71849],"mapped",[71881]],[[71850,71850],"mapped",[71882]],[[71851,71851],"mapped",[71883]],[[71852,71852],"mapped",[71884]],[[71853,71853],"mapped",[71885]],[[71854,71854],"mapped",[71886]],[[71855,71855],"mapped",[71887]],[[71856,71856],"mapped",[71888]],[[71857,71857],"mapped",[71889]],[[71858,71858],"mapped",[71890]],[[71859,71859],"mapped",[71891]],[[71860,71860],"mapped",[71892]],[[71861,71861],"mapped",[71893]],[[71862,71862],"mapped",[71894]],[[71863,71863],"mapped",[71895]],[[71864,71864],"mapped",[71896]],[[71865,71865],"mapped",[71897]],[[71866,71866],"mapped",[71898]],[[71867,71867],"mapped",[71899]],[[71868,71868],"mapped",[71900]],[[71869,71869],"mapped",[71901]],[[71870,71870],"mapped",[71902]],[[71871,71871],"mapped",[71903]],[[71872,71913],"valid"],[[71914,71922],"valid",[],"NV8"],[[71923,71934],"disallowed"],[[71935,71935],"valid"],[[71936,72383],"disallowed"],[[72384,72440],"valid"],[[72441,73727],"disallowed"],[[73728,74606],"valid"],[[74607,74648],"valid"],[[74649,74649],"valid"],[[74650,74751],"disallowed"],[[74752,74850],"valid",[],"NV8"],[[74851,74862],"valid",[],"NV8"],[[74863,74863],"disallowed"],[[74864,74867],"valid",[],"NV8"],[[74868,74868],"valid",[],"NV8"],[[74869,74879],"disallowed"],[[74880,75075],"valid"],[[75076,77823],"disallowed"],[[77824,78894],"valid"],[[78895,82943],"disallowed"],[[82944,83526],"valid"],[[83527,92159],"disallowed"],[[92160,92728],"valid"],[[92729,92735],"disallowed"],[[92736,92766],"valid"],[[92767,92767],"disallowed"],[[92768,92777],"valid"],[[92778,92781],"disallowed"],[[92782,92783],"valid",[],"NV8"],[[92784,92879],"disallowed"],[[92880,92909],"valid"],[[92910,92911],"disallowed"],[[92912,92916],"valid"],[[92917,92917],"valid",[],"NV8"],[[92918,92927],"disallowed"],[[92928,92982],"valid"],[[92983,92991],"valid",[],"NV8"],[[92992,92995],"valid"],[[92996,92997],"valid",[],"NV8"],[[92998,93007],"disallowed"],[[93008,93017],"valid"],[[93018,93018],"disallowed"],[[93019,93025],"valid",[],"NV8"],[[93026,93026],"disallowed"],[[93027,93047],"valid"],[[93048,93052],"disallowed"],[[93053,93071],"valid"],[[93072,93951],"disallowed"],[[93952,94020],"valid"],[[94021,94031],"disallowed"],[[94032,94078],"valid"],[[94079,94094],"disallowed"],[[94095,94111],"valid"],[[94112,110591],"disallowed"],[[110592,110593],"valid"],[[110594,113663],"disallowed"],[[113664,113770],"valid"],[[113771,113775],"disallowed"],[[113776,113788],"valid"],[[113789,113791],"disallowed"],[[113792,113800],"valid"],[[113801,113807],"disallowed"],[[113808,113817],"valid"],[[113818,113819],"disallowed"],[[113820,113820],"valid",[],"NV8"],[[113821,113822],"valid"],[[113823,113823],"valid",[],"NV8"],[[113824,113827],"ignored"],[[113828,118783],"disallowed"],[[118784,119029],"valid",[],"NV8"],[[119030,119039],"disallowed"],[[119040,119078],"valid",[],"NV8"],[[119079,119080],"disallowed"],[[119081,119081],"valid",[],"NV8"],[[119082,119133],"valid",[],"NV8"],[[119134,119134],"mapped",[119127,119141]],[[119135,119135],"mapped",[119128,119141]],[[119136,119136],"mapped",[119128,119141,119150]],[[119137,119137],"mapped",[119128,119141,119151]],[[119138,119138],"mapped",[119128,119141,119152]],[[119139,119139],"mapped",[119128,119141,119153]],[[119140,119140],"mapped",[119128,119141,119154]],[[119141,119154],"valid",[],"NV8"],[[119155,119162],"disallowed"],[[119163,119226],"valid",[],"NV8"],[[119227,119227],"mapped",[119225,119141]],[[119228,119228],"mapped",[119226,119141]],[[119229,119229],"mapped",[119225,119141,119150]],[[119230,119230],"mapped",[119226,119141,119150]],[[119231,119231],"mapped",[119225,119141,119151]],[[119232,119232],"mapped",[119226,119141,119151]],[[119233,119261],"valid",[],"NV8"],[[119262,119272],"valid",[],"NV8"],[[119273,119295],"disallowed"],[[119296,119365],"valid",[],"NV8"],[[119366,119551],"disallowed"],[[119552,119638],"valid",[],"NV8"],[[119639,119647],"disallowed"],[[119648,119665],"valid",[],"NV8"],[[119666,119807],"disallowed"],[[119808,119808],"mapped",[97]],[[119809,119809],"mapped",[98]],[[119810,119810],"mapped",[99]],[[119811,119811],"mapped",[100]],[[119812,119812],"mapped",[101]],[[119813,119813],"mapped",[102]],[[119814,119814],"mapped",[103]],[[119815,119815],"mapped",[104]],[[119816,119816],"mapped",[105]],[[119817,119817],"mapped",[106]],[[119818,119818],"mapped",[107]],[[119819,119819],"mapped",[108]],[[119820,119820],"mapped",[109]],[[119821,119821],"mapped",[110]],[[119822,119822],"mapped",[111]],[[119823,119823],"mapped",[112]],[[119824,119824],"mapped",[113]],[[119825,119825],"mapped",[114]],[[119826,119826],"mapped",[115]],[[119827,119827],"mapped",[116]],[[119828,119828],"mapped",[117]],[[119829,119829],"mapped",[118]],[[119830,119830],"mapped",[119]],[[119831,119831],"mapped",[120]],[[119832,119832],"mapped",[121]],[[119833,119833],"mapped",[122]],[[119834,119834],"mapped",[97]],[[119835,119835],"mapped",[98]],[[119836,119836],"mapped",[99]],[[119837,119837],"mapped",[100]],[[119838,119838],"mapped",[101]],[[119839,119839],"mapped",[102]],[[119840,119840],"mapped",[103]],[[119841,119841],"mapped",[104]],[[119842,119842],"mapped",[105]],[[119843,119843],"mapped",[106]],[[119844,119844],"mapped",[107]],[[119845,119845],"mapped",[108]],[[119846,119846],"mapped",[109]],[[119847,119847],"mapped",[110]],[[119848,119848],"mapped",[111]],[[119849,119849],"mapped",[112]],[[119850,119850],"mapped",[113]],[[119851,119851],"mapped",[114]],[[119852,119852],"mapped",[115]],[[119853,119853],"mapped",[116]],[[119854,119854],"mapped",[117]],[[119855,119855],"mapped",[118]],[[119856,119856],"mapped",[119]],[[119857,119857],"mapped",[120]],[[119858,119858],"mapped",[121]],[[119859,119859],"mapped",[122]],[[119860,119860],"mapped",[97]],[[119861,119861],"mapped",[98]],[[119862,119862],"mapped",[99]],[[119863,119863],"mapped",[100]],[[119864,119864],"mapped",[101]],[[119865,119865],"mapped",[102]],[[119866,119866],"mapped",[103]],[[119867,119867],"mapped",[104]],[[119868,119868],"mapped",[105]],[[119869,119869],"mapped",[106]],[[119870,119870],"mapped",[107]],[[119871,119871],"mapped",[108]],[[119872,119872],"mapped",[109]],[[119873,119873],"mapped",[110]],[[119874,119874],"mapped",[111]],[[119875,119875],"mapped",[112]],[[119876,119876],"mapped",[113]],[[119877,119877],"mapped",[114]],[[119878,119878],"mapped",[115]],[[119879,119879],"mapped",[116]],[[119880,119880],"mapped",[117]],[[119881,119881],"mapped",[118]],[[119882,119882],"mapped",[119]],[[119883,119883],"mapped",[120]],[[119884,119884],"mapped",[121]],[[119885,119885],"mapped",[122]],[[119886,119886],"mapped",[97]],[[119887,119887],"mapped",[98]],[[119888,119888],"mapped",[99]],[[119889,119889],"mapped",[100]],[[119890,119890],"mapped",[101]],[[119891,119891],"mapped",[102]],[[119892,119892],"mapped",[103]],[[119893,119893],"disallowed"],[[119894,119894],"mapped",[105]],[[119895,119895],"mapped",[106]],[[119896,119896],"mapped",[107]],[[119897,119897],"mapped",[108]],[[119898,119898],"mapped",[109]],[[119899,119899],"mapped",[110]],[[119900,119900],"mapped",[111]],[[119901,119901],"mapped",[112]],[[119902,119902],"mapped",[113]],[[119903,119903],"mapped",[114]],[[119904,119904],"mapped",[115]],[[119905,119905],"mapped",[116]],[[119906,119906],"mapped",[117]],[[119907,119907],"mapped",[118]],[[119908,119908],"mapped",[119]],[[119909,119909],"mapped",[120]],[[119910,119910],"mapped",[121]],[[119911,119911],"mapped",[122]],[[119912,119912],"mapped",[97]],[[119913,119913],"mapped",[98]],[[119914,119914],"mapped",[99]],[[119915,119915],"mapped",[100]],[[119916,119916],"mapped",[101]],[[119917,119917],"mapped",[102]],[[119918,119918],"mapped",[103]],[[119919,119919],"mapped",[104]],[[119920,119920],"mapped",[105]],[[119921,119921],"mapped",[106]],[[119922,119922],"mapped",[107]],[[119923,119923],"mapped",[108]],[[119924,119924],"mapped",[109]],[[119925,119925],"mapped",[110]],[[119926,119926],"mapped",[111]],[[119927,119927],"mapped",[112]],[[119928,119928],"mapped",[113]],[[119929,119929],"mapped",[114]],[[119930,119930],"mapped",[115]],[[119931,119931],"mapped",[116]],[[119932,119932],"mapped",[117]],[[119933,119933],"mapped",[118]],[[119934,119934],"mapped",[119]],[[119935,119935],"mapped",[120]],[[119936,119936],"mapped",[121]],[[119937,119937],"mapped",[122]],[[119938,119938],"mapped",[97]],[[119939,119939],"mapped",[98]],[[119940,119940],"mapped",[99]],[[119941,119941],"mapped",[100]],[[119942,119942],"mapped",[101]],[[119943,119943],"mapped",[102]],[[119944,119944],"mapped",[103]],[[119945,119945],"mapped",[104]],[[119946,119946],"mapped",[105]],[[119947,119947],"mapped",[106]],[[119948,119948],"mapped",[107]],[[119949,119949],"mapped",[108]],[[119950,119950],"mapped",[109]],[[119951,119951],"mapped",[110]],[[119952,119952],"mapped",[111]],[[119953,119953],"mapped",[112]],[[119954,119954],"mapped",[113]],[[119955,119955],"mapped",[114]],[[119956,119956],"mapped",[115]],[[119957,119957],"mapped",[116]],[[119958,119958],"mapped",[117]],[[119959,119959],"mapped",[118]],[[119960,119960],"mapped",[119]],[[119961,119961],"mapped",[120]],[[119962,119962],"mapped",[121]],[[119963,119963],"mapped",[122]],[[119964,119964],"mapped",[97]],[[119965,119965],"disallowed"],[[119966,119966],"mapped",[99]],[[119967,119967],"mapped",[100]],[[119968,119969],"disallowed"],[[119970,119970],"mapped",[103]],[[119971,119972],"disallowed"],[[119973,119973],"mapped",[106]],[[119974,119974],"mapped",[107]],[[119975,119976],"disallowed"],[[119977,119977],"mapped",[110]],[[119978,119978],"mapped",[111]],[[119979,119979],"mapped",[112]],[[119980,119980],"mapped",[113]],[[119981,119981],"disallowed"],[[119982,119982],"mapped",[115]],[[119983,119983],"mapped",[116]],[[119984,119984],"mapped",[117]],[[119985,119985],"mapped",[118]],[[119986,119986],"mapped",[119]],[[119987,119987],"mapped",[120]],[[119988,119988],"mapped",[121]],[[119989,119989],"mapped",[122]],[[119990,119990],"mapped",[97]],[[119991,119991],"mapped",[98]],[[119992,119992],"mapped",[99]],[[119993,119993],"mapped",[100]],[[119994,119994],"disallowed"],[[119995,119995],"mapped",[102]],[[119996,119996],"disallowed"],[[119997,119997],"mapped",[104]],[[119998,119998],"mapped",[105]],[[119999,119999],"mapped",[106]],[[120000,120000],"mapped",[107]],[[120001,120001],"mapped",[108]],[[120002,120002],"mapped",[109]],[[120003,120003],"mapped",[110]],[[120004,120004],"disallowed"],[[120005,120005],"mapped",[112]],[[120006,120006],"mapped",[113]],[[120007,120007],"mapped",[114]],[[120008,120008],"mapped",[115]],[[120009,120009],"mapped",[116]],[[120010,120010],"mapped",[117]],[[120011,120011],"mapped",[118]],[[120012,120012],"mapped",[119]],[[120013,120013],"mapped",[120]],[[120014,120014],"mapped",[121]],[[120015,120015],"mapped",[122]],[[120016,120016],"mapped",[97]],[[120017,120017],"mapped",[98]],[[120018,120018],"mapped",[99]],[[120019,120019],"mapped",[100]],[[120020,120020],"mapped",[101]],[[120021,120021],"mapped",[102]],[[120022,120022],"mapped",[103]],[[120023,120023],"mapped",[104]],[[120024,120024],"mapped",[105]],[[120025,120025],"mapped",[106]],[[120026,120026],"mapped",[107]],[[120027,120027],"mapped",[108]],[[120028,120028],"mapped",[109]],[[120029,120029],"mapped",[110]],[[120030,120030],"mapped",[111]],[[120031,120031],"mapped",[112]],[[120032,120032],"mapped",[113]],[[120033,120033],"mapped",[114]],[[120034,120034],"mapped",[115]],[[120035,120035],"mapped",[116]],[[120036,120036],"mapped",[117]],[[120037,120037],"mapped",[118]],[[120038,120038],"mapped",[119]],[[120039,120039],"mapped",[120]],[[120040,120040],"mapped",[121]],[[120041,120041],"mapped",[122]],[[120042,120042],"mapped",[97]],[[120043,120043],"mapped",[98]],[[120044,120044],"mapped",[99]],[[120045,120045],"mapped",[100]],[[120046,120046],"mapped",[101]],[[120047,120047],"mapped",[102]],[[120048,120048],"mapped",[103]],[[120049,120049],"mapped",[104]],[[120050,120050],"mapped",[105]],[[120051,120051],"mapped",[106]],[[120052,120052],"mapped",[107]],[[120053,120053],"mapped",[108]],[[120054,120054],"mapped",[109]],[[120055,120055],"mapped",[110]],[[120056,120056],"mapped",[111]],[[120057,120057],"mapped",[112]],[[120058,120058],"mapped",[113]],[[120059,120059],"mapped",[114]],[[120060,120060],"mapped",[115]],[[120061,120061],"mapped",[116]],[[120062,120062],"mapped",[117]],[[120063,120063],"mapped",[118]],[[120064,120064],"mapped",[119]],[[120065,120065],"mapped",[120]],[[120066,120066],"mapped",[121]],[[120067,120067],"mapped",[122]],[[120068,120068],"mapped",[97]],[[120069,120069],"mapped",[98]],[[120070,120070],"disallowed"],[[120071,120071],"mapped",[100]],[[120072,120072],"mapped",[101]],[[120073,120073],"mapped",[102]],[[120074,120074],"mapped",[103]],[[120075,120076],"disallowed"],[[120077,120077],"mapped",[106]],[[120078,120078],"mapped",[107]],[[120079,120079],"mapped",[108]],[[120080,120080],"mapped",[109]],[[120081,120081],"mapped",[110]],[[120082,120082],"mapped",[111]],[[120083,120083],"mapped",[112]],[[120084,120084],"mapped",[113]],[[120085,120085],"disallowed"],[[120086,120086],"mapped",[115]],[[120087,120087],"mapped",[116]],[[120088,120088],"mapped",[117]],[[120089,120089],"mapped",[118]],[[120090,120090],"mapped",[119]],[[120091,120091],"mapped",[120]],[[120092,120092],"mapped",[121]],[[120093,120093],"disallowed"],[[120094,120094],"mapped",[97]],[[120095,120095],"mapped",[98]],[[120096,120096],"mapped",[99]],[[120097,120097],"mapped",[100]],[[120098,120098],"mapped",[101]],[[120099,120099],"mapped",[102]],[[120100,120100],"mapped",[103]],[[120101,120101],"mapped",[104]],[[120102,120102],"mapped",[105]],[[120103,120103],"mapped",[106]],[[120104,120104],"mapped",[107]],[[120105,120105],"mapped",[108]],[[120106,120106],"mapped",[109]],[[120107,120107],"mapped",[110]],[[120108,120108],"mapped",[111]],[[120109,120109],"mapped",[112]],[[120110,120110],"mapped",[113]],[[120111,120111],"mapped",[114]],[[120112,120112],"mapped",[115]],[[120113,120113],"mapped",[116]],[[120114,120114],"mapped",[117]],[[120115,120115],"mapped",[118]],[[120116,120116],"mapped",[119]],[[120117,120117],"mapped",[120]],[[120118,120118],"mapped",[121]],[[120119,120119],"mapped",[122]],[[120120,120120],"mapped",[97]],[[120121,120121],"mapped",[98]],[[120122,120122],"disallowed"],[[120123,120123],"mapped",[100]],[[120124,120124],"mapped",[101]],[[120125,120125],"mapped",[102]],[[120126,120126],"mapped",[103]],[[120127,120127],"disallowed"],[[120128,120128],"mapped",[105]],[[120129,120129],"mapped",[106]],[[120130,120130],"mapped",[107]],[[120131,120131],"mapped",[108]],[[120132,120132],"mapped",[109]],[[120133,120133],"disallowed"],[[120134,120134],"mapped",[111]],[[120135,120137],"disallowed"],[[120138,120138],"mapped",[115]],[[120139,120139],"mapped",[116]],[[120140,120140],"mapped",[117]],[[120141,120141],"mapped",[118]],[[120142,120142],"mapped",[119]],[[120143,120143],"mapped",[120]],[[120144,120144],"mapped",[121]],[[120145,120145],"disallowed"],[[120146,120146],"mapped",[97]],[[120147,120147],"mapped",[98]],[[120148,120148],"mapped",[99]],[[120149,120149],"mapped",[100]],[[120150,120150],"mapped",[101]],[[120151,120151],"mapped",[102]],[[120152,120152],"mapped",[103]],[[120153,120153],"mapped",[104]],[[120154,120154],"mapped",[105]],[[120155,120155],"mapped",[106]],[[120156,120156],"mapped",[107]],[[120157,120157],"mapped",[108]],[[120158,120158],"mapped",[109]],[[120159,120159],"mapped",[110]],[[120160,120160],"mapped",[111]],[[120161,120161],"mapped",[112]],[[120162,120162],"mapped",[113]],[[120163,120163],"mapped",[114]],[[120164,120164],"mapped",[115]],[[120165,120165],"mapped",[116]],[[120166,120166],"mapped",[117]],[[120167,120167],"mapped",[118]],[[120168,120168],"mapped",[119]],[[120169,120169],"mapped",[120]],[[120170,120170],"mapped",[121]],[[120171,120171],"mapped",[122]],[[120172,120172],"mapped",[97]],[[120173,120173],"mapped",[98]],[[120174,120174],"mapped",[99]],[[120175,120175],"mapped",[100]],[[120176,120176],"mapped",[101]],[[120177,120177],"mapped",[102]],[[120178,120178],"mapped",[103]],[[120179,120179],"mapped",[104]],[[120180,120180],"mapped",[105]],[[120181,120181],"mapped",[106]],[[120182,120182],"mapped",[107]],[[120183,120183],"mapped",[108]],[[120184,120184],"mapped",[109]],[[120185,120185],"mapped",[110]],[[120186,120186],"mapped",[111]],[[120187,120187],"mapped",[112]],[[120188,120188],"mapped",[113]],[[120189,120189],"mapped",[114]],[[120190,120190],"mapped",[115]],[[120191,120191],"mapped",[116]],[[120192,120192],"mapped",[117]],[[120193,120193],"mapped",[118]],[[120194,120194],"mapped",[119]],[[120195,120195],"mapped",[120]],[[120196,120196],"mapped",[121]],[[120197,120197],"mapped",[122]],[[120198,120198],"mapped",[97]],[[120199,120199],"mapped",[98]],[[120200,120200],"mapped",[99]],[[120201,120201],"mapped",[100]],[[120202,120202],"mapped",[101]],[[120203,120203],"mapped",[102]],[[120204,120204],"mapped",[103]],[[120205,120205],"mapped",[104]],[[120206,120206],"mapped",[105]],[[120207,120207],"mapped",[106]],[[120208,120208],"mapped",[107]],[[120209,120209],"mapped",[108]],[[120210,120210],"mapped",[109]],[[120211,120211],"mapped",[110]],[[120212,120212],"mapped",[111]],[[120213,120213],"mapped",[112]],[[120214,120214],"mapped",[113]],[[120215,120215],"mapped",[114]],[[120216,120216],"mapped",[115]],[[120217,120217],"mapped",[116]],[[120218,120218],"mapped",[117]],[[120219,120219],"mapped",[118]],[[120220,120220],"mapped",[119]],[[120221,120221],"mapped",[120]],[[120222,120222],"mapped",[121]],[[120223,120223],"mapped",[122]],[[120224,120224],"mapped",[97]],[[120225,120225],"mapped",[98]],[[120226,120226],"mapped",[99]],[[120227,120227],"mapped",[100]],[[120228,120228],"mapped",[101]],[[120229,120229],"mapped",[102]],[[120230,120230],"mapped",[103]],[[120231,120231],"mapped",[104]],[[120232,120232],"mapped",[105]],[[120233,120233],"mapped",[106]],[[120234,120234],"mapped",[107]],[[120235,120235],"mapped",[108]],[[120236,120236],"mapped",[109]],[[120237,120237],"mapped",[110]],[[120238,120238],"mapped",[111]],[[120239,120239],"mapped",[112]],[[120240,120240],"mapped",[113]],[[120241,120241],"mapped",[114]],[[120242,120242],"mapped",[115]],[[120243,120243],"mapped",[116]],[[120244,120244],"mapped",[117]],[[120245,120245],"mapped",[118]],[[120246,120246],"mapped",[119]],[[120247,120247],"mapped",[120]],[[120248,120248],"mapped",[121]],[[120249,120249],"mapped",[122]],[[120250,120250],"mapped",[97]],[[120251,120251],"mapped",[98]],[[120252,120252],"mapped",[99]],[[120253,120253],"mapped",[100]],[[120254,120254],"mapped",[101]],[[120255,120255],"mapped",[102]],[[120256,120256],"mapped",[103]],[[120257,120257],"mapped",[104]],[[120258,120258],"mapped",[105]],[[120259,120259],"mapped",[106]],[[120260,120260],"mapped",[107]],[[120261,120261],"mapped",[108]],[[120262,120262],"mapped",[109]],[[120263,120263],"mapped",[110]],[[120264,120264],"mapped",[111]],[[120265,120265],"mapped",[112]],[[120266,120266],"mapped",[113]],[[120267,120267],"mapped",[114]],[[120268,120268],"mapped",[115]],[[120269,120269],"mapped",[116]],[[120270,120270],"mapped",[117]],[[120271,120271],"mapped",[118]],[[120272,120272],"mapped",[119]],[[120273,120273],"mapped",[120]],[[120274,120274],"mapped",[121]],[[120275,120275],"mapped",[122]],[[120276,120276],"mapped",[97]],[[120277,120277],"mapped",[98]],[[120278,120278],"mapped",[99]],[[120279,120279],"mapped",[100]],[[120280,120280],"mapped",[101]],[[120281,120281],"mapped",[102]],[[120282,120282],"mapped",[103]],[[120283,120283],"mapped",[104]],[[120284,120284],"mapped",[105]],[[120285,120285],"mapped",[106]],[[120286,120286],"mapped",[107]],[[120287,120287],"mapped",[108]],[[120288,120288],"mapped",[109]],[[120289,120289],"mapped",[110]],[[120290,120290],"mapped",[111]],[[120291,120291],"mapped",[112]],[[120292,120292],"mapped",[113]],[[120293,120293],"mapped",[114]],[[120294,120294],"mapped",[115]],[[120295,120295],"mapped",[116]],[[120296,120296],"mapped",[117]],[[120297,120297],"mapped",[118]],[[120298,120298],"mapped",[119]],[[120299,120299],"mapped",[120]],[[120300,120300],"mapped",[121]],[[120301,120301],"mapped",[122]],[[120302,120302],"mapped",[97]],[[120303,120303],"mapped",[98]],[[120304,120304],"mapped",[99]],[[120305,120305],"mapped",[100]],[[120306,120306],"mapped",[101]],[[120307,120307],"mapped",[102]],[[120308,120308],"mapped",[103]],[[120309,120309],"mapped",[104]],[[120310,120310],"mapped",[105]],[[120311,120311],"mapped",[106]],[[120312,120312],"mapped",[107]],[[120313,120313],"mapped",[108]],[[120314,120314],"mapped",[109]],[[120315,120315],"mapped",[110]],[[120316,120316],"mapped",[111]],[[120317,120317],"mapped",[112]],[[120318,120318],"mapped",[113]],[[120319,120319],"mapped",[114]],[[120320,120320],"mapped",[115]],[[120321,120321],"mapped",[116]],[[120322,120322],"mapped",[117]],[[120323,120323],"mapped",[118]],[[120324,120324],"mapped",[119]],[[120325,120325],"mapped",[120]],[[120326,120326],"mapped",[121]],[[120327,120327],"mapped",[122]],[[120328,120328],"mapped",[97]],[[120329,120329],"mapped",[98]],[[120330,120330],"mapped",[99]],[[120331,120331],"mapped",[100]],[[120332,120332],"mapped",[101]],[[120333,120333],"mapped",[102]],[[120334,120334],"mapped",[103]],[[120335,120335],"mapped",[104]],[[120336,120336],"mapped",[105]],[[120337,120337],"mapped",[106]],[[120338,120338],"mapped",[107]],[[120339,120339],"mapped",[108]],[[120340,120340],"mapped",[109]],[[120341,120341],"mapped",[110]],[[120342,120342],"mapped",[111]],[[120343,120343],"mapped",[112]],[[120344,120344],"mapped",[113]],[[120345,120345],"mapped",[114]],[[120346,120346],"mapped",[115]],[[120347,120347],"mapped",[116]],[[120348,120348],"mapped",[117]],[[120349,120349],"mapped",[118]],[[120350,120350],"mapped",[119]],[[120351,120351],"mapped",[120]],[[120352,120352],"mapped",[121]],[[120353,120353],"mapped",[122]],[[120354,120354],"mapped",[97]],[[120355,120355],"mapped",[98]],[[120356,120356],"mapped",[99]],[[120357,120357],"mapped",[100]],[[120358,120358],"mapped",[101]],[[120359,120359],"mapped",[102]],[[120360,120360],"mapped",[103]],[[120361,120361],"mapped",[104]],[[120362,120362],"mapped",[105]],[[120363,120363],"mapped",[106]],[[120364,120364],"mapped",[107]],[[120365,120365],"mapped",[108]],[[120366,120366],"mapped",[109]],[[120367,120367],"mapped",[110]],[[120368,120368],"mapped",[111]],[[120369,120369],"mapped",[112]],[[120370,120370],"mapped",[113]],[[120371,120371],"mapped",[114]],[[120372,120372],"mapped",[115]],[[120373,120373],"mapped",[116]],[[120374,120374],"mapped",[117]],[[120375,120375],"mapped",[118]],[[120376,120376],"mapped",[119]],[[120377,120377],"mapped",[120]],[[120378,120378],"mapped",[121]],[[120379,120379],"mapped",[122]],[[120380,120380],"mapped",[97]],[[120381,120381],"mapped",[98]],[[120382,120382],"mapped",[99]],[[120383,120383],"mapped",[100]],[[120384,120384],"mapped",[101]],[[120385,120385],"mapped",[102]],[[120386,120386],"mapped",[103]],[[120387,120387],"mapped",[104]],[[120388,120388],"mapped",[105]],[[120389,120389],"mapped",[106]],[[120390,120390],"mapped",[107]],[[120391,120391],"mapped",[108]],[[120392,120392],"mapped",[109]],[[120393,120393],"mapped",[110]],[[120394,120394],"mapped",[111]],[[120395,120395],"mapped",[112]],[[120396,120396],"mapped",[113]],[[120397,120397],"mapped",[114]],[[120398,120398],"mapped",[115]],[[120399,120399],"mapped",[116]],[[120400,120400],"mapped",[117]],[[120401,120401],"mapped",[118]],[[120402,120402],"mapped",[119]],[[120403,120403],"mapped",[120]],[[120404,120404],"mapped",[121]],[[120405,120405],"mapped",[122]],[[120406,120406],"mapped",[97]],[[120407,120407],"mapped",[98]],[[120408,120408],"mapped",[99]],[[120409,120409],"mapped",[100]],[[120410,120410],"mapped",[101]],[[120411,120411],"mapped",[102]],[[120412,120412],"mapped",[103]],[[120413,120413],"mapped",[104]],[[120414,120414],"mapped",[105]],[[120415,120415],"mapped",[106]],[[120416,120416],"mapped",[107]],[[120417,120417],"mapped",[108]],[[120418,120418],"mapped",[109]],[[120419,120419],"mapped",[110]],[[120420,120420],"mapped",[111]],[[120421,120421],"mapped",[112]],[[120422,120422],"mapped",[113]],[[120423,120423],"mapped",[114]],[[120424,120424],"mapped",[115]],[[120425,120425],"mapped",[116]],[[120426,120426],"mapped",[117]],[[120427,120427],"mapped",[118]],[[120428,120428],"mapped",[119]],[[120429,120429],"mapped",[120]],[[120430,120430],"mapped",[121]],[[120431,120431],"mapped",[122]],[[120432,120432],"mapped",[97]],[[120433,120433],"mapped",[98]],[[120434,120434],"mapped",[99]],[[120435,120435],"mapped",[100]],[[120436,120436],"mapped",[101]],[[120437,120437],"mapped",[102]],[[120438,120438],"mapped",[103]],[[120439,120439],"mapped",[104]],[[120440,120440],"mapped",[105]],[[120441,120441],"mapped",[106]],[[120442,120442],"mapped",[107]],[[120443,120443],"mapped",[108]],[[120444,120444],"mapped",[109]],[[120445,120445],"mapped",[110]],[[120446,120446],"mapped",[111]],[[120447,120447],"mapped",[112]],[[120448,120448],"mapped",[113]],[[120449,120449],"mapped",[114]],[[120450,120450],"mapped",[115]],[[120451,120451],"mapped",[116]],[[120452,120452],"mapped",[117]],[[120453,120453],"mapped",[118]],[[120454,120454],"mapped",[119]],[[120455,120455],"mapped",[120]],[[120456,120456],"mapped",[121]],[[120457,120457],"mapped",[122]],[[120458,120458],"mapped",[97]],[[120459,120459],"mapped",[98]],[[120460,120460],"mapped",[99]],[[120461,120461],"mapped",[100]],[[120462,120462],"mapped",[101]],[[120463,120463],"mapped",[102]],[[120464,120464],"mapped",[103]],[[120465,120465],"mapped",[104]],[[120466,120466],"mapped",[105]],[[120467,120467],"mapped",[106]],[[120468,120468],"mapped",[107]],[[120469,120469],"mapped",[108]],[[120470,120470],"mapped",[109]],[[120471,120471],"mapped",[110]],[[120472,120472],"mapped",[111]],[[120473,120473],"mapped",[112]],[[120474,120474],"mapped",[113]],[[120475,120475],"mapped",[114]],[[120476,120476],"mapped",[115]],[[120477,120477],"mapped",[116]],[[120478,120478],"mapped",[117]],[[120479,120479],"mapped",[118]],[[120480,120480],"mapped",[119]],[[120481,120481],"mapped",[120]],[[120482,120482],"mapped",[121]],[[120483,120483],"mapped",[122]],[[120484,120484],"mapped",[305]],[[120485,120485],"mapped",[567]],[[120486,120487],"disallowed"],[[120488,120488],"mapped",[945]],[[120489,120489],"mapped",[946]],[[120490,120490],"mapped",[947]],[[120491,120491],"mapped",[948]],[[120492,120492],"mapped",[949]],[[120493,120493],"mapped",[950]],[[120494,120494],"mapped",[951]],[[120495,120495],"mapped",[952]],[[120496,120496],"mapped",[953]],[[120497,120497],"mapped",[954]],[[120498,120498],"mapped",[955]],[[120499,120499],"mapped",[956]],[[120500,120500],"mapped",[957]],[[120501,120501],"mapped",[958]],[[120502,120502],"mapped",[959]],[[120503,120503],"mapped",[960]],[[120504,120504],"mapped",[961]],[[120505,120505],"mapped",[952]],[[120506,120506],"mapped",[963]],[[120507,120507],"mapped",[964]],[[120508,120508],"mapped",[965]],[[120509,120509],"mapped",[966]],[[120510,120510],"mapped",[967]],[[120511,120511],"mapped",[968]],[[120512,120512],"mapped",[969]],[[120513,120513],"mapped",[8711]],[[120514,120514],"mapped",[945]],[[120515,120515],"mapped",[946]],[[120516,120516],"mapped",[947]],[[120517,120517],"mapped",[948]],[[120518,120518],"mapped",[949]],[[120519,120519],"mapped",[950]],[[120520,120520],"mapped",[951]],[[120521,120521],"mapped",[952]],[[120522,120522],"mapped",[953]],[[120523,120523],"mapped",[954]],[[120524,120524],"mapped",[955]],[[120525,120525],"mapped",[956]],[[120526,120526],"mapped",[957]],[[120527,120527],"mapped",[958]],[[120528,120528],"mapped",[959]],[[120529,120529],"mapped",[960]],[[120530,120530],"mapped",[961]],[[120531,120532],"mapped",[963]],[[120533,120533],"mapped",[964]],[[120534,120534],"mapped",[965]],[[120535,120535],"mapped",[966]],[[120536,120536],"mapped",[967]],[[120537,120537],"mapped",[968]],[[120538,120538],"mapped",[969]],[[120539,120539],"mapped",[8706]],[[120540,120540],"mapped",[949]],[[120541,120541],"mapped",[952]],[[120542,120542],"mapped",[954]],[[120543,120543],"mapped",[966]],[[120544,120544],"mapped",[961]],[[120545,120545],"mapped",[960]],[[120546,120546],"mapped",[945]],[[120547,120547],"mapped",[946]],[[120548,120548],"mapped",[947]],[[120549,120549],"mapped",[948]],[[120550,120550],"mapped",[949]],[[120551,120551],"mapped",[950]],[[120552,120552],"mapped",[951]],[[120553,120553],"mapped",[952]],[[120554,120554],"mapped",[953]],[[120555,120555],"mapped",[954]],[[120556,120556],"mapped",[955]],[[120557,120557],"mapped",[956]],[[120558,120558],"mapped",[957]],[[120559,120559],"mapped",[958]],[[120560,120560],"mapped",[959]],[[120561,120561],"mapped",[960]],[[120562,120562],"mapped",[961]],[[120563,120563],"mapped",[952]],[[120564,120564],"mapped",[963]],[[120565,120565],"mapped",[964]],[[120566,120566],"mapped",[965]],[[120567,120567],"mapped",[966]],[[120568,120568],"mapped",[967]],[[120569,120569],"mapped",[968]],[[120570,120570],"mapped",[969]],[[120571,120571],"mapped",[8711]],[[120572,120572],"mapped",[945]],[[120573,120573],"mapped",[946]],[[120574,120574],"mapped",[947]],[[120575,120575],"mapped",[948]],[[120576,120576],"mapped",[949]],[[120577,120577],"mapped",[950]],[[120578,120578],"mapped",[951]],[[120579,120579],"mapped",[952]],[[120580,120580],"mapped",[953]],[[120581,120581],"mapped",[954]],[[120582,120582],"mapped",[955]],[[120583,120583],"mapped",[956]],[[120584,120584],"mapped",[957]],[[120585,120585],"mapped",[958]],[[120586,120586],"mapped",[959]],[[120587,120587],"mapped",[960]],[[120588,120588],"mapped",[961]],[[120589,120590],"mapped",[963]],[[120591,120591],"mapped",[964]],[[120592,120592],"mapped",[965]],[[120593,120593],"mapped",[966]],[[120594,120594],"mapped",[967]],[[120595,120595],"mapped",[968]],[[120596,120596],"mapped",[969]],[[120597,120597],"mapped",[8706]],[[120598,120598],"mapped",[949]],[[120599,120599],"mapped",[952]],[[120600,120600],"mapped",[954]],[[120601,120601],"mapped",[966]],[[120602,120602],"mapped",[961]],[[120603,120603],"mapped",[960]],[[120604,120604],"mapped",[945]],[[120605,120605],"mapped",[946]],[[120606,120606],"mapped",[947]],[[120607,120607],"mapped",[948]],[[120608,120608],"mapped",[949]],[[120609,120609],"mapped",[950]],[[120610,120610],"mapped",[951]],[[120611,120611],"mapped",[952]],[[120612,120612],"mapped",[953]],[[120613,120613],"mapped",[954]],[[120614,120614],"mapped",[955]],[[120615,120615],"mapped",[956]],[[120616,120616],"mapped",[957]],[[120617,120617],"mapped",[958]],[[120618,120618],"mapped",[959]],[[120619,120619],"mapped",[960]],[[120620,120620],"mapped",[961]],[[120621,120621],"mapped",[952]],[[120622,120622],"mapped",[963]],[[120623,120623],"mapped",[964]],[[120624,120624],"mapped",[965]],[[120625,120625],"mapped",[966]],[[120626,120626],"mapped",[967]],[[120627,120627],"mapped",[968]],[[120628,120628],"mapped",[969]],[[120629,120629],"mapped",[8711]],[[120630,120630],"mapped",[945]],[[120631,120631],"mapped",[946]],[[120632,120632],"mapped",[947]],[[120633,120633],"mapped",[948]],[[120634,120634],"mapped",[949]],[[120635,120635],"mapped",[950]],[[120636,120636],"mapped",[951]],[[120637,120637],"mapped",[952]],[[120638,120638],"mapped",[953]],[[120639,120639],"mapped",[954]],[[120640,120640],"mapped",[955]],[[120641,120641],"mapped",[956]],[[120642,120642],"mapped",[957]],[[120643,120643],"mapped",[958]],[[120644,120644],"mapped",[959]],[[120645,120645],"mapped",[960]],[[120646,120646],"mapped",[961]],[[120647,120648],"mapped",[963]],[[120649,120649],"mapped",[964]],[[120650,120650],"mapped",[965]],[[120651,120651],"mapped",[966]],[[120652,120652],"mapped",[967]],[[120653,120653],"mapped",[968]],[[120654,120654],"mapped",[969]],[[120655,120655],"mapped",[8706]],[[120656,120656],"mapped",[949]],[[120657,120657],"mapped",[952]],[[120658,120658],"mapped",[954]],[[120659,120659],"mapped",[966]],[[120660,120660],"mapped",[961]],[[120661,120661],"mapped",[960]],[[120662,120662],"mapped",[945]],[[120663,120663],"mapped",[946]],[[120664,120664],"mapped",[947]],[[120665,120665],"mapped",[948]],[[120666,120666],"mapped",[949]],[[120667,120667],"mapped",[950]],[[120668,120668],"mapped",[951]],[[120669,120669],"mapped",[952]],[[120670,120670],"mapped",[953]],[[120671,120671],"mapped",[954]],[[120672,120672],"mapped",[955]],[[120673,120673],"mapped",[956]],[[120674,120674],"mapped",[957]],[[120675,120675],"mapped",[958]],[[120676,120676],"mapped",[959]],[[120677,120677],"mapped",[960]],[[120678,120678],"mapped",[961]],[[120679,120679],"mapped",[952]],[[120680,120680],"mapped",[963]],[[120681,120681],"mapped",[964]],[[120682,120682],"mapped",[965]],[[120683,120683],"mapped",[966]],[[120684,120684],"mapped",[967]],[[120685,120685],"mapped",[968]],[[120686,120686],"mapped",[969]],[[120687,120687],"mapped",[8711]],[[120688,120688],"mapped",[945]],[[120689,120689],"mapped",[946]],[[120690,120690],"mapped",[947]],[[120691,120691],"mapped",[948]],[[120692,120692],"mapped",[949]],[[120693,120693],"mapped",[950]],[[120694,120694],"mapped",[951]],[[120695,120695],"mapped",[952]],[[120696,120696],"mapped",[953]],[[120697,120697],"mapped",[954]],[[120698,120698],"mapped",[955]],[[120699,120699],"mapped",[956]],[[120700,120700],"mapped",[957]],[[120701,120701],"mapped",[958]],[[120702,120702],"mapped",[959]],[[120703,120703],"mapped",[960]],[[120704,120704],"mapped",[961]],[[120705,120706],"mapped",[963]],[[120707,120707],"mapped",[964]],[[120708,120708],"mapped",[965]],[[120709,120709],"mapped",[966]],[[120710,120710],"mapped",[967]],[[120711,120711],"mapped",[968]],[[120712,120712],"mapped",[969]],[[120713,120713],"mapped",[8706]],[[120714,120714],"mapped",[949]],[[120715,120715],"mapped",[952]],[[120716,120716],"mapped",[954]],[[120717,120717],"mapped",[966]],[[120718,120718],"mapped",[961]],[[120719,120719],"mapped",[960]],[[120720,120720],"mapped",[945]],[[120721,120721],"mapped",[946]],[[120722,120722],"mapped",[947]],[[120723,120723],"mapped",[948]],[[120724,120724],"mapped",[949]],[[120725,120725],"mapped",[950]],[[120726,120726],"mapped",[951]],[[120727,120727],"mapped",[952]],[[120728,120728],"mapped",[953]],[[120729,120729],"mapped",[954]],[[120730,120730],"mapped",[955]],[[120731,120731],"mapped",[956]],[[120732,120732],"mapped",[957]],[[120733,120733],"mapped",[958]],[[120734,120734],"mapped",[959]],[[120735,120735],"mapped",[960]],[[120736,120736],"mapped",[961]],[[120737,120737],"mapped",[952]],[[120738,120738],"mapped",[963]],[[120739,120739],"mapped",[964]],[[120740,120740],"mapped",[965]],[[120741,120741],"mapped",[966]],[[120742,120742],"mapped",[967]],[[120743,120743],"mapped",[968]],[[120744,120744],"mapped",[969]],[[120745,120745],"mapped",[8711]],[[120746,120746],"mapped",[945]],[[120747,120747],"mapped",[946]],[[120748,120748],"mapped",[947]],[[120749,120749],"mapped",[948]],[[120750,120750],"mapped",[949]],[[120751,120751],"mapped",[950]],[[120752,120752],"mapped",[951]],[[120753,120753],"mapped",[952]],[[120754,120754],"mapped",[953]],[[120755,120755],"mapped",[954]],[[120756,120756],"mapped",[955]],[[120757,120757],"mapped",[956]],[[120758,120758],"mapped",[957]],[[120759,120759],"mapped",[958]],[[120760,120760],"mapped",[959]],[[120761,120761],"mapped",[960]],[[120762,120762],"mapped",[961]],[[120763,120764],"mapped",[963]],[[120765,120765],"mapped",[964]],[[120766,120766],"mapped",[965]],[[120767,120767],"mapped",[966]],[[120768,120768],"mapped",[967]],[[120769,120769],"mapped",[968]],[[120770,120770],"mapped",[969]],[[120771,120771],"mapped",[8706]],[[120772,120772],"mapped",[949]],[[120773,120773],"mapped",[952]],[[120774,120774],"mapped",[954]],[[120775,120775],"mapped",[966]],[[120776,120776],"mapped",[961]],[[120777,120777],"mapped",[960]],[[120778,120779],"mapped",[989]],[[120780,120781],"disallowed"],[[120782,120782],"mapped",[48]],[[120783,120783],"mapped",[49]],[[120784,120784],"mapped",[50]],[[120785,120785],"mapped",[51]],[[120786,120786],"mapped",[52]],[[120787,120787],"mapped",[53]],[[120788,120788],"mapped",[54]],[[120789,120789],"mapped",[55]],[[120790,120790],"mapped",[56]],[[120791,120791],"mapped",[57]],[[120792,120792],"mapped",[48]],[[120793,120793],"mapped",[49]],[[120794,120794],"mapped",[50]],[[120795,120795],"mapped",[51]],[[120796,120796],"mapped",[52]],[[120797,120797],"mapped",[53]],[[120798,120798],"mapped",[54]],[[120799,120799],"mapped",[55]],[[120800,120800],"mapped",[56]],[[120801,120801],"mapped",[57]],[[120802,120802],"mapped",[48]],[[120803,120803],"mapped",[49]],[[120804,120804],"mapped",[50]],[[120805,120805],"mapped",[51]],[[120806,120806],"mapped",[52]],[[120807,120807],"mapped",[53]],[[120808,120808],"mapped",[54]],[[120809,120809],"mapped",[55]],[[120810,120810],"mapped",[56]],[[120811,120811],"mapped",[57]],[[120812,120812],"mapped",[48]],[[120813,120813],"mapped",[49]],[[120814,120814],"mapped",[50]],[[120815,120815],"mapped",[51]],[[120816,120816],"mapped",[52]],[[120817,120817],"mapped",[53]],[[120818,120818],"mapped",[54]],[[120819,120819],"mapped",[55]],[[120820,120820],"mapped",[56]],[[120821,120821],"mapped",[57]],[[120822,120822],"mapped",[48]],[[120823,120823],"mapped",[49]],[[120824,120824],"mapped",[50]],[[120825,120825],"mapped",[51]],[[120826,120826],"mapped",[52]],[[120827,120827],"mapped",[53]],[[120828,120828],"mapped",[54]],[[120829,120829],"mapped",[55]],[[120830,120830],"mapped",[56]],[[120831,120831],"mapped",[57]],[[120832,121343],"valid",[],"NV8"],[[121344,121398],"valid"],[[121399,121402],"valid",[],"NV8"],[[121403,121452],"valid"],[[121453,121460],"valid",[],"NV8"],[[121461,121461],"valid"],[[121462,121475],"valid",[],"NV8"],[[121476,121476],"valid"],[[121477,121483],"valid",[],"NV8"],[[121484,121498],"disallowed"],[[121499,121503],"valid"],[[121504,121504],"disallowed"],[[121505,121519],"valid"],[[121520,124927],"disallowed"],[[124928,125124],"valid"],[[125125,125126],"disallowed"],[[125127,125135],"valid",[],"NV8"],[[125136,125142],"valid"],[[125143,126463],"disallowed"],[[126464,126464],"mapped",[1575]],[[126465,126465],"mapped",[1576]],[[126466,126466],"mapped",[1580]],[[126467,126467],"mapped",[1583]],[[126468,126468],"disallowed"],[[126469,126469],"mapped",[1608]],[[126470,126470],"mapped",[1586]],[[126471,126471],"mapped",[1581]],[[126472,126472],"mapped",[1591]],[[126473,126473],"mapped",[1610]],[[126474,126474],"mapped",[1603]],[[126475,126475],"mapped",[1604]],[[126476,126476],"mapped",[1605]],[[126477,126477],"mapped",[1606]],[[126478,126478],"mapped",[1587]],[[126479,126479],"mapped",[1593]],[[126480,126480],"mapped",[1601]],[[126481,126481],"mapped",[1589]],[[126482,126482],"mapped",[1602]],[[126483,126483],"mapped",[1585]],[[126484,126484],"mapped",[1588]],[[126485,126485],"mapped",[1578]],[[126486,126486],"mapped",[1579]],[[126487,126487],"mapped",[1582]],[[126488,126488],"mapped",[1584]],[[126489,126489],"mapped",[1590]],[[126490,126490],"mapped",[1592]],[[126491,126491],"mapped",[1594]],[[126492,126492],"mapped",[1646]],[[126493,126493],"mapped",[1722]],[[126494,126494],"mapped",[1697]],[[126495,126495],"mapped",[1647]],[[126496,126496],"disallowed"],[[126497,126497],"mapped",[1576]],[[126498,126498],"mapped",[1580]],[[126499,126499],"disallowed"],[[126500,126500],"mapped",[1607]],[[126501,126502],"disallowed"],[[126503,126503],"mapped",[1581]],[[126504,126504],"disallowed"],[[126505,126505],"mapped",[1610]],[[126506,126506],"mapped",[1603]],[[126507,126507],"mapped",[1604]],[[126508,126508],"mapped",[1605]],[[126509,126509],"mapped",[1606]],[[126510,126510],"mapped",[1587]],[[126511,126511],"mapped",[1593]],[[126512,126512],"mapped",[1601]],[[126513,126513],"mapped",[1589]],[[126514,126514],"mapped",[1602]],[[126515,126515],"disallowed"],[[126516,126516],"mapped",[1588]],[[126517,126517],"mapped",[1578]],[[126518,126518],"mapped",[1579]],[[126519,126519],"mapped",[1582]],[[126520,126520],"disallowed"],[[126521,126521],"mapped",[1590]],[[126522,126522],"disallowed"],[[126523,126523],"mapped",[1594]],[[126524,126529],"disallowed"],[[126530,126530],"mapped",[1580]],[[126531,126534],"disallowed"],[[126535,126535],"mapped",[1581]],[[126536,126536],"disallowed"],[[126537,126537],"mapped",[1610]],[[126538,126538],"disallowed"],[[126539,126539],"mapped",[1604]],[[126540,126540],"disallowed"],[[126541,126541],"mapped",[1606]],[[126542,126542],"mapped",[1587]],[[126543,126543],"mapped",[1593]],[[126544,126544],"disallowed"],[[126545,126545],"mapped",[1589]],[[126546,126546],"mapped",[1602]],[[126547,126547],"disallowed"],[[126548,126548],"mapped",[1588]],[[126549,126550],"disallowed"],[[126551,126551],"mapped",[1582]],[[126552,126552],"disallowed"],[[126553,126553],"mapped",[1590]],[[126554,126554],"disallowed"],[[126555,126555],"mapped",[1594]],[[126556,126556],"disallowed"],[[126557,126557],"mapped",[1722]],[[126558,126558],"disallowed"],[[126559,126559],"mapped",[1647]],[[126560,126560],"disallowed"],[[126561,126561],"mapped",[1576]],[[126562,126562],"mapped",[1580]],[[126563,126563],"disallowed"],[[126564,126564],"mapped",[1607]],[[126565,126566],"disallowed"],[[126567,126567],"mapped",[1581]],[[126568,126568],"mapped",[1591]],[[126569,126569],"mapped",[1610]],[[126570,126570],"mapped",[1603]],[[126571,126571],"disallowed"],[[126572,126572],"mapped",[1605]],[[126573,126573],"mapped",[1606]],[[126574,126574],"mapped",[1587]],[[126575,126575],"mapped",[1593]],[[126576,126576],"mapped",[1601]],[[126577,126577],"mapped",[1589]],[[126578,126578],"mapped",[1602]],[[126579,126579],"disallowed"],[[126580,126580],"mapped",[1588]],[[126581,126581],"mapped",[1578]],[[126582,126582],"mapped",[1579]],[[126583,126583],"mapped",[1582]],[[126584,126584],"disallowed"],[[126585,126585],"mapped",[1590]],[[126586,126586],"mapped",[1592]],[[126587,126587],"mapped",[1594]],[[126588,126588],"mapped",[1646]],[[126589,126589],"disallowed"],[[126590,126590],"mapped",[1697]],[[126591,126591],"disallowed"],[[126592,126592],"mapped",[1575]],[[126593,126593],"mapped",[1576]],[[126594,126594],"mapped",[1580]],[[126595,126595],"mapped",[1583]],[[126596,126596],"mapped",[1607]],[[126597,126597],"mapped",[1608]],[[126598,126598],"mapped",[1586]],[[126599,126599],"mapped",[1581]],[[126600,126600],"mapped",[1591]],[[126601,126601],"mapped",[1610]],[[126602,126602],"disallowed"],[[126603,126603],"mapped",[1604]],[[126604,126604],"mapped",[1605]],[[126605,126605],"mapped",[1606]],[[126606,126606],"mapped",[1587]],[[126607,126607],"mapped",[1593]],[[126608,126608],"mapped",[1601]],[[126609,126609],"mapped",[1589]],[[126610,126610],"mapped",[1602]],[[126611,126611],"mapped",[1585]],[[126612,126612],"mapped",[1588]],[[126613,126613],"mapped",[1578]],[[126614,126614],"mapped",[1579]],[[126615,126615],"mapped",[1582]],[[126616,126616],"mapped",[1584]],[[126617,126617],"mapped",[1590]],[[126618,126618],"mapped",[1592]],[[126619,126619],"mapped",[1594]],[[126620,126624],"disallowed"],[[126625,126625],"mapped",[1576]],[[126626,126626],"mapped",[1580]],[[126627,126627],"mapped",[1583]],[[126628,126628],"disallowed"],[[126629,126629],"mapped",[1608]],[[126630,126630],"mapped",[1586]],[[126631,126631],"mapped",[1581]],[[126632,126632],"mapped",[1591]],[[126633,126633],"mapped",[1610]],[[126634,126634],"disallowed"],[[126635,126635],"mapped",[1604]],[[126636,126636],"mapped",[1605]],[[126637,126637],"mapped",[1606]],[[126638,126638],"mapped",[1587]],[[126639,126639],"mapped",[1593]],[[126640,126640],"mapped",[1601]],[[126641,126641],"mapped",[1589]],[[126642,126642],"mapped",[1602]],[[126643,126643],"mapped",[1585]],[[126644,126644],"mapped",[1588]],[[126645,126645],"mapped",[1578]],[[126646,126646],"mapped",[1579]],[[126647,126647],"mapped",[1582]],[[126648,126648],"mapped",[1584]],[[126649,126649],"mapped",[1590]],[[126650,126650],"mapped",[1592]],[[126651,126651],"mapped",[1594]],[[126652,126703],"disallowed"],[[126704,126705],"valid",[],"NV8"],[[126706,126975],"disallowed"],[[126976,127019],"valid",[],"NV8"],[[127020,127023],"disallowed"],[[127024,127123],"valid",[],"NV8"],[[127124,127135],"disallowed"],[[127136,127150],"valid",[],"NV8"],[[127151,127152],"disallowed"],[[127153,127166],"valid",[],"NV8"],[[127167,127167],"valid",[],"NV8"],[[127168,127168],"disallowed"],[[127169,127183],"valid",[],"NV8"],[[127184,127184],"disallowed"],[[127185,127199],"valid",[],"NV8"],[[127200,127221],"valid",[],"NV8"],[[127222,127231],"disallowed"],[[127232,127232],"disallowed"],[[127233,127233],"disallowed_STD3_mapped",[48,44]],[[127234,127234],"disallowed_STD3_mapped",[49,44]],[[127235,127235],"disallowed_STD3_mapped",[50,44]],[[127236,127236],"disallowed_STD3_mapped",[51,44]],[[127237,127237],"disallowed_STD3_mapped",[52,44]],[[127238,127238],"disallowed_STD3_mapped",[53,44]],[[127239,127239],"disallowed_STD3_mapped",[54,44]],[[127240,127240],"disallowed_STD3_mapped",[55,44]],[[127241,127241],"disallowed_STD3_mapped",[56,44]],[[127242,127242],"disallowed_STD3_mapped",[57,44]],[[127243,127244],"valid",[],"NV8"],[[127245,127247],"disallowed"],[[127248,127248],"disallowed_STD3_mapped",[40,97,41]],[[127249,127249],"disallowed_STD3_mapped",[40,98,41]],[[127250,127250],"disallowed_STD3_mapped",[40,99,41]],[[127251,127251],"disallowed_STD3_mapped",[40,100,41]],[[127252,127252],"disallowed_STD3_mapped",[40,101,41]],[[127253,127253],"disallowed_STD3_mapped",[40,102,41]],[[127254,127254],"disallowed_STD3_mapped",[40,103,41]],[[127255,127255],"disallowed_STD3_mapped",[40,104,41]],[[127256,127256],"disallowed_STD3_mapped",[40,105,41]],[[127257,127257],"disallowed_STD3_mapped",[40,106,41]],[[127258,127258],"disallowed_STD3_mapped",[40,107,41]],[[127259,127259],"disallowed_STD3_mapped",[40,108,41]],[[127260,127260],"disallowed_STD3_mapped",[40,109,41]],[[127261,127261],"disallowed_STD3_mapped",[40,110,41]],[[127262,127262],"disallowed_STD3_mapped",[40,111,41]],[[127263,127263],"disallowed_STD3_mapped",[40,112,41]],[[127264,127264],"disallowed_STD3_mapped",[40,113,41]],[[127265,127265],"disallowed_STD3_mapped",[40,114,41]],[[127266,127266],"disallowed_STD3_mapped",[40,115,41]],[[127267,127267],"disallowed_STD3_mapped",[40,116,41]],[[127268,127268],"disallowed_STD3_mapped",[40,117,41]],[[127269,127269],"disallowed_STD3_mapped",[40,118,41]],[[127270,127270],"disallowed_STD3_mapped",[40,119,41]],[[127271,127271],"disallowed_STD3_mapped",[40,120,41]],[[127272,127272],"disallowed_STD3_mapped",[40,121,41]],[[127273,127273],"disallowed_STD3_mapped",[40,122,41]],[[127274,127274],"mapped",[12308,115,12309]],[[127275,127275],"mapped",[99]],[[127276,127276],"mapped",[114]],[[127277,127277],"mapped",[99,100]],[[127278,127278],"mapped",[119,122]],[[127279,127279],"disallowed"],[[127280,127280],"mapped",[97]],[[127281,127281],"mapped",[98]],[[127282,127282],"mapped",[99]],[[127283,127283],"mapped",[100]],[[127284,127284],"mapped",[101]],[[127285,127285],"mapped",[102]],[[127286,127286],"mapped",[103]],[[127287,127287],"mapped",[104]],[[127288,127288],"mapped",[105]],[[127289,127289],"mapped",[106]],[[127290,127290],"mapped",[107]],[[127291,127291],"mapped",[108]],[[127292,127292],"mapped",[109]],[[127293,127293],"mapped",[110]],[[127294,127294],"mapped",[111]],[[127295,127295],"mapped",[112]],[[127296,127296],"mapped",[113]],[[127297,127297],"mapped",[114]],[[127298,127298],"mapped",[115]],[[127299,127299],"mapped",[116]],[[127300,127300],"mapped",[117]],[[127301,127301],"mapped",[118]],[[127302,127302],"mapped",[119]],[[127303,127303],"mapped",[120]],[[127304,127304],"mapped",[121]],[[127305,127305],"mapped",[122]],[[127306,127306],"mapped",[104,118]],[[127307,127307],"mapped",[109,118]],[[127308,127308],"mapped",[115,100]],[[127309,127309],"mapped",[115,115]],[[127310,127310],"mapped",[112,112,118]],[[127311,127311],"mapped",[119,99]],[[127312,127318],"valid",[],"NV8"],[[127319,127319],"valid",[],"NV8"],[[127320,127326],"valid",[],"NV8"],[[127327,127327],"valid",[],"NV8"],[[127328,127337],"valid",[],"NV8"],[[127338,127338],"mapped",[109,99]],[[127339,127339],"mapped",[109,100]],[[127340,127343],"disallowed"],[[127344,127352],"valid",[],"NV8"],[[127353,127353],"valid",[],"NV8"],[[127354,127354],"valid",[],"NV8"],[[127355,127356],"valid",[],"NV8"],[[127357,127358],"valid",[],"NV8"],[[127359,127359],"valid",[],"NV8"],[[127360,127369],"valid",[],"NV8"],[[127370,127373],"valid",[],"NV8"],[[127374,127375],"valid",[],"NV8"],[[127376,127376],"mapped",[100,106]],[[127377,127386],"valid",[],"NV8"],[[127387,127461],"disallowed"],[[127462,127487],"valid",[],"NV8"],[[127488,127488],"mapped",[12411,12363]],[[127489,127489],"mapped",[12467,12467]],[[127490,127490],"mapped",[12469]],[[127491,127503],"disallowed"],[[127504,127504],"mapped",[25163]],[[127505,127505],"mapped",[23383]],[[127506,127506],"mapped",[21452]],[[127507,127507],"mapped",[12487]],[[127508,127508],"mapped",[20108]],[[127509,127509],"mapped",[22810]],[[127510,127510],"mapped",[35299]],[[127511,127511],"mapped",[22825]],[[127512,127512],"mapped",[20132]],[[127513,127513],"mapped",[26144]],[[127514,127514],"mapped",[28961]],[[127515,127515],"mapped",[26009]],[[127516,127516],"mapped",[21069]],[[127517,127517],"mapped",[24460]],[[127518,127518],"mapped",[20877]],[[127519,127519],"mapped",[26032]],[[127520,127520],"mapped",[21021]],[[127521,127521],"mapped",[32066]],[[127522,127522],"mapped",[29983]],[[127523,127523],"mapped",[36009]],[[127524,127524],"mapped",[22768]],[[127525,127525],"mapped",[21561]],[[127526,127526],"mapped",[28436]],[[127527,127527],"mapped",[25237]],[[127528,127528],"mapped",[25429]],[[127529,127529],"mapped",[19968]],[[127530,127530],"mapped",[19977]],[[127531,127531],"mapped",[36938]],[[127532,127532],"mapped",[24038]],[[127533,127533],"mapped",[20013]],[[127534,127534],"mapped",[21491]],[[127535,127535],"mapped",[25351]],[[127536,127536],"mapped",[36208]],[[127537,127537],"mapped",[25171]],[[127538,127538],"mapped",[31105]],[[127539,127539],"mapped",[31354]],[[127540,127540],"mapped",[21512]],[[127541,127541],"mapped",[28288]],[[127542,127542],"mapped",[26377]],[[127543,127543],"mapped",[26376]],[[127544,127544],"mapped",[30003]],[[127545,127545],"mapped",[21106]],[[127546,127546],"mapped",[21942]],[[127547,127551],"disallowed"],[[127552,127552],"mapped",[12308,26412,12309]],[[127553,127553],"mapped",[12308,19977,12309]],[[127554,127554],"mapped",[12308,20108,12309]],[[127555,127555],"mapped",[12308,23433,12309]],[[127556,127556],"mapped",[12308,28857,12309]],[[127557,127557],"mapped",[12308,25171,12309]],[[127558,127558],"mapped",[12308,30423,12309]],[[127559,127559],"mapped",[12308,21213,12309]],[[127560,127560],"mapped",[12308,25943,12309]],[[127561,127567],"disallowed"],[[127568,127568],"mapped",[24471]],[[127569,127569],"mapped",[21487]],[[127570,127743],"disallowed"],[[127744,127776],"valid",[],"NV8"],[[127777,127788],"valid",[],"NV8"],[[127789,127791],"valid",[],"NV8"],[[127792,127797],"valid",[],"NV8"],[[127798,127798],"valid",[],"NV8"],[[127799,127868],"valid",[],"NV8"],[[127869,127869],"valid",[],"NV8"],[[127870,127871],"valid",[],"NV8"],[[127872,127891],"valid",[],"NV8"],[[127892,127903],"valid",[],"NV8"],[[127904,127940],"valid",[],"NV8"],[[127941,127941],"valid",[],"NV8"],[[127942,127946],"valid",[],"NV8"],[[127947,127950],"valid",[],"NV8"],[[127951,127955],"valid",[],"NV8"],[[127956,127967],"valid",[],"NV8"],[[127968,127984],"valid",[],"NV8"],[[127985,127991],"valid",[],"NV8"],[[127992,127999],"valid",[],"NV8"],[[128000,128062],"valid",[],"NV8"],[[128063,128063],"valid",[],"NV8"],[[128064,128064],"valid",[],"NV8"],[[128065,128065],"valid",[],"NV8"],[[128066,128247],"valid",[],"NV8"],[[128248,128248],"valid",[],"NV8"],[[128249,128252],"valid",[],"NV8"],[[128253,128254],"valid",[],"NV8"],[[128255,128255],"valid",[],"NV8"],[[128256,128317],"valid",[],"NV8"],[[128318,128319],"valid",[],"NV8"],[[128320,128323],"valid",[],"NV8"],[[128324,128330],"valid",[],"NV8"],[[128331,128335],"valid",[],"NV8"],[[128336,128359],"valid",[],"NV8"],[[128360,128377],"valid",[],"NV8"],[[128378,128378],"disallowed"],[[128379,128419],"valid",[],"NV8"],[[128420,128420],"disallowed"],[[128421,128506],"valid",[],"NV8"],[[128507,128511],"valid",[],"NV8"],[[128512,128512],"valid",[],"NV8"],[[128513,128528],"valid",[],"NV8"],[[128529,128529],"valid",[],"NV8"],[[128530,128532],"valid",[],"NV8"],[[128533,128533],"valid",[],"NV8"],[[128534,128534],"valid",[],"NV8"],[[128535,128535],"valid",[],"NV8"],[[128536,128536],"valid",[],"NV8"],[[128537,128537],"valid",[],"NV8"],[[128538,128538],"valid",[],"NV8"],[[128539,128539],"valid",[],"NV8"],[[128540,128542],"valid",[],"NV8"],[[128543,128543],"valid",[],"NV8"],[[128544,128549],"valid",[],"NV8"],[[128550,128551],"valid",[],"NV8"],[[128552,128555],"valid",[],"NV8"],[[128556,128556],"valid",[],"NV8"],[[128557,128557],"valid",[],"NV8"],[[128558,128559],"valid",[],"NV8"],[[128560,128563],"valid",[],"NV8"],[[128564,128564],"valid",[],"NV8"],[[128565,128576],"valid",[],"NV8"],[[128577,128578],"valid",[],"NV8"],[[128579,128580],"valid",[],"NV8"],[[128581,128591],"valid",[],"NV8"],[[128592,128639],"valid",[],"NV8"],[[128640,128709],"valid",[],"NV8"],[[128710,128719],"valid",[],"NV8"],[[128720,128720],"valid",[],"NV8"],[[128721,128735],"disallowed"],[[128736,128748],"valid",[],"NV8"],[[128749,128751],"disallowed"],[[128752,128755],"valid",[],"NV8"],[[128756,128767],"disallowed"],[[128768,128883],"valid",[],"NV8"],[[128884,128895],"disallowed"],[[128896,128980],"valid",[],"NV8"],[[128981,129023],"disallowed"],[[129024,129035],"valid",[],"NV8"],[[129036,129039],"disallowed"],[[129040,129095],"valid",[],"NV8"],[[129096,129103],"disallowed"],[[129104,129113],"valid",[],"NV8"],[[129114,129119],"disallowed"],[[129120,129159],"valid",[],"NV8"],[[129160,129167],"disallowed"],[[129168,129197],"valid",[],"NV8"],[[129198,129295],"disallowed"],[[129296,129304],"valid",[],"NV8"],[[129305,129407],"disallowed"],[[129408,129412],"valid",[],"NV8"],[[129413,129471],"disallowed"],[[129472,129472],"valid",[],"NV8"],[[129473,131069],"disallowed"],[[131070,131071],"disallowed"],[[131072,173782],"valid"],[[173783,173823],"disallowed"],[[173824,177972],"valid"],[[177973,177983],"disallowed"],[[177984,178205],"valid"],[[178206,178207],"disallowed"],[[178208,183969],"valid"],[[183970,194559],"disallowed"],[[194560,194560],"mapped",[20029]],[[194561,194561],"mapped",[20024]],[[194562,194562],"mapped",[20033]],[[194563,194563],"mapped",[131362]],[[194564,194564],"mapped",[20320]],[[194565,194565],"mapped",[20398]],[[194566,194566],"mapped",[20411]],[[194567,194567],"mapped",[20482]],[[194568,194568],"mapped",[20602]],[[194569,194569],"mapped",[20633]],[[194570,194570],"mapped",[20711]],[[194571,194571],"mapped",[20687]],[[194572,194572],"mapped",[13470]],[[194573,194573],"mapped",[132666]],[[194574,194574],"mapped",[20813]],[[194575,194575],"mapped",[20820]],[[194576,194576],"mapped",[20836]],[[194577,194577],"mapped",[20855]],[[194578,194578],"mapped",[132380]],[[194579,194579],"mapped",[13497]],[[194580,194580],"mapped",[20839]],[[194581,194581],"mapped",[20877]],[[194582,194582],"mapped",[132427]],[[194583,194583],"mapped",[20887]],[[194584,194584],"mapped",[20900]],[[194585,194585],"mapped",[20172]],[[194586,194586],"mapped",[20908]],[[194587,194587],"mapped",[20917]],[[194588,194588],"mapped",[168415]],[[194589,194589],"mapped",[20981]],[[194590,194590],"mapped",[20995]],[[194591,194591],"mapped",[13535]],[[194592,194592],"mapped",[21051]],[[194593,194593],"mapped",[21062]],[[194594,194594],"mapped",[21106]],[[194595,194595],"mapped",[21111]],[[194596,194596],"mapped",[13589]],[[194597,194597],"mapped",[21191]],[[194598,194598],"mapped",[21193]],[[194599,194599],"mapped",[21220]],[[194600,194600],"mapped",[21242]],[[194601,194601],"mapped",[21253]],[[194602,194602],"mapped",[21254]],[[194603,194603],"mapped",[21271]],[[194604,194604],"mapped",[21321]],[[194605,194605],"mapped",[21329]],[[194606,194606],"mapped",[21338]],[[194607,194607],"mapped",[21363]],[[194608,194608],"mapped",[21373]],[[194609,194611],"mapped",[21375]],[[194612,194612],"mapped",[133676]],[[194613,194613],"mapped",[28784]],[[194614,194614],"mapped",[21450]],[[194615,194615],"mapped",[21471]],[[194616,194616],"mapped",[133987]],[[194617,194617],"mapped",[21483]],[[194618,194618],"mapped",[21489]],[[194619,194619],"mapped",[21510]],[[194620,194620],"mapped",[21662]],[[194621,194621],"mapped",[21560]],[[194622,194622],"mapped",[21576]],[[194623,194623],"mapped",[21608]],[[194624,194624],"mapped",[21666]],[[194625,194625],"mapped",[21750]],[[194626,194626],"mapped",[21776]],[[194627,194627],"mapped",[21843]],[[194628,194628],"mapped",[21859]],[[194629,194630],"mapped",[21892]],[[194631,194631],"mapped",[21913]],[[194632,194632],"mapped",[21931]],[[194633,194633],"mapped",[21939]],[[194634,194634],"mapped",[21954]],[[194635,194635],"mapped",[22294]],[[194636,194636],"mapped",[22022]],[[194637,194637],"mapped",[22295]],[[194638,194638],"mapped",[22097]],[[194639,194639],"mapped",[22132]],[[194640,194640],"mapped",[20999]],[[194641,194641],"mapped",[22766]],[[194642,194642],"mapped",[22478]],[[194643,194643],"mapped",[22516]],[[194644,194644],"mapped",[22541]],[[194645,194645],"mapped",[22411]],[[194646,194646],"mapped",[22578]],[[194647,194647],"mapped",[22577]],[[194648,194648],"mapped",[22700]],[[194649,194649],"mapped",[136420]],[[194650,194650],"mapped",[22770]],[[194651,194651],"mapped",[22775]],[[194652,194652],"mapped",[22790]],[[194653,194653],"mapped",[22810]],[[194654,194654],"mapped",[22818]],[[194655,194655],"mapped",[22882]],[[194656,194656],"mapped",[136872]],[[194657,194657],"mapped",[136938]],[[194658,194658],"mapped",[23020]],[[194659,194659],"mapped",[23067]],[[194660,194660],"mapped",[23079]],[[194661,194661],"mapped",[23000]],[[194662,194662],"mapped",[23142]],[[194663,194663],"mapped",[14062]],[[194664,194664],"disallowed"],[[194665,194665],"mapped",[23304]],[[194666,194667],"mapped",[23358]],[[194668,194668],"mapped",[137672]],[[194669,194669],"mapped",[23491]],[[194670,194670],"mapped",[23512]],[[194671,194671],"mapped",[23527]],[[194672,194672],"mapped",[23539]],[[194673,194673],"mapped",[138008]],[[194674,194674],"mapped",[23551]],[[194675,194675],"mapped",[23558]],[[194676,194676],"disallowed"],[[194677,194677],"mapped",[23586]],[[194678,194678],"mapped",[14209]],[[194679,194679],"mapped",[23648]],[[194680,194680],"mapped",[23662]],[[194681,194681],"mapped",[23744]],[[194682,194682],"mapped",[23693]],[[194683,194683],"mapped",[138724]],[[194684,194684],"mapped",[23875]],[[194685,194685],"mapped",[138726]],[[194686,194686],"mapped",[23918]],[[194687,194687],"mapped",[23915]],[[194688,194688],"mapped",[23932]],[[194689,194689],"mapped",[24033]],[[194690,194690],"mapped",[24034]],[[194691,194691],"mapped",[14383]],[[194692,194692],"mapped",[24061]],[[194693,194693],"mapped",[24104]],[[194694,194694],"mapped",[24125]],[[194695,194695],"mapped",[24169]],[[194696,194696],"mapped",[14434]],[[194697,194697],"mapped",[139651]],[[194698,194698],"mapped",[14460]],[[194699,194699],"mapped",[24240]],[[194700,194700],"mapped",[24243]],[[194701,194701],"mapped",[24246]],[[194702,194702],"mapped",[24266]],[[194703,194703],"mapped",[172946]],[[194704,194704],"mapped",[24318]],[[194705,194706],"mapped",[140081]],[[194707,194707],"mapped",[33281]],[[194708,194709],"mapped",[24354]],[[194710,194710],"mapped",[14535]],[[194711,194711],"mapped",[144056]],[[194712,194712],"mapped",[156122]],[[194713,194713],"mapped",[24418]],[[194714,194714],"mapped",[24427]],[[194715,194715],"mapped",[14563]],[[194716,194716],"mapped",[24474]],[[194717,194717],"mapped",[24525]],[[194718,194718],"mapped",[24535]],[[194719,194719],"mapped",[24569]],[[194720,194720],"mapped",[24705]],[[194721,194721],"mapped",[14650]],[[194722,194722],"mapped",[14620]],[[194723,194723],"mapped",[24724]],[[194724,194724],"mapped",[141012]],[[194725,194725],"mapped",[24775]],[[194726,194726],"mapped",[24904]],[[194727,194727],"mapped",[24908]],[[194728,194728],"mapped",[24910]],[[194729,194729],"mapped",[24908]],[[194730,194730],"mapped",[24954]],[[194731,194731],"mapped",[24974]],[[194732,194732],"mapped",[25010]],[[194733,194733],"mapped",[24996]],[[194734,194734],"mapped",[25007]],[[194735,194735],"mapped",[25054]],[[194736,194736],"mapped",[25074]],[[194737,194737],"mapped",[25078]],[[194738,194738],"mapped",[25104]],[[194739,194739],"mapped",[25115]],[[194740,194740],"mapped",[25181]],[[194741,194741],"mapped",[25265]],[[194742,194742],"mapped",[25300]],[[194743,194743],"mapped",[25424]],[[194744,194744],"mapped",[142092]],[[194745,194745],"mapped",[25405]],[[194746,194746],"mapped",[25340]],[[194747,194747],"mapped",[25448]],[[194748,194748],"mapped",[25475]],[[194749,194749],"mapped",[25572]],[[194750,194750],"mapped",[142321]],[[194751,194751],"mapped",[25634]],[[194752,194752],"mapped",[25541]],[[194753,194753],"mapped",[25513]],[[194754,194754],"mapped",[14894]],[[194755,194755],"mapped",[25705]],[[194756,194756],"mapped",[25726]],[[194757,194757],"mapped",[25757]],[[194758,194758],"mapped",[25719]],[[194759,194759],"mapped",[14956]],[[194760,194760],"mapped",[25935]],[[194761,194761],"mapped",[25964]],[[194762,194762],"mapped",[143370]],[[194763,194763],"mapped",[26083]],[[194764,194764],"mapped",[26360]],[[194765,194765],"mapped",[26185]],[[194766,194766],"mapped",[15129]],[[194767,194767],"mapped",[26257]],[[194768,194768],"mapped",[15112]],[[194769,194769],"mapped",[15076]],[[194770,194770],"mapped",[20882]],[[194771,194771],"mapped",[20885]],[[194772,194772],"mapped",[26368]],[[194773,194773],"mapped",[26268]],[[194774,194774],"mapped",[32941]],[[194775,194775],"mapped",[17369]],[[194776,194776],"mapped",[26391]],[[194777,194777],"mapped",[26395]],[[194778,194778],"mapped",[26401]],[[194779,194779],"mapped",[26462]],[[194780,194780],"mapped",[26451]],[[194781,194781],"mapped",[144323]],[[194782,194782],"mapped",[15177]],[[194783,194783],"mapped",[26618]],[[194784,194784],"mapped",[26501]],[[194785,194785],"mapped",[26706]],[[194786,194786],"mapped",[26757]],[[194787,194787],"mapped",[144493]],[[194788,194788],"mapped",[26766]],[[194789,194789],"mapped",[26655]],[[194790,194790],"mapped",[26900]],[[194791,194791],"mapped",[15261]],[[194792,194792],"mapped",[26946]],[[194793,194793],"mapped",[27043]],[[194794,194794],"mapped",[27114]],[[194795,194795],"mapped",[27304]],[[194796,194796],"mapped",[145059]],[[194797,194797],"mapped",[27355]],[[194798,194798],"mapped",[15384]],[[194799,194799],"mapped",[27425]],[[194800,194800],"mapped",[145575]],[[194801,194801],"mapped",[27476]],[[194802,194802],"mapped",[15438]],[[194803,194803],"mapped",[27506]],[[194804,194804],"mapped",[27551]],[[194805,194805],"mapped",[27578]],[[194806,194806],"mapped",[27579]],[[194807,194807],"mapped",[146061]],[[194808,194808],"mapped",[138507]],[[194809,194809],"mapped",[146170]],[[194810,194810],"mapped",[27726]],[[194811,194811],"mapped",[146620]],[[194812,194812],"mapped",[27839]],[[194813,194813],"mapped",[27853]],[[194814,194814],"mapped",[27751]],[[194815,194815],"mapped",[27926]],[[194816,194816],"mapped",[27966]],[[194817,194817],"mapped",[28023]],[[194818,194818],"mapped",[27969]],[[194819,194819],"mapped",[28009]],[[194820,194820],"mapped",[28024]],[[194821,194821],"mapped",[28037]],[[194822,194822],"mapped",[146718]],[[194823,194823],"mapped",[27956]],[[194824,194824],"mapped",[28207]],[[194825,194825],"mapped",[28270]],[[194826,194826],"mapped",[15667]],[[194827,194827],"mapped",[28363]],[[194828,194828],"mapped",[28359]],[[194829,194829],"mapped",[147153]],[[194830,194830],"mapped",[28153]],[[194831,194831],"mapped",[28526]],[[194832,194832],"mapped",[147294]],[[194833,194833],"mapped",[147342]],[[194834,194834],"mapped",[28614]],[[194835,194835],"mapped",[28729]],[[194836,194836],"mapped",[28702]],[[194837,194837],"mapped",[28699]],[[194838,194838],"mapped",[15766]],[[194839,194839],"mapped",[28746]],[[194840,194840],"mapped",[28797]],[[194841,194841],"mapped",[28791]],[[194842,194842],"mapped",[28845]],[[194843,194843],"mapped",[132389]],[[194844,194844],"mapped",[28997]],[[194845,194845],"mapped",[148067]],[[194846,194846],"mapped",[29084]],[[194847,194847],"disallowed"],[[194848,194848],"mapped",[29224]],[[194849,194849],"mapped",[29237]],[[194850,194850],"mapped",[29264]],[[194851,194851],"mapped",[149000]],[[194852,194852],"mapped",[29312]],[[194853,194853],"mapped",[29333]],[[194854,194854],"mapped",[149301]],[[194855,194855],"mapped",[149524]],[[194856,194856],"mapped",[29562]],[[194857,194857],"mapped",[29579]],[[194858,194858],"mapped",[16044]],[[194859,194859],"mapped",[29605]],[[194860,194861],"mapped",[16056]],[[194862,194862],"mapped",[29767]],[[194863,194863],"mapped",[29788]],[[194864,194864],"mapped",[29809]],[[194865,194865],"mapped",[29829]],[[194866,194866],"mapped",[29898]],[[194867,194867],"mapped",[16155]],[[194868,194868],"mapped",[29988]],[[194869,194869],"mapped",[150582]],[[194870,194870],"mapped",[30014]],[[194871,194871],"mapped",[150674]],[[194872,194872],"mapped",[30064]],[[194873,194873],"mapped",[139679]],[[194874,194874],"mapped",[30224]],[[194875,194875],"mapped",[151457]],[[194876,194876],"mapped",[151480]],[[194877,194877],"mapped",[151620]],[[194878,194878],"mapped",[16380]],[[194879,194879],"mapped",[16392]],[[194880,194880],"mapped",[30452]],[[194881,194881],"mapped",[151795]],[[194882,194882],"mapped",[151794]],[[194883,194883],"mapped",[151833]],[[194884,194884],"mapped",[151859]],[[194885,194885],"mapped",[30494]],[[194886,194887],"mapped",[30495]],[[194888,194888],"mapped",[30538]],[[194889,194889],"mapped",[16441]],[[194890,194890],"mapped",[30603]],[[194891,194891],"mapped",[16454]],[[194892,194892],"mapped",[16534]],[[194893,194893],"mapped",[152605]],[[194894,194894],"mapped",[30798]],[[194895,194895],"mapped",[30860]],[[194896,194896],"mapped",[30924]],[[194897,194897],"mapped",[16611]],[[194898,194898],"mapped",[153126]],[[194899,194899],"mapped",[31062]],[[194900,194900],"mapped",[153242]],[[194901,194901],"mapped",[153285]],[[194902,194902],"mapped",[31119]],[[194903,194903],"mapped",[31211]],[[194904,194904],"mapped",[16687]],[[194905,194905],"mapped",[31296]],[[194906,194906],"mapped",[31306]],[[194907,194907],"mapped",[31311]],[[194908,194908],"mapped",[153980]],[[194909,194910],"mapped",[154279]],[[194911,194911],"disallowed"],[[194912,194912],"mapped",[16898]],[[194913,194913],"mapped",[154539]],[[194914,194914],"mapped",[31686]],[[194915,194915],"mapped",[31689]],[[194916,194916],"mapped",[16935]],[[194917,194917],"mapped",[154752]],[[194918,194918],"mapped",[31954]],[[194919,194919],"mapped",[17056]],[[194920,194920],"mapped",[31976]],[[194921,194921],"mapped",[31971]],[[194922,194922],"mapped",[32000]],[[194923,194923],"mapped",[155526]],[[194924,194924],"mapped",[32099]],[[194925,194925],"mapped",[17153]],[[194926,194926],"mapped",[32199]],[[194927,194927],"mapped",[32258]],[[194928,194928],"mapped",[32325]],[[194929,194929],"mapped",[17204]],[[194930,194930],"mapped",[156200]],[[194931,194931],"mapped",[156231]],[[194932,194932],"mapped",[17241]],[[194933,194933],"mapped",[156377]],[[194934,194934],"mapped",[32634]],[[194935,194935],"mapped",[156478]],[[194936,194936],"mapped",[32661]],[[194937,194937],"mapped",[32762]],[[194938,194938],"mapped",[32773]],[[194939,194939],"mapped",[156890]],[[194940,194940],"mapped",[156963]],[[194941,194941],"mapped",[32864]],[[194942,194942],"mapped",[157096]],[[194943,194943],"mapped",[32880]],[[194944,194944],"mapped",[144223]],[[194945,194945],"mapped",[17365]],[[194946,194946],"mapped",[32946]],[[194947,194947],"mapped",[33027]],[[194948,194948],"mapped",[17419]],[[194949,194949],"mapped",[33086]],[[194950,194950],"mapped",[23221]],[[194951,194951],"mapped",[157607]],[[194952,194952],"mapped",[157621]],[[194953,194953],"mapped",[144275]],[[194954,194954],"mapped",[144284]],[[194955,194955],"mapped",[33281]],[[194956,194956],"mapped",[33284]],[[194957,194957],"mapped",[36766]],[[194958,194958],"mapped",[17515]],[[194959,194959],"mapped",[33425]],[[194960,194960],"mapped",[33419]],[[194961,194961],"mapped",[33437]],[[194962,194962],"mapped",[21171]],[[194963,194963],"mapped",[33457]],[[194964,194964],"mapped",[33459]],[[194965,194965],"mapped",[33469]],[[194966,194966],"mapped",[33510]],[[194967,194967],"mapped",[158524]],[[194968,194968],"mapped",[33509]],[[194969,194969],"mapped",[33565]],[[194970,194970],"mapped",[33635]],[[194971,194971],"mapped",[33709]],[[194972,194972],"mapped",[33571]],[[194973,194973],"mapped",[33725]],[[194974,194974],"mapped",[33767]],[[194975,194975],"mapped",[33879]],[[194976,194976],"mapped",[33619]],[[194977,194977],"mapped",[33738]],[[194978,194978],"mapped",[33740]],[[194979,194979],"mapped",[33756]],[[194980,194980],"mapped",[158774]],[[194981,194981],"mapped",[159083]],[[194982,194982],"mapped",[158933]],[[194983,194983],"mapped",[17707]],[[194984,194984],"mapped",[34033]],[[194985,194985],"mapped",[34035]],[[194986,194986],"mapped",[34070]],[[194987,194987],"mapped",[160714]],[[194988,194988],"mapped",[34148]],[[194989,194989],"mapped",[159532]],[[194990,194990],"mapped",[17757]],[[194991,194991],"mapped",[17761]],[[194992,194992],"mapped",[159665]],[[194993,194993],"mapped",[159954]],[[194994,194994],"mapped",[17771]],[[194995,194995],"mapped",[34384]],[[194996,194996],"mapped",[34396]],[[194997,194997],"mapped",[34407]],[[194998,194998],"mapped",[34409]],[[194999,194999],"mapped",[34473]],[[195000,195000],"mapped",[34440]],[[195001,195001],"mapped",[34574]],[[195002,195002],"mapped",[34530]],[[195003,195003],"mapped",[34681]],[[195004,195004],"mapped",[34600]],[[195005,195005],"mapped",[34667]],[[195006,195006],"mapped",[34694]],[[195007,195007],"disallowed"],[[195008,195008],"mapped",[34785]],[[195009,195009],"mapped",[34817]],[[195010,195010],"mapped",[17913]],[[195011,195011],"mapped",[34912]],[[195012,195012],"mapped",[34915]],[[195013,195013],"mapped",[161383]],[[195014,195014],"mapped",[35031]],[[195015,195015],"mapped",[35038]],[[195016,195016],"mapped",[17973]],[[195017,195017],"mapped",[35066]],[[195018,195018],"mapped",[13499]],[[195019,195019],"mapped",[161966]],[[195020,195020],"mapped",[162150]],[[195021,195021],"mapped",[18110]],[[195022,195022],"mapped",[18119]],[[195023,195023],"mapped",[35488]],[[195024,195024],"mapped",[35565]],[[195025,195025],"mapped",[35722]],[[195026,195026],"mapped",[35925]],[[195027,195027],"mapped",[162984]],[[195028,195028],"mapped",[36011]],[[195029,195029],"mapped",[36033]],[[195030,195030],"mapped",[36123]],[[195031,195031],"mapped",[36215]],[[195032,195032],"mapped",[163631]],[[195033,195033],"mapped",[133124]],[[195034,195034],"mapped",[36299]],[[195035,195035],"mapped",[36284]],[[195036,195036],"mapped",[36336]],[[195037,195037],"mapped",[133342]],[[195038,195038],"mapped",[36564]],[[195039,195039],"mapped",[36664]],[[195040,195040],"mapped",[165330]],[[195041,195041],"mapped",[165357]],[[195042,195042],"mapped",[37012]],[[195043,195043],"mapped",[37105]],[[195044,195044],"mapped",[37137]],[[195045,195045],"mapped",[165678]],[[195046,195046],"mapped",[37147]],[[195047,195047],"mapped",[37432]],[[195048,195048],"mapped",[37591]],[[195049,195049],"mapped",[37592]],[[195050,195050],"mapped",[37500]],[[195051,195051],"mapped",[37881]],[[195052,195052],"mapped",[37909]],[[195053,195053],"mapped",[166906]],[[195054,195054],"mapped",[38283]],[[195055,195055],"mapped",[18837]],[[195056,195056],"mapped",[38327]],[[195057,195057],"mapped",[167287]],[[195058,195058],"mapped",[18918]],[[195059,195059],"mapped",[38595]],[[195060,195060],"mapped",[23986]],[[195061,195061],"mapped",[38691]],[[195062,195062],"mapped",[168261]],[[195063,195063],"mapped",[168474]],[[195064,195064],"mapped",[19054]],[[195065,195065],"mapped",[19062]],[[195066,195066],"mapped",[38880]],[[195067,195067],"mapped",[168970]],[[195068,195068],"mapped",[19122]],[[195069,195069],"mapped",[169110]],[[195070,195071],"mapped",[38923]],[[195072,195072],"mapped",[38953]],[[195073,195073],"mapped",[169398]],[[195074,195074],"mapped",[39138]],[[195075,195075],"mapped",[19251]],[[195076,195076],"mapped",[39209]],[[195077,195077],"mapped",[39335]],[[195078,195078],"mapped",[39362]],[[195079,195079],"mapped",[39422]],[[195080,195080],"mapped",[19406]],[[195081,195081],"mapped",[170800]],[[195082,195082],"mapped",[39698]],[[195083,195083],"mapped",[40000]],[[195084,195084],"mapped",[40189]],[[195085,195085],"mapped",[19662]],[[195086,195086],"mapped",[19693]],[[195087,195087],"mapped",[40295]],[[195088,195088],"mapped",[172238]],[[195089,195089],"mapped",[19704]],[[195090,195090],"mapped",[172293]],[[195091,195091],"mapped",[172558]],[[195092,195092],"mapped",[172689]],[[195093,195093],"mapped",[40635]],[[195094,195094],"mapped",[19798]],[[195095,195095],"mapped",[40697]],[[195096,195096],"mapped",[40702]],[[195097,195097],"mapped",[40709]],[[195098,195098],"mapped",[40719]],[[195099,195099],"mapped",[40726]],[[195100,195100],"mapped",[40763]],[[195101,195101],"mapped",[173568]],[[195102,196605],"disallowed"],[[196606,196607],"disallowed"],[[196608,262141],"disallowed"],[[262142,262143],"disallowed"],[[262144,327677],"disallowed"],[[327678,327679],"disallowed"],[[327680,393213],"disallowed"],[[393214,393215],"disallowed"],[[393216,458749],"disallowed"],[[458750,458751],"disallowed"],[[458752,524285],"disallowed"],[[524286,524287],"disallowed"],[[524288,589821],"disallowed"],[[589822,589823],"disallowed"],[[589824,655357],"disallowed"],[[655358,655359],"disallowed"],[[655360,720893],"disallowed"],[[720894,720895],"disallowed"],[[720896,786429],"disallowed"],[[786430,786431],"disallowed"],[[786432,851965],"disallowed"],[[851966,851967],"disallowed"],[[851968,917501],"disallowed"],[[917502,917503],"disallowed"],[[917504,917504],"disallowed"],[[917505,917505],"disallowed"],[[917506,917535],"disallowed"],[[917536,917631],"disallowed"],[[917632,917759],"disallowed"],[[917760,917999],"ignored"],[[918000,983037],"disallowed"],[[983038,983039],"disallowed"],[[983040,1048573],"disallowed"],[[1048574,1048575],"disallowed"],[[1048576,1114109],"disallowed"],[[1114110,1114111],"disallowed"]] \ No newline at end of file diff --git a/node_modules/tr46/package.json b/node_modules/tr46/package.json new file mode 100644 index 00000000..b6826da1 --- /dev/null +++ b/node_modules/tr46/package.json @@ -0,0 +1,31 @@ +{ + "name": "tr46", + "version": "0.0.3", + "description": "An implementation of the Unicode TR46 spec", + "main": "index.js", + "scripts": { + "test": "mocha", + "pretest": "node scripts/getLatestUnicodeTests.js", + "prepublish": "node scripts/generateMappingTable.js" + }, + "repository": { + "type": "git", + "url": "git+https://github.com/Sebmaster/tr46.js.git" + }, + "keywords": [ + "unicode", + "tr46", + "url", + "whatwg" + ], + "author": "Sebastian Mayr ", + "license": "MIT", + "bugs": { + "url": "https://github.com/Sebmaster/tr46.js/issues" + }, + "homepage": "https://github.com/Sebmaster/tr46.js#readme", + "devDependencies": { + "mocha": "^2.2.5", + "request": "^2.57.0" + } +} diff --git a/node_modules/webidl-conversions/LICENSE.md b/node_modules/webidl-conversions/LICENSE.md new file mode 100644 index 00000000..d4a994f5 --- /dev/null +++ b/node_modules/webidl-conversions/LICENSE.md @@ -0,0 +1,12 @@ +# The BSD 2-Clause License + +Copyright (c) 2014, Domenic Denicola +All rights reserved. + +Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: + +1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. + +2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/node_modules/webidl-conversions/README.md b/node_modules/webidl-conversions/README.md new file mode 100644 index 00000000..3657890a --- /dev/null +++ b/node_modules/webidl-conversions/README.md @@ -0,0 +1,53 @@ +# WebIDL Type Conversions on JavaScript Values + +This package implements, in JavaScript, the algorithms to convert a given JavaScript value according to a given [WebIDL](http://heycam.github.io/webidl/) [type](http://heycam.github.io/webidl/#idl-types). + +The goal is that you should be able to write code like + +```js +const conversions = require("webidl-conversions"); + +function doStuff(x, y) { + x = conversions["boolean"](x); + y = conversions["unsigned long"](y); + // actual algorithm code here +} +``` + +and your function `doStuff` will behave the same as a WebIDL operation declared as + +```webidl +void doStuff(boolean x, unsigned long y); +``` + +## API + +This package's main module's default export is an object with a variety of methods, each corresponding to a different WebIDL type. Each method, when invoked on a JavaScript value, will give back the new JavaScript value that results after passing through the WebIDL conversion rules. (See below for more details on what that means.) Alternately, the method could throw an error, if the WebIDL algorithm is specified to do so: for example `conversions["float"](NaN)` [will throw a `TypeError`](http://heycam.github.io/webidl/#es-float). + +## Status + +All of the numeric types are implemented (float being implemented as double) and some others are as well - check the source for all of them. This list will grow over time in service of the [HTML as Custom Elements](https://github.com/dglazkov/html-as-custom-elements) project, but in the meantime, pull requests welcome! + +I'm not sure yet what the strategy will be for modifiers, e.g. [`[Clamp]`](http://heycam.github.io/webidl/#Clamp). Maybe something like `conversions["unsigned long"](x, { clamp: true })`? We'll see. + +We might also want to extend the API to give better error messages, e.g. "Argument 1 of HTMLMediaElement.fastSeek is not a finite floating-point value" instead of "Argument is not a finite floating-point value." This would require passing in more information to the conversion functions than we currently do. + +## Background + +What's actually going on here, conceptually, is pretty weird. Let's try to explain. + +WebIDL, as part of its madness-inducing design, has its own type system. When people write algorithms in web platform specs, they usually operate on WebIDL values, i.e. instances of WebIDL types. For example, if they were specifying the algorithm for our `doStuff` operation above, they would treat `x` as a WebIDL value of [WebIDL type `boolean`](http://heycam.github.io/webidl/#idl-boolean). Crucially, they would _not_ treat `x` as a JavaScript variable whose value is either the JavaScript `true` or `false`. They're instead working in a different type system altogether, with its own rules. + +Separately from its type system, WebIDL defines a ["binding"](http://heycam.github.io/webidl/#ecmascript-binding) of the type system into JavaScript. This contains rules like: when you pass a JavaScript value to the JavaScript method that manifests a given WebIDL operation, how does that get converted into a WebIDL value? For example, a JavaScript `true` passed in the position of a WebIDL `boolean` argument becomes a WebIDL `true`. But, a JavaScript `true` passed in the position of a [WebIDL `unsigned long`](http://heycam.github.io/webidl/#idl-unsigned-long) becomes a WebIDL `1`. And so on. + +Finally, we have the actual implementation code. This is usually C++, although these days [some smart people are using Rust](https://github.com/servo/servo). The implementation, of course, has its own type system. So when they implement the WebIDL algorithms, they don't actually use WebIDL values, since those aren't "real" outside of specs. Instead, implementations apply the WebIDL binding rules in such a way as to convert incoming JavaScript values into C++ values. For example, if code in the browser called `doStuff(true, true)`, then the implementation code would eventually receive a C++ `bool` containing `true` and a C++ `uint32_t` containing `1`. + +The upside of all this is that implementations can abstract all the conversion logic away, letting WebIDL handle it, and focus on implementing the relevant methods in C++ with values of the correct type already provided. That is payoff of WebIDL, in a nutshell. + +And getting to that payoff is the goal of _this_ project—but for JavaScript implementations, instead of C++ ones. That is, this library is designed to make it easier for JavaScript developers to write functions that behave like a given WebIDL operation. So conceptually, the conversion pipeline, which in its general form is JavaScript values ↦ WebIDL values ↦ implementation-language values, in this case becomes JavaScript values ↦ WebIDL values ↦ JavaScript values. And that intermediate step is where all the logic is performed: a JavaScript `true` becomes a WebIDL `1` in an unsigned long context, which then becomes a JavaScript `1`. + +## Don't Use This + +Seriously, why would you ever use this? You really shouldn't. WebIDL is … not great, and you shouldn't be emulating its semantics. If you're looking for a generic argument-processing library, you should find one with better rules than those from WebIDL. In general, your JavaScript should not be trying to become more like WebIDL; if anything, we should fix WebIDL to make it more like JavaScript. + +The _only_ people who should use this are those trying to create faithful implementations (or polyfills) of web platform interfaces defined in WebIDL. diff --git a/node_modules/webidl-conversions/lib/index.js b/node_modules/webidl-conversions/lib/index.js new file mode 100644 index 00000000..c5153a3a --- /dev/null +++ b/node_modules/webidl-conversions/lib/index.js @@ -0,0 +1,189 @@ +"use strict"; + +var conversions = {}; +module.exports = conversions; + +function sign(x) { + return x < 0 ? -1 : 1; +} + +function evenRound(x) { + // Round x to the nearest integer, choosing the even integer if it lies halfway between two. + if ((x % 1) === 0.5 && (x & 1) === 0) { // [even number].5; round down (i.e. floor) + return Math.floor(x); + } else { + return Math.round(x); + } +} + +function createNumberConversion(bitLength, typeOpts) { + if (!typeOpts.unsigned) { + --bitLength; + } + const lowerBound = typeOpts.unsigned ? 0 : -Math.pow(2, bitLength); + const upperBound = Math.pow(2, bitLength) - 1; + + const moduloVal = typeOpts.moduloBitLength ? Math.pow(2, typeOpts.moduloBitLength) : Math.pow(2, bitLength); + const moduloBound = typeOpts.moduloBitLength ? Math.pow(2, typeOpts.moduloBitLength - 1) : Math.pow(2, bitLength - 1); + + return function(V, opts) { + if (!opts) opts = {}; + + let x = +V; + + if (opts.enforceRange) { + if (!Number.isFinite(x)) { + throw new TypeError("Argument is not a finite number"); + } + + x = sign(x) * Math.floor(Math.abs(x)); + if (x < lowerBound || x > upperBound) { + throw new TypeError("Argument is not in byte range"); + } + + return x; + } + + if (!isNaN(x) && opts.clamp) { + x = evenRound(x); + + if (x < lowerBound) x = lowerBound; + if (x > upperBound) x = upperBound; + return x; + } + + if (!Number.isFinite(x) || x === 0) { + return 0; + } + + x = sign(x) * Math.floor(Math.abs(x)); + x = x % moduloVal; + + if (!typeOpts.unsigned && x >= moduloBound) { + return x - moduloVal; + } else if (typeOpts.unsigned) { + if (x < 0) { + x += moduloVal; + } else if (x === -0) { // don't return negative zero + return 0; + } + } + + return x; + } +} + +conversions["void"] = function () { + return undefined; +}; + +conversions["boolean"] = function (val) { + return !!val; +}; + +conversions["byte"] = createNumberConversion(8, { unsigned: false }); +conversions["octet"] = createNumberConversion(8, { unsigned: true }); + +conversions["short"] = createNumberConversion(16, { unsigned: false }); +conversions["unsigned short"] = createNumberConversion(16, { unsigned: true }); + +conversions["long"] = createNumberConversion(32, { unsigned: false }); +conversions["unsigned long"] = createNumberConversion(32, { unsigned: true }); + +conversions["long long"] = createNumberConversion(32, { unsigned: false, moduloBitLength: 64 }); +conversions["unsigned long long"] = createNumberConversion(32, { unsigned: true, moduloBitLength: 64 }); + +conversions["double"] = function (V) { + const x = +V; + + if (!Number.isFinite(x)) { + throw new TypeError("Argument is not a finite floating-point value"); + } + + return x; +}; + +conversions["unrestricted double"] = function (V) { + const x = +V; + + if (isNaN(x)) { + throw new TypeError("Argument is NaN"); + } + + return x; +}; + +// not quite valid, but good enough for JS +conversions["float"] = conversions["double"]; +conversions["unrestricted float"] = conversions["unrestricted double"]; + +conversions["DOMString"] = function (V, opts) { + if (!opts) opts = {}; + + if (opts.treatNullAsEmptyString && V === null) { + return ""; + } + + return String(V); +}; + +conversions["ByteString"] = function (V, opts) { + const x = String(V); + let c = undefined; + for (let i = 0; (c = x.codePointAt(i)) !== undefined; ++i) { + if (c > 255) { + throw new TypeError("Argument is not a valid bytestring"); + } + } + + return x; +}; + +conversions["USVString"] = function (V) { + const S = String(V); + const n = S.length; + const U = []; + for (let i = 0; i < n; ++i) { + const c = S.charCodeAt(i); + if (c < 0xD800 || c > 0xDFFF) { + U.push(String.fromCodePoint(c)); + } else if (0xDC00 <= c && c <= 0xDFFF) { + U.push(String.fromCodePoint(0xFFFD)); + } else { + if (i === n - 1) { + U.push(String.fromCodePoint(0xFFFD)); + } else { + const d = S.charCodeAt(i + 1); + if (0xDC00 <= d && d <= 0xDFFF) { + const a = c & 0x3FF; + const b = d & 0x3FF; + U.push(String.fromCodePoint((2 << 15) + (2 << 9) * a + b)); + ++i; + } else { + U.push(String.fromCodePoint(0xFFFD)); + } + } + } + } + + return U.join(''); +}; + +conversions["Date"] = function (V, opts) { + if (!(V instanceof Date)) { + throw new TypeError("Argument is not a Date object"); + } + if (isNaN(V)) { + return undefined; + } + + return V; +}; + +conversions["RegExp"] = function (V, opts) { + if (!(V instanceof RegExp)) { + V = new RegExp(V); + } + + return V; +}; diff --git a/node_modules/webidl-conversions/package.json b/node_modules/webidl-conversions/package.json new file mode 100644 index 00000000..c31bc074 --- /dev/null +++ b/node_modules/webidl-conversions/package.json @@ -0,0 +1,23 @@ +{ + "name": "webidl-conversions", + "version": "3.0.1", + "description": "Implements the WebIDL algorithms for converting to and from JavaScript values", + "main": "lib/index.js", + "scripts": { + "test": "mocha test/*.js" + }, + "repository": "jsdom/webidl-conversions", + "keywords": [ + "webidl", + "web", + "types" + ], + "files": [ + "lib/" + ], + "author": "Domenic Denicola (https://domenic.me/)", + "license": "BSD-2-Clause", + "devDependencies": { + "mocha": "^1.21.4" + } +} diff --git a/node_modules/whatwg-url/LICENSE.txt b/node_modules/whatwg-url/LICENSE.txt new file mode 100644 index 00000000..54dfac39 --- /dev/null +++ b/node_modules/whatwg-url/LICENSE.txt @@ -0,0 +1,21 @@ +The MIT License (MIT) + +Copyright (c) 2015–2016 Sebastian Mayr + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. diff --git a/node_modules/whatwg-url/README.md b/node_modules/whatwg-url/README.md new file mode 100644 index 00000000..4347a7fc --- /dev/null +++ b/node_modules/whatwg-url/README.md @@ -0,0 +1,67 @@ +# whatwg-url + +whatwg-url is a full implementation of the WHATWG [URL Standard](https://url.spec.whatwg.org/). It can be used standalone, but it also exposes a lot of the internal algorithms that are useful for integrating a URL parser into a project like [jsdom](https://github.com/tmpvar/jsdom). + +## Current Status + +whatwg-url is currently up to date with the URL spec up to commit [a62223](https://github.com/whatwg/url/commit/a622235308342c9adc7fc2fd1659ff059f7d5e2a). + +## API + +### The `URL` Constructor + +The main API is the [`URL`](https://url.spec.whatwg.org/#url) export, which follows the spec's behavior in all ways (including e.g. `USVString` conversion). Most consumers of this library will want to use this. + +### Low-level URL Standard API + +The following methods are exported for use by places like jsdom that need to implement things like [`HTMLHyperlinkElementUtils`](https://html.spec.whatwg.org/#htmlhyperlinkelementutils). They operate on or return an "internal URL" or ["URL record"](https://url.spec.whatwg.org/#concept-url) type. + +- [URL parser](https://url.spec.whatwg.org/#concept-url-parser): `parseURL(input, { baseURL, encodingOverride })` +- [Basic URL parser](https://url.spec.whatwg.org/#concept-basic-url-parser): `basicURLParse(input, { baseURL, encodingOverride, url, stateOverride })` +- [URL serializer](https://url.spec.whatwg.org/#concept-url-serializer): `serializeURL(urlRecord, excludeFragment)` +- [Host serializer](https://url.spec.whatwg.org/#concept-host-serializer): `serializeHost(hostFromURLRecord)` +- [Serialize an integer](https://url.spec.whatwg.org/#serialize-an-integer): `serializeInteger(number)` +- [Origin](https://url.spec.whatwg.org/#concept-url-origin) [serializer](https://html.spec.whatwg.org/multipage/browsers.html#serialization-of-an-origin): `serializeURLOrigin(urlRecord)` +- [Set the username](https://url.spec.whatwg.org/#set-the-username): `setTheUsername(urlRecord, usernameString)` +- [Set the password](https://url.spec.whatwg.org/#set-the-password): `setThePassword(urlRecord, passwordString)` +- [Cannot have a username/password/port](https://url.spec.whatwg.org/#cannot-have-a-username-password-port): `cannotHaveAUsernamePasswordPort(urlRecord)` + +The `stateOverride` parameter is one of the following strings: + +- [`"scheme start"`](https://url.spec.whatwg.org/#scheme-start-state) +- [`"scheme"`](https://url.spec.whatwg.org/#scheme-state) +- [`"no scheme"`](https://url.spec.whatwg.org/#no-scheme-state) +- [`"special relative or authority"`](https://url.spec.whatwg.org/#special-relative-or-authority-state) +- [`"path or authority"`](https://url.spec.whatwg.org/#path-or-authority-state) +- [`"relative"`](https://url.spec.whatwg.org/#relative-state) +- [`"relative slash"`](https://url.spec.whatwg.org/#relative-slash-state) +- [`"special authority slashes"`](https://url.spec.whatwg.org/#special-authority-slashes-state) +- [`"special authority ignore slashes"`](https://url.spec.whatwg.org/#special-authority-ignore-slashes-state) +- [`"authority"`](https://url.spec.whatwg.org/#authority-state) +- [`"host"`](https://url.spec.whatwg.org/#host-state) +- [`"hostname"`](https://url.spec.whatwg.org/#hostname-state) +- [`"port"`](https://url.spec.whatwg.org/#port-state) +- [`"file"`](https://url.spec.whatwg.org/#file-state) +- [`"file slash"`](https://url.spec.whatwg.org/#file-slash-state) +- [`"file host"`](https://url.spec.whatwg.org/#file-host-state) +- [`"path start"`](https://url.spec.whatwg.org/#path-start-state) +- [`"path"`](https://url.spec.whatwg.org/#path-state) +- [`"cannot-be-a-base-URL path"`](https://url.spec.whatwg.org/#cannot-be-a-base-url-path-state) +- [`"query"`](https://url.spec.whatwg.org/#query-state) +- [`"fragment"`](https://url.spec.whatwg.org/#fragment-state) + +The URL record type has the following API: + +- [`scheme`](https://url.spec.whatwg.org/#concept-url-scheme) +- [`username`](https://url.spec.whatwg.org/#concept-url-username) +- [`password`](https://url.spec.whatwg.org/#concept-url-password) +- [`host`](https://url.spec.whatwg.org/#concept-url-host) +- [`port`](https://url.spec.whatwg.org/#concept-url-port) +- [`path`](https://url.spec.whatwg.org/#concept-url-path) (as an array) +- [`query`](https://url.spec.whatwg.org/#concept-url-query) +- [`fragment`](https://url.spec.whatwg.org/#concept-url-fragment) +- [`cannotBeABaseURL`](https://url.spec.whatwg.org/#url-cannot-be-a-base-url-flag) (as a boolean) + +These properties should be treated with care, as in general changing them will cause the URL record to be in an inconsistent state until the appropriate invocation of `basicURLParse` is used to fix it up. You can see examples of this in the URL Standard, where there are many step sequences like "4. Set context object’s url’s fragment to the empty string. 5. Basic URL parse _input_ with context object’s url as _url_ and fragment state as _state override_." In between those two steps, a URL record is in an unusable state. + +The return value of "failure" in the spec is represented by the string `"failure"`. That is, functions like `parseURL` and `basicURLParse` can return _either_ a URL record _or_ the string `"failure"`. diff --git a/node_modules/whatwg-url/lib/URL-impl.js b/node_modules/whatwg-url/lib/URL-impl.js new file mode 100644 index 00000000..dc7452cc --- /dev/null +++ b/node_modules/whatwg-url/lib/URL-impl.js @@ -0,0 +1,200 @@ +"use strict"; +const usm = require("./url-state-machine"); + +exports.implementation = class URLImpl { + constructor(constructorArgs) { + const url = constructorArgs[0]; + const base = constructorArgs[1]; + + let parsedBase = null; + if (base !== undefined) { + parsedBase = usm.basicURLParse(base); + if (parsedBase === "failure") { + throw new TypeError("Invalid base URL"); + } + } + + const parsedURL = usm.basicURLParse(url, { baseURL: parsedBase }); + if (parsedURL === "failure") { + throw new TypeError("Invalid URL"); + } + + this._url = parsedURL; + + // TODO: query stuff + } + + get href() { + return usm.serializeURL(this._url); + } + + set href(v) { + const parsedURL = usm.basicURLParse(v); + if (parsedURL === "failure") { + throw new TypeError("Invalid URL"); + } + + this._url = parsedURL; + } + + get origin() { + return usm.serializeURLOrigin(this._url); + } + + get protocol() { + return this._url.scheme + ":"; + } + + set protocol(v) { + usm.basicURLParse(v + ":", { url: this._url, stateOverride: "scheme start" }); + } + + get username() { + return this._url.username; + } + + set username(v) { + if (usm.cannotHaveAUsernamePasswordPort(this._url)) { + return; + } + + usm.setTheUsername(this._url, v); + } + + get password() { + return this._url.password; + } + + set password(v) { + if (usm.cannotHaveAUsernamePasswordPort(this._url)) { + return; + } + + usm.setThePassword(this._url, v); + } + + get host() { + const url = this._url; + + if (url.host === null) { + return ""; + } + + if (url.port === null) { + return usm.serializeHost(url.host); + } + + return usm.serializeHost(url.host) + ":" + usm.serializeInteger(url.port); + } + + set host(v) { + if (this._url.cannotBeABaseURL) { + return; + } + + usm.basicURLParse(v, { url: this._url, stateOverride: "host" }); + } + + get hostname() { + if (this._url.host === null) { + return ""; + } + + return usm.serializeHost(this._url.host); + } + + set hostname(v) { + if (this._url.cannotBeABaseURL) { + return; + } + + usm.basicURLParse(v, { url: this._url, stateOverride: "hostname" }); + } + + get port() { + if (this._url.port === null) { + return ""; + } + + return usm.serializeInteger(this._url.port); + } + + set port(v) { + if (usm.cannotHaveAUsernamePasswordPort(this._url)) { + return; + } + + if (v === "") { + this._url.port = null; + } else { + usm.basicURLParse(v, { url: this._url, stateOverride: "port" }); + } + } + + get pathname() { + if (this._url.cannotBeABaseURL) { + return this._url.path[0]; + } + + if (this._url.path.length === 0) { + return ""; + } + + return "/" + this._url.path.join("/"); + } + + set pathname(v) { + if (this._url.cannotBeABaseURL) { + return; + } + + this._url.path = []; + usm.basicURLParse(v, { url: this._url, stateOverride: "path start" }); + } + + get search() { + if (this._url.query === null || this._url.query === "") { + return ""; + } + + return "?" + this._url.query; + } + + set search(v) { + // TODO: query stuff + + const url = this._url; + + if (v === "") { + url.query = null; + return; + } + + const input = v[0] === "?" ? v.substring(1) : v; + url.query = ""; + usm.basicURLParse(input, { url, stateOverride: "query" }); + } + + get hash() { + if (this._url.fragment === null || this._url.fragment === "") { + return ""; + } + + return "#" + this._url.fragment; + } + + set hash(v) { + if (v === "") { + this._url.fragment = null; + return; + } + + const input = v[0] === "#" ? v.substring(1) : v; + this._url.fragment = ""; + usm.basicURLParse(input, { url: this._url, stateOverride: "fragment" }); + } + + toJSON() { + return this.href; + } +}; diff --git a/node_modules/whatwg-url/lib/URL.js b/node_modules/whatwg-url/lib/URL.js new file mode 100644 index 00000000..78c7207e --- /dev/null +++ b/node_modules/whatwg-url/lib/URL.js @@ -0,0 +1,196 @@ +"use strict"; + +const conversions = require("webidl-conversions"); +const utils = require("./utils.js"); +const Impl = require(".//URL-impl.js"); + +const impl = utils.implSymbol; + +function URL(url) { + if (!this || this[impl] || !(this instanceof URL)) { + throw new TypeError("Failed to construct 'URL': Please use the 'new' operator, this DOM object constructor cannot be called as a function."); + } + if (arguments.length < 1) { + throw new TypeError("Failed to construct 'URL': 1 argument required, but only " + arguments.length + " present."); + } + const args = []; + for (let i = 0; i < arguments.length && i < 2; ++i) { + args[i] = arguments[i]; + } + args[0] = conversions["USVString"](args[0]); + if (args[1] !== undefined) { + args[1] = conversions["USVString"](args[1]); + } + + module.exports.setup(this, args); +} + +URL.prototype.toJSON = function toJSON() { + if (!this || !module.exports.is(this)) { + throw new TypeError("Illegal invocation"); + } + const args = []; + for (let i = 0; i < arguments.length && i < 0; ++i) { + args[i] = arguments[i]; + } + return this[impl].toJSON.apply(this[impl], args); +}; +Object.defineProperty(URL.prototype, "href", { + get() { + return this[impl].href; + }, + set(V) { + V = conversions["USVString"](V); + this[impl].href = V; + }, + enumerable: true, + configurable: true +}); + +URL.prototype.toString = function () { + if (!this || !module.exports.is(this)) { + throw new TypeError("Illegal invocation"); + } + return this.href; +}; + +Object.defineProperty(URL.prototype, "origin", { + get() { + return this[impl].origin; + }, + enumerable: true, + configurable: true +}); + +Object.defineProperty(URL.prototype, "protocol", { + get() { + return this[impl].protocol; + }, + set(V) { + V = conversions["USVString"](V); + this[impl].protocol = V; + }, + enumerable: true, + configurable: true +}); + +Object.defineProperty(URL.prototype, "username", { + get() { + return this[impl].username; + }, + set(V) { + V = conversions["USVString"](V); + this[impl].username = V; + }, + enumerable: true, + configurable: true +}); + +Object.defineProperty(URL.prototype, "password", { + get() { + return this[impl].password; + }, + set(V) { + V = conversions["USVString"](V); + this[impl].password = V; + }, + enumerable: true, + configurable: true +}); + +Object.defineProperty(URL.prototype, "host", { + get() { + return this[impl].host; + }, + set(V) { + V = conversions["USVString"](V); + this[impl].host = V; + }, + enumerable: true, + configurable: true +}); + +Object.defineProperty(URL.prototype, "hostname", { + get() { + return this[impl].hostname; + }, + set(V) { + V = conversions["USVString"](V); + this[impl].hostname = V; + }, + enumerable: true, + configurable: true +}); + +Object.defineProperty(URL.prototype, "port", { + get() { + return this[impl].port; + }, + set(V) { + V = conversions["USVString"](V); + this[impl].port = V; + }, + enumerable: true, + configurable: true +}); + +Object.defineProperty(URL.prototype, "pathname", { + get() { + return this[impl].pathname; + }, + set(V) { + V = conversions["USVString"](V); + this[impl].pathname = V; + }, + enumerable: true, + configurable: true +}); + +Object.defineProperty(URL.prototype, "search", { + get() { + return this[impl].search; + }, + set(V) { + V = conversions["USVString"](V); + this[impl].search = V; + }, + enumerable: true, + configurable: true +}); + +Object.defineProperty(URL.prototype, "hash", { + get() { + return this[impl].hash; + }, + set(V) { + V = conversions["USVString"](V); + this[impl].hash = V; + }, + enumerable: true, + configurable: true +}); + + +module.exports = { + is(obj) { + return !!obj && obj[impl] instanceof Impl.implementation; + }, + create(constructorArgs, privateData) { + let obj = Object.create(URL.prototype); + this.setup(obj, constructorArgs, privateData); + return obj; + }, + setup(obj, constructorArgs, privateData) { + if (!privateData) privateData = {}; + privateData.wrapper = obj; + + obj[impl] = new Impl.implementation(constructorArgs, privateData); + obj[impl][utils.wrapperSymbol] = obj; + }, + interface: URL, + expose: { + Window: { URL: URL }, + Worker: { URL: URL } + } +}; + diff --git a/node_modules/whatwg-url/lib/public-api.js b/node_modules/whatwg-url/lib/public-api.js new file mode 100644 index 00000000..932dcada --- /dev/null +++ b/node_modules/whatwg-url/lib/public-api.js @@ -0,0 +1,11 @@ +"use strict"; + +exports.URL = require("./URL").interface; +exports.serializeURL = require("./url-state-machine").serializeURL; +exports.serializeURLOrigin = require("./url-state-machine").serializeURLOrigin; +exports.basicURLParse = require("./url-state-machine").basicURLParse; +exports.setTheUsername = require("./url-state-machine").setTheUsername; +exports.setThePassword = require("./url-state-machine").setThePassword; +exports.serializeHost = require("./url-state-machine").serializeHost; +exports.serializeInteger = require("./url-state-machine").serializeInteger; +exports.parseURL = require("./url-state-machine").parseURL; diff --git a/node_modules/whatwg-url/lib/url-state-machine.js b/node_modules/whatwg-url/lib/url-state-machine.js new file mode 100644 index 00000000..c25dbc2c --- /dev/null +++ b/node_modules/whatwg-url/lib/url-state-machine.js @@ -0,0 +1,1297 @@ +"use strict"; +const punycode = require("punycode"); +const tr46 = require("tr46"); + +const specialSchemes = { + ftp: 21, + file: null, + gopher: 70, + http: 80, + https: 443, + ws: 80, + wss: 443 +}; + +const failure = Symbol("failure"); + +function countSymbols(str) { + return punycode.ucs2.decode(str).length; +} + +function at(input, idx) { + const c = input[idx]; + return isNaN(c) ? undefined : String.fromCodePoint(c); +} + +function isASCIIDigit(c) { + return c >= 0x30 && c <= 0x39; +} + +function isASCIIAlpha(c) { + return (c >= 0x41 && c <= 0x5A) || (c >= 0x61 && c <= 0x7A); +} + +function isASCIIAlphanumeric(c) { + return isASCIIAlpha(c) || isASCIIDigit(c); +} + +function isASCIIHex(c) { + return isASCIIDigit(c) || (c >= 0x41 && c <= 0x46) || (c >= 0x61 && c <= 0x66); +} + +function isSingleDot(buffer) { + return buffer === "." || buffer.toLowerCase() === "%2e"; +} + +function isDoubleDot(buffer) { + buffer = buffer.toLowerCase(); + return buffer === ".." || buffer === "%2e." || buffer === ".%2e" || buffer === "%2e%2e"; +} + +function isWindowsDriveLetterCodePoints(cp1, cp2) { + return isASCIIAlpha(cp1) && (cp2 === 58 || cp2 === 124); +} + +function isWindowsDriveLetterString(string) { + return string.length === 2 && isASCIIAlpha(string.codePointAt(0)) && (string[1] === ":" || string[1] === "|"); +} + +function isNormalizedWindowsDriveLetterString(string) { + return string.length === 2 && isASCIIAlpha(string.codePointAt(0)) && string[1] === ":"; +} + +function containsForbiddenHostCodePoint(string) { + return string.search(/\u0000|\u0009|\u000A|\u000D|\u0020|#|%|\/|:|\?|@|\[|\\|\]/) !== -1; +} + +function containsForbiddenHostCodePointExcludingPercent(string) { + return string.search(/\u0000|\u0009|\u000A|\u000D|\u0020|#|\/|:|\?|@|\[|\\|\]/) !== -1; +} + +function isSpecialScheme(scheme) { + return specialSchemes[scheme] !== undefined; +} + +function isSpecial(url) { + return isSpecialScheme(url.scheme); +} + +function defaultPort(scheme) { + return specialSchemes[scheme]; +} + +function percentEncode(c) { + let hex = c.toString(16).toUpperCase(); + if (hex.length === 1) { + hex = "0" + hex; + } + + return "%" + hex; +} + +function utf8PercentEncode(c) { + const buf = new Buffer(c); + + let str = ""; + + for (let i = 0; i < buf.length; ++i) { + str += percentEncode(buf[i]); + } + + return str; +} + +function utf8PercentDecode(str) { + const input = new Buffer(str); + const output = []; + for (let i = 0; i < input.length; ++i) { + if (input[i] !== 37) { + output.push(input[i]); + } else if (input[i] === 37 && isASCIIHex(input[i + 1]) && isASCIIHex(input[i + 2])) { + output.push(parseInt(input.slice(i + 1, i + 3).toString(), 16)); + i += 2; + } else { + output.push(input[i]); + } + } + return new Buffer(output).toString(); +} + +function isC0ControlPercentEncode(c) { + return c <= 0x1F || c > 0x7E; +} + +const extraPathPercentEncodeSet = new Set([32, 34, 35, 60, 62, 63, 96, 123, 125]); +function isPathPercentEncode(c) { + return isC0ControlPercentEncode(c) || extraPathPercentEncodeSet.has(c); +} + +const extraUserinfoPercentEncodeSet = + new Set([47, 58, 59, 61, 64, 91, 92, 93, 94, 124]); +function isUserinfoPercentEncode(c) { + return isPathPercentEncode(c) || extraUserinfoPercentEncodeSet.has(c); +} + +function percentEncodeChar(c, encodeSetPredicate) { + const cStr = String.fromCodePoint(c); + + if (encodeSetPredicate(c)) { + return utf8PercentEncode(cStr); + } + + return cStr; +} + +function parseIPv4Number(input) { + let R = 10; + + if (input.length >= 2 && input.charAt(0) === "0" && input.charAt(1).toLowerCase() === "x") { + input = input.substring(2); + R = 16; + } else if (input.length >= 2 && input.charAt(0) === "0") { + input = input.substring(1); + R = 8; + } + + if (input === "") { + return 0; + } + + const regex = R === 10 ? /[^0-9]/ : (R === 16 ? /[^0-9A-Fa-f]/ : /[^0-7]/); + if (regex.test(input)) { + return failure; + } + + return parseInt(input, R); +} + +function parseIPv4(input) { + const parts = input.split("."); + if (parts[parts.length - 1] === "") { + if (parts.length > 1) { + parts.pop(); + } + } + + if (parts.length > 4) { + return input; + } + + const numbers = []; + for (const part of parts) { + if (part === "") { + return input; + } + const n = parseIPv4Number(part); + if (n === failure) { + return input; + } + + numbers.push(n); + } + + for (let i = 0; i < numbers.length - 1; ++i) { + if (numbers[i] > 255) { + return failure; + } + } + if (numbers[numbers.length - 1] >= Math.pow(256, 5 - numbers.length)) { + return failure; + } + + let ipv4 = numbers.pop(); + let counter = 0; + + for (const n of numbers) { + ipv4 += n * Math.pow(256, 3 - counter); + ++counter; + } + + return ipv4; +} + +function serializeIPv4(address) { + let output = ""; + let n = address; + + for (let i = 1; i <= 4; ++i) { + output = String(n % 256) + output; + if (i !== 4) { + output = "." + output; + } + n = Math.floor(n / 256); + } + + return output; +} + +function parseIPv6(input) { + const address = [0, 0, 0, 0, 0, 0, 0, 0]; + let pieceIndex = 0; + let compress = null; + let pointer = 0; + + input = punycode.ucs2.decode(input); + + if (input[pointer] === 58) { + if (input[pointer + 1] !== 58) { + return failure; + } + + pointer += 2; + ++pieceIndex; + compress = pieceIndex; + } + + while (pointer < input.length) { + if (pieceIndex === 8) { + return failure; + } + + if (input[pointer] === 58) { + if (compress !== null) { + return failure; + } + ++pointer; + ++pieceIndex; + compress = pieceIndex; + continue; + } + + let value = 0; + let length = 0; + + while (length < 4 && isASCIIHex(input[pointer])) { + value = value * 0x10 + parseInt(at(input, pointer), 16); + ++pointer; + ++length; + } + + if (input[pointer] === 46) { + if (length === 0) { + return failure; + } + + pointer -= length; + + if (pieceIndex > 6) { + return failure; + } + + let numbersSeen = 0; + + while (input[pointer] !== undefined) { + let ipv4Piece = null; + + if (numbersSeen > 0) { + if (input[pointer] === 46 && numbersSeen < 4) { + ++pointer; + } else { + return failure; + } + } + + if (!isASCIIDigit(input[pointer])) { + return failure; + } + + while (isASCIIDigit(input[pointer])) { + const number = parseInt(at(input, pointer)); + if (ipv4Piece === null) { + ipv4Piece = number; + } else if (ipv4Piece === 0) { + return failure; + } else { + ipv4Piece = ipv4Piece * 10 + number; + } + if (ipv4Piece > 255) { + return failure; + } + ++pointer; + } + + address[pieceIndex] = address[pieceIndex] * 0x100 + ipv4Piece; + + ++numbersSeen; + + if (numbersSeen === 2 || numbersSeen === 4) { + ++pieceIndex; + } + } + + if (numbersSeen !== 4) { + return failure; + } + + break; + } else if (input[pointer] === 58) { + ++pointer; + if (input[pointer] === undefined) { + return failure; + } + } else if (input[pointer] !== undefined) { + return failure; + } + + address[pieceIndex] = value; + ++pieceIndex; + } + + if (compress !== null) { + let swaps = pieceIndex - compress; + pieceIndex = 7; + while (pieceIndex !== 0 && swaps > 0) { + const temp = address[compress + swaps - 1]; + address[compress + swaps - 1] = address[pieceIndex]; + address[pieceIndex] = temp; + --pieceIndex; + --swaps; + } + } else if (compress === null && pieceIndex !== 8) { + return failure; + } + + return address; +} + +function serializeIPv6(address) { + let output = ""; + const seqResult = findLongestZeroSequence(address); + const compress = seqResult.idx; + let ignore0 = false; + + for (let pieceIndex = 0; pieceIndex <= 7; ++pieceIndex) { + if (ignore0 && address[pieceIndex] === 0) { + continue; + } else if (ignore0) { + ignore0 = false; + } + + if (compress === pieceIndex) { + const separator = pieceIndex === 0 ? "::" : ":"; + output += separator; + ignore0 = true; + continue; + } + + output += address[pieceIndex].toString(16); + + if (pieceIndex !== 7) { + output += ":"; + } + } + + return output; +} + +function parseHost(input, isSpecialArg) { + if (input[0] === "[") { + if (input[input.length - 1] !== "]") { + return failure; + } + + return parseIPv6(input.substring(1, input.length - 1)); + } + + if (!isSpecialArg) { + return parseOpaqueHost(input); + } + + const domain = utf8PercentDecode(input); + const asciiDomain = tr46.toASCII(domain, false, tr46.PROCESSING_OPTIONS.NONTRANSITIONAL, false); + if (asciiDomain === null) { + return failure; + } + + if (containsForbiddenHostCodePoint(asciiDomain)) { + return failure; + } + + const ipv4Host = parseIPv4(asciiDomain); + if (typeof ipv4Host === "number" || ipv4Host === failure) { + return ipv4Host; + } + + return asciiDomain; +} + +function parseOpaqueHost(input) { + if (containsForbiddenHostCodePointExcludingPercent(input)) { + return failure; + } + + let output = ""; + const decoded = punycode.ucs2.decode(input); + for (let i = 0; i < decoded.length; ++i) { + output += percentEncodeChar(decoded[i], isC0ControlPercentEncode); + } + return output; +} + +function findLongestZeroSequence(arr) { + let maxIdx = null; + let maxLen = 1; // only find elements > 1 + let currStart = null; + let currLen = 0; + + for (let i = 0; i < arr.length; ++i) { + if (arr[i] !== 0) { + if (currLen > maxLen) { + maxIdx = currStart; + maxLen = currLen; + } + + currStart = null; + currLen = 0; + } else { + if (currStart === null) { + currStart = i; + } + ++currLen; + } + } + + // if trailing zeros + if (currLen > maxLen) { + maxIdx = currStart; + maxLen = currLen; + } + + return { + idx: maxIdx, + len: maxLen + }; +} + +function serializeHost(host) { + if (typeof host === "number") { + return serializeIPv4(host); + } + + // IPv6 serializer + if (host instanceof Array) { + return "[" + serializeIPv6(host) + "]"; + } + + return host; +} + +function trimControlChars(url) { + return url.replace(/^[\u0000-\u001F\u0020]+|[\u0000-\u001F\u0020]+$/g, ""); +} + +function trimTabAndNewline(url) { + return url.replace(/\u0009|\u000A|\u000D/g, ""); +} + +function shortenPath(url) { + const path = url.path; + if (path.length === 0) { + return; + } + if (url.scheme === "file" && path.length === 1 && isNormalizedWindowsDriveLetter(path[0])) { + return; + } + + path.pop(); +} + +function includesCredentials(url) { + return url.username !== "" || url.password !== ""; +} + +function cannotHaveAUsernamePasswordPort(url) { + return url.host === null || url.host === "" || url.cannotBeABaseURL || url.scheme === "file"; +} + +function isNormalizedWindowsDriveLetter(string) { + return /^[A-Za-z]:$/.test(string); +} + +function URLStateMachine(input, base, encodingOverride, url, stateOverride) { + this.pointer = 0; + this.input = input; + this.base = base || null; + this.encodingOverride = encodingOverride || "utf-8"; + this.stateOverride = stateOverride; + this.url = url; + this.failure = false; + this.parseError = false; + + if (!this.url) { + this.url = { + scheme: "", + username: "", + password: "", + host: null, + port: null, + path: [], + query: null, + fragment: null, + + cannotBeABaseURL: false + }; + + const res = trimControlChars(this.input); + if (res !== this.input) { + this.parseError = true; + } + this.input = res; + } + + const res = trimTabAndNewline(this.input); + if (res !== this.input) { + this.parseError = true; + } + this.input = res; + + this.state = stateOverride || "scheme start"; + + this.buffer = ""; + this.atFlag = false; + this.arrFlag = false; + this.passwordTokenSeenFlag = false; + + this.input = punycode.ucs2.decode(this.input); + + for (; this.pointer <= this.input.length; ++this.pointer) { + const c = this.input[this.pointer]; + const cStr = isNaN(c) ? undefined : String.fromCodePoint(c); + + // exec state machine + const ret = this["parse " + this.state](c, cStr); + if (!ret) { + break; // terminate algorithm + } else if (ret === failure) { + this.failure = true; + break; + } + } +} + +URLStateMachine.prototype["parse scheme start"] = function parseSchemeStart(c, cStr) { + if (isASCIIAlpha(c)) { + this.buffer += cStr.toLowerCase(); + this.state = "scheme"; + } else if (!this.stateOverride) { + this.state = "no scheme"; + --this.pointer; + } else { + this.parseError = true; + return failure; + } + + return true; +}; + +URLStateMachine.prototype["parse scheme"] = function parseScheme(c, cStr) { + if (isASCIIAlphanumeric(c) || c === 43 || c === 45 || c === 46) { + this.buffer += cStr.toLowerCase(); + } else if (c === 58) { + if (this.stateOverride) { + if (isSpecial(this.url) && !isSpecialScheme(this.buffer)) { + return false; + } + + if (!isSpecial(this.url) && isSpecialScheme(this.buffer)) { + return false; + } + + if ((includesCredentials(this.url) || this.url.port !== null) && this.buffer === "file") { + return false; + } + + if (this.url.scheme === "file" && (this.url.host === "" || this.url.host === null)) { + return false; + } + } + this.url.scheme = this.buffer; + this.buffer = ""; + if (this.stateOverride) { + return false; + } + if (this.url.scheme === "file") { + if (this.input[this.pointer + 1] !== 47 || this.input[this.pointer + 2] !== 47) { + this.parseError = true; + } + this.state = "file"; + } else if (isSpecial(this.url) && this.base !== null && this.base.scheme === this.url.scheme) { + this.state = "special relative or authority"; + } else if (isSpecial(this.url)) { + this.state = "special authority slashes"; + } else if (this.input[this.pointer + 1] === 47) { + this.state = "path or authority"; + ++this.pointer; + } else { + this.url.cannotBeABaseURL = true; + this.url.path.push(""); + this.state = "cannot-be-a-base-URL path"; + } + } else if (!this.stateOverride) { + this.buffer = ""; + this.state = "no scheme"; + this.pointer = -1; + } else { + this.parseError = true; + return failure; + } + + return true; +}; + +URLStateMachine.prototype["parse no scheme"] = function parseNoScheme(c) { + if (this.base === null || (this.base.cannotBeABaseURL && c !== 35)) { + return failure; + } else if (this.base.cannotBeABaseURL && c === 35) { + this.url.scheme = this.base.scheme; + this.url.path = this.base.path.slice(); + this.url.query = this.base.query; + this.url.fragment = ""; + this.url.cannotBeABaseURL = true; + this.state = "fragment"; + } else if (this.base.scheme === "file") { + this.state = "file"; + --this.pointer; + } else { + this.state = "relative"; + --this.pointer; + } + + return true; +}; + +URLStateMachine.prototype["parse special relative or authority"] = function parseSpecialRelativeOrAuthority(c) { + if (c === 47 && this.input[this.pointer + 1] === 47) { + this.state = "special authority ignore slashes"; + ++this.pointer; + } else { + this.parseError = true; + this.state = "relative"; + --this.pointer; + } + + return true; +}; + +URLStateMachine.prototype["parse path or authority"] = function parsePathOrAuthority(c) { + if (c === 47) { + this.state = "authority"; + } else { + this.state = "path"; + --this.pointer; + } + + return true; +}; + +URLStateMachine.prototype["parse relative"] = function parseRelative(c) { + this.url.scheme = this.base.scheme; + if (isNaN(c)) { + this.url.username = this.base.username; + this.url.password = this.base.password; + this.url.host = this.base.host; + this.url.port = this.base.port; + this.url.path = this.base.path.slice(); + this.url.query = this.base.query; + } else if (c === 47) { + this.state = "relative slash"; + } else if (c === 63) { + this.url.username = this.base.username; + this.url.password = this.base.password; + this.url.host = this.base.host; + this.url.port = this.base.port; + this.url.path = this.base.path.slice(); + this.url.query = ""; + this.state = "query"; + } else if (c === 35) { + this.url.username = this.base.username; + this.url.password = this.base.password; + this.url.host = this.base.host; + this.url.port = this.base.port; + this.url.path = this.base.path.slice(); + this.url.query = this.base.query; + this.url.fragment = ""; + this.state = "fragment"; + } else if (isSpecial(this.url) && c === 92) { + this.parseError = true; + this.state = "relative slash"; + } else { + this.url.username = this.base.username; + this.url.password = this.base.password; + this.url.host = this.base.host; + this.url.port = this.base.port; + this.url.path = this.base.path.slice(0, this.base.path.length - 1); + + this.state = "path"; + --this.pointer; + } + + return true; +}; + +URLStateMachine.prototype["parse relative slash"] = function parseRelativeSlash(c) { + if (isSpecial(this.url) && (c === 47 || c === 92)) { + if (c === 92) { + this.parseError = true; + } + this.state = "special authority ignore slashes"; + } else if (c === 47) { + this.state = "authority"; + } else { + this.url.username = this.base.username; + this.url.password = this.base.password; + this.url.host = this.base.host; + this.url.port = this.base.port; + this.state = "path"; + --this.pointer; + } + + return true; +}; + +URLStateMachine.prototype["parse special authority slashes"] = function parseSpecialAuthoritySlashes(c) { + if (c === 47 && this.input[this.pointer + 1] === 47) { + this.state = "special authority ignore slashes"; + ++this.pointer; + } else { + this.parseError = true; + this.state = "special authority ignore slashes"; + --this.pointer; + } + + return true; +}; + +URLStateMachine.prototype["parse special authority ignore slashes"] = function parseSpecialAuthorityIgnoreSlashes(c) { + if (c !== 47 && c !== 92) { + this.state = "authority"; + --this.pointer; + } else { + this.parseError = true; + } + + return true; +}; + +URLStateMachine.prototype["parse authority"] = function parseAuthority(c, cStr) { + if (c === 64) { + this.parseError = true; + if (this.atFlag) { + this.buffer = "%40" + this.buffer; + } + this.atFlag = true; + + // careful, this is based on buffer and has its own pointer (this.pointer != pointer) and inner chars + const len = countSymbols(this.buffer); + for (let pointer = 0; pointer < len; ++pointer) { + const codePoint = this.buffer.codePointAt(pointer); + + if (codePoint === 58 && !this.passwordTokenSeenFlag) { + this.passwordTokenSeenFlag = true; + continue; + } + const encodedCodePoints = percentEncodeChar(codePoint, isUserinfoPercentEncode); + if (this.passwordTokenSeenFlag) { + this.url.password += encodedCodePoints; + } else { + this.url.username += encodedCodePoints; + } + } + this.buffer = ""; + } else if (isNaN(c) || c === 47 || c === 63 || c === 35 || + (isSpecial(this.url) && c === 92)) { + if (this.atFlag && this.buffer === "") { + this.parseError = true; + return failure; + } + this.pointer -= countSymbols(this.buffer) + 1; + this.buffer = ""; + this.state = "host"; + } else { + this.buffer += cStr; + } + + return true; +}; + +URLStateMachine.prototype["parse hostname"] = +URLStateMachine.prototype["parse host"] = function parseHostName(c, cStr) { + if (this.stateOverride && this.url.scheme === "file") { + --this.pointer; + this.state = "file host"; + } else if (c === 58 && !this.arrFlag) { + if (this.buffer === "") { + this.parseError = true; + return failure; + } + + const host = parseHost(this.buffer, isSpecial(this.url)); + if (host === failure) { + return failure; + } + + this.url.host = host; + this.buffer = ""; + this.state = "port"; + if (this.stateOverride === "hostname") { + return false; + } + } else if (isNaN(c) || c === 47 || c === 63 || c === 35 || + (isSpecial(this.url) && c === 92)) { + --this.pointer; + if (isSpecial(this.url) && this.buffer === "") { + this.parseError = true; + return failure; + } else if (this.stateOverride && this.buffer === "" && + (includesCredentials(this.url) || this.url.port !== null)) { + this.parseError = true; + return false; + } + + const host = parseHost(this.buffer, isSpecial(this.url)); + if (host === failure) { + return failure; + } + + this.url.host = host; + this.buffer = ""; + this.state = "path start"; + if (this.stateOverride) { + return false; + } + } else { + if (c === 91) { + this.arrFlag = true; + } else if (c === 93) { + this.arrFlag = false; + } + this.buffer += cStr; + } + + return true; +}; + +URLStateMachine.prototype["parse port"] = function parsePort(c, cStr) { + if (isASCIIDigit(c)) { + this.buffer += cStr; + } else if (isNaN(c) || c === 47 || c === 63 || c === 35 || + (isSpecial(this.url) && c === 92) || + this.stateOverride) { + if (this.buffer !== "") { + const port = parseInt(this.buffer); + if (port > Math.pow(2, 16) - 1) { + this.parseError = true; + return failure; + } + this.url.port = port === defaultPort(this.url.scheme) ? null : port; + this.buffer = ""; + } + if (this.stateOverride) { + return false; + } + this.state = "path start"; + --this.pointer; + } else { + this.parseError = true; + return failure; + } + + return true; +}; + +const fileOtherwiseCodePoints = new Set([47, 92, 63, 35]); + +URLStateMachine.prototype["parse file"] = function parseFile(c) { + this.url.scheme = "file"; + + if (c === 47 || c === 92) { + if (c === 92) { + this.parseError = true; + } + this.state = "file slash"; + } else if (this.base !== null && this.base.scheme === "file") { + if (isNaN(c)) { + this.url.host = this.base.host; + this.url.path = this.base.path.slice(); + this.url.query = this.base.query; + } else if (c === 63) { + this.url.host = this.base.host; + this.url.path = this.base.path.slice(); + this.url.query = ""; + this.state = "query"; + } else if (c === 35) { + this.url.host = this.base.host; + this.url.path = this.base.path.slice(); + this.url.query = this.base.query; + this.url.fragment = ""; + this.state = "fragment"; + } else { + if (this.input.length - this.pointer - 1 === 0 || // remaining consists of 0 code points + !isWindowsDriveLetterCodePoints(c, this.input[this.pointer + 1]) || + (this.input.length - this.pointer - 1 >= 2 && // remaining has at least 2 code points + !fileOtherwiseCodePoints.has(this.input[this.pointer + 2]))) { + this.url.host = this.base.host; + this.url.path = this.base.path.slice(); + shortenPath(this.url); + } else { + this.parseError = true; + } + + this.state = "path"; + --this.pointer; + } + } else { + this.state = "path"; + --this.pointer; + } + + return true; +}; + +URLStateMachine.prototype["parse file slash"] = function parseFileSlash(c) { + if (c === 47 || c === 92) { + if (c === 92) { + this.parseError = true; + } + this.state = "file host"; + } else { + if (this.base !== null && this.base.scheme === "file") { + if (isNormalizedWindowsDriveLetterString(this.base.path[0])) { + this.url.path.push(this.base.path[0]); + } else { + this.url.host = this.base.host; + } + } + this.state = "path"; + --this.pointer; + } + + return true; +}; + +URLStateMachine.prototype["parse file host"] = function parseFileHost(c, cStr) { + if (isNaN(c) || c === 47 || c === 92 || c === 63 || c === 35) { + --this.pointer; + if (!this.stateOverride && isWindowsDriveLetterString(this.buffer)) { + this.parseError = true; + this.state = "path"; + } else if (this.buffer === "") { + this.url.host = ""; + if (this.stateOverride) { + return false; + } + this.state = "path start"; + } else { + let host = parseHost(this.buffer, isSpecial(this.url)); + if (host === failure) { + return failure; + } + if (host === "localhost") { + host = ""; + } + this.url.host = host; + + if (this.stateOverride) { + return false; + } + + this.buffer = ""; + this.state = "path start"; + } + } else { + this.buffer += cStr; + } + + return true; +}; + +URLStateMachine.prototype["parse path start"] = function parsePathStart(c) { + if (isSpecial(this.url)) { + if (c === 92) { + this.parseError = true; + } + this.state = "path"; + + if (c !== 47 && c !== 92) { + --this.pointer; + } + } else if (!this.stateOverride && c === 63) { + this.url.query = ""; + this.state = "query"; + } else if (!this.stateOverride && c === 35) { + this.url.fragment = ""; + this.state = "fragment"; + } else if (c !== undefined) { + this.state = "path"; + if (c !== 47) { + --this.pointer; + } + } + + return true; +}; + +URLStateMachine.prototype["parse path"] = function parsePath(c) { + if (isNaN(c) || c === 47 || (isSpecial(this.url) && c === 92) || + (!this.stateOverride && (c === 63 || c === 35))) { + if (isSpecial(this.url) && c === 92) { + this.parseError = true; + } + + if (isDoubleDot(this.buffer)) { + shortenPath(this.url); + if (c !== 47 && !(isSpecial(this.url) && c === 92)) { + this.url.path.push(""); + } + } else if (isSingleDot(this.buffer) && c !== 47 && + !(isSpecial(this.url) && c === 92)) { + this.url.path.push(""); + } else if (!isSingleDot(this.buffer)) { + if (this.url.scheme === "file" && this.url.path.length === 0 && isWindowsDriveLetterString(this.buffer)) { + if (this.url.host !== "" && this.url.host !== null) { + this.parseError = true; + this.url.host = ""; + } + this.buffer = this.buffer[0] + ":"; + } + this.url.path.push(this.buffer); + } + this.buffer = ""; + if (this.url.scheme === "file" && (c === undefined || c === 63 || c === 35)) { + while (this.url.path.length > 1 && this.url.path[0] === "") { + this.parseError = true; + this.url.path.shift(); + } + } + if (c === 63) { + this.url.query = ""; + this.state = "query"; + } + if (c === 35) { + this.url.fragment = ""; + this.state = "fragment"; + } + } else { + // TODO: If c is not a URL code point and not "%", parse error. + + if (c === 37 && + (!isASCIIHex(this.input[this.pointer + 1]) || + !isASCIIHex(this.input[this.pointer + 2]))) { + this.parseError = true; + } + + this.buffer += percentEncodeChar(c, isPathPercentEncode); + } + + return true; +}; + +URLStateMachine.prototype["parse cannot-be-a-base-URL path"] = function parseCannotBeABaseURLPath(c) { + if (c === 63) { + this.url.query = ""; + this.state = "query"; + } else if (c === 35) { + this.url.fragment = ""; + this.state = "fragment"; + } else { + // TODO: Add: not a URL code point + if (!isNaN(c) && c !== 37) { + this.parseError = true; + } + + if (c === 37 && + (!isASCIIHex(this.input[this.pointer + 1]) || + !isASCIIHex(this.input[this.pointer + 2]))) { + this.parseError = true; + } + + if (!isNaN(c)) { + this.url.path[0] = this.url.path[0] + percentEncodeChar(c, isC0ControlPercentEncode); + } + } + + return true; +}; + +URLStateMachine.prototype["parse query"] = function parseQuery(c, cStr) { + if (isNaN(c) || (!this.stateOverride && c === 35)) { + if (!isSpecial(this.url) || this.url.scheme === "ws" || this.url.scheme === "wss") { + this.encodingOverride = "utf-8"; + } + + const buffer = new Buffer(this.buffer); // TODO: Use encoding override instead + for (let i = 0; i < buffer.length; ++i) { + if (buffer[i] < 0x21 || buffer[i] > 0x7E || buffer[i] === 0x22 || buffer[i] === 0x23 || + buffer[i] === 0x3C || buffer[i] === 0x3E) { + this.url.query += percentEncode(buffer[i]); + } else { + this.url.query += String.fromCodePoint(buffer[i]); + } + } + + this.buffer = ""; + if (c === 35) { + this.url.fragment = ""; + this.state = "fragment"; + } + } else { + // TODO: If c is not a URL code point and not "%", parse error. + if (c === 37 && + (!isASCIIHex(this.input[this.pointer + 1]) || + !isASCIIHex(this.input[this.pointer + 2]))) { + this.parseError = true; + } + + this.buffer += cStr; + } + + return true; +}; + +URLStateMachine.prototype["parse fragment"] = function parseFragment(c) { + if (isNaN(c)) { // do nothing + } else if (c === 0x0) { + this.parseError = true; + } else { + // TODO: If c is not a URL code point and not "%", parse error. + if (c === 37 && + (!isASCIIHex(this.input[this.pointer + 1]) || + !isASCIIHex(this.input[this.pointer + 2]))) { + this.parseError = true; + } + + this.url.fragment += percentEncodeChar(c, isC0ControlPercentEncode); + } + + return true; +}; + +function serializeURL(url, excludeFragment) { + let output = url.scheme + ":"; + if (url.host !== null) { + output += "//"; + + if (url.username !== "" || url.password !== "") { + output += url.username; + if (url.password !== "") { + output += ":" + url.password; + } + output += "@"; + } + + output += serializeHost(url.host); + + if (url.port !== null) { + output += ":" + url.port; + } + } else if (url.host === null && url.scheme === "file") { + output += "//"; + } + + if (url.cannotBeABaseURL) { + output += url.path[0]; + } else { + for (const string of url.path) { + output += "/" + string; + } + } + + if (url.query !== null) { + output += "?" + url.query; + } + + if (!excludeFragment && url.fragment !== null) { + output += "#" + url.fragment; + } + + return output; +} + +function serializeOrigin(tuple) { + let result = tuple.scheme + "://"; + result += serializeHost(tuple.host); + + if (tuple.port !== null) { + result += ":" + tuple.port; + } + + return result; +} + +module.exports.serializeURL = serializeURL; + +module.exports.serializeURLOrigin = function (url) { + // https://url.spec.whatwg.org/#concept-url-origin + switch (url.scheme) { + case "blob": + try { + return module.exports.serializeURLOrigin(module.exports.parseURL(url.path[0])); + } catch (e) { + // serializing an opaque origin returns "null" + return "null"; + } + case "ftp": + case "gopher": + case "http": + case "https": + case "ws": + case "wss": + return serializeOrigin({ + scheme: url.scheme, + host: url.host, + port: url.port + }); + case "file": + // spec says "exercise to the reader", chrome says "file://" + return "file://"; + default: + // serializing an opaque origin returns "null" + return "null"; + } +}; + +module.exports.basicURLParse = function (input, options) { + if (options === undefined) { + options = {}; + } + + const usm = new URLStateMachine(input, options.baseURL, options.encodingOverride, options.url, options.stateOverride); + if (usm.failure) { + return "failure"; + } + + return usm.url; +}; + +module.exports.setTheUsername = function (url, username) { + url.username = ""; + const decoded = punycode.ucs2.decode(username); + for (let i = 0; i < decoded.length; ++i) { + url.username += percentEncodeChar(decoded[i], isUserinfoPercentEncode); + } +}; + +module.exports.setThePassword = function (url, password) { + url.password = ""; + const decoded = punycode.ucs2.decode(password); + for (let i = 0; i < decoded.length; ++i) { + url.password += percentEncodeChar(decoded[i], isUserinfoPercentEncode); + } +}; + +module.exports.serializeHost = serializeHost; + +module.exports.cannotHaveAUsernamePasswordPort = cannotHaveAUsernamePasswordPort; + +module.exports.serializeInteger = function (integer) { + return String(integer); +}; + +module.exports.parseURL = function (input, options) { + if (options === undefined) { + options = {}; + } + + // We don't handle blobs, so this just delegates: + return module.exports.basicURLParse(input, { baseURL: options.baseURL, encodingOverride: options.encodingOverride }); +}; diff --git a/node_modules/whatwg-url/lib/utils.js b/node_modules/whatwg-url/lib/utils.js new file mode 100644 index 00000000..a562009c --- /dev/null +++ b/node_modules/whatwg-url/lib/utils.js @@ -0,0 +1,20 @@ +"use strict"; + +module.exports.mixin = function mixin(target, source) { + const keys = Object.getOwnPropertyNames(source); + for (let i = 0; i < keys.length; ++i) { + Object.defineProperty(target, keys[i], Object.getOwnPropertyDescriptor(source, keys[i])); + } +}; + +module.exports.wrapperSymbol = Symbol("wrapper"); +module.exports.implSymbol = Symbol("impl"); + +module.exports.wrapperForImpl = function (impl) { + return impl[module.exports.wrapperSymbol]; +}; + +module.exports.implForWrapper = function (wrapper) { + return wrapper[module.exports.implSymbol]; +}; + diff --git a/node_modules/whatwg-url/package.json b/node_modules/whatwg-url/package.json new file mode 100644 index 00000000..fce35ae7 --- /dev/null +++ b/node_modules/whatwg-url/package.json @@ -0,0 +1,32 @@ +{ + "name": "whatwg-url", + "version": "5.0.0", + "description": "An implementation of the WHATWG URL Standard's URL API and parsing machinery", + "main": "lib/public-api.js", + "files": [ + "lib/" + ], + "author": "Sebastian Mayr ", + "license": "MIT", + "repository": "jsdom/whatwg-url", + "dependencies": { + "tr46": "~0.0.3", + "webidl-conversions": "^3.0.0" + }, + "devDependencies": { + "eslint": "^2.6.0", + "istanbul": "~0.4.3", + "mocha": "^2.2.4", + "recast": "~0.10.29", + "request": "^2.55.0", + "webidl2js": "^3.0.2" + }, + "scripts": { + "build": "node scripts/transform.js && node scripts/convert-idl.js", + "coverage": "istanbul cover node_modules/mocha/bin/_mocha", + "lint": "eslint .", + "prepublish": "npm run build", + "pretest": "node scripts/get-latest-platform-tests.js && npm run build", + "test": "mocha" + } +} diff --git a/package-lock.json b/package-lock.json new file mode 100644 index 00000000..98847d57 --- /dev/null +++ b/package-lock.json @@ -0,0 +1,54 @@ +{ + "name": "mlflow", + "version": "1.0.0", + "lockfileVersion": 3, + "requires": true, + "packages": { + "": { + "name": "mlflow", + "version": "1.0.0", + "license": "ISC", + "dependencies": { + "node-fetch": "^2.7.0" + } + }, + "node_modules/node-fetch": { + "version": "2.7.0", + "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.7.0.tgz", + "integrity": "sha512-c4FRfUm/dbcWZ7U+1Wq0AwCyFL+3nt2bEw05wfxSz+DWpWsitgmSgYmy2dQdWyKC1694ELPqMs/YzUSNozLt8A==", + "dependencies": { + "whatwg-url": "^5.0.0" + }, + "engines": { + "node": "4.x || >=6.0.0" + }, + "peerDependencies": { + "encoding": "^0.1.0" + }, + "peerDependenciesMeta": { + "encoding": { + "optional": true + } + } + }, + "node_modules/tr46": { + "version": "0.0.3", + "resolved": "https://registry.npmjs.org/tr46/-/tr46-0.0.3.tgz", + "integrity": "sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw==" + }, + "node_modules/webidl-conversions": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-3.0.1.tgz", + "integrity": "sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ==" + }, + "node_modules/whatwg-url": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-5.0.0.tgz", + "integrity": "sha512-saE57nupxk6v3HY35+jzBwYa0rKSy0XR8JSxZPwgLr7ys0IBzhGviA1/TUGJLmSVqs8pb9AnvICXEuOHLprYTw==", + "dependencies": { + "tr46": "~0.0.3", + "webidl-conversions": "^3.0.0" + } + } + } +} diff --git a/package.json b/package.json new file mode 100644 index 00000000..d6a50688 --- /dev/null +++ b/package.json @@ -0,0 +1,14 @@ +{ + "name": "mlflow", + "version": "1.0.0", + "description": "", + "main": "index.js", + "scripts": { + "test": "echo \"Error: no test specified\" && exit 1" + }, + "author": "", + "license": "ISC", + "dependencies": { + "node-fetch": "^2.7.0" + } +} From 0d06093f5d1656e8a8ac28877c85283855d973e0 Mon Sep 17 00:00:00 2001 From: Yiqun Zheng <16813562+yiqunzheng@users.noreply.github.com> Date: Sat, 24 Aug 2024 15:10:33 -0700 Subject: [PATCH 005/357] Revert "PR made from bash" --- README.md | 39 --------------------------------------- 1 file changed, 39 deletions(-) diff --git a/README.md b/README.md index 88d81fe2..8b137891 100644 --- a/README.md +++ b/README.md @@ -1,40 +1 @@ -// to sync w both origin/dev and upstream/dev: -git fetch upstream -git rebase upstream/dev -git push origin dev - - -// to check which remote branches are tracked: -git branch -vv - -// to make a PR fron GitHub CLI - // login to GH CLI (if you're not): - gh auth login - - // make PR: - gh pr create --base upstream/dev --head origin/dev --title "PR Title goes here" --body "Description of your changes goes here" - - -// install GH CLI (mac): -brew install gh - -// install GH CLI (windows): -winget install --id GitHub.cli - -// linux (debian): - - //add the repository: - curl -fsSL https://cli.github.com/packages/githubcli-archive-keyring.gpg | sudo dd of=/usr/share/keyrings/githubcli-archive-keyring.gpg - sudo chmod go+r /usr/share/keyrings/githubcli-archive-keyring.gpg - echo "deb [arch=$(dpkg --print-architecture) signed-by=/usr/share/keyrings/githubcli-archive-keyring.gpg] https://cli.github.com/packages stable main" | sudo tee /etc/apt/sources.list.d/github-cli.list > /dev/null - - // update package list: - sudo apt update - - // install GH CLI: - sudo apt install gh - -// test text - - From 0d400f48cbcb590e89b02e11e6e4acc1bb5b7526 Mon Sep 17 00:00:00 2001 From: Austin Fraser Date: Sat, 24 Aug 2024 16:44:30 -0700 Subject: [PATCH 006/357] finished create experiment --- Tracking_server/experiment_management.js | 38 ++++++++++++++++++++++++ 1 file changed, 38 insertions(+) diff --git a/Tracking_server/experiment_management.js b/Tracking_server/experiment_management.js index e69de29b..bf1fe337 100644 --- a/Tracking_server/experiment_management.js +++ b/Tracking_server/experiment_management.js @@ -0,0 +1,38 @@ +const fetch = require('node-fetch'); + +const MLFLOW_TRACKING_URI = 'http://localhost:5001/api/2.0/mlflow'; + +/** + * Create an experiment with a name. Returns the ID of the newly created experiment. + * Validates that another experiment with the same name does not already exist and fails if another experiment with the same name already exists. + * Throws RESOURCE_ALREADY_EXISTS if a experiment with the given name exists. + */ +async function createExperiment(name, artifact_location, tags) { + try { + const response = await fetch(`${MLFLOW_TRACKING_URI}/experiments/create`, { + method: "POST", + headers: { "Content-Type": "application/json" }, + body: JSON.stringify({ name, artifact_location, tags }), + }); + + if (response.status === 400) { + const errorBody = await response.json(); + console.error('400 Error:', errorBody.message); + return; + } + + if (!response.ok) { + throw new Error(`HTTP error! Status: ${response.status}`); + } + + const data = await response.json(); + console.log('data.experiment_id: ', data.experiment_id); + return data.experiment_id; + } + catch (error) { + console.error('Error creating experiment:', error); + } +} + + +createExperiment('test_experiment_postman10'); \ No newline at end of file From f7b17f46bff688ffe799d0fd078b21b033ac3f32 Mon Sep 17 00:00:00 2001 From: Austin Fraser Date: Sun, 25 Aug 2024 10:22:40 -0700 Subject: [PATCH 007/357] searchExperiment done --- Tracking_server/experiment_management.js | 26 ++++++++++++++++++++++-- 1 file changed, 24 insertions(+), 2 deletions(-) diff --git a/Tracking_server/experiment_management.js b/Tracking_server/experiment_management.js index bf1fe337..db402553 100644 --- a/Tracking_server/experiment_management.js +++ b/Tracking_server/experiment_management.js @@ -22,7 +22,7 @@ async function createExperiment(name, artifact_location, tags) { } if (!response.ok) { - throw new Error(`HTTP error! Status: ${response.status}`); + throw new Error(`HTTP error, status: ${response.status}`); } const data = await response.json(); @@ -34,5 +34,27 @@ async function createExperiment(name, artifact_location, tags) { } } +// createExperiment('test_experiment_postman10'); -createExperiment('test_experiment_postman10'); \ No newline at end of file +async function searchExperiment(filter, max_results, page_token, order_by, view_type) { + try { + const response = await fetch(`${MLFLOW_TRACKING_URI}/experiments/search`, { + method: "POST", + headers: { "Content-Type": "application/json" }, + body: JSON.stringify({ filter, max_results, page_token, order_by, view_type }), + }) + + if (!response.ok) { + throw new Error(`HTTP error, status: ${response.status}`); + } + + const data = await response.json(); + console.log('data.experiments: ', data.experiments); + return data.experiments + } + catch (error) { + console.error('Error searching for experiment:', error); + } +} + +// searchExperiment("name = 'test_experiment_postmanx'", 1000); \ No newline at end of file From 7d25a17122eb2c28351129641633aa77b465442a Mon Sep 17 00:00:00 2001 From: Yiqun Zheng Date: Mon, 26 Aug 2024 15:25:55 -0700 Subject: [PATCH 008/357] model registry createRegisteredModel --- .gitignore | 1 + Model_registry/model_registry.js | 133 +++++++++++++++++++++++++++++++ 2 files changed, 134 insertions(+) create mode 100644 .gitignore create mode 100644 Model_registry/model_registry.js diff --git a/.gitignore b/.gitignore new file mode 100644 index 00000000..b512c09d --- /dev/null +++ b/.gitignore @@ -0,0 +1 @@ +node_modules \ No newline at end of file diff --git a/Model_registry/model_registry.js b/Model_registry/model_registry.js new file mode 100644 index 00000000..310fc75d --- /dev/null +++ b/Model_registry/model_registry.js @@ -0,0 +1,133 @@ +//model_registry.js + +class ModelRegistry { + constructor(trackingUri) { + this.trackingUri = trackingUri; + } + + /** + * Creates a new registered model. + * + * @param {string} name - The name of the model to register (required) + * @param {Array<{key: string, value: string}>} [tags=[]] - Optional tags for the model + * @param {string} [description=''] - Optional description for the model + * @returns {Promise} The created registered model object + */ + async createRegisteredModel(name, tags = [], description = "") { + if (!name) { + throw new Error("Model name is required"); + } + + const url = `${this.trackingUri}/api/2.0/mlflow/registered-models/create`; + + const response = await fetch(url, { + method: "POST", + headers: { + "Content-Type": "application/json", + }, + body: JSON.stringify({ name, tags, description }), + }); + + const data = await response.json(); + + if (!response.ok) { + throw new Error( + `Error creating registered model: ${ + data.message || response.statusText + }` + ); + } + return data.registered_model; + } + + /** + * Gets a registered model. + * + * @param {string} name - The name of the registered model to retrieve (required) + * @returns {Promise} The registered model object + */ + async getRegisteredModel(name) { + // Implementation similar to createRegisteredModel + } + + /** + * Renames a registered model. + * + * @param {string} name - The current name of the registered model (required) + * @param {string} newName - The new name for the registered model (required) + * @returns {Promise} The updated registered model object + */ + async renameRegisteredModel(name, newName) { + // Implementation + } + + /** + * Updates a registered model. + * + * @param {string} name - The name of the registered model to update (required) + * @param {string} [description] - The new description for the model + * @returns {Promise} The updated registered model object + */ + async updateRegisteredModel(name, description) { + // Implementation + } + + /** + * Deletes a registered model. + * + * @param {string} name - The name of the registered model to delete (required) + * @returns {Promise} + */ + async deleteRegisteredModel(name) { + // Implementation + } + + /** + * Gets the latest model versions for a registered model. + * + * @param {string} name - The name of the registered model (required) + * @param {Array} [stages=[]] - The stages to get the latest versions from + * @returns {Promise>} The latest model version objects + */ + async getLatestModelVersions(name, stages = []) { + // Implementation + } + + /** + * Searches for registered models. + * + * @param {string} [filter] - String filter condition + * @param {number} [maxResults] - Maximum number of models desired + * @param {Array} [orderBy] - List of columns for ordering search results + * @param {string} [pageToken] - Token for pagination + * @returns {Promise} Object containing matching models and next page token + */ + async searchRegisteredModels(filter, maxResults, orderBy, pageToken) { + // Implementation + } + + /** + * Sets a tag on a registered model. + * + * @param {string} name - The name of the registered model (required) + * @param {string} key - The tag key (required) + * @param {string} value - The tag value (required) + * @returns {Promise} + */ + async setRegisteredModelTag(name, key, value) { + // Implementation + } + + /** + * Deletes a tag from a registered model. + * + * @param {string} name - The name of the registered model (required) + * @param {string} key - The tag key to delete (required) + * @returns {Promise} + */ + async deleteRegisteredModelTag(name, key) { + // Implementation + } +} + +export { ModelRegistry }; From 863e48a384316a859ecf7d0ec5e7cf7f4f83ec7d Mon Sep 17 00:00:00 2001 From: Yiqun Zheng Date: Mon, 26 Aug 2024 15:49:46 -0700 Subject: [PATCH 009/357] modified package.json --- node_modules/.package-lock.json | 41 +- node_modules/node-fetch/LICENSE.md | 22 - node_modules/node-fetch/README.md | 634 ------ node_modules/node-fetch/browser.js | 25 - node_modules/node-fetch/lib/index.es.js | 1777 ---------------- node_modules/node-fetch/lib/index.js | 1787 ----------------- node_modules/node-fetch/lib/index.mjs | 1775 ---------------- node_modules/node-fetch/package.json | 89 - node_modules/tr46/.npmignore | 4 - node_modules/tr46/index.js | 193 -- node_modules/tr46/lib/.gitkeep | 0 node_modules/tr46/lib/mappingTable.json | 1 - node_modules/tr46/package.json | 31 - node_modules/webidl-conversions/LICENSE.md | 12 - node_modules/webidl-conversions/README.md | 53 - node_modules/webidl-conversions/lib/index.js | 189 -- node_modules/webidl-conversions/package.json | 23 - node_modules/whatwg-url/LICENSE.txt | 21 - node_modules/whatwg-url/README.md | 67 - node_modules/whatwg-url/lib/URL-impl.js | 200 -- node_modules/whatwg-url/lib/URL.js | 196 -- node_modules/whatwg-url/lib/public-api.js | 11 - .../whatwg-url/lib/url-state-machine.js | 1297 ------------ node_modules/whatwg-url/lib/utils.js | 20 - node_modules/whatwg-url/package.json | 32 - package-lock.json | 43 +- package.json | 14 +- 27 files changed, 10 insertions(+), 8547 deletions(-) delete mode 100644 node_modules/node-fetch/LICENSE.md delete mode 100644 node_modules/node-fetch/README.md delete mode 100644 node_modules/node-fetch/browser.js delete mode 100644 node_modules/node-fetch/lib/index.es.js delete mode 100644 node_modules/node-fetch/lib/index.js delete mode 100644 node_modules/node-fetch/lib/index.mjs delete mode 100644 node_modules/node-fetch/package.json delete mode 100644 node_modules/tr46/.npmignore delete mode 100644 node_modules/tr46/index.js delete mode 100644 node_modules/tr46/lib/.gitkeep delete mode 100644 node_modules/tr46/lib/mappingTable.json delete mode 100644 node_modules/tr46/package.json delete mode 100644 node_modules/webidl-conversions/LICENSE.md delete mode 100644 node_modules/webidl-conversions/README.md delete mode 100644 node_modules/webidl-conversions/lib/index.js delete mode 100644 node_modules/webidl-conversions/package.json delete mode 100644 node_modules/whatwg-url/LICENSE.txt delete mode 100644 node_modules/whatwg-url/README.md delete mode 100644 node_modules/whatwg-url/lib/URL-impl.js delete mode 100644 node_modules/whatwg-url/lib/URL.js delete mode 100644 node_modules/whatwg-url/lib/public-api.js delete mode 100644 node_modules/whatwg-url/lib/url-state-machine.js delete mode 100644 node_modules/whatwg-url/lib/utils.js delete mode 100644 node_modules/whatwg-url/package.json diff --git a/node_modules/.package-lock.json b/node_modules/.package-lock.json index cf73c43f..ff6e8ab3 100644 --- a/node_modules/.package-lock.json +++ b/node_modules/.package-lock.json @@ -3,44 +3,5 @@ "version": "1.0.0", "lockfileVersion": 3, "requires": true, - "packages": { - "node_modules/node-fetch": { - "version": "2.7.0", - "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.7.0.tgz", - "integrity": "sha512-c4FRfUm/dbcWZ7U+1Wq0AwCyFL+3nt2bEw05wfxSz+DWpWsitgmSgYmy2dQdWyKC1694ELPqMs/YzUSNozLt8A==", - "dependencies": { - "whatwg-url": "^5.0.0" - }, - "engines": { - "node": "4.x || >=6.0.0" - }, - "peerDependencies": { - "encoding": "^0.1.0" - }, - "peerDependenciesMeta": { - "encoding": { - "optional": true - } - } - }, - "node_modules/tr46": { - "version": "0.0.3", - "resolved": "https://registry.npmjs.org/tr46/-/tr46-0.0.3.tgz", - "integrity": "sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw==" - }, - "node_modules/webidl-conversions": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-3.0.1.tgz", - "integrity": "sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ==" - }, - "node_modules/whatwg-url": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-5.0.0.tgz", - "integrity": "sha512-saE57nupxk6v3HY35+jzBwYa0rKSy0XR8JSxZPwgLr7ys0IBzhGviA1/TUGJLmSVqs8pb9AnvICXEuOHLprYTw==", - "dependencies": { - "tr46": "~0.0.3", - "webidl-conversions": "^3.0.0" - } - } - } + "packages": {} } diff --git a/node_modules/node-fetch/LICENSE.md b/node_modules/node-fetch/LICENSE.md deleted file mode 100644 index 660ffecb..00000000 --- a/node_modules/node-fetch/LICENSE.md +++ /dev/null @@ -1,22 +0,0 @@ -The MIT License (MIT) - -Copyright (c) 2016 David Frank - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. - diff --git a/node_modules/node-fetch/README.md b/node_modules/node-fetch/README.md deleted file mode 100644 index 55f09b7f..00000000 --- a/node_modules/node-fetch/README.md +++ /dev/null @@ -1,634 +0,0 @@ -node-fetch -========== - -[![npm version][npm-image]][npm-url] -[![build status][travis-image]][travis-url] -[![coverage status][codecov-image]][codecov-url] -[![install size][install-size-image]][install-size-url] -[![Discord][discord-image]][discord-url] - -A light-weight module that brings `window.fetch` to Node.js - -(We are looking for [v2 maintainers and collaborators](https://github.com/bitinn/node-fetch/issues/567)) - -[![Backers][opencollective-image]][opencollective-url] - - - -- [Motivation](#motivation) -- [Features](#features) -- [Difference from client-side fetch](#difference-from-client-side-fetch) -- [Installation](#installation) -- [Loading and configuring the module](#loading-and-configuring-the-module) -- [Common Usage](#common-usage) - - [Plain text or HTML](#plain-text-or-html) - - [JSON](#json) - - [Simple Post](#simple-post) - - [Post with JSON](#post-with-json) - - [Post with form parameters](#post-with-form-parameters) - - [Handling exceptions](#handling-exceptions) - - [Handling client and server errors](#handling-client-and-server-errors) -- [Advanced Usage](#advanced-usage) - - [Streams](#streams) - - [Buffer](#buffer) - - [Accessing Headers and other Meta data](#accessing-headers-and-other-meta-data) - - [Extract Set-Cookie Header](#extract-set-cookie-header) - - [Post data using a file stream](#post-data-using-a-file-stream) - - [Post with form-data (detect multipart)](#post-with-form-data-detect-multipart) - - [Request cancellation with AbortSignal](#request-cancellation-with-abortsignal) -- [API](#api) - - [fetch(url[, options])](#fetchurl-options) - - [Options](#options) - - [Class: Request](#class-request) - - [Class: Response](#class-response) - - [Class: Headers](#class-headers) - - [Interface: Body](#interface-body) - - [Class: FetchError](#class-fetcherror) -- [License](#license) -- [Acknowledgement](#acknowledgement) - - - -## Motivation - -Instead of implementing `XMLHttpRequest` in Node.js to run browser-specific [Fetch polyfill](https://github.com/github/fetch), why not go from native `http` to `fetch` API directly? Hence, `node-fetch`, minimal code for a `window.fetch` compatible API on Node.js runtime. - -See Matt Andrews' [isomorphic-fetch](https://github.com/matthew-andrews/isomorphic-fetch) or Leonardo Quixada's [cross-fetch](https://github.com/lquixada/cross-fetch) for isomorphic usage (exports `node-fetch` for server-side, `whatwg-fetch` for client-side). - -## Features - -- Stay consistent with `window.fetch` API. -- Make conscious trade-off when following [WHATWG fetch spec][whatwg-fetch] and [stream spec](https://streams.spec.whatwg.org/) implementation details, document known differences. -- Use native promise but allow substituting it with [insert your favorite promise library]. -- Use native Node streams for body on both request and response. -- Decode content encoding (gzip/deflate) properly and convert string output (such as `res.text()` and `res.json()`) to UTF-8 automatically. -- Useful extensions such as timeout, redirect limit, response size limit, [explicit errors](ERROR-HANDLING.md) for troubleshooting. - -## Difference from client-side fetch - -- See [Known Differences](LIMITS.md) for details. -- If you happen to use a missing feature that `window.fetch` offers, feel free to open an issue. -- Pull requests are welcomed too! - -## Installation - -Current stable release (`2.x`) - -```sh -$ npm install node-fetch -``` - -## Loading and configuring the module -We suggest you load the module via `require` until the stabilization of ES modules in node: -```js -const fetch = require('node-fetch'); -``` - -If you are using a Promise library other than native, set it through `fetch.Promise`: -```js -const Bluebird = require('bluebird'); - -fetch.Promise = Bluebird; -``` - -## Common Usage - -NOTE: The documentation below is up-to-date with `2.x` releases; see the [`1.x` readme](https://github.com/bitinn/node-fetch/blob/1.x/README.md), [changelog](https://github.com/bitinn/node-fetch/blob/1.x/CHANGELOG.md) and [2.x upgrade guide](UPGRADE-GUIDE.md) for the differences. - -#### Plain text or HTML -```js -fetch('https://github.com/') - .then(res => res.text()) - .then(body => console.log(body)); -``` - -#### JSON - -```js - -fetch('https://api.github.com/users/github') - .then(res => res.json()) - .then(json => console.log(json)); -``` - -#### Simple Post -```js -fetch('https://httpbin.org/post', { method: 'POST', body: 'a=1' }) - .then(res => res.json()) // expecting a json response - .then(json => console.log(json)); -``` - -#### Post with JSON - -```js -const body = { a: 1 }; - -fetch('https://httpbin.org/post', { - method: 'post', - body: JSON.stringify(body), - headers: { 'Content-Type': 'application/json' }, - }) - .then(res => res.json()) - .then(json => console.log(json)); -``` - -#### Post with form parameters -`URLSearchParams` is available in Node.js as of v7.5.0. See [official documentation](https://nodejs.org/api/url.html#url_class_urlsearchparams) for more usage methods. - -NOTE: The `Content-Type` header is only set automatically to `x-www-form-urlencoded` when an instance of `URLSearchParams` is given as such: - -```js -const { URLSearchParams } = require('url'); - -const params = new URLSearchParams(); -params.append('a', 1); - -fetch('https://httpbin.org/post', { method: 'POST', body: params }) - .then(res => res.json()) - .then(json => console.log(json)); -``` - -#### Handling exceptions -NOTE: 3xx-5xx responses are *NOT* exceptions and should be handled in `then()`; see the next section for more information. - -Adding a catch to the fetch promise chain will catch *all* exceptions, such as errors originating from node core libraries, network errors and operational errors, which are instances of FetchError. See the [error handling document](ERROR-HANDLING.md) for more details. - -```js -fetch('https://domain.invalid/') - .catch(err => console.error(err)); -``` - -#### Handling client and server errors -It is common to create a helper function to check that the response contains no client (4xx) or server (5xx) error responses: - -```js -function checkStatus(res) { - if (res.ok) { // res.status >= 200 && res.status < 300 - return res; - } else { - throw MyCustomError(res.statusText); - } -} - -fetch('https://httpbin.org/status/400') - .then(checkStatus) - .then(res => console.log('will not get here...')) -``` - -## Advanced Usage - -#### Streams -The "Node.js way" is to use streams when possible: - -```js -fetch('https://assets-cdn.github.com/images/modules/logos_page/Octocat.png') - .then(res => { - const dest = fs.createWriteStream('./octocat.png'); - res.body.pipe(dest); - }); -``` - -In Node.js 14 you can also use async iterators to read `body`; however, be careful to catch -errors -- the longer a response runs, the more likely it is to encounter an error. - -```js -const fetch = require('node-fetch'); -const response = await fetch('https://httpbin.org/stream/3'); -try { - for await (const chunk of response.body) { - console.dir(JSON.parse(chunk.toString())); - } -} catch (err) { - console.error(err.stack); -} -``` - -In Node.js 12 you can also use async iterators to read `body`; however, async iterators with streams -did not mature until Node.js 14, so you need to do some extra work to ensure you handle errors -directly from the stream and wait on it response to fully close. - -```js -const fetch = require('node-fetch'); -const read = async body => { - let error; - body.on('error', err => { - error = err; - }); - for await (const chunk of body) { - console.dir(JSON.parse(chunk.toString())); - } - return new Promise((resolve, reject) => { - body.on('close', () => { - error ? reject(error) : resolve(); - }); - }); -}; -try { - const response = await fetch('https://httpbin.org/stream/3'); - await read(response.body); -} catch (err) { - console.error(err.stack); -} -``` - -#### Buffer -If you prefer to cache binary data in full, use buffer(). (NOTE: `buffer()` is a `node-fetch`-only API) - -```js -const fileType = require('file-type'); - -fetch('https://assets-cdn.github.com/images/modules/logos_page/Octocat.png') - .then(res => res.buffer()) - .then(buffer => fileType(buffer)) - .then(type => { /* ... */ }); -``` - -#### Accessing Headers and other Meta data -```js -fetch('https://github.com/') - .then(res => { - console.log(res.ok); - console.log(res.status); - console.log(res.statusText); - console.log(res.headers.raw()); - console.log(res.headers.get('content-type')); - }); -``` - -#### Extract Set-Cookie Header - -Unlike browsers, you can access raw `Set-Cookie` headers manually using `Headers.raw()`. This is a `node-fetch` only API. - -```js -fetch(url).then(res => { - // returns an array of values, instead of a string of comma-separated values - console.log(res.headers.raw()['set-cookie']); -}); -``` - -#### Post data using a file stream - -```js -const { createReadStream } = require('fs'); - -const stream = createReadStream('input.txt'); - -fetch('https://httpbin.org/post', { method: 'POST', body: stream }) - .then(res => res.json()) - .then(json => console.log(json)); -``` - -#### Post with form-data (detect multipart) - -```js -const FormData = require('form-data'); - -const form = new FormData(); -form.append('a', 1); - -fetch('https://httpbin.org/post', { method: 'POST', body: form }) - .then(res => res.json()) - .then(json => console.log(json)); - -// OR, using custom headers -// NOTE: getHeaders() is non-standard API - -const form = new FormData(); -form.append('a', 1); - -const options = { - method: 'POST', - body: form, - headers: form.getHeaders() -} - -fetch('https://httpbin.org/post', options) - .then(res => res.json()) - .then(json => console.log(json)); -``` - -#### Request cancellation with AbortSignal - -> NOTE: You may cancel streamed requests only on Node >= v8.0.0 - -You may cancel requests with `AbortController`. A suggested implementation is [`abort-controller`](https://www.npmjs.com/package/abort-controller). - -An example of timing out a request after 150ms could be achieved as the following: - -```js -import AbortController from 'abort-controller'; - -const controller = new AbortController(); -const timeout = setTimeout( - () => { controller.abort(); }, - 150, -); - -fetch(url, { signal: controller.signal }) - .then(res => res.json()) - .then( - data => { - useData(data) - }, - err => { - if (err.name === 'AbortError') { - // request was aborted - } - }, - ) - .finally(() => { - clearTimeout(timeout); - }); -``` - -See [test cases](https://github.com/bitinn/node-fetch/blob/master/test/test.js) for more examples. - - -## API - -### fetch(url[, options]) - -- `url` A string representing the URL for fetching -- `options` [Options](#fetch-options) for the HTTP(S) request -- Returns: Promise<[Response](#class-response)> - -Perform an HTTP(S) fetch. - -`url` should be an absolute url, such as `https://example.com/`. A path-relative URL (`/file/under/root`) or protocol-relative URL (`//can-be-http-or-https.com/`) will result in a rejected `Promise`. - - -### Options - -The default values are shown after each option key. - -```js -{ - // These properties are part of the Fetch Standard - method: 'GET', - headers: {}, // request headers. format is the identical to that accepted by the Headers constructor (see below) - body: null, // request body. can be null, a string, a Buffer, a Blob, or a Node.js Readable stream - redirect: 'follow', // set to `manual` to extract redirect headers, `error` to reject redirect - signal: null, // pass an instance of AbortSignal to optionally abort requests - - // The following properties are node-fetch extensions - follow: 20, // maximum redirect count. 0 to not follow redirect - timeout: 0, // req/res timeout in ms, it resets on redirect. 0 to disable (OS limit applies). Signal is recommended instead. - compress: true, // support gzip/deflate content encoding. false to disable - size: 0, // maximum response body size in bytes. 0 to disable - agent: null // http(s).Agent instance or function that returns an instance (see below) -} -``` - -##### Default Headers - -If no values are set, the following request headers will be sent automatically: - -Header | Value -------------------- | -------------------------------------------------------- -`Accept-Encoding` | `gzip,deflate` _(when `options.compress === true`)_ -`Accept` | `*/*` -`Content-Length` | _(automatically calculated, if possible)_ -`Transfer-Encoding` | `chunked` _(when `req.body` is a stream)_ -`User-Agent` | `node-fetch/1.0 (+https://github.com/bitinn/node-fetch)` - -Note: when `body` is a `Stream`, `Content-Length` is not set automatically. - -##### Custom Agent - -The `agent` option allows you to specify networking related options which are out of the scope of Fetch, including and not limited to the following: - -- Support self-signed certificate -- Use only IPv4 or IPv6 -- Custom DNS Lookup - -See [`http.Agent`](https://nodejs.org/api/http.html#http_new_agent_options) for more information. - -If no agent is specified, the default agent provided by Node.js is used. Note that [this changed in Node.js 19](https://github.com/nodejs/node/blob/4267b92604ad78584244488e7f7508a690cb80d0/lib/_http_agent.js#L564) to have `keepalive` true by default. If you wish to enable `keepalive` in an earlier version of Node.js, you can override the agent as per the following code sample. - -In addition, the `agent` option accepts a function that returns `http`(s)`.Agent` instance given current [URL](https://nodejs.org/api/url.html), this is useful during a redirection chain across HTTP and HTTPS protocol. - -```js -const httpAgent = new http.Agent({ - keepAlive: true -}); -const httpsAgent = new https.Agent({ - keepAlive: true -}); - -const options = { - agent: function (_parsedURL) { - if (_parsedURL.protocol == 'http:') { - return httpAgent; - } else { - return httpsAgent; - } - } -} -``` - - -### Class: Request - -An HTTP(S) request containing information about URL, method, headers, and the body. This class implements the [Body](#iface-body) interface. - -Due to the nature of Node.js, the following properties are not implemented at this moment: - -- `type` -- `destination` -- `referrer` -- `referrerPolicy` -- `mode` -- `credentials` -- `cache` -- `integrity` -- `keepalive` - -The following node-fetch extension properties are provided: - -- `follow` -- `compress` -- `counter` -- `agent` - -See [options](#fetch-options) for exact meaning of these extensions. - -#### new Request(input[, options]) - -*(spec-compliant)* - -- `input` A string representing a URL, or another `Request` (which will be cloned) -- `options` [Options][#fetch-options] for the HTTP(S) request - -Constructs a new `Request` object. The constructor is identical to that in the [browser](https://developer.mozilla.org/en-US/docs/Web/API/Request/Request). - -In most cases, directly `fetch(url, options)` is simpler than creating a `Request` object. - - -### Class: Response - -An HTTP(S) response. This class implements the [Body](#iface-body) interface. - -The following properties are not implemented in node-fetch at this moment: - -- `Response.error()` -- `Response.redirect()` -- `type` -- `trailer` - -#### new Response([body[, options]]) - -*(spec-compliant)* - -- `body` A `String` or [`Readable` stream][node-readable] -- `options` A [`ResponseInit`][response-init] options dictionary - -Constructs a new `Response` object. The constructor is identical to that in the [browser](https://developer.mozilla.org/en-US/docs/Web/API/Response/Response). - -Because Node.js does not implement service workers (for which this class was designed), one rarely has to construct a `Response` directly. - -#### response.ok - -*(spec-compliant)* - -Convenience property representing if the request ended normally. Will evaluate to true if the response status was greater than or equal to 200 but smaller than 300. - -#### response.redirected - -*(spec-compliant)* - -Convenience property representing if the request has been redirected at least once. Will evaluate to true if the internal redirect counter is greater than 0. - - -### Class: Headers - -This class allows manipulating and iterating over a set of HTTP headers. All methods specified in the [Fetch Standard][whatwg-fetch] are implemented. - -#### new Headers([init]) - -*(spec-compliant)* - -- `init` Optional argument to pre-fill the `Headers` object - -Construct a new `Headers` object. `init` can be either `null`, a `Headers` object, an key-value map object or any iterable object. - -```js -// Example adapted from https://fetch.spec.whatwg.org/#example-headers-class - -const meta = { - 'Content-Type': 'text/xml', - 'Breaking-Bad': '<3' -}; -const headers = new Headers(meta); - -// The above is equivalent to -const meta = [ - [ 'Content-Type', 'text/xml' ], - [ 'Breaking-Bad', '<3' ] -]; -const headers = new Headers(meta); - -// You can in fact use any iterable objects, like a Map or even another Headers -const meta = new Map(); -meta.set('Content-Type', 'text/xml'); -meta.set('Breaking-Bad', '<3'); -const headers = new Headers(meta); -const copyOfHeaders = new Headers(headers); -``` - - -### Interface: Body - -`Body` is an abstract interface with methods that are applicable to both `Request` and `Response` classes. - -The following methods are not yet implemented in node-fetch at this moment: - -- `formData()` - -#### body.body - -*(deviation from spec)* - -* Node.js [`Readable` stream][node-readable] - -Data are encapsulated in the `Body` object. Note that while the [Fetch Standard][whatwg-fetch] requires the property to always be a WHATWG `ReadableStream`, in node-fetch it is a Node.js [`Readable` stream][node-readable]. - -#### body.bodyUsed - -*(spec-compliant)* - -* `Boolean` - -A boolean property for if this body has been consumed. Per the specs, a consumed body cannot be used again. - -#### body.arrayBuffer() -#### body.blob() -#### body.json() -#### body.text() - -*(spec-compliant)* - -* Returns: Promise - -Consume the body and return a promise that will resolve to one of these formats. - -#### body.buffer() - -*(node-fetch extension)* - -* Returns: Promise<Buffer> - -Consume the body and return a promise that will resolve to a Buffer. - -#### body.textConverted() - -*(node-fetch extension)* - -* Returns: Promise<String> - -Identical to `body.text()`, except instead of always converting to UTF-8, encoding sniffing will be performed and text converted to UTF-8 if possible. - -(This API requires an optional dependency of the npm package [encoding](https://www.npmjs.com/package/encoding), which you need to install manually. `webpack` users may see [a warning message](https://github.com/bitinn/node-fetch/issues/412#issuecomment-379007792) due to this optional dependency.) - - -### Class: FetchError - -*(node-fetch extension)* - -An operational error in the fetching process. See [ERROR-HANDLING.md][] for more info. - - -### Class: AbortError - -*(node-fetch extension)* - -An Error thrown when the request is aborted in response to an `AbortSignal`'s `abort` event. It has a `name` property of `AbortError`. See [ERROR-HANDLING.MD][] for more info. - -## Acknowledgement - -Thanks to [github/fetch](https://github.com/github/fetch) for providing a solid implementation reference. - -`node-fetch` v1 was maintained by [@bitinn](https://github.com/bitinn); v2 was maintained by [@TimothyGu](https://github.com/timothygu), [@bitinn](https://github.com/bitinn) and [@jimmywarting](https://github.com/jimmywarting); v2 readme is written by [@jkantr](https://github.com/jkantr). - -## License - -MIT - -[npm-image]: https://flat.badgen.net/npm/v/node-fetch -[npm-url]: https://www.npmjs.com/package/node-fetch -[travis-image]: https://flat.badgen.net/travis/bitinn/node-fetch -[travis-url]: https://travis-ci.org/bitinn/node-fetch -[codecov-image]: https://flat.badgen.net/codecov/c/github/bitinn/node-fetch/master -[codecov-url]: https://codecov.io/gh/bitinn/node-fetch -[install-size-image]: https://flat.badgen.net/packagephobia/install/node-fetch -[install-size-url]: https://packagephobia.now.sh/result?p=node-fetch -[discord-image]: https://img.shields.io/discord/619915844268326952?color=%237289DA&label=Discord&style=flat-square -[discord-url]: https://discord.gg/Zxbndcm -[opencollective-image]: https://opencollective.com/node-fetch/backers.svg -[opencollective-url]: https://opencollective.com/node-fetch -[whatwg-fetch]: https://fetch.spec.whatwg.org/ -[response-init]: https://fetch.spec.whatwg.org/#responseinit -[node-readable]: https://nodejs.org/api/stream.html#stream_readable_streams -[mdn-headers]: https://developer.mozilla.org/en-US/docs/Web/API/Headers -[LIMITS.md]: https://github.com/bitinn/node-fetch/blob/master/LIMITS.md -[ERROR-HANDLING.md]: https://github.com/bitinn/node-fetch/blob/master/ERROR-HANDLING.md -[UPGRADE-GUIDE.md]: https://github.com/bitinn/node-fetch/blob/master/UPGRADE-GUIDE.md diff --git a/node_modules/node-fetch/browser.js b/node_modules/node-fetch/browser.js deleted file mode 100644 index ee86265a..00000000 --- a/node_modules/node-fetch/browser.js +++ /dev/null @@ -1,25 +0,0 @@ -"use strict"; - -// ref: https://github.com/tc39/proposal-global -var getGlobal = function () { - // the only reliable means to get the global object is - // `Function('return this')()` - // However, this causes CSP violations in Chrome apps. - if (typeof self !== 'undefined') { return self; } - if (typeof window !== 'undefined') { return window; } - if (typeof global !== 'undefined') { return global; } - throw new Error('unable to locate global object'); -} - -var globalObject = getGlobal(); - -module.exports = exports = globalObject.fetch; - -// Needed for TypeScript and Webpack. -if (globalObject.fetch) { - exports.default = globalObject.fetch.bind(globalObject); -} - -exports.Headers = globalObject.Headers; -exports.Request = globalObject.Request; -exports.Response = globalObject.Response; diff --git a/node_modules/node-fetch/lib/index.es.js b/node_modules/node-fetch/lib/index.es.js deleted file mode 100644 index aae9799c..00000000 --- a/node_modules/node-fetch/lib/index.es.js +++ /dev/null @@ -1,1777 +0,0 @@ -process.emitWarning("The .es.js file is deprecated. Use .mjs instead."); - -import Stream from 'stream'; -import http from 'http'; -import Url from 'url'; -import whatwgUrl from 'whatwg-url'; -import https from 'https'; -import zlib from 'zlib'; - -// Based on https://github.com/tmpvar/jsdom/blob/aa85b2abf07766ff7bf5c1f6daafb3726f2f2db5/lib/jsdom/living/blob.js - -// fix for "Readable" isn't a named export issue -const Readable = Stream.Readable; - -const BUFFER = Symbol('buffer'); -const TYPE = Symbol('type'); - -class Blob { - constructor() { - this[TYPE] = ''; - - const blobParts = arguments[0]; - const options = arguments[1]; - - const buffers = []; - let size = 0; - - if (blobParts) { - const a = blobParts; - const length = Number(a.length); - for (let i = 0; i < length; i++) { - const element = a[i]; - let buffer; - if (element instanceof Buffer) { - buffer = element; - } else if (ArrayBuffer.isView(element)) { - buffer = Buffer.from(element.buffer, element.byteOffset, element.byteLength); - } else if (element instanceof ArrayBuffer) { - buffer = Buffer.from(element); - } else if (element instanceof Blob) { - buffer = element[BUFFER]; - } else { - buffer = Buffer.from(typeof element === 'string' ? element : String(element)); - } - size += buffer.length; - buffers.push(buffer); - } - } - - this[BUFFER] = Buffer.concat(buffers); - - let type = options && options.type !== undefined && String(options.type).toLowerCase(); - if (type && !/[^\u0020-\u007E]/.test(type)) { - this[TYPE] = type; - } - } - get size() { - return this[BUFFER].length; - } - get type() { - return this[TYPE]; - } - text() { - return Promise.resolve(this[BUFFER].toString()); - } - arrayBuffer() { - const buf = this[BUFFER]; - const ab = buf.buffer.slice(buf.byteOffset, buf.byteOffset + buf.byteLength); - return Promise.resolve(ab); - } - stream() { - const readable = new Readable(); - readable._read = function () {}; - readable.push(this[BUFFER]); - readable.push(null); - return readable; - } - toString() { - return '[object Blob]'; - } - slice() { - const size = this.size; - - const start = arguments[0]; - const end = arguments[1]; - let relativeStart, relativeEnd; - if (start === undefined) { - relativeStart = 0; - } else if (start < 0) { - relativeStart = Math.max(size + start, 0); - } else { - relativeStart = Math.min(start, size); - } - if (end === undefined) { - relativeEnd = size; - } else if (end < 0) { - relativeEnd = Math.max(size + end, 0); - } else { - relativeEnd = Math.min(end, size); - } - const span = Math.max(relativeEnd - relativeStart, 0); - - const buffer = this[BUFFER]; - const slicedBuffer = buffer.slice(relativeStart, relativeStart + span); - const blob = new Blob([], { type: arguments[2] }); - blob[BUFFER] = slicedBuffer; - return blob; - } -} - -Object.defineProperties(Blob.prototype, { - size: { enumerable: true }, - type: { enumerable: true }, - slice: { enumerable: true } -}); - -Object.defineProperty(Blob.prototype, Symbol.toStringTag, { - value: 'Blob', - writable: false, - enumerable: false, - configurable: true -}); - -/** - * fetch-error.js - * - * FetchError interface for operational errors - */ - -/** - * Create FetchError instance - * - * @param String message Error message for human - * @param String type Error type for machine - * @param String systemError For Node.js system error - * @return FetchError - */ -function FetchError(message, type, systemError) { - Error.call(this, message); - - this.message = message; - this.type = type; - - // when err.type is `system`, err.code contains system error code - if (systemError) { - this.code = this.errno = systemError.code; - } - - // hide custom error implementation details from end-users - Error.captureStackTrace(this, this.constructor); -} - -FetchError.prototype = Object.create(Error.prototype); -FetchError.prototype.constructor = FetchError; -FetchError.prototype.name = 'FetchError'; - -let convert; -try { - convert = require('encoding').convert; -} catch (e) {} - -const INTERNALS = Symbol('Body internals'); - -// fix an issue where "PassThrough" isn't a named export for node <10 -const PassThrough = Stream.PassThrough; - -/** - * Body mixin - * - * Ref: https://fetch.spec.whatwg.org/#body - * - * @param Stream body Readable stream - * @param Object opts Response options - * @return Void - */ -function Body(body) { - var _this = this; - - var _ref = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {}, - _ref$size = _ref.size; - - let size = _ref$size === undefined ? 0 : _ref$size; - var _ref$timeout = _ref.timeout; - let timeout = _ref$timeout === undefined ? 0 : _ref$timeout; - - if (body == null) { - // body is undefined or null - body = null; - } else if (isURLSearchParams(body)) { - // body is a URLSearchParams - body = Buffer.from(body.toString()); - } else if (isBlob(body)) ; else if (Buffer.isBuffer(body)) ; else if (Object.prototype.toString.call(body) === '[object ArrayBuffer]') { - // body is ArrayBuffer - body = Buffer.from(body); - } else if (ArrayBuffer.isView(body)) { - // body is ArrayBufferView - body = Buffer.from(body.buffer, body.byteOffset, body.byteLength); - } else if (body instanceof Stream) ; else { - // none of the above - // coerce to string then buffer - body = Buffer.from(String(body)); - } - this[INTERNALS] = { - body, - disturbed: false, - error: null - }; - this.size = size; - this.timeout = timeout; - - if (body instanceof Stream) { - body.on('error', function (err) { - const error = err.name === 'AbortError' ? err : new FetchError(`Invalid response body while trying to fetch ${_this.url}: ${err.message}`, 'system', err); - _this[INTERNALS].error = error; - }); - } -} - -Body.prototype = { - get body() { - return this[INTERNALS].body; - }, - - get bodyUsed() { - return this[INTERNALS].disturbed; - }, - - /** - * Decode response as ArrayBuffer - * - * @return Promise - */ - arrayBuffer() { - return consumeBody.call(this).then(function (buf) { - return buf.buffer.slice(buf.byteOffset, buf.byteOffset + buf.byteLength); - }); - }, - - /** - * Return raw response as Blob - * - * @return Promise - */ - blob() { - let ct = this.headers && this.headers.get('content-type') || ''; - return consumeBody.call(this).then(function (buf) { - return Object.assign( - // Prevent copying - new Blob([], { - type: ct.toLowerCase() - }), { - [BUFFER]: buf - }); - }); - }, - - /** - * Decode response as json - * - * @return Promise - */ - json() { - var _this2 = this; - - return consumeBody.call(this).then(function (buffer) { - try { - return JSON.parse(buffer.toString()); - } catch (err) { - return Body.Promise.reject(new FetchError(`invalid json response body at ${_this2.url} reason: ${err.message}`, 'invalid-json')); - } - }); - }, - - /** - * Decode response as text - * - * @return Promise - */ - text() { - return consumeBody.call(this).then(function (buffer) { - return buffer.toString(); - }); - }, - - /** - * Decode response as buffer (non-spec api) - * - * @return Promise - */ - buffer() { - return consumeBody.call(this); - }, - - /** - * Decode response as text, while automatically detecting the encoding and - * trying to decode to UTF-8 (non-spec api) - * - * @return Promise - */ - textConverted() { - var _this3 = this; - - return consumeBody.call(this).then(function (buffer) { - return convertBody(buffer, _this3.headers); - }); - } -}; - -// In browsers, all properties are enumerable. -Object.defineProperties(Body.prototype, { - body: { enumerable: true }, - bodyUsed: { enumerable: true }, - arrayBuffer: { enumerable: true }, - blob: { enumerable: true }, - json: { enumerable: true }, - text: { enumerable: true } -}); - -Body.mixIn = function (proto) { - for (const name of Object.getOwnPropertyNames(Body.prototype)) { - // istanbul ignore else: future proof - if (!(name in proto)) { - const desc = Object.getOwnPropertyDescriptor(Body.prototype, name); - Object.defineProperty(proto, name, desc); - } - } -}; - -/** - * Consume and convert an entire Body to a Buffer. - * - * Ref: https://fetch.spec.whatwg.org/#concept-body-consume-body - * - * @return Promise - */ -function consumeBody() { - var _this4 = this; - - if (this[INTERNALS].disturbed) { - return Body.Promise.reject(new TypeError(`body used already for: ${this.url}`)); - } - - this[INTERNALS].disturbed = true; - - if (this[INTERNALS].error) { - return Body.Promise.reject(this[INTERNALS].error); - } - - let body = this.body; - - // body is null - if (body === null) { - return Body.Promise.resolve(Buffer.alloc(0)); - } - - // body is blob - if (isBlob(body)) { - body = body.stream(); - } - - // body is buffer - if (Buffer.isBuffer(body)) { - return Body.Promise.resolve(body); - } - - // istanbul ignore if: should never happen - if (!(body instanceof Stream)) { - return Body.Promise.resolve(Buffer.alloc(0)); - } - - // body is stream - // get ready to actually consume the body - let accum = []; - let accumBytes = 0; - let abort = false; - - return new Body.Promise(function (resolve, reject) { - let resTimeout; - - // allow timeout on slow response body - if (_this4.timeout) { - resTimeout = setTimeout(function () { - abort = true; - reject(new FetchError(`Response timeout while trying to fetch ${_this4.url} (over ${_this4.timeout}ms)`, 'body-timeout')); - }, _this4.timeout); - } - - // handle stream errors - body.on('error', function (err) { - if (err.name === 'AbortError') { - // if the request was aborted, reject with this Error - abort = true; - reject(err); - } else { - // other errors, such as incorrect content-encoding - reject(new FetchError(`Invalid response body while trying to fetch ${_this4.url}: ${err.message}`, 'system', err)); - } - }); - - body.on('data', function (chunk) { - if (abort || chunk === null) { - return; - } - - if (_this4.size && accumBytes + chunk.length > _this4.size) { - abort = true; - reject(new FetchError(`content size at ${_this4.url} over limit: ${_this4.size}`, 'max-size')); - return; - } - - accumBytes += chunk.length; - accum.push(chunk); - }); - - body.on('end', function () { - if (abort) { - return; - } - - clearTimeout(resTimeout); - - try { - resolve(Buffer.concat(accum, accumBytes)); - } catch (err) { - // handle streams that have accumulated too much data (issue #414) - reject(new FetchError(`Could not create Buffer from response body for ${_this4.url}: ${err.message}`, 'system', err)); - } - }); - }); -} - -/** - * Detect buffer encoding and convert to target encoding - * ref: http://www.w3.org/TR/2011/WD-html5-20110113/parsing.html#determining-the-character-encoding - * - * @param Buffer buffer Incoming buffer - * @param String encoding Target encoding - * @return String - */ -function convertBody(buffer, headers) { - if (typeof convert !== 'function') { - throw new Error('The package `encoding` must be installed to use the textConverted() function'); - } - - const ct = headers.get('content-type'); - let charset = 'utf-8'; - let res, str; - - // header - if (ct) { - res = /charset=([^;]*)/i.exec(ct); - } - - // no charset in content type, peek at response body for at most 1024 bytes - str = buffer.slice(0, 1024).toString(); - - // html5 - if (!res && str) { - res = / 0 && arguments[0] !== undefined ? arguments[0] : undefined; - - this[MAP] = Object.create(null); - - if (init instanceof Headers) { - const rawHeaders = init.raw(); - const headerNames = Object.keys(rawHeaders); - - for (const headerName of headerNames) { - for (const value of rawHeaders[headerName]) { - this.append(headerName, value); - } - } - - return; - } - - // We don't worry about converting prop to ByteString here as append() - // will handle it. - if (init == null) ; else if (typeof init === 'object') { - const method = init[Symbol.iterator]; - if (method != null) { - if (typeof method !== 'function') { - throw new TypeError('Header pairs must be iterable'); - } - - // sequence> - // Note: per spec we have to first exhaust the lists then process them - const pairs = []; - for (const pair of init) { - if (typeof pair !== 'object' || typeof pair[Symbol.iterator] !== 'function') { - throw new TypeError('Each header pair must be iterable'); - } - pairs.push(Array.from(pair)); - } - - for (const pair of pairs) { - if (pair.length !== 2) { - throw new TypeError('Each header pair must be a name/value tuple'); - } - this.append(pair[0], pair[1]); - } - } else { - // record - for (const key of Object.keys(init)) { - const value = init[key]; - this.append(key, value); - } - } - } else { - throw new TypeError('Provided initializer must be an object'); - } - } - - /** - * Return combined header value given name - * - * @param String name Header name - * @return Mixed - */ - get(name) { - name = `${name}`; - validateName(name); - const key = find(this[MAP], name); - if (key === undefined) { - return null; - } - - return this[MAP][key].join(', '); - } - - /** - * Iterate over all headers - * - * @param Function callback Executed for each item with parameters (value, name, thisArg) - * @param Boolean thisArg `this` context for callback function - * @return Void - */ - forEach(callback) { - let thisArg = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : undefined; - - let pairs = getHeaders(this); - let i = 0; - while (i < pairs.length) { - var _pairs$i = pairs[i]; - const name = _pairs$i[0], - value = _pairs$i[1]; - - callback.call(thisArg, value, name, this); - pairs = getHeaders(this); - i++; - } - } - - /** - * Overwrite header values given name - * - * @param String name Header name - * @param String value Header value - * @return Void - */ - set(name, value) { - name = `${name}`; - value = `${value}`; - validateName(name); - validateValue(value); - const key = find(this[MAP], name); - this[MAP][key !== undefined ? key : name] = [value]; - } - - /** - * Append a value onto existing header - * - * @param String name Header name - * @param String value Header value - * @return Void - */ - append(name, value) { - name = `${name}`; - value = `${value}`; - validateName(name); - validateValue(value); - const key = find(this[MAP], name); - if (key !== undefined) { - this[MAP][key].push(value); - } else { - this[MAP][name] = [value]; - } - } - - /** - * Check for header name existence - * - * @param String name Header name - * @return Boolean - */ - has(name) { - name = `${name}`; - validateName(name); - return find(this[MAP], name) !== undefined; - } - - /** - * Delete all header values given name - * - * @param String name Header name - * @return Void - */ - delete(name) { - name = `${name}`; - validateName(name); - const key = find(this[MAP], name); - if (key !== undefined) { - delete this[MAP][key]; - } - } - - /** - * Return raw headers (non-spec api) - * - * @return Object - */ - raw() { - return this[MAP]; - } - - /** - * Get an iterator on keys. - * - * @return Iterator - */ - keys() { - return createHeadersIterator(this, 'key'); - } - - /** - * Get an iterator on values. - * - * @return Iterator - */ - values() { - return createHeadersIterator(this, 'value'); - } - - /** - * Get an iterator on entries. - * - * This is the default iterator of the Headers object. - * - * @return Iterator - */ - [Symbol.iterator]() { - return createHeadersIterator(this, 'key+value'); - } -} -Headers.prototype.entries = Headers.prototype[Symbol.iterator]; - -Object.defineProperty(Headers.prototype, Symbol.toStringTag, { - value: 'Headers', - writable: false, - enumerable: false, - configurable: true -}); - -Object.defineProperties(Headers.prototype, { - get: { enumerable: true }, - forEach: { enumerable: true }, - set: { enumerable: true }, - append: { enumerable: true }, - has: { enumerable: true }, - delete: { enumerable: true }, - keys: { enumerable: true }, - values: { enumerable: true }, - entries: { enumerable: true } -}); - -function getHeaders(headers) { - let kind = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 'key+value'; - - const keys = Object.keys(headers[MAP]).sort(); - return keys.map(kind === 'key' ? function (k) { - return k.toLowerCase(); - } : kind === 'value' ? function (k) { - return headers[MAP][k].join(', '); - } : function (k) { - return [k.toLowerCase(), headers[MAP][k].join(', ')]; - }); -} - -const INTERNAL = Symbol('internal'); - -function createHeadersIterator(target, kind) { - const iterator = Object.create(HeadersIteratorPrototype); - iterator[INTERNAL] = { - target, - kind, - index: 0 - }; - return iterator; -} - -const HeadersIteratorPrototype = Object.setPrototypeOf({ - next() { - // istanbul ignore if - if (!this || Object.getPrototypeOf(this) !== HeadersIteratorPrototype) { - throw new TypeError('Value of `this` is not a HeadersIterator'); - } - - var _INTERNAL = this[INTERNAL]; - const target = _INTERNAL.target, - kind = _INTERNAL.kind, - index = _INTERNAL.index; - - const values = getHeaders(target, kind); - const len = values.length; - if (index >= len) { - return { - value: undefined, - done: true - }; - } - - this[INTERNAL].index = index + 1; - - return { - value: values[index], - done: false - }; - } -}, Object.getPrototypeOf(Object.getPrototypeOf([][Symbol.iterator]()))); - -Object.defineProperty(HeadersIteratorPrototype, Symbol.toStringTag, { - value: 'HeadersIterator', - writable: false, - enumerable: false, - configurable: true -}); - -/** - * Export the Headers object in a form that Node.js can consume. - * - * @param Headers headers - * @return Object - */ -function exportNodeCompatibleHeaders(headers) { - const obj = Object.assign({ __proto__: null }, headers[MAP]); - - // http.request() only supports string as Host header. This hack makes - // specifying custom Host header possible. - const hostHeaderKey = find(headers[MAP], 'Host'); - if (hostHeaderKey !== undefined) { - obj[hostHeaderKey] = obj[hostHeaderKey][0]; - } - - return obj; -} - -/** - * Create a Headers object from an object of headers, ignoring those that do - * not conform to HTTP grammar productions. - * - * @param Object obj Object of headers - * @return Headers - */ -function createHeadersLenient(obj) { - const headers = new Headers(); - for (const name of Object.keys(obj)) { - if (invalidTokenRegex.test(name)) { - continue; - } - if (Array.isArray(obj[name])) { - for (const val of obj[name]) { - if (invalidHeaderCharRegex.test(val)) { - continue; - } - if (headers[MAP][name] === undefined) { - headers[MAP][name] = [val]; - } else { - headers[MAP][name].push(val); - } - } - } else if (!invalidHeaderCharRegex.test(obj[name])) { - headers[MAP][name] = [obj[name]]; - } - } - return headers; -} - -const INTERNALS$1 = Symbol('Response internals'); - -// fix an issue where "STATUS_CODES" aren't a named export for node <10 -const STATUS_CODES = http.STATUS_CODES; - -/** - * Response class - * - * @param Stream body Readable stream - * @param Object opts Response options - * @return Void - */ -class Response { - constructor() { - let body = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : null; - let opts = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {}; - - Body.call(this, body, opts); - - const status = opts.status || 200; - const headers = new Headers(opts.headers); - - if (body != null && !headers.has('Content-Type')) { - const contentType = extractContentType(body); - if (contentType) { - headers.append('Content-Type', contentType); - } - } - - this[INTERNALS$1] = { - url: opts.url, - status, - statusText: opts.statusText || STATUS_CODES[status], - headers, - counter: opts.counter - }; - } - - get url() { - return this[INTERNALS$1].url || ''; - } - - get status() { - return this[INTERNALS$1].status; - } - - /** - * Convenience property representing if the request ended normally - */ - get ok() { - return this[INTERNALS$1].status >= 200 && this[INTERNALS$1].status < 300; - } - - get redirected() { - return this[INTERNALS$1].counter > 0; - } - - get statusText() { - return this[INTERNALS$1].statusText; - } - - get headers() { - return this[INTERNALS$1].headers; - } - - /** - * Clone this response - * - * @return Response - */ - clone() { - return new Response(clone(this), { - url: this.url, - status: this.status, - statusText: this.statusText, - headers: this.headers, - ok: this.ok, - redirected: this.redirected - }); - } -} - -Body.mixIn(Response.prototype); - -Object.defineProperties(Response.prototype, { - url: { enumerable: true }, - status: { enumerable: true }, - ok: { enumerable: true }, - redirected: { enumerable: true }, - statusText: { enumerable: true }, - headers: { enumerable: true }, - clone: { enumerable: true } -}); - -Object.defineProperty(Response.prototype, Symbol.toStringTag, { - value: 'Response', - writable: false, - enumerable: false, - configurable: true -}); - -const INTERNALS$2 = Symbol('Request internals'); -const URL = Url.URL || whatwgUrl.URL; - -// fix an issue where "format", "parse" aren't a named export for node <10 -const parse_url = Url.parse; -const format_url = Url.format; - -/** - * Wrapper around `new URL` to handle arbitrary URLs - * - * @param {string} urlStr - * @return {void} - */ -function parseURL(urlStr) { - /* - Check whether the URL is absolute or not - Scheme: https://tools.ietf.org/html/rfc3986#section-3.1 - Absolute URL: https://tools.ietf.org/html/rfc3986#section-4.3 - */ - if (/^[a-zA-Z][a-zA-Z\d+\-.]*:/.exec(urlStr)) { - urlStr = new URL(urlStr).toString(); - } - - // Fallback to old implementation for arbitrary URLs - return parse_url(urlStr); -} - -const streamDestructionSupported = 'destroy' in Stream.Readable.prototype; - -/** - * Check if a value is an instance of Request. - * - * @param Mixed input - * @return Boolean - */ -function isRequest(input) { - return typeof input === 'object' && typeof input[INTERNALS$2] === 'object'; -} - -function isAbortSignal(signal) { - const proto = signal && typeof signal === 'object' && Object.getPrototypeOf(signal); - return !!(proto && proto.constructor.name === 'AbortSignal'); -} - -/** - * Request class - * - * @param Mixed input Url or Request instance - * @param Object init Custom options - * @return Void - */ -class Request { - constructor(input) { - let init = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {}; - - let parsedURL; - - // normalize input - if (!isRequest(input)) { - if (input && input.href) { - // in order to support Node.js' Url objects; though WHATWG's URL objects - // will fall into this branch also (since their `toString()` will return - // `href` property anyway) - parsedURL = parseURL(input.href); - } else { - // coerce input to a string before attempting to parse - parsedURL = parseURL(`${input}`); - } - input = {}; - } else { - parsedURL = parseURL(input.url); - } - - let method = init.method || input.method || 'GET'; - method = method.toUpperCase(); - - if ((init.body != null || isRequest(input) && input.body !== null) && (method === 'GET' || method === 'HEAD')) { - throw new TypeError('Request with GET/HEAD method cannot have body'); - } - - let inputBody = init.body != null ? init.body : isRequest(input) && input.body !== null ? clone(input) : null; - - Body.call(this, inputBody, { - timeout: init.timeout || input.timeout || 0, - size: init.size || input.size || 0 - }); - - const headers = new Headers(init.headers || input.headers || {}); - - if (inputBody != null && !headers.has('Content-Type')) { - const contentType = extractContentType(inputBody); - if (contentType) { - headers.append('Content-Type', contentType); - } - } - - let signal = isRequest(input) ? input.signal : null; - if ('signal' in init) signal = init.signal; - - if (signal != null && !isAbortSignal(signal)) { - throw new TypeError('Expected signal to be an instanceof AbortSignal'); - } - - this[INTERNALS$2] = { - method, - redirect: init.redirect || input.redirect || 'follow', - headers, - parsedURL, - signal - }; - - // node-fetch-only options - this.follow = init.follow !== undefined ? init.follow : input.follow !== undefined ? input.follow : 20; - this.compress = init.compress !== undefined ? init.compress : input.compress !== undefined ? input.compress : true; - this.counter = init.counter || input.counter || 0; - this.agent = init.agent || input.agent; - } - - get method() { - return this[INTERNALS$2].method; - } - - get url() { - return format_url(this[INTERNALS$2].parsedURL); - } - - get headers() { - return this[INTERNALS$2].headers; - } - - get redirect() { - return this[INTERNALS$2].redirect; - } - - get signal() { - return this[INTERNALS$2].signal; - } - - /** - * Clone this request - * - * @return Request - */ - clone() { - return new Request(this); - } -} - -Body.mixIn(Request.prototype); - -Object.defineProperty(Request.prototype, Symbol.toStringTag, { - value: 'Request', - writable: false, - enumerable: false, - configurable: true -}); - -Object.defineProperties(Request.prototype, { - method: { enumerable: true }, - url: { enumerable: true }, - headers: { enumerable: true }, - redirect: { enumerable: true }, - clone: { enumerable: true }, - signal: { enumerable: true } -}); - -/** - * Convert a Request to Node.js http request options. - * - * @param Request A Request instance - * @return Object The options object to be passed to http.request - */ -function getNodeRequestOptions(request) { - const parsedURL = request[INTERNALS$2].parsedURL; - const headers = new Headers(request[INTERNALS$2].headers); - - // fetch step 1.3 - if (!headers.has('Accept')) { - headers.set('Accept', '*/*'); - } - - // Basic fetch - if (!parsedURL.protocol || !parsedURL.hostname) { - throw new TypeError('Only absolute URLs are supported'); - } - - if (!/^https?:$/.test(parsedURL.protocol)) { - throw new TypeError('Only HTTP(S) protocols are supported'); - } - - if (request.signal && request.body instanceof Stream.Readable && !streamDestructionSupported) { - throw new Error('Cancellation of streamed requests with AbortSignal is not supported in node < 8'); - } - - // HTTP-network-or-cache fetch steps 2.4-2.7 - let contentLengthValue = null; - if (request.body == null && /^(POST|PUT)$/i.test(request.method)) { - contentLengthValue = '0'; - } - if (request.body != null) { - const totalBytes = getTotalBytes(request); - if (typeof totalBytes === 'number') { - contentLengthValue = String(totalBytes); - } - } - if (contentLengthValue) { - headers.set('Content-Length', contentLengthValue); - } - - // HTTP-network-or-cache fetch step 2.11 - if (!headers.has('User-Agent')) { - headers.set('User-Agent', 'node-fetch/1.0 (+https://github.com/bitinn/node-fetch)'); - } - - // HTTP-network-or-cache fetch step 2.15 - if (request.compress && !headers.has('Accept-Encoding')) { - headers.set('Accept-Encoding', 'gzip,deflate'); - } - - let agent = request.agent; - if (typeof agent === 'function') { - agent = agent(parsedURL); - } - - // HTTP-network fetch step 4.2 - // chunked encoding is handled by Node.js - - return Object.assign({}, parsedURL, { - method: request.method, - headers: exportNodeCompatibleHeaders(headers), - agent - }); -} - -/** - * abort-error.js - * - * AbortError interface for cancelled requests - */ - -/** - * Create AbortError instance - * - * @param String message Error message for human - * @return AbortError - */ -function AbortError(message) { - Error.call(this, message); - - this.type = 'aborted'; - this.message = message; - - // hide custom error implementation details from end-users - Error.captureStackTrace(this, this.constructor); -} - -AbortError.prototype = Object.create(Error.prototype); -AbortError.prototype.constructor = AbortError; -AbortError.prototype.name = 'AbortError'; - -const URL$1 = Url.URL || whatwgUrl.URL; - -// fix an issue where "PassThrough", "resolve" aren't a named export for node <10 -const PassThrough$1 = Stream.PassThrough; - -const isDomainOrSubdomain = function isDomainOrSubdomain(destination, original) { - const orig = new URL$1(original).hostname; - const dest = new URL$1(destination).hostname; - - return orig === dest || orig[orig.length - dest.length - 1] === '.' && orig.endsWith(dest); -}; - -/** - * isSameProtocol reports whether the two provided URLs use the same protocol. - * - * Both domains must already be in canonical form. - * @param {string|URL} original - * @param {string|URL} destination - */ -const isSameProtocol = function isSameProtocol(destination, original) { - const orig = new URL$1(original).protocol; - const dest = new URL$1(destination).protocol; - - return orig === dest; -}; - -/** - * Fetch function - * - * @param Mixed url Absolute url or Request instance - * @param Object opts Fetch options - * @return Promise - */ -function fetch(url, opts) { - - // allow custom promise - if (!fetch.Promise) { - throw new Error('native promise missing, set fetch.Promise to your favorite alternative'); - } - - Body.Promise = fetch.Promise; - - // wrap http.request into fetch - return new fetch.Promise(function (resolve, reject) { - // build request object - const request = new Request(url, opts); - const options = getNodeRequestOptions(request); - - const send = (options.protocol === 'https:' ? https : http).request; - const signal = request.signal; - - let response = null; - - const abort = function abort() { - let error = new AbortError('The user aborted a request.'); - reject(error); - if (request.body && request.body instanceof Stream.Readable) { - destroyStream(request.body, error); - } - if (!response || !response.body) return; - response.body.emit('error', error); - }; - - if (signal && signal.aborted) { - abort(); - return; - } - - const abortAndFinalize = function abortAndFinalize() { - abort(); - finalize(); - }; - - // send request - const req = send(options); - let reqTimeout; - - if (signal) { - signal.addEventListener('abort', abortAndFinalize); - } - - function finalize() { - req.abort(); - if (signal) signal.removeEventListener('abort', abortAndFinalize); - clearTimeout(reqTimeout); - } - - if (request.timeout) { - req.once('socket', function (socket) { - reqTimeout = setTimeout(function () { - reject(new FetchError(`network timeout at: ${request.url}`, 'request-timeout')); - finalize(); - }, request.timeout); - }); - } - - req.on('error', function (err) { - reject(new FetchError(`request to ${request.url} failed, reason: ${err.message}`, 'system', err)); - - if (response && response.body) { - destroyStream(response.body, err); - } - - finalize(); - }); - - fixResponseChunkedTransferBadEnding(req, function (err) { - if (signal && signal.aborted) { - return; - } - - if (response && response.body) { - destroyStream(response.body, err); - } - }); - - /* c8 ignore next 18 */ - if (parseInt(process.version.substring(1)) < 14) { - // Before Node.js 14, pipeline() does not fully support async iterators and does not always - // properly handle when the socket close/end events are out of order. - req.on('socket', function (s) { - s.addListener('close', function (hadError) { - // if a data listener is still present we didn't end cleanly - const hasDataListener = s.listenerCount('data') > 0; - - // if end happened before close but the socket didn't emit an error, do it now - if (response && hasDataListener && !hadError && !(signal && signal.aborted)) { - const err = new Error('Premature close'); - err.code = 'ERR_STREAM_PREMATURE_CLOSE'; - response.body.emit('error', err); - } - }); - }); - } - - req.on('response', function (res) { - clearTimeout(reqTimeout); - - const headers = createHeadersLenient(res.headers); - - // HTTP fetch step 5 - if (fetch.isRedirect(res.statusCode)) { - // HTTP fetch step 5.2 - const location = headers.get('Location'); - - // HTTP fetch step 5.3 - let locationURL = null; - try { - locationURL = location === null ? null : new URL$1(location, request.url).toString(); - } catch (err) { - // error here can only be invalid URL in Location: header - // do not throw when options.redirect == manual - // let the user extract the errorneous redirect URL - if (request.redirect !== 'manual') { - reject(new FetchError(`uri requested responds with an invalid redirect URL: ${location}`, 'invalid-redirect')); - finalize(); - return; - } - } - - // HTTP fetch step 5.5 - switch (request.redirect) { - case 'error': - reject(new FetchError(`uri requested responds with a redirect, redirect mode is set to error: ${request.url}`, 'no-redirect')); - finalize(); - return; - case 'manual': - // node-fetch-specific step: make manual redirect a bit easier to use by setting the Location header value to the resolved URL. - if (locationURL !== null) { - // handle corrupted header - try { - headers.set('Location', locationURL); - } catch (err) { - // istanbul ignore next: nodejs server prevent invalid response headers, we can't test this through normal request - reject(err); - } - } - break; - case 'follow': - // HTTP-redirect fetch step 2 - if (locationURL === null) { - break; - } - - // HTTP-redirect fetch step 5 - if (request.counter >= request.follow) { - reject(new FetchError(`maximum redirect reached at: ${request.url}`, 'max-redirect')); - finalize(); - return; - } - - // HTTP-redirect fetch step 6 (counter increment) - // Create a new Request object. - const requestOpts = { - headers: new Headers(request.headers), - follow: request.follow, - counter: request.counter + 1, - agent: request.agent, - compress: request.compress, - method: request.method, - body: request.body, - signal: request.signal, - timeout: request.timeout, - size: request.size - }; - - if (!isDomainOrSubdomain(request.url, locationURL) || !isSameProtocol(request.url, locationURL)) { - for (const name of ['authorization', 'www-authenticate', 'cookie', 'cookie2']) { - requestOpts.headers.delete(name); - } - } - - // HTTP-redirect fetch step 9 - if (res.statusCode !== 303 && request.body && getTotalBytes(request) === null) { - reject(new FetchError('Cannot follow redirect with body being a readable stream', 'unsupported-redirect')); - finalize(); - return; - } - - // HTTP-redirect fetch step 11 - if (res.statusCode === 303 || (res.statusCode === 301 || res.statusCode === 302) && request.method === 'POST') { - requestOpts.method = 'GET'; - requestOpts.body = undefined; - requestOpts.headers.delete('content-length'); - } - - // HTTP-redirect fetch step 15 - resolve(fetch(new Request(locationURL, requestOpts))); - finalize(); - return; - } - } - - // prepare response - res.once('end', function () { - if (signal) signal.removeEventListener('abort', abortAndFinalize); - }); - let body = res.pipe(new PassThrough$1()); - - const response_options = { - url: request.url, - status: res.statusCode, - statusText: res.statusMessage, - headers: headers, - size: request.size, - timeout: request.timeout, - counter: request.counter - }; - - // HTTP-network fetch step 12.1.1.3 - const codings = headers.get('Content-Encoding'); - - // HTTP-network fetch step 12.1.1.4: handle content codings - - // in following scenarios we ignore compression support - // 1. compression support is disabled - // 2. HEAD request - // 3. no Content-Encoding header - // 4. no content response (204) - // 5. content not modified response (304) - if (!request.compress || request.method === 'HEAD' || codings === null || res.statusCode === 204 || res.statusCode === 304) { - response = new Response(body, response_options); - resolve(response); - return; - } - - // For Node v6+ - // Be less strict when decoding compressed responses, since sometimes - // servers send slightly invalid responses that are still accepted - // by common browsers. - // Always using Z_SYNC_FLUSH is what cURL does. - const zlibOptions = { - flush: zlib.Z_SYNC_FLUSH, - finishFlush: zlib.Z_SYNC_FLUSH - }; - - // for gzip - if (codings == 'gzip' || codings == 'x-gzip') { - body = body.pipe(zlib.createGunzip(zlibOptions)); - response = new Response(body, response_options); - resolve(response); - return; - } - - // for deflate - if (codings == 'deflate' || codings == 'x-deflate') { - // handle the infamous raw deflate response from old servers - // a hack for old IIS and Apache servers - const raw = res.pipe(new PassThrough$1()); - raw.once('data', function (chunk) { - // see http://stackoverflow.com/questions/37519828 - if ((chunk[0] & 0x0F) === 0x08) { - body = body.pipe(zlib.createInflate()); - } else { - body = body.pipe(zlib.createInflateRaw()); - } - response = new Response(body, response_options); - resolve(response); - }); - raw.on('end', function () { - // some old IIS servers return zero-length OK deflate responses, so 'data' is never emitted. - if (!response) { - response = new Response(body, response_options); - resolve(response); - } - }); - return; - } - - // for br - if (codings == 'br' && typeof zlib.createBrotliDecompress === 'function') { - body = body.pipe(zlib.createBrotliDecompress()); - response = new Response(body, response_options); - resolve(response); - return; - } - - // otherwise, use response as-is - response = new Response(body, response_options); - resolve(response); - }); - - writeToStream(req, request); - }); -} -function fixResponseChunkedTransferBadEnding(request, errorCallback) { - let socket; - - request.on('socket', function (s) { - socket = s; - }); - - request.on('response', function (response) { - const headers = response.headers; - - if (headers['transfer-encoding'] === 'chunked' && !headers['content-length']) { - response.once('close', function (hadError) { - // tests for socket presence, as in some situations the - // the 'socket' event is not triggered for the request - // (happens in deno), avoids `TypeError` - // if a data listener is still present we didn't end cleanly - const hasDataListener = socket && socket.listenerCount('data') > 0; - - if (hasDataListener && !hadError) { - const err = new Error('Premature close'); - err.code = 'ERR_STREAM_PREMATURE_CLOSE'; - errorCallback(err); - } - }); - } - }); -} - -function destroyStream(stream, err) { - if (stream.destroy) { - stream.destroy(err); - } else { - // node < 8 - stream.emit('error', err); - stream.end(); - } -} - -/** - * Redirect code matching - * - * @param Number code Status code - * @return Boolean - */ -fetch.isRedirect = function (code) { - return code === 301 || code === 302 || code === 303 || code === 307 || code === 308; -}; - -// expose Promise -fetch.Promise = global.Promise; - -export default fetch; -export { Headers, Request, Response, FetchError, AbortError }; diff --git a/node_modules/node-fetch/lib/index.js b/node_modules/node-fetch/lib/index.js deleted file mode 100644 index 567ff5da..00000000 --- a/node_modules/node-fetch/lib/index.js +++ /dev/null @@ -1,1787 +0,0 @@ -'use strict'; - -Object.defineProperty(exports, '__esModule', { value: true }); - -function _interopDefault (ex) { return (ex && (typeof ex === 'object') && 'default' in ex) ? ex['default'] : ex; } - -var Stream = _interopDefault(require('stream')); -var http = _interopDefault(require('http')); -var Url = _interopDefault(require('url')); -var whatwgUrl = _interopDefault(require('whatwg-url')); -var https = _interopDefault(require('https')); -var zlib = _interopDefault(require('zlib')); - -// Based on https://github.com/tmpvar/jsdom/blob/aa85b2abf07766ff7bf5c1f6daafb3726f2f2db5/lib/jsdom/living/blob.js - -// fix for "Readable" isn't a named export issue -const Readable = Stream.Readable; - -const BUFFER = Symbol('buffer'); -const TYPE = Symbol('type'); - -class Blob { - constructor() { - this[TYPE] = ''; - - const blobParts = arguments[0]; - const options = arguments[1]; - - const buffers = []; - let size = 0; - - if (blobParts) { - const a = blobParts; - const length = Number(a.length); - for (let i = 0; i < length; i++) { - const element = a[i]; - let buffer; - if (element instanceof Buffer) { - buffer = element; - } else if (ArrayBuffer.isView(element)) { - buffer = Buffer.from(element.buffer, element.byteOffset, element.byteLength); - } else if (element instanceof ArrayBuffer) { - buffer = Buffer.from(element); - } else if (element instanceof Blob) { - buffer = element[BUFFER]; - } else { - buffer = Buffer.from(typeof element === 'string' ? element : String(element)); - } - size += buffer.length; - buffers.push(buffer); - } - } - - this[BUFFER] = Buffer.concat(buffers); - - let type = options && options.type !== undefined && String(options.type).toLowerCase(); - if (type && !/[^\u0020-\u007E]/.test(type)) { - this[TYPE] = type; - } - } - get size() { - return this[BUFFER].length; - } - get type() { - return this[TYPE]; - } - text() { - return Promise.resolve(this[BUFFER].toString()); - } - arrayBuffer() { - const buf = this[BUFFER]; - const ab = buf.buffer.slice(buf.byteOffset, buf.byteOffset + buf.byteLength); - return Promise.resolve(ab); - } - stream() { - const readable = new Readable(); - readable._read = function () {}; - readable.push(this[BUFFER]); - readable.push(null); - return readable; - } - toString() { - return '[object Blob]'; - } - slice() { - const size = this.size; - - const start = arguments[0]; - const end = arguments[1]; - let relativeStart, relativeEnd; - if (start === undefined) { - relativeStart = 0; - } else if (start < 0) { - relativeStart = Math.max(size + start, 0); - } else { - relativeStart = Math.min(start, size); - } - if (end === undefined) { - relativeEnd = size; - } else if (end < 0) { - relativeEnd = Math.max(size + end, 0); - } else { - relativeEnd = Math.min(end, size); - } - const span = Math.max(relativeEnd - relativeStart, 0); - - const buffer = this[BUFFER]; - const slicedBuffer = buffer.slice(relativeStart, relativeStart + span); - const blob = new Blob([], { type: arguments[2] }); - blob[BUFFER] = slicedBuffer; - return blob; - } -} - -Object.defineProperties(Blob.prototype, { - size: { enumerable: true }, - type: { enumerable: true }, - slice: { enumerable: true } -}); - -Object.defineProperty(Blob.prototype, Symbol.toStringTag, { - value: 'Blob', - writable: false, - enumerable: false, - configurable: true -}); - -/** - * fetch-error.js - * - * FetchError interface for operational errors - */ - -/** - * Create FetchError instance - * - * @param String message Error message for human - * @param String type Error type for machine - * @param String systemError For Node.js system error - * @return FetchError - */ -function FetchError(message, type, systemError) { - Error.call(this, message); - - this.message = message; - this.type = type; - - // when err.type is `system`, err.code contains system error code - if (systemError) { - this.code = this.errno = systemError.code; - } - - // hide custom error implementation details from end-users - Error.captureStackTrace(this, this.constructor); -} - -FetchError.prototype = Object.create(Error.prototype); -FetchError.prototype.constructor = FetchError; -FetchError.prototype.name = 'FetchError'; - -let convert; -try { - convert = require('encoding').convert; -} catch (e) {} - -const INTERNALS = Symbol('Body internals'); - -// fix an issue where "PassThrough" isn't a named export for node <10 -const PassThrough = Stream.PassThrough; - -/** - * Body mixin - * - * Ref: https://fetch.spec.whatwg.org/#body - * - * @param Stream body Readable stream - * @param Object opts Response options - * @return Void - */ -function Body(body) { - var _this = this; - - var _ref = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {}, - _ref$size = _ref.size; - - let size = _ref$size === undefined ? 0 : _ref$size; - var _ref$timeout = _ref.timeout; - let timeout = _ref$timeout === undefined ? 0 : _ref$timeout; - - if (body == null) { - // body is undefined or null - body = null; - } else if (isURLSearchParams(body)) { - // body is a URLSearchParams - body = Buffer.from(body.toString()); - } else if (isBlob(body)) ; else if (Buffer.isBuffer(body)) ; else if (Object.prototype.toString.call(body) === '[object ArrayBuffer]') { - // body is ArrayBuffer - body = Buffer.from(body); - } else if (ArrayBuffer.isView(body)) { - // body is ArrayBufferView - body = Buffer.from(body.buffer, body.byteOffset, body.byteLength); - } else if (body instanceof Stream) ; else { - // none of the above - // coerce to string then buffer - body = Buffer.from(String(body)); - } - this[INTERNALS] = { - body, - disturbed: false, - error: null - }; - this.size = size; - this.timeout = timeout; - - if (body instanceof Stream) { - body.on('error', function (err) { - const error = err.name === 'AbortError' ? err : new FetchError(`Invalid response body while trying to fetch ${_this.url}: ${err.message}`, 'system', err); - _this[INTERNALS].error = error; - }); - } -} - -Body.prototype = { - get body() { - return this[INTERNALS].body; - }, - - get bodyUsed() { - return this[INTERNALS].disturbed; - }, - - /** - * Decode response as ArrayBuffer - * - * @return Promise - */ - arrayBuffer() { - return consumeBody.call(this).then(function (buf) { - return buf.buffer.slice(buf.byteOffset, buf.byteOffset + buf.byteLength); - }); - }, - - /** - * Return raw response as Blob - * - * @return Promise - */ - blob() { - let ct = this.headers && this.headers.get('content-type') || ''; - return consumeBody.call(this).then(function (buf) { - return Object.assign( - // Prevent copying - new Blob([], { - type: ct.toLowerCase() - }), { - [BUFFER]: buf - }); - }); - }, - - /** - * Decode response as json - * - * @return Promise - */ - json() { - var _this2 = this; - - return consumeBody.call(this).then(function (buffer) { - try { - return JSON.parse(buffer.toString()); - } catch (err) { - return Body.Promise.reject(new FetchError(`invalid json response body at ${_this2.url} reason: ${err.message}`, 'invalid-json')); - } - }); - }, - - /** - * Decode response as text - * - * @return Promise - */ - text() { - return consumeBody.call(this).then(function (buffer) { - return buffer.toString(); - }); - }, - - /** - * Decode response as buffer (non-spec api) - * - * @return Promise - */ - buffer() { - return consumeBody.call(this); - }, - - /** - * Decode response as text, while automatically detecting the encoding and - * trying to decode to UTF-8 (non-spec api) - * - * @return Promise - */ - textConverted() { - var _this3 = this; - - return consumeBody.call(this).then(function (buffer) { - return convertBody(buffer, _this3.headers); - }); - } -}; - -// In browsers, all properties are enumerable. -Object.defineProperties(Body.prototype, { - body: { enumerable: true }, - bodyUsed: { enumerable: true }, - arrayBuffer: { enumerable: true }, - blob: { enumerable: true }, - json: { enumerable: true }, - text: { enumerable: true } -}); - -Body.mixIn = function (proto) { - for (const name of Object.getOwnPropertyNames(Body.prototype)) { - // istanbul ignore else: future proof - if (!(name in proto)) { - const desc = Object.getOwnPropertyDescriptor(Body.prototype, name); - Object.defineProperty(proto, name, desc); - } - } -}; - -/** - * Consume and convert an entire Body to a Buffer. - * - * Ref: https://fetch.spec.whatwg.org/#concept-body-consume-body - * - * @return Promise - */ -function consumeBody() { - var _this4 = this; - - if (this[INTERNALS].disturbed) { - return Body.Promise.reject(new TypeError(`body used already for: ${this.url}`)); - } - - this[INTERNALS].disturbed = true; - - if (this[INTERNALS].error) { - return Body.Promise.reject(this[INTERNALS].error); - } - - let body = this.body; - - // body is null - if (body === null) { - return Body.Promise.resolve(Buffer.alloc(0)); - } - - // body is blob - if (isBlob(body)) { - body = body.stream(); - } - - // body is buffer - if (Buffer.isBuffer(body)) { - return Body.Promise.resolve(body); - } - - // istanbul ignore if: should never happen - if (!(body instanceof Stream)) { - return Body.Promise.resolve(Buffer.alloc(0)); - } - - // body is stream - // get ready to actually consume the body - let accum = []; - let accumBytes = 0; - let abort = false; - - return new Body.Promise(function (resolve, reject) { - let resTimeout; - - // allow timeout on slow response body - if (_this4.timeout) { - resTimeout = setTimeout(function () { - abort = true; - reject(new FetchError(`Response timeout while trying to fetch ${_this4.url} (over ${_this4.timeout}ms)`, 'body-timeout')); - }, _this4.timeout); - } - - // handle stream errors - body.on('error', function (err) { - if (err.name === 'AbortError') { - // if the request was aborted, reject with this Error - abort = true; - reject(err); - } else { - // other errors, such as incorrect content-encoding - reject(new FetchError(`Invalid response body while trying to fetch ${_this4.url}: ${err.message}`, 'system', err)); - } - }); - - body.on('data', function (chunk) { - if (abort || chunk === null) { - return; - } - - if (_this4.size && accumBytes + chunk.length > _this4.size) { - abort = true; - reject(new FetchError(`content size at ${_this4.url} over limit: ${_this4.size}`, 'max-size')); - return; - } - - accumBytes += chunk.length; - accum.push(chunk); - }); - - body.on('end', function () { - if (abort) { - return; - } - - clearTimeout(resTimeout); - - try { - resolve(Buffer.concat(accum, accumBytes)); - } catch (err) { - // handle streams that have accumulated too much data (issue #414) - reject(new FetchError(`Could not create Buffer from response body for ${_this4.url}: ${err.message}`, 'system', err)); - } - }); - }); -} - -/** - * Detect buffer encoding and convert to target encoding - * ref: http://www.w3.org/TR/2011/WD-html5-20110113/parsing.html#determining-the-character-encoding - * - * @param Buffer buffer Incoming buffer - * @param String encoding Target encoding - * @return String - */ -function convertBody(buffer, headers) { - if (typeof convert !== 'function') { - throw new Error('The package `encoding` must be installed to use the textConverted() function'); - } - - const ct = headers.get('content-type'); - let charset = 'utf-8'; - let res, str; - - // header - if (ct) { - res = /charset=([^;]*)/i.exec(ct); - } - - // no charset in content type, peek at response body for at most 1024 bytes - str = buffer.slice(0, 1024).toString(); - - // html5 - if (!res && str) { - res = / 0 && arguments[0] !== undefined ? arguments[0] : undefined; - - this[MAP] = Object.create(null); - - if (init instanceof Headers) { - const rawHeaders = init.raw(); - const headerNames = Object.keys(rawHeaders); - - for (const headerName of headerNames) { - for (const value of rawHeaders[headerName]) { - this.append(headerName, value); - } - } - - return; - } - - // We don't worry about converting prop to ByteString here as append() - // will handle it. - if (init == null) ; else if (typeof init === 'object') { - const method = init[Symbol.iterator]; - if (method != null) { - if (typeof method !== 'function') { - throw new TypeError('Header pairs must be iterable'); - } - - // sequence> - // Note: per spec we have to first exhaust the lists then process them - const pairs = []; - for (const pair of init) { - if (typeof pair !== 'object' || typeof pair[Symbol.iterator] !== 'function') { - throw new TypeError('Each header pair must be iterable'); - } - pairs.push(Array.from(pair)); - } - - for (const pair of pairs) { - if (pair.length !== 2) { - throw new TypeError('Each header pair must be a name/value tuple'); - } - this.append(pair[0], pair[1]); - } - } else { - // record - for (const key of Object.keys(init)) { - const value = init[key]; - this.append(key, value); - } - } - } else { - throw new TypeError('Provided initializer must be an object'); - } - } - - /** - * Return combined header value given name - * - * @param String name Header name - * @return Mixed - */ - get(name) { - name = `${name}`; - validateName(name); - const key = find(this[MAP], name); - if (key === undefined) { - return null; - } - - return this[MAP][key].join(', '); - } - - /** - * Iterate over all headers - * - * @param Function callback Executed for each item with parameters (value, name, thisArg) - * @param Boolean thisArg `this` context for callback function - * @return Void - */ - forEach(callback) { - let thisArg = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : undefined; - - let pairs = getHeaders(this); - let i = 0; - while (i < pairs.length) { - var _pairs$i = pairs[i]; - const name = _pairs$i[0], - value = _pairs$i[1]; - - callback.call(thisArg, value, name, this); - pairs = getHeaders(this); - i++; - } - } - - /** - * Overwrite header values given name - * - * @param String name Header name - * @param String value Header value - * @return Void - */ - set(name, value) { - name = `${name}`; - value = `${value}`; - validateName(name); - validateValue(value); - const key = find(this[MAP], name); - this[MAP][key !== undefined ? key : name] = [value]; - } - - /** - * Append a value onto existing header - * - * @param String name Header name - * @param String value Header value - * @return Void - */ - append(name, value) { - name = `${name}`; - value = `${value}`; - validateName(name); - validateValue(value); - const key = find(this[MAP], name); - if (key !== undefined) { - this[MAP][key].push(value); - } else { - this[MAP][name] = [value]; - } - } - - /** - * Check for header name existence - * - * @param String name Header name - * @return Boolean - */ - has(name) { - name = `${name}`; - validateName(name); - return find(this[MAP], name) !== undefined; - } - - /** - * Delete all header values given name - * - * @param String name Header name - * @return Void - */ - delete(name) { - name = `${name}`; - validateName(name); - const key = find(this[MAP], name); - if (key !== undefined) { - delete this[MAP][key]; - } - } - - /** - * Return raw headers (non-spec api) - * - * @return Object - */ - raw() { - return this[MAP]; - } - - /** - * Get an iterator on keys. - * - * @return Iterator - */ - keys() { - return createHeadersIterator(this, 'key'); - } - - /** - * Get an iterator on values. - * - * @return Iterator - */ - values() { - return createHeadersIterator(this, 'value'); - } - - /** - * Get an iterator on entries. - * - * This is the default iterator of the Headers object. - * - * @return Iterator - */ - [Symbol.iterator]() { - return createHeadersIterator(this, 'key+value'); - } -} -Headers.prototype.entries = Headers.prototype[Symbol.iterator]; - -Object.defineProperty(Headers.prototype, Symbol.toStringTag, { - value: 'Headers', - writable: false, - enumerable: false, - configurable: true -}); - -Object.defineProperties(Headers.prototype, { - get: { enumerable: true }, - forEach: { enumerable: true }, - set: { enumerable: true }, - append: { enumerable: true }, - has: { enumerable: true }, - delete: { enumerable: true }, - keys: { enumerable: true }, - values: { enumerable: true }, - entries: { enumerable: true } -}); - -function getHeaders(headers) { - let kind = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 'key+value'; - - const keys = Object.keys(headers[MAP]).sort(); - return keys.map(kind === 'key' ? function (k) { - return k.toLowerCase(); - } : kind === 'value' ? function (k) { - return headers[MAP][k].join(', '); - } : function (k) { - return [k.toLowerCase(), headers[MAP][k].join(', ')]; - }); -} - -const INTERNAL = Symbol('internal'); - -function createHeadersIterator(target, kind) { - const iterator = Object.create(HeadersIteratorPrototype); - iterator[INTERNAL] = { - target, - kind, - index: 0 - }; - return iterator; -} - -const HeadersIteratorPrototype = Object.setPrototypeOf({ - next() { - // istanbul ignore if - if (!this || Object.getPrototypeOf(this) !== HeadersIteratorPrototype) { - throw new TypeError('Value of `this` is not a HeadersIterator'); - } - - var _INTERNAL = this[INTERNAL]; - const target = _INTERNAL.target, - kind = _INTERNAL.kind, - index = _INTERNAL.index; - - const values = getHeaders(target, kind); - const len = values.length; - if (index >= len) { - return { - value: undefined, - done: true - }; - } - - this[INTERNAL].index = index + 1; - - return { - value: values[index], - done: false - }; - } -}, Object.getPrototypeOf(Object.getPrototypeOf([][Symbol.iterator]()))); - -Object.defineProperty(HeadersIteratorPrototype, Symbol.toStringTag, { - value: 'HeadersIterator', - writable: false, - enumerable: false, - configurable: true -}); - -/** - * Export the Headers object in a form that Node.js can consume. - * - * @param Headers headers - * @return Object - */ -function exportNodeCompatibleHeaders(headers) { - const obj = Object.assign({ __proto__: null }, headers[MAP]); - - // http.request() only supports string as Host header. This hack makes - // specifying custom Host header possible. - const hostHeaderKey = find(headers[MAP], 'Host'); - if (hostHeaderKey !== undefined) { - obj[hostHeaderKey] = obj[hostHeaderKey][0]; - } - - return obj; -} - -/** - * Create a Headers object from an object of headers, ignoring those that do - * not conform to HTTP grammar productions. - * - * @param Object obj Object of headers - * @return Headers - */ -function createHeadersLenient(obj) { - const headers = new Headers(); - for (const name of Object.keys(obj)) { - if (invalidTokenRegex.test(name)) { - continue; - } - if (Array.isArray(obj[name])) { - for (const val of obj[name]) { - if (invalidHeaderCharRegex.test(val)) { - continue; - } - if (headers[MAP][name] === undefined) { - headers[MAP][name] = [val]; - } else { - headers[MAP][name].push(val); - } - } - } else if (!invalidHeaderCharRegex.test(obj[name])) { - headers[MAP][name] = [obj[name]]; - } - } - return headers; -} - -const INTERNALS$1 = Symbol('Response internals'); - -// fix an issue where "STATUS_CODES" aren't a named export for node <10 -const STATUS_CODES = http.STATUS_CODES; - -/** - * Response class - * - * @param Stream body Readable stream - * @param Object opts Response options - * @return Void - */ -class Response { - constructor() { - let body = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : null; - let opts = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {}; - - Body.call(this, body, opts); - - const status = opts.status || 200; - const headers = new Headers(opts.headers); - - if (body != null && !headers.has('Content-Type')) { - const contentType = extractContentType(body); - if (contentType) { - headers.append('Content-Type', contentType); - } - } - - this[INTERNALS$1] = { - url: opts.url, - status, - statusText: opts.statusText || STATUS_CODES[status], - headers, - counter: opts.counter - }; - } - - get url() { - return this[INTERNALS$1].url || ''; - } - - get status() { - return this[INTERNALS$1].status; - } - - /** - * Convenience property representing if the request ended normally - */ - get ok() { - return this[INTERNALS$1].status >= 200 && this[INTERNALS$1].status < 300; - } - - get redirected() { - return this[INTERNALS$1].counter > 0; - } - - get statusText() { - return this[INTERNALS$1].statusText; - } - - get headers() { - return this[INTERNALS$1].headers; - } - - /** - * Clone this response - * - * @return Response - */ - clone() { - return new Response(clone(this), { - url: this.url, - status: this.status, - statusText: this.statusText, - headers: this.headers, - ok: this.ok, - redirected: this.redirected - }); - } -} - -Body.mixIn(Response.prototype); - -Object.defineProperties(Response.prototype, { - url: { enumerable: true }, - status: { enumerable: true }, - ok: { enumerable: true }, - redirected: { enumerable: true }, - statusText: { enumerable: true }, - headers: { enumerable: true }, - clone: { enumerable: true } -}); - -Object.defineProperty(Response.prototype, Symbol.toStringTag, { - value: 'Response', - writable: false, - enumerable: false, - configurable: true -}); - -const INTERNALS$2 = Symbol('Request internals'); -const URL = Url.URL || whatwgUrl.URL; - -// fix an issue where "format", "parse" aren't a named export for node <10 -const parse_url = Url.parse; -const format_url = Url.format; - -/** - * Wrapper around `new URL` to handle arbitrary URLs - * - * @param {string} urlStr - * @return {void} - */ -function parseURL(urlStr) { - /* - Check whether the URL is absolute or not - Scheme: https://tools.ietf.org/html/rfc3986#section-3.1 - Absolute URL: https://tools.ietf.org/html/rfc3986#section-4.3 - */ - if (/^[a-zA-Z][a-zA-Z\d+\-.]*:/.exec(urlStr)) { - urlStr = new URL(urlStr).toString(); - } - - // Fallback to old implementation for arbitrary URLs - return parse_url(urlStr); -} - -const streamDestructionSupported = 'destroy' in Stream.Readable.prototype; - -/** - * Check if a value is an instance of Request. - * - * @param Mixed input - * @return Boolean - */ -function isRequest(input) { - return typeof input === 'object' && typeof input[INTERNALS$2] === 'object'; -} - -function isAbortSignal(signal) { - const proto = signal && typeof signal === 'object' && Object.getPrototypeOf(signal); - return !!(proto && proto.constructor.name === 'AbortSignal'); -} - -/** - * Request class - * - * @param Mixed input Url or Request instance - * @param Object init Custom options - * @return Void - */ -class Request { - constructor(input) { - let init = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {}; - - let parsedURL; - - // normalize input - if (!isRequest(input)) { - if (input && input.href) { - // in order to support Node.js' Url objects; though WHATWG's URL objects - // will fall into this branch also (since their `toString()` will return - // `href` property anyway) - parsedURL = parseURL(input.href); - } else { - // coerce input to a string before attempting to parse - parsedURL = parseURL(`${input}`); - } - input = {}; - } else { - parsedURL = parseURL(input.url); - } - - let method = init.method || input.method || 'GET'; - method = method.toUpperCase(); - - if ((init.body != null || isRequest(input) && input.body !== null) && (method === 'GET' || method === 'HEAD')) { - throw new TypeError('Request with GET/HEAD method cannot have body'); - } - - let inputBody = init.body != null ? init.body : isRequest(input) && input.body !== null ? clone(input) : null; - - Body.call(this, inputBody, { - timeout: init.timeout || input.timeout || 0, - size: init.size || input.size || 0 - }); - - const headers = new Headers(init.headers || input.headers || {}); - - if (inputBody != null && !headers.has('Content-Type')) { - const contentType = extractContentType(inputBody); - if (contentType) { - headers.append('Content-Type', contentType); - } - } - - let signal = isRequest(input) ? input.signal : null; - if ('signal' in init) signal = init.signal; - - if (signal != null && !isAbortSignal(signal)) { - throw new TypeError('Expected signal to be an instanceof AbortSignal'); - } - - this[INTERNALS$2] = { - method, - redirect: init.redirect || input.redirect || 'follow', - headers, - parsedURL, - signal - }; - - // node-fetch-only options - this.follow = init.follow !== undefined ? init.follow : input.follow !== undefined ? input.follow : 20; - this.compress = init.compress !== undefined ? init.compress : input.compress !== undefined ? input.compress : true; - this.counter = init.counter || input.counter || 0; - this.agent = init.agent || input.agent; - } - - get method() { - return this[INTERNALS$2].method; - } - - get url() { - return format_url(this[INTERNALS$2].parsedURL); - } - - get headers() { - return this[INTERNALS$2].headers; - } - - get redirect() { - return this[INTERNALS$2].redirect; - } - - get signal() { - return this[INTERNALS$2].signal; - } - - /** - * Clone this request - * - * @return Request - */ - clone() { - return new Request(this); - } -} - -Body.mixIn(Request.prototype); - -Object.defineProperty(Request.prototype, Symbol.toStringTag, { - value: 'Request', - writable: false, - enumerable: false, - configurable: true -}); - -Object.defineProperties(Request.prototype, { - method: { enumerable: true }, - url: { enumerable: true }, - headers: { enumerable: true }, - redirect: { enumerable: true }, - clone: { enumerable: true }, - signal: { enumerable: true } -}); - -/** - * Convert a Request to Node.js http request options. - * - * @param Request A Request instance - * @return Object The options object to be passed to http.request - */ -function getNodeRequestOptions(request) { - const parsedURL = request[INTERNALS$2].parsedURL; - const headers = new Headers(request[INTERNALS$2].headers); - - // fetch step 1.3 - if (!headers.has('Accept')) { - headers.set('Accept', '*/*'); - } - - // Basic fetch - if (!parsedURL.protocol || !parsedURL.hostname) { - throw new TypeError('Only absolute URLs are supported'); - } - - if (!/^https?:$/.test(parsedURL.protocol)) { - throw new TypeError('Only HTTP(S) protocols are supported'); - } - - if (request.signal && request.body instanceof Stream.Readable && !streamDestructionSupported) { - throw new Error('Cancellation of streamed requests with AbortSignal is not supported in node < 8'); - } - - // HTTP-network-or-cache fetch steps 2.4-2.7 - let contentLengthValue = null; - if (request.body == null && /^(POST|PUT)$/i.test(request.method)) { - contentLengthValue = '0'; - } - if (request.body != null) { - const totalBytes = getTotalBytes(request); - if (typeof totalBytes === 'number') { - contentLengthValue = String(totalBytes); - } - } - if (contentLengthValue) { - headers.set('Content-Length', contentLengthValue); - } - - // HTTP-network-or-cache fetch step 2.11 - if (!headers.has('User-Agent')) { - headers.set('User-Agent', 'node-fetch/1.0 (+https://github.com/bitinn/node-fetch)'); - } - - // HTTP-network-or-cache fetch step 2.15 - if (request.compress && !headers.has('Accept-Encoding')) { - headers.set('Accept-Encoding', 'gzip,deflate'); - } - - let agent = request.agent; - if (typeof agent === 'function') { - agent = agent(parsedURL); - } - - // HTTP-network fetch step 4.2 - // chunked encoding is handled by Node.js - - return Object.assign({}, parsedURL, { - method: request.method, - headers: exportNodeCompatibleHeaders(headers), - agent - }); -} - -/** - * abort-error.js - * - * AbortError interface for cancelled requests - */ - -/** - * Create AbortError instance - * - * @param String message Error message for human - * @return AbortError - */ -function AbortError(message) { - Error.call(this, message); - - this.type = 'aborted'; - this.message = message; - - // hide custom error implementation details from end-users - Error.captureStackTrace(this, this.constructor); -} - -AbortError.prototype = Object.create(Error.prototype); -AbortError.prototype.constructor = AbortError; -AbortError.prototype.name = 'AbortError'; - -const URL$1 = Url.URL || whatwgUrl.URL; - -// fix an issue where "PassThrough", "resolve" aren't a named export for node <10 -const PassThrough$1 = Stream.PassThrough; - -const isDomainOrSubdomain = function isDomainOrSubdomain(destination, original) { - const orig = new URL$1(original).hostname; - const dest = new URL$1(destination).hostname; - - return orig === dest || orig[orig.length - dest.length - 1] === '.' && orig.endsWith(dest); -}; - -/** - * isSameProtocol reports whether the two provided URLs use the same protocol. - * - * Both domains must already be in canonical form. - * @param {string|URL} original - * @param {string|URL} destination - */ -const isSameProtocol = function isSameProtocol(destination, original) { - const orig = new URL$1(original).protocol; - const dest = new URL$1(destination).protocol; - - return orig === dest; -}; - -/** - * Fetch function - * - * @param Mixed url Absolute url or Request instance - * @param Object opts Fetch options - * @return Promise - */ -function fetch(url, opts) { - - // allow custom promise - if (!fetch.Promise) { - throw new Error('native promise missing, set fetch.Promise to your favorite alternative'); - } - - Body.Promise = fetch.Promise; - - // wrap http.request into fetch - return new fetch.Promise(function (resolve, reject) { - // build request object - const request = new Request(url, opts); - const options = getNodeRequestOptions(request); - - const send = (options.protocol === 'https:' ? https : http).request; - const signal = request.signal; - - let response = null; - - const abort = function abort() { - let error = new AbortError('The user aborted a request.'); - reject(error); - if (request.body && request.body instanceof Stream.Readable) { - destroyStream(request.body, error); - } - if (!response || !response.body) return; - response.body.emit('error', error); - }; - - if (signal && signal.aborted) { - abort(); - return; - } - - const abortAndFinalize = function abortAndFinalize() { - abort(); - finalize(); - }; - - // send request - const req = send(options); - let reqTimeout; - - if (signal) { - signal.addEventListener('abort', abortAndFinalize); - } - - function finalize() { - req.abort(); - if (signal) signal.removeEventListener('abort', abortAndFinalize); - clearTimeout(reqTimeout); - } - - if (request.timeout) { - req.once('socket', function (socket) { - reqTimeout = setTimeout(function () { - reject(new FetchError(`network timeout at: ${request.url}`, 'request-timeout')); - finalize(); - }, request.timeout); - }); - } - - req.on('error', function (err) { - reject(new FetchError(`request to ${request.url} failed, reason: ${err.message}`, 'system', err)); - - if (response && response.body) { - destroyStream(response.body, err); - } - - finalize(); - }); - - fixResponseChunkedTransferBadEnding(req, function (err) { - if (signal && signal.aborted) { - return; - } - - if (response && response.body) { - destroyStream(response.body, err); - } - }); - - /* c8 ignore next 18 */ - if (parseInt(process.version.substring(1)) < 14) { - // Before Node.js 14, pipeline() does not fully support async iterators and does not always - // properly handle when the socket close/end events are out of order. - req.on('socket', function (s) { - s.addListener('close', function (hadError) { - // if a data listener is still present we didn't end cleanly - const hasDataListener = s.listenerCount('data') > 0; - - // if end happened before close but the socket didn't emit an error, do it now - if (response && hasDataListener && !hadError && !(signal && signal.aborted)) { - const err = new Error('Premature close'); - err.code = 'ERR_STREAM_PREMATURE_CLOSE'; - response.body.emit('error', err); - } - }); - }); - } - - req.on('response', function (res) { - clearTimeout(reqTimeout); - - const headers = createHeadersLenient(res.headers); - - // HTTP fetch step 5 - if (fetch.isRedirect(res.statusCode)) { - // HTTP fetch step 5.2 - const location = headers.get('Location'); - - // HTTP fetch step 5.3 - let locationURL = null; - try { - locationURL = location === null ? null : new URL$1(location, request.url).toString(); - } catch (err) { - // error here can only be invalid URL in Location: header - // do not throw when options.redirect == manual - // let the user extract the errorneous redirect URL - if (request.redirect !== 'manual') { - reject(new FetchError(`uri requested responds with an invalid redirect URL: ${location}`, 'invalid-redirect')); - finalize(); - return; - } - } - - // HTTP fetch step 5.5 - switch (request.redirect) { - case 'error': - reject(new FetchError(`uri requested responds with a redirect, redirect mode is set to error: ${request.url}`, 'no-redirect')); - finalize(); - return; - case 'manual': - // node-fetch-specific step: make manual redirect a bit easier to use by setting the Location header value to the resolved URL. - if (locationURL !== null) { - // handle corrupted header - try { - headers.set('Location', locationURL); - } catch (err) { - // istanbul ignore next: nodejs server prevent invalid response headers, we can't test this through normal request - reject(err); - } - } - break; - case 'follow': - // HTTP-redirect fetch step 2 - if (locationURL === null) { - break; - } - - // HTTP-redirect fetch step 5 - if (request.counter >= request.follow) { - reject(new FetchError(`maximum redirect reached at: ${request.url}`, 'max-redirect')); - finalize(); - return; - } - - // HTTP-redirect fetch step 6 (counter increment) - // Create a new Request object. - const requestOpts = { - headers: new Headers(request.headers), - follow: request.follow, - counter: request.counter + 1, - agent: request.agent, - compress: request.compress, - method: request.method, - body: request.body, - signal: request.signal, - timeout: request.timeout, - size: request.size - }; - - if (!isDomainOrSubdomain(request.url, locationURL) || !isSameProtocol(request.url, locationURL)) { - for (const name of ['authorization', 'www-authenticate', 'cookie', 'cookie2']) { - requestOpts.headers.delete(name); - } - } - - // HTTP-redirect fetch step 9 - if (res.statusCode !== 303 && request.body && getTotalBytes(request) === null) { - reject(new FetchError('Cannot follow redirect with body being a readable stream', 'unsupported-redirect')); - finalize(); - return; - } - - // HTTP-redirect fetch step 11 - if (res.statusCode === 303 || (res.statusCode === 301 || res.statusCode === 302) && request.method === 'POST') { - requestOpts.method = 'GET'; - requestOpts.body = undefined; - requestOpts.headers.delete('content-length'); - } - - // HTTP-redirect fetch step 15 - resolve(fetch(new Request(locationURL, requestOpts))); - finalize(); - return; - } - } - - // prepare response - res.once('end', function () { - if (signal) signal.removeEventListener('abort', abortAndFinalize); - }); - let body = res.pipe(new PassThrough$1()); - - const response_options = { - url: request.url, - status: res.statusCode, - statusText: res.statusMessage, - headers: headers, - size: request.size, - timeout: request.timeout, - counter: request.counter - }; - - // HTTP-network fetch step 12.1.1.3 - const codings = headers.get('Content-Encoding'); - - // HTTP-network fetch step 12.1.1.4: handle content codings - - // in following scenarios we ignore compression support - // 1. compression support is disabled - // 2. HEAD request - // 3. no Content-Encoding header - // 4. no content response (204) - // 5. content not modified response (304) - if (!request.compress || request.method === 'HEAD' || codings === null || res.statusCode === 204 || res.statusCode === 304) { - response = new Response(body, response_options); - resolve(response); - return; - } - - // For Node v6+ - // Be less strict when decoding compressed responses, since sometimes - // servers send slightly invalid responses that are still accepted - // by common browsers. - // Always using Z_SYNC_FLUSH is what cURL does. - const zlibOptions = { - flush: zlib.Z_SYNC_FLUSH, - finishFlush: zlib.Z_SYNC_FLUSH - }; - - // for gzip - if (codings == 'gzip' || codings == 'x-gzip') { - body = body.pipe(zlib.createGunzip(zlibOptions)); - response = new Response(body, response_options); - resolve(response); - return; - } - - // for deflate - if (codings == 'deflate' || codings == 'x-deflate') { - // handle the infamous raw deflate response from old servers - // a hack for old IIS and Apache servers - const raw = res.pipe(new PassThrough$1()); - raw.once('data', function (chunk) { - // see http://stackoverflow.com/questions/37519828 - if ((chunk[0] & 0x0F) === 0x08) { - body = body.pipe(zlib.createInflate()); - } else { - body = body.pipe(zlib.createInflateRaw()); - } - response = new Response(body, response_options); - resolve(response); - }); - raw.on('end', function () { - // some old IIS servers return zero-length OK deflate responses, so 'data' is never emitted. - if (!response) { - response = new Response(body, response_options); - resolve(response); - } - }); - return; - } - - // for br - if (codings == 'br' && typeof zlib.createBrotliDecompress === 'function') { - body = body.pipe(zlib.createBrotliDecompress()); - response = new Response(body, response_options); - resolve(response); - return; - } - - // otherwise, use response as-is - response = new Response(body, response_options); - resolve(response); - }); - - writeToStream(req, request); - }); -} -function fixResponseChunkedTransferBadEnding(request, errorCallback) { - let socket; - - request.on('socket', function (s) { - socket = s; - }); - - request.on('response', function (response) { - const headers = response.headers; - - if (headers['transfer-encoding'] === 'chunked' && !headers['content-length']) { - response.once('close', function (hadError) { - // tests for socket presence, as in some situations the - // the 'socket' event is not triggered for the request - // (happens in deno), avoids `TypeError` - // if a data listener is still present we didn't end cleanly - const hasDataListener = socket && socket.listenerCount('data') > 0; - - if (hasDataListener && !hadError) { - const err = new Error('Premature close'); - err.code = 'ERR_STREAM_PREMATURE_CLOSE'; - errorCallback(err); - } - }); - } - }); -} - -function destroyStream(stream, err) { - if (stream.destroy) { - stream.destroy(err); - } else { - // node < 8 - stream.emit('error', err); - stream.end(); - } -} - -/** - * Redirect code matching - * - * @param Number code Status code - * @return Boolean - */ -fetch.isRedirect = function (code) { - return code === 301 || code === 302 || code === 303 || code === 307 || code === 308; -}; - -// expose Promise -fetch.Promise = global.Promise; - -module.exports = exports = fetch; -Object.defineProperty(exports, "__esModule", { value: true }); -exports.default = exports; -exports.Headers = Headers; -exports.Request = Request; -exports.Response = Response; -exports.FetchError = FetchError; -exports.AbortError = AbortError; diff --git a/node_modules/node-fetch/lib/index.mjs b/node_modules/node-fetch/lib/index.mjs deleted file mode 100644 index 2863dd9c..00000000 --- a/node_modules/node-fetch/lib/index.mjs +++ /dev/null @@ -1,1775 +0,0 @@ -import Stream from 'stream'; -import http from 'http'; -import Url from 'url'; -import whatwgUrl from 'whatwg-url'; -import https from 'https'; -import zlib from 'zlib'; - -// Based on https://github.com/tmpvar/jsdom/blob/aa85b2abf07766ff7bf5c1f6daafb3726f2f2db5/lib/jsdom/living/blob.js - -// fix for "Readable" isn't a named export issue -const Readable = Stream.Readable; - -const BUFFER = Symbol('buffer'); -const TYPE = Symbol('type'); - -class Blob { - constructor() { - this[TYPE] = ''; - - const blobParts = arguments[0]; - const options = arguments[1]; - - const buffers = []; - let size = 0; - - if (blobParts) { - const a = blobParts; - const length = Number(a.length); - for (let i = 0; i < length; i++) { - const element = a[i]; - let buffer; - if (element instanceof Buffer) { - buffer = element; - } else if (ArrayBuffer.isView(element)) { - buffer = Buffer.from(element.buffer, element.byteOffset, element.byteLength); - } else if (element instanceof ArrayBuffer) { - buffer = Buffer.from(element); - } else if (element instanceof Blob) { - buffer = element[BUFFER]; - } else { - buffer = Buffer.from(typeof element === 'string' ? element : String(element)); - } - size += buffer.length; - buffers.push(buffer); - } - } - - this[BUFFER] = Buffer.concat(buffers); - - let type = options && options.type !== undefined && String(options.type).toLowerCase(); - if (type && !/[^\u0020-\u007E]/.test(type)) { - this[TYPE] = type; - } - } - get size() { - return this[BUFFER].length; - } - get type() { - return this[TYPE]; - } - text() { - return Promise.resolve(this[BUFFER].toString()); - } - arrayBuffer() { - const buf = this[BUFFER]; - const ab = buf.buffer.slice(buf.byteOffset, buf.byteOffset + buf.byteLength); - return Promise.resolve(ab); - } - stream() { - const readable = new Readable(); - readable._read = function () {}; - readable.push(this[BUFFER]); - readable.push(null); - return readable; - } - toString() { - return '[object Blob]'; - } - slice() { - const size = this.size; - - const start = arguments[0]; - const end = arguments[1]; - let relativeStart, relativeEnd; - if (start === undefined) { - relativeStart = 0; - } else if (start < 0) { - relativeStart = Math.max(size + start, 0); - } else { - relativeStart = Math.min(start, size); - } - if (end === undefined) { - relativeEnd = size; - } else if (end < 0) { - relativeEnd = Math.max(size + end, 0); - } else { - relativeEnd = Math.min(end, size); - } - const span = Math.max(relativeEnd - relativeStart, 0); - - const buffer = this[BUFFER]; - const slicedBuffer = buffer.slice(relativeStart, relativeStart + span); - const blob = new Blob([], { type: arguments[2] }); - blob[BUFFER] = slicedBuffer; - return blob; - } -} - -Object.defineProperties(Blob.prototype, { - size: { enumerable: true }, - type: { enumerable: true }, - slice: { enumerable: true } -}); - -Object.defineProperty(Blob.prototype, Symbol.toStringTag, { - value: 'Blob', - writable: false, - enumerable: false, - configurable: true -}); - -/** - * fetch-error.js - * - * FetchError interface for operational errors - */ - -/** - * Create FetchError instance - * - * @param String message Error message for human - * @param String type Error type for machine - * @param String systemError For Node.js system error - * @return FetchError - */ -function FetchError(message, type, systemError) { - Error.call(this, message); - - this.message = message; - this.type = type; - - // when err.type is `system`, err.code contains system error code - if (systemError) { - this.code = this.errno = systemError.code; - } - - // hide custom error implementation details from end-users - Error.captureStackTrace(this, this.constructor); -} - -FetchError.prototype = Object.create(Error.prototype); -FetchError.prototype.constructor = FetchError; -FetchError.prototype.name = 'FetchError'; - -let convert; -try { - convert = require('encoding').convert; -} catch (e) {} - -const INTERNALS = Symbol('Body internals'); - -// fix an issue where "PassThrough" isn't a named export for node <10 -const PassThrough = Stream.PassThrough; - -/** - * Body mixin - * - * Ref: https://fetch.spec.whatwg.org/#body - * - * @param Stream body Readable stream - * @param Object opts Response options - * @return Void - */ -function Body(body) { - var _this = this; - - var _ref = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {}, - _ref$size = _ref.size; - - let size = _ref$size === undefined ? 0 : _ref$size; - var _ref$timeout = _ref.timeout; - let timeout = _ref$timeout === undefined ? 0 : _ref$timeout; - - if (body == null) { - // body is undefined or null - body = null; - } else if (isURLSearchParams(body)) { - // body is a URLSearchParams - body = Buffer.from(body.toString()); - } else if (isBlob(body)) ; else if (Buffer.isBuffer(body)) ; else if (Object.prototype.toString.call(body) === '[object ArrayBuffer]') { - // body is ArrayBuffer - body = Buffer.from(body); - } else if (ArrayBuffer.isView(body)) { - // body is ArrayBufferView - body = Buffer.from(body.buffer, body.byteOffset, body.byteLength); - } else if (body instanceof Stream) ; else { - // none of the above - // coerce to string then buffer - body = Buffer.from(String(body)); - } - this[INTERNALS] = { - body, - disturbed: false, - error: null - }; - this.size = size; - this.timeout = timeout; - - if (body instanceof Stream) { - body.on('error', function (err) { - const error = err.name === 'AbortError' ? err : new FetchError(`Invalid response body while trying to fetch ${_this.url}: ${err.message}`, 'system', err); - _this[INTERNALS].error = error; - }); - } -} - -Body.prototype = { - get body() { - return this[INTERNALS].body; - }, - - get bodyUsed() { - return this[INTERNALS].disturbed; - }, - - /** - * Decode response as ArrayBuffer - * - * @return Promise - */ - arrayBuffer() { - return consumeBody.call(this).then(function (buf) { - return buf.buffer.slice(buf.byteOffset, buf.byteOffset + buf.byteLength); - }); - }, - - /** - * Return raw response as Blob - * - * @return Promise - */ - blob() { - let ct = this.headers && this.headers.get('content-type') || ''; - return consumeBody.call(this).then(function (buf) { - return Object.assign( - // Prevent copying - new Blob([], { - type: ct.toLowerCase() - }), { - [BUFFER]: buf - }); - }); - }, - - /** - * Decode response as json - * - * @return Promise - */ - json() { - var _this2 = this; - - return consumeBody.call(this).then(function (buffer) { - try { - return JSON.parse(buffer.toString()); - } catch (err) { - return Body.Promise.reject(new FetchError(`invalid json response body at ${_this2.url} reason: ${err.message}`, 'invalid-json')); - } - }); - }, - - /** - * Decode response as text - * - * @return Promise - */ - text() { - return consumeBody.call(this).then(function (buffer) { - return buffer.toString(); - }); - }, - - /** - * Decode response as buffer (non-spec api) - * - * @return Promise - */ - buffer() { - return consumeBody.call(this); - }, - - /** - * Decode response as text, while automatically detecting the encoding and - * trying to decode to UTF-8 (non-spec api) - * - * @return Promise - */ - textConverted() { - var _this3 = this; - - return consumeBody.call(this).then(function (buffer) { - return convertBody(buffer, _this3.headers); - }); - } -}; - -// In browsers, all properties are enumerable. -Object.defineProperties(Body.prototype, { - body: { enumerable: true }, - bodyUsed: { enumerable: true }, - arrayBuffer: { enumerable: true }, - blob: { enumerable: true }, - json: { enumerable: true }, - text: { enumerable: true } -}); - -Body.mixIn = function (proto) { - for (const name of Object.getOwnPropertyNames(Body.prototype)) { - // istanbul ignore else: future proof - if (!(name in proto)) { - const desc = Object.getOwnPropertyDescriptor(Body.prototype, name); - Object.defineProperty(proto, name, desc); - } - } -}; - -/** - * Consume and convert an entire Body to a Buffer. - * - * Ref: https://fetch.spec.whatwg.org/#concept-body-consume-body - * - * @return Promise - */ -function consumeBody() { - var _this4 = this; - - if (this[INTERNALS].disturbed) { - return Body.Promise.reject(new TypeError(`body used already for: ${this.url}`)); - } - - this[INTERNALS].disturbed = true; - - if (this[INTERNALS].error) { - return Body.Promise.reject(this[INTERNALS].error); - } - - let body = this.body; - - // body is null - if (body === null) { - return Body.Promise.resolve(Buffer.alloc(0)); - } - - // body is blob - if (isBlob(body)) { - body = body.stream(); - } - - // body is buffer - if (Buffer.isBuffer(body)) { - return Body.Promise.resolve(body); - } - - // istanbul ignore if: should never happen - if (!(body instanceof Stream)) { - return Body.Promise.resolve(Buffer.alloc(0)); - } - - // body is stream - // get ready to actually consume the body - let accum = []; - let accumBytes = 0; - let abort = false; - - return new Body.Promise(function (resolve, reject) { - let resTimeout; - - // allow timeout on slow response body - if (_this4.timeout) { - resTimeout = setTimeout(function () { - abort = true; - reject(new FetchError(`Response timeout while trying to fetch ${_this4.url} (over ${_this4.timeout}ms)`, 'body-timeout')); - }, _this4.timeout); - } - - // handle stream errors - body.on('error', function (err) { - if (err.name === 'AbortError') { - // if the request was aborted, reject with this Error - abort = true; - reject(err); - } else { - // other errors, such as incorrect content-encoding - reject(new FetchError(`Invalid response body while trying to fetch ${_this4.url}: ${err.message}`, 'system', err)); - } - }); - - body.on('data', function (chunk) { - if (abort || chunk === null) { - return; - } - - if (_this4.size && accumBytes + chunk.length > _this4.size) { - abort = true; - reject(new FetchError(`content size at ${_this4.url} over limit: ${_this4.size}`, 'max-size')); - return; - } - - accumBytes += chunk.length; - accum.push(chunk); - }); - - body.on('end', function () { - if (abort) { - return; - } - - clearTimeout(resTimeout); - - try { - resolve(Buffer.concat(accum, accumBytes)); - } catch (err) { - // handle streams that have accumulated too much data (issue #414) - reject(new FetchError(`Could not create Buffer from response body for ${_this4.url}: ${err.message}`, 'system', err)); - } - }); - }); -} - -/** - * Detect buffer encoding and convert to target encoding - * ref: http://www.w3.org/TR/2011/WD-html5-20110113/parsing.html#determining-the-character-encoding - * - * @param Buffer buffer Incoming buffer - * @param String encoding Target encoding - * @return String - */ -function convertBody(buffer, headers) { - if (typeof convert !== 'function') { - throw new Error('The package `encoding` must be installed to use the textConverted() function'); - } - - const ct = headers.get('content-type'); - let charset = 'utf-8'; - let res, str; - - // header - if (ct) { - res = /charset=([^;]*)/i.exec(ct); - } - - // no charset in content type, peek at response body for at most 1024 bytes - str = buffer.slice(0, 1024).toString(); - - // html5 - if (!res && str) { - res = / 0 && arguments[0] !== undefined ? arguments[0] : undefined; - - this[MAP] = Object.create(null); - - if (init instanceof Headers) { - const rawHeaders = init.raw(); - const headerNames = Object.keys(rawHeaders); - - for (const headerName of headerNames) { - for (const value of rawHeaders[headerName]) { - this.append(headerName, value); - } - } - - return; - } - - // We don't worry about converting prop to ByteString here as append() - // will handle it. - if (init == null) ; else if (typeof init === 'object') { - const method = init[Symbol.iterator]; - if (method != null) { - if (typeof method !== 'function') { - throw new TypeError('Header pairs must be iterable'); - } - - // sequence> - // Note: per spec we have to first exhaust the lists then process them - const pairs = []; - for (const pair of init) { - if (typeof pair !== 'object' || typeof pair[Symbol.iterator] !== 'function') { - throw new TypeError('Each header pair must be iterable'); - } - pairs.push(Array.from(pair)); - } - - for (const pair of pairs) { - if (pair.length !== 2) { - throw new TypeError('Each header pair must be a name/value tuple'); - } - this.append(pair[0], pair[1]); - } - } else { - // record - for (const key of Object.keys(init)) { - const value = init[key]; - this.append(key, value); - } - } - } else { - throw new TypeError('Provided initializer must be an object'); - } - } - - /** - * Return combined header value given name - * - * @param String name Header name - * @return Mixed - */ - get(name) { - name = `${name}`; - validateName(name); - const key = find(this[MAP], name); - if (key === undefined) { - return null; - } - - return this[MAP][key].join(', '); - } - - /** - * Iterate over all headers - * - * @param Function callback Executed for each item with parameters (value, name, thisArg) - * @param Boolean thisArg `this` context for callback function - * @return Void - */ - forEach(callback) { - let thisArg = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : undefined; - - let pairs = getHeaders(this); - let i = 0; - while (i < pairs.length) { - var _pairs$i = pairs[i]; - const name = _pairs$i[0], - value = _pairs$i[1]; - - callback.call(thisArg, value, name, this); - pairs = getHeaders(this); - i++; - } - } - - /** - * Overwrite header values given name - * - * @param String name Header name - * @param String value Header value - * @return Void - */ - set(name, value) { - name = `${name}`; - value = `${value}`; - validateName(name); - validateValue(value); - const key = find(this[MAP], name); - this[MAP][key !== undefined ? key : name] = [value]; - } - - /** - * Append a value onto existing header - * - * @param String name Header name - * @param String value Header value - * @return Void - */ - append(name, value) { - name = `${name}`; - value = `${value}`; - validateName(name); - validateValue(value); - const key = find(this[MAP], name); - if (key !== undefined) { - this[MAP][key].push(value); - } else { - this[MAP][name] = [value]; - } - } - - /** - * Check for header name existence - * - * @param String name Header name - * @return Boolean - */ - has(name) { - name = `${name}`; - validateName(name); - return find(this[MAP], name) !== undefined; - } - - /** - * Delete all header values given name - * - * @param String name Header name - * @return Void - */ - delete(name) { - name = `${name}`; - validateName(name); - const key = find(this[MAP], name); - if (key !== undefined) { - delete this[MAP][key]; - } - } - - /** - * Return raw headers (non-spec api) - * - * @return Object - */ - raw() { - return this[MAP]; - } - - /** - * Get an iterator on keys. - * - * @return Iterator - */ - keys() { - return createHeadersIterator(this, 'key'); - } - - /** - * Get an iterator on values. - * - * @return Iterator - */ - values() { - return createHeadersIterator(this, 'value'); - } - - /** - * Get an iterator on entries. - * - * This is the default iterator of the Headers object. - * - * @return Iterator - */ - [Symbol.iterator]() { - return createHeadersIterator(this, 'key+value'); - } -} -Headers.prototype.entries = Headers.prototype[Symbol.iterator]; - -Object.defineProperty(Headers.prototype, Symbol.toStringTag, { - value: 'Headers', - writable: false, - enumerable: false, - configurable: true -}); - -Object.defineProperties(Headers.prototype, { - get: { enumerable: true }, - forEach: { enumerable: true }, - set: { enumerable: true }, - append: { enumerable: true }, - has: { enumerable: true }, - delete: { enumerable: true }, - keys: { enumerable: true }, - values: { enumerable: true }, - entries: { enumerable: true } -}); - -function getHeaders(headers) { - let kind = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 'key+value'; - - const keys = Object.keys(headers[MAP]).sort(); - return keys.map(kind === 'key' ? function (k) { - return k.toLowerCase(); - } : kind === 'value' ? function (k) { - return headers[MAP][k].join(', '); - } : function (k) { - return [k.toLowerCase(), headers[MAP][k].join(', ')]; - }); -} - -const INTERNAL = Symbol('internal'); - -function createHeadersIterator(target, kind) { - const iterator = Object.create(HeadersIteratorPrototype); - iterator[INTERNAL] = { - target, - kind, - index: 0 - }; - return iterator; -} - -const HeadersIteratorPrototype = Object.setPrototypeOf({ - next() { - // istanbul ignore if - if (!this || Object.getPrototypeOf(this) !== HeadersIteratorPrototype) { - throw new TypeError('Value of `this` is not a HeadersIterator'); - } - - var _INTERNAL = this[INTERNAL]; - const target = _INTERNAL.target, - kind = _INTERNAL.kind, - index = _INTERNAL.index; - - const values = getHeaders(target, kind); - const len = values.length; - if (index >= len) { - return { - value: undefined, - done: true - }; - } - - this[INTERNAL].index = index + 1; - - return { - value: values[index], - done: false - }; - } -}, Object.getPrototypeOf(Object.getPrototypeOf([][Symbol.iterator]()))); - -Object.defineProperty(HeadersIteratorPrototype, Symbol.toStringTag, { - value: 'HeadersIterator', - writable: false, - enumerable: false, - configurable: true -}); - -/** - * Export the Headers object in a form that Node.js can consume. - * - * @param Headers headers - * @return Object - */ -function exportNodeCompatibleHeaders(headers) { - const obj = Object.assign({ __proto__: null }, headers[MAP]); - - // http.request() only supports string as Host header. This hack makes - // specifying custom Host header possible. - const hostHeaderKey = find(headers[MAP], 'Host'); - if (hostHeaderKey !== undefined) { - obj[hostHeaderKey] = obj[hostHeaderKey][0]; - } - - return obj; -} - -/** - * Create a Headers object from an object of headers, ignoring those that do - * not conform to HTTP grammar productions. - * - * @param Object obj Object of headers - * @return Headers - */ -function createHeadersLenient(obj) { - const headers = new Headers(); - for (const name of Object.keys(obj)) { - if (invalidTokenRegex.test(name)) { - continue; - } - if (Array.isArray(obj[name])) { - for (const val of obj[name]) { - if (invalidHeaderCharRegex.test(val)) { - continue; - } - if (headers[MAP][name] === undefined) { - headers[MAP][name] = [val]; - } else { - headers[MAP][name].push(val); - } - } - } else if (!invalidHeaderCharRegex.test(obj[name])) { - headers[MAP][name] = [obj[name]]; - } - } - return headers; -} - -const INTERNALS$1 = Symbol('Response internals'); - -// fix an issue where "STATUS_CODES" aren't a named export for node <10 -const STATUS_CODES = http.STATUS_CODES; - -/** - * Response class - * - * @param Stream body Readable stream - * @param Object opts Response options - * @return Void - */ -class Response { - constructor() { - let body = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : null; - let opts = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {}; - - Body.call(this, body, opts); - - const status = opts.status || 200; - const headers = new Headers(opts.headers); - - if (body != null && !headers.has('Content-Type')) { - const contentType = extractContentType(body); - if (contentType) { - headers.append('Content-Type', contentType); - } - } - - this[INTERNALS$1] = { - url: opts.url, - status, - statusText: opts.statusText || STATUS_CODES[status], - headers, - counter: opts.counter - }; - } - - get url() { - return this[INTERNALS$1].url || ''; - } - - get status() { - return this[INTERNALS$1].status; - } - - /** - * Convenience property representing if the request ended normally - */ - get ok() { - return this[INTERNALS$1].status >= 200 && this[INTERNALS$1].status < 300; - } - - get redirected() { - return this[INTERNALS$1].counter > 0; - } - - get statusText() { - return this[INTERNALS$1].statusText; - } - - get headers() { - return this[INTERNALS$1].headers; - } - - /** - * Clone this response - * - * @return Response - */ - clone() { - return new Response(clone(this), { - url: this.url, - status: this.status, - statusText: this.statusText, - headers: this.headers, - ok: this.ok, - redirected: this.redirected - }); - } -} - -Body.mixIn(Response.prototype); - -Object.defineProperties(Response.prototype, { - url: { enumerable: true }, - status: { enumerable: true }, - ok: { enumerable: true }, - redirected: { enumerable: true }, - statusText: { enumerable: true }, - headers: { enumerable: true }, - clone: { enumerable: true } -}); - -Object.defineProperty(Response.prototype, Symbol.toStringTag, { - value: 'Response', - writable: false, - enumerable: false, - configurable: true -}); - -const INTERNALS$2 = Symbol('Request internals'); -const URL = Url.URL || whatwgUrl.URL; - -// fix an issue where "format", "parse" aren't a named export for node <10 -const parse_url = Url.parse; -const format_url = Url.format; - -/** - * Wrapper around `new URL` to handle arbitrary URLs - * - * @param {string} urlStr - * @return {void} - */ -function parseURL(urlStr) { - /* - Check whether the URL is absolute or not - Scheme: https://tools.ietf.org/html/rfc3986#section-3.1 - Absolute URL: https://tools.ietf.org/html/rfc3986#section-4.3 - */ - if (/^[a-zA-Z][a-zA-Z\d+\-.]*:/.exec(urlStr)) { - urlStr = new URL(urlStr).toString(); - } - - // Fallback to old implementation for arbitrary URLs - return parse_url(urlStr); -} - -const streamDestructionSupported = 'destroy' in Stream.Readable.prototype; - -/** - * Check if a value is an instance of Request. - * - * @param Mixed input - * @return Boolean - */ -function isRequest(input) { - return typeof input === 'object' && typeof input[INTERNALS$2] === 'object'; -} - -function isAbortSignal(signal) { - const proto = signal && typeof signal === 'object' && Object.getPrototypeOf(signal); - return !!(proto && proto.constructor.name === 'AbortSignal'); -} - -/** - * Request class - * - * @param Mixed input Url or Request instance - * @param Object init Custom options - * @return Void - */ -class Request { - constructor(input) { - let init = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {}; - - let parsedURL; - - // normalize input - if (!isRequest(input)) { - if (input && input.href) { - // in order to support Node.js' Url objects; though WHATWG's URL objects - // will fall into this branch also (since their `toString()` will return - // `href` property anyway) - parsedURL = parseURL(input.href); - } else { - // coerce input to a string before attempting to parse - parsedURL = parseURL(`${input}`); - } - input = {}; - } else { - parsedURL = parseURL(input.url); - } - - let method = init.method || input.method || 'GET'; - method = method.toUpperCase(); - - if ((init.body != null || isRequest(input) && input.body !== null) && (method === 'GET' || method === 'HEAD')) { - throw new TypeError('Request with GET/HEAD method cannot have body'); - } - - let inputBody = init.body != null ? init.body : isRequest(input) && input.body !== null ? clone(input) : null; - - Body.call(this, inputBody, { - timeout: init.timeout || input.timeout || 0, - size: init.size || input.size || 0 - }); - - const headers = new Headers(init.headers || input.headers || {}); - - if (inputBody != null && !headers.has('Content-Type')) { - const contentType = extractContentType(inputBody); - if (contentType) { - headers.append('Content-Type', contentType); - } - } - - let signal = isRequest(input) ? input.signal : null; - if ('signal' in init) signal = init.signal; - - if (signal != null && !isAbortSignal(signal)) { - throw new TypeError('Expected signal to be an instanceof AbortSignal'); - } - - this[INTERNALS$2] = { - method, - redirect: init.redirect || input.redirect || 'follow', - headers, - parsedURL, - signal - }; - - // node-fetch-only options - this.follow = init.follow !== undefined ? init.follow : input.follow !== undefined ? input.follow : 20; - this.compress = init.compress !== undefined ? init.compress : input.compress !== undefined ? input.compress : true; - this.counter = init.counter || input.counter || 0; - this.agent = init.agent || input.agent; - } - - get method() { - return this[INTERNALS$2].method; - } - - get url() { - return format_url(this[INTERNALS$2].parsedURL); - } - - get headers() { - return this[INTERNALS$2].headers; - } - - get redirect() { - return this[INTERNALS$2].redirect; - } - - get signal() { - return this[INTERNALS$2].signal; - } - - /** - * Clone this request - * - * @return Request - */ - clone() { - return new Request(this); - } -} - -Body.mixIn(Request.prototype); - -Object.defineProperty(Request.prototype, Symbol.toStringTag, { - value: 'Request', - writable: false, - enumerable: false, - configurable: true -}); - -Object.defineProperties(Request.prototype, { - method: { enumerable: true }, - url: { enumerable: true }, - headers: { enumerable: true }, - redirect: { enumerable: true }, - clone: { enumerable: true }, - signal: { enumerable: true } -}); - -/** - * Convert a Request to Node.js http request options. - * - * @param Request A Request instance - * @return Object The options object to be passed to http.request - */ -function getNodeRequestOptions(request) { - const parsedURL = request[INTERNALS$2].parsedURL; - const headers = new Headers(request[INTERNALS$2].headers); - - // fetch step 1.3 - if (!headers.has('Accept')) { - headers.set('Accept', '*/*'); - } - - // Basic fetch - if (!parsedURL.protocol || !parsedURL.hostname) { - throw new TypeError('Only absolute URLs are supported'); - } - - if (!/^https?:$/.test(parsedURL.protocol)) { - throw new TypeError('Only HTTP(S) protocols are supported'); - } - - if (request.signal && request.body instanceof Stream.Readable && !streamDestructionSupported) { - throw new Error('Cancellation of streamed requests with AbortSignal is not supported in node < 8'); - } - - // HTTP-network-or-cache fetch steps 2.4-2.7 - let contentLengthValue = null; - if (request.body == null && /^(POST|PUT)$/i.test(request.method)) { - contentLengthValue = '0'; - } - if (request.body != null) { - const totalBytes = getTotalBytes(request); - if (typeof totalBytes === 'number') { - contentLengthValue = String(totalBytes); - } - } - if (contentLengthValue) { - headers.set('Content-Length', contentLengthValue); - } - - // HTTP-network-or-cache fetch step 2.11 - if (!headers.has('User-Agent')) { - headers.set('User-Agent', 'node-fetch/1.0 (+https://github.com/bitinn/node-fetch)'); - } - - // HTTP-network-or-cache fetch step 2.15 - if (request.compress && !headers.has('Accept-Encoding')) { - headers.set('Accept-Encoding', 'gzip,deflate'); - } - - let agent = request.agent; - if (typeof agent === 'function') { - agent = agent(parsedURL); - } - - // HTTP-network fetch step 4.2 - // chunked encoding is handled by Node.js - - return Object.assign({}, parsedURL, { - method: request.method, - headers: exportNodeCompatibleHeaders(headers), - agent - }); -} - -/** - * abort-error.js - * - * AbortError interface for cancelled requests - */ - -/** - * Create AbortError instance - * - * @param String message Error message for human - * @return AbortError - */ -function AbortError(message) { - Error.call(this, message); - - this.type = 'aborted'; - this.message = message; - - // hide custom error implementation details from end-users - Error.captureStackTrace(this, this.constructor); -} - -AbortError.prototype = Object.create(Error.prototype); -AbortError.prototype.constructor = AbortError; -AbortError.prototype.name = 'AbortError'; - -const URL$1 = Url.URL || whatwgUrl.URL; - -// fix an issue where "PassThrough", "resolve" aren't a named export for node <10 -const PassThrough$1 = Stream.PassThrough; - -const isDomainOrSubdomain = function isDomainOrSubdomain(destination, original) { - const orig = new URL$1(original).hostname; - const dest = new URL$1(destination).hostname; - - return orig === dest || orig[orig.length - dest.length - 1] === '.' && orig.endsWith(dest); -}; - -/** - * isSameProtocol reports whether the two provided URLs use the same protocol. - * - * Both domains must already be in canonical form. - * @param {string|URL} original - * @param {string|URL} destination - */ -const isSameProtocol = function isSameProtocol(destination, original) { - const orig = new URL$1(original).protocol; - const dest = new URL$1(destination).protocol; - - return orig === dest; -}; - -/** - * Fetch function - * - * @param Mixed url Absolute url or Request instance - * @param Object opts Fetch options - * @return Promise - */ -function fetch(url, opts) { - - // allow custom promise - if (!fetch.Promise) { - throw new Error('native promise missing, set fetch.Promise to your favorite alternative'); - } - - Body.Promise = fetch.Promise; - - // wrap http.request into fetch - return new fetch.Promise(function (resolve, reject) { - // build request object - const request = new Request(url, opts); - const options = getNodeRequestOptions(request); - - const send = (options.protocol === 'https:' ? https : http).request; - const signal = request.signal; - - let response = null; - - const abort = function abort() { - let error = new AbortError('The user aborted a request.'); - reject(error); - if (request.body && request.body instanceof Stream.Readable) { - destroyStream(request.body, error); - } - if (!response || !response.body) return; - response.body.emit('error', error); - }; - - if (signal && signal.aborted) { - abort(); - return; - } - - const abortAndFinalize = function abortAndFinalize() { - abort(); - finalize(); - }; - - // send request - const req = send(options); - let reqTimeout; - - if (signal) { - signal.addEventListener('abort', abortAndFinalize); - } - - function finalize() { - req.abort(); - if (signal) signal.removeEventListener('abort', abortAndFinalize); - clearTimeout(reqTimeout); - } - - if (request.timeout) { - req.once('socket', function (socket) { - reqTimeout = setTimeout(function () { - reject(new FetchError(`network timeout at: ${request.url}`, 'request-timeout')); - finalize(); - }, request.timeout); - }); - } - - req.on('error', function (err) { - reject(new FetchError(`request to ${request.url} failed, reason: ${err.message}`, 'system', err)); - - if (response && response.body) { - destroyStream(response.body, err); - } - - finalize(); - }); - - fixResponseChunkedTransferBadEnding(req, function (err) { - if (signal && signal.aborted) { - return; - } - - if (response && response.body) { - destroyStream(response.body, err); - } - }); - - /* c8 ignore next 18 */ - if (parseInt(process.version.substring(1)) < 14) { - // Before Node.js 14, pipeline() does not fully support async iterators and does not always - // properly handle when the socket close/end events are out of order. - req.on('socket', function (s) { - s.addListener('close', function (hadError) { - // if a data listener is still present we didn't end cleanly - const hasDataListener = s.listenerCount('data') > 0; - - // if end happened before close but the socket didn't emit an error, do it now - if (response && hasDataListener && !hadError && !(signal && signal.aborted)) { - const err = new Error('Premature close'); - err.code = 'ERR_STREAM_PREMATURE_CLOSE'; - response.body.emit('error', err); - } - }); - }); - } - - req.on('response', function (res) { - clearTimeout(reqTimeout); - - const headers = createHeadersLenient(res.headers); - - // HTTP fetch step 5 - if (fetch.isRedirect(res.statusCode)) { - // HTTP fetch step 5.2 - const location = headers.get('Location'); - - // HTTP fetch step 5.3 - let locationURL = null; - try { - locationURL = location === null ? null : new URL$1(location, request.url).toString(); - } catch (err) { - // error here can only be invalid URL in Location: header - // do not throw when options.redirect == manual - // let the user extract the errorneous redirect URL - if (request.redirect !== 'manual') { - reject(new FetchError(`uri requested responds with an invalid redirect URL: ${location}`, 'invalid-redirect')); - finalize(); - return; - } - } - - // HTTP fetch step 5.5 - switch (request.redirect) { - case 'error': - reject(new FetchError(`uri requested responds with a redirect, redirect mode is set to error: ${request.url}`, 'no-redirect')); - finalize(); - return; - case 'manual': - // node-fetch-specific step: make manual redirect a bit easier to use by setting the Location header value to the resolved URL. - if (locationURL !== null) { - // handle corrupted header - try { - headers.set('Location', locationURL); - } catch (err) { - // istanbul ignore next: nodejs server prevent invalid response headers, we can't test this through normal request - reject(err); - } - } - break; - case 'follow': - // HTTP-redirect fetch step 2 - if (locationURL === null) { - break; - } - - // HTTP-redirect fetch step 5 - if (request.counter >= request.follow) { - reject(new FetchError(`maximum redirect reached at: ${request.url}`, 'max-redirect')); - finalize(); - return; - } - - // HTTP-redirect fetch step 6 (counter increment) - // Create a new Request object. - const requestOpts = { - headers: new Headers(request.headers), - follow: request.follow, - counter: request.counter + 1, - agent: request.agent, - compress: request.compress, - method: request.method, - body: request.body, - signal: request.signal, - timeout: request.timeout, - size: request.size - }; - - if (!isDomainOrSubdomain(request.url, locationURL) || !isSameProtocol(request.url, locationURL)) { - for (const name of ['authorization', 'www-authenticate', 'cookie', 'cookie2']) { - requestOpts.headers.delete(name); - } - } - - // HTTP-redirect fetch step 9 - if (res.statusCode !== 303 && request.body && getTotalBytes(request) === null) { - reject(new FetchError('Cannot follow redirect with body being a readable stream', 'unsupported-redirect')); - finalize(); - return; - } - - // HTTP-redirect fetch step 11 - if (res.statusCode === 303 || (res.statusCode === 301 || res.statusCode === 302) && request.method === 'POST') { - requestOpts.method = 'GET'; - requestOpts.body = undefined; - requestOpts.headers.delete('content-length'); - } - - // HTTP-redirect fetch step 15 - resolve(fetch(new Request(locationURL, requestOpts))); - finalize(); - return; - } - } - - // prepare response - res.once('end', function () { - if (signal) signal.removeEventListener('abort', abortAndFinalize); - }); - let body = res.pipe(new PassThrough$1()); - - const response_options = { - url: request.url, - status: res.statusCode, - statusText: res.statusMessage, - headers: headers, - size: request.size, - timeout: request.timeout, - counter: request.counter - }; - - // HTTP-network fetch step 12.1.1.3 - const codings = headers.get('Content-Encoding'); - - // HTTP-network fetch step 12.1.1.4: handle content codings - - // in following scenarios we ignore compression support - // 1. compression support is disabled - // 2. HEAD request - // 3. no Content-Encoding header - // 4. no content response (204) - // 5. content not modified response (304) - if (!request.compress || request.method === 'HEAD' || codings === null || res.statusCode === 204 || res.statusCode === 304) { - response = new Response(body, response_options); - resolve(response); - return; - } - - // For Node v6+ - // Be less strict when decoding compressed responses, since sometimes - // servers send slightly invalid responses that are still accepted - // by common browsers. - // Always using Z_SYNC_FLUSH is what cURL does. - const zlibOptions = { - flush: zlib.Z_SYNC_FLUSH, - finishFlush: zlib.Z_SYNC_FLUSH - }; - - // for gzip - if (codings == 'gzip' || codings == 'x-gzip') { - body = body.pipe(zlib.createGunzip(zlibOptions)); - response = new Response(body, response_options); - resolve(response); - return; - } - - // for deflate - if (codings == 'deflate' || codings == 'x-deflate') { - // handle the infamous raw deflate response from old servers - // a hack for old IIS and Apache servers - const raw = res.pipe(new PassThrough$1()); - raw.once('data', function (chunk) { - // see http://stackoverflow.com/questions/37519828 - if ((chunk[0] & 0x0F) === 0x08) { - body = body.pipe(zlib.createInflate()); - } else { - body = body.pipe(zlib.createInflateRaw()); - } - response = new Response(body, response_options); - resolve(response); - }); - raw.on('end', function () { - // some old IIS servers return zero-length OK deflate responses, so 'data' is never emitted. - if (!response) { - response = new Response(body, response_options); - resolve(response); - } - }); - return; - } - - // for br - if (codings == 'br' && typeof zlib.createBrotliDecompress === 'function') { - body = body.pipe(zlib.createBrotliDecompress()); - response = new Response(body, response_options); - resolve(response); - return; - } - - // otherwise, use response as-is - response = new Response(body, response_options); - resolve(response); - }); - - writeToStream(req, request); - }); -} -function fixResponseChunkedTransferBadEnding(request, errorCallback) { - let socket; - - request.on('socket', function (s) { - socket = s; - }); - - request.on('response', function (response) { - const headers = response.headers; - - if (headers['transfer-encoding'] === 'chunked' && !headers['content-length']) { - response.once('close', function (hadError) { - // tests for socket presence, as in some situations the - // the 'socket' event is not triggered for the request - // (happens in deno), avoids `TypeError` - // if a data listener is still present we didn't end cleanly - const hasDataListener = socket && socket.listenerCount('data') > 0; - - if (hasDataListener && !hadError) { - const err = new Error('Premature close'); - err.code = 'ERR_STREAM_PREMATURE_CLOSE'; - errorCallback(err); - } - }); - } - }); -} - -function destroyStream(stream, err) { - if (stream.destroy) { - stream.destroy(err); - } else { - // node < 8 - stream.emit('error', err); - stream.end(); - } -} - -/** - * Redirect code matching - * - * @param Number code Status code - * @return Boolean - */ -fetch.isRedirect = function (code) { - return code === 301 || code === 302 || code === 303 || code === 307 || code === 308; -}; - -// expose Promise -fetch.Promise = global.Promise; - -export default fetch; -export { Headers, Request, Response, FetchError, AbortError }; diff --git a/node_modules/node-fetch/package.json b/node_modules/node-fetch/package.json deleted file mode 100644 index e0be1768..00000000 --- a/node_modules/node-fetch/package.json +++ /dev/null @@ -1,89 +0,0 @@ -{ - "name": "node-fetch", - "version": "2.7.0", - "description": "A light-weight module that brings window.fetch to node.js", - "main": "lib/index.js", - "browser": "./browser.js", - "module": "lib/index.mjs", - "files": [ - "lib/index.js", - "lib/index.mjs", - "lib/index.es.js", - "browser.js" - ], - "engines": { - "node": "4.x || >=6.0.0" - }, - "scripts": { - "build": "cross-env BABEL_ENV=rollup rollup -c", - "prepare": "npm run build", - "test": "cross-env BABEL_ENV=test mocha --require babel-register --throw-deprecation test/test.js", - "report": "cross-env BABEL_ENV=coverage nyc --reporter lcov --reporter text mocha -R spec test/test.js", - "coverage": "cross-env BABEL_ENV=coverage nyc --reporter json --reporter text mocha -R spec test/test.js && codecov -f coverage/coverage-final.json" - }, - "repository": { - "type": "git", - "url": "https://github.com/bitinn/node-fetch.git" - }, - "keywords": [ - "fetch", - "http", - "promise" - ], - "author": "David Frank", - "license": "MIT", - "bugs": { - "url": "https://github.com/bitinn/node-fetch/issues" - }, - "homepage": "https://github.com/bitinn/node-fetch", - "dependencies": { - "whatwg-url": "^5.0.0" - }, - "peerDependencies": { - "encoding": "^0.1.0" - }, - "peerDependenciesMeta": { - "encoding": { - "optional": true - } - }, - "devDependencies": { - "@ungap/url-search-params": "^0.1.2", - "abort-controller": "^1.1.0", - "abortcontroller-polyfill": "^1.3.0", - "babel-core": "^6.26.3", - "babel-plugin-istanbul": "^4.1.6", - "babel-plugin-transform-async-generator-functions": "^6.24.1", - "babel-polyfill": "^6.26.0", - "babel-preset-env": "1.4.0", - "babel-register": "^6.16.3", - "chai": "^3.5.0", - "chai-as-promised": "^7.1.1", - "chai-iterator": "^1.1.1", - "chai-string": "~1.3.0", - "codecov": "3.3.0", - "cross-env": "^5.2.0", - "form-data": "^2.3.3", - "is-builtin-module": "^1.0.0", - "mocha": "^5.0.0", - "nyc": "11.9.0", - "parted": "^0.1.1", - "promise": "^8.0.3", - "resumer": "0.0.0", - "rollup": "^0.63.4", - "rollup-plugin-babel": "^3.0.7", - "string-to-arraybuffer": "^1.0.2", - "teeny-request": "3.7.0" - }, - "release": { - "branches": [ - "+([0-9]).x", - "main", - "next", - { - "name": "beta", - "prerelease": true - } - ] - } -} diff --git a/node_modules/tr46/.npmignore b/node_modules/tr46/.npmignore deleted file mode 100644 index 96e9161f..00000000 --- a/node_modules/tr46/.npmignore +++ /dev/null @@ -1,4 +0,0 @@ -scripts/ -test/ - -!lib/mapping_table.json diff --git a/node_modules/tr46/index.js b/node_modules/tr46/index.js deleted file mode 100644 index 9ce12ca2..00000000 --- a/node_modules/tr46/index.js +++ /dev/null @@ -1,193 +0,0 @@ -"use strict"; - -var punycode = require("punycode"); -var mappingTable = require("./lib/mappingTable.json"); - -var PROCESSING_OPTIONS = { - TRANSITIONAL: 0, - NONTRANSITIONAL: 1 -}; - -function normalize(str) { // fix bug in v8 - return str.split('\u0000').map(function (s) { return s.normalize('NFC'); }).join('\u0000'); -} - -function findStatus(val) { - var start = 0; - var end = mappingTable.length - 1; - - while (start <= end) { - var mid = Math.floor((start + end) / 2); - - var target = mappingTable[mid]; - if (target[0][0] <= val && target[0][1] >= val) { - return target; - } else if (target[0][0] > val) { - end = mid - 1; - } else { - start = mid + 1; - } - } - - return null; -} - -var regexAstralSymbols = /[\uD800-\uDBFF][\uDC00-\uDFFF]/g; - -function countSymbols(string) { - return string - // replace every surrogate pair with a BMP symbol - .replace(regexAstralSymbols, '_') - // then get the length - .length; -} - -function mapChars(domain_name, useSTD3, processing_option) { - var hasError = false; - var processed = ""; - - var len = countSymbols(domain_name); - for (var i = 0; i < len; ++i) { - var codePoint = domain_name.codePointAt(i); - var status = findStatus(codePoint); - - switch (status[1]) { - case "disallowed": - hasError = true; - processed += String.fromCodePoint(codePoint); - break; - case "ignored": - break; - case "mapped": - processed += String.fromCodePoint.apply(String, status[2]); - break; - case "deviation": - if (processing_option === PROCESSING_OPTIONS.TRANSITIONAL) { - processed += String.fromCodePoint.apply(String, status[2]); - } else { - processed += String.fromCodePoint(codePoint); - } - break; - case "valid": - processed += String.fromCodePoint(codePoint); - break; - case "disallowed_STD3_mapped": - if (useSTD3) { - hasError = true; - processed += String.fromCodePoint(codePoint); - } else { - processed += String.fromCodePoint.apply(String, status[2]); - } - break; - case "disallowed_STD3_valid": - if (useSTD3) { - hasError = true; - } - - processed += String.fromCodePoint(codePoint); - break; - } - } - - return { - string: processed, - error: hasError - }; -} - -var combiningMarksRegex = /[\u0300-\u036F\u0483-\u0489\u0591-\u05BD\u05BF\u05C1\u05C2\u05C4\u05C5\u05C7\u0610-\u061A\u064B-\u065F\u0670\u06D6-\u06DC\u06DF-\u06E4\u06E7\u06E8\u06EA-\u06ED\u0711\u0730-\u074A\u07A6-\u07B0\u07EB-\u07F3\u0816-\u0819\u081B-\u0823\u0825-\u0827\u0829-\u082D\u0859-\u085B\u08E4-\u0903\u093A-\u093C\u093E-\u094F\u0951-\u0957\u0962\u0963\u0981-\u0983\u09BC\u09BE-\u09C4\u09C7\u09C8\u09CB-\u09CD\u09D7\u09E2\u09E3\u0A01-\u0A03\u0A3C\u0A3E-\u0A42\u0A47\u0A48\u0A4B-\u0A4D\u0A51\u0A70\u0A71\u0A75\u0A81-\u0A83\u0ABC\u0ABE-\u0AC5\u0AC7-\u0AC9\u0ACB-\u0ACD\u0AE2\u0AE3\u0B01-\u0B03\u0B3C\u0B3E-\u0B44\u0B47\u0B48\u0B4B-\u0B4D\u0B56\u0B57\u0B62\u0B63\u0B82\u0BBE-\u0BC2\u0BC6-\u0BC8\u0BCA-\u0BCD\u0BD7\u0C00-\u0C03\u0C3E-\u0C44\u0C46-\u0C48\u0C4A-\u0C4D\u0C55\u0C56\u0C62\u0C63\u0C81-\u0C83\u0CBC\u0CBE-\u0CC4\u0CC6-\u0CC8\u0CCA-\u0CCD\u0CD5\u0CD6\u0CE2\u0CE3\u0D01-\u0D03\u0D3E-\u0D44\u0D46-\u0D48\u0D4A-\u0D4D\u0D57\u0D62\u0D63\u0D82\u0D83\u0DCA\u0DCF-\u0DD4\u0DD6\u0DD8-\u0DDF\u0DF2\u0DF3\u0E31\u0E34-\u0E3A\u0E47-\u0E4E\u0EB1\u0EB4-\u0EB9\u0EBB\u0EBC\u0EC8-\u0ECD\u0F18\u0F19\u0F35\u0F37\u0F39\u0F3E\u0F3F\u0F71-\u0F84\u0F86\u0F87\u0F8D-\u0F97\u0F99-\u0FBC\u0FC6\u102B-\u103E\u1056-\u1059\u105E-\u1060\u1062-\u1064\u1067-\u106D\u1071-\u1074\u1082-\u108D\u108F\u109A-\u109D\u135D-\u135F\u1712-\u1714\u1732-\u1734\u1752\u1753\u1772\u1773\u17B4-\u17D3\u17DD\u180B-\u180D\u18A9\u1920-\u192B\u1930-\u193B\u19B0-\u19C0\u19C8\u19C9\u1A17-\u1A1B\u1A55-\u1A5E\u1A60-\u1A7C\u1A7F\u1AB0-\u1ABE\u1B00-\u1B04\u1B34-\u1B44\u1B6B-\u1B73\u1B80-\u1B82\u1BA1-\u1BAD\u1BE6-\u1BF3\u1C24-\u1C37\u1CD0-\u1CD2\u1CD4-\u1CE8\u1CED\u1CF2-\u1CF4\u1CF8\u1CF9\u1DC0-\u1DF5\u1DFC-\u1DFF\u20D0-\u20F0\u2CEF-\u2CF1\u2D7F\u2DE0-\u2DFF\u302A-\u302F\u3099\u309A\uA66F-\uA672\uA674-\uA67D\uA69F\uA6F0\uA6F1\uA802\uA806\uA80B\uA823-\uA827\uA880\uA881\uA8B4-\uA8C4\uA8E0-\uA8F1\uA926-\uA92D\uA947-\uA953\uA980-\uA983\uA9B3-\uA9C0\uA9E5\uAA29-\uAA36\uAA43\uAA4C\uAA4D\uAA7B-\uAA7D\uAAB0\uAAB2-\uAAB4\uAAB7\uAAB8\uAABE\uAABF\uAAC1\uAAEB-\uAAEF\uAAF5\uAAF6\uABE3-\uABEA\uABEC\uABED\uFB1E\uFE00-\uFE0F\uFE20-\uFE2D]|\uD800[\uDDFD\uDEE0\uDF76-\uDF7A]|\uD802[\uDE01-\uDE03\uDE05\uDE06\uDE0C-\uDE0F\uDE38-\uDE3A\uDE3F\uDEE5\uDEE6]|\uD804[\uDC00-\uDC02\uDC38-\uDC46\uDC7F-\uDC82\uDCB0-\uDCBA\uDD00-\uDD02\uDD27-\uDD34\uDD73\uDD80-\uDD82\uDDB3-\uDDC0\uDE2C-\uDE37\uDEDF-\uDEEA\uDF01-\uDF03\uDF3C\uDF3E-\uDF44\uDF47\uDF48\uDF4B-\uDF4D\uDF57\uDF62\uDF63\uDF66-\uDF6C\uDF70-\uDF74]|\uD805[\uDCB0-\uDCC3\uDDAF-\uDDB5\uDDB8-\uDDC0\uDE30-\uDE40\uDEAB-\uDEB7]|\uD81A[\uDEF0-\uDEF4\uDF30-\uDF36]|\uD81B[\uDF51-\uDF7E\uDF8F-\uDF92]|\uD82F[\uDC9D\uDC9E]|\uD834[\uDD65-\uDD69\uDD6D-\uDD72\uDD7B-\uDD82\uDD85-\uDD8B\uDDAA-\uDDAD\uDE42-\uDE44]|\uD83A[\uDCD0-\uDCD6]|\uDB40[\uDD00-\uDDEF]/; - -function validateLabel(label, processing_option) { - if (label.substr(0, 4) === "xn--") { - label = punycode.toUnicode(label); - processing_option = PROCESSING_OPTIONS.NONTRANSITIONAL; - } - - var error = false; - - if (normalize(label) !== label || - (label[3] === "-" && label[4] === "-") || - label[0] === "-" || label[label.length - 1] === "-" || - label.indexOf(".") !== -1 || - label.search(combiningMarksRegex) === 0) { - error = true; - } - - var len = countSymbols(label); - for (var i = 0; i < len; ++i) { - var status = findStatus(label.codePointAt(i)); - if ((processing === PROCESSING_OPTIONS.TRANSITIONAL && status[1] !== "valid") || - (processing === PROCESSING_OPTIONS.NONTRANSITIONAL && - status[1] !== "valid" && status[1] !== "deviation")) { - error = true; - break; - } - } - - return { - label: label, - error: error - }; -} - -function processing(domain_name, useSTD3, processing_option) { - var result = mapChars(domain_name, useSTD3, processing_option); - result.string = normalize(result.string); - - var labels = result.string.split("."); - for (var i = 0; i < labels.length; ++i) { - try { - var validation = validateLabel(labels[i]); - labels[i] = validation.label; - result.error = result.error || validation.error; - } catch(e) { - result.error = true; - } - } - - return { - string: labels.join("."), - error: result.error - }; -} - -module.exports.toASCII = function(domain_name, useSTD3, processing_option, verifyDnsLength) { - var result = processing(domain_name, useSTD3, processing_option); - var labels = result.string.split("."); - labels = labels.map(function(l) { - try { - return punycode.toASCII(l); - } catch(e) { - result.error = true; - return l; - } - }); - - if (verifyDnsLength) { - var total = labels.slice(0, labels.length - 1).join(".").length; - if (total.length > 253 || total.length === 0) { - result.error = true; - } - - for (var i=0; i < labels.length; ++i) { - if (labels.length > 63 || labels.length === 0) { - result.error = true; - break; - } - } - } - - if (result.error) return null; - return labels.join("."); -}; - -module.exports.toUnicode = function(domain_name, useSTD3) { - var result = processing(domain_name, useSTD3, PROCESSING_OPTIONS.NONTRANSITIONAL); - - return { - domain: result.string, - error: result.error - }; -}; - -module.exports.PROCESSING_OPTIONS = PROCESSING_OPTIONS; diff --git a/node_modules/tr46/lib/.gitkeep b/node_modules/tr46/lib/.gitkeep deleted file mode 100644 index e69de29b..00000000 diff --git a/node_modules/tr46/lib/mappingTable.json b/node_modules/tr46/lib/mappingTable.json deleted file mode 100644 index 89cf19a7..00000000 --- a/node_modules/tr46/lib/mappingTable.json +++ /dev/null @@ -1 +0,0 @@ -[[[0,44],"disallowed_STD3_valid"],[[45,46],"valid"],[[47,47],"disallowed_STD3_valid"],[[48,57],"valid"],[[58,64],"disallowed_STD3_valid"],[[65,65],"mapped",[97]],[[66,66],"mapped",[98]],[[67,67],"mapped",[99]],[[68,68],"mapped",[100]],[[69,69],"mapped",[101]],[[70,70],"mapped",[102]],[[71,71],"mapped",[103]],[[72,72],"mapped",[104]],[[73,73],"mapped",[105]],[[74,74],"mapped",[106]],[[75,75],"mapped",[107]],[[76,76],"mapped",[108]],[[77,77],"mapped",[109]],[[78,78],"mapped",[110]],[[79,79],"mapped",[111]],[[80,80],"mapped",[112]],[[81,81],"mapped",[113]],[[82,82],"mapped",[114]],[[83,83],"mapped",[115]],[[84,84],"mapped",[116]],[[85,85],"mapped",[117]],[[86,86],"mapped",[118]],[[87,87],"mapped",[119]],[[88,88],"mapped",[120]],[[89,89],"mapped",[121]],[[90,90],"mapped",[122]],[[91,96],"disallowed_STD3_valid"],[[97,122],"valid"],[[123,127],"disallowed_STD3_valid"],[[128,159],"disallowed"],[[160,160],"disallowed_STD3_mapped",[32]],[[161,167],"valid",[],"NV8"],[[168,168],"disallowed_STD3_mapped",[32,776]],[[169,169],"valid",[],"NV8"],[[170,170],"mapped",[97]],[[171,172],"valid",[],"NV8"],[[173,173],"ignored"],[[174,174],"valid",[],"NV8"],[[175,175],"disallowed_STD3_mapped",[32,772]],[[176,177],"valid",[],"NV8"],[[178,178],"mapped",[50]],[[179,179],"mapped",[51]],[[180,180],"disallowed_STD3_mapped",[32,769]],[[181,181],"mapped",[956]],[[182,182],"valid",[],"NV8"],[[183,183],"valid"],[[184,184],"disallowed_STD3_mapped",[32,807]],[[185,185],"mapped",[49]],[[186,186],"mapped",[111]],[[187,187],"valid",[],"NV8"],[[188,188],"mapped",[49,8260,52]],[[189,189],"mapped",[49,8260,50]],[[190,190],"mapped",[51,8260,52]],[[191,191],"valid",[],"NV8"],[[192,192],"mapped",[224]],[[193,193],"mapped",[225]],[[194,194],"mapped",[226]],[[195,195],"mapped",[227]],[[196,196],"mapped",[228]],[[197,197],"mapped",[229]],[[198,198],"mapped",[230]],[[199,199],"mapped",[231]],[[200,200],"mapped",[232]],[[201,201],"mapped",[233]],[[202,202],"mapped",[234]],[[203,203],"mapped",[235]],[[204,204],"mapped",[236]],[[205,205],"mapped",[237]],[[206,206],"mapped",[238]],[[207,207],"mapped",[239]],[[208,208],"mapped",[240]],[[209,209],"mapped",[241]],[[210,210],"mapped",[242]],[[211,211],"mapped",[243]],[[212,212],"mapped",[244]],[[213,213],"mapped",[245]],[[214,214],"mapped",[246]],[[215,215],"valid",[],"NV8"],[[216,216],"mapped",[248]],[[217,217],"mapped",[249]],[[218,218],"mapped",[250]],[[219,219],"mapped",[251]],[[220,220],"mapped",[252]],[[221,221],"mapped",[253]],[[222,222],"mapped",[254]],[[223,223],"deviation",[115,115]],[[224,246],"valid"],[[247,247],"valid",[],"NV8"],[[248,255],"valid"],[[256,256],"mapped",[257]],[[257,257],"valid"],[[258,258],"mapped",[259]],[[259,259],"valid"],[[260,260],"mapped",[261]],[[261,261],"valid"],[[262,262],"mapped",[263]],[[263,263],"valid"],[[264,264],"mapped",[265]],[[265,265],"valid"],[[266,266],"mapped",[267]],[[267,267],"valid"],[[268,268],"mapped",[269]],[[269,269],"valid"],[[270,270],"mapped",[271]],[[271,271],"valid"],[[272,272],"mapped",[273]],[[273,273],"valid"],[[274,274],"mapped",[275]],[[275,275],"valid"],[[276,276],"mapped",[277]],[[277,277],"valid"],[[278,278],"mapped",[279]],[[279,279],"valid"],[[280,280],"mapped",[281]],[[281,281],"valid"],[[282,282],"mapped",[283]],[[283,283],"valid"],[[284,284],"mapped",[285]],[[285,285],"valid"],[[286,286],"mapped",[287]],[[287,287],"valid"],[[288,288],"mapped",[289]],[[289,289],"valid"],[[290,290],"mapped",[291]],[[291,291],"valid"],[[292,292],"mapped",[293]],[[293,293],"valid"],[[294,294],"mapped",[295]],[[295,295],"valid"],[[296,296],"mapped",[297]],[[297,297],"valid"],[[298,298],"mapped",[299]],[[299,299],"valid"],[[300,300],"mapped",[301]],[[301,301],"valid"],[[302,302],"mapped",[303]],[[303,303],"valid"],[[304,304],"mapped",[105,775]],[[305,305],"valid"],[[306,307],"mapped",[105,106]],[[308,308],"mapped",[309]],[[309,309],"valid"],[[310,310],"mapped",[311]],[[311,312],"valid"],[[313,313],"mapped",[314]],[[314,314],"valid"],[[315,315],"mapped",[316]],[[316,316],"valid"],[[317,317],"mapped",[318]],[[318,318],"valid"],[[319,320],"mapped",[108,183]],[[321,321],"mapped",[322]],[[322,322],"valid"],[[323,323],"mapped",[324]],[[324,324],"valid"],[[325,325],"mapped",[326]],[[326,326],"valid"],[[327,327],"mapped",[328]],[[328,328],"valid"],[[329,329],"mapped",[700,110]],[[330,330],"mapped",[331]],[[331,331],"valid"],[[332,332],"mapped",[333]],[[333,333],"valid"],[[334,334],"mapped",[335]],[[335,335],"valid"],[[336,336],"mapped",[337]],[[337,337],"valid"],[[338,338],"mapped",[339]],[[339,339],"valid"],[[340,340],"mapped",[341]],[[341,341],"valid"],[[342,342],"mapped",[343]],[[343,343],"valid"],[[344,344],"mapped",[345]],[[345,345],"valid"],[[346,346],"mapped",[347]],[[347,347],"valid"],[[348,348],"mapped",[349]],[[349,349],"valid"],[[350,350],"mapped",[351]],[[351,351],"valid"],[[352,352],"mapped",[353]],[[353,353],"valid"],[[354,354],"mapped",[355]],[[355,355],"valid"],[[356,356],"mapped",[357]],[[357,357],"valid"],[[358,358],"mapped",[359]],[[359,359],"valid"],[[360,360],"mapped",[361]],[[361,361],"valid"],[[362,362],"mapped",[363]],[[363,363],"valid"],[[364,364],"mapped",[365]],[[365,365],"valid"],[[366,366],"mapped",[367]],[[367,367],"valid"],[[368,368],"mapped",[369]],[[369,369],"valid"],[[370,370],"mapped",[371]],[[371,371],"valid"],[[372,372],"mapped",[373]],[[373,373],"valid"],[[374,374],"mapped",[375]],[[375,375],"valid"],[[376,376],"mapped",[255]],[[377,377],"mapped",[378]],[[378,378],"valid"],[[379,379],"mapped",[380]],[[380,380],"valid"],[[381,381],"mapped",[382]],[[382,382],"valid"],[[383,383],"mapped",[115]],[[384,384],"valid"],[[385,385],"mapped",[595]],[[386,386],"mapped",[387]],[[387,387],"valid"],[[388,388],"mapped",[389]],[[389,389],"valid"],[[390,390],"mapped",[596]],[[391,391],"mapped",[392]],[[392,392],"valid"],[[393,393],"mapped",[598]],[[394,394],"mapped",[599]],[[395,395],"mapped",[396]],[[396,397],"valid"],[[398,398],"mapped",[477]],[[399,399],"mapped",[601]],[[400,400],"mapped",[603]],[[401,401],"mapped",[402]],[[402,402],"valid"],[[403,403],"mapped",[608]],[[404,404],"mapped",[611]],[[405,405],"valid"],[[406,406],"mapped",[617]],[[407,407],"mapped",[616]],[[408,408],"mapped",[409]],[[409,411],"valid"],[[412,412],"mapped",[623]],[[413,413],"mapped",[626]],[[414,414],"valid"],[[415,415],"mapped",[629]],[[416,416],"mapped",[417]],[[417,417],"valid"],[[418,418],"mapped",[419]],[[419,419],"valid"],[[420,420],"mapped",[421]],[[421,421],"valid"],[[422,422],"mapped",[640]],[[423,423],"mapped",[424]],[[424,424],"valid"],[[425,425],"mapped",[643]],[[426,427],"valid"],[[428,428],"mapped",[429]],[[429,429],"valid"],[[430,430],"mapped",[648]],[[431,431],"mapped",[432]],[[432,432],"valid"],[[433,433],"mapped",[650]],[[434,434],"mapped",[651]],[[435,435],"mapped",[436]],[[436,436],"valid"],[[437,437],"mapped",[438]],[[438,438],"valid"],[[439,439],"mapped",[658]],[[440,440],"mapped",[441]],[[441,443],"valid"],[[444,444],"mapped",[445]],[[445,451],"valid"],[[452,454],"mapped",[100,382]],[[455,457],"mapped",[108,106]],[[458,460],"mapped",[110,106]],[[461,461],"mapped",[462]],[[462,462],"valid"],[[463,463],"mapped",[464]],[[464,464],"valid"],[[465,465],"mapped",[466]],[[466,466],"valid"],[[467,467],"mapped",[468]],[[468,468],"valid"],[[469,469],"mapped",[470]],[[470,470],"valid"],[[471,471],"mapped",[472]],[[472,472],"valid"],[[473,473],"mapped",[474]],[[474,474],"valid"],[[475,475],"mapped",[476]],[[476,477],"valid"],[[478,478],"mapped",[479]],[[479,479],"valid"],[[480,480],"mapped",[481]],[[481,481],"valid"],[[482,482],"mapped",[483]],[[483,483],"valid"],[[484,484],"mapped",[485]],[[485,485],"valid"],[[486,486],"mapped",[487]],[[487,487],"valid"],[[488,488],"mapped",[489]],[[489,489],"valid"],[[490,490],"mapped",[491]],[[491,491],"valid"],[[492,492],"mapped",[493]],[[493,493],"valid"],[[494,494],"mapped",[495]],[[495,496],"valid"],[[497,499],"mapped",[100,122]],[[500,500],"mapped",[501]],[[501,501],"valid"],[[502,502],"mapped",[405]],[[503,503],"mapped",[447]],[[504,504],"mapped",[505]],[[505,505],"valid"],[[506,506],"mapped",[507]],[[507,507],"valid"],[[508,508],"mapped",[509]],[[509,509],"valid"],[[510,510],"mapped",[511]],[[511,511],"valid"],[[512,512],"mapped",[513]],[[513,513],"valid"],[[514,514],"mapped",[515]],[[515,515],"valid"],[[516,516],"mapped",[517]],[[517,517],"valid"],[[518,518],"mapped",[519]],[[519,519],"valid"],[[520,520],"mapped",[521]],[[521,521],"valid"],[[522,522],"mapped",[523]],[[523,523],"valid"],[[524,524],"mapped",[525]],[[525,525],"valid"],[[526,526],"mapped",[527]],[[527,527],"valid"],[[528,528],"mapped",[529]],[[529,529],"valid"],[[530,530],"mapped",[531]],[[531,531],"valid"],[[532,532],"mapped",[533]],[[533,533],"valid"],[[534,534],"mapped",[535]],[[535,535],"valid"],[[536,536],"mapped",[537]],[[537,537],"valid"],[[538,538],"mapped",[539]],[[539,539],"valid"],[[540,540],"mapped",[541]],[[541,541],"valid"],[[542,542],"mapped",[543]],[[543,543],"valid"],[[544,544],"mapped",[414]],[[545,545],"valid"],[[546,546],"mapped",[547]],[[547,547],"valid"],[[548,548],"mapped",[549]],[[549,549],"valid"],[[550,550],"mapped",[551]],[[551,551],"valid"],[[552,552],"mapped",[553]],[[553,553],"valid"],[[554,554],"mapped",[555]],[[555,555],"valid"],[[556,556],"mapped",[557]],[[557,557],"valid"],[[558,558],"mapped",[559]],[[559,559],"valid"],[[560,560],"mapped",[561]],[[561,561],"valid"],[[562,562],"mapped",[563]],[[563,563],"valid"],[[564,566],"valid"],[[567,569],"valid"],[[570,570],"mapped",[11365]],[[571,571],"mapped",[572]],[[572,572],"valid"],[[573,573],"mapped",[410]],[[574,574],"mapped",[11366]],[[575,576],"valid"],[[577,577],"mapped",[578]],[[578,578],"valid"],[[579,579],"mapped",[384]],[[580,580],"mapped",[649]],[[581,581],"mapped",[652]],[[582,582],"mapped",[583]],[[583,583],"valid"],[[584,584],"mapped",[585]],[[585,585],"valid"],[[586,586],"mapped",[587]],[[587,587],"valid"],[[588,588],"mapped",[589]],[[589,589],"valid"],[[590,590],"mapped",[591]],[[591,591],"valid"],[[592,680],"valid"],[[681,685],"valid"],[[686,687],"valid"],[[688,688],"mapped",[104]],[[689,689],"mapped",[614]],[[690,690],"mapped",[106]],[[691,691],"mapped",[114]],[[692,692],"mapped",[633]],[[693,693],"mapped",[635]],[[694,694],"mapped",[641]],[[695,695],"mapped",[119]],[[696,696],"mapped",[121]],[[697,705],"valid"],[[706,709],"valid",[],"NV8"],[[710,721],"valid"],[[722,727],"valid",[],"NV8"],[[728,728],"disallowed_STD3_mapped",[32,774]],[[729,729],"disallowed_STD3_mapped",[32,775]],[[730,730],"disallowed_STD3_mapped",[32,778]],[[731,731],"disallowed_STD3_mapped",[32,808]],[[732,732],"disallowed_STD3_mapped",[32,771]],[[733,733],"disallowed_STD3_mapped",[32,779]],[[734,734],"valid",[],"NV8"],[[735,735],"valid",[],"NV8"],[[736,736],"mapped",[611]],[[737,737],"mapped",[108]],[[738,738],"mapped",[115]],[[739,739],"mapped",[120]],[[740,740],"mapped",[661]],[[741,745],"valid",[],"NV8"],[[746,747],"valid",[],"NV8"],[[748,748],"valid"],[[749,749],"valid",[],"NV8"],[[750,750],"valid"],[[751,767],"valid",[],"NV8"],[[768,831],"valid"],[[832,832],"mapped",[768]],[[833,833],"mapped",[769]],[[834,834],"valid"],[[835,835],"mapped",[787]],[[836,836],"mapped",[776,769]],[[837,837],"mapped",[953]],[[838,846],"valid"],[[847,847],"ignored"],[[848,855],"valid"],[[856,860],"valid"],[[861,863],"valid"],[[864,865],"valid"],[[866,866],"valid"],[[867,879],"valid"],[[880,880],"mapped",[881]],[[881,881],"valid"],[[882,882],"mapped",[883]],[[883,883],"valid"],[[884,884],"mapped",[697]],[[885,885],"valid"],[[886,886],"mapped",[887]],[[887,887],"valid"],[[888,889],"disallowed"],[[890,890],"disallowed_STD3_mapped",[32,953]],[[891,893],"valid"],[[894,894],"disallowed_STD3_mapped",[59]],[[895,895],"mapped",[1011]],[[896,899],"disallowed"],[[900,900],"disallowed_STD3_mapped",[32,769]],[[901,901],"disallowed_STD3_mapped",[32,776,769]],[[902,902],"mapped",[940]],[[903,903],"mapped",[183]],[[904,904],"mapped",[941]],[[905,905],"mapped",[942]],[[906,906],"mapped",[943]],[[907,907],"disallowed"],[[908,908],"mapped",[972]],[[909,909],"disallowed"],[[910,910],"mapped",[973]],[[911,911],"mapped",[974]],[[912,912],"valid"],[[913,913],"mapped",[945]],[[914,914],"mapped",[946]],[[915,915],"mapped",[947]],[[916,916],"mapped",[948]],[[917,917],"mapped",[949]],[[918,918],"mapped",[950]],[[919,919],"mapped",[951]],[[920,920],"mapped",[952]],[[921,921],"mapped",[953]],[[922,922],"mapped",[954]],[[923,923],"mapped",[955]],[[924,924],"mapped",[956]],[[925,925],"mapped",[957]],[[926,926],"mapped",[958]],[[927,927],"mapped",[959]],[[928,928],"mapped",[960]],[[929,929],"mapped",[961]],[[930,930],"disallowed"],[[931,931],"mapped",[963]],[[932,932],"mapped",[964]],[[933,933],"mapped",[965]],[[934,934],"mapped",[966]],[[935,935],"mapped",[967]],[[936,936],"mapped",[968]],[[937,937],"mapped",[969]],[[938,938],"mapped",[970]],[[939,939],"mapped",[971]],[[940,961],"valid"],[[962,962],"deviation",[963]],[[963,974],"valid"],[[975,975],"mapped",[983]],[[976,976],"mapped",[946]],[[977,977],"mapped",[952]],[[978,978],"mapped",[965]],[[979,979],"mapped",[973]],[[980,980],"mapped",[971]],[[981,981],"mapped",[966]],[[982,982],"mapped",[960]],[[983,983],"valid"],[[984,984],"mapped",[985]],[[985,985],"valid"],[[986,986],"mapped",[987]],[[987,987],"valid"],[[988,988],"mapped",[989]],[[989,989],"valid"],[[990,990],"mapped",[991]],[[991,991],"valid"],[[992,992],"mapped",[993]],[[993,993],"valid"],[[994,994],"mapped",[995]],[[995,995],"valid"],[[996,996],"mapped",[997]],[[997,997],"valid"],[[998,998],"mapped",[999]],[[999,999],"valid"],[[1000,1000],"mapped",[1001]],[[1001,1001],"valid"],[[1002,1002],"mapped",[1003]],[[1003,1003],"valid"],[[1004,1004],"mapped",[1005]],[[1005,1005],"valid"],[[1006,1006],"mapped",[1007]],[[1007,1007],"valid"],[[1008,1008],"mapped",[954]],[[1009,1009],"mapped",[961]],[[1010,1010],"mapped",[963]],[[1011,1011],"valid"],[[1012,1012],"mapped",[952]],[[1013,1013],"mapped",[949]],[[1014,1014],"valid",[],"NV8"],[[1015,1015],"mapped",[1016]],[[1016,1016],"valid"],[[1017,1017],"mapped",[963]],[[1018,1018],"mapped",[1019]],[[1019,1019],"valid"],[[1020,1020],"valid"],[[1021,1021],"mapped",[891]],[[1022,1022],"mapped",[892]],[[1023,1023],"mapped",[893]],[[1024,1024],"mapped",[1104]],[[1025,1025],"mapped",[1105]],[[1026,1026],"mapped",[1106]],[[1027,1027],"mapped",[1107]],[[1028,1028],"mapped",[1108]],[[1029,1029],"mapped",[1109]],[[1030,1030],"mapped",[1110]],[[1031,1031],"mapped",[1111]],[[1032,1032],"mapped",[1112]],[[1033,1033],"mapped",[1113]],[[1034,1034],"mapped",[1114]],[[1035,1035],"mapped",[1115]],[[1036,1036],"mapped",[1116]],[[1037,1037],"mapped",[1117]],[[1038,1038],"mapped",[1118]],[[1039,1039],"mapped",[1119]],[[1040,1040],"mapped",[1072]],[[1041,1041],"mapped",[1073]],[[1042,1042],"mapped",[1074]],[[1043,1043],"mapped",[1075]],[[1044,1044],"mapped",[1076]],[[1045,1045],"mapped",[1077]],[[1046,1046],"mapped",[1078]],[[1047,1047],"mapped",[1079]],[[1048,1048],"mapped",[1080]],[[1049,1049],"mapped",[1081]],[[1050,1050],"mapped",[1082]],[[1051,1051],"mapped",[1083]],[[1052,1052],"mapped",[1084]],[[1053,1053],"mapped",[1085]],[[1054,1054],"mapped",[1086]],[[1055,1055],"mapped",[1087]],[[1056,1056],"mapped",[1088]],[[1057,1057],"mapped",[1089]],[[1058,1058],"mapped",[1090]],[[1059,1059],"mapped",[1091]],[[1060,1060],"mapped",[1092]],[[1061,1061],"mapped",[1093]],[[1062,1062],"mapped",[1094]],[[1063,1063],"mapped",[1095]],[[1064,1064],"mapped",[1096]],[[1065,1065],"mapped",[1097]],[[1066,1066],"mapped",[1098]],[[1067,1067],"mapped",[1099]],[[1068,1068],"mapped",[1100]],[[1069,1069],"mapped",[1101]],[[1070,1070],"mapped",[1102]],[[1071,1071],"mapped",[1103]],[[1072,1103],"valid"],[[1104,1104],"valid"],[[1105,1116],"valid"],[[1117,1117],"valid"],[[1118,1119],"valid"],[[1120,1120],"mapped",[1121]],[[1121,1121],"valid"],[[1122,1122],"mapped",[1123]],[[1123,1123],"valid"],[[1124,1124],"mapped",[1125]],[[1125,1125],"valid"],[[1126,1126],"mapped",[1127]],[[1127,1127],"valid"],[[1128,1128],"mapped",[1129]],[[1129,1129],"valid"],[[1130,1130],"mapped",[1131]],[[1131,1131],"valid"],[[1132,1132],"mapped",[1133]],[[1133,1133],"valid"],[[1134,1134],"mapped",[1135]],[[1135,1135],"valid"],[[1136,1136],"mapped",[1137]],[[1137,1137],"valid"],[[1138,1138],"mapped",[1139]],[[1139,1139],"valid"],[[1140,1140],"mapped",[1141]],[[1141,1141],"valid"],[[1142,1142],"mapped",[1143]],[[1143,1143],"valid"],[[1144,1144],"mapped",[1145]],[[1145,1145],"valid"],[[1146,1146],"mapped",[1147]],[[1147,1147],"valid"],[[1148,1148],"mapped",[1149]],[[1149,1149],"valid"],[[1150,1150],"mapped",[1151]],[[1151,1151],"valid"],[[1152,1152],"mapped",[1153]],[[1153,1153],"valid"],[[1154,1154],"valid",[],"NV8"],[[1155,1158],"valid"],[[1159,1159],"valid"],[[1160,1161],"valid",[],"NV8"],[[1162,1162],"mapped",[1163]],[[1163,1163],"valid"],[[1164,1164],"mapped",[1165]],[[1165,1165],"valid"],[[1166,1166],"mapped",[1167]],[[1167,1167],"valid"],[[1168,1168],"mapped",[1169]],[[1169,1169],"valid"],[[1170,1170],"mapped",[1171]],[[1171,1171],"valid"],[[1172,1172],"mapped",[1173]],[[1173,1173],"valid"],[[1174,1174],"mapped",[1175]],[[1175,1175],"valid"],[[1176,1176],"mapped",[1177]],[[1177,1177],"valid"],[[1178,1178],"mapped",[1179]],[[1179,1179],"valid"],[[1180,1180],"mapped",[1181]],[[1181,1181],"valid"],[[1182,1182],"mapped",[1183]],[[1183,1183],"valid"],[[1184,1184],"mapped",[1185]],[[1185,1185],"valid"],[[1186,1186],"mapped",[1187]],[[1187,1187],"valid"],[[1188,1188],"mapped",[1189]],[[1189,1189],"valid"],[[1190,1190],"mapped",[1191]],[[1191,1191],"valid"],[[1192,1192],"mapped",[1193]],[[1193,1193],"valid"],[[1194,1194],"mapped",[1195]],[[1195,1195],"valid"],[[1196,1196],"mapped",[1197]],[[1197,1197],"valid"],[[1198,1198],"mapped",[1199]],[[1199,1199],"valid"],[[1200,1200],"mapped",[1201]],[[1201,1201],"valid"],[[1202,1202],"mapped",[1203]],[[1203,1203],"valid"],[[1204,1204],"mapped",[1205]],[[1205,1205],"valid"],[[1206,1206],"mapped",[1207]],[[1207,1207],"valid"],[[1208,1208],"mapped",[1209]],[[1209,1209],"valid"],[[1210,1210],"mapped",[1211]],[[1211,1211],"valid"],[[1212,1212],"mapped",[1213]],[[1213,1213],"valid"],[[1214,1214],"mapped",[1215]],[[1215,1215],"valid"],[[1216,1216],"disallowed"],[[1217,1217],"mapped",[1218]],[[1218,1218],"valid"],[[1219,1219],"mapped",[1220]],[[1220,1220],"valid"],[[1221,1221],"mapped",[1222]],[[1222,1222],"valid"],[[1223,1223],"mapped",[1224]],[[1224,1224],"valid"],[[1225,1225],"mapped",[1226]],[[1226,1226],"valid"],[[1227,1227],"mapped",[1228]],[[1228,1228],"valid"],[[1229,1229],"mapped",[1230]],[[1230,1230],"valid"],[[1231,1231],"valid"],[[1232,1232],"mapped",[1233]],[[1233,1233],"valid"],[[1234,1234],"mapped",[1235]],[[1235,1235],"valid"],[[1236,1236],"mapped",[1237]],[[1237,1237],"valid"],[[1238,1238],"mapped",[1239]],[[1239,1239],"valid"],[[1240,1240],"mapped",[1241]],[[1241,1241],"valid"],[[1242,1242],"mapped",[1243]],[[1243,1243],"valid"],[[1244,1244],"mapped",[1245]],[[1245,1245],"valid"],[[1246,1246],"mapped",[1247]],[[1247,1247],"valid"],[[1248,1248],"mapped",[1249]],[[1249,1249],"valid"],[[1250,1250],"mapped",[1251]],[[1251,1251],"valid"],[[1252,1252],"mapped",[1253]],[[1253,1253],"valid"],[[1254,1254],"mapped",[1255]],[[1255,1255],"valid"],[[1256,1256],"mapped",[1257]],[[1257,1257],"valid"],[[1258,1258],"mapped",[1259]],[[1259,1259],"valid"],[[1260,1260],"mapped",[1261]],[[1261,1261],"valid"],[[1262,1262],"mapped",[1263]],[[1263,1263],"valid"],[[1264,1264],"mapped",[1265]],[[1265,1265],"valid"],[[1266,1266],"mapped",[1267]],[[1267,1267],"valid"],[[1268,1268],"mapped",[1269]],[[1269,1269],"valid"],[[1270,1270],"mapped",[1271]],[[1271,1271],"valid"],[[1272,1272],"mapped",[1273]],[[1273,1273],"valid"],[[1274,1274],"mapped",[1275]],[[1275,1275],"valid"],[[1276,1276],"mapped",[1277]],[[1277,1277],"valid"],[[1278,1278],"mapped",[1279]],[[1279,1279],"valid"],[[1280,1280],"mapped",[1281]],[[1281,1281],"valid"],[[1282,1282],"mapped",[1283]],[[1283,1283],"valid"],[[1284,1284],"mapped",[1285]],[[1285,1285],"valid"],[[1286,1286],"mapped",[1287]],[[1287,1287],"valid"],[[1288,1288],"mapped",[1289]],[[1289,1289],"valid"],[[1290,1290],"mapped",[1291]],[[1291,1291],"valid"],[[1292,1292],"mapped",[1293]],[[1293,1293],"valid"],[[1294,1294],"mapped",[1295]],[[1295,1295],"valid"],[[1296,1296],"mapped",[1297]],[[1297,1297],"valid"],[[1298,1298],"mapped",[1299]],[[1299,1299],"valid"],[[1300,1300],"mapped",[1301]],[[1301,1301],"valid"],[[1302,1302],"mapped",[1303]],[[1303,1303],"valid"],[[1304,1304],"mapped",[1305]],[[1305,1305],"valid"],[[1306,1306],"mapped",[1307]],[[1307,1307],"valid"],[[1308,1308],"mapped",[1309]],[[1309,1309],"valid"],[[1310,1310],"mapped",[1311]],[[1311,1311],"valid"],[[1312,1312],"mapped",[1313]],[[1313,1313],"valid"],[[1314,1314],"mapped",[1315]],[[1315,1315],"valid"],[[1316,1316],"mapped",[1317]],[[1317,1317],"valid"],[[1318,1318],"mapped",[1319]],[[1319,1319],"valid"],[[1320,1320],"mapped",[1321]],[[1321,1321],"valid"],[[1322,1322],"mapped",[1323]],[[1323,1323],"valid"],[[1324,1324],"mapped",[1325]],[[1325,1325],"valid"],[[1326,1326],"mapped",[1327]],[[1327,1327],"valid"],[[1328,1328],"disallowed"],[[1329,1329],"mapped",[1377]],[[1330,1330],"mapped",[1378]],[[1331,1331],"mapped",[1379]],[[1332,1332],"mapped",[1380]],[[1333,1333],"mapped",[1381]],[[1334,1334],"mapped",[1382]],[[1335,1335],"mapped",[1383]],[[1336,1336],"mapped",[1384]],[[1337,1337],"mapped",[1385]],[[1338,1338],"mapped",[1386]],[[1339,1339],"mapped",[1387]],[[1340,1340],"mapped",[1388]],[[1341,1341],"mapped",[1389]],[[1342,1342],"mapped",[1390]],[[1343,1343],"mapped",[1391]],[[1344,1344],"mapped",[1392]],[[1345,1345],"mapped",[1393]],[[1346,1346],"mapped",[1394]],[[1347,1347],"mapped",[1395]],[[1348,1348],"mapped",[1396]],[[1349,1349],"mapped",[1397]],[[1350,1350],"mapped",[1398]],[[1351,1351],"mapped",[1399]],[[1352,1352],"mapped",[1400]],[[1353,1353],"mapped",[1401]],[[1354,1354],"mapped",[1402]],[[1355,1355],"mapped",[1403]],[[1356,1356],"mapped",[1404]],[[1357,1357],"mapped",[1405]],[[1358,1358],"mapped",[1406]],[[1359,1359],"mapped",[1407]],[[1360,1360],"mapped",[1408]],[[1361,1361],"mapped",[1409]],[[1362,1362],"mapped",[1410]],[[1363,1363],"mapped",[1411]],[[1364,1364],"mapped",[1412]],[[1365,1365],"mapped",[1413]],[[1366,1366],"mapped",[1414]],[[1367,1368],"disallowed"],[[1369,1369],"valid"],[[1370,1375],"valid",[],"NV8"],[[1376,1376],"disallowed"],[[1377,1414],"valid"],[[1415,1415],"mapped",[1381,1410]],[[1416,1416],"disallowed"],[[1417,1417],"valid",[],"NV8"],[[1418,1418],"valid",[],"NV8"],[[1419,1420],"disallowed"],[[1421,1422],"valid",[],"NV8"],[[1423,1423],"valid",[],"NV8"],[[1424,1424],"disallowed"],[[1425,1441],"valid"],[[1442,1442],"valid"],[[1443,1455],"valid"],[[1456,1465],"valid"],[[1466,1466],"valid"],[[1467,1469],"valid"],[[1470,1470],"valid",[],"NV8"],[[1471,1471],"valid"],[[1472,1472],"valid",[],"NV8"],[[1473,1474],"valid"],[[1475,1475],"valid",[],"NV8"],[[1476,1476],"valid"],[[1477,1477],"valid"],[[1478,1478],"valid",[],"NV8"],[[1479,1479],"valid"],[[1480,1487],"disallowed"],[[1488,1514],"valid"],[[1515,1519],"disallowed"],[[1520,1524],"valid"],[[1525,1535],"disallowed"],[[1536,1539],"disallowed"],[[1540,1540],"disallowed"],[[1541,1541],"disallowed"],[[1542,1546],"valid",[],"NV8"],[[1547,1547],"valid",[],"NV8"],[[1548,1548],"valid",[],"NV8"],[[1549,1551],"valid",[],"NV8"],[[1552,1557],"valid"],[[1558,1562],"valid"],[[1563,1563],"valid",[],"NV8"],[[1564,1564],"disallowed"],[[1565,1565],"disallowed"],[[1566,1566],"valid",[],"NV8"],[[1567,1567],"valid",[],"NV8"],[[1568,1568],"valid"],[[1569,1594],"valid"],[[1595,1599],"valid"],[[1600,1600],"valid",[],"NV8"],[[1601,1618],"valid"],[[1619,1621],"valid"],[[1622,1624],"valid"],[[1625,1630],"valid"],[[1631,1631],"valid"],[[1632,1641],"valid"],[[1642,1645],"valid",[],"NV8"],[[1646,1647],"valid"],[[1648,1652],"valid"],[[1653,1653],"mapped",[1575,1652]],[[1654,1654],"mapped",[1608,1652]],[[1655,1655],"mapped",[1735,1652]],[[1656,1656],"mapped",[1610,1652]],[[1657,1719],"valid"],[[1720,1721],"valid"],[[1722,1726],"valid"],[[1727,1727],"valid"],[[1728,1742],"valid"],[[1743,1743],"valid"],[[1744,1747],"valid"],[[1748,1748],"valid",[],"NV8"],[[1749,1756],"valid"],[[1757,1757],"disallowed"],[[1758,1758],"valid",[],"NV8"],[[1759,1768],"valid"],[[1769,1769],"valid",[],"NV8"],[[1770,1773],"valid"],[[1774,1775],"valid"],[[1776,1785],"valid"],[[1786,1790],"valid"],[[1791,1791],"valid"],[[1792,1805],"valid",[],"NV8"],[[1806,1806],"disallowed"],[[1807,1807],"disallowed"],[[1808,1836],"valid"],[[1837,1839],"valid"],[[1840,1866],"valid"],[[1867,1868],"disallowed"],[[1869,1871],"valid"],[[1872,1901],"valid"],[[1902,1919],"valid"],[[1920,1968],"valid"],[[1969,1969],"valid"],[[1970,1983],"disallowed"],[[1984,2037],"valid"],[[2038,2042],"valid",[],"NV8"],[[2043,2047],"disallowed"],[[2048,2093],"valid"],[[2094,2095],"disallowed"],[[2096,2110],"valid",[],"NV8"],[[2111,2111],"disallowed"],[[2112,2139],"valid"],[[2140,2141],"disallowed"],[[2142,2142],"valid",[],"NV8"],[[2143,2207],"disallowed"],[[2208,2208],"valid"],[[2209,2209],"valid"],[[2210,2220],"valid"],[[2221,2226],"valid"],[[2227,2228],"valid"],[[2229,2274],"disallowed"],[[2275,2275],"valid"],[[2276,2302],"valid"],[[2303,2303],"valid"],[[2304,2304],"valid"],[[2305,2307],"valid"],[[2308,2308],"valid"],[[2309,2361],"valid"],[[2362,2363],"valid"],[[2364,2381],"valid"],[[2382,2382],"valid"],[[2383,2383],"valid"],[[2384,2388],"valid"],[[2389,2389],"valid"],[[2390,2391],"valid"],[[2392,2392],"mapped",[2325,2364]],[[2393,2393],"mapped",[2326,2364]],[[2394,2394],"mapped",[2327,2364]],[[2395,2395],"mapped",[2332,2364]],[[2396,2396],"mapped",[2337,2364]],[[2397,2397],"mapped",[2338,2364]],[[2398,2398],"mapped",[2347,2364]],[[2399,2399],"mapped",[2351,2364]],[[2400,2403],"valid"],[[2404,2405],"valid",[],"NV8"],[[2406,2415],"valid"],[[2416,2416],"valid",[],"NV8"],[[2417,2418],"valid"],[[2419,2423],"valid"],[[2424,2424],"valid"],[[2425,2426],"valid"],[[2427,2428],"valid"],[[2429,2429],"valid"],[[2430,2431],"valid"],[[2432,2432],"valid"],[[2433,2435],"valid"],[[2436,2436],"disallowed"],[[2437,2444],"valid"],[[2445,2446],"disallowed"],[[2447,2448],"valid"],[[2449,2450],"disallowed"],[[2451,2472],"valid"],[[2473,2473],"disallowed"],[[2474,2480],"valid"],[[2481,2481],"disallowed"],[[2482,2482],"valid"],[[2483,2485],"disallowed"],[[2486,2489],"valid"],[[2490,2491],"disallowed"],[[2492,2492],"valid"],[[2493,2493],"valid"],[[2494,2500],"valid"],[[2501,2502],"disallowed"],[[2503,2504],"valid"],[[2505,2506],"disallowed"],[[2507,2509],"valid"],[[2510,2510],"valid"],[[2511,2518],"disallowed"],[[2519,2519],"valid"],[[2520,2523],"disallowed"],[[2524,2524],"mapped",[2465,2492]],[[2525,2525],"mapped",[2466,2492]],[[2526,2526],"disallowed"],[[2527,2527],"mapped",[2479,2492]],[[2528,2531],"valid"],[[2532,2533],"disallowed"],[[2534,2545],"valid"],[[2546,2554],"valid",[],"NV8"],[[2555,2555],"valid",[],"NV8"],[[2556,2560],"disallowed"],[[2561,2561],"valid"],[[2562,2562],"valid"],[[2563,2563],"valid"],[[2564,2564],"disallowed"],[[2565,2570],"valid"],[[2571,2574],"disallowed"],[[2575,2576],"valid"],[[2577,2578],"disallowed"],[[2579,2600],"valid"],[[2601,2601],"disallowed"],[[2602,2608],"valid"],[[2609,2609],"disallowed"],[[2610,2610],"valid"],[[2611,2611],"mapped",[2610,2620]],[[2612,2612],"disallowed"],[[2613,2613],"valid"],[[2614,2614],"mapped",[2616,2620]],[[2615,2615],"disallowed"],[[2616,2617],"valid"],[[2618,2619],"disallowed"],[[2620,2620],"valid"],[[2621,2621],"disallowed"],[[2622,2626],"valid"],[[2627,2630],"disallowed"],[[2631,2632],"valid"],[[2633,2634],"disallowed"],[[2635,2637],"valid"],[[2638,2640],"disallowed"],[[2641,2641],"valid"],[[2642,2648],"disallowed"],[[2649,2649],"mapped",[2582,2620]],[[2650,2650],"mapped",[2583,2620]],[[2651,2651],"mapped",[2588,2620]],[[2652,2652],"valid"],[[2653,2653],"disallowed"],[[2654,2654],"mapped",[2603,2620]],[[2655,2661],"disallowed"],[[2662,2676],"valid"],[[2677,2677],"valid"],[[2678,2688],"disallowed"],[[2689,2691],"valid"],[[2692,2692],"disallowed"],[[2693,2699],"valid"],[[2700,2700],"valid"],[[2701,2701],"valid"],[[2702,2702],"disallowed"],[[2703,2705],"valid"],[[2706,2706],"disallowed"],[[2707,2728],"valid"],[[2729,2729],"disallowed"],[[2730,2736],"valid"],[[2737,2737],"disallowed"],[[2738,2739],"valid"],[[2740,2740],"disallowed"],[[2741,2745],"valid"],[[2746,2747],"disallowed"],[[2748,2757],"valid"],[[2758,2758],"disallowed"],[[2759,2761],"valid"],[[2762,2762],"disallowed"],[[2763,2765],"valid"],[[2766,2767],"disallowed"],[[2768,2768],"valid"],[[2769,2783],"disallowed"],[[2784,2784],"valid"],[[2785,2787],"valid"],[[2788,2789],"disallowed"],[[2790,2799],"valid"],[[2800,2800],"valid",[],"NV8"],[[2801,2801],"valid",[],"NV8"],[[2802,2808],"disallowed"],[[2809,2809],"valid"],[[2810,2816],"disallowed"],[[2817,2819],"valid"],[[2820,2820],"disallowed"],[[2821,2828],"valid"],[[2829,2830],"disallowed"],[[2831,2832],"valid"],[[2833,2834],"disallowed"],[[2835,2856],"valid"],[[2857,2857],"disallowed"],[[2858,2864],"valid"],[[2865,2865],"disallowed"],[[2866,2867],"valid"],[[2868,2868],"disallowed"],[[2869,2869],"valid"],[[2870,2873],"valid"],[[2874,2875],"disallowed"],[[2876,2883],"valid"],[[2884,2884],"valid"],[[2885,2886],"disallowed"],[[2887,2888],"valid"],[[2889,2890],"disallowed"],[[2891,2893],"valid"],[[2894,2901],"disallowed"],[[2902,2903],"valid"],[[2904,2907],"disallowed"],[[2908,2908],"mapped",[2849,2876]],[[2909,2909],"mapped",[2850,2876]],[[2910,2910],"disallowed"],[[2911,2913],"valid"],[[2914,2915],"valid"],[[2916,2917],"disallowed"],[[2918,2927],"valid"],[[2928,2928],"valid",[],"NV8"],[[2929,2929],"valid"],[[2930,2935],"valid",[],"NV8"],[[2936,2945],"disallowed"],[[2946,2947],"valid"],[[2948,2948],"disallowed"],[[2949,2954],"valid"],[[2955,2957],"disallowed"],[[2958,2960],"valid"],[[2961,2961],"disallowed"],[[2962,2965],"valid"],[[2966,2968],"disallowed"],[[2969,2970],"valid"],[[2971,2971],"disallowed"],[[2972,2972],"valid"],[[2973,2973],"disallowed"],[[2974,2975],"valid"],[[2976,2978],"disallowed"],[[2979,2980],"valid"],[[2981,2983],"disallowed"],[[2984,2986],"valid"],[[2987,2989],"disallowed"],[[2990,2997],"valid"],[[2998,2998],"valid"],[[2999,3001],"valid"],[[3002,3005],"disallowed"],[[3006,3010],"valid"],[[3011,3013],"disallowed"],[[3014,3016],"valid"],[[3017,3017],"disallowed"],[[3018,3021],"valid"],[[3022,3023],"disallowed"],[[3024,3024],"valid"],[[3025,3030],"disallowed"],[[3031,3031],"valid"],[[3032,3045],"disallowed"],[[3046,3046],"valid"],[[3047,3055],"valid"],[[3056,3058],"valid",[],"NV8"],[[3059,3066],"valid",[],"NV8"],[[3067,3071],"disallowed"],[[3072,3072],"valid"],[[3073,3075],"valid"],[[3076,3076],"disallowed"],[[3077,3084],"valid"],[[3085,3085],"disallowed"],[[3086,3088],"valid"],[[3089,3089],"disallowed"],[[3090,3112],"valid"],[[3113,3113],"disallowed"],[[3114,3123],"valid"],[[3124,3124],"valid"],[[3125,3129],"valid"],[[3130,3132],"disallowed"],[[3133,3133],"valid"],[[3134,3140],"valid"],[[3141,3141],"disallowed"],[[3142,3144],"valid"],[[3145,3145],"disallowed"],[[3146,3149],"valid"],[[3150,3156],"disallowed"],[[3157,3158],"valid"],[[3159,3159],"disallowed"],[[3160,3161],"valid"],[[3162,3162],"valid"],[[3163,3167],"disallowed"],[[3168,3169],"valid"],[[3170,3171],"valid"],[[3172,3173],"disallowed"],[[3174,3183],"valid"],[[3184,3191],"disallowed"],[[3192,3199],"valid",[],"NV8"],[[3200,3200],"disallowed"],[[3201,3201],"valid"],[[3202,3203],"valid"],[[3204,3204],"disallowed"],[[3205,3212],"valid"],[[3213,3213],"disallowed"],[[3214,3216],"valid"],[[3217,3217],"disallowed"],[[3218,3240],"valid"],[[3241,3241],"disallowed"],[[3242,3251],"valid"],[[3252,3252],"disallowed"],[[3253,3257],"valid"],[[3258,3259],"disallowed"],[[3260,3261],"valid"],[[3262,3268],"valid"],[[3269,3269],"disallowed"],[[3270,3272],"valid"],[[3273,3273],"disallowed"],[[3274,3277],"valid"],[[3278,3284],"disallowed"],[[3285,3286],"valid"],[[3287,3293],"disallowed"],[[3294,3294],"valid"],[[3295,3295],"disallowed"],[[3296,3297],"valid"],[[3298,3299],"valid"],[[3300,3301],"disallowed"],[[3302,3311],"valid"],[[3312,3312],"disallowed"],[[3313,3314],"valid"],[[3315,3328],"disallowed"],[[3329,3329],"valid"],[[3330,3331],"valid"],[[3332,3332],"disallowed"],[[3333,3340],"valid"],[[3341,3341],"disallowed"],[[3342,3344],"valid"],[[3345,3345],"disallowed"],[[3346,3368],"valid"],[[3369,3369],"valid"],[[3370,3385],"valid"],[[3386,3386],"valid"],[[3387,3388],"disallowed"],[[3389,3389],"valid"],[[3390,3395],"valid"],[[3396,3396],"valid"],[[3397,3397],"disallowed"],[[3398,3400],"valid"],[[3401,3401],"disallowed"],[[3402,3405],"valid"],[[3406,3406],"valid"],[[3407,3414],"disallowed"],[[3415,3415],"valid"],[[3416,3422],"disallowed"],[[3423,3423],"valid"],[[3424,3425],"valid"],[[3426,3427],"valid"],[[3428,3429],"disallowed"],[[3430,3439],"valid"],[[3440,3445],"valid",[],"NV8"],[[3446,3448],"disallowed"],[[3449,3449],"valid",[],"NV8"],[[3450,3455],"valid"],[[3456,3457],"disallowed"],[[3458,3459],"valid"],[[3460,3460],"disallowed"],[[3461,3478],"valid"],[[3479,3481],"disallowed"],[[3482,3505],"valid"],[[3506,3506],"disallowed"],[[3507,3515],"valid"],[[3516,3516],"disallowed"],[[3517,3517],"valid"],[[3518,3519],"disallowed"],[[3520,3526],"valid"],[[3527,3529],"disallowed"],[[3530,3530],"valid"],[[3531,3534],"disallowed"],[[3535,3540],"valid"],[[3541,3541],"disallowed"],[[3542,3542],"valid"],[[3543,3543],"disallowed"],[[3544,3551],"valid"],[[3552,3557],"disallowed"],[[3558,3567],"valid"],[[3568,3569],"disallowed"],[[3570,3571],"valid"],[[3572,3572],"valid",[],"NV8"],[[3573,3584],"disallowed"],[[3585,3634],"valid"],[[3635,3635],"mapped",[3661,3634]],[[3636,3642],"valid"],[[3643,3646],"disallowed"],[[3647,3647],"valid",[],"NV8"],[[3648,3662],"valid"],[[3663,3663],"valid",[],"NV8"],[[3664,3673],"valid"],[[3674,3675],"valid",[],"NV8"],[[3676,3712],"disallowed"],[[3713,3714],"valid"],[[3715,3715],"disallowed"],[[3716,3716],"valid"],[[3717,3718],"disallowed"],[[3719,3720],"valid"],[[3721,3721],"disallowed"],[[3722,3722],"valid"],[[3723,3724],"disallowed"],[[3725,3725],"valid"],[[3726,3731],"disallowed"],[[3732,3735],"valid"],[[3736,3736],"disallowed"],[[3737,3743],"valid"],[[3744,3744],"disallowed"],[[3745,3747],"valid"],[[3748,3748],"disallowed"],[[3749,3749],"valid"],[[3750,3750],"disallowed"],[[3751,3751],"valid"],[[3752,3753],"disallowed"],[[3754,3755],"valid"],[[3756,3756],"disallowed"],[[3757,3762],"valid"],[[3763,3763],"mapped",[3789,3762]],[[3764,3769],"valid"],[[3770,3770],"disallowed"],[[3771,3773],"valid"],[[3774,3775],"disallowed"],[[3776,3780],"valid"],[[3781,3781],"disallowed"],[[3782,3782],"valid"],[[3783,3783],"disallowed"],[[3784,3789],"valid"],[[3790,3791],"disallowed"],[[3792,3801],"valid"],[[3802,3803],"disallowed"],[[3804,3804],"mapped",[3755,3737]],[[3805,3805],"mapped",[3755,3745]],[[3806,3807],"valid"],[[3808,3839],"disallowed"],[[3840,3840],"valid"],[[3841,3850],"valid",[],"NV8"],[[3851,3851],"valid"],[[3852,3852],"mapped",[3851]],[[3853,3863],"valid",[],"NV8"],[[3864,3865],"valid"],[[3866,3871],"valid",[],"NV8"],[[3872,3881],"valid"],[[3882,3892],"valid",[],"NV8"],[[3893,3893],"valid"],[[3894,3894],"valid",[],"NV8"],[[3895,3895],"valid"],[[3896,3896],"valid",[],"NV8"],[[3897,3897],"valid"],[[3898,3901],"valid",[],"NV8"],[[3902,3906],"valid"],[[3907,3907],"mapped",[3906,4023]],[[3908,3911],"valid"],[[3912,3912],"disallowed"],[[3913,3916],"valid"],[[3917,3917],"mapped",[3916,4023]],[[3918,3921],"valid"],[[3922,3922],"mapped",[3921,4023]],[[3923,3926],"valid"],[[3927,3927],"mapped",[3926,4023]],[[3928,3931],"valid"],[[3932,3932],"mapped",[3931,4023]],[[3933,3944],"valid"],[[3945,3945],"mapped",[3904,4021]],[[3946,3946],"valid"],[[3947,3948],"valid"],[[3949,3952],"disallowed"],[[3953,3954],"valid"],[[3955,3955],"mapped",[3953,3954]],[[3956,3956],"valid"],[[3957,3957],"mapped",[3953,3956]],[[3958,3958],"mapped",[4018,3968]],[[3959,3959],"mapped",[4018,3953,3968]],[[3960,3960],"mapped",[4019,3968]],[[3961,3961],"mapped",[4019,3953,3968]],[[3962,3968],"valid"],[[3969,3969],"mapped",[3953,3968]],[[3970,3972],"valid"],[[3973,3973],"valid",[],"NV8"],[[3974,3979],"valid"],[[3980,3983],"valid"],[[3984,3986],"valid"],[[3987,3987],"mapped",[3986,4023]],[[3988,3989],"valid"],[[3990,3990],"valid"],[[3991,3991],"valid"],[[3992,3992],"disallowed"],[[3993,3996],"valid"],[[3997,3997],"mapped",[3996,4023]],[[3998,4001],"valid"],[[4002,4002],"mapped",[4001,4023]],[[4003,4006],"valid"],[[4007,4007],"mapped",[4006,4023]],[[4008,4011],"valid"],[[4012,4012],"mapped",[4011,4023]],[[4013,4013],"valid"],[[4014,4016],"valid"],[[4017,4023],"valid"],[[4024,4024],"valid"],[[4025,4025],"mapped",[3984,4021]],[[4026,4028],"valid"],[[4029,4029],"disallowed"],[[4030,4037],"valid",[],"NV8"],[[4038,4038],"valid"],[[4039,4044],"valid",[],"NV8"],[[4045,4045],"disallowed"],[[4046,4046],"valid",[],"NV8"],[[4047,4047],"valid",[],"NV8"],[[4048,4049],"valid",[],"NV8"],[[4050,4052],"valid",[],"NV8"],[[4053,4056],"valid",[],"NV8"],[[4057,4058],"valid",[],"NV8"],[[4059,4095],"disallowed"],[[4096,4129],"valid"],[[4130,4130],"valid"],[[4131,4135],"valid"],[[4136,4136],"valid"],[[4137,4138],"valid"],[[4139,4139],"valid"],[[4140,4146],"valid"],[[4147,4149],"valid"],[[4150,4153],"valid"],[[4154,4159],"valid"],[[4160,4169],"valid"],[[4170,4175],"valid",[],"NV8"],[[4176,4185],"valid"],[[4186,4249],"valid"],[[4250,4253],"valid"],[[4254,4255],"valid",[],"NV8"],[[4256,4293],"disallowed"],[[4294,4294],"disallowed"],[[4295,4295],"mapped",[11559]],[[4296,4300],"disallowed"],[[4301,4301],"mapped",[11565]],[[4302,4303],"disallowed"],[[4304,4342],"valid"],[[4343,4344],"valid"],[[4345,4346],"valid"],[[4347,4347],"valid",[],"NV8"],[[4348,4348],"mapped",[4316]],[[4349,4351],"valid"],[[4352,4441],"valid",[],"NV8"],[[4442,4446],"valid",[],"NV8"],[[4447,4448],"disallowed"],[[4449,4514],"valid",[],"NV8"],[[4515,4519],"valid",[],"NV8"],[[4520,4601],"valid",[],"NV8"],[[4602,4607],"valid",[],"NV8"],[[4608,4614],"valid"],[[4615,4615],"valid"],[[4616,4678],"valid"],[[4679,4679],"valid"],[[4680,4680],"valid"],[[4681,4681],"disallowed"],[[4682,4685],"valid"],[[4686,4687],"disallowed"],[[4688,4694],"valid"],[[4695,4695],"disallowed"],[[4696,4696],"valid"],[[4697,4697],"disallowed"],[[4698,4701],"valid"],[[4702,4703],"disallowed"],[[4704,4742],"valid"],[[4743,4743],"valid"],[[4744,4744],"valid"],[[4745,4745],"disallowed"],[[4746,4749],"valid"],[[4750,4751],"disallowed"],[[4752,4782],"valid"],[[4783,4783],"valid"],[[4784,4784],"valid"],[[4785,4785],"disallowed"],[[4786,4789],"valid"],[[4790,4791],"disallowed"],[[4792,4798],"valid"],[[4799,4799],"disallowed"],[[4800,4800],"valid"],[[4801,4801],"disallowed"],[[4802,4805],"valid"],[[4806,4807],"disallowed"],[[4808,4814],"valid"],[[4815,4815],"valid"],[[4816,4822],"valid"],[[4823,4823],"disallowed"],[[4824,4846],"valid"],[[4847,4847],"valid"],[[4848,4878],"valid"],[[4879,4879],"valid"],[[4880,4880],"valid"],[[4881,4881],"disallowed"],[[4882,4885],"valid"],[[4886,4887],"disallowed"],[[4888,4894],"valid"],[[4895,4895],"valid"],[[4896,4934],"valid"],[[4935,4935],"valid"],[[4936,4954],"valid"],[[4955,4956],"disallowed"],[[4957,4958],"valid"],[[4959,4959],"valid"],[[4960,4960],"valid",[],"NV8"],[[4961,4988],"valid",[],"NV8"],[[4989,4991],"disallowed"],[[4992,5007],"valid"],[[5008,5017],"valid",[],"NV8"],[[5018,5023],"disallowed"],[[5024,5108],"valid"],[[5109,5109],"valid"],[[5110,5111],"disallowed"],[[5112,5112],"mapped",[5104]],[[5113,5113],"mapped",[5105]],[[5114,5114],"mapped",[5106]],[[5115,5115],"mapped",[5107]],[[5116,5116],"mapped",[5108]],[[5117,5117],"mapped",[5109]],[[5118,5119],"disallowed"],[[5120,5120],"valid",[],"NV8"],[[5121,5740],"valid"],[[5741,5742],"valid",[],"NV8"],[[5743,5750],"valid"],[[5751,5759],"valid"],[[5760,5760],"disallowed"],[[5761,5786],"valid"],[[5787,5788],"valid",[],"NV8"],[[5789,5791],"disallowed"],[[5792,5866],"valid"],[[5867,5872],"valid",[],"NV8"],[[5873,5880],"valid"],[[5881,5887],"disallowed"],[[5888,5900],"valid"],[[5901,5901],"disallowed"],[[5902,5908],"valid"],[[5909,5919],"disallowed"],[[5920,5940],"valid"],[[5941,5942],"valid",[],"NV8"],[[5943,5951],"disallowed"],[[5952,5971],"valid"],[[5972,5983],"disallowed"],[[5984,5996],"valid"],[[5997,5997],"disallowed"],[[5998,6000],"valid"],[[6001,6001],"disallowed"],[[6002,6003],"valid"],[[6004,6015],"disallowed"],[[6016,6067],"valid"],[[6068,6069],"disallowed"],[[6070,6099],"valid"],[[6100,6102],"valid",[],"NV8"],[[6103,6103],"valid"],[[6104,6107],"valid",[],"NV8"],[[6108,6108],"valid"],[[6109,6109],"valid"],[[6110,6111],"disallowed"],[[6112,6121],"valid"],[[6122,6127],"disallowed"],[[6128,6137],"valid",[],"NV8"],[[6138,6143],"disallowed"],[[6144,6149],"valid",[],"NV8"],[[6150,6150],"disallowed"],[[6151,6154],"valid",[],"NV8"],[[6155,6157],"ignored"],[[6158,6158],"disallowed"],[[6159,6159],"disallowed"],[[6160,6169],"valid"],[[6170,6175],"disallowed"],[[6176,6263],"valid"],[[6264,6271],"disallowed"],[[6272,6313],"valid"],[[6314,6314],"valid"],[[6315,6319],"disallowed"],[[6320,6389],"valid"],[[6390,6399],"disallowed"],[[6400,6428],"valid"],[[6429,6430],"valid"],[[6431,6431],"disallowed"],[[6432,6443],"valid"],[[6444,6447],"disallowed"],[[6448,6459],"valid"],[[6460,6463],"disallowed"],[[6464,6464],"valid",[],"NV8"],[[6465,6467],"disallowed"],[[6468,6469],"valid",[],"NV8"],[[6470,6509],"valid"],[[6510,6511],"disallowed"],[[6512,6516],"valid"],[[6517,6527],"disallowed"],[[6528,6569],"valid"],[[6570,6571],"valid"],[[6572,6575],"disallowed"],[[6576,6601],"valid"],[[6602,6607],"disallowed"],[[6608,6617],"valid"],[[6618,6618],"valid",[],"XV8"],[[6619,6621],"disallowed"],[[6622,6623],"valid",[],"NV8"],[[6624,6655],"valid",[],"NV8"],[[6656,6683],"valid"],[[6684,6685],"disallowed"],[[6686,6687],"valid",[],"NV8"],[[6688,6750],"valid"],[[6751,6751],"disallowed"],[[6752,6780],"valid"],[[6781,6782],"disallowed"],[[6783,6793],"valid"],[[6794,6799],"disallowed"],[[6800,6809],"valid"],[[6810,6815],"disallowed"],[[6816,6822],"valid",[],"NV8"],[[6823,6823],"valid"],[[6824,6829],"valid",[],"NV8"],[[6830,6831],"disallowed"],[[6832,6845],"valid"],[[6846,6846],"valid",[],"NV8"],[[6847,6911],"disallowed"],[[6912,6987],"valid"],[[6988,6991],"disallowed"],[[6992,7001],"valid"],[[7002,7018],"valid",[],"NV8"],[[7019,7027],"valid"],[[7028,7036],"valid",[],"NV8"],[[7037,7039],"disallowed"],[[7040,7082],"valid"],[[7083,7085],"valid"],[[7086,7097],"valid"],[[7098,7103],"valid"],[[7104,7155],"valid"],[[7156,7163],"disallowed"],[[7164,7167],"valid",[],"NV8"],[[7168,7223],"valid"],[[7224,7226],"disallowed"],[[7227,7231],"valid",[],"NV8"],[[7232,7241],"valid"],[[7242,7244],"disallowed"],[[7245,7293],"valid"],[[7294,7295],"valid",[],"NV8"],[[7296,7359],"disallowed"],[[7360,7367],"valid",[],"NV8"],[[7368,7375],"disallowed"],[[7376,7378],"valid"],[[7379,7379],"valid",[],"NV8"],[[7380,7410],"valid"],[[7411,7414],"valid"],[[7415,7415],"disallowed"],[[7416,7417],"valid"],[[7418,7423],"disallowed"],[[7424,7467],"valid"],[[7468,7468],"mapped",[97]],[[7469,7469],"mapped",[230]],[[7470,7470],"mapped",[98]],[[7471,7471],"valid"],[[7472,7472],"mapped",[100]],[[7473,7473],"mapped",[101]],[[7474,7474],"mapped",[477]],[[7475,7475],"mapped",[103]],[[7476,7476],"mapped",[104]],[[7477,7477],"mapped",[105]],[[7478,7478],"mapped",[106]],[[7479,7479],"mapped",[107]],[[7480,7480],"mapped",[108]],[[7481,7481],"mapped",[109]],[[7482,7482],"mapped",[110]],[[7483,7483],"valid"],[[7484,7484],"mapped",[111]],[[7485,7485],"mapped",[547]],[[7486,7486],"mapped",[112]],[[7487,7487],"mapped",[114]],[[7488,7488],"mapped",[116]],[[7489,7489],"mapped",[117]],[[7490,7490],"mapped",[119]],[[7491,7491],"mapped",[97]],[[7492,7492],"mapped",[592]],[[7493,7493],"mapped",[593]],[[7494,7494],"mapped",[7426]],[[7495,7495],"mapped",[98]],[[7496,7496],"mapped",[100]],[[7497,7497],"mapped",[101]],[[7498,7498],"mapped",[601]],[[7499,7499],"mapped",[603]],[[7500,7500],"mapped",[604]],[[7501,7501],"mapped",[103]],[[7502,7502],"valid"],[[7503,7503],"mapped",[107]],[[7504,7504],"mapped",[109]],[[7505,7505],"mapped",[331]],[[7506,7506],"mapped",[111]],[[7507,7507],"mapped",[596]],[[7508,7508],"mapped",[7446]],[[7509,7509],"mapped",[7447]],[[7510,7510],"mapped",[112]],[[7511,7511],"mapped",[116]],[[7512,7512],"mapped",[117]],[[7513,7513],"mapped",[7453]],[[7514,7514],"mapped",[623]],[[7515,7515],"mapped",[118]],[[7516,7516],"mapped",[7461]],[[7517,7517],"mapped",[946]],[[7518,7518],"mapped",[947]],[[7519,7519],"mapped",[948]],[[7520,7520],"mapped",[966]],[[7521,7521],"mapped",[967]],[[7522,7522],"mapped",[105]],[[7523,7523],"mapped",[114]],[[7524,7524],"mapped",[117]],[[7525,7525],"mapped",[118]],[[7526,7526],"mapped",[946]],[[7527,7527],"mapped",[947]],[[7528,7528],"mapped",[961]],[[7529,7529],"mapped",[966]],[[7530,7530],"mapped",[967]],[[7531,7531],"valid"],[[7532,7543],"valid"],[[7544,7544],"mapped",[1085]],[[7545,7578],"valid"],[[7579,7579],"mapped",[594]],[[7580,7580],"mapped",[99]],[[7581,7581],"mapped",[597]],[[7582,7582],"mapped",[240]],[[7583,7583],"mapped",[604]],[[7584,7584],"mapped",[102]],[[7585,7585],"mapped",[607]],[[7586,7586],"mapped",[609]],[[7587,7587],"mapped",[613]],[[7588,7588],"mapped",[616]],[[7589,7589],"mapped",[617]],[[7590,7590],"mapped",[618]],[[7591,7591],"mapped",[7547]],[[7592,7592],"mapped",[669]],[[7593,7593],"mapped",[621]],[[7594,7594],"mapped",[7557]],[[7595,7595],"mapped",[671]],[[7596,7596],"mapped",[625]],[[7597,7597],"mapped",[624]],[[7598,7598],"mapped",[626]],[[7599,7599],"mapped",[627]],[[7600,7600],"mapped",[628]],[[7601,7601],"mapped",[629]],[[7602,7602],"mapped",[632]],[[7603,7603],"mapped",[642]],[[7604,7604],"mapped",[643]],[[7605,7605],"mapped",[427]],[[7606,7606],"mapped",[649]],[[7607,7607],"mapped",[650]],[[7608,7608],"mapped",[7452]],[[7609,7609],"mapped",[651]],[[7610,7610],"mapped",[652]],[[7611,7611],"mapped",[122]],[[7612,7612],"mapped",[656]],[[7613,7613],"mapped",[657]],[[7614,7614],"mapped",[658]],[[7615,7615],"mapped",[952]],[[7616,7619],"valid"],[[7620,7626],"valid"],[[7627,7654],"valid"],[[7655,7669],"valid"],[[7670,7675],"disallowed"],[[7676,7676],"valid"],[[7677,7677],"valid"],[[7678,7679],"valid"],[[7680,7680],"mapped",[7681]],[[7681,7681],"valid"],[[7682,7682],"mapped",[7683]],[[7683,7683],"valid"],[[7684,7684],"mapped",[7685]],[[7685,7685],"valid"],[[7686,7686],"mapped",[7687]],[[7687,7687],"valid"],[[7688,7688],"mapped",[7689]],[[7689,7689],"valid"],[[7690,7690],"mapped",[7691]],[[7691,7691],"valid"],[[7692,7692],"mapped",[7693]],[[7693,7693],"valid"],[[7694,7694],"mapped",[7695]],[[7695,7695],"valid"],[[7696,7696],"mapped",[7697]],[[7697,7697],"valid"],[[7698,7698],"mapped",[7699]],[[7699,7699],"valid"],[[7700,7700],"mapped",[7701]],[[7701,7701],"valid"],[[7702,7702],"mapped",[7703]],[[7703,7703],"valid"],[[7704,7704],"mapped",[7705]],[[7705,7705],"valid"],[[7706,7706],"mapped",[7707]],[[7707,7707],"valid"],[[7708,7708],"mapped",[7709]],[[7709,7709],"valid"],[[7710,7710],"mapped",[7711]],[[7711,7711],"valid"],[[7712,7712],"mapped",[7713]],[[7713,7713],"valid"],[[7714,7714],"mapped",[7715]],[[7715,7715],"valid"],[[7716,7716],"mapped",[7717]],[[7717,7717],"valid"],[[7718,7718],"mapped",[7719]],[[7719,7719],"valid"],[[7720,7720],"mapped",[7721]],[[7721,7721],"valid"],[[7722,7722],"mapped",[7723]],[[7723,7723],"valid"],[[7724,7724],"mapped",[7725]],[[7725,7725],"valid"],[[7726,7726],"mapped",[7727]],[[7727,7727],"valid"],[[7728,7728],"mapped",[7729]],[[7729,7729],"valid"],[[7730,7730],"mapped",[7731]],[[7731,7731],"valid"],[[7732,7732],"mapped",[7733]],[[7733,7733],"valid"],[[7734,7734],"mapped",[7735]],[[7735,7735],"valid"],[[7736,7736],"mapped",[7737]],[[7737,7737],"valid"],[[7738,7738],"mapped",[7739]],[[7739,7739],"valid"],[[7740,7740],"mapped",[7741]],[[7741,7741],"valid"],[[7742,7742],"mapped",[7743]],[[7743,7743],"valid"],[[7744,7744],"mapped",[7745]],[[7745,7745],"valid"],[[7746,7746],"mapped",[7747]],[[7747,7747],"valid"],[[7748,7748],"mapped",[7749]],[[7749,7749],"valid"],[[7750,7750],"mapped",[7751]],[[7751,7751],"valid"],[[7752,7752],"mapped",[7753]],[[7753,7753],"valid"],[[7754,7754],"mapped",[7755]],[[7755,7755],"valid"],[[7756,7756],"mapped",[7757]],[[7757,7757],"valid"],[[7758,7758],"mapped",[7759]],[[7759,7759],"valid"],[[7760,7760],"mapped",[7761]],[[7761,7761],"valid"],[[7762,7762],"mapped",[7763]],[[7763,7763],"valid"],[[7764,7764],"mapped",[7765]],[[7765,7765],"valid"],[[7766,7766],"mapped",[7767]],[[7767,7767],"valid"],[[7768,7768],"mapped",[7769]],[[7769,7769],"valid"],[[7770,7770],"mapped",[7771]],[[7771,7771],"valid"],[[7772,7772],"mapped",[7773]],[[7773,7773],"valid"],[[7774,7774],"mapped",[7775]],[[7775,7775],"valid"],[[7776,7776],"mapped",[7777]],[[7777,7777],"valid"],[[7778,7778],"mapped",[7779]],[[7779,7779],"valid"],[[7780,7780],"mapped",[7781]],[[7781,7781],"valid"],[[7782,7782],"mapped",[7783]],[[7783,7783],"valid"],[[7784,7784],"mapped",[7785]],[[7785,7785],"valid"],[[7786,7786],"mapped",[7787]],[[7787,7787],"valid"],[[7788,7788],"mapped",[7789]],[[7789,7789],"valid"],[[7790,7790],"mapped",[7791]],[[7791,7791],"valid"],[[7792,7792],"mapped",[7793]],[[7793,7793],"valid"],[[7794,7794],"mapped",[7795]],[[7795,7795],"valid"],[[7796,7796],"mapped",[7797]],[[7797,7797],"valid"],[[7798,7798],"mapped",[7799]],[[7799,7799],"valid"],[[7800,7800],"mapped",[7801]],[[7801,7801],"valid"],[[7802,7802],"mapped",[7803]],[[7803,7803],"valid"],[[7804,7804],"mapped",[7805]],[[7805,7805],"valid"],[[7806,7806],"mapped",[7807]],[[7807,7807],"valid"],[[7808,7808],"mapped",[7809]],[[7809,7809],"valid"],[[7810,7810],"mapped",[7811]],[[7811,7811],"valid"],[[7812,7812],"mapped",[7813]],[[7813,7813],"valid"],[[7814,7814],"mapped",[7815]],[[7815,7815],"valid"],[[7816,7816],"mapped",[7817]],[[7817,7817],"valid"],[[7818,7818],"mapped",[7819]],[[7819,7819],"valid"],[[7820,7820],"mapped",[7821]],[[7821,7821],"valid"],[[7822,7822],"mapped",[7823]],[[7823,7823],"valid"],[[7824,7824],"mapped",[7825]],[[7825,7825],"valid"],[[7826,7826],"mapped",[7827]],[[7827,7827],"valid"],[[7828,7828],"mapped",[7829]],[[7829,7833],"valid"],[[7834,7834],"mapped",[97,702]],[[7835,7835],"mapped",[7777]],[[7836,7837],"valid"],[[7838,7838],"mapped",[115,115]],[[7839,7839],"valid"],[[7840,7840],"mapped",[7841]],[[7841,7841],"valid"],[[7842,7842],"mapped",[7843]],[[7843,7843],"valid"],[[7844,7844],"mapped",[7845]],[[7845,7845],"valid"],[[7846,7846],"mapped",[7847]],[[7847,7847],"valid"],[[7848,7848],"mapped",[7849]],[[7849,7849],"valid"],[[7850,7850],"mapped",[7851]],[[7851,7851],"valid"],[[7852,7852],"mapped",[7853]],[[7853,7853],"valid"],[[7854,7854],"mapped",[7855]],[[7855,7855],"valid"],[[7856,7856],"mapped",[7857]],[[7857,7857],"valid"],[[7858,7858],"mapped",[7859]],[[7859,7859],"valid"],[[7860,7860],"mapped",[7861]],[[7861,7861],"valid"],[[7862,7862],"mapped",[7863]],[[7863,7863],"valid"],[[7864,7864],"mapped",[7865]],[[7865,7865],"valid"],[[7866,7866],"mapped",[7867]],[[7867,7867],"valid"],[[7868,7868],"mapped",[7869]],[[7869,7869],"valid"],[[7870,7870],"mapped",[7871]],[[7871,7871],"valid"],[[7872,7872],"mapped",[7873]],[[7873,7873],"valid"],[[7874,7874],"mapped",[7875]],[[7875,7875],"valid"],[[7876,7876],"mapped",[7877]],[[7877,7877],"valid"],[[7878,7878],"mapped",[7879]],[[7879,7879],"valid"],[[7880,7880],"mapped",[7881]],[[7881,7881],"valid"],[[7882,7882],"mapped",[7883]],[[7883,7883],"valid"],[[7884,7884],"mapped",[7885]],[[7885,7885],"valid"],[[7886,7886],"mapped",[7887]],[[7887,7887],"valid"],[[7888,7888],"mapped",[7889]],[[7889,7889],"valid"],[[7890,7890],"mapped",[7891]],[[7891,7891],"valid"],[[7892,7892],"mapped",[7893]],[[7893,7893],"valid"],[[7894,7894],"mapped",[7895]],[[7895,7895],"valid"],[[7896,7896],"mapped",[7897]],[[7897,7897],"valid"],[[7898,7898],"mapped",[7899]],[[7899,7899],"valid"],[[7900,7900],"mapped",[7901]],[[7901,7901],"valid"],[[7902,7902],"mapped",[7903]],[[7903,7903],"valid"],[[7904,7904],"mapped",[7905]],[[7905,7905],"valid"],[[7906,7906],"mapped",[7907]],[[7907,7907],"valid"],[[7908,7908],"mapped",[7909]],[[7909,7909],"valid"],[[7910,7910],"mapped",[7911]],[[7911,7911],"valid"],[[7912,7912],"mapped",[7913]],[[7913,7913],"valid"],[[7914,7914],"mapped",[7915]],[[7915,7915],"valid"],[[7916,7916],"mapped",[7917]],[[7917,7917],"valid"],[[7918,7918],"mapped",[7919]],[[7919,7919],"valid"],[[7920,7920],"mapped",[7921]],[[7921,7921],"valid"],[[7922,7922],"mapped",[7923]],[[7923,7923],"valid"],[[7924,7924],"mapped",[7925]],[[7925,7925],"valid"],[[7926,7926],"mapped",[7927]],[[7927,7927],"valid"],[[7928,7928],"mapped",[7929]],[[7929,7929],"valid"],[[7930,7930],"mapped",[7931]],[[7931,7931],"valid"],[[7932,7932],"mapped",[7933]],[[7933,7933],"valid"],[[7934,7934],"mapped",[7935]],[[7935,7935],"valid"],[[7936,7943],"valid"],[[7944,7944],"mapped",[7936]],[[7945,7945],"mapped",[7937]],[[7946,7946],"mapped",[7938]],[[7947,7947],"mapped",[7939]],[[7948,7948],"mapped",[7940]],[[7949,7949],"mapped",[7941]],[[7950,7950],"mapped",[7942]],[[7951,7951],"mapped",[7943]],[[7952,7957],"valid"],[[7958,7959],"disallowed"],[[7960,7960],"mapped",[7952]],[[7961,7961],"mapped",[7953]],[[7962,7962],"mapped",[7954]],[[7963,7963],"mapped",[7955]],[[7964,7964],"mapped",[7956]],[[7965,7965],"mapped",[7957]],[[7966,7967],"disallowed"],[[7968,7975],"valid"],[[7976,7976],"mapped",[7968]],[[7977,7977],"mapped",[7969]],[[7978,7978],"mapped",[7970]],[[7979,7979],"mapped",[7971]],[[7980,7980],"mapped",[7972]],[[7981,7981],"mapped",[7973]],[[7982,7982],"mapped",[7974]],[[7983,7983],"mapped",[7975]],[[7984,7991],"valid"],[[7992,7992],"mapped",[7984]],[[7993,7993],"mapped",[7985]],[[7994,7994],"mapped",[7986]],[[7995,7995],"mapped",[7987]],[[7996,7996],"mapped",[7988]],[[7997,7997],"mapped",[7989]],[[7998,7998],"mapped",[7990]],[[7999,7999],"mapped",[7991]],[[8000,8005],"valid"],[[8006,8007],"disallowed"],[[8008,8008],"mapped",[8000]],[[8009,8009],"mapped",[8001]],[[8010,8010],"mapped",[8002]],[[8011,8011],"mapped",[8003]],[[8012,8012],"mapped",[8004]],[[8013,8013],"mapped",[8005]],[[8014,8015],"disallowed"],[[8016,8023],"valid"],[[8024,8024],"disallowed"],[[8025,8025],"mapped",[8017]],[[8026,8026],"disallowed"],[[8027,8027],"mapped",[8019]],[[8028,8028],"disallowed"],[[8029,8029],"mapped",[8021]],[[8030,8030],"disallowed"],[[8031,8031],"mapped",[8023]],[[8032,8039],"valid"],[[8040,8040],"mapped",[8032]],[[8041,8041],"mapped",[8033]],[[8042,8042],"mapped",[8034]],[[8043,8043],"mapped",[8035]],[[8044,8044],"mapped",[8036]],[[8045,8045],"mapped",[8037]],[[8046,8046],"mapped",[8038]],[[8047,8047],"mapped",[8039]],[[8048,8048],"valid"],[[8049,8049],"mapped",[940]],[[8050,8050],"valid"],[[8051,8051],"mapped",[941]],[[8052,8052],"valid"],[[8053,8053],"mapped",[942]],[[8054,8054],"valid"],[[8055,8055],"mapped",[943]],[[8056,8056],"valid"],[[8057,8057],"mapped",[972]],[[8058,8058],"valid"],[[8059,8059],"mapped",[973]],[[8060,8060],"valid"],[[8061,8061],"mapped",[974]],[[8062,8063],"disallowed"],[[8064,8064],"mapped",[7936,953]],[[8065,8065],"mapped",[7937,953]],[[8066,8066],"mapped",[7938,953]],[[8067,8067],"mapped",[7939,953]],[[8068,8068],"mapped",[7940,953]],[[8069,8069],"mapped",[7941,953]],[[8070,8070],"mapped",[7942,953]],[[8071,8071],"mapped",[7943,953]],[[8072,8072],"mapped",[7936,953]],[[8073,8073],"mapped",[7937,953]],[[8074,8074],"mapped",[7938,953]],[[8075,8075],"mapped",[7939,953]],[[8076,8076],"mapped",[7940,953]],[[8077,8077],"mapped",[7941,953]],[[8078,8078],"mapped",[7942,953]],[[8079,8079],"mapped",[7943,953]],[[8080,8080],"mapped",[7968,953]],[[8081,8081],"mapped",[7969,953]],[[8082,8082],"mapped",[7970,953]],[[8083,8083],"mapped",[7971,953]],[[8084,8084],"mapped",[7972,953]],[[8085,8085],"mapped",[7973,953]],[[8086,8086],"mapped",[7974,953]],[[8087,8087],"mapped",[7975,953]],[[8088,8088],"mapped",[7968,953]],[[8089,8089],"mapped",[7969,953]],[[8090,8090],"mapped",[7970,953]],[[8091,8091],"mapped",[7971,953]],[[8092,8092],"mapped",[7972,953]],[[8093,8093],"mapped",[7973,953]],[[8094,8094],"mapped",[7974,953]],[[8095,8095],"mapped",[7975,953]],[[8096,8096],"mapped",[8032,953]],[[8097,8097],"mapped",[8033,953]],[[8098,8098],"mapped",[8034,953]],[[8099,8099],"mapped",[8035,953]],[[8100,8100],"mapped",[8036,953]],[[8101,8101],"mapped",[8037,953]],[[8102,8102],"mapped",[8038,953]],[[8103,8103],"mapped",[8039,953]],[[8104,8104],"mapped",[8032,953]],[[8105,8105],"mapped",[8033,953]],[[8106,8106],"mapped",[8034,953]],[[8107,8107],"mapped",[8035,953]],[[8108,8108],"mapped",[8036,953]],[[8109,8109],"mapped",[8037,953]],[[8110,8110],"mapped",[8038,953]],[[8111,8111],"mapped",[8039,953]],[[8112,8113],"valid"],[[8114,8114],"mapped",[8048,953]],[[8115,8115],"mapped",[945,953]],[[8116,8116],"mapped",[940,953]],[[8117,8117],"disallowed"],[[8118,8118],"valid"],[[8119,8119],"mapped",[8118,953]],[[8120,8120],"mapped",[8112]],[[8121,8121],"mapped",[8113]],[[8122,8122],"mapped",[8048]],[[8123,8123],"mapped",[940]],[[8124,8124],"mapped",[945,953]],[[8125,8125],"disallowed_STD3_mapped",[32,787]],[[8126,8126],"mapped",[953]],[[8127,8127],"disallowed_STD3_mapped",[32,787]],[[8128,8128],"disallowed_STD3_mapped",[32,834]],[[8129,8129],"disallowed_STD3_mapped",[32,776,834]],[[8130,8130],"mapped",[8052,953]],[[8131,8131],"mapped",[951,953]],[[8132,8132],"mapped",[942,953]],[[8133,8133],"disallowed"],[[8134,8134],"valid"],[[8135,8135],"mapped",[8134,953]],[[8136,8136],"mapped",[8050]],[[8137,8137],"mapped",[941]],[[8138,8138],"mapped",[8052]],[[8139,8139],"mapped",[942]],[[8140,8140],"mapped",[951,953]],[[8141,8141],"disallowed_STD3_mapped",[32,787,768]],[[8142,8142],"disallowed_STD3_mapped",[32,787,769]],[[8143,8143],"disallowed_STD3_mapped",[32,787,834]],[[8144,8146],"valid"],[[8147,8147],"mapped",[912]],[[8148,8149],"disallowed"],[[8150,8151],"valid"],[[8152,8152],"mapped",[8144]],[[8153,8153],"mapped",[8145]],[[8154,8154],"mapped",[8054]],[[8155,8155],"mapped",[943]],[[8156,8156],"disallowed"],[[8157,8157],"disallowed_STD3_mapped",[32,788,768]],[[8158,8158],"disallowed_STD3_mapped",[32,788,769]],[[8159,8159],"disallowed_STD3_mapped",[32,788,834]],[[8160,8162],"valid"],[[8163,8163],"mapped",[944]],[[8164,8167],"valid"],[[8168,8168],"mapped",[8160]],[[8169,8169],"mapped",[8161]],[[8170,8170],"mapped",[8058]],[[8171,8171],"mapped",[973]],[[8172,8172],"mapped",[8165]],[[8173,8173],"disallowed_STD3_mapped",[32,776,768]],[[8174,8174],"disallowed_STD3_mapped",[32,776,769]],[[8175,8175],"disallowed_STD3_mapped",[96]],[[8176,8177],"disallowed"],[[8178,8178],"mapped",[8060,953]],[[8179,8179],"mapped",[969,953]],[[8180,8180],"mapped",[974,953]],[[8181,8181],"disallowed"],[[8182,8182],"valid"],[[8183,8183],"mapped",[8182,953]],[[8184,8184],"mapped",[8056]],[[8185,8185],"mapped",[972]],[[8186,8186],"mapped",[8060]],[[8187,8187],"mapped",[974]],[[8188,8188],"mapped",[969,953]],[[8189,8189],"disallowed_STD3_mapped",[32,769]],[[8190,8190],"disallowed_STD3_mapped",[32,788]],[[8191,8191],"disallowed"],[[8192,8202],"disallowed_STD3_mapped",[32]],[[8203,8203],"ignored"],[[8204,8205],"deviation",[]],[[8206,8207],"disallowed"],[[8208,8208],"valid",[],"NV8"],[[8209,8209],"mapped",[8208]],[[8210,8214],"valid",[],"NV8"],[[8215,8215],"disallowed_STD3_mapped",[32,819]],[[8216,8227],"valid",[],"NV8"],[[8228,8230],"disallowed"],[[8231,8231],"valid",[],"NV8"],[[8232,8238],"disallowed"],[[8239,8239],"disallowed_STD3_mapped",[32]],[[8240,8242],"valid",[],"NV8"],[[8243,8243],"mapped",[8242,8242]],[[8244,8244],"mapped",[8242,8242,8242]],[[8245,8245],"valid",[],"NV8"],[[8246,8246],"mapped",[8245,8245]],[[8247,8247],"mapped",[8245,8245,8245]],[[8248,8251],"valid",[],"NV8"],[[8252,8252],"disallowed_STD3_mapped",[33,33]],[[8253,8253],"valid",[],"NV8"],[[8254,8254],"disallowed_STD3_mapped",[32,773]],[[8255,8262],"valid",[],"NV8"],[[8263,8263],"disallowed_STD3_mapped",[63,63]],[[8264,8264],"disallowed_STD3_mapped",[63,33]],[[8265,8265],"disallowed_STD3_mapped",[33,63]],[[8266,8269],"valid",[],"NV8"],[[8270,8274],"valid",[],"NV8"],[[8275,8276],"valid",[],"NV8"],[[8277,8278],"valid",[],"NV8"],[[8279,8279],"mapped",[8242,8242,8242,8242]],[[8280,8286],"valid",[],"NV8"],[[8287,8287],"disallowed_STD3_mapped",[32]],[[8288,8288],"ignored"],[[8289,8291],"disallowed"],[[8292,8292],"ignored"],[[8293,8293],"disallowed"],[[8294,8297],"disallowed"],[[8298,8303],"disallowed"],[[8304,8304],"mapped",[48]],[[8305,8305],"mapped",[105]],[[8306,8307],"disallowed"],[[8308,8308],"mapped",[52]],[[8309,8309],"mapped",[53]],[[8310,8310],"mapped",[54]],[[8311,8311],"mapped",[55]],[[8312,8312],"mapped",[56]],[[8313,8313],"mapped",[57]],[[8314,8314],"disallowed_STD3_mapped",[43]],[[8315,8315],"mapped",[8722]],[[8316,8316],"disallowed_STD3_mapped",[61]],[[8317,8317],"disallowed_STD3_mapped",[40]],[[8318,8318],"disallowed_STD3_mapped",[41]],[[8319,8319],"mapped",[110]],[[8320,8320],"mapped",[48]],[[8321,8321],"mapped",[49]],[[8322,8322],"mapped",[50]],[[8323,8323],"mapped",[51]],[[8324,8324],"mapped",[52]],[[8325,8325],"mapped",[53]],[[8326,8326],"mapped",[54]],[[8327,8327],"mapped",[55]],[[8328,8328],"mapped",[56]],[[8329,8329],"mapped",[57]],[[8330,8330],"disallowed_STD3_mapped",[43]],[[8331,8331],"mapped",[8722]],[[8332,8332],"disallowed_STD3_mapped",[61]],[[8333,8333],"disallowed_STD3_mapped",[40]],[[8334,8334],"disallowed_STD3_mapped",[41]],[[8335,8335],"disallowed"],[[8336,8336],"mapped",[97]],[[8337,8337],"mapped",[101]],[[8338,8338],"mapped",[111]],[[8339,8339],"mapped",[120]],[[8340,8340],"mapped",[601]],[[8341,8341],"mapped",[104]],[[8342,8342],"mapped",[107]],[[8343,8343],"mapped",[108]],[[8344,8344],"mapped",[109]],[[8345,8345],"mapped",[110]],[[8346,8346],"mapped",[112]],[[8347,8347],"mapped",[115]],[[8348,8348],"mapped",[116]],[[8349,8351],"disallowed"],[[8352,8359],"valid",[],"NV8"],[[8360,8360],"mapped",[114,115]],[[8361,8362],"valid",[],"NV8"],[[8363,8363],"valid",[],"NV8"],[[8364,8364],"valid",[],"NV8"],[[8365,8367],"valid",[],"NV8"],[[8368,8369],"valid",[],"NV8"],[[8370,8373],"valid",[],"NV8"],[[8374,8376],"valid",[],"NV8"],[[8377,8377],"valid",[],"NV8"],[[8378,8378],"valid",[],"NV8"],[[8379,8381],"valid",[],"NV8"],[[8382,8382],"valid",[],"NV8"],[[8383,8399],"disallowed"],[[8400,8417],"valid",[],"NV8"],[[8418,8419],"valid",[],"NV8"],[[8420,8426],"valid",[],"NV8"],[[8427,8427],"valid",[],"NV8"],[[8428,8431],"valid",[],"NV8"],[[8432,8432],"valid",[],"NV8"],[[8433,8447],"disallowed"],[[8448,8448],"disallowed_STD3_mapped",[97,47,99]],[[8449,8449],"disallowed_STD3_mapped",[97,47,115]],[[8450,8450],"mapped",[99]],[[8451,8451],"mapped",[176,99]],[[8452,8452],"valid",[],"NV8"],[[8453,8453],"disallowed_STD3_mapped",[99,47,111]],[[8454,8454],"disallowed_STD3_mapped",[99,47,117]],[[8455,8455],"mapped",[603]],[[8456,8456],"valid",[],"NV8"],[[8457,8457],"mapped",[176,102]],[[8458,8458],"mapped",[103]],[[8459,8462],"mapped",[104]],[[8463,8463],"mapped",[295]],[[8464,8465],"mapped",[105]],[[8466,8467],"mapped",[108]],[[8468,8468],"valid",[],"NV8"],[[8469,8469],"mapped",[110]],[[8470,8470],"mapped",[110,111]],[[8471,8472],"valid",[],"NV8"],[[8473,8473],"mapped",[112]],[[8474,8474],"mapped",[113]],[[8475,8477],"mapped",[114]],[[8478,8479],"valid",[],"NV8"],[[8480,8480],"mapped",[115,109]],[[8481,8481],"mapped",[116,101,108]],[[8482,8482],"mapped",[116,109]],[[8483,8483],"valid",[],"NV8"],[[8484,8484],"mapped",[122]],[[8485,8485],"valid",[],"NV8"],[[8486,8486],"mapped",[969]],[[8487,8487],"valid",[],"NV8"],[[8488,8488],"mapped",[122]],[[8489,8489],"valid",[],"NV8"],[[8490,8490],"mapped",[107]],[[8491,8491],"mapped",[229]],[[8492,8492],"mapped",[98]],[[8493,8493],"mapped",[99]],[[8494,8494],"valid",[],"NV8"],[[8495,8496],"mapped",[101]],[[8497,8497],"mapped",[102]],[[8498,8498],"disallowed"],[[8499,8499],"mapped",[109]],[[8500,8500],"mapped",[111]],[[8501,8501],"mapped",[1488]],[[8502,8502],"mapped",[1489]],[[8503,8503],"mapped",[1490]],[[8504,8504],"mapped",[1491]],[[8505,8505],"mapped",[105]],[[8506,8506],"valid",[],"NV8"],[[8507,8507],"mapped",[102,97,120]],[[8508,8508],"mapped",[960]],[[8509,8510],"mapped",[947]],[[8511,8511],"mapped",[960]],[[8512,8512],"mapped",[8721]],[[8513,8516],"valid",[],"NV8"],[[8517,8518],"mapped",[100]],[[8519,8519],"mapped",[101]],[[8520,8520],"mapped",[105]],[[8521,8521],"mapped",[106]],[[8522,8523],"valid",[],"NV8"],[[8524,8524],"valid",[],"NV8"],[[8525,8525],"valid",[],"NV8"],[[8526,8526],"valid"],[[8527,8527],"valid",[],"NV8"],[[8528,8528],"mapped",[49,8260,55]],[[8529,8529],"mapped",[49,8260,57]],[[8530,8530],"mapped",[49,8260,49,48]],[[8531,8531],"mapped",[49,8260,51]],[[8532,8532],"mapped",[50,8260,51]],[[8533,8533],"mapped",[49,8260,53]],[[8534,8534],"mapped",[50,8260,53]],[[8535,8535],"mapped",[51,8260,53]],[[8536,8536],"mapped",[52,8260,53]],[[8537,8537],"mapped",[49,8260,54]],[[8538,8538],"mapped",[53,8260,54]],[[8539,8539],"mapped",[49,8260,56]],[[8540,8540],"mapped",[51,8260,56]],[[8541,8541],"mapped",[53,8260,56]],[[8542,8542],"mapped",[55,8260,56]],[[8543,8543],"mapped",[49,8260]],[[8544,8544],"mapped",[105]],[[8545,8545],"mapped",[105,105]],[[8546,8546],"mapped",[105,105,105]],[[8547,8547],"mapped",[105,118]],[[8548,8548],"mapped",[118]],[[8549,8549],"mapped",[118,105]],[[8550,8550],"mapped",[118,105,105]],[[8551,8551],"mapped",[118,105,105,105]],[[8552,8552],"mapped",[105,120]],[[8553,8553],"mapped",[120]],[[8554,8554],"mapped",[120,105]],[[8555,8555],"mapped",[120,105,105]],[[8556,8556],"mapped",[108]],[[8557,8557],"mapped",[99]],[[8558,8558],"mapped",[100]],[[8559,8559],"mapped",[109]],[[8560,8560],"mapped",[105]],[[8561,8561],"mapped",[105,105]],[[8562,8562],"mapped",[105,105,105]],[[8563,8563],"mapped",[105,118]],[[8564,8564],"mapped",[118]],[[8565,8565],"mapped",[118,105]],[[8566,8566],"mapped",[118,105,105]],[[8567,8567],"mapped",[118,105,105,105]],[[8568,8568],"mapped",[105,120]],[[8569,8569],"mapped",[120]],[[8570,8570],"mapped",[120,105]],[[8571,8571],"mapped",[120,105,105]],[[8572,8572],"mapped",[108]],[[8573,8573],"mapped",[99]],[[8574,8574],"mapped",[100]],[[8575,8575],"mapped",[109]],[[8576,8578],"valid",[],"NV8"],[[8579,8579],"disallowed"],[[8580,8580],"valid"],[[8581,8584],"valid",[],"NV8"],[[8585,8585],"mapped",[48,8260,51]],[[8586,8587],"valid",[],"NV8"],[[8588,8591],"disallowed"],[[8592,8682],"valid",[],"NV8"],[[8683,8691],"valid",[],"NV8"],[[8692,8703],"valid",[],"NV8"],[[8704,8747],"valid",[],"NV8"],[[8748,8748],"mapped",[8747,8747]],[[8749,8749],"mapped",[8747,8747,8747]],[[8750,8750],"valid",[],"NV8"],[[8751,8751],"mapped",[8750,8750]],[[8752,8752],"mapped",[8750,8750,8750]],[[8753,8799],"valid",[],"NV8"],[[8800,8800],"disallowed_STD3_valid"],[[8801,8813],"valid",[],"NV8"],[[8814,8815],"disallowed_STD3_valid"],[[8816,8945],"valid",[],"NV8"],[[8946,8959],"valid",[],"NV8"],[[8960,8960],"valid",[],"NV8"],[[8961,8961],"valid",[],"NV8"],[[8962,9000],"valid",[],"NV8"],[[9001,9001],"mapped",[12296]],[[9002,9002],"mapped",[12297]],[[9003,9082],"valid",[],"NV8"],[[9083,9083],"valid",[],"NV8"],[[9084,9084],"valid",[],"NV8"],[[9085,9114],"valid",[],"NV8"],[[9115,9166],"valid",[],"NV8"],[[9167,9168],"valid",[],"NV8"],[[9169,9179],"valid",[],"NV8"],[[9180,9191],"valid",[],"NV8"],[[9192,9192],"valid",[],"NV8"],[[9193,9203],"valid",[],"NV8"],[[9204,9210],"valid",[],"NV8"],[[9211,9215],"disallowed"],[[9216,9252],"valid",[],"NV8"],[[9253,9254],"valid",[],"NV8"],[[9255,9279],"disallowed"],[[9280,9290],"valid",[],"NV8"],[[9291,9311],"disallowed"],[[9312,9312],"mapped",[49]],[[9313,9313],"mapped",[50]],[[9314,9314],"mapped",[51]],[[9315,9315],"mapped",[52]],[[9316,9316],"mapped",[53]],[[9317,9317],"mapped",[54]],[[9318,9318],"mapped",[55]],[[9319,9319],"mapped",[56]],[[9320,9320],"mapped",[57]],[[9321,9321],"mapped",[49,48]],[[9322,9322],"mapped",[49,49]],[[9323,9323],"mapped",[49,50]],[[9324,9324],"mapped",[49,51]],[[9325,9325],"mapped",[49,52]],[[9326,9326],"mapped",[49,53]],[[9327,9327],"mapped",[49,54]],[[9328,9328],"mapped",[49,55]],[[9329,9329],"mapped",[49,56]],[[9330,9330],"mapped",[49,57]],[[9331,9331],"mapped",[50,48]],[[9332,9332],"disallowed_STD3_mapped",[40,49,41]],[[9333,9333],"disallowed_STD3_mapped",[40,50,41]],[[9334,9334],"disallowed_STD3_mapped",[40,51,41]],[[9335,9335],"disallowed_STD3_mapped",[40,52,41]],[[9336,9336],"disallowed_STD3_mapped",[40,53,41]],[[9337,9337],"disallowed_STD3_mapped",[40,54,41]],[[9338,9338],"disallowed_STD3_mapped",[40,55,41]],[[9339,9339],"disallowed_STD3_mapped",[40,56,41]],[[9340,9340],"disallowed_STD3_mapped",[40,57,41]],[[9341,9341],"disallowed_STD3_mapped",[40,49,48,41]],[[9342,9342],"disallowed_STD3_mapped",[40,49,49,41]],[[9343,9343],"disallowed_STD3_mapped",[40,49,50,41]],[[9344,9344],"disallowed_STD3_mapped",[40,49,51,41]],[[9345,9345],"disallowed_STD3_mapped",[40,49,52,41]],[[9346,9346],"disallowed_STD3_mapped",[40,49,53,41]],[[9347,9347],"disallowed_STD3_mapped",[40,49,54,41]],[[9348,9348],"disallowed_STD3_mapped",[40,49,55,41]],[[9349,9349],"disallowed_STD3_mapped",[40,49,56,41]],[[9350,9350],"disallowed_STD3_mapped",[40,49,57,41]],[[9351,9351],"disallowed_STD3_mapped",[40,50,48,41]],[[9352,9371],"disallowed"],[[9372,9372],"disallowed_STD3_mapped",[40,97,41]],[[9373,9373],"disallowed_STD3_mapped",[40,98,41]],[[9374,9374],"disallowed_STD3_mapped",[40,99,41]],[[9375,9375],"disallowed_STD3_mapped",[40,100,41]],[[9376,9376],"disallowed_STD3_mapped",[40,101,41]],[[9377,9377],"disallowed_STD3_mapped",[40,102,41]],[[9378,9378],"disallowed_STD3_mapped",[40,103,41]],[[9379,9379],"disallowed_STD3_mapped",[40,104,41]],[[9380,9380],"disallowed_STD3_mapped",[40,105,41]],[[9381,9381],"disallowed_STD3_mapped",[40,106,41]],[[9382,9382],"disallowed_STD3_mapped",[40,107,41]],[[9383,9383],"disallowed_STD3_mapped",[40,108,41]],[[9384,9384],"disallowed_STD3_mapped",[40,109,41]],[[9385,9385],"disallowed_STD3_mapped",[40,110,41]],[[9386,9386],"disallowed_STD3_mapped",[40,111,41]],[[9387,9387],"disallowed_STD3_mapped",[40,112,41]],[[9388,9388],"disallowed_STD3_mapped",[40,113,41]],[[9389,9389],"disallowed_STD3_mapped",[40,114,41]],[[9390,9390],"disallowed_STD3_mapped",[40,115,41]],[[9391,9391],"disallowed_STD3_mapped",[40,116,41]],[[9392,9392],"disallowed_STD3_mapped",[40,117,41]],[[9393,9393],"disallowed_STD3_mapped",[40,118,41]],[[9394,9394],"disallowed_STD3_mapped",[40,119,41]],[[9395,9395],"disallowed_STD3_mapped",[40,120,41]],[[9396,9396],"disallowed_STD3_mapped",[40,121,41]],[[9397,9397],"disallowed_STD3_mapped",[40,122,41]],[[9398,9398],"mapped",[97]],[[9399,9399],"mapped",[98]],[[9400,9400],"mapped",[99]],[[9401,9401],"mapped",[100]],[[9402,9402],"mapped",[101]],[[9403,9403],"mapped",[102]],[[9404,9404],"mapped",[103]],[[9405,9405],"mapped",[104]],[[9406,9406],"mapped",[105]],[[9407,9407],"mapped",[106]],[[9408,9408],"mapped",[107]],[[9409,9409],"mapped",[108]],[[9410,9410],"mapped",[109]],[[9411,9411],"mapped",[110]],[[9412,9412],"mapped",[111]],[[9413,9413],"mapped",[112]],[[9414,9414],"mapped",[113]],[[9415,9415],"mapped",[114]],[[9416,9416],"mapped",[115]],[[9417,9417],"mapped",[116]],[[9418,9418],"mapped",[117]],[[9419,9419],"mapped",[118]],[[9420,9420],"mapped",[119]],[[9421,9421],"mapped",[120]],[[9422,9422],"mapped",[121]],[[9423,9423],"mapped",[122]],[[9424,9424],"mapped",[97]],[[9425,9425],"mapped",[98]],[[9426,9426],"mapped",[99]],[[9427,9427],"mapped",[100]],[[9428,9428],"mapped",[101]],[[9429,9429],"mapped",[102]],[[9430,9430],"mapped",[103]],[[9431,9431],"mapped",[104]],[[9432,9432],"mapped",[105]],[[9433,9433],"mapped",[106]],[[9434,9434],"mapped",[107]],[[9435,9435],"mapped",[108]],[[9436,9436],"mapped",[109]],[[9437,9437],"mapped",[110]],[[9438,9438],"mapped",[111]],[[9439,9439],"mapped",[112]],[[9440,9440],"mapped",[113]],[[9441,9441],"mapped",[114]],[[9442,9442],"mapped",[115]],[[9443,9443],"mapped",[116]],[[9444,9444],"mapped",[117]],[[9445,9445],"mapped",[118]],[[9446,9446],"mapped",[119]],[[9447,9447],"mapped",[120]],[[9448,9448],"mapped",[121]],[[9449,9449],"mapped",[122]],[[9450,9450],"mapped",[48]],[[9451,9470],"valid",[],"NV8"],[[9471,9471],"valid",[],"NV8"],[[9472,9621],"valid",[],"NV8"],[[9622,9631],"valid",[],"NV8"],[[9632,9711],"valid",[],"NV8"],[[9712,9719],"valid",[],"NV8"],[[9720,9727],"valid",[],"NV8"],[[9728,9747],"valid",[],"NV8"],[[9748,9749],"valid",[],"NV8"],[[9750,9751],"valid",[],"NV8"],[[9752,9752],"valid",[],"NV8"],[[9753,9753],"valid",[],"NV8"],[[9754,9839],"valid",[],"NV8"],[[9840,9841],"valid",[],"NV8"],[[9842,9853],"valid",[],"NV8"],[[9854,9855],"valid",[],"NV8"],[[9856,9865],"valid",[],"NV8"],[[9866,9873],"valid",[],"NV8"],[[9874,9884],"valid",[],"NV8"],[[9885,9885],"valid",[],"NV8"],[[9886,9887],"valid",[],"NV8"],[[9888,9889],"valid",[],"NV8"],[[9890,9905],"valid",[],"NV8"],[[9906,9906],"valid",[],"NV8"],[[9907,9916],"valid",[],"NV8"],[[9917,9919],"valid",[],"NV8"],[[9920,9923],"valid",[],"NV8"],[[9924,9933],"valid",[],"NV8"],[[9934,9934],"valid",[],"NV8"],[[9935,9953],"valid",[],"NV8"],[[9954,9954],"valid",[],"NV8"],[[9955,9955],"valid",[],"NV8"],[[9956,9959],"valid",[],"NV8"],[[9960,9983],"valid",[],"NV8"],[[9984,9984],"valid",[],"NV8"],[[9985,9988],"valid",[],"NV8"],[[9989,9989],"valid",[],"NV8"],[[9990,9993],"valid",[],"NV8"],[[9994,9995],"valid",[],"NV8"],[[9996,10023],"valid",[],"NV8"],[[10024,10024],"valid",[],"NV8"],[[10025,10059],"valid",[],"NV8"],[[10060,10060],"valid",[],"NV8"],[[10061,10061],"valid",[],"NV8"],[[10062,10062],"valid",[],"NV8"],[[10063,10066],"valid",[],"NV8"],[[10067,10069],"valid",[],"NV8"],[[10070,10070],"valid",[],"NV8"],[[10071,10071],"valid",[],"NV8"],[[10072,10078],"valid",[],"NV8"],[[10079,10080],"valid",[],"NV8"],[[10081,10087],"valid",[],"NV8"],[[10088,10101],"valid",[],"NV8"],[[10102,10132],"valid",[],"NV8"],[[10133,10135],"valid",[],"NV8"],[[10136,10159],"valid",[],"NV8"],[[10160,10160],"valid",[],"NV8"],[[10161,10174],"valid",[],"NV8"],[[10175,10175],"valid",[],"NV8"],[[10176,10182],"valid",[],"NV8"],[[10183,10186],"valid",[],"NV8"],[[10187,10187],"valid",[],"NV8"],[[10188,10188],"valid",[],"NV8"],[[10189,10189],"valid",[],"NV8"],[[10190,10191],"valid",[],"NV8"],[[10192,10219],"valid",[],"NV8"],[[10220,10223],"valid",[],"NV8"],[[10224,10239],"valid",[],"NV8"],[[10240,10495],"valid",[],"NV8"],[[10496,10763],"valid",[],"NV8"],[[10764,10764],"mapped",[8747,8747,8747,8747]],[[10765,10867],"valid",[],"NV8"],[[10868,10868],"disallowed_STD3_mapped",[58,58,61]],[[10869,10869],"disallowed_STD3_mapped",[61,61]],[[10870,10870],"disallowed_STD3_mapped",[61,61,61]],[[10871,10971],"valid",[],"NV8"],[[10972,10972],"mapped",[10973,824]],[[10973,11007],"valid",[],"NV8"],[[11008,11021],"valid",[],"NV8"],[[11022,11027],"valid",[],"NV8"],[[11028,11034],"valid",[],"NV8"],[[11035,11039],"valid",[],"NV8"],[[11040,11043],"valid",[],"NV8"],[[11044,11084],"valid",[],"NV8"],[[11085,11087],"valid",[],"NV8"],[[11088,11092],"valid",[],"NV8"],[[11093,11097],"valid",[],"NV8"],[[11098,11123],"valid",[],"NV8"],[[11124,11125],"disallowed"],[[11126,11157],"valid",[],"NV8"],[[11158,11159],"disallowed"],[[11160,11193],"valid",[],"NV8"],[[11194,11196],"disallowed"],[[11197,11208],"valid",[],"NV8"],[[11209,11209],"disallowed"],[[11210,11217],"valid",[],"NV8"],[[11218,11243],"disallowed"],[[11244,11247],"valid",[],"NV8"],[[11248,11263],"disallowed"],[[11264,11264],"mapped",[11312]],[[11265,11265],"mapped",[11313]],[[11266,11266],"mapped",[11314]],[[11267,11267],"mapped",[11315]],[[11268,11268],"mapped",[11316]],[[11269,11269],"mapped",[11317]],[[11270,11270],"mapped",[11318]],[[11271,11271],"mapped",[11319]],[[11272,11272],"mapped",[11320]],[[11273,11273],"mapped",[11321]],[[11274,11274],"mapped",[11322]],[[11275,11275],"mapped",[11323]],[[11276,11276],"mapped",[11324]],[[11277,11277],"mapped",[11325]],[[11278,11278],"mapped",[11326]],[[11279,11279],"mapped",[11327]],[[11280,11280],"mapped",[11328]],[[11281,11281],"mapped",[11329]],[[11282,11282],"mapped",[11330]],[[11283,11283],"mapped",[11331]],[[11284,11284],"mapped",[11332]],[[11285,11285],"mapped",[11333]],[[11286,11286],"mapped",[11334]],[[11287,11287],"mapped",[11335]],[[11288,11288],"mapped",[11336]],[[11289,11289],"mapped",[11337]],[[11290,11290],"mapped",[11338]],[[11291,11291],"mapped",[11339]],[[11292,11292],"mapped",[11340]],[[11293,11293],"mapped",[11341]],[[11294,11294],"mapped",[11342]],[[11295,11295],"mapped",[11343]],[[11296,11296],"mapped",[11344]],[[11297,11297],"mapped",[11345]],[[11298,11298],"mapped",[11346]],[[11299,11299],"mapped",[11347]],[[11300,11300],"mapped",[11348]],[[11301,11301],"mapped",[11349]],[[11302,11302],"mapped",[11350]],[[11303,11303],"mapped",[11351]],[[11304,11304],"mapped",[11352]],[[11305,11305],"mapped",[11353]],[[11306,11306],"mapped",[11354]],[[11307,11307],"mapped",[11355]],[[11308,11308],"mapped",[11356]],[[11309,11309],"mapped",[11357]],[[11310,11310],"mapped",[11358]],[[11311,11311],"disallowed"],[[11312,11358],"valid"],[[11359,11359],"disallowed"],[[11360,11360],"mapped",[11361]],[[11361,11361],"valid"],[[11362,11362],"mapped",[619]],[[11363,11363],"mapped",[7549]],[[11364,11364],"mapped",[637]],[[11365,11366],"valid"],[[11367,11367],"mapped",[11368]],[[11368,11368],"valid"],[[11369,11369],"mapped",[11370]],[[11370,11370],"valid"],[[11371,11371],"mapped",[11372]],[[11372,11372],"valid"],[[11373,11373],"mapped",[593]],[[11374,11374],"mapped",[625]],[[11375,11375],"mapped",[592]],[[11376,11376],"mapped",[594]],[[11377,11377],"valid"],[[11378,11378],"mapped",[11379]],[[11379,11379],"valid"],[[11380,11380],"valid"],[[11381,11381],"mapped",[11382]],[[11382,11383],"valid"],[[11384,11387],"valid"],[[11388,11388],"mapped",[106]],[[11389,11389],"mapped",[118]],[[11390,11390],"mapped",[575]],[[11391,11391],"mapped",[576]],[[11392,11392],"mapped",[11393]],[[11393,11393],"valid"],[[11394,11394],"mapped",[11395]],[[11395,11395],"valid"],[[11396,11396],"mapped",[11397]],[[11397,11397],"valid"],[[11398,11398],"mapped",[11399]],[[11399,11399],"valid"],[[11400,11400],"mapped",[11401]],[[11401,11401],"valid"],[[11402,11402],"mapped",[11403]],[[11403,11403],"valid"],[[11404,11404],"mapped",[11405]],[[11405,11405],"valid"],[[11406,11406],"mapped",[11407]],[[11407,11407],"valid"],[[11408,11408],"mapped",[11409]],[[11409,11409],"valid"],[[11410,11410],"mapped",[11411]],[[11411,11411],"valid"],[[11412,11412],"mapped",[11413]],[[11413,11413],"valid"],[[11414,11414],"mapped",[11415]],[[11415,11415],"valid"],[[11416,11416],"mapped",[11417]],[[11417,11417],"valid"],[[11418,11418],"mapped",[11419]],[[11419,11419],"valid"],[[11420,11420],"mapped",[11421]],[[11421,11421],"valid"],[[11422,11422],"mapped",[11423]],[[11423,11423],"valid"],[[11424,11424],"mapped",[11425]],[[11425,11425],"valid"],[[11426,11426],"mapped",[11427]],[[11427,11427],"valid"],[[11428,11428],"mapped",[11429]],[[11429,11429],"valid"],[[11430,11430],"mapped",[11431]],[[11431,11431],"valid"],[[11432,11432],"mapped",[11433]],[[11433,11433],"valid"],[[11434,11434],"mapped",[11435]],[[11435,11435],"valid"],[[11436,11436],"mapped",[11437]],[[11437,11437],"valid"],[[11438,11438],"mapped",[11439]],[[11439,11439],"valid"],[[11440,11440],"mapped",[11441]],[[11441,11441],"valid"],[[11442,11442],"mapped",[11443]],[[11443,11443],"valid"],[[11444,11444],"mapped",[11445]],[[11445,11445],"valid"],[[11446,11446],"mapped",[11447]],[[11447,11447],"valid"],[[11448,11448],"mapped",[11449]],[[11449,11449],"valid"],[[11450,11450],"mapped",[11451]],[[11451,11451],"valid"],[[11452,11452],"mapped",[11453]],[[11453,11453],"valid"],[[11454,11454],"mapped",[11455]],[[11455,11455],"valid"],[[11456,11456],"mapped",[11457]],[[11457,11457],"valid"],[[11458,11458],"mapped",[11459]],[[11459,11459],"valid"],[[11460,11460],"mapped",[11461]],[[11461,11461],"valid"],[[11462,11462],"mapped",[11463]],[[11463,11463],"valid"],[[11464,11464],"mapped",[11465]],[[11465,11465],"valid"],[[11466,11466],"mapped",[11467]],[[11467,11467],"valid"],[[11468,11468],"mapped",[11469]],[[11469,11469],"valid"],[[11470,11470],"mapped",[11471]],[[11471,11471],"valid"],[[11472,11472],"mapped",[11473]],[[11473,11473],"valid"],[[11474,11474],"mapped",[11475]],[[11475,11475],"valid"],[[11476,11476],"mapped",[11477]],[[11477,11477],"valid"],[[11478,11478],"mapped",[11479]],[[11479,11479],"valid"],[[11480,11480],"mapped",[11481]],[[11481,11481],"valid"],[[11482,11482],"mapped",[11483]],[[11483,11483],"valid"],[[11484,11484],"mapped",[11485]],[[11485,11485],"valid"],[[11486,11486],"mapped",[11487]],[[11487,11487],"valid"],[[11488,11488],"mapped",[11489]],[[11489,11489],"valid"],[[11490,11490],"mapped",[11491]],[[11491,11492],"valid"],[[11493,11498],"valid",[],"NV8"],[[11499,11499],"mapped",[11500]],[[11500,11500],"valid"],[[11501,11501],"mapped",[11502]],[[11502,11505],"valid"],[[11506,11506],"mapped",[11507]],[[11507,11507],"valid"],[[11508,11512],"disallowed"],[[11513,11519],"valid",[],"NV8"],[[11520,11557],"valid"],[[11558,11558],"disallowed"],[[11559,11559],"valid"],[[11560,11564],"disallowed"],[[11565,11565],"valid"],[[11566,11567],"disallowed"],[[11568,11621],"valid"],[[11622,11623],"valid"],[[11624,11630],"disallowed"],[[11631,11631],"mapped",[11617]],[[11632,11632],"valid",[],"NV8"],[[11633,11646],"disallowed"],[[11647,11647],"valid"],[[11648,11670],"valid"],[[11671,11679],"disallowed"],[[11680,11686],"valid"],[[11687,11687],"disallowed"],[[11688,11694],"valid"],[[11695,11695],"disallowed"],[[11696,11702],"valid"],[[11703,11703],"disallowed"],[[11704,11710],"valid"],[[11711,11711],"disallowed"],[[11712,11718],"valid"],[[11719,11719],"disallowed"],[[11720,11726],"valid"],[[11727,11727],"disallowed"],[[11728,11734],"valid"],[[11735,11735],"disallowed"],[[11736,11742],"valid"],[[11743,11743],"disallowed"],[[11744,11775],"valid"],[[11776,11799],"valid",[],"NV8"],[[11800,11803],"valid",[],"NV8"],[[11804,11805],"valid",[],"NV8"],[[11806,11822],"valid",[],"NV8"],[[11823,11823],"valid"],[[11824,11824],"valid",[],"NV8"],[[11825,11825],"valid",[],"NV8"],[[11826,11835],"valid",[],"NV8"],[[11836,11842],"valid",[],"NV8"],[[11843,11903],"disallowed"],[[11904,11929],"valid",[],"NV8"],[[11930,11930],"disallowed"],[[11931,11934],"valid",[],"NV8"],[[11935,11935],"mapped",[27597]],[[11936,12018],"valid",[],"NV8"],[[12019,12019],"mapped",[40863]],[[12020,12031],"disallowed"],[[12032,12032],"mapped",[19968]],[[12033,12033],"mapped",[20008]],[[12034,12034],"mapped",[20022]],[[12035,12035],"mapped",[20031]],[[12036,12036],"mapped",[20057]],[[12037,12037],"mapped",[20101]],[[12038,12038],"mapped",[20108]],[[12039,12039],"mapped",[20128]],[[12040,12040],"mapped",[20154]],[[12041,12041],"mapped",[20799]],[[12042,12042],"mapped",[20837]],[[12043,12043],"mapped",[20843]],[[12044,12044],"mapped",[20866]],[[12045,12045],"mapped",[20886]],[[12046,12046],"mapped",[20907]],[[12047,12047],"mapped",[20960]],[[12048,12048],"mapped",[20981]],[[12049,12049],"mapped",[20992]],[[12050,12050],"mapped",[21147]],[[12051,12051],"mapped",[21241]],[[12052,12052],"mapped",[21269]],[[12053,12053],"mapped",[21274]],[[12054,12054],"mapped",[21304]],[[12055,12055],"mapped",[21313]],[[12056,12056],"mapped",[21340]],[[12057,12057],"mapped",[21353]],[[12058,12058],"mapped",[21378]],[[12059,12059],"mapped",[21430]],[[12060,12060],"mapped",[21448]],[[12061,12061],"mapped",[21475]],[[12062,12062],"mapped",[22231]],[[12063,12063],"mapped",[22303]],[[12064,12064],"mapped",[22763]],[[12065,12065],"mapped",[22786]],[[12066,12066],"mapped",[22794]],[[12067,12067],"mapped",[22805]],[[12068,12068],"mapped",[22823]],[[12069,12069],"mapped",[22899]],[[12070,12070],"mapped",[23376]],[[12071,12071],"mapped",[23424]],[[12072,12072],"mapped",[23544]],[[12073,12073],"mapped",[23567]],[[12074,12074],"mapped",[23586]],[[12075,12075],"mapped",[23608]],[[12076,12076],"mapped",[23662]],[[12077,12077],"mapped",[23665]],[[12078,12078],"mapped",[24027]],[[12079,12079],"mapped",[24037]],[[12080,12080],"mapped",[24049]],[[12081,12081],"mapped",[24062]],[[12082,12082],"mapped",[24178]],[[12083,12083],"mapped",[24186]],[[12084,12084],"mapped",[24191]],[[12085,12085],"mapped",[24308]],[[12086,12086],"mapped",[24318]],[[12087,12087],"mapped",[24331]],[[12088,12088],"mapped",[24339]],[[12089,12089],"mapped",[24400]],[[12090,12090],"mapped",[24417]],[[12091,12091],"mapped",[24435]],[[12092,12092],"mapped",[24515]],[[12093,12093],"mapped",[25096]],[[12094,12094],"mapped",[25142]],[[12095,12095],"mapped",[25163]],[[12096,12096],"mapped",[25903]],[[12097,12097],"mapped",[25908]],[[12098,12098],"mapped",[25991]],[[12099,12099],"mapped",[26007]],[[12100,12100],"mapped",[26020]],[[12101,12101],"mapped",[26041]],[[12102,12102],"mapped",[26080]],[[12103,12103],"mapped",[26085]],[[12104,12104],"mapped",[26352]],[[12105,12105],"mapped",[26376]],[[12106,12106],"mapped",[26408]],[[12107,12107],"mapped",[27424]],[[12108,12108],"mapped",[27490]],[[12109,12109],"mapped",[27513]],[[12110,12110],"mapped",[27571]],[[12111,12111],"mapped",[27595]],[[12112,12112],"mapped",[27604]],[[12113,12113],"mapped",[27611]],[[12114,12114],"mapped",[27663]],[[12115,12115],"mapped",[27668]],[[12116,12116],"mapped",[27700]],[[12117,12117],"mapped",[28779]],[[12118,12118],"mapped",[29226]],[[12119,12119],"mapped",[29238]],[[12120,12120],"mapped",[29243]],[[12121,12121],"mapped",[29247]],[[12122,12122],"mapped",[29255]],[[12123,12123],"mapped",[29273]],[[12124,12124],"mapped",[29275]],[[12125,12125],"mapped",[29356]],[[12126,12126],"mapped",[29572]],[[12127,12127],"mapped",[29577]],[[12128,12128],"mapped",[29916]],[[12129,12129],"mapped",[29926]],[[12130,12130],"mapped",[29976]],[[12131,12131],"mapped",[29983]],[[12132,12132],"mapped",[29992]],[[12133,12133],"mapped",[30000]],[[12134,12134],"mapped",[30091]],[[12135,12135],"mapped",[30098]],[[12136,12136],"mapped",[30326]],[[12137,12137],"mapped",[30333]],[[12138,12138],"mapped",[30382]],[[12139,12139],"mapped",[30399]],[[12140,12140],"mapped",[30446]],[[12141,12141],"mapped",[30683]],[[12142,12142],"mapped",[30690]],[[12143,12143],"mapped",[30707]],[[12144,12144],"mapped",[31034]],[[12145,12145],"mapped",[31160]],[[12146,12146],"mapped",[31166]],[[12147,12147],"mapped",[31348]],[[12148,12148],"mapped",[31435]],[[12149,12149],"mapped",[31481]],[[12150,12150],"mapped",[31859]],[[12151,12151],"mapped",[31992]],[[12152,12152],"mapped",[32566]],[[12153,12153],"mapped",[32593]],[[12154,12154],"mapped",[32650]],[[12155,12155],"mapped",[32701]],[[12156,12156],"mapped",[32769]],[[12157,12157],"mapped",[32780]],[[12158,12158],"mapped",[32786]],[[12159,12159],"mapped",[32819]],[[12160,12160],"mapped",[32895]],[[12161,12161],"mapped",[32905]],[[12162,12162],"mapped",[33251]],[[12163,12163],"mapped",[33258]],[[12164,12164],"mapped",[33267]],[[12165,12165],"mapped",[33276]],[[12166,12166],"mapped",[33292]],[[12167,12167],"mapped",[33307]],[[12168,12168],"mapped",[33311]],[[12169,12169],"mapped",[33390]],[[12170,12170],"mapped",[33394]],[[12171,12171],"mapped",[33400]],[[12172,12172],"mapped",[34381]],[[12173,12173],"mapped",[34411]],[[12174,12174],"mapped",[34880]],[[12175,12175],"mapped",[34892]],[[12176,12176],"mapped",[34915]],[[12177,12177],"mapped",[35198]],[[12178,12178],"mapped",[35211]],[[12179,12179],"mapped",[35282]],[[12180,12180],"mapped",[35328]],[[12181,12181],"mapped",[35895]],[[12182,12182],"mapped",[35910]],[[12183,12183],"mapped",[35925]],[[12184,12184],"mapped",[35960]],[[12185,12185],"mapped",[35997]],[[12186,12186],"mapped",[36196]],[[12187,12187],"mapped",[36208]],[[12188,12188],"mapped",[36275]],[[12189,12189],"mapped",[36523]],[[12190,12190],"mapped",[36554]],[[12191,12191],"mapped",[36763]],[[12192,12192],"mapped",[36784]],[[12193,12193],"mapped",[36789]],[[12194,12194],"mapped",[37009]],[[12195,12195],"mapped",[37193]],[[12196,12196],"mapped",[37318]],[[12197,12197],"mapped",[37324]],[[12198,12198],"mapped",[37329]],[[12199,12199],"mapped",[38263]],[[12200,12200],"mapped",[38272]],[[12201,12201],"mapped",[38428]],[[12202,12202],"mapped",[38582]],[[12203,12203],"mapped",[38585]],[[12204,12204],"mapped",[38632]],[[12205,12205],"mapped",[38737]],[[12206,12206],"mapped",[38750]],[[12207,12207],"mapped",[38754]],[[12208,12208],"mapped",[38761]],[[12209,12209],"mapped",[38859]],[[12210,12210],"mapped",[38893]],[[12211,12211],"mapped",[38899]],[[12212,12212],"mapped",[38913]],[[12213,12213],"mapped",[39080]],[[12214,12214],"mapped",[39131]],[[12215,12215],"mapped",[39135]],[[12216,12216],"mapped",[39318]],[[12217,12217],"mapped",[39321]],[[12218,12218],"mapped",[39340]],[[12219,12219],"mapped",[39592]],[[12220,12220],"mapped",[39640]],[[12221,12221],"mapped",[39647]],[[12222,12222],"mapped",[39717]],[[12223,12223],"mapped",[39727]],[[12224,12224],"mapped",[39730]],[[12225,12225],"mapped",[39740]],[[12226,12226],"mapped",[39770]],[[12227,12227],"mapped",[40165]],[[12228,12228],"mapped",[40565]],[[12229,12229],"mapped",[40575]],[[12230,12230],"mapped",[40613]],[[12231,12231],"mapped",[40635]],[[12232,12232],"mapped",[40643]],[[12233,12233],"mapped",[40653]],[[12234,12234],"mapped",[40657]],[[12235,12235],"mapped",[40697]],[[12236,12236],"mapped",[40701]],[[12237,12237],"mapped",[40718]],[[12238,12238],"mapped",[40723]],[[12239,12239],"mapped",[40736]],[[12240,12240],"mapped",[40763]],[[12241,12241],"mapped",[40778]],[[12242,12242],"mapped",[40786]],[[12243,12243],"mapped",[40845]],[[12244,12244],"mapped",[40860]],[[12245,12245],"mapped",[40864]],[[12246,12271],"disallowed"],[[12272,12283],"disallowed"],[[12284,12287],"disallowed"],[[12288,12288],"disallowed_STD3_mapped",[32]],[[12289,12289],"valid",[],"NV8"],[[12290,12290],"mapped",[46]],[[12291,12292],"valid",[],"NV8"],[[12293,12295],"valid"],[[12296,12329],"valid",[],"NV8"],[[12330,12333],"valid"],[[12334,12341],"valid",[],"NV8"],[[12342,12342],"mapped",[12306]],[[12343,12343],"valid",[],"NV8"],[[12344,12344],"mapped",[21313]],[[12345,12345],"mapped",[21316]],[[12346,12346],"mapped",[21317]],[[12347,12347],"valid",[],"NV8"],[[12348,12348],"valid"],[[12349,12349],"valid",[],"NV8"],[[12350,12350],"valid",[],"NV8"],[[12351,12351],"valid",[],"NV8"],[[12352,12352],"disallowed"],[[12353,12436],"valid"],[[12437,12438],"valid"],[[12439,12440],"disallowed"],[[12441,12442],"valid"],[[12443,12443],"disallowed_STD3_mapped",[32,12441]],[[12444,12444],"disallowed_STD3_mapped",[32,12442]],[[12445,12446],"valid"],[[12447,12447],"mapped",[12424,12426]],[[12448,12448],"valid",[],"NV8"],[[12449,12542],"valid"],[[12543,12543],"mapped",[12467,12488]],[[12544,12548],"disallowed"],[[12549,12588],"valid"],[[12589,12589],"valid"],[[12590,12592],"disallowed"],[[12593,12593],"mapped",[4352]],[[12594,12594],"mapped",[4353]],[[12595,12595],"mapped",[4522]],[[12596,12596],"mapped",[4354]],[[12597,12597],"mapped",[4524]],[[12598,12598],"mapped",[4525]],[[12599,12599],"mapped",[4355]],[[12600,12600],"mapped",[4356]],[[12601,12601],"mapped",[4357]],[[12602,12602],"mapped",[4528]],[[12603,12603],"mapped",[4529]],[[12604,12604],"mapped",[4530]],[[12605,12605],"mapped",[4531]],[[12606,12606],"mapped",[4532]],[[12607,12607],"mapped",[4533]],[[12608,12608],"mapped",[4378]],[[12609,12609],"mapped",[4358]],[[12610,12610],"mapped",[4359]],[[12611,12611],"mapped",[4360]],[[12612,12612],"mapped",[4385]],[[12613,12613],"mapped",[4361]],[[12614,12614],"mapped",[4362]],[[12615,12615],"mapped",[4363]],[[12616,12616],"mapped",[4364]],[[12617,12617],"mapped",[4365]],[[12618,12618],"mapped",[4366]],[[12619,12619],"mapped",[4367]],[[12620,12620],"mapped",[4368]],[[12621,12621],"mapped",[4369]],[[12622,12622],"mapped",[4370]],[[12623,12623],"mapped",[4449]],[[12624,12624],"mapped",[4450]],[[12625,12625],"mapped",[4451]],[[12626,12626],"mapped",[4452]],[[12627,12627],"mapped",[4453]],[[12628,12628],"mapped",[4454]],[[12629,12629],"mapped",[4455]],[[12630,12630],"mapped",[4456]],[[12631,12631],"mapped",[4457]],[[12632,12632],"mapped",[4458]],[[12633,12633],"mapped",[4459]],[[12634,12634],"mapped",[4460]],[[12635,12635],"mapped",[4461]],[[12636,12636],"mapped",[4462]],[[12637,12637],"mapped",[4463]],[[12638,12638],"mapped",[4464]],[[12639,12639],"mapped",[4465]],[[12640,12640],"mapped",[4466]],[[12641,12641],"mapped",[4467]],[[12642,12642],"mapped",[4468]],[[12643,12643],"mapped",[4469]],[[12644,12644],"disallowed"],[[12645,12645],"mapped",[4372]],[[12646,12646],"mapped",[4373]],[[12647,12647],"mapped",[4551]],[[12648,12648],"mapped",[4552]],[[12649,12649],"mapped",[4556]],[[12650,12650],"mapped",[4558]],[[12651,12651],"mapped",[4563]],[[12652,12652],"mapped",[4567]],[[12653,12653],"mapped",[4569]],[[12654,12654],"mapped",[4380]],[[12655,12655],"mapped",[4573]],[[12656,12656],"mapped",[4575]],[[12657,12657],"mapped",[4381]],[[12658,12658],"mapped",[4382]],[[12659,12659],"mapped",[4384]],[[12660,12660],"mapped",[4386]],[[12661,12661],"mapped",[4387]],[[12662,12662],"mapped",[4391]],[[12663,12663],"mapped",[4393]],[[12664,12664],"mapped",[4395]],[[12665,12665],"mapped",[4396]],[[12666,12666],"mapped",[4397]],[[12667,12667],"mapped",[4398]],[[12668,12668],"mapped",[4399]],[[12669,12669],"mapped",[4402]],[[12670,12670],"mapped",[4406]],[[12671,12671],"mapped",[4416]],[[12672,12672],"mapped",[4423]],[[12673,12673],"mapped",[4428]],[[12674,12674],"mapped",[4593]],[[12675,12675],"mapped",[4594]],[[12676,12676],"mapped",[4439]],[[12677,12677],"mapped",[4440]],[[12678,12678],"mapped",[4441]],[[12679,12679],"mapped",[4484]],[[12680,12680],"mapped",[4485]],[[12681,12681],"mapped",[4488]],[[12682,12682],"mapped",[4497]],[[12683,12683],"mapped",[4498]],[[12684,12684],"mapped",[4500]],[[12685,12685],"mapped",[4510]],[[12686,12686],"mapped",[4513]],[[12687,12687],"disallowed"],[[12688,12689],"valid",[],"NV8"],[[12690,12690],"mapped",[19968]],[[12691,12691],"mapped",[20108]],[[12692,12692],"mapped",[19977]],[[12693,12693],"mapped",[22235]],[[12694,12694],"mapped",[19978]],[[12695,12695],"mapped",[20013]],[[12696,12696],"mapped",[19979]],[[12697,12697],"mapped",[30002]],[[12698,12698],"mapped",[20057]],[[12699,12699],"mapped",[19993]],[[12700,12700],"mapped",[19969]],[[12701,12701],"mapped",[22825]],[[12702,12702],"mapped",[22320]],[[12703,12703],"mapped",[20154]],[[12704,12727],"valid"],[[12728,12730],"valid"],[[12731,12735],"disallowed"],[[12736,12751],"valid",[],"NV8"],[[12752,12771],"valid",[],"NV8"],[[12772,12783],"disallowed"],[[12784,12799],"valid"],[[12800,12800],"disallowed_STD3_mapped",[40,4352,41]],[[12801,12801],"disallowed_STD3_mapped",[40,4354,41]],[[12802,12802],"disallowed_STD3_mapped",[40,4355,41]],[[12803,12803],"disallowed_STD3_mapped",[40,4357,41]],[[12804,12804],"disallowed_STD3_mapped",[40,4358,41]],[[12805,12805],"disallowed_STD3_mapped",[40,4359,41]],[[12806,12806],"disallowed_STD3_mapped",[40,4361,41]],[[12807,12807],"disallowed_STD3_mapped",[40,4363,41]],[[12808,12808],"disallowed_STD3_mapped",[40,4364,41]],[[12809,12809],"disallowed_STD3_mapped",[40,4366,41]],[[12810,12810],"disallowed_STD3_mapped",[40,4367,41]],[[12811,12811],"disallowed_STD3_mapped",[40,4368,41]],[[12812,12812],"disallowed_STD3_mapped",[40,4369,41]],[[12813,12813],"disallowed_STD3_mapped",[40,4370,41]],[[12814,12814],"disallowed_STD3_mapped",[40,44032,41]],[[12815,12815],"disallowed_STD3_mapped",[40,45208,41]],[[12816,12816],"disallowed_STD3_mapped",[40,45796,41]],[[12817,12817],"disallowed_STD3_mapped",[40,46972,41]],[[12818,12818],"disallowed_STD3_mapped",[40,47560,41]],[[12819,12819],"disallowed_STD3_mapped",[40,48148,41]],[[12820,12820],"disallowed_STD3_mapped",[40,49324,41]],[[12821,12821],"disallowed_STD3_mapped",[40,50500,41]],[[12822,12822],"disallowed_STD3_mapped",[40,51088,41]],[[12823,12823],"disallowed_STD3_mapped",[40,52264,41]],[[12824,12824],"disallowed_STD3_mapped",[40,52852,41]],[[12825,12825],"disallowed_STD3_mapped",[40,53440,41]],[[12826,12826],"disallowed_STD3_mapped",[40,54028,41]],[[12827,12827],"disallowed_STD3_mapped",[40,54616,41]],[[12828,12828],"disallowed_STD3_mapped",[40,51452,41]],[[12829,12829],"disallowed_STD3_mapped",[40,50724,51204,41]],[[12830,12830],"disallowed_STD3_mapped",[40,50724,54980,41]],[[12831,12831],"disallowed"],[[12832,12832],"disallowed_STD3_mapped",[40,19968,41]],[[12833,12833],"disallowed_STD3_mapped",[40,20108,41]],[[12834,12834],"disallowed_STD3_mapped",[40,19977,41]],[[12835,12835],"disallowed_STD3_mapped",[40,22235,41]],[[12836,12836],"disallowed_STD3_mapped",[40,20116,41]],[[12837,12837],"disallowed_STD3_mapped",[40,20845,41]],[[12838,12838],"disallowed_STD3_mapped",[40,19971,41]],[[12839,12839],"disallowed_STD3_mapped",[40,20843,41]],[[12840,12840],"disallowed_STD3_mapped",[40,20061,41]],[[12841,12841],"disallowed_STD3_mapped",[40,21313,41]],[[12842,12842],"disallowed_STD3_mapped",[40,26376,41]],[[12843,12843],"disallowed_STD3_mapped",[40,28779,41]],[[12844,12844],"disallowed_STD3_mapped",[40,27700,41]],[[12845,12845],"disallowed_STD3_mapped",[40,26408,41]],[[12846,12846],"disallowed_STD3_mapped",[40,37329,41]],[[12847,12847],"disallowed_STD3_mapped",[40,22303,41]],[[12848,12848],"disallowed_STD3_mapped",[40,26085,41]],[[12849,12849],"disallowed_STD3_mapped",[40,26666,41]],[[12850,12850],"disallowed_STD3_mapped",[40,26377,41]],[[12851,12851],"disallowed_STD3_mapped",[40,31038,41]],[[12852,12852],"disallowed_STD3_mapped",[40,21517,41]],[[12853,12853],"disallowed_STD3_mapped",[40,29305,41]],[[12854,12854],"disallowed_STD3_mapped",[40,36001,41]],[[12855,12855],"disallowed_STD3_mapped",[40,31069,41]],[[12856,12856],"disallowed_STD3_mapped",[40,21172,41]],[[12857,12857],"disallowed_STD3_mapped",[40,20195,41]],[[12858,12858],"disallowed_STD3_mapped",[40,21628,41]],[[12859,12859],"disallowed_STD3_mapped",[40,23398,41]],[[12860,12860],"disallowed_STD3_mapped",[40,30435,41]],[[12861,12861],"disallowed_STD3_mapped",[40,20225,41]],[[12862,12862],"disallowed_STD3_mapped",[40,36039,41]],[[12863,12863],"disallowed_STD3_mapped",[40,21332,41]],[[12864,12864],"disallowed_STD3_mapped",[40,31085,41]],[[12865,12865],"disallowed_STD3_mapped",[40,20241,41]],[[12866,12866],"disallowed_STD3_mapped",[40,33258,41]],[[12867,12867],"disallowed_STD3_mapped",[40,33267,41]],[[12868,12868],"mapped",[21839]],[[12869,12869],"mapped",[24188]],[[12870,12870],"mapped",[25991]],[[12871,12871],"mapped",[31631]],[[12872,12879],"valid",[],"NV8"],[[12880,12880],"mapped",[112,116,101]],[[12881,12881],"mapped",[50,49]],[[12882,12882],"mapped",[50,50]],[[12883,12883],"mapped",[50,51]],[[12884,12884],"mapped",[50,52]],[[12885,12885],"mapped",[50,53]],[[12886,12886],"mapped",[50,54]],[[12887,12887],"mapped",[50,55]],[[12888,12888],"mapped",[50,56]],[[12889,12889],"mapped",[50,57]],[[12890,12890],"mapped",[51,48]],[[12891,12891],"mapped",[51,49]],[[12892,12892],"mapped",[51,50]],[[12893,12893],"mapped",[51,51]],[[12894,12894],"mapped",[51,52]],[[12895,12895],"mapped",[51,53]],[[12896,12896],"mapped",[4352]],[[12897,12897],"mapped",[4354]],[[12898,12898],"mapped",[4355]],[[12899,12899],"mapped",[4357]],[[12900,12900],"mapped",[4358]],[[12901,12901],"mapped",[4359]],[[12902,12902],"mapped",[4361]],[[12903,12903],"mapped",[4363]],[[12904,12904],"mapped",[4364]],[[12905,12905],"mapped",[4366]],[[12906,12906],"mapped",[4367]],[[12907,12907],"mapped",[4368]],[[12908,12908],"mapped",[4369]],[[12909,12909],"mapped",[4370]],[[12910,12910],"mapped",[44032]],[[12911,12911],"mapped",[45208]],[[12912,12912],"mapped",[45796]],[[12913,12913],"mapped",[46972]],[[12914,12914],"mapped",[47560]],[[12915,12915],"mapped",[48148]],[[12916,12916],"mapped",[49324]],[[12917,12917],"mapped",[50500]],[[12918,12918],"mapped",[51088]],[[12919,12919],"mapped",[52264]],[[12920,12920],"mapped",[52852]],[[12921,12921],"mapped",[53440]],[[12922,12922],"mapped",[54028]],[[12923,12923],"mapped",[54616]],[[12924,12924],"mapped",[52280,44256]],[[12925,12925],"mapped",[51452,51032]],[[12926,12926],"mapped",[50864]],[[12927,12927],"valid",[],"NV8"],[[12928,12928],"mapped",[19968]],[[12929,12929],"mapped",[20108]],[[12930,12930],"mapped",[19977]],[[12931,12931],"mapped",[22235]],[[12932,12932],"mapped",[20116]],[[12933,12933],"mapped",[20845]],[[12934,12934],"mapped",[19971]],[[12935,12935],"mapped",[20843]],[[12936,12936],"mapped",[20061]],[[12937,12937],"mapped",[21313]],[[12938,12938],"mapped",[26376]],[[12939,12939],"mapped",[28779]],[[12940,12940],"mapped",[27700]],[[12941,12941],"mapped",[26408]],[[12942,12942],"mapped",[37329]],[[12943,12943],"mapped",[22303]],[[12944,12944],"mapped",[26085]],[[12945,12945],"mapped",[26666]],[[12946,12946],"mapped",[26377]],[[12947,12947],"mapped",[31038]],[[12948,12948],"mapped",[21517]],[[12949,12949],"mapped",[29305]],[[12950,12950],"mapped",[36001]],[[12951,12951],"mapped",[31069]],[[12952,12952],"mapped",[21172]],[[12953,12953],"mapped",[31192]],[[12954,12954],"mapped",[30007]],[[12955,12955],"mapped",[22899]],[[12956,12956],"mapped",[36969]],[[12957,12957],"mapped",[20778]],[[12958,12958],"mapped",[21360]],[[12959,12959],"mapped",[27880]],[[12960,12960],"mapped",[38917]],[[12961,12961],"mapped",[20241]],[[12962,12962],"mapped",[20889]],[[12963,12963],"mapped",[27491]],[[12964,12964],"mapped",[19978]],[[12965,12965],"mapped",[20013]],[[12966,12966],"mapped",[19979]],[[12967,12967],"mapped",[24038]],[[12968,12968],"mapped",[21491]],[[12969,12969],"mapped",[21307]],[[12970,12970],"mapped",[23447]],[[12971,12971],"mapped",[23398]],[[12972,12972],"mapped",[30435]],[[12973,12973],"mapped",[20225]],[[12974,12974],"mapped",[36039]],[[12975,12975],"mapped",[21332]],[[12976,12976],"mapped",[22812]],[[12977,12977],"mapped",[51,54]],[[12978,12978],"mapped",[51,55]],[[12979,12979],"mapped",[51,56]],[[12980,12980],"mapped",[51,57]],[[12981,12981],"mapped",[52,48]],[[12982,12982],"mapped",[52,49]],[[12983,12983],"mapped",[52,50]],[[12984,12984],"mapped",[52,51]],[[12985,12985],"mapped",[52,52]],[[12986,12986],"mapped",[52,53]],[[12987,12987],"mapped",[52,54]],[[12988,12988],"mapped",[52,55]],[[12989,12989],"mapped",[52,56]],[[12990,12990],"mapped",[52,57]],[[12991,12991],"mapped",[53,48]],[[12992,12992],"mapped",[49,26376]],[[12993,12993],"mapped",[50,26376]],[[12994,12994],"mapped",[51,26376]],[[12995,12995],"mapped",[52,26376]],[[12996,12996],"mapped",[53,26376]],[[12997,12997],"mapped",[54,26376]],[[12998,12998],"mapped",[55,26376]],[[12999,12999],"mapped",[56,26376]],[[13000,13000],"mapped",[57,26376]],[[13001,13001],"mapped",[49,48,26376]],[[13002,13002],"mapped",[49,49,26376]],[[13003,13003],"mapped",[49,50,26376]],[[13004,13004],"mapped",[104,103]],[[13005,13005],"mapped",[101,114,103]],[[13006,13006],"mapped",[101,118]],[[13007,13007],"mapped",[108,116,100]],[[13008,13008],"mapped",[12450]],[[13009,13009],"mapped",[12452]],[[13010,13010],"mapped",[12454]],[[13011,13011],"mapped",[12456]],[[13012,13012],"mapped",[12458]],[[13013,13013],"mapped",[12459]],[[13014,13014],"mapped",[12461]],[[13015,13015],"mapped",[12463]],[[13016,13016],"mapped",[12465]],[[13017,13017],"mapped",[12467]],[[13018,13018],"mapped",[12469]],[[13019,13019],"mapped",[12471]],[[13020,13020],"mapped",[12473]],[[13021,13021],"mapped",[12475]],[[13022,13022],"mapped",[12477]],[[13023,13023],"mapped",[12479]],[[13024,13024],"mapped",[12481]],[[13025,13025],"mapped",[12484]],[[13026,13026],"mapped",[12486]],[[13027,13027],"mapped",[12488]],[[13028,13028],"mapped",[12490]],[[13029,13029],"mapped",[12491]],[[13030,13030],"mapped",[12492]],[[13031,13031],"mapped",[12493]],[[13032,13032],"mapped",[12494]],[[13033,13033],"mapped",[12495]],[[13034,13034],"mapped",[12498]],[[13035,13035],"mapped",[12501]],[[13036,13036],"mapped",[12504]],[[13037,13037],"mapped",[12507]],[[13038,13038],"mapped",[12510]],[[13039,13039],"mapped",[12511]],[[13040,13040],"mapped",[12512]],[[13041,13041],"mapped",[12513]],[[13042,13042],"mapped",[12514]],[[13043,13043],"mapped",[12516]],[[13044,13044],"mapped",[12518]],[[13045,13045],"mapped",[12520]],[[13046,13046],"mapped",[12521]],[[13047,13047],"mapped",[12522]],[[13048,13048],"mapped",[12523]],[[13049,13049],"mapped",[12524]],[[13050,13050],"mapped",[12525]],[[13051,13051],"mapped",[12527]],[[13052,13052],"mapped",[12528]],[[13053,13053],"mapped",[12529]],[[13054,13054],"mapped",[12530]],[[13055,13055],"disallowed"],[[13056,13056],"mapped",[12450,12497,12540,12488]],[[13057,13057],"mapped",[12450,12523,12501,12449]],[[13058,13058],"mapped",[12450,12531,12506,12450]],[[13059,13059],"mapped",[12450,12540,12523]],[[13060,13060],"mapped",[12452,12491,12531,12464]],[[13061,13061],"mapped",[12452,12531,12481]],[[13062,13062],"mapped",[12454,12457,12531]],[[13063,13063],"mapped",[12456,12473,12463,12540,12489]],[[13064,13064],"mapped",[12456,12540,12459,12540]],[[13065,13065],"mapped",[12458,12531,12473]],[[13066,13066],"mapped",[12458,12540,12512]],[[13067,13067],"mapped",[12459,12452,12522]],[[13068,13068],"mapped",[12459,12521,12483,12488]],[[13069,13069],"mapped",[12459,12525,12522,12540]],[[13070,13070],"mapped",[12460,12525,12531]],[[13071,13071],"mapped",[12460,12531,12510]],[[13072,13072],"mapped",[12462,12460]],[[13073,13073],"mapped",[12462,12491,12540]],[[13074,13074],"mapped",[12461,12517,12522,12540]],[[13075,13075],"mapped",[12462,12523,12480,12540]],[[13076,13076],"mapped",[12461,12525]],[[13077,13077],"mapped",[12461,12525,12464,12521,12512]],[[13078,13078],"mapped",[12461,12525,12513,12540,12488,12523]],[[13079,13079],"mapped",[12461,12525,12527,12483,12488]],[[13080,13080],"mapped",[12464,12521,12512]],[[13081,13081],"mapped",[12464,12521,12512,12488,12531]],[[13082,13082],"mapped",[12463,12523,12476,12452,12525]],[[13083,13083],"mapped",[12463,12525,12540,12493]],[[13084,13084],"mapped",[12465,12540,12473]],[[13085,13085],"mapped",[12467,12523,12490]],[[13086,13086],"mapped",[12467,12540,12509]],[[13087,13087],"mapped",[12469,12452,12463,12523]],[[13088,13088],"mapped",[12469,12531,12481,12540,12512]],[[13089,13089],"mapped",[12471,12522,12531,12464]],[[13090,13090],"mapped",[12475,12531,12481]],[[13091,13091],"mapped",[12475,12531,12488]],[[13092,13092],"mapped",[12480,12540,12473]],[[13093,13093],"mapped",[12487,12471]],[[13094,13094],"mapped",[12489,12523]],[[13095,13095],"mapped",[12488,12531]],[[13096,13096],"mapped",[12490,12494]],[[13097,13097],"mapped",[12494,12483,12488]],[[13098,13098],"mapped",[12495,12452,12484]],[[13099,13099],"mapped",[12497,12540,12475,12531,12488]],[[13100,13100],"mapped",[12497,12540,12484]],[[13101,13101],"mapped",[12496,12540,12524,12523]],[[13102,13102],"mapped",[12500,12450,12473,12488,12523]],[[13103,13103],"mapped",[12500,12463,12523]],[[13104,13104],"mapped",[12500,12467]],[[13105,13105],"mapped",[12499,12523]],[[13106,13106],"mapped",[12501,12449,12521,12483,12489]],[[13107,13107],"mapped",[12501,12451,12540,12488]],[[13108,13108],"mapped",[12502,12483,12471,12455,12523]],[[13109,13109],"mapped",[12501,12521,12531]],[[13110,13110],"mapped",[12504,12463,12479,12540,12523]],[[13111,13111],"mapped",[12506,12477]],[[13112,13112],"mapped",[12506,12491,12498]],[[13113,13113],"mapped",[12504,12523,12484]],[[13114,13114],"mapped",[12506,12531,12473]],[[13115,13115],"mapped",[12506,12540,12472]],[[13116,13116],"mapped",[12505,12540,12479]],[[13117,13117],"mapped",[12509,12452,12531,12488]],[[13118,13118],"mapped",[12508,12523,12488]],[[13119,13119],"mapped",[12507,12531]],[[13120,13120],"mapped",[12509,12531,12489]],[[13121,13121],"mapped",[12507,12540,12523]],[[13122,13122],"mapped",[12507,12540,12531]],[[13123,13123],"mapped",[12510,12452,12463,12525]],[[13124,13124],"mapped",[12510,12452,12523]],[[13125,13125],"mapped",[12510,12483,12495]],[[13126,13126],"mapped",[12510,12523,12463]],[[13127,13127],"mapped",[12510,12531,12471,12519,12531]],[[13128,13128],"mapped",[12511,12463,12525,12531]],[[13129,13129],"mapped",[12511,12522]],[[13130,13130],"mapped",[12511,12522,12496,12540,12523]],[[13131,13131],"mapped",[12513,12460]],[[13132,13132],"mapped",[12513,12460,12488,12531]],[[13133,13133],"mapped",[12513,12540,12488,12523]],[[13134,13134],"mapped",[12516,12540,12489]],[[13135,13135],"mapped",[12516,12540,12523]],[[13136,13136],"mapped",[12518,12450,12531]],[[13137,13137],"mapped",[12522,12483,12488,12523]],[[13138,13138],"mapped",[12522,12521]],[[13139,13139],"mapped",[12523,12500,12540]],[[13140,13140],"mapped",[12523,12540,12502,12523]],[[13141,13141],"mapped",[12524,12512]],[[13142,13142],"mapped",[12524,12531,12488,12466,12531]],[[13143,13143],"mapped",[12527,12483,12488]],[[13144,13144],"mapped",[48,28857]],[[13145,13145],"mapped",[49,28857]],[[13146,13146],"mapped",[50,28857]],[[13147,13147],"mapped",[51,28857]],[[13148,13148],"mapped",[52,28857]],[[13149,13149],"mapped",[53,28857]],[[13150,13150],"mapped",[54,28857]],[[13151,13151],"mapped",[55,28857]],[[13152,13152],"mapped",[56,28857]],[[13153,13153],"mapped",[57,28857]],[[13154,13154],"mapped",[49,48,28857]],[[13155,13155],"mapped",[49,49,28857]],[[13156,13156],"mapped",[49,50,28857]],[[13157,13157],"mapped",[49,51,28857]],[[13158,13158],"mapped",[49,52,28857]],[[13159,13159],"mapped",[49,53,28857]],[[13160,13160],"mapped",[49,54,28857]],[[13161,13161],"mapped",[49,55,28857]],[[13162,13162],"mapped",[49,56,28857]],[[13163,13163],"mapped",[49,57,28857]],[[13164,13164],"mapped",[50,48,28857]],[[13165,13165],"mapped",[50,49,28857]],[[13166,13166],"mapped",[50,50,28857]],[[13167,13167],"mapped",[50,51,28857]],[[13168,13168],"mapped",[50,52,28857]],[[13169,13169],"mapped",[104,112,97]],[[13170,13170],"mapped",[100,97]],[[13171,13171],"mapped",[97,117]],[[13172,13172],"mapped",[98,97,114]],[[13173,13173],"mapped",[111,118]],[[13174,13174],"mapped",[112,99]],[[13175,13175],"mapped",[100,109]],[[13176,13176],"mapped",[100,109,50]],[[13177,13177],"mapped",[100,109,51]],[[13178,13178],"mapped",[105,117]],[[13179,13179],"mapped",[24179,25104]],[[13180,13180],"mapped",[26157,21644]],[[13181,13181],"mapped",[22823,27491]],[[13182,13182],"mapped",[26126,27835]],[[13183,13183],"mapped",[26666,24335,20250,31038]],[[13184,13184],"mapped",[112,97]],[[13185,13185],"mapped",[110,97]],[[13186,13186],"mapped",[956,97]],[[13187,13187],"mapped",[109,97]],[[13188,13188],"mapped",[107,97]],[[13189,13189],"mapped",[107,98]],[[13190,13190],"mapped",[109,98]],[[13191,13191],"mapped",[103,98]],[[13192,13192],"mapped",[99,97,108]],[[13193,13193],"mapped",[107,99,97,108]],[[13194,13194],"mapped",[112,102]],[[13195,13195],"mapped",[110,102]],[[13196,13196],"mapped",[956,102]],[[13197,13197],"mapped",[956,103]],[[13198,13198],"mapped",[109,103]],[[13199,13199],"mapped",[107,103]],[[13200,13200],"mapped",[104,122]],[[13201,13201],"mapped",[107,104,122]],[[13202,13202],"mapped",[109,104,122]],[[13203,13203],"mapped",[103,104,122]],[[13204,13204],"mapped",[116,104,122]],[[13205,13205],"mapped",[956,108]],[[13206,13206],"mapped",[109,108]],[[13207,13207],"mapped",[100,108]],[[13208,13208],"mapped",[107,108]],[[13209,13209],"mapped",[102,109]],[[13210,13210],"mapped",[110,109]],[[13211,13211],"mapped",[956,109]],[[13212,13212],"mapped",[109,109]],[[13213,13213],"mapped",[99,109]],[[13214,13214],"mapped",[107,109]],[[13215,13215],"mapped",[109,109,50]],[[13216,13216],"mapped",[99,109,50]],[[13217,13217],"mapped",[109,50]],[[13218,13218],"mapped",[107,109,50]],[[13219,13219],"mapped",[109,109,51]],[[13220,13220],"mapped",[99,109,51]],[[13221,13221],"mapped",[109,51]],[[13222,13222],"mapped",[107,109,51]],[[13223,13223],"mapped",[109,8725,115]],[[13224,13224],"mapped",[109,8725,115,50]],[[13225,13225],"mapped",[112,97]],[[13226,13226],"mapped",[107,112,97]],[[13227,13227],"mapped",[109,112,97]],[[13228,13228],"mapped",[103,112,97]],[[13229,13229],"mapped",[114,97,100]],[[13230,13230],"mapped",[114,97,100,8725,115]],[[13231,13231],"mapped",[114,97,100,8725,115,50]],[[13232,13232],"mapped",[112,115]],[[13233,13233],"mapped",[110,115]],[[13234,13234],"mapped",[956,115]],[[13235,13235],"mapped",[109,115]],[[13236,13236],"mapped",[112,118]],[[13237,13237],"mapped",[110,118]],[[13238,13238],"mapped",[956,118]],[[13239,13239],"mapped",[109,118]],[[13240,13240],"mapped",[107,118]],[[13241,13241],"mapped",[109,118]],[[13242,13242],"mapped",[112,119]],[[13243,13243],"mapped",[110,119]],[[13244,13244],"mapped",[956,119]],[[13245,13245],"mapped",[109,119]],[[13246,13246],"mapped",[107,119]],[[13247,13247],"mapped",[109,119]],[[13248,13248],"mapped",[107,969]],[[13249,13249],"mapped",[109,969]],[[13250,13250],"disallowed"],[[13251,13251],"mapped",[98,113]],[[13252,13252],"mapped",[99,99]],[[13253,13253],"mapped",[99,100]],[[13254,13254],"mapped",[99,8725,107,103]],[[13255,13255],"disallowed"],[[13256,13256],"mapped",[100,98]],[[13257,13257],"mapped",[103,121]],[[13258,13258],"mapped",[104,97]],[[13259,13259],"mapped",[104,112]],[[13260,13260],"mapped",[105,110]],[[13261,13261],"mapped",[107,107]],[[13262,13262],"mapped",[107,109]],[[13263,13263],"mapped",[107,116]],[[13264,13264],"mapped",[108,109]],[[13265,13265],"mapped",[108,110]],[[13266,13266],"mapped",[108,111,103]],[[13267,13267],"mapped",[108,120]],[[13268,13268],"mapped",[109,98]],[[13269,13269],"mapped",[109,105,108]],[[13270,13270],"mapped",[109,111,108]],[[13271,13271],"mapped",[112,104]],[[13272,13272],"disallowed"],[[13273,13273],"mapped",[112,112,109]],[[13274,13274],"mapped",[112,114]],[[13275,13275],"mapped",[115,114]],[[13276,13276],"mapped",[115,118]],[[13277,13277],"mapped",[119,98]],[[13278,13278],"mapped",[118,8725,109]],[[13279,13279],"mapped",[97,8725,109]],[[13280,13280],"mapped",[49,26085]],[[13281,13281],"mapped",[50,26085]],[[13282,13282],"mapped",[51,26085]],[[13283,13283],"mapped",[52,26085]],[[13284,13284],"mapped",[53,26085]],[[13285,13285],"mapped",[54,26085]],[[13286,13286],"mapped",[55,26085]],[[13287,13287],"mapped",[56,26085]],[[13288,13288],"mapped",[57,26085]],[[13289,13289],"mapped",[49,48,26085]],[[13290,13290],"mapped",[49,49,26085]],[[13291,13291],"mapped",[49,50,26085]],[[13292,13292],"mapped",[49,51,26085]],[[13293,13293],"mapped",[49,52,26085]],[[13294,13294],"mapped",[49,53,26085]],[[13295,13295],"mapped",[49,54,26085]],[[13296,13296],"mapped",[49,55,26085]],[[13297,13297],"mapped",[49,56,26085]],[[13298,13298],"mapped",[49,57,26085]],[[13299,13299],"mapped",[50,48,26085]],[[13300,13300],"mapped",[50,49,26085]],[[13301,13301],"mapped",[50,50,26085]],[[13302,13302],"mapped",[50,51,26085]],[[13303,13303],"mapped",[50,52,26085]],[[13304,13304],"mapped",[50,53,26085]],[[13305,13305],"mapped",[50,54,26085]],[[13306,13306],"mapped",[50,55,26085]],[[13307,13307],"mapped",[50,56,26085]],[[13308,13308],"mapped",[50,57,26085]],[[13309,13309],"mapped",[51,48,26085]],[[13310,13310],"mapped",[51,49,26085]],[[13311,13311],"mapped",[103,97,108]],[[13312,19893],"valid"],[[19894,19903],"disallowed"],[[19904,19967],"valid",[],"NV8"],[[19968,40869],"valid"],[[40870,40891],"valid"],[[40892,40899],"valid"],[[40900,40907],"valid"],[[40908,40908],"valid"],[[40909,40917],"valid"],[[40918,40959],"disallowed"],[[40960,42124],"valid"],[[42125,42127],"disallowed"],[[42128,42145],"valid",[],"NV8"],[[42146,42147],"valid",[],"NV8"],[[42148,42163],"valid",[],"NV8"],[[42164,42164],"valid",[],"NV8"],[[42165,42176],"valid",[],"NV8"],[[42177,42177],"valid",[],"NV8"],[[42178,42180],"valid",[],"NV8"],[[42181,42181],"valid",[],"NV8"],[[42182,42182],"valid",[],"NV8"],[[42183,42191],"disallowed"],[[42192,42237],"valid"],[[42238,42239],"valid",[],"NV8"],[[42240,42508],"valid"],[[42509,42511],"valid",[],"NV8"],[[42512,42539],"valid"],[[42540,42559],"disallowed"],[[42560,42560],"mapped",[42561]],[[42561,42561],"valid"],[[42562,42562],"mapped",[42563]],[[42563,42563],"valid"],[[42564,42564],"mapped",[42565]],[[42565,42565],"valid"],[[42566,42566],"mapped",[42567]],[[42567,42567],"valid"],[[42568,42568],"mapped",[42569]],[[42569,42569],"valid"],[[42570,42570],"mapped",[42571]],[[42571,42571],"valid"],[[42572,42572],"mapped",[42573]],[[42573,42573],"valid"],[[42574,42574],"mapped",[42575]],[[42575,42575],"valid"],[[42576,42576],"mapped",[42577]],[[42577,42577],"valid"],[[42578,42578],"mapped",[42579]],[[42579,42579],"valid"],[[42580,42580],"mapped",[42581]],[[42581,42581],"valid"],[[42582,42582],"mapped",[42583]],[[42583,42583],"valid"],[[42584,42584],"mapped",[42585]],[[42585,42585],"valid"],[[42586,42586],"mapped",[42587]],[[42587,42587],"valid"],[[42588,42588],"mapped",[42589]],[[42589,42589],"valid"],[[42590,42590],"mapped",[42591]],[[42591,42591],"valid"],[[42592,42592],"mapped",[42593]],[[42593,42593],"valid"],[[42594,42594],"mapped",[42595]],[[42595,42595],"valid"],[[42596,42596],"mapped",[42597]],[[42597,42597],"valid"],[[42598,42598],"mapped",[42599]],[[42599,42599],"valid"],[[42600,42600],"mapped",[42601]],[[42601,42601],"valid"],[[42602,42602],"mapped",[42603]],[[42603,42603],"valid"],[[42604,42604],"mapped",[42605]],[[42605,42607],"valid"],[[42608,42611],"valid",[],"NV8"],[[42612,42619],"valid"],[[42620,42621],"valid"],[[42622,42622],"valid",[],"NV8"],[[42623,42623],"valid"],[[42624,42624],"mapped",[42625]],[[42625,42625],"valid"],[[42626,42626],"mapped",[42627]],[[42627,42627],"valid"],[[42628,42628],"mapped",[42629]],[[42629,42629],"valid"],[[42630,42630],"mapped",[42631]],[[42631,42631],"valid"],[[42632,42632],"mapped",[42633]],[[42633,42633],"valid"],[[42634,42634],"mapped",[42635]],[[42635,42635],"valid"],[[42636,42636],"mapped",[42637]],[[42637,42637],"valid"],[[42638,42638],"mapped",[42639]],[[42639,42639],"valid"],[[42640,42640],"mapped",[42641]],[[42641,42641],"valid"],[[42642,42642],"mapped",[42643]],[[42643,42643],"valid"],[[42644,42644],"mapped",[42645]],[[42645,42645],"valid"],[[42646,42646],"mapped",[42647]],[[42647,42647],"valid"],[[42648,42648],"mapped",[42649]],[[42649,42649],"valid"],[[42650,42650],"mapped",[42651]],[[42651,42651],"valid"],[[42652,42652],"mapped",[1098]],[[42653,42653],"mapped",[1100]],[[42654,42654],"valid"],[[42655,42655],"valid"],[[42656,42725],"valid"],[[42726,42735],"valid",[],"NV8"],[[42736,42737],"valid"],[[42738,42743],"valid",[],"NV8"],[[42744,42751],"disallowed"],[[42752,42774],"valid",[],"NV8"],[[42775,42778],"valid"],[[42779,42783],"valid"],[[42784,42785],"valid",[],"NV8"],[[42786,42786],"mapped",[42787]],[[42787,42787],"valid"],[[42788,42788],"mapped",[42789]],[[42789,42789],"valid"],[[42790,42790],"mapped",[42791]],[[42791,42791],"valid"],[[42792,42792],"mapped",[42793]],[[42793,42793],"valid"],[[42794,42794],"mapped",[42795]],[[42795,42795],"valid"],[[42796,42796],"mapped",[42797]],[[42797,42797],"valid"],[[42798,42798],"mapped",[42799]],[[42799,42801],"valid"],[[42802,42802],"mapped",[42803]],[[42803,42803],"valid"],[[42804,42804],"mapped",[42805]],[[42805,42805],"valid"],[[42806,42806],"mapped",[42807]],[[42807,42807],"valid"],[[42808,42808],"mapped",[42809]],[[42809,42809],"valid"],[[42810,42810],"mapped",[42811]],[[42811,42811],"valid"],[[42812,42812],"mapped",[42813]],[[42813,42813],"valid"],[[42814,42814],"mapped",[42815]],[[42815,42815],"valid"],[[42816,42816],"mapped",[42817]],[[42817,42817],"valid"],[[42818,42818],"mapped",[42819]],[[42819,42819],"valid"],[[42820,42820],"mapped",[42821]],[[42821,42821],"valid"],[[42822,42822],"mapped",[42823]],[[42823,42823],"valid"],[[42824,42824],"mapped",[42825]],[[42825,42825],"valid"],[[42826,42826],"mapped",[42827]],[[42827,42827],"valid"],[[42828,42828],"mapped",[42829]],[[42829,42829],"valid"],[[42830,42830],"mapped",[42831]],[[42831,42831],"valid"],[[42832,42832],"mapped",[42833]],[[42833,42833],"valid"],[[42834,42834],"mapped",[42835]],[[42835,42835],"valid"],[[42836,42836],"mapped",[42837]],[[42837,42837],"valid"],[[42838,42838],"mapped",[42839]],[[42839,42839],"valid"],[[42840,42840],"mapped",[42841]],[[42841,42841],"valid"],[[42842,42842],"mapped",[42843]],[[42843,42843],"valid"],[[42844,42844],"mapped",[42845]],[[42845,42845],"valid"],[[42846,42846],"mapped",[42847]],[[42847,42847],"valid"],[[42848,42848],"mapped",[42849]],[[42849,42849],"valid"],[[42850,42850],"mapped",[42851]],[[42851,42851],"valid"],[[42852,42852],"mapped",[42853]],[[42853,42853],"valid"],[[42854,42854],"mapped",[42855]],[[42855,42855],"valid"],[[42856,42856],"mapped",[42857]],[[42857,42857],"valid"],[[42858,42858],"mapped",[42859]],[[42859,42859],"valid"],[[42860,42860],"mapped",[42861]],[[42861,42861],"valid"],[[42862,42862],"mapped",[42863]],[[42863,42863],"valid"],[[42864,42864],"mapped",[42863]],[[42865,42872],"valid"],[[42873,42873],"mapped",[42874]],[[42874,42874],"valid"],[[42875,42875],"mapped",[42876]],[[42876,42876],"valid"],[[42877,42877],"mapped",[7545]],[[42878,42878],"mapped",[42879]],[[42879,42879],"valid"],[[42880,42880],"mapped",[42881]],[[42881,42881],"valid"],[[42882,42882],"mapped",[42883]],[[42883,42883],"valid"],[[42884,42884],"mapped",[42885]],[[42885,42885],"valid"],[[42886,42886],"mapped",[42887]],[[42887,42888],"valid"],[[42889,42890],"valid",[],"NV8"],[[42891,42891],"mapped",[42892]],[[42892,42892],"valid"],[[42893,42893],"mapped",[613]],[[42894,42894],"valid"],[[42895,42895],"valid"],[[42896,42896],"mapped",[42897]],[[42897,42897],"valid"],[[42898,42898],"mapped",[42899]],[[42899,42899],"valid"],[[42900,42901],"valid"],[[42902,42902],"mapped",[42903]],[[42903,42903],"valid"],[[42904,42904],"mapped",[42905]],[[42905,42905],"valid"],[[42906,42906],"mapped",[42907]],[[42907,42907],"valid"],[[42908,42908],"mapped",[42909]],[[42909,42909],"valid"],[[42910,42910],"mapped",[42911]],[[42911,42911],"valid"],[[42912,42912],"mapped",[42913]],[[42913,42913],"valid"],[[42914,42914],"mapped",[42915]],[[42915,42915],"valid"],[[42916,42916],"mapped",[42917]],[[42917,42917],"valid"],[[42918,42918],"mapped",[42919]],[[42919,42919],"valid"],[[42920,42920],"mapped",[42921]],[[42921,42921],"valid"],[[42922,42922],"mapped",[614]],[[42923,42923],"mapped",[604]],[[42924,42924],"mapped",[609]],[[42925,42925],"mapped",[620]],[[42926,42927],"disallowed"],[[42928,42928],"mapped",[670]],[[42929,42929],"mapped",[647]],[[42930,42930],"mapped",[669]],[[42931,42931],"mapped",[43859]],[[42932,42932],"mapped",[42933]],[[42933,42933],"valid"],[[42934,42934],"mapped",[42935]],[[42935,42935],"valid"],[[42936,42998],"disallowed"],[[42999,42999],"valid"],[[43000,43000],"mapped",[295]],[[43001,43001],"mapped",[339]],[[43002,43002],"valid"],[[43003,43007],"valid"],[[43008,43047],"valid"],[[43048,43051],"valid",[],"NV8"],[[43052,43055],"disallowed"],[[43056,43065],"valid",[],"NV8"],[[43066,43071],"disallowed"],[[43072,43123],"valid"],[[43124,43127],"valid",[],"NV8"],[[43128,43135],"disallowed"],[[43136,43204],"valid"],[[43205,43213],"disallowed"],[[43214,43215],"valid",[],"NV8"],[[43216,43225],"valid"],[[43226,43231],"disallowed"],[[43232,43255],"valid"],[[43256,43258],"valid",[],"NV8"],[[43259,43259],"valid"],[[43260,43260],"valid",[],"NV8"],[[43261,43261],"valid"],[[43262,43263],"disallowed"],[[43264,43309],"valid"],[[43310,43311],"valid",[],"NV8"],[[43312,43347],"valid"],[[43348,43358],"disallowed"],[[43359,43359],"valid",[],"NV8"],[[43360,43388],"valid",[],"NV8"],[[43389,43391],"disallowed"],[[43392,43456],"valid"],[[43457,43469],"valid",[],"NV8"],[[43470,43470],"disallowed"],[[43471,43481],"valid"],[[43482,43485],"disallowed"],[[43486,43487],"valid",[],"NV8"],[[43488,43518],"valid"],[[43519,43519],"disallowed"],[[43520,43574],"valid"],[[43575,43583],"disallowed"],[[43584,43597],"valid"],[[43598,43599],"disallowed"],[[43600,43609],"valid"],[[43610,43611],"disallowed"],[[43612,43615],"valid",[],"NV8"],[[43616,43638],"valid"],[[43639,43641],"valid",[],"NV8"],[[43642,43643],"valid"],[[43644,43647],"valid"],[[43648,43714],"valid"],[[43715,43738],"disallowed"],[[43739,43741],"valid"],[[43742,43743],"valid",[],"NV8"],[[43744,43759],"valid"],[[43760,43761],"valid",[],"NV8"],[[43762,43766],"valid"],[[43767,43776],"disallowed"],[[43777,43782],"valid"],[[43783,43784],"disallowed"],[[43785,43790],"valid"],[[43791,43792],"disallowed"],[[43793,43798],"valid"],[[43799,43807],"disallowed"],[[43808,43814],"valid"],[[43815,43815],"disallowed"],[[43816,43822],"valid"],[[43823,43823],"disallowed"],[[43824,43866],"valid"],[[43867,43867],"valid",[],"NV8"],[[43868,43868],"mapped",[42791]],[[43869,43869],"mapped",[43831]],[[43870,43870],"mapped",[619]],[[43871,43871],"mapped",[43858]],[[43872,43875],"valid"],[[43876,43877],"valid"],[[43878,43887],"disallowed"],[[43888,43888],"mapped",[5024]],[[43889,43889],"mapped",[5025]],[[43890,43890],"mapped",[5026]],[[43891,43891],"mapped",[5027]],[[43892,43892],"mapped",[5028]],[[43893,43893],"mapped",[5029]],[[43894,43894],"mapped",[5030]],[[43895,43895],"mapped",[5031]],[[43896,43896],"mapped",[5032]],[[43897,43897],"mapped",[5033]],[[43898,43898],"mapped",[5034]],[[43899,43899],"mapped",[5035]],[[43900,43900],"mapped",[5036]],[[43901,43901],"mapped",[5037]],[[43902,43902],"mapped",[5038]],[[43903,43903],"mapped",[5039]],[[43904,43904],"mapped",[5040]],[[43905,43905],"mapped",[5041]],[[43906,43906],"mapped",[5042]],[[43907,43907],"mapped",[5043]],[[43908,43908],"mapped",[5044]],[[43909,43909],"mapped",[5045]],[[43910,43910],"mapped",[5046]],[[43911,43911],"mapped",[5047]],[[43912,43912],"mapped",[5048]],[[43913,43913],"mapped",[5049]],[[43914,43914],"mapped",[5050]],[[43915,43915],"mapped",[5051]],[[43916,43916],"mapped",[5052]],[[43917,43917],"mapped",[5053]],[[43918,43918],"mapped",[5054]],[[43919,43919],"mapped",[5055]],[[43920,43920],"mapped",[5056]],[[43921,43921],"mapped",[5057]],[[43922,43922],"mapped",[5058]],[[43923,43923],"mapped",[5059]],[[43924,43924],"mapped",[5060]],[[43925,43925],"mapped",[5061]],[[43926,43926],"mapped",[5062]],[[43927,43927],"mapped",[5063]],[[43928,43928],"mapped",[5064]],[[43929,43929],"mapped",[5065]],[[43930,43930],"mapped",[5066]],[[43931,43931],"mapped",[5067]],[[43932,43932],"mapped",[5068]],[[43933,43933],"mapped",[5069]],[[43934,43934],"mapped",[5070]],[[43935,43935],"mapped",[5071]],[[43936,43936],"mapped",[5072]],[[43937,43937],"mapped",[5073]],[[43938,43938],"mapped",[5074]],[[43939,43939],"mapped",[5075]],[[43940,43940],"mapped",[5076]],[[43941,43941],"mapped",[5077]],[[43942,43942],"mapped",[5078]],[[43943,43943],"mapped",[5079]],[[43944,43944],"mapped",[5080]],[[43945,43945],"mapped",[5081]],[[43946,43946],"mapped",[5082]],[[43947,43947],"mapped",[5083]],[[43948,43948],"mapped",[5084]],[[43949,43949],"mapped",[5085]],[[43950,43950],"mapped",[5086]],[[43951,43951],"mapped",[5087]],[[43952,43952],"mapped",[5088]],[[43953,43953],"mapped",[5089]],[[43954,43954],"mapped",[5090]],[[43955,43955],"mapped",[5091]],[[43956,43956],"mapped",[5092]],[[43957,43957],"mapped",[5093]],[[43958,43958],"mapped",[5094]],[[43959,43959],"mapped",[5095]],[[43960,43960],"mapped",[5096]],[[43961,43961],"mapped",[5097]],[[43962,43962],"mapped",[5098]],[[43963,43963],"mapped",[5099]],[[43964,43964],"mapped",[5100]],[[43965,43965],"mapped",[5101]],[[43966,43966],"mapped",[5102]],[[43967,43967],"mapped",[5103]],[[43968,44010],"valid"],[[44011,44011],"valid",[],"NV8"],[[44012,44013],"valid"],[[44014,44015],"disallowed"],[[44016,44025],"valid"],[[44026,44031],"disallowed"],[[44032,55203],"valid"],[[55204,55215],"disallowed"],[[55216,55238],"valid",[],"NV8"],[[55239,55242],"disallowed"],[[55243,55291],"valid",[],"NV8"],[[55292,55295],"disallowed"],[[55296,57343],"disallowed"],[[57344,63743],"disallowed"],[[63744,63744],"mapped",[35912]],[[63745,63745],"mapped",[26356]],[[63746,63746],"mapped",[36554]],[[63747,63747],"mapped",[36040]],[[63748,63748],"mapped",[28369]],[[63749,63749],"mapped",[20018]],[[63750,63750],"mapped",[21477]],[[63751,63752],"mapped",[40860]],[[63753,63753],"mapped",[22865]],[[63754,63754],"mapped",[37329]],[[63755,63755],"mapped",[21895]],[[63756,63756],"mapped",[22856]],[[63757,63757],"mapped",[25078]],[[63758,63758],"mapped",[30313]],[[63759,63759],"mapped",[32645]],[[63760,63760],"mapped",[34367]],[[63761,63761],"mapped",[34746]],[[63762,63762],"mapped",[35064]],[[63763,63763],"mapped",[37007]],[[63764,63764],"mapped",[27138]],[[63765,63765],"mapped",[27931]],[[63766,63766],"mapped",[28889]],[[63767,63767],"mapped",[29662]],[[63768,63768],"mapped",[33853]],[[63769,63769],"mapped",[37226]],[[63770,63770],"mapped",[39409]],[[63771,63771],"mapped",[20098]],[[63772,63772],"mapped",[21365]],[[63773,63773],"mapped",[27396]],[[63774,63774],"mapped",[29211]],[[63775,63775],"mapped",[34349]],[[63776,63776],"mapped",[40478]],[[63777,63777],"mapped",[23888]],[[63778,63778],"mapped",[28651]],[[63779,63779],"mapped",[34253]],[[63780,63780],"mapped",[35172]],[[63781,63781],"mapped",[25289]],[[63782,63782],"mapped",[33240]],[[63783,63783],"mapped",[34847]],[[63784,63784],"mapped",[24266]],[[63785,63785],"mapped",[26391]],[[63786,63786],"mapped",[28010]],[[63787,63787],"mapped",[29436]],[[63788,63788],"mapped",[37070]],[[63789,63789],"mapped",[20358]],[[63790,63790],"mapped",[20919]],[[63791,63791],"mapped",[21214]],[[63792,63792],"mapped",[25796]],[[63793,63793],"mapped",[27347]],[[63794,63794],"mapped",[29200]],[[63795,63795],"mapped",[30439]],[[63796,63796],"mapped",[32769]],[[63797,63797],"mapped",[34310]],[[63798,63798],"mapped",[34396]],[[63799,63799],"mapped",[36335]],[[63800,63800],"mapped",[38706]],[[63801,63801],"mapped",[39791]],[[63802,63802],"mapped",[40442]],[[63803,63803],"mapped",[30860]],[[63804,63804],"mapped",[31103]],[[63805,63805],"mapped",[32160]],[[63806,63806],"mapped",[33737]],[[63807,63807],"mapped",[37636]],[[63808,63808],"mapped",[40575]],[[63809,63809],"mapped",[35542]],[[63810,63810],"mapped",[22751]],[[63811,63811],"mapped",[24324]],[[63812,63812],"mapped",[31840]],[[63813,63813],"mapped",[32894]],[[63814,63814],"mapped",[29282]],[[63815,63815],"mapped",[30922]],[[63816,63816],"mapped",[36034]],[[63817,63817],"mapped",[38647]],[[63818,63818],"mapped",[22744]],[[63819,63819],"mapped",[23650]],[[63820,63820],"mapped",[27155]],[[63821,63821],"mapped",[28122]],[[63822,63822],"mapped",[28431]],[[63823,63823],"mapped",[32047]],[[63824,63824],"mapped",[32311]],[[63825,63825],"mapped",[38475]],[[63826,63826],"mapped",[21202]],[[63827,63827],"mapped",[32907]],[[63828,63828],"mapped",[20956]],[[63829,63829],"mapped",[20940]],[[63830,63830],"mapped",[31260]],[[63831,63831],"mapped",[32190]],[[63832,63832],"mapped",[33777]],[[63833,63833],"mapped",[38517]],[[63834,63834],"mapped",[35712]],[[63835,63835],"mapped",[25295]],[[63836,63836],"mapped",[27138]],[[63837,63837],"mapped",[35582]],[[63838,63838],"mapped",[20025]],[[63839,63839],"mapped",[23527]],[[63840,63840],"mapped",[24594]],[[63841,63841],"mapped",[29575]],[[63842,63842],"mapped",[30064]],[[63843,63843],"mapped",[21271]],[[63844,63844],"mapped",[30971]],[[63845,63845],"mapped",[20415]],[[63846,63846],"mapped",[24489]],[[63847,63847],"mapped",[19981]],[[63848,63848],"mapped",[27852]],[[63849,63849],"mapped",[25976]],[[63850,63850],"mapped",[32034]],[[63851,63851],"mapped",[21443]],[[63852,63852],"mapped",[22622]],[[63853,63853],"mapped",[30465]],[[63854,63854],"mapped",[33865]],[[63855,63855],"mapped",[35498]],[[63856,63856],"mapped",[27578]],[[63857,63857],"mapped",[36784]],[[63858,63858],"mapped",[27784]],[[63859,63859],"mapped",[25342]],[[63860,63860],"mapped",[33509]],[[63861,63861],"mapped",[25504]],[[63862,63862],"mapped",[30053]],[[63863,63863],"mapped",[20142]],[[63864,63864],"mapped",[20841]],[[63865,63865],"mapped",[20937]],[[63866,63866],"mapped",[26753]],[[63867,63867],"mapped",[31975]],[[63868,63868],"mapped",[33391]],[[63869,63869],"mapped",[35538]],[[63870,63870],"mapped",[37327]],[[63871,63871],"mapped",[21237]],[[63872,63872],"mapped",[21570]],[[63873,63873],"mapped",[22899]],[[63874,63874],"mapped",[24300]],[[63875,63875],"mapped",[26053]],[[63876,63876],"mapped",[28670]],[[63877,63877],"mapped",[31018]],[[63878,63878],"mapped",[38317]],[[63879,63879],"mapped",[39530]],[[63880,63880],"mapped",[40599]],[[63881,63881],"mapped",[40654]],[[63882,63882],"mapped",[21147]],[[63883,63883],"mapped",[26310]],[[63884,63884],"mapped",[27511]],[[63885,63885],"mapped",[36706]],[[63886,63886],"mapped",[24180]],[[63887,63887],"mapped",[24976]],[[63888,63888],"mapped",[25088]],[[63889,63889],"mapped",[25754]],[[63890,63890],"mapped",[28451]],[[63891,63891],"mapped",[29001]],[[63892,63892],"mapped",[29833]],[[63893,63893],"mapped",[31178]],[[63894,63894],"mapped",[32244]],[[63895,63895],"mapped",[32879]],[[63896,63896],"mapped",[36646]],[[63897,63897],"mapped",[34030]],[[63898,63898],"mapped",[36899]],[[63899,63899],"mapped",[37706]],[[63900,63900],"mapped",[21015]],[[63901,63901],"mapped",[21155]],[[63902,63902],"mapped",[21693]],[[63903,63903],"mapped",[28872]],[[63904,63904],"mapped",[35010]],[[63905,63905],"mapped",[35498]],[[63906,63906],"mapped",[24265]],[[63907,63907],"mapped",[24565]],[[63908,63908],"mapped",[25467]],[[63909,63909],"mapped",[27566]],[[63910,63910],"mapped",[31806]],[[63911,63911],"mapped",[29557]],[[63912,63912],"mapped",[20196]],[[63913,63913],"mapped",[22265]],[[63914,63914],"mapped",[23527]],[[63915,63915],"mapped",[23994]],[[63916,63916],"mapped",[24604]],[[63917,63917],"mapped",[29618]],[[63918,63918],"mapped",[29801]],[[63919,63919],"mapped",[32666]],[[63920,63920],"mapped",[32838]],[[63921,63921],"mapped",[37428]],[[63922,63922],"mapped",[38646]],[[63923,63923],"mapped",[38728]],[[63924,63924],"mapped",[38936]],[[63925,63925],"mapped",[20363]],[[63926,63926],"mapped",[31150]],[[63927,63927],"mapped",[37300]],[[63928,63928],"mapped",[38584]],[[63929,63929],"mapped",[24801]],[[63930,63930],"mapped",[20102]],[[63931,63931],"mapped",[20698]],[[63932,63932],"mapped",[23534]],[[63933,63933],"mapped",[23615]],[[63934,63934],"mapped",[26009]],[[63935,63935],"mapped",[27138]],[[63936,63936],"mapped",[29134]],[[63937,63937],"mapped",[30274]],[[63938,63938],"mapped",[34044]],[[63939,63939],"mapped",[36988]],[[63940,63940],"mapped",[40845]],[[63941,63941],"mapped",[26248]],[[63942,63942],"mapped",[38446]],[[63943,63943],"mapped",[21129]],[[63944,63944],"mapped",[26491]],[[63945,63945],"mapped",[26611]],[[63946,63946],"mapped",[27969]],[[63947,63947],"mapped",[28316]],[[63948,63948],"mapped",[29705]],[[63949,63949],"mapped",[30041]],[[63950,63950],"mapped",[30827]],[[63951,63951],"mapped",[32016]],[[63952,63952],"mapped",[39006]],[[63953,63953],"mapped",[20845]],[[63954,63954],"mapped",[25134]],[[63955,63955],"mapped",[38520]],[[63956,63956],"mapped",[20523]],[[63957,63957],"mapped",[23833]],[[63958,63958],"mapped",[28138]],[[63959,63959],"mapped",[36650]],[[63960,63960],"mapped",[24459]],[[63961,63961],"mapped",[24900]],[[63962,63962],"mapped",[26647]],[[63963,63963],"mapped",[29575]],[[63964,63964],"mapped",[38534]],[[63965,63965],"mapped",[21033]],[[63966,63966],"mapped",[21519]],[[63967,63967],"mapped",[23653]],[[63968,63968],"mapped",[26131]],[[63969,63969],"mapped",[26446]],[[63970,63970],"mapped",[26792]],[[63971,63971],"mapped",[27877]],[[63972,63972],"mapped",[29702]],[[63973,63973],"mapped",[30178]],[[63974,63974],"mapped",[32633]],[[63975,63975],"mapped",[35023]],[[63976,63976],"mapped",[35041]],[[63977,63977],"mapped",[37324]],[[63978,63978],"mapped",[38626]],[[63979,63979],"mapped",[21311]],[[63980,63980],"mapped",[28346]],[[63981,63981],"mapped",[21533]],[[63982,63982],"mapped",[29136]],[[63983,63983],"mapped",[29848]],[[63984,63984],"mapped",[34298]],[[63985,63985],"mapped",[38563]],[[63986,63986],"mapped",[40023]],[[63987,63987],"mapped",[40607]],[[63988,63988],"mapped",[26519]],[[63989,63989],"mapped",[28107]],[[63990,63990],"mapped",[33256]],[[63991,63991],"mapped",[31435]],[[63992,63992],"mapped",[31520]],[[63993,63993],"mapped",[31890]],[[63994,63994],"mapped",[29376]],[[63995,63995],"mapped",[28825]],[[63996,63996],"mapped",[35672]],[[63997,63997],"mapped",[20160]],[[63998,63998],"mapped",[33590]],[[63999,63999],"mapped",[21050]],[[64000,64000],"mapped",[20999]],[[64001,64001],"mapped",[24230]],[[64002,64002],"mapped",[25299]],[[64003,64003],"mapped",[31958]],[[64004,64004],"mapped",[23429]],[[64005,64005],"mapped",[27934]],[[64006,64006],"mapped",[26292]],[[64007,64007],"mapped",[36667]],[[64008,64008],"mapped",[34892]],[[64009,64009],"mapped",[38477]],[[64010,64010],"mapped",[35211]],[[64011,64011],"mapped",[24275]],[[64012,64012],"mapped",[20800]],[[64013,64013],"mapped",[21952]],[[64014,64015],"valid"],[[64016,64016],"mapped",[22618]],[[64017,64017],"valid"],[[64018,64018],"mapped",[26228]],[[64019,64020],"valid"],[[64021,64021],"mapped",[20958]],[[64022,64022],"mapped",[29482]],[[64023,64023],"mapped",[30410]],[[64024,64024],"mapped",[31036]],[[64025,64025],"mapped",[31070]],[[64026,64026],"mapped",[31077]],[[64027,64027],"mapped",[31119]],[[64028,64028],"mapped",[38742]],[[64029,64029],"mapped",[31934]],[[64030,64030],"mapped",[32701]],[[64031,64031],"valid"],[[64032,64032],"mapped",[34322]],[[64033,64033],"valid"],[[64034,64034],"mapped",[35576]],[[64035,64036],"valid"],[[64037,64037],"mapped",[36920]],[[64038,64038],"mapped",[37117]],[[64039,64041],"valid"],[[64042,64042],"mapped",[39151]],[[64043,64043],"mapped",[39164]],[[64044,64044],"mapped",[39208]],[[64045,64045],"mapped",[40372]],[[64046,64046],"mapped",[37086]],[[64047,64047],"mapped",[38583]],[[64048,64048],"mapped",[20398]],[[64049,64049],"mapped",[20711]],[[64050,64050],"mapped",[20813]],[[64051,64051],"mapped",[21193]],[[64052,64052],"mapped",[21220]],[[64053,64053],"mapped",[21329]],[[64054,64054],"mapped",[21917]],[[64055,64055],"mapped",[22022]],[[64056,64056],"mapped",[22120]],[[64057,64057],"mapped",[22592]],[[64058,64058],"mapped",[22696]],[[64059,64059],"mapped",[23652]],[[64060,64060],"mapped",[23662]],[[64061,64061],"mapped",[24724]],[[64062,64062],"mapped",[24936]],[[64063,64063],"mapped",[24974]],[[64064,64064],"mapped",[25074]],[[64065,64065],"mapped",[25935]],[[64066,64066],"mapped",[26082]],[[64067,64067],"mapped",[26257]],[[64068,64068],"mapped",[26757]],[[64069,64069],"mapped",[28023]],[[64070,64070],"mapped",[28186]],[[64071,64071],"mapped",[28450]],[[64072,64072],"mapped",[29038]],[[64073,64073],"mapped",[29227]],[[64074,64074],"mapped",[29730]],[[64075,64075],"mapped",[30865]],[[64076,64076],"mapped",[31038]],[[64077,64077],"mapped",[31049]],[[64078,64078],"mapped",[31048]],[[64079,64079],"mapped",[31056]],[[64080,64080],"mapped",[31062]],[[64081,64081],"mapped",[31069]],[[64082,64082],"mapped",[31117]],[[64083,64083],"mapped",[31118]],[[64084,64084],"mapped",[31296]],[[64085,64085],"mapped",[31361]],[[64086,64086],"mapped",[31680]],[[64087,64087],"mapped",[32244]],[[64088,64088],"mapped",[32265]],[[64089,64089],"mapped",[32321]],[[64090,64090],"mapped",[32626]],[[64091,64091],"mapped",[32773]],[[64092,64092],"mapped",[33261]],[[64093,64094],"mapped",[33401]],[[64095,64095],"mapped",[33879]],[[64096,64096],"mapped",[35088]],[[64097,64097],"mapped",[35222]],[[64098,64098],"mapped",[35585]],[[64099,64099],"mapped",[35641]],[[64100,64100],"mapped",[36051]],[[64101,64101],"mapped",[36104]],[[64102,64102],"mapped",[36790]],[[64103,64103],"mapped",[36920]],[[64104,64104],"mapped",[38627]],[[64105,64105],"mapped",[38911]],[[64106,64106],"mapped",[38971]],[[64107,64107],"mapped",[24693]],[[64108,64108],"mapped",[148206]],[[64109,64109],"mapped",[33304]],[[64110,64111],"disallowed"],[[64112,64112],"mapped",[20006]],[[64113,64113],"mapped",[20917]],[[64114,64114],"mapped",[20840]],[[64115,64115],"mapped",[20352]],[[64116,64116],"mapped",[20805]],[[64117,64117],"mapped",[20864]],[[64118,64118],"mapped",[21191]],[[64119,64119],"mapped",[21242]],[[64120,64120],"mapped",[21917]],[[64121,64121],"mapped",[21845]],[[64122,64122],"mapped",[21913]],[[64123,64123],"mapped",[21986]],[[64124,64124],"mapped",[22618]],[[64125,64125],"mapped",[22707]],[[64126,64126],"mapped",[22852]],[[64127,64127],"mapped",[22868]],[[64128,64128],"mapped",[23138]],[[64129,64129],"mapped",[23336]],[[64130,64130],"mapped",[24274]],[[64131,64131],"mapped",[24281]],[[64132,64132],"mapped",[24425]],[[64133,64133],"mapped",[24493]],[[64134,64134],"mapped",[24792]],[[64135,64135],"mapped",[24910]],[[64136,64136],"mapped",[24840]],[[64137,64137],"mapped",[24974]],[[64138,64138],"mapped",[24928]],[[64139,64139],"mapped",[25074]],[[64140,64140],"mapped",[25140]],[[64141,64141],"mapped",[25540]],[[64142,64142],"mapped",[25628]],[[64143,64143],"mapped",[25682]],[[64144,64144],"mapped",[25942]],[[64145,64145],"mapped",[26228]],[[64146,64146],"mapped",[26391]],[[64147,64147],"mapped",[26395]],[[64148,64148],"mapped",[26454]],[[64149,64149],"mapped",[27513]],[[64150,64150],"mapped",[27578]],[[64151,64151],"mapped",[27969]],[[64152,64152],"mapped",[28379]],[[64153,64153],"mapped",[28363]],[[64154,64154],"mapped",[28450]],[[64155,64155],"mapped",[28702]],[[64156,64156],"mapped",[29038]],[[64157,64157],"mapped",[30631]],[[64158,64158],"mapped",[29237]],[[64159,64159],"mapped",[29359]],[[64160,64160],"mapped",[29482]],[[64161,64161],"mapped",[29809]],[[64162,64162],"mapped",[29958]],[[64163,64163],"mapped",[30011]],[[64164,64164],"mapped",[30237]],[[64165,64165],"mapped",[30239]],[[64166,64166],"mapped",[30410]],[[64167,64167],"mapped",[30427]],[[64168,64168],"mapped",[30452]],[[64169,64169],"mapped",[30538]],[[64170,64170],"mapped",[30528]],[[64171,64171],"mapped",[30924]],[[64172,64172],"mapped",[31409]],[[64173,64173],"mapped",[31680]],[[64174,64174],"mapped",[31867]],[[64175,64175],"mapped",[32091]],[[64176,64176],"mapped",[32244]],[[64177,64177],"mapped",[32574]],[[64178,64178],"mapped",[32773]],[[64179,64179],"mapped",[33618]],[[64180,64180],"mapped",[33775]],[[64181,64181],"mapped",[34681]],[[64182,64182],"mapped",[35137]],[[64183,64183],"mapped",[35206]],[[64184,64184],"mapped",[35222]],[[64185,64185],"mapped",[35519]],[[64186,64186],"mapped",[35576]],[[64187,64187],"mapped",[35531]],[[64188,64188],"mapped",[35585]],[[64189,64189],"mapped",[35582]],[[64190,64190],"mapped",[35565]],[[64191,64191],"mapped",[35641]],[[64192,64192],"mapped",[35722]],[[64193,64193],"mapped",[36104]],[[64194,64194],"mapped",[36664]],[[64195,64195],"mapped",[36978]],[[64196,64196],"mapped",[37273]],[[64197,64197],"mapped",[37494]],[[64198,64198],"mapped",[38524]],[[64199,64199],"mapped",[38627]],[[64200,64200],"mapped",[38742]],[[64201,64201],"mapped",[38875]],[[64202,64202],"mapped",[38911]],[[64203,64203],"mapped",[38923]],[[64204,64204],"mapped",[38971]],[[64205,64205],"mapped",[39698]],[[64206,64206],"mapped",[40860]],[[64207,64207],"mapped",[141386]],[[64208,64208],"mapped",[141380]],[[64209,64209],"mapped",[144341]],[[64210,64210],"mapped",[15261]],[[64211,64211],"mapped",[16408]],[[64212,64212],"mapped",[16441]],[[64213,64213],"mapped",[152137]],[[64214,64214],"mapped",[154832]],[[64215,64215],"mapped",[163539]],[[64216,64216],"mapped",[40771]],[[64217,64217],"mapped",[40846]],[[64218,64255],"disallowed"],[[64256,64256],"mapped",[102,102]],[[64257,64257],"mapped",[102,105]],[[64258,64258],"mapped",[102,108]],[[64259,64259],"mapped",[102,102,105]],[[64260,64260],"mapped",[102,102,108]],[[64261,64262],"mapped",[115,116]],[[64263,64274],"disallowed"],[[64275,64275],"mapped",[1396,1398]],[[64276,64276],"mapped",[1396,1381]],[[64277,64277],"mapped",[1396,1387]],[[64278,64278],"mapped",[1406,1398]],[[64279,64279],"mapped",[1396,1389]],[[64280,64284],"disallowed"],[[64285,64285],"mapped",[1497,1460]],[[64286,64286],"valid"],[[64287,64287],"mapped",[1522,1463]],[[64288,64288],"mapped",[1506]],[[64289,64289],"mapped",[1488]],[[64290,64290],"mapped",[1491]],[[64291,64291],"mapped",[1492]],[[64292,64292],"mapped",[1499]],[[64293,64293],"mapped",[1500]],[[64294,64294],"mapped",[1501]],[[64295,64295],"mapped",[1512]],[[64296,64296],"mapped",[1514]],[[64297,64297],"disallowed_STD3_mapped",[43]],[[64298,64298],"mapped",[1513,1473]],[[64299,64299],"mapped",[1513,1474]],[[64300,64300],"mapped",[1513,1468,1473]],[[64301,64301],"mapped",[1513,1468,1474]],[[64302,64302],"mapped",[1488,1463]],[[64303,64303],"mapped",[1488,1464]],[[64304,64304],"mapped",[1488,1468]],[[64305,64305],"mapped",[1489,1468]],[[64306,64306],"mapped",[1490,1468]],[[64307,64307],"mapped",[1491,1468]],[[64308,64308],"mapped",[1492,1468]],[[64309,64309],"mapped",[1493,1468]],[[64310,64310],"mapped",[1494,1468]],[[64311,64311],"disallowed"],[[64312,64312],"mapped",[1496,1468]],[[64313,64313],"mapped",[1497,1468]],[[64314,64314],"mapped",[1498,1468]],[[64315,64315],"mapped",[1499,1468]],[[64316,64316],"mapped",[1500,1468]],[[64317,64317],"disallowed"],[[64318,64318],"mapped",[1502,1468]],[[64319,64319],"disallowed"],[[64320,64320],"mapped",[1504,1468]],[[64321,64321],"mapped",[1505,1468]],[[64322,64322],"disallowed"],[[64323,64323],"mapped",[1507,1468]],[[64324,64324],"mapped",[1508,1468]],[[64325,64325],"disallowed"],[[64326,64326],"mapped",[1510,1468]],[[64327,64327],"mapped",[1511,1468]],[[64328,64328],"mapped",[1512,1468]],[[64329,64329],"mapped",[1513,1468]],[[64330,64330],"mapped",[1514,1468]],[[64331,64331],"mapped",[1493,1465]],[[64332,64332],"mapped",[1489,1471]],[[64333,64333],"mapped",[1499,1471]],[[64334,64334],"mapped",[1508,1471]],[[64335,64335],"mapped",[1488,1500]],[[64336,64337],"mapped",[1649]],[[64338,64341],"mapped",[1659]],[[64342,64345],"mapped",[1662]],[[64346,64349],"mapped",[1664]],[[64350,64353],"mapped",[1658]],[[64354,64357],"mapped",[1663]],[[64358,64361],"mapped",[1657]],[[64362,64365],"mapped",[1700]],[[64366,64369],"mapped",[1702]],[[64370,64373],"mapped",[1668]],[[64374,64377],"mapped",[1667]],[[64378,64381],"mapped",[1670]],[[64382,64385],"mapped",[1671]],[[64386,64387],"mapped",[1677]],[[64388,64389],"mapped",[1676]],[[64390,64391],"mapped",[1678]],[[64392,64393],"mapped",[1672]],[[64394,64395],"mapped",[1688]],[[64396,64397],"mapped",[1681]],[[64398,64401],"mapped",[1705]],[[64402,64405],"mapped",[1711]],[[64406,64409],"mapped",[1715]],[[64410,64413],"mapped",[1713]],[[64414,64415],"mapped",[1722]],[[64416,64419],"mapped",[1723]],[[64420,64421],"mapped",[1728]],[[64422,64425],"mapped",[1729]],[[64426,64429],"mapped",[1726]],[[64430,64431],"mapped",[1746]],[[64432,64433],"mapped",[1747]],[[64434,64449],"valid",[],"NV8"],[[64450,64466],"disallowed"],[[64467,64470],"mapped",[1709]],[[64471,64472],"mapped",[1735]],[[64473,64474],"mapped",[1734]],[[64475,64476],"mapped",[1736]],[[64477,64477],"mapped",[1735,1652]],[[64478,64479],"mapped",[1739]],[[64480,64481],"mapped",[1733]],[[64482,64483],"mapped",[1737]],[[64484,64487],"mapped",[1744]],[[64488,64489],"mapped",[1609]],[[64490,64491],"mapped",[1574,1575]],[[64492,64493],"mapped",[1574,1749]],[[64494,64495],"mapped",[1574,1608]],[[64496,64497],"mapped",[1574,1735]],[[64498,64499],"mapped",[1574,1734]],[[64500,64501],"mapped",[1574,1736]],[[64502,64504],"mapped",[1574,1744]],[[64505,64507],"mapped",[1574,1609]],[[64508,64511],"mapped",[1740]],[[64512,64512],"mapped",[1574,1580]],[[64513,64513],"mapped",[1574,1581]],[[64514,64514],"mapped",[1574,1605]],[[64515,64515],"mapped",[1574,1609]],[[64516,64516],"mapped",[1574,1610]],[[64517,64517],"mapped",[1576,1580]],[[64518,64518],"mapped",[1576,1581]],[[64519,64519],"mapped",[1576,1582]],[[64520,64520],"mapped",[1576,1605]],[[64521,64521],"mapped",[1576,1609]],[[64522,64522],"mapped",[1576,1610]],[[64523,64523],"mapped",[1578,1580]],[[64524,64524],"mapped",[1578,1581]],[[64525,64525],"mapped",[1578,1582]],[[64526,64526],"mapped",[1578,1605]],[[64527,64527],"mapped",[1578,1609]],[[64528,64528],"mapped",[1578,1610]],[[64529,64529],"mapped",[1579,1580]],[[64530,64530],"mapped",[1579,1605]],[[64531,64531],"mapped",[1579,1609]],[[64532,64532],"mapped",[1579,1610]],[[64533,64533],"mapped",[1580,1581]],[[64534,64534],"mapped",[1580,1605]],[[64535,64535],"mapped",[1581,1580]],[[64536,64536],"mapped",[1581,1605]],[[64537,64537],"mapped",[1582,1580]],[[64538,64538],"mapped",[1582,1581]],[[64539,64539],"mapped",[1582,1605]],[[64540,64540],"mapped",[1587,1580]],[[64541,64541],"mapped",[1587,1581]],[[64542,64542],"mapped",[1587,1582]],[[64543,64543],"mapped",[1587,1605]],[[64544,64544],"mapped",[1589,1581]],[[64545,64545],"mapped",[1589,1605]],[[64546,64546],"mapped",[1590,1580]],[[64547,64547],"mapped",[1590,1581]],[[64548,64548],"mapped",[1590,1582]],[[64549,64549],"mapped",[1590,1605]],[[64550,64550],"mapped",[1591,1581]],[[64551,64551],"mapped",[1591,1605]],[[64552,64552],"mapped",[1592,1605]],[[64553,64553],"mapped",[1593,1580]],[[64554,64554],"mapped",[1593,1605]],[[64555,64555],"mapped",[1594,1580]],[[64556,64556],"mapped",[1594,1605]],[[64557,64557],"mapped",[1601,1580]],[[64558,64558],"mapped",[1601,1581]],[[64559,64559],"mapped",[1601,1582]],[[64560,64560],"mapped",[1601,1605]],[[64561,64561],"mapped",[1601,1609]],[[64562,64562],"mapped",[1601,1610]],[[64563,64563],"mapped",[1602,1581]],[[64564,64564],"mapped",[1602,1605]],[[64565,64565],"mapped",[1602,1609]],[[64566,64566],"mapped",[1602,1610]],[[64567,64567],"mapped",[1603,1575]],[[64568,64568],"mapped",[1603,1580]],[[64569,64569],"mapped",[1603,1581]],[[64570,64570],"mapped",[1603,1582]],[[64571,64571],"mapped",[1603,1604]],[[64572,64572],"mapped",[1603,1605]],[[64573,64573],"mapped",[1603,1609]],[[64574,64574],"mapped",[1603,1610]],[[64575,64575],"mapped",[1604,1580]],[[64576,64576],"mapped",[1604,1581]],[[64577,64577],"mapped",[1604,1582]],[[64578,64578],"mapped",[1604,1605]],[[64579,64579],"mapped",[1604,1609]],[[64580,64580],"mapped",[1604,1610]],[[64581,64581],"mapped",[1605,1580]],[[64582,64582],"mapped",[1605,1581]],[[64583,64583],"mapped",[1605,1582]],[[64584,64584],"mapped",[1605,1605]],[[64585,64585],"mapped",[1605,1609]],[[64586,64586],"mapped",[1605,1610]],[[64587,64587],"mapped",[1606,1580]],[[64588,64588],"mapped",[1606,1581]],[[64589,64589],"mapped",[1606,1582]],[[64590,64590],"mapped",[1606,1605]],[[64591,64591],"mapped",[1606,1609]],[[64592,64592],"mapped",[1606,1610]],[[64593,64593],"mapped",[1607,1580]],[[64594,64594],"mapped",[1607,1605]],[[64595,64595],"mapped",[1607,1609]],[[64596,64596],"mapped",[1607,1610]],[[64597,64597],"mapped",[1610,1580]],[[64598,64598],"mapped",[1610,1581]],[[64599,64599],"mapped",[1610,1582]],[[64600,64600],"mapped",[1610,1605]],[[64601,64601],"mapped",[1610,1609]],[[64602,64602],"mapped",[1610,1610]],[[64603,64603],"mapped",[1584,1648]],[[64604,64604],"mapped",[1585,1648]],[[64605,64605],"mapped",[1609,1648]],[[64606,64606],"disallowed_STD3_mapped",[32,1612,1617]],[[64607,64607],"disallowed_STD3_mapped",[32,1613,1617]],[[64608,64608],"disallowed_STD3_mapped",[32,1614,1617]],[[64609,64609],"disallowed_STD3_mapped",[32,1615,1617]],[[64610,64610],"disallowed_STD3_mapped",[32,1616,1617]],[[64611,64611],"disallowed_STD3_mapped",[32,1617,1648]],[[64612,64612],"mapped",[1574,1585]],[[64613,64613],"mapped",[1574,1586]],[[64614,64614],"mapped",[1574,1605]],[[64615,64615],"mapped",[1574,1606]],[[64616,64616],"mapped",[1574,1609]],[[64617,64617],"mapped",[1574,1610]],[[64618,64618],"mapped",[1576,1585]],[[64619,64619],"mapped",[1576,1586]],[[64620,64620],"mapped",[1576,1605]],[[64621,64621],"mapped",[1576,1606]],[[64622,64622],"mapped",[1576,1609]],[[64623,64623],"mapped",[1576,1610]],[[64624,64624],"mapped",[1578,1585]],[[64625,64625],"mapped",[1578,1586]],[[64626,64626],"mapped",[1578,1605]],[[64627,64627],"mapped",[1578,1606]],[[64628,64628],"mapped",[1578,1609]],[[64629,64629],"mapped",[1578,1610]],[[64630,64630],"mapped",[1579,1585]],[[64631,64631],"mapped",[1579,1586]],[[64632,64632],"mapped",[1579,1605]],[[64633,64633],"mapped",[1579,1606]],[[64634,64634],"mapped",[1579,1609]],[[64635,64635],"mapped",[1579,1610]],[[64636,64636],"mapped",[1601,1609]],[[64637,64637],"mapped",[1601,1610]],[[64638,64638],"mapped",[1602,1609]],[[64639,64639],"mapped",[1602,1610]],[[64640,64640],"mapped",[1603,1575]],[[64641,64641],"mapped",[1603,1604]],[[64642,64642],"mapped",[1603,1605]],[[64643,64643],"mapped",[1603,1609]],[[64644,64644],"mapped",[1603,1610]],[[64645,64645],"mapped",[1604,1605]],[[64646,64646],"mapped",[1604,1609]],[[64647,64647],"mapped",[1604,1610]],[[64648,64648],"mapped",[1605,1575]],[[64649,64649],"mapped",[1605,1605]],[[64650,64650],"mapped",[1606,1585]],[[64651,64651],"mapped",[1606,1586]],[[64652,64652],"mapped",[1606,1605]],[[64653,64653],"mapped",[1606,1606]],[[64654,64654],"mapped",[1606,1609]],[[64655,64655],"mapped",[1606,1610]],[[64656,64656],"mapped",[1609,1648]],[[64657,64657],"mapped",[1610,1585]],[[64658,64658],"mapped",[1610,1586]],[[64659,64659],"mapped",[1610,1605]],[[64660,64660],"mapped",[1610,1606]],[[64661,64661],"mapped",[1610,1609]],[[64662,64662],"mapped",[1610,1610]],[[64663,64663],"mapped",[1574,1580]],[[64664,64664],"mapped",[1574,1581]],[[64665,64665],"mapped",[1574,1582]],[[64666,64666],"mapped",[1574,1605]],[[64667,64667],"mapped",[1574,1607]],[[64668,64668],"mapped",[1576,1580]],[[64669,64669],"mapped",[1576,1581]],[[64670,64670],"mapped",[1576,1582]],[[64671,64671],"mapped",[1576,1605]],[[64672,64672],"mapped",[1576,1607]],[[64673,64673],"mapped",[1578,1580]],[[64674,64674],"mapped",[1578,1581]],[[64675,64675],"mapped",[1578,1582]],[[64676,64676],"mapped",[1578,1605]],[[64677,64677],"mapped",[1578,1607]],[[64678,64678],"mapped",[1579,1605]],[[64679,64679],"mapped",[1580,1581]],[[64680,64680],"mapped",[1580,1605]],[[64681,64681],"mapped",[1581,1580]],[[64682,64682],"mapped",[1581,1605]],[[64683,64683],"mapped",[1582,1580]],[[64684,64684],"mapped",[1582,1605]],[[64685,64685],"mapped",[1587,1580]],[[64686,64686],"mapped",[1587,1581]],[[64687,64687],"mapped",[1587,1582]],[[64688,64688],"mapped",[1587,1605]],[[64689,64689],"mapped",[1589,1581]],[[64690,64690],"mapped",[1589,1582]],[[64691,64691],"mapped",[1589,1605]],[[64692,64692],"mapped",[1590,1580]],[[64693,64693],"mapped",[1590,1581]],[[64694,64694],"mapped",[1590,1582]],[[64695,64695],"mapped",[1590,1605]],[[64696,64696],"mapped",[1591,1581]],[[64697,64697],"mapped",[1592,1605]],[[64698,64698],"mapped",[1593,1580]],[[64699,64699],"mapped",[1593,1605]],[[64700,64700],"mapped",[1594,1580]],[[64701,64701],"mapped",[1594,1605]],[[64702,64702],"mapped",[1601,1580]],[[64703,64703],"mapped",[1601,1581]],[[64704,64704],"mapped",[1601,1582]],[[64705,64705],"mapped",[1601,1605]],[[64706,64706],"mapped",[1602,1581]],[[64707,64707],"mapped",[1602,1605]],[[64708,64708],"mapped",[1603,1580]],[[64709,64709],"mapped",[1603,1581]],[[64710,64710],"mapped",[1603,1582]],[[64711,64711],"mapped",[1603,1604]],[[64712,64712],"mapped",[1603,1605]],[[64713,64713],"mapped",[1604,1580]],[[64714,64714],"mapped",[1604,1581]],[[64715,64715],"mapped",[1604,1582]],[[64716,64716],"mapped",[1604,1605]],[[64717,64717],"mapped",[1604,1607]],[[64718,64718],"mapped",[1605,1580]],[[64719,64719],"mapped",[1605,1581]],[[64720,64720],"mapped",[1605,1582]],[[64721,64721],"mapped",[1605,1605]],[[64722,64722],"mapped",[1606,1580]],[[64723,64723],"mapped",[1606,1581]],[[64724,64724],"mapped",[1606,1582]],[[64725,64725],"mapped",[1606,1605]],[[64726,64726],"mapped",[1606,1607]],[[64727,64727],"mapped",[1607,1580]],[[64728,64728],"mapped",[1607,1605]],[[64729,64729],"mapped",[1607,1648]],[[64730,64730],"mapped",[1610,1580]],[[64731,64731],"mapped",[1610,1581]],[[64732,64732],"mapped",[1610,1582]],[[64733,64733],"mapped",[1610,1605]],[[64734,64734],"mapped",[1610,1607]],[[64735,64735],"mapped",[1574,1605]],[[64736,64736],"mapped",[1574,1607]],[[64737,64737],"mapped",[1576,1605]],[[64738,64738],"mapped",[1576,1607]],[[64739,64739],"mapped",[1578,1605]],[[64740,64740],"mapped",[1578,1607]],[[64741,64741],"mapped",[1579,1605]],[[64742,64742],"mapped",[1579,1607]],[[64743,64743],"mapped",[1587,1605]],[[64744,64744],"mapped",[1587,1607]],[[64745,64745],"mapped",[1588,1605]],[[64746,64746],"mapped",[1588,1607]],[[64747,64747],"mapped",[1603,1604]],[[64748,64748],"mapped",[1603,1605]],[[64749,64749],"mapped",[1604,1605]],[[64750,64750],"mapped",[1606,1605]],[[64751,64751],"mapped",[1606,1607]],[[64752,64752],"mapped",[1610,1605]],[[64753,64753],"mapped",[1610,1607]],[[64754,64754],"mapped",[1600,1614,1617]],[[64755,64755],"mapped",[1600,1615,1617]],[[64756,64756],"mapped",[1600,1616,1617]],[[64757,64757],"mapped",[1591,1609]],[[64758,64758],"mapped",[1591,1610]],[[64759,64759],"mapped",[1593,1609]],[[64760,64760],"mapped",[1593,1610]],[[64761,64761],"mapped",[1594,1609]],[[64762,64762],"mapped",[1594,1610]],[[64763,64763],"mapped",[1587,1609]],[[64764,64764],"mapped",[1587,1610]],[[64765,64765],"mapped",[1588,1609]],[[64766,64766],"mapped",[1588,1610]],[[64767,64767],"mapped",[1581,1609]],[[64768,64768],"mapped",[1581,1610]],[[64769,64769],"mapped",[1580,1609]],[[64770,64770],"mapped",[1580,1610]],[[64771,64771],"mapped",[1582,1609]],[[64772,64772],"mapped",[1582,1610]],[[64773,64773],"mapped",[1589,1609]],[[64774,64774],"mapped",[1589,1610]],[[64775,64775],"mapped",[1590,1609]],[[64776,64776],"mapped",[1590,1610]],[[64777,64777],"mapped",[1588,1580]],[[64778,64778],"mapped",[1588,1581]],[[64779,64779],"mapped",[1588,1582]],[[64780,64780],"mapped",[1588,1605]],[[64781,64781],"mapped",[1588,1585]],[[64782,64782],"mapped",[1587,1585]],[[64783,64783],"mapped",[1589,1585]],[[64784,64784],"mapped",[1590,1585]],[[64785,64785],"mapped",[1591,1609]],[[64786,64786],"mapped",[1591,1610]],[[64787,64787],"mapped",[1593,1609]],[[64788,64788],"mapped",[1593,1610]],[[64789,64789],"mapped",[1594,1609]],[[64790,64790],"mapped",[1594,1610]],[[64791,64791],"mapped",[1587,1609]],[[64792,64792],"mapped",[1587,1610]],[[64793,64793],"mapped",[1588,1609]],[[64794,64794],"mapped",[1588,1610]],[[64795,64795],"mapped",[1581,1609]],[[64796,64796],"mapped",[1581,1610]],[[64797,64797],"mapped",[1580,1609]],[[64798,64798],"mapped",[1580,1610]],[[64799,64799],"mapped",[1582,1609]],[[64800,64800],"mapped",[1582,1610]],[[64801,64801],"mapped",[1589,1609]],[[64802,64802],"mapped",[1589,1610]],[[64803,64803],"mapped",[1590,1609]],[[64804,64804],"mapped",[1590,1610]],[[64805,64805],"mapped",[1588,1580]],[[64806,64806],"mapped",[1588,1581]],[[64807,64807],"mapped",[1588,1582]],[[64808,64808],"mapped",[1588,1605]],[[64809,64809],"mapped",[1588,1585]],[[64810,64810],"mapped",[1587,1585]],[[64811,64811],"mapped",[1589,1585]],[[64812,64812],"mapped",[1590,1585]],[[64813,64813],"mapped",[1588,1580]],[[64814,64814],"mapped",[1588,1581]],[[64815,64815],"mapped",[1588,1582]],[[64816,64816],"mapped",[1588,1605]],[[64817,64817],"mapped",[1587,1607]],[[64818,64818],"mapped",[1588,1607]],[[64819,64819],"mapped",[1591,1605]],[[64820,64820],"mapped",[1587,1580]],[[64821,64821],"mapped",[1587,1581]],[[64822,64822],"mapped",[1587,1582]],[[64823,64823],"mapped",[1588,1580]],[[64824,64824],"mapped",[1588,1581]],[[64825,64825],"mapped",[1588,1582]],[[64826,64826],"mapped",[1591,1605]],[[64827,64827],"mapped",[1592,1605]],[[64828,64829],"mapped",[1575,1611]],[[64830,64831],"valid",[],"NV8"],[[64832,64847],"disallowed"],[[64848,64848],"mapped",[1578,1580,1605]],[[64849,64850],"mapped",[1578,1581,1580]],[[64851,64851],"mapped",[1578,1581,1605]],[[64852,64852],"mapped",[1578,1582,1605]],[[64853,64853],"mapped",[1578,1605,1580]],[[64854,64854],"mapped",[1578,1605,1581]],[[64855,64855],"mapped",[1578,1605,1582]],[[64856,64857],"mapped",[1580,1605,1581]],[[64858,64858],"mapped",[1581,1605,1610]],[[64859,64859],"mapped",[1581,1605,1609]],[[64860,64860],"mapped",[1587,1581,1580]],[[64861,64861],"mapped",[1587,1580,1581]],[[64862,64862],"mapped",[1587,1580,1609]],[[64863,64864],"mapped",[1587,1605,1581]],[[64865,64865],"mapped",[1587,1605,1580]],[[64866,64867],"mapped",[1587,1605,1605]],[[64868,64869],"mapped",[1589,1581,1581]],[[64870,64870],"mapped",[1589,1605,1605]],[[64871,64872],"mapped",[1588,1581,1605]],[[64873,64873],"mapped",[1588,1580,1610]],[[64874,64875],"mapped",[1588,1605,1582]],[[64876,64877],"mapped",[1588,1605,1605]],[[64878,64878],"mapped",[1590,1581,1609]],[[64879,64880],"mapped",[1590,1582,1605]],[[64881,64882],"mapped",[1591,1605,1581]],[[64883,64883],"mapped",[1591,1605,1605]],[[64884,64884],"mapped",[1591,1605,1610]],[[64885,64885],"mapped",[1593,1580,1605]],[[64886,64887],"mapped",[1593,1605,1605]],[[64888,64888],"mapped",[1593,1605,1609]],[[64889,64889],"mapped",[1594,1605,1605]],[[64890,64890],"mapped",[1594,1605,1610]],[[64891,64891],"mapped",[1594,1605,1609]],[[64892,64893],"mapped",[1601,1582,1605]],[[64894,64894],"mapped",[1602,1605,1581]],[[64895,64895],"mapped",[1602,1605,1605]],[[64896,64896],"mapped",[1604,1581,1605]],[[64897,64897],"mapped",[1604,1581,1610]],[[64898,64898],"mapped",[1604,1581,1609]],[[64899,64900],"mapped",[1604,1580,1580]],[[64901,64902],"mapped",[1604,1582,1605]],[[64903,64904],"mapped",[1604,1605,1581]],[[64905,64905],"mapped",[1605,1581,1580]],[[64906,64906],"mapped",[1605,1581,1605]],[[64907,64907],"mapped",[1605,1581,1610]],[[64908,64908],"mapped",[1605,1580,1581]],[[64909,64909],"mapped",[1605,1580,1605]],[[64910,64910],"mapped",[1605,1582,1580]],[[64911,64911],"mapped",[1605,1582,1605]],[[64912,64913],"disallowed"],[[64914,64914],"mapped",[1605,1580,1582]],[[64915,64915],"mapped",[1607,1605,1580]],[[64916,64916],"mapped",[1607,1605,1605]],[[64917,64917],"mapped",[1606,1581,1605]],[[64918,64918],"mapped",[1606,1581,1609]],[[64919,64920],"mapped",[1606,1580,1605]],[[64921,64921],"mapped",[1606,1580,1609]],[[64922,64922],"mapped",[1606,1605,1610]],[[64923,64923],"mapped",[1606,1605,1609]],[[64924,64925],"mapped",[1610,1605,1605]],[[64926,64926],"mapped",[1576,1582,1610]],[[64927,64927],"mapped",[1578,1580,1610]],[[64928,64928],"mapped",[1578,1580,1609]],[[64929,64929],"mapped",[1578,1582,1610]],[[64930,64930],"mapped",[1578,1582,1609]],[[64931,64931],"mapped",[1578,1605,1610]],[[64932,64932],"mapped",[1578,1605,1609]],[[64933,64933],"mapped",[1580,1605,1610]],[[64934,64934],"mapped",[1580,1581,1609]],[[64935,64935],"mapped",[1580,1605,1609]],[[64936,64936],"mapped",[1587,1582,1609]],[[64937,64937],"mapped",[1589,1581,1610]],[[64938,64938],"mapped",[1588,1581,1610]],[[64939,64939],"mapped",[1590,1581,1610]],[[64940,64940],"mapped",[1604,1580,1610]],[[64941,64941],"mapped",[1604,1605,1610]],[[64942,64942],"mapped",[1610,1581,1610]],[[64943,64943],"mapped",[1610,1580,1610]],[[64944,64944],"mapped",[1610,1605,1610]],[[64945,64945],"mapped",[1605,1605,1610]],[[64946,64946],"mapped",[1602,1605,1610]],[[64947,64947],"mapped",[1606,1581,1610]],[[64948,64948],"mapped",[1602,1605,1581]],[[64949,64949],"mapped",[1604,1581,1605]],[[64950,64950],"mapped",[1593,1605,1610]],[[64951,64951],"mapped",[1603,1605,1610]],[[64952,64952],"mapped",[1606,1580,1581]],[[64953,64953],"mapped",[1605,1582,1610]],[[64954,64954],"mapped",[1604,1580,1605]],[[64955,64955],"mapped",[1603,1605,1605]],[[64956,64956],"mapped",[1604,1580,1605]],[[64957,64957],"mapped",[1606,1580,1581]],[[64958,64958],"mapped",[1580,1581,1610]],[[64959,64959],"mapped",[1581,1580,1610]],[[64960,64960],"mapped",[1605,1580,1610]],[[64961,64961],"mapped",[1601,1605,1610]],[[64962,64962],"mapped",[1576,1581,1610]],[[64963,64963],"mapped",[1603,1605,1605]],[[64964,64964],"mapped",[1593,1580,1605]],[[64965,64965],"mapped",[1589,1605,1605]],[[64966,64966],"mapped",[1587,1582,1610]],[[64967,64967],"mapped",[1606,1580,1610]],[[64968,64975],"disallowed"],[[64976,65007],"disallowed"],[[65008,65008],"mapped",[1589,1604,1746]],[[65009,65009],"mapped",[1602,1604,1746]],[[65010,65010],"mapped",[1575,1604,1604,1607]],[[65011,65011],"mapped",[1575,1603,1576,1585]],[[65012,65012],"mapped",[1605,1581,1605,1583]],[[65013,65013],"mapped",[1589,1604,1593,1605]],[[65014,65014],"mapped",[1585,1587,1608,1604]],[[65015,65015],"mapped",[1593,1604,1610,1607]],[[65016,65016],"mapped",[1608,1587,1604,1605]],[[65017,65017],"mapped",[1589,1604,1609]],[[65018,65018],"disallowed_STD3_mapped",[1589,1604,1609,32,1575,1604,1604,1607,32,1593,1604,1610,1607,32,1608,1587,1604,1605]],[[65019,65019],"disallowed_STD3_mapped",[1580,1604,32,1580,1604,1575,1604,1607]],[[65020,65020],"mapped",[1585,1740,1575,1604]],[[65021,65021],"valid",[],"NV8"],[[65022,65023],"disallowed"],[[65024,65039],"ignored"],[[65040,65040],"disallowed_STD3_mapped",[44]],[[65041,65041],"mapped",[12289]],[[65042,65042],"disallowed"],[[65043,65043],"disallowed_STD3_mapped",[58]],[[65044,65044],"disallowed_STD3_mapped",[59]],[[65045,65045],"disallowed_STD3_mapped",[33]],[[65046,65046],"disallowed_STD3_mapped",[63]],[[65047,65047],"mapped",[12310]],[[65048,65048],"mapped",[12311]],[[65049,65049],"disallowed"],[[65050,65055],"disallowed"],[[65056,65059],"valid"],[[65060,65062],"valid"],[[65063,65069],"valid"],[[65070,65071],"valid"],[[65072,65072],"disallowed"],[[65073,65073],"mapped",[8212]],[[65074,65074],"mapped",[8211]],[[65075,65076],"disallowed_STD3_mapped",[95]],[[65077,65077],"disallowed_STD3_mapped",[40]],[[65078,65078],"disallowed_STD3_mapped",[41]],[[65079,65079],"disallowed_STD3_mapped",[123]],[[65080,65080],"disallowed_STD3_mapped",[125]],[[65081,65081],"mapped",[12308]],[[65082,65082],"mapped",[12309]],[[65083,65083],"mapped",[12304]],[[65084,65084],"mapped",[12305]],[[65085,65085],"mapped",[12298]],[[65086,65086],"mapped",[12299]],[[65087,65087],"mapped",[12296]],[[65088,65088],"mapped",[12297]],[[65089,65089],"mapped",[12300]],[[65090,65090],"mapped",[12301]],[[65091,65091],"mapped",[12302]],[[65092,65092],"mapped",[12303]],[[65093,65094],"valid",[],"NV8"],[[65095,65095],"disallowed_STD3_mapped",[91]],[[65096,65096],"disallowed_STD3_mapped",[93]],[[65097,65100],"disallowed_STD3_mapped",[32,773]],[[65101,65103],"disallowed_STD3_mapped",[95]],[[65104,65104],"disallowed_STD3_mapped",[44]],[[65105,65105],"mapped",[12289]],[[65106,65106],"disallowed"],[[65107,65107],"disallowed"],[[65108,65108],"disallowed_STD3_mapped",[59]],[[65109,65109],"disallowed_STD3_mapped",[58]],[[65110,65110],"disallowed_STD3_mapped",[63]],[[65111,65111],"disallowed_STD3_mapped",[33]],[[65112,65112],"mapped",[8212]],[[65113,65113],"disallowed_STD3_mapped",[40]],[[65114,65114],"disallowed_STD3_mapped",[41]],[[65115,65115],"disallowed_STD3_mapped",[123]],[[65116,65116],"disallowed_STD3_mapped",[125]],[[65117,65117],"mapped",[12308]],[[65118,65118],"mapped",[12309]],[[65119,65119],"disallowed_STD3_mapped",[35]],[[65120,65120],"disallowed_STD3_mapped",[38]],[[65121,65121],"disallowed_STD3_mapped",[42]],[[65122,65122],"disallowed_STD3_mapped",[43]],[[65123,65123],"mapped",[45]],[[65124,65124],"disallowed_STD3_mapped",[60]],[[65125,65125],"disallowed_STD3_mapped",[62]],[[65126,65126],"disallowed_STD3_mapped",[61]],[[65127,65127],"disallowed"],[[65128,65128],"disallowed_STD3_mapped",[92]],[[65129,65129],"disallowed_STD3_mapped",[36]],[[65130,65130],"disallowed_STD3_mapped",[37]],[[65131,65131],"disallowed_STD3_mapped",[64]],[[65132,65135],"disallowed"],[[65136,65136],"disallowed_STD3_mapped",[32,1611]],[[65137,65137],"mapped",[1600,1611]],[[65138,65138],"disallowed_STD3_mapped",[32,1612]],[[65139,65139],"valid"],[[65140,65140],"disallowed_STD3_mapped",[32,1613]],[[65141,65141],"disallowed"],[[65142,65142],"disallowed_STD3_mapped",[32,1614]],[[65143,65143],"mapped",[1600,1614]],[[65144,65144],"disallowed_STD3_mapped",[32,1615]],[[65145,65145],"mapped",[1600,1615]],[[65146,65146],"disallowed_STD3_mapped",[32,1616]],[[65147,65147],"mapped",[1600,1616]],[[65148,65148],"disallowed_STD3_mapped",[32,1617]],[[65149,65149],"mapped",[1600,1617]],[[65150,65150],"disallowed_STD3_mapped",[32,1618]],[[65151,65151],"mapped",[1600,1618]],[[65152,65152],"mapped",[1569]],[[65153,65154],"mapped",[1570]],[[65155,65156],"mapped",[1571]],[[65157,65158],"mapped",[1572]],[[65159,65160],"mapped",[1573]],[[65161,65164],"mapped",[1574]],[[65165,65166],"mapped",[1575]],[[65167,65170],"mapped",[1576]],[[65171,65172],"mapped",[1577]],[[65173,65176],"mapped",[1578]],[[65177,65180],"mapped",[1579]],[[65181,65184],"mapped",[1580]],[[65185,65188],"mapped",[1581]],[[65189,65192],"mapped",[1582]],[[65193,65194],"mapped",[1583]],[[65195,65196],"mapped",[1584]],[[65197,65198],"mapped",[1585]],[[65199,65200],"mapped",[1586]],[[65201,65204],"mapped",[1587]],[[65205,65208],"mapped",[1588]],[[65209,65212],"mapped",[1589]],[[65213,65216],"mapped",[1590]],[[65217,65220],"mapped",[1591]],[[65221,65224],"mapped",[1592]],[[65225,65228],"mapped",[1593]],[[65229,65232],"mapped",[1594]],[[65233,65236],"mapped",[1601]],[[65237,65240],"mapped",[1602]],[[65241,65244],"mapped",[1603]],[[65245,65248],"mapped",[1604]],[[65249,65252],"mapped",[1605]],[[65253,65256],"mapped",[1606]],[[65257,65260],"mapped",[1607]],[[65261,65262],"mapped",[1608]],[[65263,65264],"mapped",[1609]],[[65265,65268],"mapped",[1610]],[[65269,65270],"mapped",[1604,1570]],[[65271,65272],"mapped",[1604,1571]],[[65273,65274],"mapped",[1604,1573]],[[65275,65276],"mapped",[1604,1575]],[[65277,65278],"disallowed"],[[65279,65279],"ignored"],[[65280,65280],"disallowed"],[[65281,65281],"disallowed_STD3_mapped",[33]],[[65282,65282],"disallowed_STD3_mapped",[34]],[[65283,65283],"disallowed_STD3_mapped",[35]],[[65284,65284],"disallowed_STD3_mapped",[36]],[[65285,65285],"disallowed_STD3_mapped",[37]],[[65286,65286],"disallowed_STD3_mapped",[38]],[[65287,65287],"disallowed_STD3_mapped",[39]],[[65288,65288],"disallowed_STD3_mapped",[40]],[[65289,65289],"disallowed_STD3_mapped",[41]],[[65290,65290],"disallowed_STD3_mapped",[42]],[[65291,65291],"disallowed_STD3_mapped",[43]],[[65292,65292],"disallowed_STD3_mapped",[44]],[[65293,65293],"mapped",[45]],[[65294,65294],"mapped",[46]],[[65295,65295],"disallowed_STD3_mapped",[47]],[[65296,65296],"mapped",[48]],[[65297,65297],"mapped",[49]],[[65298,65298],"mapped",[50]],[[65299,65299],"mapped",[51]],[[65300,65300],"mapped",[52]],[[65301,65301],"mapped",[53]],[[65302,65302],"mapped",[54]],[[65303,65303],"mapped",[55]],[[65304,65304],"mapped",[56]],[[65305,65305],"mapped",[57]],[[65306,65306],"disallowed_STD3_mapped",[58]],[[65307,65307],"disallowed_STD3_mapped",[59]],[[65308,65308],"disallowed_STD3_mapped",[60]],[[65309,65309],"disallowed_STD3_mapped",[61]],[[65310,65310],"disallowed_STD3_mapped",[62]],[[65311,65311],"disallowed_STD3_mapped",[63]],[[65312,65312],"disallowed_STD3_mapped",[64]],[[65313,65313],"mapped",[97]],[[65314,65314],"mapped",[98]],[[65315,65315],"mapped",[99]],[[65316,65316],"mapped",[100]],[[65317,65317],"mapped",[101]],[[65318,65318],"mapped",[102]],[[65319,65319],"mapped",[103]],[[65320,65320],"mapped",[104]],[[65321,65321],"mapped",[105]],[[65322,65322],"mapped",[106]],[[65323,65323],"mapped",[107]],[[65324,65324],"mapped",[108]],[[65325,65325],"mapped",[109]],[[65326,65326],"mapped",[110]],[[65327,65327],"mapped",[111]],[[65328,65328],"mapped",[112]],[[65329,65329],"mapped",[113]],[[65330,65330],"mapped",[114]],[[65331,65331],"mapped",[115]],[[65332,65332],"mapped",[116]],[[65333,65333],"mapped",[117]],[[65334,65334],"mapped",[118]],[[65335,65335],"mapped",[119]],[[65336,65336],"mapped",[120]],[[65337,65337],"mapped",[121]],[[65338,65338],"mapped",[122]],[[65339,65339],"disallowed_STD3_mapped",[91]],[[65340,65340],"disallowed_STD3_mapped",[92]],[[65341,65341],"disallowed_STD3_mapped",[93]],[[65342,65342],"disallowed_STD3_mapped",[94]],[[65343,65343],"disallowed_STD3_mapped",[95]],[[65344,65344],"disallowed_STD3_mapped",[96]],[[65345,65345],"mapped",[97]],[[65346,65346],"mapped",[98]],[[65347,65347],"mapped",[99]],[[65348,65348],"mapped",[100]],[[65349,65349],"mapped",[101]],[[65350,65350],"mapped",[102]],[[65351,65351],"mapped",[103]],[[65352,65352],"mapped",[104]],[[65353,65353],"mapped",[105]],[[65354,65354],"mapped",[106]],[[65355,65355],"mapped",[107]],[[65356,65356],"mapped",[108]],[[65357,65357],"mapped",[109]],[[65358,65358],"mapped",[110]],[[65359,65359],"mapped",[111]],[[65360,65360],"mapped",[112]],[[65361,65361],"mapped",[113]],[[65362,65362],"mapped",[114]],[[65363,65363],"mapped",[115]],[[65364,65364],"mapped",[116]],[[65365,65365],"mapped",[117]],[[65366,65366],"mapped",[118]],[[65367,65367],"mapped",[119]],[[65368,65368],"mapped",[120]],[[65369,65369],"mapped",[121]],[[65370,65370],"mapped",[122]],[[65371,65371],"disallowed_STD3_mapped",[123]],[[65372,65372],"disallowed_STD3_mapped",[124]],[[65373,65373],"disallowed_STD3_mapped",[125]],[[65374,65374],"disallowed_STD3_mapped",[126]],[[65375,65375],"mapped",[10629]],[[65376,65376],"mapped",[10630]],[[65377,65377],"mapped",[46]],[[65378,65378],"mapped",[12300]],[[65379,65379],"mapped",[12301]],[[65380,65380],"mapped",[12289]],[[65381,65381],"mapped",[12539]],[[65382,65382],"mapped",[12530]],[[65383,65383],"mapped",[12449]],[[65384,65384],"mapped",[12451]],[[65385,65385],"mapped",[12453]],[[65386,65386],"mapped",[12455]],[[65387,65387],"mapped",[12457]],[[65388,65388],"mapped",[12515]],[[65389,65389],"mapped",[12517]],[[65390,65390],"mapped",[12519]],[[65391,65391],"mapped",[12483]],[[65392,65392],"mapped",[12540]],[[65393,65393],"mapped",[12450]],[[65394,65394],"mapped",[12452]],[[65395,65395],"mapped",[12454]],[[65396,65396],"mapped",[12456]],[[65397,65397],"mapped",[12458]],[[65398,65398],"mapped",[12459]],[[65399,65399],"mapped",[12461]],[[65400,65400],"mapped",[12463]],[[65401,65401],"mapped",[12465]],[[65402,65402],"mapped",[12467]],[[65403,65403],"mapped",[12469]],[[65404,65404],"mapped",[12471]],[[65405,65405],"mapped",[12473]],[[65406,65406],"mapped",[12475]],[[65407,65407],"mapped",[12477]],[[65408,65408],"mapped",[12479]],[[65409,65409],"mapped",[12481]],[[65410,65410],"mapped",[12484]],[[65411,65411],"mapped",[12486]],[[65412,65412],"mapped",[12488]],[[65413,65413],"mapped",[12490]],[[65414,65414],"mapped",[12491]],[[65415,65415],"mapped",[12492]],[[65416,65416],"mapped",[12493]],[[65417,65417],"mapped",[12494]],[[65418,65418],"mapped",[12495]],[[65419,65419],"mapped",[12498]],[[65420,65420],"mapped",[12501]],[[65421,65421],"mapped",[12504]],[[65422,65422],"mapped",[12507]],[[65423,65423],"mapped",[12510]],[[65424,65424],"mapped",[12511]],[[65425,65425],"mapped",[12512]],[[65426,65426],"mapped",[12513]],[[65427,65427],"mapped",[12514]],[[65428,65428],"mapped",[12516]],[[65429,65429],"mapped",[12518]],[[65430,65430],"mapped",[12520]],[[65431,65431],"mapped",[12521]],[[65432,65432],"mapped",[12522]],[[65433,65433],"mapped",[12523]],[[65434,65434],"mapped",[12524]],[[65435,65435],"mapped",[12525]],[[65436,65436],"mapped",[12527]],[[65437,65437],"mapped",[12531]],[[65438,65438],"mapped",[12441]],[[65439,65439],"mapped",[12442]],[[65440,65440],"disallowed"],[[65441,65441],"mapped",[4352]],[[65442,65442],"mapped",[4353]],[[65443,65443],"mapped",[4522]],[[65444,65444],"mapped",[4354]],[[65445,65445],"mapped",[4524]],[[65446,65446],"mapped",[4525]],[[65447,65447],"mapped",[4355]],[[65448,65448],"mapped",[4356]],[[65449,65449],"mapped",[4357]],[[65450,65450],"mapped",[4528]],[[65451,65451],"mapped",[4529]],[[65452,65452],"mapped",[4530]],[[65453,65453],"mapped",[4531]],[[65454,65454],"mapped",[4532]],[[65455,65455],"mapped",[4533]],[[65456,65456],"mapped",[4378]],[[65457,65457],"mapped",[4358]],[[65458,65458],"mapped",[4359]],[[65459,65459],"mapped",[4360]],[[65460,65460],"mapped",[4385]],[[65461,65461],"mapped",[4361]],[[65462,65462],"mapped",[4362]],[[65463,65463],"mapped",[4363]],[[65464,65464],"mapped",[4364]],[[65465,65465],"mapped",[4365]],[[65466,65466],"mapped",[4366]],[[65467,65467],"mapped",[4367]],[[65468,65468],"mapped",[4368]],[[65469,65469],"mapped",[4369]],[[65470,65470],"mapped",[4370]],[[65471,65473],"disallowed"],[[65474,65474],"mapped",[4449]],[[65475,65475],"mapped",[4450]],[[65476,65476],"mapped",[4451]],[[65477,65477],"mapped",[4452]],[[65478,65478],"mapped",[4453]],[[65479,65479],"mapped",[4454]],[[65480,65481],"disallowed"],[[65482,65482],"mapped",[4455]],[[65483,65483],"mapped",[4456]],[[65484,65484],"mapped",[4457]],[[65485,65485],"mapped",[4458]],[[65486,65486],"mapped",[4459]],[[65487,65487],"mapped",[4460]],[[65488,65489],"disallowed"],[[65490,65490],"mapped",[4461]],[[65491,65491],"mapped",[4462]],[[65492,65492],"mapped",[4463]],[[65493,65493],"mapped",[4464]],[[65494,65494],"mapped",[4465]],[[65495,65495],"mapped",[4466]],[[65496,65497],"disallowed"],[[65498,65498],"mapped",[4467]],[[65499,65499],"mapped",[4468]],[[65500,65500],"mapped",[4469]],[[65501,65503],"disallowed"],[[65504,65504],"mapped",[162]],[[65505,65505],"mapped",[163]],[[65506,65506],"mapped",[172]],[[65507,65507],"disallowed_STD3_mapped",[32,772]],[[65508,65508],"mapped",[166]],[[65509,65509],"mapped",[165]],[[65510,65510],"mapped",[8361]],[[65511,65511],"disallowed"],[[65512,65512],"mapped",[9474]],[[65513,65513],"mapped",[8592]],[[65514,65514],"mapped",[8593]],[[65515,65515],"mapped",[8594]],[[65516,65516],"mapped",[8595]],[[65517,65517],"mapped",[9632]],[[65518,65518],"mapped",[9675]],[[65519,65528],"disallowed"],[[65529,65531],"disallowed"],[[65532,65532],"disallowed"],[[65533,65533],"disallowed"],[[65534,65535],"disallowed"],[[65536,65547],"valid"],[[65548,65548],"disallowed"],[[65549,65574],"valid"],[[65575,65575],"disallowed"],[[65576,65594],"valid"],[[65595,65595],"disallowed"],[[65596,65597],"valid"],[[65598,65598],"disallowed"],[[65599,65613],"valid"],[[65614,65615],"disallowed"],[[65616,65629],"valid"],[[65630,65663],"disallowed"],[[65664,65786],"valid"],[[65787,65791],"disallowed"],[[65792,65794],"valid",[],"NV8"],[[65795,65798],"disallowed"],[[65799,65843],"valid",[],"NV8"],[[65844,65846],"disallowed"],[[65847,65855],"valid",[],"NV8"],[[65856,65930],"valid",[],"NV8"],[[65931,65932],"valid",[],"NV8"],[[65933,65935],"disallowed"],[[65936,65947],"valid",[],"NV8"],[[65948,65951],"disallowed"],[[65952,65952],"valid",[],"NV8"],[[65953,65999],"disallowed"],[[66000,66044],"valid",[],"NV8"],[[66045,66045],"valid"],[[66046,66175],"disallowed"],[[66176,66204],"valid"],[[66205,66207],"disallowed"],[[66208,66256],"valid"],[[66257,66271],"disallowed"],[[66272,66272],"valid"],[[66273,66299],"valid",[],"NV8"],[[66300,66303],"disallowed"],[[66304,66334],"valid"],[[66335,66335],"valid"],[[66336,66339],"valid",[],"NV8"],[[66340,66351],"disallowed"],[[66352,66368],"valid"],[[66369,66369],"valid",[],"NV8"],[[66370,66377],"valid"],[[66378,66378],"valid",[],"NV8"],[[66379,66383],"disallowed"],[[66384,66426],"valid"],[[66427,66431],"disallowed"],[[66432,66461],"valid"],[[66462,66462],"disallowed"],[[66463,66463],"valid",[],"NV8"],[[66464,66499],"valid"],[[66500,66503],"disallowed"],[[66504,66511],"valid"],[[66512,66517],"valid",[],"NV8"],[[66518,66559],"disallowed"],[[66560,66560],"mapped",[66600]],[[66561,66561],"mapped",[66601]],[[66562,66562],"mapped",[66602]],[[66563,66563],"mapped",[66603]],[[66564,66564],"mapped",[66604]],[[66565,66565],"mapped",[66605]],[[66566,66566],"mapped",[66606]],[[66567,66567],"mapped",[66607]],[[66568,66568],"mapped",[66608]],[[66569,66569],"mapped",[66609]],[[66570,66570],"mapped",[66610]],[[66571,66571],"mapped",[66611]],[[66572,66572],"mapped",[66612]],[[66573,66573],"mapped",[66613]],[[66574,66574],"mapped",[66614]],[[66575,66575],"mapped",[66615]],[[66576,66576],"mapped",[66616]],[[66577,66577],"mapped",[66617]],[[66578,66578],"mapped",[66618]],[[66579,66579],"mapped",[66619]],[[66580,66580],"mapped",[66620]],[[66581,66581],"mapped",[66621]],[[66582,66582],"mapped",[66622]],[[66583,66583],"mapped",[66623]],[[66584,66584],"mapped",[66624]],[[66585,66585],"mapped",[66625]],[[66586,66586],"mapped",[66626]],[[66587,66587],"mapped",[66627]],[[66588,66588],"mapped",[66628]],[[66589,66589],"mapped",[66629]],[[66590,66590],"mapped",[66630]],[[66591,66591],"mapped",[66631]],[[66592,66592],"mapped",[66632]],[[66593,66593],"mapped",[66633]],[[66594,66594],"mapped",[66634]],[[66595,66595],"mapped",[66635]],[[66596,66596],"mapped",[66636]],[[66597,66597],"mapped",[66637]],[[66598,66598],"mapped",[66638]],[[66599,66599],"mapped",[66639]],[[66600,66637],"valid"],[[66638,66717],"valid"],[[66718,66719],"disallowed"],[[66720,66729],"valid"],[[66730,66815],"disallowed"],[[66816,66855],"valid"],[[66856,66863],"disallowed"],[[66864,66915],"valid"],[[66916,66926],"disallowed"],[[66927,66927],"valid",[],"NV8"],[[66928,67071],"disallowed"],[[67072,67382],"valid"],[[67383,67391],"disallowed"],[[67392,67413],"valid"],[[67414,67423],"disallowed"],[[67424,67431],"valid"],[[67432,67583],"disallowed"],[[67584,67589],"valid"],[[67590,67591],"disallowed"],[[67592,67592],"valid"],[[67593,67593],"disallowed"],[[67594,67637],"valid"],[[67638,67638],"disallowed"],[[67639,67640],"valid"],[[67641,67643],"disallowed"],[[67644,67644],"valid"],[[67645,67646],"disallowed"],[[67647,67647],"valid"],[[67648,67669],"valid"],[[67670,67670],"disallowed"],[[67671,67679],"valid",[],"NV8"],[[67680,67702],"valid"],[[67703,67711],"valid",[],"NV8"],[[67712,67742],"valid"],[[67743,67750],"disallowed"],[[67751,67759],"valid",[],"NV8"],[[67760,67807],"disallowed"],[[67808,67826],"valid"],[[67827,67827],"disallowed"],[[67828,67829],"valid"],[[67830,67834],"disallowed"],[[67835,67839],"valid",[],"NV8"],[[67840,67861],"valid"],[[67862,67865],"valid",[],"NV8"],[[67866,67867],"valid",[],"NV8"],[[67868,67870],"disallowed"],[[67871,67871],"valid",[],"NV8"],[[67872,67897],"valid"],[[67898,67902],"disallowed"],[[67903,67903],"valid",[],"NV8"],[[67904,67967],"disallowed"],[[67968,68023],"valid"],[[68024,68027],"disallowed"],[[68028,68029],"valid",[],"NV8"],[[68030,68031],"valid"],[[68032,68047],"valid",[],"NV8"],[[68048,68049],"disallowed"],[[68050,68095],"valid",[],"NV8"],[[68096,68099],"valid"],[[68100,68100],"disallowed"],[[68101,68102],"valid"],[[68103,68107],"disallowed"],[[68108,68115],"valid"],[[68116,68116],"disallowed"],[[68117,68119],"valid"],[[68120,68120],"disallowed"],[[68121,68147],"valid"],[[68148,68151],"disallowed"],[[68152,68154],"valid"],[[68155,68158],"disallowed"],[[68159,68159],"valid"],[[68160,68167],"valid",[],"NV8"],[[68168,68175],"disallowed"],[[68176,68184],"valid",[],"NV8"],[[68185,68191],"disallowed"],[[68192,68220],"valid"],[[68221,68223],"valid",[],"NV8"],[[68224,68252],"valid"],[[68253,68255],"valid",[],"NV8"],[[68256,68287],"disallowed"],[[68288,68295],"valid"],[[68296,68296],"valid",[],"NV8"],[[68297,68326],"valid"],[[68327,68330],"disallowed"],[[68331,68342],"valid",[],"NV8"],[[68343,68351],"disallowed"],[[68352,68405],"valid"],[[68406,68408],"disallowed"],[[68409,68415],"valid",[],"NV8"],[[68416,68437],"valid"],[[68438,68439],"disallowed"],[[68440,68447],"valid",[],"NV8"],[[68448,68466],"valid"],[[68467,68471],"disallowed"],[[68472,68479],"valid",[],"NV8"],[[68480,68497],"valid"],[[68498,68504],"disallowed"],[[68505,68508],"valid",[],"NV8"],[[68509,68520],"disallowed"],[[68521,68527],"valid",[],"NV8"],[[68528,68607],"disallowed"],[[68608,68680],"valid"],[[68681,68735],"disallowed"],[[68736,68736],"mapped",[68800]],[[68737,68737],"mapped",[68801]],[[68738,68738],"mapped",[68802]],[[68739,68739],"mapped",[68803]],[[68740,68740],"mapped",[68804]],[[68741,68741],"mapped",[68805]],[[68742,68742],"mapped",[68806]],[[68743,68743],"mapped",[68807]],[[68744,68744],"mapped",[68808]],[[68745,68745],"mapped",[68809]],[[68746,68746],"mapped",[68810]],[[68747,68747],"mapped",[68811]],[[68748,68748],"mapped",[68812]],[[68749,68749],"mapped",[68813]],[[68750,68750],"mapped",[68814]],[[68751,68751],"mapped",[68815]],[[68752,68752],"mapped",[68816]],[[68753,68753],"mapped",[68817]],[[68754,68754],"mapped",[68818]],[[68755,68755],"mapped",[68819]],[[68756,68756],"mapped",[68820]],[[68757,68757],"mapped",[68821]],[[68758,68758],"mapped",[68822]],[[68759,68759],"mapped",[68823]],[[68760,68760],"mapped",[68824]],[[68761,68761],"mapped",[68825]],[[68762,68762],"mapped",[68826]],[[68763,68763],"mapped",[68827]],[[68764,68764],"mapped",[68828]],[[68765,68765],"mapped",[68829]],[[68766,68766],"mapped",[68830]],[[68767,68767],"mapped",[68831]],[[68768,68768],"mapped",[68832]],[[68769,68769],"mapped",[68833]],[[68770,68770],"mapped",[68834]],[[68771,68771],"mapped",[68835]],[[68772,68772],"mapped",[68836]],[[68773,68773],"mapped",[68837]],[[68774,68774],"mapped",[68838]],[[68775,68775],"mapped",[68839]],[[68776,68776],"mapped",[68840]],[[68777,68777],"mapped",[68841]],[[68778,68778],"mapped",[68842]],[[68779,68779],"mapped",[68843]],[[68780,68780],"mapped",[68844]],[[68781,68781],"mapped",[68845]],[[68782,68782],"mapped",[68846]],[[68783,68783],"mapped",[68847]],[[68784,68784],"mapped",[68848]],[[68785,68785],"mapped",[68849]],[[68786,68786],"mapped",[68850]],[[68787,68799],"disallowed"],[[68800,68850],"valid"],[[68851,68857],"disallowed"],[[68858,68863],"valid",[],"NV8"],[[68864,69215],"disallowed"],[[69216,69246],"valid",[],"NV8"],[[69247,69631],"disallowed"],[[69632,69702],"valid"],[[69703,69709],"valid",[],"NV8"],[[69710,69713],"disallowed"],[[69714,69733],"valid",[],"NV8"],[[69734,69743],"valid"],[[69744,69758],"disallowed"],[[69759,69759],"valid"],[[69760,69818],"valid"],[[69819,69820],"valid",[],"NV8"],[[69821,69821],"disallowed"],[[69822,69825],"valid",[],"NV8"],[[69826,69839],"disallowed"],[[69840,69864],"valid"],[[69865,69871],"disallowed"],[[69872,69881],"valid"],[[69882,69887],"disallowed"],[[69888,69940],"valid"],[[69941,69941],"disallowed"],[[69942,69951],"valid"],[[69952,69955],"valid",[],"NV8"],[[69956,69967],"disallowed"],[[69968,70003],"valid"],[[70004,70005],"valid",[],"NV8"],[[70006,70006],"valid"],[[70007,70015],"disallowed"],[[70016,70084],"valid"],[[70085,70088],"valid",[],"NV8"],[[70089,70089],"valid",[],"NV8"],[[70090,70092],"valid"],[[70093,70093],"valid",[],"NV8"],[[70094,70095],"disallowed"],[[70096,70105],"valid"],[[70106,70106],"valid"],[[70107,70107],"valid",[],"NV8"],[[70108,70108],"valid"],[[70109,70111],"valid",[],"NV8"],[[70112,70112],"disallowed"],[[70113,70132],"valid",[],"NV8"],[[70133,70143],"disallowed"],[[70144,70161],"valid"],[[70162,70162],"disallowed"],[[70163,70199],"valid"],[[70200,70205],"valid",[],"NV8"],[[70206,70271],"disallowed"],[[70272,70278],"valid"],[[70279,70279],"disallowed"],[[70280,70280],"valid"],[[70281,70281],"disallowed"],[[70282,70285],"valid"],[[70286,70286],"disallowed"],[[70287,70301],"valid"],[[70302,70302],"disallowed"],[[70303,70312],"valid"],[[70313,70313],"valid",[],"NV8"],[[70314,70319],"disallowed"],[[70320,70378],"valid"],[[70379,70383],"disallowed"],[[70384,70393],"valid"],[[70394,70399],"disallowed"],[[70400,70400],"valid"],[[70401,70403],"valid"],[[70404,70404],"disallowed"],[[70405,70412],"valid"],[[70413,70414],"disallowed"],[[70415,70416],"valid"],[[70417,70418],"disallowed"],[[70419,70440],"valid"],[[70441,70441],"disallowed"],[[70442,70448],"valid"],[[70449,70449],"disallowed"],[[70450,70451],"valid"],[[70452,70452],"disallowed"],[[70453,70457],"valid"],[[70458,70459],"disallowed"],[[70460,70468],"valid"],[[70469,70470],"disallowed"],[[70471,70472],"valid"],[[70473,70474],"disallowed"],[[70475,70477],"valid"],[[70478,70479],"disallowed"],[[70480,70480],"valid"],[[70481,70486],"disallowed"],[[70487,70487],"valid"],[[70488,70492],"disallowed"],[[70493,70499],"valid"],[[70500,70501],"disallowed"],[[70502,70508],"valid"],[[70509,70511],"disallowed"],[[70512,70516],"valid"],[[70517,70783],"disallowed"],[[70784,70853],"valid"],[[70854,70854],"valid",[],"NV8"],[[70855,70855],"valid"],[[70856,70863],"disallowed"],[[70864,70873],"valid"],[[70874,71039],"disallowed"],[[71040,71093],"valid"],[[71094,71095],"disallowed"],[[71096,71104],"valid"],[[71105,71113],"valid",[],"NV8"],[[71114,71127],"valid",[],"NV8"],[[71128,71133],"valid"],[[71134,71167],"disallowed"],[[71168,71232],"valid"],[[71233,71235],"valid",[],"NV8"],[[71236,71236],"valid"],[[71237,71247],"disallowed"],[[71248,71257],"valid"],[[71258,71295],"disallowed"],[[71296,71351],"valid"],[[71352,71359],"disallowed"],[[71360,71369],"valid"],[[71370,71423],"disallowed"],[[71424,71449],"valid"],[[71450,71452],"disallowed"],[[71453,71467],"valid"],[[71468,71471],"disallowed"],[[71472,71481],"valid"],[[71482,71487],"valid",[],"NV8"],[[71488,71839],"disallowed"],[[71840,71840],"mapped",[71872]],[[71841,71841],"mapped",[71873]],[[71842,71842],"mapped",[71874]],[[71843,71843],"mapped",[71875]],[[71844,71844],"mapped",[71876]],[[71845,71845],"mapped",[71877]],[[71846,71846],"mapped",[71878]],[[71847,71847],"mapped",[71879]],[[71848,71848],"mapped",[71880]],[[71849,71849],"mapped",[71881]],[[71850,71850],"mapped",[71882]],[[71851,71851],"mapped",[71883]],[[71852,71852],"mapped",[71884]],[[71853,71853],"mapped",[71885]],[[71854,71854],"mapped",[71886]],[[71855,71855],"mapped",[71887]],[[71856,71856],"mapped",[71888]],[[71857,71857],"mapped",[71889]],[[71858,71858],"mapped",[71890]],[[71859,71859],"mapped",[71891]],[[71860,71860],"mapped",[71892]],[[71861,71861],"mapped",[71893]],[[71862,71862],"mapped",[71894]],[[71863,71863],"mapped",[71895]],[[71864,71864],"mapped",[71896]],[[71865,71865],"mapped",[71897]],[[71866,71866],"mapped",[71898]],[[71867,71867],"mapped",[71899]],[[71868,71868],"mapped",[71900]],[[71869,71869],"mapped",[71901]],[[71870,71870],"mapped",[71902]],[[71871,71871],"mapped",[71903]],[[71872,71913],"valid"],[[71914,71922],"valid",[],"NV8"],[[71923,71934],"disallowed"],[[71935,71935],"valid"],[[71936,72383],"disallowed"],[[72384,72440],"valid"],[[72441,73727],"disallowed"],[[73728,74606],"valid"],[[74607,74648],"valid"],[[74649,74649],"valid"],[[74650,74751],"disallowed"],[[74752,74850],"valid",[],"NV8"],[[74851,74862],"valid",[],"NV8"],[[74863,74863],"disallowed"],[[74864,74867],"valid",[],"NV8"],[[74868,74868],"valid",[],"NV8"],[[74869,74879],"disallowed"],[[74880,75075],"valid"],[[75076,77823],"disallowed"],[[77824,78894],"valid"],[[78895,82943],"disallowed"],[[82944,83526],"valid"],[[83527,92159],"disallowed"],[[92160,92728],"valid"],[[92729,92735],"disallowed"],[[92736,92766],"valid"],[[92767,92767],"disallowed"],[[92768,92777],"valid"],[[92778,92781],"disallowed"],[[92782,92783],"valid",[],"NV8"],[[92784,92879],"disallowed"],[[92880,92909],"valid"],[[92910,92911],"disallowed"],[[92912,92916],"valid"],[[92917,92917],"valid",[],"NV8"],[[92918,92927],"disallowed"],[[92928,92982],"valid"],[[92983,92991],"valid",[],"NV8"],[[92992,92995],"valid"],[[92996,92997],"valid",[],"NV8"],[[92998,93007],"disallowed"],[[93008,93017],"valid"],[[93018,93018],"disallowed"],[[93019,93025],"valid",[],"NV8"],[[93026,93026],"disallowed"],[[93027,93047],"valid"],[[93048,93052],"disallowed"],[[93053,93071],"valid"],[[93072,93951],"disallowed"],[[93952,94020],"valid"],[[94021,94031],"disallowed"],[[94032,94078],"valid"],[[94079,94094],"disallowed"],[[94095,94111],"valid"],[[94112,110591],"disallowed"],[[110592,110593],"valid"],[[110594,113663],"disallowed"],[[113664,113770],"valid"],[[113771,113775],"disallowed"],[[113776,113788],"valid"],[[113789,113791],"disallowed"],[[113792,113800],"valid"],[[113801,113807],"disallowed"],[[113808,113817],"valid"],[[113818,113819],"disallowed"],[[113820,113820],"valid",[],"NV8"],[[113821,113822],"valid"],[[113823,113823],"valid",[],"NV8"],[[113824,113827],"ignored"],[[113828,118783],"disallowed"],[[118784,119029],"valid",[],"NV8"],[[119030,119039],"disallowed"],[[119040,119078],"valid",[],"NV8"],[[119079,119080],"disallowed"],[[119081,119081],"valid",[],"NV8"],[[119082,119133],"valid",[],"NV8"],[[119134,119134],"mapped",[119127,119141]],[[119135,119135],"mapped",[119128,119141]],[[119136,119136],"mapped",[119128,119141,119150]],[[119137,119137],"mapped",[119128,119141,119151]],[[119138,119138],"mapped",[119128,119141,119152]],[[119139,119139],"mapped",[119128,119141,119153]],[[119140,119140],"mapped",[119128,119141,119154]],[[119141,119154],"valid",[],"NV8"],[[119155,119162],"disallowed"],[[119163,119226],"valid",[],"NV8"],[[119227,119227],"mapped",[119225,119141]],[[119228,119228],"mapped",[119226,119141]],[[119229,119229],"mapped",[119225,119141,119150]],[[119230,119230],"mapped",[119226,119141,119150]],[[119231,119231],"mapped",[119225,119141,119151]],[[119232,119232],"mapped",[119226,119141,119151]],[[119233,119261],"valid",[],"NV8"],[[119262,119272],"valid",[],"NV8"],[[119273,119295],"disallowed"],[[119296,119365],"valid",[],"NV8"],[[119366,119551],"disallowed"],[[119552,119638],"valid",[],"NV8"],[[119639,119647],"disallowed"],[[119648,119665],"valid",[],"NV8"],[[119666,119807],"disallowed"],[[119808,119808],"mapped",[97]],[[119809,119809],"mapped",[98]],[[119810,119810],"mapped",[99]],[[119811,119811],"mapped",[100]],[[119812,119812],"mapped",[101]],[[119813,119813],"mapped",[102]],[[119814,119814],"mapped",[103]],[[119815,119815],"mapped",[104]],[[119816,119816],"mapped",[105]],[[119817,119817],"mapped",[106]],[[119818,119818],"mapped",[107]],[[119819,119819],"mapped",[108]],[[119820,119820],"mapped",[109]],[[119821,119821],"mapped",[110]],[[119822,119822],"mapped",[111]],[[119823,119823],"mapped",[112]],[[119824,119824],"mapped",[113]],[[119825,119825],"mapped",[114]],[[119826,119826],"mapped",[115]],[[119827,119827],"mapped",[116]],[[119828,119828],"mapped",[117]],[[119829,119829],"mapped",[118]],[[119830,119830],"mapped",[119]],[[119831,119831],"mapped",[120]],[[119832,119832],"mapped",[121]],[[119833,119833],"mapped",[122]],[[119834,119834],"mapped",[97]],[[119835,119835],"mapped",[98]],[[119836,119836],"mapped",[99]],[[119837,119837],"mapped",[100]],[[119838,119838],"mapped",[101]],[[119839,119839],"mapped",[102]],[[119840,119840],"mapped",[103]],[[119841,119841],"mapped",[104]],[[119842,119842],"mapped",[105]],[[119843,119843],"mapped",[106]],[[119844,119844],"mapped",[107]],[[119845,119845],"mapped",[108]],[[119846,119846],"mapped",[109]],[[119847,119847],"mapped",[110]],[[119848,119848],"mapped",[111]],[[119849,119849],"mapped",[112]],[[119850,119850],"mapped",[113]],[[119851,119851],"mapped",[114]],[[119852,119852],"mapped",[115]],[[119853,119853],"mapped",[116]],[[119854,119854],"mapped",[117]],[[119855,119855],"mapped",[118]],[[119856,119856],"mapped",[119]],[[119857,119857],"mapped",[120]],[[119858,119858],"mapped",[121]],[[119859,119859],"mapped",[122]],[[119860,119860],"mapped",[97]],[[119861,119861],"mapped",[98]],[[119862,119862],"mapped",[99]],[[119863,119863],"mapped",[100]],[[119864,119864],"mapped",[101]],[[119865,119865],"mapped",[102]],[[119866,119866],"mapped",[103]],[[119867,119867],"mapped",[104]],[[119868,119868],"mapped",[105]],[[119869,119869],"mapped",[106]],[[119870,119870],"mapped",[107]],[[119871,119871],"mapped",[108]],[[119872,119872],"mapped",[109]],[[119873,119873],"mapped",[110]],[[119874,119874],"mapped",[111]],[[119875,119875],"mapped",[112]],[[119876,119876],"mapped",[113]],[[119877,119877],"mapped",[114]],[[119878,119878],"mapped",[115]],[[119879,119879],"mapped",[116]],[[119880,119880],"mapped",[117]],[[119881,119881],"mapped",[118]],[[119882,119882],"mapped",[119]],[[119883,119883],"mapped",[120]],[[119884,119884],"mapped",[121]],[[119885,119885],"mapped",[122]],[[119886,119886],"mapped",[97]],[[119887,119887],"mapped",[98]],[[119888,119888],"mapped",[99]],[[119889,119889],"mapped",[100]],[[119890,119890],"mapped",[101]],[[119891,119891],"mapped",[102]],[[119892,119892],"mapped",[103]],[[119893,119893],"disallowed"],[[119894,119894],"mapped",[105]],[[119895,119895],"mapped",[106]],[[119896,119896],"mapped",[107]],[[119897,119897],"mapped",[108]],[[119898,119898],"mapped",[109]],[[119899,119899],"mapped",[110]],[[119900,119900],"mapped",[111]],[[119901,119901],"mapped",[112]],[[119902,119902],"mapped",[113]],[[119903,119903],"mapped",[114]],[[119904,119904],"mapped",[115]],[[119905,119905],"mapped",[116]],[[119906,119906],"mapped",[117]],[[119907,119907],"mapped",[118]],[[119908,119908],"mapped",[119]],[[119909,119909],"mapped",[120]],[[119910,119910],"mapped",[121]],[[119911,119911],"mapped",[122]],[[119912,119912],"mapped",[97]],[[119913,119913],"mapped",[98]],[[119914,119914],"mapped",[99]],[[119915,119915],"mapped",[100]],[[119916,119916],"mapped",[101]],[[119917,119917],"mapped",[102]],[[119918,119918],"mapped",[103]],[[119919,119919],"mapped",[104]],[[119920,119920],"mapped",[105]],[[119921,119921],"mapped",[106]],[[119922,119922],"mapped",[107]],[[119923,119923],"mapped",[108]],[[119924,119924],"mapped",[109]],[[119925,119925],"mapped",[110]],[[119926,119926],"mapped",[111]],[[119927,119927],"mapped",[112]],[[119928,119928],"mapped",[113]],[[119929,119929],"mapped",[114]],[[119930,119930],"mapped",[115]],[[119931,119931],"mapped",[116]],[[119932,119932],"mapped",[117]],[[119933,119933],"mapped",[118]],[[119934,119934],"mapped",[119]],[[119935,119935],"mapped",[120]],[[119936,119936],"mapped",[121]],[[119937,119937],"mapped",[122]],[[119938,119938],"mapped",[97]],[[119939,119939],"mapped",[98]],[[119940,119940],"mapped",[99]],[[119941,119941],"mapped",[100]],[[119942,119942],"mapped",[101]],[[119943,119943],"mapped",[102]],[[119944,119944],"mapped",[103]],[[119945,119945],"mapped",[104]],[[119946,119946],"mapped",[105]],[[119947,119947],"mapped",[106]],[[119948,119948],"mapped",[107]],[[119949,119949],"mapped",[108]],[[119950,119950],"mapped",[109]],[[119951,119951],"mapped",[110]],[[119952,119952],"mapped",[111]],[[119953,119953],"mapped",[112]],[[119954,119954],"mapped",[113]],[[119955,119955],"mapped",[114]],[[119956,119956],"mapped",[115]],[[119957,119957],"mapped",[116]],[[119958,119958],"mapped",[117]],[[119959,119959],"mapped",[118]],[[119960,119960],"mapped",[119]],[[119961,119961],"mapped",[120]],[[119962,119962],"mapped",[121]],[[119963,119963],"mapped",[122]],[[119964,119964],"mapped",[97]],[[119965,119965],"disallowed"],[[119966,119966],"mapped",[99]],[[119967,119967],"mapped",[100]],[[119968,119969],"disallowed"],[[119970,119970],"mapped",[103]],[[119971,119972],"disallowed"],[[119973,119973],"mapped",[106]],[[119974,119974],"mapped",[107]],[[119975,119976],"disallowed"],[[119977,119977],"mapped",[110]],[[119978,119978],"mapped",[111]],[[119979,119979],"mapped",[112]],[[119980,119980],"mapped",[113]],[[119981,119981],"disallowed"],[[119982,119982],"mapped",[115]],[[119983,119983],"mapped",[116]],[[119984,119984],"mapped",[117]],[[119985,119985],"mapped",[118]],[[119986,119986],"mapped",[119]],[[119987,119987],"mapped",[120]],[[119988,119988],"mapped",[121]],[[119989,119989],"mapped",[122]],[[119990,119990],"mapped",[97]],[[119991,119991],"mapped",[98]],[[119992,119992],"mapped",[99]],[[119993,119993],"mapped",[100]],[[119994,119994],"disallowed"],[[119995,119995],"mapped",[102]],[[119996,119996],"disallowed"],[[119997,119997],"mapped",[104]],[[119998,119998],"mapped",[105]],[[119999,119999],"mapped",[106]],[[120000,120000],"mapped",[107]],[[120001,120001],"mapped",[108]],[[120002,120002],"mapped",[109]],[[120003,120003],"mapped",[110]],[[120004,120004],"disallowed"],[[120005,120005],"mapped",[112]],[[120006,120006],"mapped",[113]],[[120007,120007],"mapped",[114]],[[120008,120008],"mapped",[115]],[[120009,120009],"mapped",[116]],[[120010,120010],"mapped",[117]],[[120011,120011],"mapped",[118]],[[120012,120012],"mapped",[119]],[[120013,120013],"mapped",[120]],[[120014,120014],"mapped",[121]],[[120015,120015],"mapped",[122]],[[120016,120016],"mapped",[97]],[[120017,120017],"mapped",[98]],[[120018,120018],"mapped",[99]],[[120019,120019],"mapped",[100]],[[120020,120020],"mapped",[101]],[[120021,120021],"mapped",[102]],[[120022,120022],"mapped",[103]],[[120023,120023],"mapped",[104]],[[120024,120024],"mapped",[105]],[[120025,120025],"mapped",[106]],[[120026,120026],"mapped",[107]],[[120027,120027],"mapped",[108]],[[120028,120028],"mapped",[109]],[[120029,120029],"mapped",[110]],[[120030,120030],"mapped",[111]],[[120031,120031],"mapped",[112]],[[120032,120032],"mapped",[113]],[[120033,120033],"mapped",[114]],[[120034,120034],"mapped",[115]],[[120035,120035],"mapped",[116]],[[120036,120036],"mapped",[117]],[[120037,120037],"mapped",[118]],[[120038,120038],"mapped",[119]],[[120039,120039],"mapped",[120]],[[120040,120040],"mapped",[121]],[[120041,120041],"mapped",[122]],[[120042,120042],"mapped",[97]],[[120043,120043],"mapped",[98]],[[120044,120044],"mapped",[99]],[[120045,120045],"mapped",[100]],[[120046,120046],"mapped",[101]],[[120047,120047],"mapped",[102]],[[120048,120048],"mapped",[103]],[[120049,120049],"mapped",[104]],[[120050,120050],"mapped",[105]],[[120051,120051],"mapped",[106]],[[120052,120052],"mapped",[107]],[[120053,120053],"mapped",[108]],[[120054,120054],"mapped",[109]],[[120055,120055],"mapped",[110]],[[120056,120056],"mapped",[111]],[[120057,120057],"mapped",[112]],[[120058,120058],"mapped",[113]],[[120059,120059],"mapped",[114]],[[120060,120060],"mapped",[115]],[[120061,120061],"mapped",[116]],[[120062,120062],"mapped",[117]],[[120063,120063],"mapped",[118]],[[120064,120064],"mapped",[119]],[[120065,120065],"mapped",[120]],[[120066,120066],"mapped",[121]],[[120067,120067],"mapped",[122]],[[120068,120068],"mapped",[97]],[[120069,120069],"mapped",[98]],[[120070,120070],"disallowed"],[[120071,120071],"mapped",[100]],[[120072,120072],"mapped",[101]],[[120073,120073],"mapped",[102]],[[120074,120074],"mapped",[103]],[[120075,120076],"disallowed"],[[120077,120077],"mapped",[106]],[[120078,120078],"mapped",[107]],[[120079,120079],"mapped",[108]],[[120080,120080],"mapped",[109]],[[120081,120081],"mapped",[110]],[[120082,120082],"mapped",[111]],[[120083,120083],"mapped",[112]],[[120084,120084],"mapped",[113]],[[120085,120085],"disallowed"],[[120086,120086],"mapped",[115]],[[120087,120087],"mapped",[116]],[[120088,120088],"mapped",[117]],[[120089,120089],"mapped",[118]],[[120090,120090],"mapped",[119]],[[120091,120091],"mapped",[120]],[[120092,120092],"mapped",[121]],[[120093,120093],"disallowed"],[[120094,120094],"mapped",[97]],[[120095,120095],"mapped",[98]],[[120096,120096],"mapped",[99]],[[120097,120097],"mapped",[100]],[[120098,120098],"mapped",[101]],[[120099,120099],"mapped",[102]],[[120100,120100],"mapped",[103]],[[120101,120101],"mapped",[104]],[[120102,120102],"mapped",[105]],[[120103,120103],"mapped",[106]],[[120104,120104],"mapped",[107]],[[120105,120105],"mapped",[108]],[[120106,120106],"mapped",[109]],[[120107,120107],"mapped",[110]],[[120108,120108],"mapped",[111]],[[120109,120109],"mapped",[112]],[[120110,120110],"mapped",[113]],[[120111,120111],"mapped",[114]],[[120112,120112],"mapped",[115]],[[120113,120113],"mapped",[116]],[[120114,120114],"mapped",[117]],[[120115,120115],"mapped",[118]],[[120116,120116],"mapped",[119]],[[120117,120117],"mapped",[120]],[[120118,120118],"mapped",[121]],[[120119,120119],"mapped",[122]],[[120120,120120],"mapped",[97]],[[120121,120121],"mapped",[98]],[[120122,120122],"disallowed"],[[120123,120123],"mapped",[100]],[[120124,120124],"mapped",[101]],[[120125,120125],"mapped",[102]],[[120126,120126],"mapped",[103]],[[120127,120127],"disallowed"],[[120128,120128],"mapped",[105]],[[120129,120129],"mapped",[106]],[[120130,120130],"mapped",[107]],[[120131,120131],"mapped",[108]],[[120132,120132],"mapped",[109]],[[120133,120133],"disallowed"],[[120134,120134],"mapped",[111]],[[120135,120137],"disallowed"],[[120138,120138],"mapped",[115]],[[120139,120139],"mapped",[116]],[[120140,120140],"mapped",[117]],[[120141,120141],"mapped",[118]],[[120142,120142],"mapped",[119]],[[120143,120143],"mapped",[120]],[[120144,120144],"mapped",[121]],[[120145,120145],"disallowed"],[[120146,120146],"mapped",[97]],[[120147,120147],"mapped",[98]],[[120148,120148],"mapped",[99]],[[120149,120149],"mapped",[100]],[[120150,120150],"mapped",[101]],[[120151,120151],"mapped",[102]],[[120152,120152],"mapped",[103]],[[120153,120153],"mapped",[104]],[[120154,120154],"mapped",[105]],[[120155,120155],"mapped",[106]],[[120156,120156],"mapped",[107]],[[120157,120157],"mapped",[108]],[[120158,120158],"mapped",[109]],[[120159,120159],"mapped",[110]],[[120160,120160],"mapped",[111]],[[120161,120161],"mapped",[112]],[[120162,120162],"mapped",[113]],[[120163,120163],"mapped",[114]],[[120164,120164],"mapped",[115]],[[120165,120165],"mapped",[116]],[[120166,120166],"mapped",[117]],[[120167,120167],"mapped",[118]],[[120168,120168],"mapped",[119]],[[120169,120169],"mapped",[120]],[[120170,120170],"mapped",[121]],[[120171,120171],"mapped",[122]],[[120172,120172],"mapped",[97]],[[120173,120173],"mapped",[98]],[[120174,120174],"mapped",[99]],[[120175,120175],"mapped",[100]],[[120176,120176],"mapped",[101]],[[120177,120177],"mapped",[102]],[[120178,120178],"mapped",[103]],[[120179,120179],"mapped",[104]],[[120180,120180],"mapped",[105]],[[120181,120181],"mapped",[106]],[[120182,120182],"mapped",[107]],[[120183,120183],"mapped",[108]],[[120184,120184],"mapped",[109]],[[120185,120185],"mapped",[110]],[[120186,120186],"mapped",[111]],[[120187,120187],"mapped",[112]],[[120188,120188],"mapped",[113]],[[120189,120189],"mapped",[114]],[[120190,120190],"mapped",[115]],[[120191,120191],"mapped",[116]],[[120192,120192],"mapped",[117]],[[120193,120193],"mapped",[118]],[[120194,120194],"mapped",[119]],[[120195,120195],"mapped",[120]],[[120196,120196],"mapped",[121]],[[120197,120197],"mapped",[122]],[[120198,120198],"mapped",[97]],[[120199,120199],"mapped",[98]],[[120200,120200],"mapped",[99]],[[120201,120201],"mapped",[100]],[[120202,120202],"mapped",[101]],[[120203,120203],"mapped",[102]],[[120204,120204],"mapped",[103]],[[120205,120205],"mapped",[104]],[[120206,120206],"mapped",[105]],[[120207,120207],"mapped",[106]],[[120208,120208],"mapped",[107]],[[120209,120209],"mapped",[108]],[[120210,120210],"mapped",[109]],[[120211,120211],"mapped",[110]],[[120212,120212],"mapped",[111]],[[120213,120213],"mapped",[112]],[[120214,120214],"mapped",[113]],[[120215,120215],"mapped",[114]],[[120216,120216],"mapped",[115]],[[120217,120217],"mapped",[116]],[[120218,120218],"mapped",[117]],[[120219,120219],"mapped",[118]],[[120220,120220],"mapped",[119]],[[120221,120221],"mapped",[120]],[[120222,120222],"mapped",[121]],[[120223,120223],"mapped",[122]],[[120224,120224],"mapped",[97]],[[120225,120225],"mapped",[98]],[[120226,120226],"mapped",[99]],[[120227,120227],"mapped",[100]],[[120228,120228],"mapped",[101]],[[120229,120229],"mapped",[102]],[[120230,120230],"mapped",[103]],[[120231,120231],"mapped",[104]],[[120232,120232],"mapped",[105]],[[120233,120233],"mapped",[106]],[[120234,120234],"mapped",[107]],[[120235,120235],"mapped",[108]],[[120236,120236],"mapped",[109]],[[120237,120237],"mapped",[110]],[[120238,120238],"mapped",[111]],[[120239,120239],"mapped",[112]],[[120240,120240],"mapped",[113]],[[120241,120241],"mapped",[114]],[[120242,120242],"mapped",[115]],[[120243,120243],"mapped",[116]],[[120244,120244],"mapped",[117]],[[120245,120245],"mapped",[118]],[[120246,120246],"mapped",[119]],[[120247,120247],"mapped",[120]],[[120248,120248],"mapped",[121]],[[120249,120249],"mapped",[122]],[[120250,120250],"mapped",[97]],[[120251,120251],"mapped",[98]],[[120252,120252],"mapped",[99]],[[120253,120253],"mapped",[100]],[[120254,120254],"mapped",[101]],[[120255,120255],"mapped",[102]],[[120256,120256],"mapped",[103]],[[120257,120257],"mapped",[104]],[[120258,120258],"mapped",[105]],[[120259,120259],"mapped",[106]],[[120260,120260],"mapped",[107]],[[120261,120261],"mapped",[108]],[[120262,120262],"mapped",[109]],[[120263,120263],"mapped",[110]],[[120264,120264],"mapped",[111]],[[120265,120265],"mapped",[112]],[[120266,120266],"mapped",[113]],[[120267,120267],"mapped",[114]],[[120268,120268],"mapped",[115]],[[120269,120269],"mapped",[116]],[[120270,120270],"mapped",[117]],[[120271,120271],"mapped",[118]],[[120272,120272],"mapped",[119]],[[120273,120273],"mapped",[120]],[[120274,120274],"mapped",[121]],[[120275,120275],"mapped",[122]],[[120276,120276],"mapped",[97]],[[120277,120277],"mapped",[98]],[[120278,120278],"mapped",[99]],[[120279,120279],"mapped",[100]],[[120280,120280],"mapped",[101]],[[120281,120281],"mapped",[102]],[[120282,120282],"mapped",[103]],[[120283,120283],"mapped",[104]],[[120284,120284],"mapped",[105]],[[120285,120285],"mapped",[106]],[[120286,120286],"mapped",[107]],[[120287,120287],"mapped",[108]],[[120288,120288],"mapped",[109]],[[120289,120289],"mapped",[110]],[[120290,120290],"mapped",[111]],[[120291,120291],"mapped",[112]],[[120292,120292],"mapped",[113]],[[120293,120293],"mapped",[114]],[[120294,120294],"mapped",[115]],[[120295,120295],"mapped",[116]],[[120296,120296],"mapped",[117]],[[120297,120297],"mapped",[118]],[[120298,120298],"mapped",[119]],[[120299,120299],"mapped",[120]],[[120300,120300],"mapped",[121]],[[120301,120301],"mapped",[122]],[[120302,120302],"mapped",[97]],[[120303,120303],"mapped",[98]],[[120304,120304],"mapped",[99]],[[120305,120305],"mapped",[100]],[[120306,120306],"mapped",[101]],[[120307,120307],"mapped",[102]],[[120308,120308],"mapped",[103]],[[120309,120309],"mapped",[104]],[[120310,120310],"mapped",[105]],[[120311,120311],"mapped",[106]],[[120312,120312],"mapped",[107]],[[120313,120313],"mapped",[108]],[[120314,120314],"mapped",[109]],[[120315,120315],"mapped",[110]],[[120316,120316],"mapped",[111]],[[120317,120317],"mapped",[112]],[[120318,120318],"mapped",[113]],[[120319,120319],"mapped",[114]],[[120320,120320],"mapped",[115]],[[120321,120321],"mapped",[116]],[[120322,120322],"mapped",[117]],[[120323,120323],"mapped",[118]],[[120324,120324],"mapped",[119]],[[120325,120325],"mapped",[120]],[[120326,120326],"mapped",[121]],[[120327,120327],"mapped",[122]],[[120328,120328],"mapped",[97]],[[120329,120329],"mapped",[98]],[[120330,120330],"mapped",[99]],[[120331,120331],"mapped",[100]],[[120332,120332],"mapped",[101]],[[120333,120333],"mapped",[102]],[[120334,120334],"mapped",[103]],[[120335,120335],"mapped",[104]],[[120336,120336],"mapped",[105]],[[120337,120337],"mapped",[106]],[[120338,120338],"mapped",[107]],[[120339,120339],"mapped",[108]],[[120340,120340],"mapped",[109]],[[120341,120341],"mapped",[110]],[[120342,120342],"mapped",[111]],[[120343,120343],"mapped",[112]],[[120344,120344],"mapped",[113]],[[120345,120345],"mapped",[114]],[[120346,120346],"mapped",[115]],[[120347,120347],"mapped",[116]],[[120348,120348],"mapped",[117]],[[120349,120349],"mapped",[118]],[[120350,120350],"mapped",[119]],[[120351,120351],"mapped",[120]],[[120352,120352],"mapped",[121]],[[120353,120353],"mapped",[122]],[[120354,120354],"mapped",[97]],[[120355,120355],"mapped",[98]],[[120356,120356],"mapped",[99]],[[120357,120357],"mapped",[100]],[[120358,120358],"mapped",[101]],[[120359,120359],"mapped",[102]],[[120360,120360],"mapped",[103]],[[120361,120361],"mapped",[104]],[[120362,120362],"mapped",[105]],[[120363,120363],"mapped",[106]],[[120364,120364],"mapped",[107]],[[120365,120365],"mapped",[108]],[[120366,120366],"mapped",[109]],[[120367,120367],"mapped",[110]],[[120368,120368],"mapped",[111]],[[120369,120369],"mapped",[112]],[[120370,120370],"mapped",[113]],[[120371,120371],"mapped",[114]],[[120372,120372],"mapped",[115]],[[120373,120373],"mapped",[116]],[[120374,120374],"mapped",[117]],[[120375,120375],"mapped",[118]],[[120376,120376],"mapped",[119]],[[120377,120377],"mapped",[120]],[[120378,120378],"mapped",[121]],[[120379,120379],"mapped",[122]],[[120380,120380],"mapped",[97]],[[120381,120381],"mapped",[98]],[[120382,120382],"mapped",[99]],[[120383,120383],"mapped",[100]],[[120384,120384],"mapped",[101]],[[120385,120385],"mapped",[102]],[[120386,120386],"mapped",[103]],[[120387,120387],"mapped",[104]],[[120388,120388],"mapped",[105]],[[120389,120389],"mapped",[106]],[[120390,120390],"mapped",[107]],[[120391,120391],"mapped",[108]],[[120392,120392],"mapped",[109]],[[120393,120393],"mapped",[110]],[[120394,120394],"mapped",[111]],[[120395,120395],"mapped",[112]],[[120396,120396],"mapped",[113]],[[120397,120397],"mapped",[114]],[[120398,120398],"mapped",[115]],[[120399,120399],"mapped",[116]],[[120400,120400],"mapped",[117]],[[120401,120401],"mapped",[118]],[[120402,120402],"mapped",[119]],[[120403,120403],"mapped",[120]],[[120404,120404],"mapped",[121]],[[120405,120405],"mapped",[122]],[[120406,120406],"mapped",[97]],[[120407,120407],"mapped",[98]],[[120408,120408],"mapped",[99]],[[120409,120409],"mapped",[100]],[[120410,120410],"mapped",[101]],[[120411,120411],"mapped",[102]],[[120412,120412],"mapped",[103]],[[120413,120413],"mapped",[104]],[[120414,120414],"mapped",[105]],[[120415,120415],"mapped",[106]],[[120416,120416],"mapped",[107]],[[120417,120417],"mapped",[108]],[[120418,120418],"mapped",[109]],[[120419,120419],"mapped",[110]],[[120420,120420],"mapped",[111]],[[120421,120421],"mapped",[112]],[[120422,120422],"mapped",[113]],[[120423,120423],"mapped",[114]],[[120424,120424],"mapped",[115]],[[120425,120425],"mapped",[116]],[[120426,120426],"mapped",[117]],[[120427,120427],"mapped",[118]],[[120428,120428],"mapped",[119]],[[120429,120429],"mapped",[120]],[[120430,120430],"mapped",[121]],[[120431,120431],"mapped",[122]],[[120432,120432],"mapped",[97]],[[120433,120433],"mapped",[98]],[[120434,120434],"mapped",[99]],[[120435,120435],"mapped",[100]],[[120436,120436],"mapped",[101]],[[120437,120437],"mapped",[102]],[[120438,120438],"mapped",[103]],[[120439,120439],"mapped",[104]],[[120440,120440],"mapped",[105]],[[120441,120441],"mapped",[106]],[[120442,120442],"mapped",[107]],[[120443,120443],"mapped",[108]],[[120444,120444],"mapped",[109]],[[120445,120445],"mapped",[110]],[[120446,120446],"mapped",[111]],[[120447,120447],"mapped",[112]],[[120448,120448],"mapped",[113]],[[120449,120449],"mapped",[114]],[[120450,120450],"mapped",[115]],[[120451,120451],"mapped",[116]],[[120452,120452],"mapped",[117]],[[120453,120453],"mapped",[118]],[[120454,120454],"mapped",[119]],[[120455,120455],"mapped",[120]],[[120456,120456],"mapped",[121]],[[120457,120457],"mapped",[122]],[[120458,120458],"mapped",[97]],[[120459,120459],"mapped",[98]],[[120460,120460],"mapped",[99]],[[120461,120461],"mapped",[100]],[[120462,120462],"mapped",[101]],[[120463,120463],"mapped",[102]],[[120464,120464],"mapped",[103]],[[120465,120465],"mapped",[104]],[[120466,120466],"mapped",[105]],[[120467,120467],"mapped",[106]],[[120468,120468],"mapped",[107]],[[120469,120469],"mapped",[108]],[[120470,120470],"mapped",[109]],[[120471,120471],"mapped",[110]],[[120472,120472],"mapped",[111]],[[120473,120473],"mapped",[112]],[[120474,120474],"mapped",[113]],[[120475,120475],"mapped",[114]],[[120476,120476],"mapped",[115]],[[120477,120477],"mapped",[116]],[[120478,120478],"mapped",[117]],[[120479,120479],"mapped",[118]],[[120480,120480],"mapped",[119]],[[120481,120481],"mapped",[120]],[[120482,120482],"mapped",[121]],[[120483,120483],"mapped",[122]],[[120484,120484],"mapped",[305]],[[120485,120485],"mapped",[567]],[[120486,120487],"disallowed"],[[120488,120488],"mapped",[945]],[[120489,120489],"mapped",[946]],[[120490,120490],"mapped",[947]],[[120491,120491],"mapped",[948]],[[120492,120492],"mapped",[949]],[[120493,120493],"mapped",[950]],[[120494,120494],"mapped",[951]],[[120495,120495],"mapped",[952]],[[120496,120496],"mapped",[953]],[[120497,120497],"mapped",[954]],[[120498,120498],"mapped",[955]],[[120499,120499],"mapped",[956]],[[120500,120500],"mapped",[957]],[[120501,120501],"mapped",[958]],[[120502,120502],"mapped",[959]],[[120503,120503],"mapped",[960]],[[120504,120504],"mapped",[961]],[[120505,120505],"mapped",[952]],[[120506,120506],"mapped",[963]],[[120507,120507],"mapped",[964]],[[120508,120508],"mapped",[965]],[[120509,120509],"mapped",[966]],[[120510,120510],"mapped",[967]],[[120511,120511],"mapped",[968]],[[120512,120512],"mapped",[969]],[[120513,120513],"mapped",[8711]],[[120514,120514],"mapped",[945]],[[120515,120515],"mapped",[946]],[[120516,120516],"mapped",[947]],[[120517,120517],"mapped",[948]],[[120518,120518],"mapped",[949]],[[120519,120519],"mapped",[950]],[[120520,120520],"mapped",[951]],[[120521,120521],"mapped",[952]],[[120522,120522],"mapped",[953]],[[120523,120523],"mapped",[954]],[[120524,120524],"mapped",[955]],[[120525,120525],"mapped",[956]],[[120526,120526],"mapped",[957]],[[120527,120527],"mapped",[958]],[[120528,120528],"mapped",[959]],[[120529,120529],"mapped",[960]],[[120530,120530],"mapped",[961]],[[120531,120532],"mapped",[963]],[[120533,120533],"mapped",[964]],[[120534,120534],"mapped",[965]],[[120535,120535],"mapped",[966]],[[120536,120536],"mapped",[967]],[[120537,120537],"mapped",[968]],[[120538,120538],"mapped",[969]],[[120539,120539],"mapped",[8706]],[[120540,120540],"mapped",[949]],[[120541,120541],"mapped",[952]],[[120542,120542],"mapped",[954]],[[120543,120543],"mapped",[966]],[[120544,120544],"mapped",[961]],[[120545,120545],"mapped",[960]],[[120546,120546],"mapped",[945]],[[120547,120547],"mapped",[946]],[[120548,120548],"mapped",[947]],[[120549,120549],"mapped",[948]],[[120550,120550],"mapped",[949]],[[120551,120551],"mapped",[950]],[[120552,120552],"mapped",[951]],[[120553,120553],"mapped",[952]],[[120554,120554],"mapped",[953]],[[120555,120555],"mapped",[954]],[[120556,120556],"mapped",[955]],[[120557,120557],"mapped",[956]],[[120558,120558],"mapped",[957]],[[120559,120559],"mapped",[958]],[[120560,120560],"mapped",[959]],[[120561,120561],"mapped",[960]],[[120562,120562],"mapped",[961]],[[120563,120563],"mapped",[952]],[[120564,120564],"mapped",[963]],[[120565,120565],"mapped",[964]],[[120566,120566],"mapped",[965]],[[120567,120567],"mapped",[966]],[[120568,120568],"mapped",[967]],[[120569,120569],"mapped",[968]],[[120570,120570],"mapped",[969]],[[120571,120571],"mapped",[8711]],[[120572,120572],"mapped",[945]],[[120573,120573],"mapped",[946]],[[120574,120574],"mapped",[947]],[[120575,120575],"mapped",[948]],[[120576,120576],"mapped",[949]],[[120577,120577],"mapped",[950]],[[120578,120578],"mapped",[951]],[[120579,120579],"mapped",[952]],[[120580,120580],"mapped",[953]],[[120581,120581],"mapped",[954]],[[120582,120582],"mapped",[955]],[[120583,120583],"mapped",[956]],[[120584,120584],"mapped",[957]],[[120585,120585],"mapped",[958]],[[120586,120586],"mapped",[959]],[[120587,120587],"mapped",[960]],[[120588,120588],"mapped",[961]],[[120589,120590],"mapped",[963]],[[120591,120591],"mapped",[964]],[[120592,120592],"mapped",[965]],[[120593,120593],"mapped",[966]],[[120594,120594],"mapped",[967]],[[120595,120595],"mapped",[968]],[[120596,120596],"mapped",[969]],[[120597,120597],"mapped",[8706]],[[120598,120598],"mapped",[949]],[[120599,120599],"mapped",[952]],[[120600,120600],"mapped",[954]],[[120601,120601],"mapped",[966]],[[120602,120602],"mapped",[961]],[[120603,120603],"mapped",[960]],[[120604,120604],"mapped",[945]],[[120605,120605],"mapped",[946]],[[120606,120606],"mapped",[947]],[[120607,120607],"mapped",[948]],[[120608,120608],"mapped",[949]],[[120609,120609],"mapped",[950]],[[120610,120610],"mapped",[951]],[[120611,120611],"mapped",[952]],[[120612,120612],"mapped",[953]],[[120613,120613],"mapped",[954]],[[120614,120614],"mapped",[955]],[[120615,120615],"mapped",[956]],[[120616,120616],"mapped",[957]],[[120617,120617],"mapped",[958]],[[120618,120618],"mapped",[959]],[[120619,120619],"mapped",[960]],[[120620,120620],"mapped",[961]],[[120621,120621],"mapped",[952]],[[120622,120622],"mapped",[963]],[[120623,120623],"mapped",[964]],[[120624,120624],"mapped",[965]],[[120625,120625],"mapped",[966]],[[120626,120626],"mapped",[967]],[[120627,120627],"mapped",[968]],[[120628,120628],"mapped",[969]],[[120629,120629],"mapped",[8711]],[[120630,120630],"mapped",[945]],[[120631,120631],"mapped",[946]],[[120632,120632],"mapped",[947]],[[120633,120633],"mapped",[948]],[[120634,120634],"mapped",[949]],[[120635,120635],"mapped",[950]],[[120636,120636],"mapped",[951]],[[120637,120637],"mapped",[952]],[[120638,120638],"mapped",[953]],[[120639,120639],"mapped",[954]],[[120640,120640],"mapped",[955]],[[120641,120641],"mapped",[956]],[[120642,120642],"mapped",[957]],[[120643,120643],"mapped",[958]],[[120644,120644],"mapped",[959]],[[120645,120645],"mapped",[960]],[[120646,120646],"mapped",[961]],[[120647,120648],"mapped",[963]],[[120649,120649],"mapped",[964]],[[120650,120650],"mapped",[965]],[[120651,120651],"mapped",[966]],[[120652,120652],"mapped",[967]],[[120653,120653],"mapped",[968]],[[120654,120654],"mapped",[969]],[[120655,120655],"mapped",[8706]],[[120656,120656],"mapped",[949]],[[120657,120657],"mapped",[952]],[[120658,120658],"mapped",[954]],[[120659,120659],"mapped",[966]],[[120660,120660],"mapped",[961]],[[120661,120661],"mapped",[960]],[[120662,120662],"mapped",[945]],[[120663,120663],"mapped",[946]],[[120664,120664],"mapped",[947]],[[120665,120665],"mapped",[948]],[[120666,120666],"mapped",[949]],[[120667,120667],"mapped",[950]],[[120668,120668],"mapped",[951]],[[120669,120669],"mapped",[952]],[[120670,120670],"mapped",[953]],[[120671,120671],"mapped",[954]],[[120672,120672],"mapped",[955]],[[120673,120673],"mapped",[956]],[[120674,120674],"mapped",[957]],[[120675,120675],"mapped",[958]],[[120676,120676],"mapped",[959]],[[120677,120677],"mapped",[960]],[[120678,120678],"mapped",[961]],[[120679,120679],"mapped",[952]],[[120680,120680],"mapped",[963]],[[120681,120681],"mapped",[964]],[[120682,120682],"mapped",[965]],[[120683,120683],"mapped",[966]],[[120684,120684],"mapped",[967]],[[120685,120685],"mapped",[968]],[[120686,120686],"mapped",[969]],[[120687,120687],"mapped",[8711]],[[120688,120688],"mapped",[945]],[[120689,120689],"mapped",[946]],[[120690,120690],"mapped",[947]],[[120691,120691],"mapped",[948]],[[120692,120692],"mapped",[949]],[[120693,120693],"mapped",[950]],[[120694,120694],"mapped",[951]],[[120695,120695],"mapped",[952]],[[120696,120696],"mapped",[953]],[[120697,120697],"mapped",[954]],[[120698,120698],"mapped",[955]],[[120699,120699],"mapped",[956]],[[120700,120700],"mapped",[957]],[[120701,120701],"mapped",[958]],[[120702,120702],"mapped",[959]],[[120703,120703],"mapped",[960]],[[120704,120704],"mapped",[961]],[[120705,120706],"mapped",[963]],[[120707,120707],"mapped",[964]],[[120708,120708],"mapped",[965]],[[120709,120709],"mapped",[966]],[[120710,120710],"mapped",[967]],[[120711,120711],"mapped",[968]],[[120712,120712],"mapped",[969]],[[120713,120713],"mapped",[8706]],[[120714,120714],"mapped",[949]],[[120715,120715],"mapped",[952]],[[120716,120716],"mapped",[954]],[[120717,120717],"mapped",[966]],[[120718,120718],"mapped",[961]],[[120719,120719],"mapped",[960]],[[120720,120720],"mapped",[945]],[[120721,120721],"mapped",[946]],[[120722,120722],"mapped",[947]],[[120723,120723],"mapped",[948]],[[120724,120724],"mapped",[949]],[[120725,120725],"mapped",[950]],[[120726,120726],"mapped",[951]],[[120727,120727],"mapped",[952]],[[120728,120728],"mapped",[953]],[[120729,120729],"mapped",[954]],[[120730,120730],"mapped",[955]],[[120731,120731],"mapped",[956]],[[120732,120732],"mapped",[957]],[[120733,120733],"mapped",[958]],[[120734,120734],"mapped",[959]],[[120735,120735],"mapped",[960]],[[120736,120736],"mapped",[961]],[[120737,120737],"mapped",[952]],[[120738,120738],"mapped",[963]],[[120739,120739],"mapped",[964]],[[120740,120740],"mapped",[965]],[[120741,120741],"mapped",[966]],[[120742,120742],"mapped",[967]],[[120743,120743],"mapped",[968]],[[120744,120744],"mapped",[969]],[[120745,120745],"mapped",[8711]],[[120746,120746],"mapped",[945]],[[120747,120747],"mapped",[946]],[[120748,120748],"mapped",[947]],[[120749,120749],"mapped",[948]],[[120750,120750],"mapped",[949]],[[120751,120751],"mapped",[950]],[[120752,120752],"mapped",[951]],[[120753,120753],"mapped",[952]],[[120754,120754],"mapped",[953]],[[120755,120755],"mapped",[954]],[[120756,120756],"mapped",[955]],[[120757,120757],"mapped",[956]],[[120758,120758],"mapped",[957]],[[120759,120759],"mapped",[958]],[[120760,120760],"mapped",[959]],[[120761,120761],"mapped",[960]],[[120762,120762],"mapped",[961]],[[120763,120764],"mapped",[963]],[[120765,120765],"mapped",[964]],[[120766,120766],"mapped",[965]],[[120767,120767],"mapped",[966]],[[120768,120768],"mapped",[967]],[[120769,120769],"mapped",[968]],[[120770,120770],"mapped",[969]],[[120771,120771],"mapped",[8706]],[[120772,120772],"mapped",[949]],[[120773,120773],"mapped",[952]],[[120774,120774],"mapped",[954]],[[120775,120775],"mapped",[966]],[[120776,120776],"mapped",[961]],[[120777,120777],"mapped",[960]],[[120778,120779],"mapped",[989]],[[120780,120781],"disallowed"],[[120782,120782],"mapped",[48]],[[120783,120783],"mapped",[49]],[[120784,120784],"mapped",[50]],[[120785,120785],"mapped",[51]],[[120786,120786],"mapped",[52]],[[120787,120787],"mapped",[53]],[[120788,120788],"mapped",[54]],[[120789,120789],"mapped",[55]],[[120790,120790],"mapped",[56]],[[120791,120791],"mapped",[57]],[[120792,120792],"mapped",[48]],[[120793,120793],"mapped",[49]],[[120794,120794],"mapped",[50]],[[120795,120795],"mapped",[51]],[[120796,120796],"mapped",[52]],[[120797,120797],"mapped",[53]],[[120798,120798],"mapped",[54]],[[120799,120799],"mapped",[55]],[[120800,120800],"mapped",[56]],[[120801,120801],"mapped",[57]],[[120802,120802],"mapped",[48]],[[120803,120803],"mapped",[49]],[[120804,120804],"mapped",[50]],[[120805,120805],"mapped",[51]],[[120806,120806],"mapped",[52]],[[120807,120807],"mapped",[53]],[[120808,120808],"mapped",[54]],[[120809,120809],"mapped",[55]],[[120810,120810],"mapped",[56]],[[120811,120811],"mapped",[57]],[[120812,120812],"mapped",[48]],[[120813,120813],"mapped",[49]],[[120814,120814],"mapped",[50]],[[120815,120815],"mapped",[51]],[[120816,120816],"mapped",[52]],[[120817,120817],"mapped",[53]],[[120818,120818],"mapped",[54]],[[120819,120819],"mapped",[55]],[[120820,120820],"mapped",[56]],[[120821,120821],"mapped",[57]],[[120822,120822],"mapped",[48]],[[120823,120823],"mapped",[49]],[[120824,120824],"mapped",[50]],[[120825,120825],"mapped",[51]],[[120826,120826],"mapped",[52]],[[120827,120827],"mapped",[53]],[[120828,120828],"mapped",[54]],[[120829,120829],"mapped",[55]],[[120830,120830],"mapped",[56]],[[120831,120831],"mapped",[57]],[[120832,121343],"valid",[],"NV8"],[[121344,121398],"valid"],[[121399,121402],"valid",[],"NV8"],[[121403,121452],"valid"],[[121453,121460],"valid",[],"NV8"],[[121461,121461],"valid"],[[121462,121475],"valid",[],"NV8"],[[121476,121476],"valid"],[[121477,121483],"valid",[],"NV8"],[[121484,121498],"disallowed"],[[121499,121503],"valid"],[[121504,121504],"disallowed"],[[121505,121519],"valid"],[[121520,124927],"disallowed"],[[124928,125124],"valid"],[[125125,125126],"disallowed"],[[125127,125135],"valid",[],"NV8"],[[125136,125142],"valid"],[[125143,126463],"disallowed"],[[126464,126464],"mapped",[1575]],[[126465,126465],"mapped",[1576]],[[126466,126466],"mapped",[1580]],[[126467,126467],"mapped",[1583]],[[126468,126468],"disallowed"],[[126469,126469],"mapped",[1608]],[[126470,126470],"mapped",[1586]],[[126471,126471],"mapped",[1581]],[[126472,126472],"mapped",[1591]],[[126473,126473],"mapped",[1610]],[[126474,126474],"mapped",[1603]],[[126475,126475],"mapped",[1604]],[[126476,126476],"mapped",[1605]],[[126477,126477],"mapped",[1606]],[[126478,126478],"mapped",[1587]],[[126479,126479],"mapped",[1593]],[[126480,126480],"mapped",[1601]],[[126481,126481],"mapped",[1589]],[[126482,126482],"mapped",[1602]],[[126483,126483],"mapped",[1585]],[[126484,126484],"mapped",[1588]],[[126485,126485],"mapped",[1578]],[[126486,126486],"mapped",[1579]],[[126487,126487],"mapped",[1582]],[[126488,126488],"mapped",[1584]],[[126489,126489],"mapped",[1590]],[[126490,126490],"mapped",[1592]],[[126491,126491],"mapped",[1594]],[[126492,126492],"mapped",[1646]],[[126493,126493],"mapped",[1722]],[[126494,126494],"mapped",[1697]],[[126495,126495],"mapped",[1647]],[[126496,126496],"disallowed"],[[126497,126497],"mapped",[1576]],[[126498,126498],"mapped",[1580]],[[126499,126499],"disallowed"],[[126500,126500],"mapped",[1607]],[[126501,126502],"disallowed"],[[126503,126503],"mapped",[1581]],[[126504,126504],"disallowed"],[[126505,126505],"mapped",[1610]],[[126506,126506],"mapped",[1603]],[[126507,126507],"mapped",[1604]],[[126508,126508],"mapped",[1605]],[[126509,126509],"mapped",[1606]],[[126510,126510],"mapped",[1587]],[[126511,126511],"mapped",[1593]],[[126512,126512],"mapped",[1601]],[[126513,126513],"mapped",[1589]],[[126514,126514],"mapped",[1602]],[[126515,126515],"disallowed"],[[126516,126516],"mapped",[1588]],[[126517,126517],"mapped",[1578]],[[126518,126518],"mapped",[1579]],[[126519,126519],"mapped",[1582]],[[126520,126520],"disallowed"],[[126521,126521],"mapped",[1590]],[[126522,126522],"disallowed"],[[126523,126523],"mapped",[1594]],[[126524,126529],"disallowed"],[[126530,126530],"mapped",[1580]],[[126531,126534],"disallowed"],[[126535,126535],"mapped",[1581]],[[126536,126536],"disallowed"],[[126537,126537],"mapped",[1610]],[[126538,126538],"disallowed"],[[126539,126539],"mapped",[1604]],[[126540,126540],"disallowed"],[[126541,126541],"mapped",[1606]],[[126542,126542],"mapped",[1587]],[[126543,126543],"mapped",[1593]],[[126544,126544],"disallowed"],[[126545,126545],"mapped",[1589]],[[126546,126546],"mapped",[1602]],[[126547,126547],"disallowed"],[[126548,126548],"mapped",[1588]],[[126549,126550],"disallowed"],[[126551,126551],"mapped",[1582]],[[126552,126552],"disallowed"],[[126553,126553],"mapped",[1590]],[[126554,126554],"disallowed"],[[126555,126555],"mapped",[1594]],[[126556,126556],"disallowed"],[[126557,126557],"mapped",[1722]],[[126558,126558],"disallowed"],[[126559,126559],"mapped",[1647]],[[126560,126560],"disallowed"],[[126561,126561],"mapped",[1576]],[[126562,126562],"mapped",[1580]],[[126563,126563],"disallowed"],[[126564,126564],"mapped",[1607]],[[126565,126566],"disallowed"],[[126567,126567],"mapped",[1581]],[[126568,126568],"mapped",[1591]],[[126569,126569],"mapped",[1610]],[[126570,126570],"mapped",[1603]],[[126571,126571],"disallowed"],[[126572,126572],"mapped",[1605]],[[126573,126573],"mapped",[1606]],[[126574,126574],"mapped",[1587]],[[126575,126575],"mapped",[1593]],[[126576,126576],"mapped",[1601]],[[126577,126577],"mapped",[1589]],[[126578,126578],"mapped",[1602]],[[126579,126579],"disallowed"],[[126580,126580],"mapped",[1588]],[[126581,126581],"mapped",[1578]],[[126582,126582],"mapped",[1579]],[[126583,126583],"mapped",[1582]],[[126584,126584],"disallowed"],[[126585,126585],"mapped",[1590]],[[126586,126586],"mapped",[1592]],[[126587,126587],"mapped",[1594]],[[126588,126588],"mapped",[1646]],[[126589,126589],"disallowed"],[[126590,126590],"mapped",[1697]],[[126591,126591],"disallowed"],[[126592,126592],"mapped",[1575]],[[126593,126593],"mapped",[1576]],[[126594,126594],"mapped",[1580]],[[126595,126595],"mapped",[1583]],[[126596,126596],"mapped",[1607]],[[126597,126597],"mapped",[1608]],[[126598,126598],"mapped",[1586]],[[126599,126599],"mapped",[1581]],[[126600,126600],"mapped",[1591]],[[126601,126601],"mapped",[1610]],[[126602,126602],"disallowed"],[[126603,126603],"mapped",[1604]],[[126604,126604],"mapped",[1605]],[[126605,126605],"mapped",[1606]],[[126606,126606],"mapped",[1587]],[[126607,126607],"mapped",[1593]],[[126608,126608],"mapped",[1601]],[[126609,126609],"mapped",[1589]],[[126610,126610],"mapped",[1602]],[[126611,126611],"mapped",[1585]],[[126612,126612],"mapped",[1588]],[[126613,126613],"mapped",[1578]],[[126614,126614],"mapped",[1579]],[[126615,126615],"mapped",[1582]],[[126616,126616],"mapped",[1584]],[[126617,126617],"mapped",[1590]],[[126618,126618],"mapped",[1592]],[[126619,126619],"mapped",[1594]],[[126620,126624],"disallowed"],[[126625,126625],"mapped",[1576]],[[126626,126626],"mapped",[1580]],[[126627,126627],"mapped",[1583]],[[126628,126628],"disallowed"],[[126629,126629],"mapped",[1608]],[[126630,126630],"mapped",[1586]],[[126631,126631],"mapped",[1581]],[[126632,126632],"mapped",[1591]],[[126633,126633],"mapped",[1610]],[[126634,126634],"disallowed"],[[126635,126635],"mapped",[1604]],[[126636,126636],"mapped",[1605]],[[126637,126637],"mapped",[1606]],[[126638,126638],"mapped",[1587]],[[126639,126639],"mapped",[1593]],[[126640,126640],"mapped",[1601]],[[126641,126641],"mapped",[1589]],[[126642,126642],"mapped",[1602]],[[126643,126643],"mapped",[1585]],[[126644,126644],"mapped",[1588]],[[126645,126645],"mapped",[1578]],[[126646,126646],"mapped",[1579]],[[126647,126647],"mapped",[1582]],[[126648,126648],"mapped",[1584]],[[126649,126649],"mapped",[1590]],[[126650,126650],"mapped",[1592]],[[126651,126651],"mapped",[1594]],[[126652,126703],"disallowed"],[[126704,126705],"valid",[],"NV8"],[[126706,126975],"disallowed"],[[126976,127019],"valid",[],"NV8"],[[127020,127023],"disallowed"],[[127024,127123],"valid",[],"NV8"],[[127124,127135],"disallowed"],[[127136,127150],"valid",[],"NV8"],[[127151,127152],"disallowed"],[[127153,127166],"valid",[],"NV8"],[[127167,127167],"valid",[],"NV8"],[[127168,127168],"disallowed"],[[127169,127183],"valid",[],"NV8"],[[127184,127184],"disallowed"],[[127185,127199],"valid",[],"NV8"],[[127200,127221],"valid",[],"NV8"],[[127222,127231],"disallowed"],[[127232,127232],"disallowed"],[[127233,127233],"disallowed_STD3_mapped",[48,44]],[[127234,127234],"disallowed_STD3_mapped",[49,44]],[[127235,127235],"disallowed_STD3_mapped",[50,44]],[[127236,127236],"disallowed_STD3_mapped",[51,44]],[[127237,127237],"disallowed_STD3_mapped",[52,44]],[[127238,127238],"disallowed_STD3_mapped",[53,44]],[[127239,127239],"disallowed_STD3_mapped",[54,44]],[[127240,127240],"disallowed_STD3_mapped",[55,44]],[[127241,127241],"disallowed_STD3_mapped",[56,44]],[[127242,127242],"disallowed_STD3_mapped",[57,44]],[[127243,127244],"valid",[],"NV8"],[[127245,127247],"disallowed"],[[127248,127248],"disallowed_STD3_mapped",[40,97,41]],[[127249,127249],"disallowed_STD3_mapped",[40,98,41]],[[127250,127250],"disallowed_STD3_mapped",[40,99,41]],[[127251,127251],"disallowed_STD3_mapped",[40,100,41]],[[127252,127252],"disallowed_STD3_mapped",[40,101,41]],[[127253,127253],"disallowed_STD3_mapped",[40,102,41]],[[127254,127254],"disallowed_STD3_mapped",[40,103,41]],[[127255,127255],"disallowed_STD3_mapped",[40,104,41]],[[127256,127256],"disallowed_STD3_mapped",[40,105,41]],[[127257,127257],"disallowed_STD3_mapped",[40,106,41]],[[127258,127258],"disallowed_STD3_mapped",[40,107,41]],[[127259,127259],"disallowed_STD3_mapped",[40,108,41]],[[127260,127260],"disallowed_STD3_mapped",[40,109,41]],[[127261,127261],"disallowed_STD3_mapped",[40,110,41]],[[127262,127262],"disallowed_STD3_mapped",[40,111,41]],[[127263,127263],"disallowed_STD3_mapped",[40,112,41]],[[127264,127264],"disallowed_STD3_mapped",[40,113,41]],[[127265,127265],"disallowed_STD3_mapped",[40,114,41]],[[127266,127266],"disallowed_STD3_mapped",[40,115,41]],[[127267,127267],"disallowed_STD3_mapped",[40,116,41]],[[127268,127268],"disallowed_STD3_mapped",[40,117,41]],[[127269,127269],"disallowed_STD3_mapped",[40,118,41]],[[127270,127270],"disallowed_STD3_mapped",[40,119,41]],[[127271,127271],"disallowed_STD3_mapped",[40,120,41]],[[127272,127272],"disallowed_STD3_mapped",[40,121,41]],[[127273,127273],"disallowed_STD3_mapped",[40,122,41]],[[127274,127274],"mapped",[12308,115,12309]],[[127275,127275],"mapped",[99]],[[127276,127276],"mapped",[114]],[[127277,127277],"mapped",[99,100]],[[127278,127278],"mapped",[119,122]],[[127279,127279],"disallowed"],[[127280,127280],"mapped",[97]],[[127281,127281],"mapped",[98]],[[127282,127282],"mapped",[99]],[[127283,127283],"mapped",[100]],[[127284,127284],"mapped",[101]],[[127285,127285],"mapped",[102]],[[127286,127286],"mapped",[103]],[[127287,127287],"mapped",[104]],[[127288,127288],"mapped",[105]],[[127289,127289],"mapped",[106]],[[127290,127290],"mapped",[107]],[[127291,127291],"mapped",[108]],[[127292,127292],"mapped",[109]],[[127293,127293],"mapped",[110]],[[127294,127294],"mapped",[111]],[[127295,127295],"mapped",[112]],[[127296,127296],"mapped",[113]],[[127297,127297],"mapped",[114]],[[127298,127298],"mapped",[115]],[[127299,127299],"mapped",[116]],[[127300,127300],"mapped",[117]],[[127301,127301],"mapped",[118]],[[127302,127302],"mapped",[119]],[[127303,127303],"mapped",[120]],[[127304,127304],"mapped",[121]],[[127305,127305],"mapped",[122]],[[127306,127306],"mapped",[104,118]],[[127307,127307],"mapped",[109,118]],[[127308,127308],"mapped",[115,100]],[[127309,127309],"mapped",[115,115]],[[127310,127310],"mapped",[112,112,118]],[[127311,127311],"mapped",[119,99]],[[127312,127318],"valid",[],"NV8"],[[127319,127319],"valid",[],"NV8"],[[127320,127326],"valid",[],"NV8"],[[127327,127327],"valid",[],"NV8"],[[127328,127337],"valid",[],"NV8"],[[127338,127338],"mapped",[109,99]],[[127339,127339],"mapped",[109,100]],[[127340,127343],"disallowed"],[[127344,127352],"valid",[],"NV8"],[[127353,127353],"valid",[],"NV8"],[[127354,127354],"valid",[],"NV8"],[[127355,127356],"valid",[],"NV8"],[[127357,127358],"valid",[],"NV8"],[[127359,127359],"valid",[],"NV8"],[[127360,127369],"valid",[],"NV8"],[[127370,127373],"valid",[],"NV8"],[[127374,127375],"valid",[],"NV8"],[[127376,127376],"mapped",[100,106]],[[127377,127386],"valid",[],"NV8"],[[127387,127461],"disallowed"],[[127462,127487],"valid",[],"NV8"],[[127488,127488],"mapped",[12411,12363]],[[127489,127489],"mapped",[12467,12467]],[[127490,127490],"mapped",[12469]],[[127491,127503],"disallowed"],[[127504,127504],"mapped",[25163]],[[127505,127505],"mapped",[23383]],[[127506,127506],"mapped",[21452]],[[127507,127507],"mapped",[12487]],[[127508,127508],"mapped",[20108]],[[127509,127509],"mapped",[22810]],[[127510,127510],"mapped",[35299]],[[127511,127511],"mapped",[22825]],[[127512,127512],"mapped",[20132]],[[127513,127513],"mapped",[26144]],[[127514,127514],"mapped",[28961]],[[127515,127515],"mapped",[26009]],[[127516,127516],"mapped",[21069]],[[127517,127517],"mapped",[24460]],[[127518,127518],"mapped",[20877]],[[127519,127519],"mapped",[26032]],[[127520,127520],"mapped",[21021]],[[127521,127521],"mapped",[32066]],[[127522,127522],"mapped",[29983]],[[127523,127523],"mapped",[36009]],[[127524,127524],"mapped",[22768]],[[127525,127525],"mapped",[21561]],[[127526,127526],"mapped",[28436]],[[127527,127527],"mapped",[25237]],[[127528,127528],"mapped",[25429]],[[127529,127529],"mapped",[19968]],[[127530,127530],"mapped",[19977]],[[127531,127531],"mapped",[36938]],[[127532,127532],"mapped",[24038]],[[127533,127533],"mapped",[20013]],[[127534,127534],"mapped",[21491]],[[127535,127535],"mapped",[25351]],[[127536,127536],"mapped",[36208]],[[127537,127537],"mapped",[25171]],[[127538,127538],"mapped",[31105]],[[127539,127539],"mapped",[31354]],[[127540,127540],"mapped",[21512]],[[127541,127541],"mapped",[28288]],[[127542,127542],"mapped",[26377]],[[127543,127543],"mapped",[26376]],[[127544,127544],"mapped",[30003]],[[127545,127545],"mapped",[21106]],[[127546,127546],"mapped",[21942]],[[127547,127551],"disallowed"],[[127552,127552],"mapped",[12308,26412,12309]],[[127553,127553],"mapped",[12308,19977,12309]],[[127554,127554],"mapped",[12308,20108,12309]],[[127555,127555],"mapped",[12308,23433,12309]],[[127556,127556],"mapped",[12308,28857,12309]],[[127557,127557],"mapped",[12308,25171,12309]],[[127558,127558],"mapped",[12308,30423,12309]],[[127559,127559],"mapped",[12308,21213,12309]],[[127560,127560],"mapped",[12308,25943,12309]],[[127561,127567],"disallowed"],[[127568,127568],"mapped",[24471]],[[127569,127569],"mapped",[21487]],[[127570,127743],"disallowed"],[[127744,127776],"valid",[],"NV8"],[[127777,127788],"valid",[],"NV8"],[[127789,127791],"valid",[],"NV8"],[[127792,127797],"valid",[],"NV8"],[[127798,127798],"valid",[],"NV8"],[[127799,127868],"valid",[],"NV8"],[[127869,127869],"valid",[],"NV8"],[[127870,127871],"valid",[],"NV8"],[[127872,127891],"valid",[],"NV8"],[[127892,127903],"valid",[],"NV8"],[[127904,127940],"valid",[],"NV8"],[[127941,127941],"valid",[],"NV8"],[[127942,127946],"valid",[],"NV8"],[[127947,127950],"valid",[],"NV8"],[[127951,127955],"valid",[],"NV8"],[[127956,127967],"valid",[],"NV8"],[[127968,127984],"valid",[],"NV8"],[[127985,127991],"valid",[],"NV8"],[[127992,127999],"valid",[],"NV8"],[[128000,128062],"valid",[],"NV8"],[[128063,128063],"valid",[],"NV8"],[[128064,128064],"valid",[],"NV8"],[[128065,128065],"valid",[],"NV8"],[[128066,128247],"valid",[],"NV8"],[[128248,128248],"valid",[],"NV8"],[[128249,128252],"valid",[],"NV8"],[[128253,128254],"valid",[],"NV8"],[[128255,128255],"valid",[],"NV8"],[[128256,128317],"valid",[],"NV8"],[[128318,128319],"valid",[],"NV8"],[[128320,128323],"valid",[],"NV8"],[[128324,128330],"valid",[],"NV8"],[[128331,128335],"valid",[],"NV8"],[[128336,128359],"valid",[],"NV8"],[[128360,128377],"valid",[],"NV8"],[[128378,128378],"disallowed"],[[128379,128419],"valid",[],"NV8"],[[128420,128420],"disallowed"],[[128421,128506],"valid",[],"NV8"],[[128507,128511],"valid",[],"NV8"],[[128512,128512],"valid",[],"NV8"],[[128513,128528],"valid",[],"NV8"],[[128529,128529],"valid",[],"NV8"],[[128530,128532],"valid",[],"NV8"],[[128533,128533],"valid",[],"NV8"],[[128534,128534],"valid",[],"NV8"],[[128535,128535],"valid",[],"NV8"],[[128536,128536],"valid",[],"NV8"],[[128537,128537],"valid",[],"NV8"],[[128538,128538],"valid",[],"NV8"],[[128539,128539],"valid",[],"NV8"],[[128540,128542],"valid",[],"NV8"],[[128543,128543],"valid",[],"NV8"],[[128544,128549],"valid",[],"NV8"],[[128550,128551],"valid",[],"NV8"],[[128552,128555],"valid",[],"NV8"],[[128556,128556],"valid",[],"NV8"],[[128557,128557],"valid",[],"NV8"],[[128558,128559],"valid",[],"NV8"],[[128560,128563],"valid",[],"NV8"],[[128564,128564],"valid",[],"NV8"],[[128565,128576],"valid",[],"NV8"],[[128577,128578],"valid",[],"NV8"],[[128579,128580],"valid",[],"NV8"],[[128581,128591],"valid",[],"NV8"],[[128592,128639],"valid",[],"NV8"],[[128640,128709],"valid",[],"NV8"],[[128710,128719],"valid",[],"NV8"],[[128720,128720],"valid",[],"NV8"],[[128721,128735],"disallowed"],[[128736,128748],"valid",[],"NV8"],[[128749,128751],"disallowed"],[[128752,128755],"valid",[],"NV8"],[[128756,128767],"disallowed"],[[128768,128883],"valid",[],"NV8"],[[128884,128895],"disallowed"],[[128896,128980],"valid",[],"NV8"],[[128981,129023],"disallowed"],[[129024,129035],"valid",[],"NV8"],[[129036,129039],"disallowed"],[[129040,129095],"valid",[],"NV8"],[[129096,129103],"disallowed"],[[129104,129113],"valid",[],"NV8"],[[129114,129119],"disallowed"],[[129120,129159],"valid",[],"NV8"],[[129160,129167],"disallowed"],[[129168,129197],"valid",[],"NV8"],[[129198,129295],"disallowed"],[[129296,129304],"valid",[],"NV8"],[[129305,129407],"disallowed"],[[129408,129412],"valid",[],"NV8"],[[129413,129471],"disallowed"],[[129472,129472],"valid",[],"NV8"],[[129473,131069],"disallowed"],[[131070,131071],"disallowed"],[[131072,173782],"valid"],[[173783,173823],"disallowed"],[[173824,177972],"valid"],[[177973,177983],"disallowed"],[[177984,178205],"valid"],[[178206,178207],"disallowed"],[[178208,183969],"valid"],[[183970,194559],"disallowed"],[[194560,194560],"mapped",[20029]],[[194561,194561],"mapped",[20024]],[[194562,194562],"mapped",[20033]],[[194563,194563],"mapped",[131362]],[[194564,194564],"mapped",[20320]],[[194565,194565],"mapped",[20398]],[[194566,194566],"mapped",[20411]],[[194567,194567],"mapped",[20482]],[[194568,194568],"mapped",[20602]],[[194569,194569],"mapped",[20633]],[[194570,194570],"mapped",[20711]],[[194571,194571],"mapped",[20687]],[[194572,194572],"mapped",[13470]],[[194573,194573],"mapped",[132666]],[[194574,194574],"mapped",[20813]],[[194575,194575],"mapped",[20820]],[[194576,194576],"mapped",[20836]],[[194577,194577],"mapped",[20855]],[[194578,194578],"mapped",[132380]],[[194579,194579],"mapped",[13497]],[[194580,194580],"mapped",[20839]],[[194581,194581],"mapped",[20877]],[[194582,194582],"mapped",[132427]],[[194583,194583],"mapped",[20887]],[[194584,194584],"mapped",[20900]],[[194585,194585],"mapped",[20172]],[[194586,194586],"mapped",[20908]],[[194587,194587],"mapped",[20917]],[[194588,194588],"mapped",[168415]],[[194589,194589],"mapped",[20981]],[[194590,194590],"mapped",[20995]],[[194591,194591],"mapped",[13535]],[[194592,194592],"mapped",[21051]],[[194593,194593],"mapped",[21062]],[[194594,194594],"mapped",[21106]],[[194595,194595],"mapped",[21111]],[[194596,194596],"mapped",[13589]],[[194597,194597],"mapped",[21191]],[[194598,194598],"mapped",[21193]],[[194599,194599],"mapped",[21220]],[[194600,194600],"mapped",[21242]],[[194601,194601],"mapped",[21253]],[[194602,194602],"mapped",[21254]],[[194603,194603],"mapped",[21271]],[[194604,194604],"mapped",[21321]],[[194605,194605],"mapped",[21329]],[[194606,194606],"mapped",[21338]],[[194607,194607],"mapped",[21363]],[[194608,194608],"mapped",[21373]],[[194609,194611],"mapped",[21375]],[[194612,194612],"mapped",[133676]],[[194613,194613],"mapped",[28784]],[[194614,194614],"mapped",[21450]],[[194615,194615],"mapped",[21471]],[[194616,194616],"mapped",[133987]],[[194617,194617],"mapped",[21483]],[[194618,194618],"mapped",[21489]],[[194619,194619],"mapped",[21510]],[[194620,194620],"mapped",[21662]],[[194621,194621],"mapped",[21560]],[[194622,194622],"mapped",[21576]],[[194623,194623],"mapped",[21608]],[[194624,194624],"mapped",[21666]],[[194625,194625],"mapped",[21750]],[[194626,194626],"mapped",[21776]],[[194627,194627],"mapped",[21843]],[[194628,194628],"mapped",[21859]],[[194629,194630],"mapped",[21892]],[[194631,194631],"mapped",[21913]],[[194632,194632],"mapped",[21931]],[[194633,194633],"mapped",[21939]],[[194634,194634],"mapped",[21954]],[[194635,194635],"mapped",[22294]],[[194636,194636],"mapped",[22022]],[[194637,194637],"mapped",[22295]],[[194638,194638],"mapped",[22097]],[[194639,194639],"mapped",[22132]],[[194640,194640],"mapped",[20999]],[[194641,194641],"mapped",[22766]],[[194642,194642],"mapped",[22478]],[[194643,194643],"mapped",[22516]],[[194644,194644],"mapped",[22541]],[[194645,194645],"mapped",[22411]],[[194646,194646],"mapped",[22578]],[[194647,194647],"mapped",[22577]],[[194648,194648],"mapped",[22700]],[[194649,194649],"mapped",[136420]],[[194650,194650],"mapped",[22770]],[[194651,194651],"mapped",[22775]],[[194652,194652],"mapped",[22790]],[[194653,194653],"mapped",[22810]],[[194654,194654],"mapped",[22818]],[[194655,194655],"mapped",[22882]],[[194656,194656],"mapped",[136872]],[[194657,194657],"mapped",[136938]],[[194658,194658],"mapped",[23020]],[[194659,194659],"mapped",[23067]],[[194660,194660],"mapped",[23079]],[[194661,194661],"mapped",[23000]],[[194662,194662],"mapped",[23142]],[[194663,194663],"mapped",[14062]],[[194664,194664],"disallowed"],[[194665,194665],"mapped",[23304]],[[194666,194667],"mapped",[23358]],[[194668,194668],"mapped",[137672]],[[194669,194669],"mapped",[23491]],[[194670,194670],"mapped",[23512]],[[194671,194671],"mapped",[23527]],[[194672,194672],"mapped",[23539]],[[194673,194673],"mapped",[138008]],[[194674,194674],"mapped",[23551]],[[194675,194675],"mapped",[23558]],[[194676,194676],"disallowed"],[[194677,194677],"mapped",[23586]],[[194678,194678],"mapped",[14209]],[[194679,194679],"mapped",[23648]],[[194680,194680],"mapped",[23662]],[[194681,194681],"mapped",[23744]],[[194682,194682],"mapped",[23693]],[[194683,194683],"mapped",[138724]],[[194684,194684],"mapped",[23875]],[[194685,194685],"mapped",[138726]],[[194686,194686],"mapped",[23918]],[[194687,194687],"mapped",[23915]],[[194688,194688],"mapped",[23932]],[[194689,194689],"mapped",[24033]],[[194690,194690],"mapped",[24034]],[[194691,194691],"mapped",[14383]],[[194692,194692],"mapped",[24061]],[[194693,194693],"mapped",[24104]],[[194694,194694],"mapped",[24125]],[[194695,194695],"mapped",[24169]],[[194696,194696],"mapped",[14434]],[[194697,194697],"mapped",[139651]],[[194698,194698],"mapped",[14460]],[[194699,194699],"mapped",[24240]],[[194700,194700],"mapped",[24243]],[[194701,194701],"mapped",[24246]],[[194702,194702],"mapped",[24266]],[[194703,194703],"mapped",[172946]],[[194704,194704],"mapped",[24318]],[[194705,194706],"mapped",[140081]],[[194707,194707],"mapped",[33281]],[[194708,194709],"mapped",[24354]],[[194710,194710],"mapped",[14535]],[[194711,194711],"mapped",[144056]],[[194712,194712],"mapped",[156122]],[[194713,194713],"mapped",[24418]],[[194714,194714],"mapped",[24427]],[[194715,194715],"mapped",[14563]],[[194716,194716],"mapped",[24474]],[[194717,194717],"mapped",[24525]],[[194718,194718],"mapped",[24535]],[[194719,194719],"mapped",[24569]],[[194720,194720],"mapped",[24705]],[[194721,194721],"mapped",[14650]],[[194722,194722],"mapped",[14620]],[[194723,194723],"mapped",[24724]],[[194724,194724],"mapped",[141012]],[[194725,194725],"mapped",[24775]],[[194726,194726],"mapped",[24904]],[[194727,194727],"mapped",[24908]],[[194728,194728],"mapped",[24910]],[[194729,194729],"mapped",[24908]],[[194730,194730],"mapped",[24954]],[[194731,194731],"mapped",[24974]],[[194732,194732],"mapped",[25010]],[[194733,194733],"mapped",[24996]],[[194734,194734],"mapped",[25007]],[[194735,194735],"mapped",[25054]],[[194736,194736],"mapped",[25074]],[[194737,194737],"mapped",[25078]],[[194738,194738],"mapped",[25104]],[[194739,194739],"mapped",[25115]],[[194740,194740],"mapped",[25181]],[[194741,194741],"mapped",[25265]],[[194742,194742],"mapped",[25300]],[[194743,194743],"mapped",[25424]],[[194744,194744],"mapped",[142092]],[[194745,194745],"mapped",[25405]],[[194746,194746],"mapped",[25340]],[[194747,194747],"mapped",[25448]],[[194748,194748],"mapped",[25475]],[[194749,194749],"mapped",[25572]],[[194750,194750],"mapped",[142321]],[[194751,194751],"mapped",[25634]],[[194752,194752],"mapped",[25541]],[[194753,194753],"mapped",[25513]],[[194754,194754],"mapped",[14894]],[[194755,194755],"mapped",[25705]],[[194756,194756],"mapped",[25726]],[[194757,194757],"mapped",[25757]],[[194758,194758],"mapped",[25719]],[[194759,194759],"mapped",[14956]],[[194760,194760],"mapped",[25935]],[[194761,194761],"mapped",[25964]],[[194762,194762],"mapped",[143370]],[[194763,194763],"mapped",[26083]],[[194764,194764],"mapped",[26360]],[[194765,194765],"mapped",[26185]],[[194766,194766],"mapped",[15129]],[[194767,194767],"mapped",[26257]],[[194768,194768],"mapped",[15112]],[[194769,194769],"mapped",[15076]],[[194770,194770],"mapped",[20882]],[[194771,194771],"mapped",[20885]],[[194772,194772],"mapped",[26368]],[[194773,194773],"mapped",[26268]],[[194774,194774],"mapped",[32941]],[[194775,194775],"mapped",[17369]],[[194776,194776],"mapped",[26391]],[[194777,194777],"mapped",[26395]],[[194778,194778],"mapped",[26401]],[[194779,194779],"mapped",[26462]],[[194780,194780],"mapped",[26451]],[[194781,194781],"mapped",[144323]],[[194782,194782],"mapped",[15177]],[[194783,194783],"mapped",[26618]],[[194784,194784],"mapped",[26501]],[[194785,194785],"mapped",[26706]],[[194786,194786],"mapped",[26757]],[[194787,194787],"mapped",[144493]],[[194788,194788],"mapped",[26766]],[[194789,194789],"mapped",[26655]],[[194790,194790],"mapped",[26900]],[[194791,194791],"mapped",[15261]],[[194792,194792],"mapped",[26946]],[[194793,194793],"mapped",[27043]],[[194794,194794],"mapped",[27114]],[[194795,194795],"mapped",[27304]],[[194796,194796],"mapped",[145059]],[[194797,194797],"mapped",[27355]],[[194798,194798],"mapped",[15384]],[[194799,194799],"mapped",[27425]],[[194800,194800],"mapped",[145575]],[[194801,194801],"mapped",[27476]],[[194802,194802],"mapped",[15438]],[[194803,194803],"mapped",[27506]],[[194804,194804],"mapped",[27551]],[[194805,194805],"mapped",[27578]],[[194806,194806],"mapped",[27579]],[[194807,194807],"mapped",[146061]],[[194808,194808],"mapped",[138507]],[[194809,194809],"mapped",[146170]],[[194810,194810],"mapped",[27726]],[[194811,194811],"mapped",[146620]],[[194812,194812],"mapped",[27839]],[[194813,194813],"mapped",[27853]],[[194814,194814],"mapped",[27751]],[[194815,194815],"mapped",[27926]],[[194816,194816],"mapped",[27966]],[[194817,194817],"mapped",[28023]],[[194818,194818],"mapped",[27969]],[[194819,194819],"mapped",[28009]],[[194820,194820],"mapped",[28024]],[[194821,194821],"mapped",[28037]],[[194822,194822],"mapped",[146718]],[[194823,194823],"mapped",[27956]],[[194824,194824],"mapped",[28207]],[[194825,194825],"mapped",[28270]],[[194826,194826],"mapped",[15667]],[[194827,194827],"mapped",[28363]],[[194828,194828],"mapped",[28359]],[[194829,194829],"mapped",[147153]],[[194830,194830],"mapped",[28153]],[[194831,194831],"mapped",[28526]],[[194832,194832],"mapped",[147294]],[[194833,194833],"mapped",[147342]],[[194834,194834],"mapped",[28614]],[[194835,194835],"mapped",[28729]],[[194836,194836],"mapped",[28702]],[[194837,194837],"mapped",[28699]],[[194838,194838],"mapped",[15766]],[[194839,194839],"mapped",[28746]],[[194840,194840],"mapped",[28797]],[[194841,194841],"mapped",[28791]],[[194842,194842],"mapped",[28845]],[[194843,194843],"mapped",[132389]],[[194844,194844],"mapped",[28997]],[[194845,194845],"mapped",[148067]],[[194846,194846],"mapped",[29084]],[[194847,194847],"disallowed"],[[194848,194848],"mapped",[29224]],[[194849,194849],"mapped",[29237]],[[194850,194850],"mapped",[29264]],[[194851,194851],"mapped",[149000]],[[194852,194852],"mapped",[29312]],[[194853,194853],"mapped",[29333]],[[194854,194854],"mapped",[149301]],[[194855,194855],"mapped",[149524]],[[194856,194856],"mapped",[29562]],[[194857,194857],"mapped",[29579]],[[194858,194858],"mapped",[16044]],[[194859,194859],"mapped",[29605]],[[194860,194861],"mapped",[16056]],[[194862,194862],"mapped",[29767]],[[194863,194863],"mapped",[29788]],[[194864,194864],"mapped",[29809]],[[194865,194865],"mapped",[29829]],[[194866,194866],"mapped",[29898]],[[194867,194867],"mapped",[16155]],[[194868,194868],"mapped",[29988]],[[194869,194869],"mapped",[150582]],[[194870,194870],"mapped",[30014]],[[194871,194871],"mapped",[150674]],[[194872,194872],"mapped",[30064]],[[194873,194873],"mapped",[139679]],[[194874,194874],"mapped",[30224]],[[194875,194875],"mapped",[151457]],[[194876,194876],"mapped",[151480]],[[194877,194877],"mapped",[151620]],[[194878,194878],"mapped",[16380]],[[194879,194879],"mapped",[16392]],[[194880,194880],"mapped",[30452]],[[194881,194881],"mapped",[151795]],[[194882,194882],"mapped",[151794]],[[194883,194883],"mapped",[151833]],[[194884,194884],"mapped",[151859]],[[194885,194885],"mapped",[30494]],[[194886,194887],"mapped",[30495]],[[194888,194888],"mapped",[30538]],[[194889,194889],"mapped",[16441]],[[194890,194890],"mapped",[30603]],[[194891,194891],"mapped",[16454]],[[194892,194892],"mapped",[16534]],[[194893,194893],"mapped",[152605]],[[194894,194894],"mapped",[30798]],[[194895,194895],"mapped",[30860]],[[194896,194896],"mapped",[30924]],[[194897,194897],"mapped",[16611]],[[194898,194898],"mapped",[153126]],[[194899,194899],"mapped",[31062]],[[194900,194900],"mapped",[153242]],[[194901,194901],"mapped",[153285]],[[194902,194902],"mapped",[31119]],[[194903,194903],"mapped",[31211]],[[194904,194904],"mapped",[16687]],[[194905,194905],"mapped",[31296]],[[194906,194906],"mapped",[31306]],[[194907,194907],"mapped",[31311]],[[194908,194908],"mapped",[153980]],[[194909,194910],"mapped",[154279]],[[194911,194911],"disallowed"],[[194912,194912],"mapped",[16898]],[[194913,194913],"mapped",[154539]],[[194914,194914],"mapped",[31686]],[[194915,194915],"mapped",[31689]],[[194916,194916],"mapped",[16935]],[[194917,194917],"mapped",[154752]],[[194918,194918],"mapped",[31954]],[[194919,194919],"mapped",[17056]],[[194920,194920],"mapped",[31976]],[[194921,194921],"mapped",[31971]],[[194922,194922],"mapped",[32000]],[[194923,194923],"mapped",[155526]],[[194924,194924],"mapped",[32099]],[[194925,194925],"mapped",[17153]],[[194926,194926],"mapped",[32199]],[[194927,194927],"mapped",[32258]],[[194928,194928],"mapped",[32325]],[[194929,194929],"mapped",[17204]],[[194930,194930],"mapped",[156200]],[[194931,194931],"mapped",[156231]],[[194932,194932],"mapped",[17241]],[[194933,194933],"mapped",[156377]],[[194934,194934],"mapped",[32634]],[[194935,194935],"mapped",[156478]],[[194936,194936],"mapped",[32661]],[[194937,194937],"mapped",[32762]],[[194938,194938],"mapped",[32773]],[[194939,194939],"mapped",[156890]],[[194940,194940],"mapped",[156963]],[[194941,194941],"mapped",[32864]],[[194942,194942],"mapped",[157096]],[[194943,194943],"mapped",[32880]],[[194944,194944],"mapped",[144223]],[[194945,194945],"mapped",[17365]],[[194946,194946],"mapped",[32946]],[[194947,194947],"mapped",[33027]],[[194948,194948],"mapped",[17419]],[[194949,194949],"mapped",[33086]],[[194950,194950],"mapped",[23221]],[[194951,194951],"mapped",[157607]],[[194952,194952],"mapped",[157621]],[[194953,194953],"mapped",[144275]],[[194954,194954],"mapped",[144284]],[[194955,194955],"mapped",[33281]],[[194956,194956],"mapped",[33284]],[[194957,194957],"mapped",[36766]],[[194958,194958],"mapped",[17515]],[[194959,194959],"mapped",[33425]],[[194960,194960],"mapped",[33419]],[[194961,194961],"mapped",[33437]],[[194962,194962],"mapped",[21171]],[[194963,194963],"mapped",[33457]],[[194964,194964],"mapped",[33459]],[[194965,194965],"mapped",[33469]],[[194966,194966],"mapped",[33510]],[[194967,194967],"mapped",[158524]],[[194968,194968],"mapped",[33509]],[[194969,194969],"mapped",[33565]],[[194970,194970],"mapped",[33635]],[[194971,194971],"mapped",[33709]],[[194972,194972],"mapped",[33571]],[[194973,194973],"mapped",[33725]],[[194974,194974],"mapped",[33767]],[[194975,194975],"mapped",[33879]],[[194976,194976],"mapped",[33619]],[[194977,194977],"mapped",[33738]],[[194978,194978],"mapped",[33740]],[[194979,194979],"mapped",[33756]],[[194980,194980],"mapped",[158774]],[[194981,194981],"mapped",[159083]],[[194982,194982],"mapped",[158933]],[[194983,194983],"mapped",[17707]],[[194984,194984],"mapped",[34033]],[[194985,194985],"mapped",[34035]],[[194986,194986],"mapped",[34070]],[[194987,194987],"mapped",[160714]],[[194988,194988],"mapped",[34148]],[[194989,194989],"mapped",[159532]],[[194990,194990],"mapped",[17757]],[[194991,194991],"mapped",[17761]],[[194992,194992],"mapped",[159665]],[[194993,194993],"mapped",[159954]],[[194994,194994],"mapped",[17771]],[[194995,194995],"mapped",[34384]],[[194996,194996],"mapped",[34396]],[[194997,194997],"mapped",[34407]],[[194998,194998],"mapped",[34409]],[[194999,194999],"mapped",[34473]],[[195000,195000],"mapped",[34440]],[[195001,195001],"mapped",[34574]],[[195002,195002],"mapped",[34530]],[[195003,195003],"mapped",[34681]],[[195004,195004],"mapped",[34600]],[[195005,195005],"mapped",[34667]],[[195006,195006],"mapped",[34694]],[[195007,195007],"disallowed"],[[195008,195008],"mapped",[34785]],[[195009,195009],"mapped",[34817]],[[195010,195010],"mapped",[17913]],[[195011,195011],"mapped",[34912]],[[195012,195012],"mapped",[34915]],[[195013,195013],"mapped",[161383]],[[195014,195014],"mapped",[35031]],[[195015,195015],"mapped",[35038]],[[195016,195016],"mapped",[17973]],[[195017,195017],"mapped",[35066]],[[195018,195018],"mapped",[13499]],[[195019,195019],"mapped",[161966]],[[195020,195020],"mapped",[162150]],[[195021,195021],"mapped",[18110]],[[195022,195022],"mapped",[18119]],[[195023,195023],"mapped",[35488]],[[195024,195024],"mapped",[35565]],[[195025,195025],"mapped",[35722]],[[195026,195026],"mapped",[35925]],[[195027,195027],"mapped",[162984]],[[195028,195028],"mapped",[36011]],[[195029,195029],"mapped",[36033]],[[195030,195030],"mapped",[36123]],[[195031,195031],"mapped",[36215]],[[195032,195032],"mapped",[163631]],[[195033,195033],"mapped",[133124]],[[195034,195034],"mapped",[36299]],[[195035,195035],"mapped",[36284]],[[195036,195036],"mapped",[36336]],[[195037,195037],"mapped",[133342]],[[195038,195038],"mapped",[36564]],[[195039,195039],"mapped",[36664]],[[195040,195040],"mapped",[165330]],[[195041,195041],"mapped",[165357]],[[195042,195042],"mapped",[37012]],[[195043,195043],"mapped",[37105]],[[195044,195044],"mapped",[37137]],[[195045,195045],"mapped",[165678]],[[195046,195046],"mapped",[37147]],[[195047,195047],"mapped",[37432]],[[195048,195048],"mapped",[37591]],[[195049,195049],"mapped",[37592]],[[195050,195050],"mapped",[37500]],[[195051,195051],"mapped",[37881]],[[195052,195052],"mapped",[37909]],[[195053,195053],"mapped",[166906]],[[195054,195054],"mapped",[38283]],[[195055,195055],"mapped",[18837]],[[195056,195056],"mapped",[38327]],[[195057,195057],"mapped",[167287]],[[195058,195058],"mapped",[18918]],[[195059,195059],"mapped",[38595]],[[195060,195060],"mapped",[23986]],[[195061,195061],"mapped",[38691]],[[195062,195062],"mapped",[168261]],[[195063,195063],"mapped",[168474]],[[195064,195064],"mapped",[19054]],[[195065,195065],"mapped",[19062]],[[195066,195066],"mapped",[38880]],[[195067,195067],"mapped",[168970]],[[195068,195068],"mapped",[19122]],[[195069,195069],"mapped",[169110]],[[195070,195071],"mapped",[38923]],[[195072,195072],"mapped",[38953]],[[195073,195073],"mapped",[169398]],[[195074,195074],"mapped",[39138]],[[195075,195075],"mapped",[19251]],[[195076,195076],"mapped",[39209]],[[195077,195077],"mapped",[39335]],[[195078,195078],"mapped",[39362]],[[195079,195079],"mapped",[39422]],[[195080,195080],"mapped",[19406]],[[195081,195081],"mapped",[170800]],[[195082,195082],"mapped",[39698]],[[195083,195083],"mapped",[40000]],[[195084,195084],"mapped",[40189]],[[195085,195085],"mapped",[19662]],[[195086,195086],"mapped",[19693]],[[195087,195087],"mapped",[40295]],[[195088,195088],"mapped",[172238]],[[195089,195089],"mapped",[19704]],[[195090,195090],"mapped",[172293]],[[195091,195091],"mapped",[172558]],[[195092,195092],"mapped",[172689]],[[195093,195093],"mapped",[40635]],[[195094,195094],"mapped",[19798]],[[195095,195095],"mapped",[40697]],[[195096,195096],"mapped",[40702]],[[195097,195097],"mapped",[40709]],[[195098,195098],"mapped",[40719]],[[195099,195099],"mapped",[40726]],[[195100,195100],"mapped",[40763]],[[195101,195101],"mapped",[173568]],[[195102,196605],"disallowed"],[[196606,196607],"disallowed"],[[196608,262141],"disallowed"],[[262142,262143],"disallowed"],[[262144,327677],"disallowed"],[[327678,327679],"disallowed"],[[327680,393213],"disallowed"],[[393214,393215],"disallowed"],[[393216,458749],"disallowed"],[[458750,458751],"disallowed"],[[458752,524285],"disallowed"],[[524286,524287],"disallowed"],[[524288,589821],"disallowed"],[[589822,589823],"disallowed"],[[589824,655357],"disallowed"],[[655358,655359],"disallowed"],[[655360,720893],"disallowed"],[[720894,720895],"disallowed"],[[720896,786429],"disallowed"],[[786430,786431],"disallowed"],[[786432,851965],"disallowed"],[[851966,851967],"disallowed"],[[851968,917501],"disallowed"],[[917502,917503],"disallowed"],[[917504,917504],"disallowed"],[[917505,917505],"disallowed"],[[917506,917535],"disallowed"],[[917536,917631],"disallowed"],[[917632,917759],"disallowed"],[[917760,917999],"ignored"],[[918000,983037],"disallowed"],[[983038,983039],"disallowed"],[[983040,1048573],"disallowed"],[[1048574,1048575],"disallowed"],[[1048576,1114109],"disallowed"],[[1114110,1114111],"disallowed"]] \ No newline at end of file diff --git a/node_modules/tr46/package.json b/node_modules/tr46/package.json deleted file mode 100644 index b6826da1..00000000 --- a/node_modules/tr46/package.json +++ /dev/null @@ -1,31 +0,0 @@ -{ - "name": "tr46", - "version": "0.0.3", - "description": "An implementation of the Unicode TR46 spec", - "main": "index.js", - "scripts": { - "test": "mocha", - "pretest": "node scripts/getLatestUnicodeTests.js", - "prepublish": "node scripts/generateMappingTable.js" - }, - "repository": { - "type": "git", - "url": "git+https://github.com/Sebmaster/tr46.js.git" - }, - "keywords": [ - "unicode", - "tr46", - "url", - "whatwg" - ], - "author": "Sebastian Mayr ", - "license": "MIT", - "bugs": { - "url": "https://github.com/Sebmaster/tr46.js/issues" - }, - "homepage": "https://github.com/Sebmaster/tr46.js#readme", - "devDependencies": { - "mocha": "^2.2.5", - "request": "^2.57.0" - } -} diff --git a/node_modules/webidl-conversions/LICENSE.md b/node_modules/webidl-conversions/LICENSE.md deleted file mode 100644 index d4a994f5..00000000 --- a/node_modules/webidl-conversions/LICENSE.md +++ /dev/null @@ -1,12 +0,0 @@ -# The BSD 2-Clause License - -Copyright (c) 2014, Domenic Denicola -All rights reserved. - -Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: - -1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. - -2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/node_modules/webidl-conversions/README.md b/node_modules/webidl-conversions/README.md deleted file mode 100644 index 3657890a..00000000 --- a/node_modules/webidl-conversions/README.md +++ /dev/null @@ -1,53 +0,0 @@ -# WebIDL Type Conversions on JavaScript Values - -This package implements, in JavaScript, the algorithms to convert a given JavaScript value according to a given [WebIDL](http://heycam.github.io/webidl/) [type](http://heycam.github.io/webidl/#idl-types). - -The goal is that you should be able to write code like - -```js -const conversions = require("webidl-conversions"); - -function doStuff(x, y) { - x = conversions["boolean"](x); - y = conversions["unsigned long"](y); - // actual algorithm code here -} -``` - -and your function `doStuff` will behave the same as a WebIDL operation declared as - -```webidl -void doStuff(boolean x, unsigned long y); -``` - -## API - -This package's main module's default export is an object with a variety of methods, each corresponding to a different WebIDL type. Each method, when invoked on a JavaScript value, will give back the new JavaScript value that results after passing through the WebIDL conversion rules. (See below for more details on what that means.) Alternately, the method could throw an error, if the WebIDL algorithm is specified to do so: for example `conversions["float"](NaN)` [will throw a `TypeError`](http://heycam.github.io/webidl/#es-float). - -## Status - -All of the numeric types are implemented (float being implemented as double) and some others are as well - check the source for all of them. This list will grow over time in service of the [HTML as Custom Elements](https://github.com/dglazkov/html-as-custom-elements) project, but in the meantime, pull requests welcome! - -I'm not sure yet what the strategy will be for modifiers, e.g. [`[Clamp]`](http://heycam.github.io/webidl/#Clamp). Maybe something like `conversions["unsigned long"](x, { clamp: true })`? We'll see. - -We might also want to extend the API to give better error messages, e.g. "Argument 1 of HTMLMediaElement.fastSeek is not a finite floating-point value" instead of "Argument is not a finite floating-point value." This would require passing in more information to the conversion functions than we currently do. - -## Background - -What's actually going on here, conceptually, is pretty weird. Let's try to explain. - -WebIDL, as part of its madness-inducing design, has its own type system. When people write algorithms in web platform specs, they usually operate on WebIDL values, i.e. instances of WebIDL types. For example, if they were specifying the algorithm for our `doStuff` operation above, they would treat `x` as a WebIDL value of [WebIDL type `boolean`](http://heycam.github.io/webidl/#idl-boolean). Crucially, they would _not_ treat `x` as a JavaScript variable whose value is either the JavaScript `true` or `false`. They're instead working in a different type system altogether, with its own rules. - -Separately from its type system, WebIDL defines a ["binding"](http://heycam.github.io/webidl/#ecmascript-binding) of the type system into JavaScript. This contains rules like: when you pass a JavaScript value to the JavaScript method that manifests a given WebIDL operation, how does that get converted into a WebIDL value? For example, a JavaScript `true` passed in the position of a WebIDL `boolean` argument becomes a WebIDL `true`. But, a JavaScript `true` passed in the position of a [WebIDL `unsigned long`](http://heycam.github.io/webidl/#idl-unsigned-long) becomes a WebIDL `1`. And so on. - -Finally, we have the actual implementation code. This is usually C++, although these days [some smart people are using Rust](https://github.com/servo/servo). The implementation, of course, has its own type system. So when they implement the WebIDL algorithms, they don't actually use WebIDL values, since those aren't "real" outside of specs. Instead, implementations apply the WebIDL binding rules in such a way as to convert incoming JavaScript values into C++ values. For example, if code in the browser called `doStuff(true, true)`, then the implementation code would eventually receive a C++ `bool` containing `true` and a C++ `uint32_t` containing `1`. - -The upside of all this is that implementations can abstract all the conversion logic away, letting WebIDL handle it, and focus on implementing the relevant methods in C++ with values of the correct type already provided. That is payoff of WebIDL, in a nutshell. - -And getting to that payoff is the goal of _this_ project—but for JavaScript implementations, instead of C++ ones. That is, this library is designed to make it easier for JavaScript developers to write functions that behave like a given WebIDL operation. So conceptually, the conversion pipeline, which in its general form is JavaScript values ↦ WebIDL values ↦ implementation-language values, in this case becomes JavaScript values ↦ WebIDL values ↦ JavaScript values. And that intermediate step is where all the logic is performed: a JavaScript `true` becomes a WebIDL `1` in an unsigned long context, which then becomes a JavaScript `1`. - -## Don't Use This - -Seriously, why would you ever use this? You really shouldn't. WebIDL is … not great, and you shouldn't be emulating its semantics. If you're looking for a generic argument-processing library, you should find one with better rules than those from WebIDL. In general, your JavaScript should not be trying to become more like WebIDL; if anything, we should fix WebIDL to make it more like JavaScript. - -The _only_ people who should use this are those trying to create faithful implementations (or polyfills) of web platform interfaces defined in WebIDL. diff --git a/node_modules/webidl-conversions/lib/index.js b/node_modules/webidl-conversions/lib/index.js deleted file mode 100644 index c5153a3a..00000000 --- a/node_modules/webidl-conversions/lib/index.js +++ /dev/null @@ -1,189 +0,0 @@ -"use strict"; - -var conversions = {}; -module.exports = conversions; - -function sign(x) { - return x < 0 ? -1 : 1; -} - -function evenRound(x) { - // Round x to the nearest integer, choosing the even integer if it lies halfway between two. - if ((x % 1) === 0.5 && (x & 1) === 0) { // [even number].5; round down (i.e. floor) - return Math.floor(x); - } else { - return Math.round(x); - } -} - -function createNumberConversion(bitLength, typeOpts) { - if (!typeOpts.unsigned) { - --bitLength; - } - const lowerBound = typeOpts.unsigned ? 0 : -Math.pow(2, bitLength); - const upperBound = Math.pow(2, bitLength) - 1; - - const moduloVal = typeOpts.moduloBitLength ? Math.pow(2, typeOpts.moduloBitLength) : Math.pow(2, bitLength); - const moduloBound = typeOpts.moduloBitLength ? Math.pow(2, typeOpts.moduloBitLength - 1) : Math.pow(2, bitLength - 1); - - return function(V, opts) { - if (!opts) opts = {}; - - let x = +V; - - if (opts.enforceRange) { - if (!Number.isFinite(x)) { - throw new TypeError("Argument is not a finite number"); - } - - x = sign(x) * Math.floor(Math.abs(x)); - if (x < lowerBound || x > upperBound) { - throw new TypeError("Argument is not in byte range"); - } - - return x; - } - - if (!isNaN(x) && opts.clamp) { - x = evenRound(x); - - if (x < lowerBound) x = lowerBound; - if (x > upperBound) x = upperBound; - return x; - } - - if (!Number.isFinite(x) || x === 0) { - return 0; - } - - x = sign(x) * Math.floor(Math.abs(x)); - x = x % moduloVal; - - if (!typeOpts.unsigned && x >= moduloBound) { - return x - moduloVal; - } else if (typeOpts.unsigned) { - if (x < 0) { - x += moduloVal; - } else if (x === -0) { // don't return negative zero - return 0; - } - } - - return x; - } -} - -conversions["void"] = function () { - return undefined; -}; - -conversions["boolean"] = function (val) { - return !!val; -}; - -conversions["byte"] = createNumberConversion(8, { unsigned: false }); -conversions["octet"] = createNumberConversion(8, { unsigned: true }); - -conversions["short"] = createNumberConversion(16, { unsigned: false }); -conversions["unsigned short"] = createNumberConversion(16, { unsigned: true }); - -conversions["long"] = createNumberConversion(32, { unsigned: false }); -conversions["unsigned long"] = createNumberConversion(32, { unsigned: true }); - -conversions["long long"] = createNumberConversion(32, { unsigned: false, moduloBitLength: 64 }); -conversions["unsigned long long"] = createNumberConversion(32, { unsigned: true, moduloBitLength: 64 }); - -conversions["double"] = function (V) { - const x = +V; - - if (!Number.isFinite(x)) { - throw new TypeError("Argument is not a finite floating-point value"); - } - - return x; -}; - -conversions["unrestricted double"] = function (V) { - const x = +V; - - if (isNaN(x)) { - throw new TypeError("Argument is NaN"); - } - - return x; -}; - -// not quite valid, but good enough for JS -conversions["float"] = conversions["double"]; -conversions["unrestricted float"] = conversions["unrestricted double"]; - -conversions["DOMString"] = function (V, opts) { - if (!opts) opts = {}; - - if (opts.treatNullAsEmptyString && V === null) { - return ""; - } - - return String(V); -}; - -conversions["ByteString"] = function (V, opts) { - const x = String(V); - let c = undefined; - for (let i = 0; (c = x.codePointAt(i)) !== undefined; ++i) { - if (c > 255) { - throw new TypeError("Argument is not a valid bytestring"); - } - } - - return x; -}; - -conversions["USVString"] = function (V) { - const S = String(V); - const n = S.length; - const U = []; - for (let i = 0; i < n; ++i) { - const c = S.charCodeAt(i); - if (c < 0xD800 || c > 0xDFFF) { - U.push(String.fromCodePoint(c)); - } else if (0xDC00 <= c && c <= 0xDFFF) { - U.push(String.fromCodePoint(0xFFFD)); - } else { - if (i === n - 1) { - U.push(String.fromCodePoint(0xFFFD)); - } else { - const d = S.charCodeAt(i + 1); - if (0xDC00 <= d && d <= 0xDFFF) { - const a = c & 0x3FF; - const b = d & 0x3FF; - U.push(String.fromCodePoint((2 << 15) + (2 << 9) * a + b)); - ++i; - } else { - U.push(String.fromCodePoint(0xFFFD)); - } - } - } - } - - return U.join(''); -}; - -conversions["Date"] = function (V, opts) { - if (!(V instanceof Date)) { - throw new TypeError("Argument is not a Date object"); - } - if (isNaN(V)) { - return undefined; - } - - return V; -}; - -conversions["RegExp"] = function (V, opts) { - if (!(V instanceof RegExp)) { - V = new RegExp(V); - } - - return V; -}; diff --git a/node_modules/webidl-conversions/package.json b/node_modules/webidl-conversions/package.json deleted file mode 100644 index c31bc074..00000000 --- a/node_modules/webidl-conversions/package.json +++ /dev/null @@ -1,23 +0,0 @@ -{ - "name": "webidl-conversions", - "version": "3.0.1", - "description": "Implements the WebIDL algorithms for converting to and from JavaScript values", - "main": "lib/index.js", - "scripts": { - "test": "mocha test/*.js" - }, - "repository": "jsdom/webidl-conversions", - "keywords": [ - "webidl", - "web", - "types" - ], - "files": [ - "lib/" - ], - "author": "Domenic Denicola (https://domenic.me/)", - "license": "BSD-2-Clause", - "devDependencies": { - "mocha": "^1.21.4" - } -} diff --git a/node_modules/whatwg-url/LICENSE.txt b/node_modules/whatwg-url/LICENSE.txt deleted file mode 100644 index 54dfac39..00000000 --- a/node_modules/whatwg-url/LICENSE.txt +++ /dev/null @@ -1,21 +0,0 @@ -The MIT License (MIT) - -Copyright (c) 2015–2016 Sebastian Mayr - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in -all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -THE SOFTWARE. diff --git a/node_modules/whatwg-url/README.md b/node_modules/whatwg-url/README.md deleted file mode 100644 index 4347a7fc..00000000 --- a/node_modules/whatwg-url/README.md +++ /dev/null @@ -1,67 +0,0 @@ -# whatwg-url - -whatwg-url is a full implementation of the WHATWG [URL Standard](https://url.spec.whatwg.org/). It can be used standalone, but it also exposes a lot of the internal algorithms that are useful for integrating a URL parser into a project like [jsdom](https://github.com/tmpvar/jsdom). - -## Current Status - -whatwg-url is currently up to date with the URL spec up to commit [a62223](https://github.com/whatwg/url/commit/a622235308342c9adc7fc2fd1659ff059f7d5e2a). - -## API - -### The `URL` Constructor - -The main API is the [`URL`](https://url.spec.whatwg.org/#url) export, which follows the spec's behavior in all ways (including e.g. `USVString` conversion). Most consumers of this library will want to use this. - -### Low-level URL Standard API - -The following methods are exported for use by places like jsdom that need to implement things like [`HTMLHyperlinkElementUtils`](https://html.spec.whatwg.org/#htmlhyperlinkelementutils). They operate on or return an "internal URL" or ["URL record"](https://url.spec.whatwg.org/#concept-url) type. - -- [URL parser](https://url.spec.whatwg.org/#concept-url-parser): `parseURL(input, { baseURL, encodingOverride })` -- [Basic URL parser](https://url.spec.whatwg.org/#concept-basic-url-parser): `basicURLParse(input, { baseURL, encodingOverride, url, stateOverride })` -- [URL serializer](https://url.spec.whatwg.org/#concept-url-serializer): `serializeURL(urlRecord, excludeFragment)` -- [Host serializer](https://url.spec.whatwg.org/#concept-host-serializer): `serializeHost(hostFromURLRecord)` -- [Serialize an integer](https://url.spec.whatwg.org/#serialize-an-integer): `serializeInteger(number)` -- [Origin](https://url.spec.whatwg.org/#concept-url-origin) [serializer](https://html.spec.whatwg.org/multipage/browsers.html#serialization-of-an-origin): `serializeURLOrigin(urlRecord)` -- [Set the username](https://url.spec.whatwg.org/#set-the-username): `setTheUsername(urlRecord, usernameString)` -- [Set the password](https://url.spec.whatwg.org/#set-the-password): `setThePassword(urlRecord, passwordString)` -- [Cannot have a username/password/port](https://url.spec.whatwg.org/#cannot-have-a-username-password-port): `cannotHaveAUsernamePasswordPort(urlRecord)` - -The `stateOverride` parameter is one of the following strings: - -- [`"scheme start"`](https://url.spec.whatwg.org/#scheme-start-state) -- [`"scheme"`](https://url.spec.whatwg.org/#scheme-state) -- [`"no scheme"`](https://url.spec.whatwg.org/#no-scheme-state) -- [`"special relative or authority"`](https://url.spec.whatwg.org/#special-relative-or-authority-state) -- [`"path or authority"`](https://url.spec.whatwg.org/#path-or-authority-state) -- [`"relative"`](https://url.spec.whatwg.org/#relative-state) -- [`"relative slash"`](https://url.spec.whatwg.org/#relative-slash-state) -- [`"special authority slashes"`](https://url.spec.whatwg.org/#special-authority-slashes-state) -- [`"special authority ignore slashes"`](https://url.spec.whatwg.org/#special-authority-ignore-slashes-state) -- [`"authority"`](https://url.spec.whatwg.org/#authority-state) -- [`"host"`](https://url.spec.whatwg.org/#host-state) -- [`"hostname"`](https://url.spec.whatwg.org/#hostname-state) -- [`"port"`](https://url.spec.whatwg.org/#port-state) -- [`"file"`](https://url.spec.whatwg.org/#file-state) -- [`"file slash"`](https://url.spec.whatwg.org/#file-slash-state) -- [`"file host"`](https://url.spec.whatwg.org/#file-host-state) -- [`"path start"`](https://url.spec.whatwg.org/#path-start-state) -- [`"path"`](https://url.spec.whatwg.org/#path-state) -- [`"cannot-be-a-base-URL path"`](https://url.spec.whatwg.org/#cannot-be-a-base-url-path-state) -- [`"query"`](https://url.spec.whatwg.org/#query-state) -- [`"fragment"`](https://url.spec.whatwg.org/#fragment-state) - -The URL record type has the following API: - -- [`scheme`](https://url.spec.whatwg.org/#concept-url-scheme) -- [`username`](https://url.spec.whatwg.org/#concept-url-username) -- [`password`](https://url.spec.whatwg.org/#concept-url-password) -- [`host`](https://url.spec.whatwg.org/#concept-url-host) -- [`port`](https://url.spec.whatwg.org/#concept-url-port) -- [`path`](https://url.spec.whatwg.org/#concept-url-path) (as an array) -- [`query`](https://url.spec.whatwg.org/#concept-url-query) -- [`fragment`](https://url.spec.whatwg.org/#concept-url-fragment) -- [`cannotBeABaseURL`](https://url.spec.whatwg.org/#url-cannot-be-a-base-url-flag) (as a boolean) - -These properties should be treated with care, as in general changing them will cause the URL record to be in an inconsistent state until the appropriate invocation of `basicURLParse` is used to fix it up. You can see examples of this in the URL Standard, where there are many step sequences like "4. Set context object’s url’s fragment to the empty string. 5. Basic URL parse _input_ with context object’s url as _url_ and fragment state as _state override_." In between those two steps, a URL record is in an unusable state. - -The return value of "failure" in the spec is represented by the string `"failure"`. That is, functions like `parseURL` and `basicURLParse` can return _either_ a URL record _or_ the string `"failure"`. diff --git a/node_modules/whatwg-url/lib/URL-impl.js b/node_modules/whatwg-url/lib/URL-impl.js deleted file mode 100644 index dc7452cc..00000000 --- a/node_modules/whatwg-url/lib/URL-impl.js +++ /dev/null @@ -1,200 +0,0 @@ -"use strict"; -const usm = require("./url-state-machine"); - -exports.implementation = class URLImpl { - constructor(constructorArgs) { - const url = constructorArgs[0]; - const base = constructorArgs[1]; - - let parsedBase = null; - if (base !== undefined) { - parsedBase = usm.basicURLParse(base); - if (parsedBase === "failure") { - throw new TypeError("Invalid base URL"); - } - } - - const parsedURL = usm.basicURLParse(url, { baseURL: parsedBase }); - if (parsedURL === "failure") { - throw new TypeError("Invalid URL"); - } - - this._url = parsedURL; - - // TODO: query stuff - } - - get href() { - return usm.serializeURL(this._url); - } - - set href(v) { - const parsedURL = usm.basicURLParse(v); - if (parsedURL === "failure") { - throw new TypeError("Invalid URL"); - } - - this._url = parsedURL; - } - - get origin() { - return usm.serializeURLOrigin(this._url); - } - - get protocol() { - return this._url.scheme + ":"; - } - - set protocol(v) { - usm.basicURLParse(v + ":", { url: this._url, stateOverride: "scheme start" }); - } - - get username() { - return this._url.username; - } - - set username(v) { - if (usm.cannotHaveAUsernamePasswordPort(this._url)) { - return; - } - - usm.setTheUsername(this._url, v); - } - - get password() { - return this._url.password; - } - - set password(v) { - if (usm.cannotHaveAUsernamePasswordPort(this._url)) { - return; - } - - usm.setThePassword(this._url, v); - } - - get host() { - const url = this._url; - - if (url.host === null) { - return ""; - } - - if (url.port === null) { - return usm.serializeHost(url.host); - } - - return usm.serializeHost(url.host) + ":" + usm.serializeInteger(url.port); - } - - set host(v) { - if (this._url.cannotBeABaseURL) { - return; - } - - usm.basicURLParse(v, { url: this._url, stateOverride: "host" }); - } - - get hostname() { - if (this._url.host === null) { - return ""; - } - - return usm.serializeHost(this._url.host); - } - - set hostname(v) { - if (this._url.cannotBeABaseURL) { - return; - } - - usm.basicURLParse(v, { url: this._url, stateOverride: "hostname" }); - } - - get port() { - if (this._url.port === null) { - return ""; - } - - return usm.serializeInteger(this._url.port); - } - - set port(v) { - if (usm.cannotHaveAUsernamePasswordPort(this._url)) { - return; - } - - if (v === "") { - this._url.port = null; - } else { - usm.basicURLParse(v, { url: this._url, stateOverride: "port" }); - } - } - - get pathname() { - if (this._url.cannotBeABaseURL) { - return this._url.path[0]; - } - - if (this._url.path.length === 0) { - return ""; - } - - return "/" + this._url.path.join("/"); - } - - set pathname(v) { - if (this._url.cannotBeABaseURL) { - return; - } - - this._url.path = []; - usm.basicURLParse(v, { url: this._url, stateOverride: "path start" }); - } - - get search() { - if (this._url.query === null || this._url.query === "") { - return ""; - } - - return "?" + this._url.query; - } - - set search(v) { - // TODO: query stuff - - const url = this._url; - - if (v === "") { - url.query = null; - return; - } - - const input = v[0] === "?" ? v.substring(1) : v; - url.query = ""; - usm.basicURLParse(input, { url, stateOverride: "query" }); - } - - get hash() { - if (this._url.fragment === null || this._url.fragment === "") { - return ""; - } - - return "#" + this._url.fragment; - } - - set hash(v) { - if (v === "") { - this._url.fragment = null; - return; - } - - const input = v[0] === "#" ? v.substring(1) : v; - this._url.fragment = ""; - usm.basicURLParse(input, { url: this._url, stateOverride: "fragment" }); - } - - toJSON() { - return this.href; - } -}; diff --git a/node_modules/whatwg-url/lib/URL.js b/node_modules/whatwg-url/lib/URL.js deleted file mode 100644 index 78c7207e..00000000 --- a/node_modules/whatwg-url/lib/URL.js +++ /dev/null @@ -1,196 +0,0 @@ -"use strict"; - -const conversions = require("webidl-conversions"); -const utils = require("./utils.js"); -const Impl = require(".//URL-impl.js"); - -const impl = utils.implSymbol; - -function URL(url) { - if (!this || this[impl] || !(this instanceof URL)) { - throw new TypeError("Failed to construct 'URL': Please use the 'new' operator, this DOM object constructor cannot be called as a function."); - } - if (arguments.length < 1) { - throw new TypeError("Failed to construct 'URL': 1 argument required, but only " + arguments.length + " present."); - } - const args = []; - for (let i = 0; i < arguments.length && i < 2; ++i) { - args[i] = arguments[i]; - } - args[0] = conversions["USVString"](args[0]); - if (args[1] !== undefined) { - args[1] = conversions["USVString"](args[1]); - } - - module.exports.setup(this, args); -} - -URL.prototype.toJSON = function toJSON() { - if (!this || !module.exports.is(this)) { - throw new TypeError("Illegal invocation"); - } - const args = []; - for (let i = 0; i < arguments.length && i < 0; ++i) { - args[i] = arguments[i]; - } - return this[impl].toJSON.apply(this[impl], args); -}; -Object.defineProperty(URL.prototype, "href", { - get() { - return this[impl].href; - }, - set(V) { - V = conversions["USVString"](V); - this[impl].href = V; - }, - enumerable: true, - configurable: true -}); - -URL.prototype.toString = function () { - if (!this || !module.exports.is(this)) { - throw new TypeError("Illegal invocation"); - } - return this.href; -}; - -Object.defineProperty(URL.prototype, "origin", { - get() { - return this[impl].origin; - }, - enumerable: true, - configurable: true -}); - -Object.defineProperty(URL.prototype, "protocol", { - get() { - return this[impl].protocol; - }, - set(V) { - V = conversions["USVString"](V); - this[impl].protocol = V; - }, - enumerable: true, - configurable: true -}); - -Object.defineProperty(URL.prototype, "username", { - get() { - return this[impl].username; - }, - set(V) { - V = conversions["USVString"](V); - this[impl].username = V; - }, - enumerable: true, - configurable: true -}); - -Object.defineProperty(URL.prototype, "password", { - get() { - return this[impl].password; - }, - set(V) { - V = conversions["USVString"](V); - this[impl].password = V; - }, - enumerable: true, - configurable: true -}); - -Object.defineProperty(URL.prototype, "host", { - get() { - return this[impl].host; - }, - set(V) { - V = conversions["USVString"](V); - this[impl].host = V; - }, - enumerable: true, - configurable: true -}); - -Object.defineProperty(URL.prototype, "hostname", { - get() { - return this[impl].hostname; - }, - set(V) { - V = conversions["USVString"](V); - this[impl].hostname = V; - }, - enumerable: true, - configurable: true -}); - -Object.defineProperty(URL.prototype, "port", { - get() { - return this[impl].port; - }, - set(V) { - V = conversions["USVString"](V); - this[impl].port = V; - }, - enumerable: true, - configurable: true -}); - -Object.defineProperty(URL.prototype, "pathname", { - get() { - return this[impl].pathname; - }, - set(V) { - V = conversions["USVString"](V); - this[impl].pathname = V; - }, - enumerable: true, - configurable: true -}); - -Object.defineProperty(URL.prototype, "search", { - get() { - return this[impl].search; - }, - set(V) { - V = conversions["USVString"](V); - this[impl].search = V; - }, - enumerable: true, - configurable: true -}); - -Object.defineProperty(URL.prototype, "hash", { - get() { - return this[impl].hash; - }, - set(V) { - V = conversions["USVString"](V); - this[impl].hash = V; - }, - enumerable: true, - configurable: true -}); - - -module.exports = { - is(obj) { - return !!obj && obj[impl] instanceof Impl.implementation; - }, - create(constructorArgs, privateData) { - let obj = Object.create(URL.prototype); - this.setup(obj, constructorArgs, privateData); - return obj; - }, - setup(obj, constructorArgs, privateData) { - if (!privateData) privateData = {}; - privateData.wrapper = obj; - - obj[impl] = new Impl.implementation(constructorArgs, privateData); - obj[impl][utils.wrapperSymbol] = obj; - }, - interface: URL, - expose: { - Window: { URL: URL }, - Worker: { URL: URL } - } -}; - diff --git a/node_modules/whatwg-url/lib/public-api.js b/node_modules/whatwg-url/lib/public-api.js deleted file mode 100644 index 932dcada..00000000 --- a/node_modules/whatwg-url/lib/public-api.js +++ /dev/null @@ -1,11 +0,0 @@ -"use strict"; - -exports.URL = require("./URL").interface; -exports.serializeURL = require("./url-state-machine").serializeURL; -exports.serializeURLOrigin = require("./url-state-machine").serializeURLOrigin; -exports.basicURLParse = require("./url-state-machine").basicURLParse; -exports.setTheUsername = require("./url-state-machine").setTheUsername; -exports.setThePassword = require("./url-state-machine").setThePassword; -exports.serializeHost = require("./url-state-machine").serializeHost; -exports.serializeInteger = require("./url-state-machine").serializeInteger; -exports.parseURL = require("./url-state-machine").parseURL; diff --git a/node_modules/whatwg-url/lib/url-state-machine.js b/node_modules/whatwg-url/lib/url-state-machine.js deleted file mode 100644 index c25dbc2c..00000000 --- a/node_modules/whatwg-url/lib/url-state-machine.js +++ /dev/null @@ -1,1297 +0,0 @@ -"use strict"; -const punycode = require("punycode"); -const tr46 = require("tr46"); - -const specialSchemes = { - ftp: 21, - file: null, - gopher: 70, - http: 80, - https: 443, - ws: 80, - wss: 443 -}; - -const failure = Symbol("failure"); - -function countSymbols(str) { - return punycode.ucs2.decode(str).length; -} - -function at(input, idx) { - const c = input[idx]; - return isNaN(c) ? undefined : String.fromCodePoint(c); -} - -function isASCIIDigit(c) { - return c >= 0x30 && c <= 0x39; -} - -function isASCIIAlpha(c) { - return (c >= 0x41 && c <= 0x5A) || (c >= 0x61 && c <= 0x7A); -} - -function isASCIIAlphanumeric(c) { - return isASCIIAlpha(c) || isASCIIDigit(c); -} - -function isASCIIHex(c) { - return isASCIIDigit(c) || (c >= 0x41 && c <= 0x46) || (c >= 0x61 && c <= 0x66); -} - -function isSingleDot(buffer) { - return buffer === "." || buffer.toLowerCase() === "%2e"; -} - -function isDoubleDot(buffer) { - buffer = buffer.toLowerCase(); - return buffer === ".." || buffer === "%2e." || buffer === ".%2e" || buffer === "%2e%2e"; -} - -function isWindowsDriveLetterCodePoints(cp1, cp2) { - return isASCIIAlpha(cp1) && (cp2 === 58 || cp2 === 124); -} - -function isWindowsDriveLetterString(string) { - return string.length === 2 && isASCIIAlpha(string.codePointAt(0)) && (string[1] === ":" || string[1] === "|"); -} - -function isNormalizedWindowsDriveLetterString(string) { - return string.length === 2 && isASCIIAlpha(string.codePointAt(0)) && string[1] === ":"; -} - -function containsForbiddenHostCodePoint(string) { - return string.search(/\u0000|\u0009|\u000A|\u000D|\u0020|#|%|\/|:|\?|@|\[|\\|\]/) !== -1; -} - -function containsForbiddenHostCodePointExcludingPercent(string) { - return string.search(/\u0000|\u0009|\u000A|\u000D|\u0020|#|\/|:|\?|@|\[|\\|\]/) !== -1; -} - -function isSpecialScheme(scheme) { - return specialSchemes[scheme] !== undefined; -} - -function isSpecial(url) { - return isSpecialScheme(url.scheme); -} - -function defaultPort(scheme) { - return specialSchemes[scheme]; -} - -function percentEncode(c) { - let hex = c.toString(16).toUpperCase(); - if (hex.length === 1) { - hex = "0" + hex; - } - - return "%" + hex; -} - -function utf8PercentEncode(c) { - const buf = new Buffer(c); - - let str = ""; - - for (let i = 0; i < buf.length; ++i) { - str += percentEncode(buf[i]); - } - - return str; -} - -function utf8PercentDecode(str) { - const input = new Buffer(str); - const output = []; - for (let i = 0; i < input.length; ++i) { - if (input[i] !== 37) { - output.push(input[i]); - } else if (input[i] === 37 && isASCIIHex(input[i + 1]) && isASCIIHex(input[i + 2])) { - output.push(parseInt(input.slice(i + 1, i + 3).toString(), 16)); - i += 2; - } else { - output.push(input[i]); - } - } - return new Buffer(output).toString(); -} - -function isC0ControlPercentEncode(c) { - return c <= 0x1F || c > 0x7E; -} - -const extraPathPercentEncodeSet = new Set([32, 34, 35, 60, 62, 63, 96, 123, 125]); -function isPathPercentEncode(c) { - return isC0ControlPercentEncode(c) || extraPathPercentEncodeSet.has(c); -} - -const extraUserinfoPercentEncodeSet = - new Set([47, 58, 59, 61, 64, 91, 92, 93, 94, 124]); -function isUserinfoPercentEncode(c) { - return isPathPercentEncode(c) || extraUserinfoPercentEncodeSet.has(c); -} - -function percentEncodeChar(c, encodeSetPredicate) { - const cStr = String.fromCodePoint(c); - - if (encodeSetPredicate(c)) { - return utf8PercentEncode(cStr); - } - - return cStr; -} - -function parseIPv4Number(input) { - let R = 10; - - if (input.length >= 2 && input.charAt(0) === "0" && input.charAt(1).toLowerCase() === "x") { - input = input.substring(2); - R = 16; - } else if (input.length >= 2 && input.charAt(0) === "0") { - input = input.substring(1); - R = 8; - } - - if (input === "") { - return 0; - } - - const regex = R === 10 ? /[^0-9]/ : (R === 16 ? /[^0-9A-Fa-f]/ : /[^0-7]/); - if (regex.test(input)) { - return failure; - } - - return parseInt(input, R); -} - -function parseIPv4(input) { - const parts = input.split("."); - if (parts[parts.length - 1] === "") { - if (parts.length > 1) { - parts.pop(); - } - } - - if (parts.length > 4) { - return input; - } - - const numbers = []; - for (const part of parts) { - if (part === "") { - return input; - } - const n = parseIPv4Number(part); - if (n === failure) { - return input; - } - - numbers.push(n); - } - - for (let i = 0; i < numbers.length - 1; ++i) { - if (numbers[i] > 255) { - return failure; - } - } - if (numbers[numbers.length - 1] >= Math.pow(256, 5 - numbers.length)) { - return failure; - } - - let ipv4 = numbers.pop(); - let counter = 0; - - for (const n of numbers) { - ipv4 += n * Math.pow(256, 3 - counter); - ++counter; - } - - return ipv4; -} - -function serializeIPv4(address) { - let output = ""; - let n = address; - - for (let i = 1; i <= 4; ++i) { - output = String(n % 256) + output; - if (i !== 4) { - output = "." + output; - } - n = Math.floor(n / 256); - } - - return output; -} - -function parseIPv6(input) { - const address = [0, 0, 0, 0, 0, 0, 0, 0]; - let pieceIndex = 0; - let compress = null; - let pointer = 0; - - input = punycode.ucs2.decode(input); - - if (input[pointer] === 58) { - if (input[pointer + 1] !== 58) { - return failure; - } - - pointer += 2; - ++pieceIndex; - compress = pieceIndex; - } - - while (pointer < input.length) { - if (pieceIndex === 8) { - return failure; - } - - if (input[pointer] === 58) { - if (compress !== null) { - return failure; - } - ++pointer; - ++pieceIndex; - compress = pieceIndex; - continue; - } - - let value = 0; - let length = 0; - - while (length < 4 && isASCIIHex(input[pointer])) { - value = value * 0x10 + parseInt(at(input, pointer), 16); - ++pointer; - ++length; - } - - if (input[pointer] === 46) { - if (length === 0) { - return failure; - } - - pointer -= length; - - if (pieceIndex > 6) { - return failure; - } - - let numbersSeen = 0; - - while (input[pointer] !== undefined) { - let ipv4Piece = null; - - if (numbersSeen > 0) { - if (input[pointer] === 46 && numbersSeen < 4) { - ++pointer; - } else { - return failure; - } - } - - if (!isASCIIDigit(input[pointer])) { - return failure; - } - - while (isASCIIDigit(input[pointer])) { - const number = parseInt(at(input, pointer)); - if (ipv4Piece === null) { - ipv4Piece = number; - } else if (ipv4Piece === 0) { - return failure; - } else { - ipv4Piece = ipv4Piece * 10 + number; - } - if (ipv4Piece > 255) { - return failure; - } - ++pointer; - } - - address[pieceIndex] = address[pieceIndex] * 0x100 + ipv4Piece; - - ++numbersSeen; - - if (numbersSeen === 2 || numbersSeen === 4) { - ++pieceIndex; - } - } - - if (numbersSeen !== 4) { - return failure; - } - - break; - } else if (input[pointer] === 58) { - ++pointer; - if (input[pointer] === undefined) { - return failure; - } - } else if (input[pointer] !== undefined) { - return failure; - } - - address[pieceIndex] = value; - ++pieceIndex; - } - - if (compress !== null) { - let swaps = pieceIndex - compress; - pieceIndex = 7; - while (pieceIndex !== 0 && swaps > 0) { - const temp = address[compress + swaps - 1]; - address[compress + swaps - 1] = address[pieceIndex]; - address[pieceIndex] = temp; - --pieceIndex; - --swaps; - } - } else if (compress === null && pieceIndex !== 8) { - return failure; - } - - return address; -} - -function serializeIPv6(address) { - let output = ""; - const seqResult = findLongestZeroSequence(address); - const compress = seqResult.idx; - let ignore0 = false; - - for (let pieceIndex = 0; pieceIndex <= 7; ++pieceIndex) { - if (ignore0 && address[pieceIndex] === 0) { - continue; - } else if (ignore0) { - ignore0 = false; - } - - if (compress === pieceIndex) { - const separator = pieceIndex === 0 ? "::" : ":"; - output += separator; - ignore0 = true; - continue; - } - - output += address[pieceIndex].toString(16); - - if (pieceIndex !== 7) { - output += ":"; - } - } - - return output; -} - -function parseHost(input, isSpecialArg) { - if (input[0] === "[") { - if (input[input.length - 1] !== "]") { - return failure; - } - - return parseIPv6(input.substring(1, input.length - 1)); - } - - if (!isSpecialArg) { - return parseOpaqueHost(input); - } - - const domain = utf8PercentDecode(input); - const asciiDomain = tr46.toASCII(domain, false, tr46.PROCESSING_OPTIONS.NONTRANSITIONAL, false); - if (asciiDomain === null) { - return failure; - } - - if (containsForbiddenHostCodePoint(asciiDomain)) { - return failure; - } - - const ipv4Host = parseIPv4(asciiDomain); - if (typeof ipv4Host === "number" || ipv4Host === failure) { - return ipv4Host; - } - - return asciiDomain; -} - -function parseOpaqueHost(input) { - if (containsForbiddenHostCodePointExcludingPercent(input)) { - return failure; - } - - let output = ""; - const decoded = punycode.ucs2.decode(input); - for (let i = 0; i < decoded.length; ++i) { - output += percentEncodeChar(decoded[i], isC0ControlPercentEncode); - } - return output; -} - -function findLongestZeroSequence(arr) { - let maxIdx = null; - let maxLen = 1; // only find elements > 1 - let currStart = null; - let currLen = 0; - - for (let i = 0; i < arr.length; ++i) { - if (arr[i] !== 0) { - if (currLen > maxLen) { - maxIdx = currStart; - maxLen = currLen; - } - - currStart = null; - currLen = 0; - } else { - if (currStart === null) { - currStart = i; - } - ++currLen; - } - } - - // if trailing zeros - if (currLen > maxLen) { - maxIdx = currStart; - maxLen = currLen; - } - - return { - idx: maxIdx, - len: maxLen - }; -} - -function serializeHost(host) { - if (typeof host === "number") { - return serializeIPv4(host); - } - - // IPv6 serializer - if (host instanceof Array) { - return "[" + serializeIPv6(host) + "]"; - } - - return host; -} - -function trimControlChars(url) { - return url.replace(/^[\u0000-\u001F\u0020]+|[\u0000-\u001F\u0020]+$/g, ""); -} - -function trimTabAndNewline(url) { - return url.replace(/\u0009|\u000A|\u000D/g, ""); -} - -function shortenPath(url) { - const path = url.path; - if (path.length === 0) { - return; - } - if (url.scheme === "file" && path.length === 1 && isNormalizedWindowsDriveLetter(path[0])) { - return; - } - - path.pop(); -} - -function includesCredentials(url) { - return url.username !== "" || url.password !== ""; -} - -function cannotHaveAUsernamePasswordPort(url) { - return url.host === null || url.host === "" || url.cannotBeABaseURL || url.scheme === "file"; -} - -function isNormalizedWindowsDriveLetter(string) { - return /^[A-Za-z]:$/.test(string); -} - -function URLStateMachine(input, base, encodingOverride, url, stateOverride) { - this.pointer = 0; - this.input = input; - this.base = base || null; - this.encodingOverride = encodingOverride || "utf-8"; - this.stateOverride = stateOverride; - this.url = url; - this.failure = false; - this.parseError = false; - - if (!this.url) { - this.url = { - scheme: "", - username: "", - password: "", - host: null, - port: null, - path: [], - query: null, - fragment: null, - - cannotBeABaseURL: false - }; - - const res = trimControlChars(this.input); - if (res !== this.input) { - this.parseError = true; - } - this.input = res; - } - - const res = trimTabAndNewline(this.input); - if (res !== this.input) { - this.parseError = true; - } - this.input = res; - - this.state = stateOverride || "scheme start"; - - this.buffer = ""; - this.atFlag = false; - this.arrFlag = false; - this.passwordTokenSeenFlag = false; - - this.input = punycode.ucs2.decode(this.input); - - for (; this.pointer <= this.input.length; ++this.pointer) { - const c = this.input[this.pointer]; - const cStr = isNaN(c) ? undefined : String.fromCodePoint(c); - - // exec state machine - const ret = this["parse " + this.state](c, cStr); - if (!ret) { - break; // terminate algorithm - } else if (ret === failure) { - this.failure = true; - break; - } - } -} - -URLStateMachine.prototype["parse scheme start"] = function parseSchemeStart(c, cStr) { - if (isASCIIAlpha(c)) { - this.buffer += cStr.toLowerCase(); - this.state = "scheme"; - } else if (!this.stateOverride) { - this.state = "no scheme"; - --this.pointer; - } else { - this.parseError = true; - return failure; - } - - return true; -}; - -URLStateMachine.prototype["parse scheme"] = function parseScheme(c, cStr) { - if (isASCIIAlphanumeric(c) || c === 43 || c === 45 || c === 46) { - this.buffer += cStr.toLowerCase(); - } else if (c === 58) { - if (this.stateOverride) { - if (isSpecial(this.url) && !isSpecialScheme(this.buffer)) { - return false; - } - - if (!isSpecial(this.url) && isSpecialScheme(this.buffer)) { - return false; - } - - if ((includesCredentials(this.url) || this.url.port !== null) && this.buffer === "file") { - return false; - } - - if (this.url.scheme === "file" && (this.url.host === "" || this.url.host === null)) { - return false; - } - } - this.url.scheme = this.buffer; - this.buffer = ""; - if (this.stateOverride) { - return false; - } - if (this.url.scheme === "file") { - if (this.input[this.pointer + 1] !== 47 || this.input[this.pointer + 2] !== 47) { - this.parseError = true; - } - this.state = "file"; - } else if (isSpecial(this.url) && this.base !== null && this.base.scheme === this.url.scheme) { - this.state = "special relative or authority"; - } else if (isSpecial(this.url)) { - this.state = "special authority slashes"; - } else if (this.input[this.pointer + 1] === 47) { - this.state = "path or authority"; - ++this.pointer; - } else { - this.url.cannotBeABaseURL = true; - this.url.path.push(""); - this.state = "cannot-be-a-base-URL path"; - } - } else if (!this.stateOverride) { - this.buffer = ""; - this.state = "no scheme"; - this.pointer = -1; - } else { - this.parseError = true; - return failure; - } - - return true; -}; - -URLStateMachine.prototype["parse no scheme"] = function parseNoScheme(c) { - if (this.base === null || (this.base.cannotBeABaseURL && c !== 35)) { - return failure; - } else if (this.base.cannotBeABaseURL && c === 35) { - this.url.scheme = this.base.scheme; - this.url.path = this.base.path.slice(); - this.url.query = this.base.query; - this.url.fragment = ""; - this.url.cannotBeABaseURL = true; - this.state = "fragment"; - } else if (this.base.scheme === "file") { - this.state = "file"; - --this.pointer; - } else { - this.state = "relative"; - --this.pointer; - } - - return true; -}; - -URLStateMachine.prototype["parse special relative or authority"] = function parseSpecialRelativeOrAuthority(c) { - if (c === 47 && this.input[this.pointer + 1] === 47) { - this.state = "special authority ignore slashes"; - ++this.pointer; - } else { - this.parseError = true; - this.state = "relative"; - --this.pointer; - } - - return true; -}; - -URLStateMachine.prototype["parse path or authority"] = function parsePathOrAuthority(c) { - if (c === 47) { - this.state = "authority"; - } else { - this.state = "path"; - --this.pointer; - } - - return true; -}; - -URLStateMachine.prototype["parse relative"] = function parseRelative(c) { - this.url.scheme = this.base.scheme; - if (isNaN(c)) { - this.url.username = this.base.username; - this.url.password = this.base.password; - this.url.host = this.base.host; - this.url.port = this.base.port; - this.url.path = this.base.path.slice(); - this.url.query = this.base.query; - } else if (c === 47) { - this.state = "relative slash"; - } else if (c === 63) { - this.url.username = this.base.username; - this.url.password = this.base.password; - this.url.host = this.base.host; - this.url.port = this.base.port; - this.url.path = this.base.path.slice(); - this.url.query = ""; - this.state = "query"; - } else if (c === 35) { - this.url.username = this.base.username; - this.url.password = this.base.password; - this.url.host = this.base.host; - this.url.port = this.base.port; - this.url.path = this.base.path.slice(); - this.url.query = this.base.query; - this.url.fragment = ""; - this.state = "fragment"; - } else if (isSpecial(this.url) && c === 92) { - this.parseError = true; - this.state = "relative slash"; - } else { - this.url.username = this.base.username; - this.url.password = this.base.password; - this.url.host = this.base.host; - this.url.port = this.base.port; - this.url.path = this.base.path.slice(0, this.base.path.length - 1); - - this.state = "path"; - --this.pointer; - } - - return true; -}; - -URLStateMachine.prototype["parse relative slash"] = function parseRelativeSlash(c) { - if (isSpecial(this.url) && (c === 47 || c === 92)) { - if (c === 92) { - this.parseError = true; - } - this.state = "special authority ignore slashes"; - } else if (c === 47) { - this.state = "authority"; - } else { - this.url.username = this.base.username; - this.url.password = this.base.password; - this.url.host = this.base.host; - this.url.port = this.base.port; - this.state = "path"; - --this.pointer; - } - - return true; -}; - -URLStateMachine.prototype["parse special authority slashes"] = function parseSpecialAuthoritySlashes(c) { - if (c === 47 && this.input[this.pointer + 1] === 47) { - this.state = "special authority ignore slashes"; - ++this.pointer; - } else { - this.parseError = true; - this.state = "special authority ignore slashes"; - --this.pointer; - } - - return true; -}; - -URLStateMachine.prototype["parse special authority ignore slashes"] = function parseSpecialAuthorityIgnoreSlashes(c) { - if (c !== 47 && c !== 92) { - this.state = "authority"; - --this.pointer; - } else { - this.parseError = true; - } - - return true; -}; - -URLStateMachine.prototype["parse authority"] = function parseAuthority(c, cStr) { - if (c === 64) { - this.parseError = true; - if (this.atFlag) { - this.buffer = "%40" + this.buffer; - } - this.atFlag = true; - - // careful, this is based on buffer and has its own pointer (this.pointer != pointer) and inner chars - const len = countSymbols(this.buffer); - for (let pointer = 0; pointer < len; ++pointer) { - const codePoint = this.buffer.codePointAt(pointer); - - if (codePoint === 58 && !this.passwordTokenSeenFlag) { - this.passwordTokenSeenFlag = true; - continue; - } - const encodedCodePoints = percentEncodeChar(codePoint, isUserinfoPercentEncode); - if (this.passwordTokenSeenFlag) { - this.url.password += encodedCodePoints; - } else { - this.url.username += encodedCodePoints; - } - } - this.buffer = ""; - } else if (isNaN(c) || c === 47 || c === 63 || c === 35 || - (isSpecial(this.url) && c === 92)) { - if (this.atFlag && this.buffer === "") { - this.parseError = true; - return failure; - } - this.pointer -= countSymbols(this.buffer) + 1; - this.buffer = ""; - this.state = "host"; - } else { - this.buffer += cStr; - } - - return true; -}; - -URLStateMachine.prototype["parse hostname"] = -URLStateMachine.prototype["parse host"] = function parseHostName(c, cStr) { - if (this.stateOverride && this.url.scheme === "file") { - --this.pointer; - this.state = "file host"; - } else if (c === 58 && !this.arrFlag) { - if (this.buffer === "") { - this.parseError = true; - return failure; - } - - const host = parseHost(this.buffer, isSpecial(this.url)); - if (host === failure) { - return failure; - } - - this.url.host = host; - this.buffer = ""; - this.state = "port"; - if (this.stateOverride === "hostname") { - return false; - } - } else if (isNaN(c) || c === 47 || c === 63 || c === 35 || - (isSpecial(this.url) && c === 92)) { - --this.pointer; - if (isSpecial(this.url) && this.buffer === "") { - this.parseError = true; - return failure; - } else if (this.stateOverride && this.buffer === "" && - (includesCredentials(this.url) || this.url.port !== null)) { - this.parseError = true; - return false; - } - - const host = parseHost(this.buffer, isSpecial(this.url)); - if (host === failure) { - return failure; - } - - this.url.host = host; - this.buffer = ""; - this.state = "path start"; - if (this.stateOverride) { - return false; - } - } else { - if (c === 91) { - this.arrFlag = true; - } else if (c === 93) { - this.arrFlag = false; - } - this.buffer += cStr; - } - - return true; -}; - -URLStateMachine.prototype["parse port"] = function parsePort(c, cStr) { - if (isASCIIDigit(c)) { - this.buffer += cStr; - } else if (isNaN(c) || c === 47 || c === 63 || c === 35 || - (isSpecial(this.url) && c === 92) || - this.stateOverride) { - if (this.buffer !== "") { - const port = parseInt(this.buffer); - if (port > Math.pow(2, 16) - 1) { - this.parseError = true; - return failure; - } - this.url.port = port === defaultPort(this.url.scheme) ? null : port; - this.buffer = ""; - } - if (this.stateOverride) { - return false; - } - this.state = "path start"; - --this.pointer; - } else { - this.parseError = true; - return failure; - } - - return true; -}; - -const fileOtherwiseCodePoints = new Set([47, 92, 63, 35]); - -URLStateMachine.prototype["parse file"] = function parseFile(c) { - this.url.scheme = "file"; - - if (c === 47 || c === 92) { - if (c === 92) { - this.parseError = true; - } - this.state = "file slash"; - } else if (this.base !== null && this.base.scheme === "file") { - if (isNaN(c)) { - this.url.host = this.base.host; - this.url.path = this.base.path.slice(); - this.url.query = this.base.query; - } else if (c === 63) { - this.url.host = this.base.host; - this.url.path = this.base.path.slice(); - this.url.query = ""; - this.state = "query"; - } else if (c === 35) { - this.url.host = this.base.host; - this.url.path = this.base.path.slice(); - this.url.query = this.base.query; - this.url.fragment = ""; - this.state = "fragment"; - } else { - if (this.input.length - this.pointer - 1 === 0 || // remaining consists of 0 code points - !isWindowsDriveLetterCodePoints(c, this.input[this.pointer + 1]) || - (this.input.length - this.pointer - 1 >= 2 && // remaining has at least 2 code points - !fileOtherwiseCodePoints.has(this.input[this.pointer + 2]))) { - this.url.host = this.base.host; - this.url.path = this.base.path.slice(); - shortenPath(this.url); - } else { - this.parseError = true; - } - - this.state = "path"; - --this.pointer; - } - } else { - this.state = "path"; - --this.pointer; - } - - return true; -}; - -URLStateMachine.prototype["parse file slash"] = function parseFileSlash(c) { - if (c === 47 || c === 92) { - if (c === 92) { - this.parseError = true; - } - this.state = "file host"; - } else { - if (this.base !== null && this.base.scheme === "file") { - if (isNormalizedWindowsDriveLetterString(this.base.path[0])) { - this.url.path.push(this.base.path[0]); - } else { - this.url.host = this.base.host; - } - } - this.state = "path"; - --this.pointer; - } - - return true; -}; - -URLStateMachine.prototype["parse file host"] = function parseFileHost(c, cStr) { - if (isNaN(c) || c === 47 || c === 92 || c === 63 || c === 35) { - --this.pointer; - if (!this.stateOverride && isWindowsDriveLetterString(this.buffer)) { - this.parseError = true; - this.state = "path"; - } else if (this.buffer === "") { - this.url.host = ""; - if (this.stateOverride) { - return false; - } - this.state = "path start"; - } else { - let host = parseHost(this.buffer, isSpecial(this.url)); - if (host === failure) { - return failure; - } - if (host === "localhost") { - host = ""; - } - this.url.host = host; - - if (this.stateOverride) { - return false; - } - - this.buffer = ""; - this.state = "path start"; - } - } else { - this.buffer += cStr; - } - - return true; -}; - -URLStateMachine.prototype["parse path start"] = function parsePathStart(c) { - if (isSpecial(this.url)) { - if (c === 92) { - this.parseError = true; - } - this.state = "path"; - - if (c !== 47 && c !== 92) { - --this.pointer; - } - } else if (!this.stateOverride && c === 63) { - this.url.query = ""; - this.state = "query"; - } else if (!this.stateOverride && c === 35) { - this.url.fragment = ""; - this.state = "fragment"; - } else if (c !== undefined) { - this.state = "path"; - if (c !== 47) { - --this.pointer; - } - } - - return true; -}; - -URLStateMachine.prototype["parse path"] = function parsePath(c) { - if (isNaN(c) || c === 47 || (isSpecial(this.url) && c === 92) || - (!this.stateOverride && (c === 63 || c === 35))) { - if (isSpecial(this.url) && c === 92) { - this.parseError = true; - } - - if (isDoubleDot(this.buffer)) { - shortenPath(this.url); - if (c !== 47 && !(isSpecial(this.url) && c === 92)) { - this.url.path.push(""); - } - } else if (isSingleDot(this.buffer) && c !== 47 && - !(isSpecial(this.url) && c === 92)) { - this.url.path.push(""); - } else if (!isSingleDot(this.buffer)) { - if (this.url.scheme === "file" && this.url.path.length === 0 && isWindowsDriveLetterString(this.buffer)) { - if (this.url.host !== "" && this.url.host !== null) { - this.parseError = true; - this.url.host = ""; - } - this.buffer = this.buffer[0] + ":"; - } - this.url.path.push(this.buffer); - } - this.buffer = ""; - if (this.url.scheme === "file" && (c === undefined || c === 63 || c === 35)) { - while (this.url.path.length > 1 && this.url.path[0] === "") { - this.parseError = true; - this.url.path.shift(); - } - } - if (c === 63) { - this.url.query = ""; - this.state = "query"; - } - if (c === 35) { - this.url.fragment = ""; - this.state = "fragment"; - } - } else { - // TODO: If c is not a URL code point and not "%", parse error. - - if (c === 37 && - (!isASCIIHex(this.input[this.pointer + 1]) || - !isASCIIHex(this.input[this.pointer + 2]))) { - this.parseError = true; - } - - this.buffer += percentEncodeChar(c, isPathPercentEncode); - } - - return true; -}; - -URLStateMachine.prototype["parse cannot-be-a-base-URL path"] = function parseCannotBeABaseURLPath(c) { - if (c === 63) { - this.url.query = ""; - this.state = "query"; - } else if (c === 35) { - this.url.fragment = ""; - this.state = "fragment"; - } else { - // TODO: Add: not a URL code point - if (!isNaN(c) && c !== 37) { - this.parseError = true; - } - - if (c === 37 && - (!isASCIIHex(this.input[this.pointer + 1]) || - !isASCIIHex(this.input[this.pointer + 2]))) { - this.parseError = true; - } - - if (!isNaN(c)) { - this.url.path[0] = this.url.path[0] + percentEncodeChar(c, isC0ControlPercentEncode); - } - } - - return true; -}; - -URLStateMachine.prototype["parse query"] = function parseQuery(c, cStr) { - if (isNaN(c) || (!this.stateOverride && c === 35)) { - if (!isSpecial(this.url) || this.url.scheme === "ws" || this.url.scheme === "wss") { - this.encodingOverride = "utf-8"; - } - - const buffer = new Buffer(this.buffer); // TODO: Use encoding override instead - for (let i = 0; i < buffer.length; ++i) { - if (buffer[i] < 0x21 || buffer[i] > 0x7E || buffer[i] === 0x22 || buffer[i] === 0x23 || - buffer[i] === 0x3C || buffer[i] === 0x3E) { - this.url.query += percentEncode(buffer[i]); - } else { - this.url.query += String.fromCodePoint(buffer[i]); - } - } - - this.buffer = ""; - if (c === 35) { - this.url.fragment = ""; - this.state = "fragment"; - } - } else { - // TODO: If c is not a URL code point and not "%", parse error. - if (c === 37 && - (!isASCIIHex(this.input[this.pointer + 1]) || - !isASCIIHex(this.input[this.pointer + 2]))) { - this.parseError = true; - } - - this.buffer += cStr; - } - - return true; -}; - -URLStateMachine.prototype["parse fragment"] = function parseFragment(c) { - if (isNaN(c)) { // do nothing - } else if (c === 0x0) { - this.parseError = true; - } else { - // TODO: If c is not a URL code point and not "%", parse error. - if (c === 37 && - (!isASCIIHex(this.input[this.pointer + 1]) || - !isASCIIHex(this.input[this.pointer + 2]))) { - this.parseError = true; - } - - this.url.fragment += percentEncodeChar(c, isC0ControlPercentEncode); - } - - return true; -}; - -function serializeURL(url, excludeFragment) { - let output = url.scheme + ":"; - if (url.host !== null) { - output += "//"; - - if (url.username !== "" || url.password !== "") { - output += url.username; - if (url.password !== "") { - output += ":" + url.password; - } - output += "@"; - } - - output += serializeHost(url.host); - - if (url.port !== null) { - output += ":" + url.port; - } - } else if (url.host === null && url.scheme === "file") { - output += "//"; - } - - if (url.cannotBeABaseURL) { - output += url.path[0]; - } else { - for (const string of url.path) { - output += "/" + string; - } - } - - if (url.query !== null) { - output += "?" + url.query; - } - - if (!excludeFragment && url.fragment !== null) { - output += "#" + url.fragment; - } - - return output; -} - -function serializeOrigin(tuple) { - let result = tuple.scheme + "://"; - result += serializeHost(tuple.host); - - if (tuple.port !== null) { - result += ":" + tuple.port; - } - - return result; -} - -module.exports.serializeURL = serializeURL; - -module.exports.serializeURLOrigin = function (url) { - // https://url.spec.whatwg.org/#concept-url-origin - switch (url.scheme) { - case "blob": - try { - return module.exports.serializeURLOrigin(module.exports.parseURL(url.path[0])); - } catch (e) { - // serializing an opaque origin returns "null" - return "null"; - } - case "ftp": - case "gopher": - case "http": - case "https": - case "ws": - case "wss": - return serializeOrigin({ - scheme: url.scheme, - host: url.host, - port: url.port - }); - case "file": - // spec says "exercise to the reader", chrome says "file://" - return "file://"; - default: - // serializing an opaque origin returns "null" - return "null"; - } -}; - -module.exports.basicURLParse = function (input, options) { - if (options === undefined) { - options = {}; - } - - const usm = new URLStateMachine(input, options.baseURL, options.encodingOverride, options.url, options.stateOverride); - if (usm.failure) { - return "failure"; - } - - return usm.url; -}; - -module.exports.setTheUsername = function (url, username) { - url.username = ""; - const decoded = punycode.ucs2.decode(username); - for (let i = 0; i < decoded.length; ++i) { - url.username += percentEncodeChar(decoded[i], isUserinfoPercentEncode); - } -}; - -module.exports.setThePassword = function (url, password) { - url.password = ""; - const decoded = punycode.ucs2.decode(password); - for (let i = 0; i < decoded.length; ++i) { - url.password += percentEncodeChar(decoded[i], isUserinfoPercentEncode); - } -}; - -module.exports.serializeHost = serializeHost; - -module.exports.cannotHaveAUsernamePasswordPort = cannotHaveAUsernamePasswordPort; - -module.exports.serializeInteger = function (integer) { - return String(integer); -}; - -module.exports.parseURL = function (input, options) { - if (options === undefined) { - options = {}; - } - - // We don't handle blobs, so this just delegates: - return module.exports.basicURLParse(input, { baseURL: options.baseURL, encodingOverride: options.encodingOverride }); -}; diff --git a/node_modules/whatwg-url/lib/utils.js b/node_modules/whatwg-url/lib/utils.js deleted file mode 100644 index a562009c..00000000 --- a/node_modules/whatwg-url/lib/utils.js +++ /dev/null @@ -1,20 +0,0 @@ -"use strict"; - -module.exports.mixin = function mixin(target, source) { - const keys = Object.getOwnPropertyNames(source); - for (let i = 0; i < keys.length; ++i) { - Object.defineProperty(target, keys[i], Object.getOwnPropertyDescriptor(source, keys[i])); - } -}; - -module.exports.wrapperSymbol = Symbol("wrapper"); -module.exports.implSymbol = Symbol("impl"); - -module.exports.wrapperForImpl = function (impl) { - return impl[module.exports.wrapperSymbol]; -}; - -module.exports.implForWrapper = function (wrapper) { - return wrapper[module.exports.implSymbol]; -}; - diff --git a/node_modules/whatwg-url/package.json b/node_modules/whatwg-url/package.json deleted file mode 100644 index fce35ae7..00000000 --- a/node_modules/whatwg-url/package.json +++ /dev/null @@ -1,32 +0,0 @@ -{ - "name": "whatwg-url", - "version": "5.0.0", - "description": "An implementation of the WHATWG URL Standard's URL API and parsing machinery", - "main": "lib/public-api.js", - "files": [ - "lib/" - ], - "author": "Sebastian Mayr ", - "license": "MIT", - "repository": "jsdom/whatwg-url", - "dependencies": { - "tr46": "~0.0.3", - "webidl-conversions": "^3.0.0" - }, - "devDependencies": { - "eslint": "^2.6.0", - "istanbul": "~0.4.3", - "mocha": "^2.2.4", - "recast": "~0.10.29", - "request": "^2.55.0", - "webidl2js": "^3.0.2" - }, - "scripts": { - "build": "node scripts/transform.js && node scripts/convert-idl.js", - "coverage": "istanbul cover node_modules/mocha/bin/_mocha", - "lint": "eslint .", - "prepublish": "npm run build", - "pretest": "node scripts/get-latest-platform-tests.js && npm run build", - "test": "mocha" - } -} diff --git a/package-lock.json b/package-lock.json index 98847d57..9526dde2 100644 --- a/package-lock.json +++ b/package-lock.json @@ -7,48 +7,7 @@ "": { "name": "mlflow", "version": "1.0.0", - "license": "ISC", - "dependencies": { - "node-fetch": "^2.7.0" - } - }, - "node_modules/node-fetch": { - "version": "2.7.0", - "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.7.0.tgz", - "integrity": "sha512-c4FRfUm/dbcWZ7U+1Wq0AwCyFL+3nt2bEw05wfxSz+DWpWsitgmSgYmy2dQdWyKC1694ELPqMs/YzUSNozLt8A==", - "dependencies": { - "whatwg-url": "^5.0.0" - }, - "engines": { - "node": "4.x || >=6.0.0" - }, - "peerDependencies": { - "encoding": "^0.1.0" - }, - "peerDependenciesMeta": { - "encoding": { - "optional": true - } - } - }, - "node_modules/tr46": { - "version": "0.0.3", - "resolved": "https://registry.npmjs.org/tr46/-/tr46-0.0.3.tgz", - "integrity": "sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw==" - }, - "node_modules/webidl-conversions": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-3.0.1.tgz", - "integrity": "sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ==" - }, - "node_modules/whatwg-url": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-5.0.0.tgz", - "integrity": "sha512-saE57nupxk6v3HY35+jzBwYa0rKSy0XR8JSxZPwgLr7ys0IBzhGviA1/TUGJLmSVqs8pb9AnvICXEuOHLprYTw==", - "dependencies": { - "tr46": "~0.0.3", - "webidl-conversions": "^3.0.0" - } + "license": "ISC" } } } diff --git a/package.json b/package.json index d6a50688..40ff170d 100644 --- a/package.json +++ b/package.json @@ -1,14 +1,16 @@ { "name": "mlflow", "version": "1.0.0", - "description": "", - "main": "index.js", + "type": "module", + "description": "JavaScript library for MLflow", + "main": "", "scripts": { "test": "echo \"Error: no test specified\" && exit 1" }, + "keywords": [ + "mlflow", + "machine learning" + ], "author": "", - "license": "ISC", - "dependencies": { - "node-fetch": "^2.7.0" - } + "license": "MIT" } From 6726c26f8a56099f9c131b957c8a09b20e73ed7e Mon Sep 17 00:00:00 2001 From: Yiqun Zheng Date: Mon, 26 Aug 2024 18:22:07 -0700 Subject: [PATCH 010/357] restructured the repo --- Model_registry/model_registry_management.js | 0 .gitignore => mlflow/.gitignore | 0 package-lock.json => mlflow/package-lock.json | 0 package.json => mlflow/package.json | 0 .../src/model_registry}/model_registry.js | 0 .../src/model_registry}/model_version_management.js | 0 .../src/tracking_server}/artifact_management.js | 0 .../src/tracking_server}/experiment_management.js | 0 .../src/tracking_server}/run_management.js | 0 node_modules/.package-lock.json | 7 ------- 10 files changed, 7 deletions(-) delete mode 100644 Model_registry/model_registry_management.js rename .gitignore => mlflow/.gitignore (100%) rename package-lock.json => mlflow/package-lock.json (100%) rename package.json => mlflow/package.json (100%) rename {Model_registry => mlflow/src/model_registry}/model_registry.js (100%) rename {Model_registry => mlflow/src/model_registry}/model_version_management.js (100%) rename {Tracking_server => mlflow/src/tracking_server}/artifact_management.js (100%) rename {Tracking_server => mlflow/src/tracking_server}/experiment_management.js (100%) rename {Tracking_server => mlflow/src/tracking_server}/run_management.js (100%) delete mode 100644 node_modules/.package-lock.json diff --git a/Model_registry/model_registry_management.js b/Model_registry/model_registry_management.js deleted file mode 100644 index e69de29b..00000000 diff --git a/.gitignore b/mlflow/.gitignore similarity index 100% rename from .gitignore rename to mlflow/.gitignore diff --git a/package-lock.json b/mlflow/package-lock.json similarity index 100% rename from package-lock.json rename to mlflow/package-lock.json diff --git a/package.json b/mlflow/package.json similarity index 100% rename from package.json rename to mlflow/package.json diff --git a/Model_registry/model_registry.js b/mlflow/src/model_registry/model_registry.js similarity index 100% rename from Model_registry/model_registry.js rename to mlflow/src/model_registry/model_registry.js diff --git a/Model_registry/model_version_management.js b/mlflow/src/model_registry/model_version_management.js similarity index 100% rename from Model_registry/model_version_management.js rename to mlflow/src/model_registry/model_version_management.js diff --git a/Tracking_server/artifact_management.js b/mlflow/src/tracking_server/artifact_management.js similarity index 100% rename from Tracking_server/artifact_management.js rename to mlflow/src/tracking_server/artifact_management.js diff --git a/Tracking_server/experiment_management.js b/mlflow/src/tracking_server/experiment_management.js similarity index 100% rename from Tracking_server/experiment_management.js rename to mlflow/src/tracking_server/experiment_management.js diff --git a/Tracking_server/run_management.js b/mlflow/src/tracking_server/run_management.js similarity index 100% rename from Tracking_server/run_management.js rename to mlflow/src/tracking_server/run_management.js diff --git a/node_modules/.package-lock.json b/node_modules/.package-lock.json deleted file mode 100644 index ff6e8ab3..00000000 --- a/node_modules/.package-lock.json +++ /dev/null @@ -1,7 +0,0 @@ -{ - "name": "mlflow", - "version": "1.0.0", - "lockfileVersion": 3, - "requires": true, - "packages": {} -} From bf4d3c87de09104ba1be34f812bfc618bf866f2f Mon Sep 17 00:00:00 2001 From: Stephany Ho Date: Tue, 27 Aug 2024 01:21:17 -0400 Subject: [PATCH 011/357] Created createRun method --- mlflow/src/tracking_server/run_management.js | 47 ++++++++++++++++++++ 1 file changed, 47 insertions(+) diff --git a/mlflow/src/tracking_server/run_management.js b/mlflow/src/tracking_server/run_management.js index e69de29b..727e0eb7 100644 --- a/mlflow/src/tracking_server/run_management.js +++ b/mlflow/src/tracking_server/run_management.js @@ -0,0 +1,47 @@ +class RunManagement { + constructor(trackingUri) { + this.trackingUri = trackingUri; + } + + /** + * Creates a new run. + * + * @param {string} experiment_id - The ID of the associated experiment (required) + * @param {string} run_name - The name of the run (required) + * @param {Array<{key: string, value: string}>} [tags=[]] - Optional metadata for the run + * @returns {Promise} - The created run object + */ + async createRun(experiment_id, run_name, tags = []) { + if (!experiment_id || !run_name) { + throw new Error('Experiment ID and run name are required'); + } + + console.log('Tracking URI: ', this.trackingUri); + const startTime = Date.now(); + + const url = `${this.trackingUri}/api/2.0/mlflow/runs/create`; + + const response = await fetch(url, { + method: 'POST', + headers: { 'Content-Type': 'application/json' }, + body: JSON.stringify({ + experiment_id, + run_name, + start_time: startTime, + tags, + }), + }); + + const data = await response.json(); + + if (!response.ok) { + throw new Error( + `Error creating run: ${data.message || response.statusText}` + ); + } + + return data.run; + } +} + +export { RunManagement }; From d538c4bc5d5151ab856d89288c0ecf5cb07e9175 Mon Sep 17 00:00:00 2001 From: Stephany Ho <36724788+seneyu@users.noreply.github.com> Date: Tue, 27 Aug 2024 09:06:51 -0400 Subject: [PATCH 012/357] Standardize LICENSE file name and content --- LICENSE | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) create mode 100644 LICENSE diff --git a/LICENSE b/LICENSE new file mode 100644 index 00000000..14ecd53f --- /dev/null +++ b/LICENSE @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2024 Open Source Labs Beta + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. From a0850b7fe0604245a095a25b750f00bedcc89db6 Mon Sep 17 00:00:00 2001 From: Stephany Ho <36724788+seneyu@users.noreply.github.com> Date: Tue, 27 Aug 2024 09:14:02 -0400 Subject: [PATCH 013/357] Delete license.md --- license.md | 9 --------- 1 file changed, 9 deletions(-) delete mode 100644 license.md diff --git a/license.md b/license.md deleted file mode 100644 index 39c794a4..00000000 --- a/license.md +++ /dev/null @@ -1,9 +0,0 @@ -# Released under MIT License - -Copyright (c) 2024 K. Chiago, A. Fraser, S. Ho, W. Ludlam, Y. Zheng. - -Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. \ No newline at end of file From d549e34bbd05e13bded8cbae126944041abd19d9 Mon Sep 17 00:00:00 2001 From: Stephany Ho Date: Tue, 27 Aug 2024 13:45:20 -0400 Subject: [PATCH 014/357] Added deleteRun, restoreRun, getRun, updateRun methods --- mlflow/src/tracking_server/run_management.js | 188 +++++++++++++++++-- 1 file changed, 176 insertions(+), 12 deletions(-) diff --git a/mlflow/src/tracking_server/run_management.js b/mlflow/src/tracking_server/run_management.js index 727e0eb7..da918997 100644 --- a/mlflow/src/tracking_server/run_management.js +++ b/mlflow/src/tracking_server/run_management.js @@ -7,29 +7,33 @@ class RunManagement { * Creates a new run. * * @param {string} experiment_id - The ID of the associated experiment (required) - * @param {string} run_name - The name of the run (required) - * @param {Array<{key: string, value: string}>} [tags=[]] - Optional metadata for the run + * @param {string} [run_name] - The name of the run (optional) + * @param {Array<{key: string, value: string}>} [tags=[]] - Additional metadata for the run (optional) * @returns {Promise} - The created run object */ - async createRun(experiment_id, run_name, tags = []) { - if (!experiment_id || !run_name) { - throw new Error('Experiment ID and run name are required'); + async createRun(experiment_id, run_name = null, tags = []) { + if (!experiment_id) { + throw new Error('Experiment ID is required'); } - console.log('Tracking URI: ', this.trackingUri); const startTime = Date.now(); const url = `${this.trackingUri}/api/2.0/mlflow/runs/create`; + const body = { + experiment_id, + start_time: startTime, + tags, + }; + + if (run_name) { + body.run_name = run_name; + } + const response = await fetch(url, { method: 'POST', headers: { 'Content-Type': 'application/json' }, - body: JSON.stringify({ - experiment_id, - run_name, - start_time: startTime, - tags, - }), + body: JSON.stringify(body), }); const data = await response.json(); @@ -42,6 +46,166 @@ class RunManagement { return data.run; } + + /** + * Deletes a run. + * + * @param {string} run_id - The ID of the run to delete (required) + * @returns {Promise} - A promise that resolves when the run is deleted + */ + async deleteRun(run_id) { + if (!run_id) { + throw new Error('Run ID is required.'); + } + + const url = `${this.trackingUri}/api/2.0/mlflow/runs/delete`; + + const response = await fetch(url, { + method: 'POST', + headers: { 'Content-Type': 'application/json' }, + body: JSON.stringify({ run_id }), + }); + + if (!response.ok) { + throw new Error( + `Error deleting run: ${data.message || response.statusText}` + ); + } + + return; + } + + /** + * Restores a run. + * + * @param {string} run_id - The ID of the run to restore (required) + * @returns {Promise} - A promise that resolves when the run is restored + */ + async restoreRun(run_id) { + if (!run_id) { + throw new Error('Run ID is required.'); + } + + const url = `${this.trackingUri}/api/2.0/mlflow/runs/restore`; + + const response = await fetch(url, { + method: 'POST', + headers: { 'Content-Type': 'application/json' }, + body: JSON.stringify({ run_id }), + }); + + if (!response.ok) { + throw new Error( + `Error restoring run: ${data.message || response.statusText}` + ); + } + + return; + } + + /** + * Fetches a run. + * + * @param {string} run_id - The ID of the run to fetch (required) + * @returns {Promise} - The fetched run object + */ + async getRun(run_id) { + if (!run_id) { + throw new Error('Run ID is required.'); + } + + const url = `${this.trackingUri}/api/2.0/mlflow/runs/get?run_id=${run_id}`; + + const response = await fetch(url); + const data = await response.json(); + + if (!response.ok) { + throw new Error( + `Error fetching run: ${data.message || response.statusText}` + ); + } + + return data.run; + } + + /** + * updates a run. + * + * @param {string} run_id - The ID of the run to update (required) + * @param {string} [status] - The status of the updated run (optional) + * @param {string} [run_name] - The updated name of the run (optional) + * @param {number} [end_time] - The end time fo the run in milliseconds since epoch (optional) + * @returns {Promise} - The updated metadata of the run object + */ + async updateRun(run_id, status = null, run_name = null, end_time = null) { + if (!run_id) { + throw new Error('Run ID is required.'); + } + + const url = `${this.trackingUri}/api/2.0/mlflow/runs/update`; + + const body = { run_id }; + if (status) body.status = status; + if (run_name) body.run_name = run_name; + if (end_time) body.end_time = end_time; + + const response = await fetch(url, { + method: 'POST', + headers: { 'Content-Type': 'application/json' }, + body: JSON.stringify(body), + }); + + const data = await response.json(); + + if (!response.ok) { + throw new Error( + `Error creating run: ${data.message || response.statusText}` + ); + } + + return data; + } + + /** + * Logs a metric for a run. + * + * @param {string} run_id - The ID of the run under which to log the metric (required) + * @param {string} key - The name of the metric (required) + * @param {number} value - The double value of the metric being logged (required) + * @param {number} timestamp - The unix timestamp in milliseconds at the time metric was logged (required) + * @param {number} [step=0] - The step at which to log the metric (optional) + * @returns {Promise} - A promise that resolves when the metric is logged + */ + async logMetric(run_id, key, value, timestamp, step = 0) {} + + /** + * Logs a batch of metrics, params, and tags for a run. + * + * @param {string} run_id - The ID of the run to log under (required) + * @param {Array<{key: string, value: number, timestamp: number, step?: number}>} [metrics] - The metrics to log (up to 1000 metrics) (optional) + * @param {Array<{key: string, value: string}>} [params] - The params to log (up to 100 params) (optional) + * @param {Array<{key: string, value: string}>} [tags=[]] - The tags to log (up to 100 tags) (optional) + * @returns {Promise} - A promise that resolves when the logging is complete + */ + async logBatch(run_id, metrics = [], params = [], tags = []) {} + + /** + * Logs a model. + * + * @param {string} run_id - The ID of the run to log under (required) + * @param {object} model_json - The MLmodel data in JSON format (required) + * @returns {Promise} - A promise that resolves when the model is successfully logged + */ + async logModel(run_id, model_json) {} + + /** + * Logs inputs. + * + * @param {string} run_id - The ID of the run to log under (required) + * @param {Array} datasets - The dataset inputs in JSON format (required) + * @returns {Promise} - A promise that resolves when the logging is complete + */ + async logInputs(run_id, datasets) {} } export { RunManagement }; From 75c3a8dc5c0fa05dc61146728688faa50861fee2 Mon Sep 17 00:00:00 2001 From: Austin Fraser Date: Tue, 27 Aug 2024 17:56:03 -0700 Subject: [PATCH 015/357] rewrite of createExperiment and searchExperiment to conform to code standards --- Tracking_server/experiment_management.js | 60 ---------- .../tracking_server/experiment_management.js | 103 ++++++++++++++++++ 2 files changed, 103 insertions(+), 60 deletions(-) delete mode 100644 Tracking_server/experiment_management.js diff --git a/Tracking_server/experiment_management.js b/Tracking_server/experiment_management.js deleted file mode 100644 index db402553..00000000 --- a/Tracking_server/experiment_management.js +++ /dev/null @@ -1,60 +0,0 @@ -const fetch = require('node-fetch'); - -const MLFLOW_TRACKING_URI = 'http://localhost:5001/api/2.0/mlflow'; - -/** - * Create an experiment with a name. Returns the ID of the newly created experiment. - * Validates that another experiment with the same name does not already exist and fails if another experiment with the same name already exists. - * Throws RESOURCE_ALREADY_EXISTS if a experiment with the given name exists. - */ -async function createExperiment(name, artifact_location, tags) { - try { - const response = await fetch(`${MLFLOW_TRACKING_URI}/experiments/create`, { - method: "POST", - headers: { "Content-Type": "application/json" }, - body: JSON.stringify({ name, artifact_location, tags }), - }); - - if (response.status === 400) { - const errorBody = await response.json(); - console.error('400 Error:', errorBody.message); - return; - } - - if (!response.ok) { - throw new Error(`HTTP error, status: ${response.status}`); - } - - const data = await response.json(); - console.log('data.experiment_id: ', data.experiment_id); - return data.experiment_id; - } - catch (error) { - console.error('Error creating experiment:', error); - } -} - -// createExperiment('test_experiment_postman10'); - -async function searchExperiment(filter, max_results, page_token, order_by, view_type) { - try { - const response = await fetch(`${MLFLOW_TRACKING_URI}/experiments/search`, { - method: "POST", - headers: { "Content-Type": "application/json" }, - body: JSON.stringify({ filter, max_results, page_token, order_by, view_type }), - }) - - if (!response.ok) { - throw new Error(`HTTP error, status: ${response.status}`); - } - - const data = await response.json(); - console.log('data.experiments: ', data.experiments); - return data.experiments - } - catch (error) { - console.error('Error searching for experiment:', error); - } -} - -// searchExperiment("name = 'test_experiment_postmanx'", 1000); \ No newline at end of file diff --git a/mlflow/src/tracking_server/experiment_management.js b/mlflow/src/tracking_server/experiment_management.js index e69de29b..55da4c2d 100644 --- a/mlflow/src/tracking_server/experiment_management.js +++ b/mlflow/src/tracking_server/experiment_management.js @@ -0,0 +1,103 @@ +const MLFLOW_TRACKING_URI = 'http://localhost:5001/api/2.0/mlflow'; + + + + +/** + * Create an experiment with a name. Returns the ID of the newly created experiment. + * Validates that another experiment with the same name does not already exist and fails if another experiment with the same name already exists. + * Throws RESOURCE_ALREADY_EXISTS if a experiment with the given name exists. + * + * @param {string} name Experiment name. (required) + * @param {string} artifact_location Optional location where all artifacts for the experiment are stored. If not provided, the remote server will select an appropriate default. + * @param {Array<{key: string, value: string}>} tags Optional collection of tags to set on the experiment. + * @returns {Promise} Returns the ID of the newly created experiment in an object. + */ +async function createExperiment( + name, + artifact_location = '', + tags = [] +) { + try { + if (!name) { + throw new Error('Experiment name is required'); + }; + + const url = `${MLFLOW_TRACKING_URI}/experiments/create`; + const response = await fetch(url, { + method: "POST", + headers: { "Content-Type": "application/json" }, + body: JSON.stringify({ name, artifact_location, tags }), + }); + + if (response.status === 400) { + const errorBody = await response.json(); + // console.error('400 Error:', errorBody.message); + // return; + throw new Error(`${errorBody.message}`); + } + + if (!response.ok) { + throw new Error(`HTTP error from tracking server, status: ${response.status}`); + } + + const data = await response.json(); + console.log('data: ', data); + return data; + } + catch (error) { + console.error('Error creating experiment:', error); + } +} + +// run the next line to test ******************************************************************** +// createExperiment('test_experiment_postman16'); + + + +/** + * Search experiments. + * + * @param {string} filter A filter expression over experiment attributes and tags that allows returning a subset of experiments. The syntax is a subset of SQL. (required) + * @param {int64} max_results Maximum number of experiments desired. (required) + * @param {string} page_token Optional token indicating the page of experiments to fetch. + * @param {Array} order_by Optional list of columns for ordering search results. + * @param {string} view_type Optional qualifier for type of experiments to be returned. See https://mlflow.org/docs/latest/rest-api.html#mlflowviewtype + * @returns {Promise} Returns an array of experiment objects matching the filter. + */ +async function searchExperiment( + filter, + max_results, + page_token = '', + order_by = [], + view_type = '') { + try { + if (!filter) { + throw new Error('Filter is required'); + }; + if (!max_results) { + throw new Error('Max results is required'); + }; + + const url = `${MLFLOW_TRACKING_URI}/experiments/search`; + const response = await fetch(url, { + method: "POST", + headers: { "Content-Type": "application/json" }, + body: JSON.stringify({ filter, max_results, page_token, order_by, view_type }), + }) + + if (!response.ok) { + throw new Error(`HTTP error, status: ${response.status}`); + } + + const data = await response.json(); + console.log('data.experiments: ', data.experiments); + return data.experiments + } + catch (error) { + console.error('Error searching for experiment:', error); + } +} + +// run the next line to test ******************************************************************** +searchExperiment("name = 'test_experiment_postman'", 1); \ No newline at end of file From cc276a56da8251e5c0168e7f0ea2298ac52c15b4 Mon Sep 17 00:00:00 2001 From: Austin Fraser Date: Tue, 27 Aug 2024 18:31:37 -0700 Subject: [PATCH 016/357] getExperiment --- .../tracking_server/experiment_management.js | 132 +++++++++++------- 1 file changed, 84 insertions(+), 48 deletions(-) diff --git a/mlflow/src/tracking_server/experiment_management.js b/mlflow/src/tracking_server/experiment_management.js index 55da4c2d..506fa179 100644 --- a/mlflow/src/tracking_server/experiment_management.js +++ b/mlflow/src/tracking_server/experiment_management.js @@ -1,103 +1,139 @@ const MLFLOW_TRACKING_URI = 'http://localhost:5001/api/2.0/mlflow'; - - - /** * Create an experiment with a name. Returns the ID of the newly created experiment. * Validates that another experiment with the same name does not already exist and fails if another experiment with the same name already exists. * Throws RESOURCE_ALREADY_EXISTS if a experiment with the given name exists. - * + * * @param {string} name Experiment name. (required) - * @param {string} artifact_location Optional location where all artifacts for the experiment are stored. If not provided, the remote server will select an appropriate default. + * @param {string} artifact_location Optional location where all artifacts for the experiment are stored. + * If not provided, the remote server will select an appropriate default. * @param {Array<{key: string, value: string}>} tags Optional collection of tags to set on the experiment. * @returns {Promise} Returns the ID of the newly created experiment in an object. */ -async function createExperiment( - name, - artifact_location = '', - tags = [] -) { +async function createExperiment(name, artifact_location = '', tags = []) { try { if (!name) { throw new Error('Experiment name is required'); - }; + } const url = `${MLFLOW_TRACKING_URI}/experiments/create`; const response = await fetch(url, { - method: "POST", - headers: { "Content-Type": "application/json" }, + method: 'POST', + headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ name, artifact_location, tags }), }); - if (response.status === 400) { - const errorBody = await response.json(); - // console.error('400 Error:', errorBody.message); - // return; - throw new Error(`${errorBody.message}`); - } - if (!response.ok) { - throw new Error(`HTTP error from tracking server, status: ${response.status}`); + const errorBody = await response.json(); + throw new Error( + `HTTP error from tracking server, status: ${response.status}. ${errorBody.message}` + ); } const data = await response.json(); console.log('data: ', data); return data; - } - catch (error) { - console.error('Error creating experiment:', error); + } catch (error) { + console.error('Error creating experiment: ', error); } } // run the next line to test ******************************************************************** // createExperiment('test_experiment_postman16'); - - /** * Search experiments. - * - * @param {string} filter A filter expression over experiment attributes and tags that allows returning a subset of experiments. The syntax is a subset of SQL. (required) + * + * @param {string} filter A filter expression over experiment attributes and tags that allows returning a subset of experiments + * The syntax is a subset of SQL. (required) * @param {int64} max_results Maximum number of experiments desired. (required) * @param {string} page_token Optional token indicating the page of experiments to fetch. * @param {Array} order_by Optional list of columns for ordering search results. - * @param {string} view_type Optional qualifier for type of experiments to be returned. See https://mlflow.org/docs/latest/rest-api.html#mlflowviewtype - * @returns {Promise} Returns an array of experiment objects matching the filter. + * @param {string} view_type Optional qualifier for type of experiments to be returned. + * See https://mlflow.org/docs/latest/rest-api.html#mlflowviewtype + * @returns {Promise} Returns object containing an array of experiment objects matching the filter, + * and optionally a next_page_token that can be used to retrieve the next page of experiments. */ async function searchExperiment( - filter, - max_results, - page_token = '', - order_by = [], - view_type = '') { + filter, + max_results, + page_token = '', + order_by = [], + view_type = '' +) { try { if (!filter) { throw new Error('Filter is required'); - }; + } if (!max_results) { throw new Error('Max results is required'); - }; + } const url = `${MLFLOW_TRACKING_URI}/experiments/search`; const response = await fetch(url, { - method: "POST", - headers: { "Content-Type": "application/json" }, - body: JSON.stringify({ filter, max_results, page_token, order_by, view_type }), - }) - + method: 'POST', + headers: { 'Content-Type': 'application/json' }, + body: JSON.stringify({ + filter, + max_results, + page_token, + order_by, + view_type, + }), + }); + if (!response.ok) { - throw new Error(`HTTP error, status: ${response.status}`); + const errorBody = await response.json(); + throw new Error( + `HTTP error from tracking server, status: ${response.status}. ${errorBody.message}` + ); } const data = await response.json(); - console.log('data.experiments: ', data.experiments); - return data.experiments + console.log('data: ', data); + return data; + } catch (error) { + console.error('Error searching for experiment: ', error); } - catch (error) { - console.error('Error searching for experiment:', error); +} + +// run the next line to test ******************************************************************** +// searchExperiment("name = 'test_experiment_postman'", 1); + +/** + * Get metadata for an experiment. This method works on deleted experiments. + * + * @param {string} experiment_id ID of the associated experiment. (required) + * @returns {Promise} Returns object containing the matched experiment. + */ +async function getExperiment(experiment_id) { + try { + if (!experiment_id) { + throw new Error('Experiment ID is required'); + } + + const url = `${MLFLOW_TRACKING_URI}/experiments/get?experiment_id=${experiment_id}`; + const response = await fetch(url, { + method: 'GET', + headers: { 'Content-Type': 'application/json' }, + // body: JSON.stringify({ experiment_id }), + }); + + if (!response.ok) { + const errorBody = await response.json(); + throw new Error( + `HTTP error from tracking server, status: ${response.status}. ${errorBody.message}` + ); + } + + const data = await response.json(); + console.log('data.experiment: ', data.experiment); + return data.experiment; + } catch (error) { + console.error('Error getting experiment: ', error); } } // run the next line to test ******************************************************************** -searchExperiment("name = 'test_experiment_postman'", 1); \ No newline at end of file +getExperiment('292357850348085316'); From 102bab5023fc972b0ca430656bd186b306cd1570 Mon Sep 17 00:00:00 2001 From: Kyler-Chiago Date: Tue, 27 Aug 2024 20:23:40 -0700 Subject: [PATCH 017/357] runManagement - getMetricHistory, searchRuns, listArtifacts working --- .../tracking_server/artifact_management.js | 0 mlflow/src/tracking_server/run_management.js | 144 ++++++++++++++++++ .../src/tracking_server/tempCodeRunnerFile.js | 2 + 3 files changed, 146 insertions(+) delete mode 100644 mlflow/src/tracking_server/artifact_management.js create mode 100644 mlflow/src/tracking_server/tempCodeRunnerFile.js diff --git a/mlflow/src/tracking_server/artifact_management.js b/mlflow/src/tracking_server/artifact_management.js deleted file mode 100644 index e69de29b..00000000 diff --git a/mlflow/src/tracking_server/run_management.js b/mlflow/src/tracking_server/run_management.js index e69de29b..51984dc7 100644 --- a/mlflow/src/tracking_server/run_management.js +++ b/mlflow/src/tracking_server/run_management.js @@ -0,0 +1,144 @@ +let domain = 'http://localhost:' +const port = 5001; +if (port) { + domain = domain + port; +} + +const version = '2.0'; + +const MLFLOW_TRACKING_URI = domain + '/api/' + version + '/mlflow'; + +const path = 'artifacts'; + +// // Can initiate the comments above the function by doing /**, right above the function + +class RunManagement { + constructor(trackingUri, path) { + this.trackingUri = trackingUri; + this.path = path; + } + + /** + * + * @param {string} run_id - ID of the run from which to fetch metric values. Required + * @param {string} metric_key - Name of the metric. Required + * @param {string} page_token - Token indicating the page of metric history to fetch + * @param {INT32} max_results - Maximum number of logged instances of a metric for a run to return per call. + * Backend servers may restrict the value of max_results depending on performance requirements. Requests that do not + * specify this value will behave as non-paginated queries where all metric history values for a given metric + * within a run are returned in a single response. + * @returns + */ + async getMetricHistory(run_id, metric_key, page_token, max_results) { + if (!run_id) { + throw new Error("run_id is required"); + } else if (!metric_key) { + throw new Error("metric_key is required"); + } + const url = `${this.trackingUri}/metrics/get-history?run_id=${run_id}&metric_key=${metric_key}&page_token=${page_token}&max_results=${max_results}`; + const response = await fetch(url); + /** + * data can have the fields: + * metrics {An array of Metric} - All logged values for this metric + * next_page_token {string} - Token that can be used to issue a query for the next page of metric history values. A + * missing token indicates that no additional metrics are available to fetch. + */ + const data = await response.json(); + if (!response.ok) { + throw new Error( + `Error finding metric for given run: ${ + data.message || response.statusText + }` + ); + } + console.log('data: ', data); + // console.log('data.runs: ', data.runs); + return data; + } + + /** + * + * @param {Array<{key: string, value: string}>} experiment_ids - List of experiment IDs to search over. + * @param {string} filter - A filter expression over params, metrics, and tags, that allows returning a subset of runs. + * The syntax is a subset of SQL that supports ANDing together binary operations between a param, metric, or tag and a constant. + * Example: metrics.rmse < 1 and params.model_class = 'LogisticRegression' + * You can select columns with special characters (hyphen, space, period, etc.) by using + * double quotes: metrics."model class" = 'LinearRegression' and tags."user-name" = 'Tomas' + * Supported operators are =, !=, >, >=, <, and <=. + * @param {ViewType} run_view_type - Whether to display only active, only deleted, or all runs. Defaults to active runs. + * @param {INT32} max_results - Maximum number of runs desired. If unspecified, defaults to 1000. All servers are + * guaranteed to support a max_results theshold of at least 50,000 but may support more. Callers of this endpoint are + * encouraged to pass max_results explicitly and leverage page_token to iterate through experiments. + * @param {Array<{key: string, value: string}>} order_by - List of columns to be ordered by, including attributes, params, metrics, + * and tags with an optional "DESC" or "ASC" annotation, where "ASC" is the default. + * Example: ["params.input DESC","metrics.alpha ASC", "metrics.rmse"] Tiebreaks are done by start_time DESC followed by run_id for + * runs with the same start time (and this is the default ordering criterion if order_by is not provided). + * @param {string} page_token + * @returns {Promise} - The list artifacts for the specified run, as a promise object + */ + async listArtifacts(run_id, artifact_path = '', page_token = '') { + if (!run_id) { + throw new Error("run_id is required"); + } + const response = await fetch(`${this.trackingUri}/${this.path}/list?run_id=${run_id}&run_uuid=${run_id}&path=${artifact_path}&page_token=${page_token}`); + /** + * data can have the fields: + * root_uri {string} - Root artifact directory for the run + * files {An array of FileInfo} - File location and metadata for artifacts + * next_page_token {string} - Token that can be used to retrieve the next page of artifact results. A missing token indicates + * that there are no additional artifact results to be fetched. + */ + const data = await response.json(); + if (!response.ok) { + throw new Error( + `Error retrieving artifacts from run: ${ + data.message || response.statusText + }` + ); + } + console.log('data: ', data); + return data; + }; +} + +let runManagement = new RunManagement(MLFLOW_TRACKING_URI, path); +// console.log(runManagement.listArtifacts('b3457c87f50440388da9d9ddabb1baaa', 'mlflow-artifacts:/784321942139901150/b3457c87f50440388da9d9ddabb1baaa/artifacts/iris_model')); +// console.log(runManagement.listArtifacts('b3457c87f50440388da9d9ddabb1baaa')); +// console.log(runManagement.searchRuns(['784321942139901150'])); +// console.log(runManagement.searchRuns()); +// console.log(runManagement.getMetricHistory('df87d99de65a42f5bc52d6f5774364b6')); \ No newline at end of file diff --git a/mlflow/src/tracking_server/tempCodeRunnerFile.js b/mlflow/src/tracking_server/tempCodeRunnerFile.js new file mode 100644 index 00000000..56bf65d0 --- /dev/null +++ b/mlflow/src/tracking_server/tempCodeRunnerFile.js @@ -0,0 +1,2 @@ + + // console.log('data.runs: ', data.runs); \ No newline at end of file From 6517522e28c1c3122b5bf8a1120af781e7b52d74 Mon Sep 17 00:00:00 2001 From: Kyler-Chiago Date: Tue, 27 Aug 2024 21:02:16 -0700 Subject: [PATCH 018/357] RunManagement: logParam, deleteTag, setTag DONE --- mlflow/src/tracking_server/run_management.js | 123 ++++++++++++++++++- 1 file changed, 117 insertions(+), 6 deletions(-) diff --git a/mlflow/src/tracking_server/run_management.js b/mlflow/src/tracking_server/run_management.js index 51984dc7..06152d82 100644 --- a/mlflow/src/tracking_server/run_management.js +++ b/mlflow/src/tracking_server/run_management.js @@ -10,7 +10,7 @@ const MLFLOW_TRACKING_URI = domain + '/api/' + version + '/mlflow'; const path = 'artifacts'; -// // Can initiate the comments above the function by doing /**, right above the function +// Can initiate the comments above the function by doing /**, right above the function class RunManagement { constructor(trackingUri, path) { @@ -18,6 +18,115 @@ class RunManagement { this.path = path; } + /** + * + * @param {string} run_id - ID of the run which to log the tag. Required + * @param {string} key - Name of the tag. Maximum size depends on storage backend. All storage backends + * are guaranteed to support key values up to 250 bytes in size. Required + * @param {string} value - String value of the tag being logged. Maximum size depends on storage + * backend. All storage backends are guaranteed to support key values up to 5000 bytes in size. Required + * @returns {Promise Date: Tue, 27 Aug 2024 21:14:00 -0700 Subject: [PATCH 019/357] getExperimentByName --- .../tracking_server/experiment_management.js | 44 +++++++++++++++++-- 1 file changed, 41 insertions(+), 3 deletions(-) diff --git a/mlflow/src/tracking_server/experiment_management.js b/mlflow/src/tracking_server/experiment_management.js index 506fa179..3ac521d7 100644 --- a/mlflow/src/tracking_server/experiment_management.js +++ b/mlflow/src/tracking_server/experiment_management.js @@ -102,7 +102,7 @@ async function searchExperiment( // searchExperiment("name = 'test_experiment_postman'", 1); /** - * Get metadata for an experiment. This method works on deleted experiments. + * Get metadata for an experiment, querying by experiment ID. This method works on deleted experiments. * * @param {string} experiment_id ID of the associated experiment. (required) * @returns {Promise} Returns object containing the matched experiment. @@ -117,7 +117,6 @@ async function getExperiment(experiment_id) { const response = await fetch(url, { method: 'GET', headers: { 'Content-Type': 'application/json' }, - // body: JSON.stringify({ experiment_id }), }); if (!response.ok) { @@ -136,4 +135,43 @@ async function getExperiment(experiment_id) { } // run the next line to test ******************************************************************** -getExperiment('292357850348085316'); +// getExperiment('292357850348085316'); + + +/** + * Get metadata for an experiment, querying by experiment name. + * This endpoint will return deleted experiments, + * but prefers the active experiment if an active and deleted experiment share the same name. + * If multiple deleted experiments share the same name, the API will return one of them. + * + * @param {string} experiment_name ID of the associated experiment. (required) + * @returns {Promise} Returns object containing the matched experiment. + */ +async function getExperimentByName (experiment_name) { + try { + if (!experiment_name) { + throw new Error('Experiment name is required'); + } + + const url = `${MLFLOW_TRACKING_URI}/experiments/get-by-name?experiment_name=${experiment_name}`; + const response = await fetch(url, { + method: 'GET', + headers: { 'Content-Type': 'application/json' }, + }); + + if (!response.ok) { + const errorBody = await response.json(); + throw new Error( + `HTTP error from tracking server, status: ${response.status}. ${errorBody.message}` + ); + } + + const data = await response.json(); + console.log('data.experiment: ', data.experiment); + return data.experiment; + } catch (error) { + console.error('Error getting experiment by name: ', error); + } +} +// run the next line to test ******************************************************************** +// getExperimentByName('test_experiment_postman16'); \ No newline at end of file From 6041fd52f6c2138b9b7a26203501263608cd0c6f Mon Sep 17 00:00:00 2001 From: Kyler-Chiago Date: Tue, 27 Aug 2024 21:25:53 -0700 Subject: [PATCH 020/357] ModelRegistry: setRegisteredModelALias, deleteRegisteredModelAlias, getModelVersionByAlias DONE --- mlflow/src/model_registry/model_registry.js | 123 +++++++++++++++++++ mlflow/src/tracking_server/run_management.js | 12 +- 2 files changed, 130 insertions(+), 5 deletions(-) diff --git a/mlflow/src/model_registry/model_registry.js b/mlflow/src/model_registry/model_registry.js index 310fc75d..8d08f114 100644 --- a/mlflow/src/model_registry/model_registry.js +++ b/mlflow/src/model_registry/model_registry.js @@ -1,5 +1,15 @@ //model_registry.js +let domain = 'http://localhost:' +const port = 5001; +if (port) { + domain = domain + port; +} + +const version = '2.0'; + +const MLFLOW_TRACKING_URI = domain + '/api/' + version + '/mlflow'; + class ModelRegistry { constructor(trackingUri) { this.trackingUri = trackingUri; @@ -128,6 +138,119 @@ class ModelRegistry { async deleteRegisteredModelTag(name, key) { // Implementation } + + /** + * Sets an alias for a registered model version. + \* + * @param {string} name - The name of the registered model (required) + * @param {string} alias - The alias to set (required) + * @param {string} version - The version number to alias (required) + * @returns {Promise} + */ + async setRegisteredModelAlias(name, alias, version) { + if (!name) { + throw new Error("name is required"); + } else if (!alias) { + throw new Error("alias is required"); + } else if (!version) { + throw new Error("version is required"); + } + + const url = `${this.trackingUri}/registered-models/alias`; + const response = await fetch(url, { + method: "POST", + headers: { + "Content-Type": "application/json", + }, + body: JSON.stringify({ name, alias, version}), + }); + + // data is an empty object + const data = await response.json(); + // console.log('data: ', data); + if (!response.ok) { + throw new Error( + `Error setting model alias: ${ + response.statusText + }` + ); + } + return data; + } + + /** + * Deletes an alias for a registered model. + \* + * @param {string} name - The name of the registered model (required) + * @param {string} alias - The alias to delete (required) + * @returns {Promise} + */ + async deleteRegisteredModelAlias(name, alias) { + if (!name) { + throw new Error("name is required"); + } else if (!alias) { + throw new Error("alias is required"); + } + + const url = `${this.trackingUri}/registered-models/alias`; + const response = await fetch(url, { + method: "DELETE", + headers: { + "Content-Type": "application/json", + }, + body: JSON.stringify({ name, alias}), + }); + + // data is an empty object + const data = await response.json(); + console.log('data: ', data); + if (!response.ok) { + throw new Error( + `Error deleting model alias: ${ + response.statusText + }` + ); + } + return data; + } + + /** + * Gets a model version by its alias. + \* + * @param {string} name - The name of the registered model (required) + * @param {string} alias - The alias of the model version to retrieve (required) + * @returns {Promise} The model version object + */ + async getModelVersionByAlias(name, alias) { + if (!name) { + throw new Error("name is required"); + } else if (!alias) { + throw new Error("alias is required"); + } + const url = `${this.trackingUri}/registered-models/alias`; + const response = await fetch(`${url}?name=${name}&alias=${alias}`); + + /** + * data has the field: + * model_version + */ + const data = await response.json(); + // console.log('data: ', data); + if (!response.ok) { + throw new Error( + `Error getting model version by alias: ${ + data.message || response.statusText + }` + ); + } + return data; + } } + +let modelRegistry = new ModelRegistry(MLFLOW_TRACKING_URI); +// console.log(modelRegistry.setRegisteredModelAlias('tracking-quickstart', 'aliasTest', '1')); +// console.log(modelRegistry.deleteRegisteredModelAlias('tracking-quickstart', 'aliasTest')); +// console.log(modelRegistry.getModelVersionByAlias('sk-learn-random-forest-reg-model', 'the_best_model_ever')); + export { ModelRegistry }; diff --git a/mlflow/src/tracking_server/run_management.js b/mlflow/src/tracking_server/run_management.js index 06152d82..879fe01b 100644 --- a/mlflow/src/tracking_server/run_management.js +++ b/mlflow/src/tracking_server/run_management.js @@ -61,7 +61,7 @@ class RunManagement { * * @param {string} run_id - ID of the run that the tag was logged under. Required * @param {string} key - Name of the tag. Maximum size is 255 bytes. Required - * @returns {Promise} - Empty promise object */ async deleteTag (run_id, key) { if (!run_id) { @@ -96,7 +96,7 @@ class RunManagement { * @param {string} run_id - ID of the run under which to log the param. Required * @param {string} key - Name of the param. Maximum size is 255 bytes. Required * @param {string} value - String value of the param being logged. Maximum size is 6000 bytes. Required - * @returns {Promise} - Empty promise object * Note: A param can be logged only once for a run */ async logParam (run_id, key, value) { @@ -136,7 +136,7 @@ class RunManagement { * Backend servers may restrict the value of max_results depending on performance requirements. Requests that do not * specify this value will behave as non-paginated queries where all metric history values for a given metric * within a run are returned in a single response. - * @returns {Promise} - The values for the specified metric, as a promise object */ async getMetricHistory(run_id, metric_key, page_token, max_results) { if (!run_id) { @@ -244,7 +244,7 @@ class RunManagement { }; } -// let runManagement = new RunManagement(MLFLOW_TRACKING_URI, path); +let runManagement = new RunManagement(MLFLOW_TRACKING_URI, path); // console.log(runManagement.listArtifacts('b3457c87f50440388da9d9ddabb1baaa', 'mlflow-artifacts:/784321942139901150/b3457c87f50440388da9d9ddabb1baaa/artifacts/iris_model')); // console.log(runManagement.listArtifacts('b3457c87f50440388da9d9ddabb1baaa')); // console.log(runManagement.searchRuns(['784321942139901150'])); @@ -252,4 +252,6 @@ class RunManagement { // console.log(runManagement.getMetricHistory('df87d99de65a42f5bc52d6f5774364b6')); // console.log(runManagement.logParam('df87d99de65a42f5bc52d6f5774364b6','test2', '008')); // console.log(runManagement.setTag('df87d99de65a42f5bc52d6f5774364b6', 'testTag1', 'testTag1Val')) -// console.log(runManagement.deleteTag('df87d99de65a42f5bc52d6f5774364b6', 'testTag1')) \ No newline at end of file +// console.log(runManagement.deleteTag('df87d99de65a42f5bc52d6f5774364b6', 'testTag1')) + +export { RunManagement }; \ No newline at end of file From 4393dc1e5142bd58d1e27a4efffe137e797b8f7e Mon Sep 17 00:00:00 2001 From: Austin Fraser Date: Tue, 27 Aug 2024 22:24:16 -0700 Subject: [PATCH 021/357] restoreExperiment --- .../tracking_server/experiment_management.js | 96 +++++++++++++++++-- 1 file changed, 89 insertions(+), 7 deletions(-) diff --git a/mlflow/src/tracking_server/experiment_management.js b/mlflow/src/tracking_server/experiment_management.js index 3ac521d7..b4034611 100644 --- a/mlflow/src/tracking_server/experiment_management.js +++ b/mlflow/src/tracking_server/experiment_management.js @@ -99,7 +99,7 @@ async function searchExperiment( } // run the next line to test ******************************************************************** -// searchExperiment("name = 'test_experiment_postman'", 1); +// searchExperiment("name = 'test_experiment_postman15'", 1); /** * Get metadata for an experiment, querying by experiment ID. This method works on deleted experiments. @@ -135,19 +135,18 @@ async function getExperiment(experiment_id) { } // run the next line to test ******************************************************************** -// getExperiment('292357850348085316'); - +// getExperiment('977566317259111173'); /** * Get metadata for an experiment, querying by experiment name. - * This endpoint will return deleted experiments, - * but prefers the active experiment if an active and deleted experiment share the same name. + * This endpoint will return deleted experiments, + * but prefers the active experiment if an active and deleted experiment share the same name. * If multiple deleted experiments share the same name, the API will return one of them. * * @param {string} experiment_name ID of the associated experiment. (required) * @returns {Promise} Returns object containing the matched experiment. */ -async function getExperimentByName (experiment_name) { +async function getExperimentByName(experiment_name) { try { if (!experiment_name) { throw new Error('Experiment name is required'); @@ -174,4 +173,87 @@ async function getExperimentByName (experiment_name) { } } // run the next line to test ******************************************************************** -// getExperimentByName('test_experiment_postman16'); \ No newline at end of file +// getExperimentByName('test_experiment_postman16'); + +/** + * Mark an experiment for deletion. + * + * @param {string} experiment_id ID of the associated experiment. (required) + * @returns {string} Returns a string i.e. "Experiment ID 99999 successfully deleted" + */ +async function deleteExperiment(experiment_id) { + try { + if (!experiment_id) { + throw new Error('Experiment ID is required'); + } + + const url = `${MLFLOW_TRACKING_URI}/experiments/delete`; + const response = await fetch(url, { + method: 'POST', + headers: { 'Content-Type': 'application/json' }, + body: JSON.stringify({ experiment_id }), + }); + + if (!response.ok) { + const errorBody = await response.json(); + throw new Error( + `HTTP error from tracking server, status: ${response.status}. ${errorBody.message}` + ); + } + + console.log(`Experiment ID ${experiment_id} successfully deleted`); + return `Experiment ID ${experiment_id} successfully deleted`; + } catch (error) { + console.error('Error deleting experiment: ', error); + } +} + +// run the next line to test ******************************************************************** +// searchExperiment("name = 'SEARCH_AN_EXPERIMENT_NAME'", 1); +// deleteExperiment('PASTE_EXPERIMENT_ID_HERE'); +// getExperiment('PASTE_EXPERIMENT_ID_HERE'); + +/** + * Restore an experiment marked for deletion. + * + * @param {string} experiment_id ID of the associated experiment. (required) + * @returns {string} Returns a string i.e. "Experiment ID 99999 successfully restored" + */ +async function restoreExperiment(experiment_id) { + try { + if (!experiment_id) { + throw new Error('Experiment ID is required'); + } + + const url = `${MLFLOW_TRACKING_URI}/experiments/restore`; + const response = await fetch(url, { + method: 'POST', + headers: { 'Content-Type': 'application/json' }, + body: JSON.stringify({ experiment_id }), + }); + + if (!response.ok) { + const errorBody = await response.json(); + throw new Error( + `HTTP error from tracking server, status: ${response.status}. ${errorBody.message}` + ); + } + + console.log(`Experiment ID ${experiment_id} successfully restored`); + return `Experiment ID ${experiment_id} successfully restored`; + } catch (error) { + console.error('Error restoring experiment: ', error); + } +} + +// run the next line to test ******************************************************************** +// getExperimentByName('GET_AN_EXPERIMENT'); +// deleteExperiment('PASTE_EXPERIMENT_ID_HERE'); +// getExperiment('PASTE_EXPERIMENT_ID_HERE'); +// restoreExperiment('PASTE_EXPERIMENT_ID_HERE'); +// getExperiment('PASTE_EXPERIMENT_ID_HERE'); + +// getExperimentByName('test_experiment_postman16'); +// restoreExperiment('977566317259111173'); +// getExperiment('977566317259111173'); +// deleteExperiment('977566317259111173'); From cb7f336a4e6989a0987e3196f47bd4825a5c93a6 Mon Sep 17 00:00:00 2001 From: Austin Fraser Date: Tue, 27 Aug 2024 22:48:23 -0700 Subject: [PATCH 022/357] updateExperiment --- .../tracking_server/experiment_management.js | 41 +++++++++++++++++++ 1 file changed, 41 insertions(+) diff --git a/mlflow/src/tracking_server/experiment_management.js b/mlflow/src/tracking_server/experiment_management.js index b4034611..8b8a26a5 100644 --- a/mlflow/src/tracking_server/experiment_management.js +++ b/mlflow/src/tracking_server/experiment_management.js @@ -257,3 +257,44 @@ async function restoreExperiment(experiment_id) { // restoreExperiment('977566317259111173'); // getExperiment('977566317259111173'); // deleteExperiment('977566317259111173'); + +/** + * + * @param {string} experiment_id ID of the associated experiment. (required) + * @param {string} new_name The experiment’s name is changed to the new name. The new name must be unique. (required) + * @returns {string} Returns a string i.e. "Experiment ID 99999 successfully updated" + */ +async function updateExperiment(experiment_id, new_name) { + try { + if (!experiment_id) { + throw new Error('Experiment ID is required'); + } + if (!new_name) { + throw new Error('New name is required'); + } + + const url = `${MLFLOW_TRACKING_URI}/experiments/update`; + const response = await fetch(url, { + method: 'POST', + headers: { 'Content-Type': 'application/json' }, + body: JSON.stringify({ experiment_id, new_name }), + }); + + if (!response.ok) { + const errorBody = await response.json(); + throw new Error( + `HTTP error from tracking server, status: ${response.status}. ${errorBody.message}` + ); + } + + console.log(`Experiment ID ${experiment_id} successfully updated - new name is ${new_name}`); + return `Experiment ID ${experiment_id} successfully updated - new name is ${new_name}`; + } catch (error) { + console.error('Error updating experiment: ', error); + } +} + +// run the next line to test ******************************************************************** +// getExperimentByName('test_experiment_postman15'); +// updateExperiment('668323101796317879', 'test_experiment_postman15'); +// getExperimentByName('test_experiment_postman15'); From 5139e22e5be6e82bfb2f1c1003f4d368bafbd259 Mon Sep 17 00:00:00 2001 From: Austin Fraser Date: Tue, 27 Aug 2024 23:16:51 -0700 Subject: [PATCH 023/357] setExperimentTag --- .../tracking_server/experiment_management.js | 48 ++++++++++++++++++- 1 file changed, 47 insertions(+), 1 deletion(-) diff --git a/mlflow/src/tracking_server/experiment_management.js b/mlflow/src/tracking_server/experiment_management.js index 8b8a26a5..c6008936 100644 --- a/mlflow/src/tracking_server/experiment_management.js +++ b/mlflow/src/tracking_server/experiment_management.js @@ -3,7 +3,6 @@ const MLFLOW_TRACKING_URI = 'http://localhost:5001/api/2.0/mlflow'; /** * Create an experiment with a name. Returns the ID of the newly created experiment. * Validates that another experiment with the same name does not already exist and fails if another experiment with the same name already exists. - * Throws RESOURCE_ALREADY_EXISTS if a experiment with the given name exists. * * @param {string} name Experiment name. (required) * @param {string} artifact_location Optional location where all artifacts for the experiment are stored. @@ -259,6 +258,7 @@ async function restoreExperiment(experiment_id) { // deleteExperiment('977566317259111173'); /** + * Update experiment name. * * @param {string} experiment_id ID of the associated experiment. (required) * @param {string} new_name The experiment’s name is changed to the new name. The new name must be unique. (required) @@ -298,3 +298,49 @@ async function updateExperiment(experiment_id, new_name) { // getExperimentByName('test_experiment_postman15'); // updateExperiment('668323101796317879', 'test_experiment_postman15'); // getExperimentByName('test_experiment_postman15'); + +/** + * Set a tag on an experiment. + * + * @param {string} experiment_id ID of the experiment under which to log the tag. (required) + * @param {string} key Name of the tag. (required) + * @param {string} value String value of the tag being logged. (required) + * @returns {string} Returns a string, i.e. `Set tag to experiment ID 99999 successfully` + */ +async function setExperimentTag(experiment_id, key, value) { + try { + if (!experiment_id) { + throw new Error('Experiment ID is required'); + } + if (!key) { + throw new Error('Key is required'); + } + if (!value) { + throw new Error('Value is required'); + } + + const url = `${MLFLOW_TRACKING_URI}/experiments/set-experiment-tag`; + const response = await fetch(url, { + method: 'POST', + headers: { 'Content-Type': 'application/json' }, + body: JSON.stringify({ experiment_id, key, value }), + }); + + if (!response.ok) { + const errorBody = await response.json(); + throw new Error( + `HTTP error from tracking server, status: ${response.status}. ${errorBody.message}` + ); + } + + console.log(`Set tag to experiment ID ${experiment_id} successfully`); + return `Set tag to experiment ID ${experiment_id} successfully`; + } catch (error) { + console.error('Error setting tag: ', error); + } +} + +// run the next line to test ******************************************************************** +// getExperimentByName('test_experiment_postman15'); +// setExperimentTag('668323101796317879', 'test_tag', 'test_value_UPDATE'); +// getExperimentByName('test_experiment_postman15'); \ No newline at end of file From aeb755577476f2597d1d5ec68ea5f00c0ee573c1 Mon Sep 17 00:00:00 2001 From: Kyler-Chiago Date: Wed, 28 Aug 2024 19:54:07 -0700 Subject: [PATCH 024/357] removed extra code, still need to merge in dev --- mlflow/src/model_registry/model_registry.js | 12 ++---- mlflow/src/tracking_server/run_management.js | 35 +++------------- mlflow/src/tracking_server/test.js | 44 ++++++++++++++++++++ 3 files changed, 52 insertions(+), 39 deletions(-) create mode 100644 mlflow/src/tracking_server/test.js diff --git a/mlflow/src/model_registry/model_registry.js b/mlflow/src/model_registry/model_registry.js index 8d08f114..b9e9060b 100644 --- a/mlflow/src/model_registry/model_registry.js +++ b/mlflow/src/model_registry/model_registry.js @@ -167,7 +167,7 @@ class ModelRegistry { // data is an empty object const data = await response.json(); - // console.log('data: ', data); + if (!response.ok) { throw new Error( `Error setting model alias: ${ @@ -203,7 +203,7 @@ class ModelRegistry { // data is an empty object const data = await response.json(); - console.log('data: ', data); + if (!response.ok) { throw new Error( `Error deleting model alias: ${ @@ -235,7 +235,7 @@ class ModelRegistry { * model_version */ const data = await response.json(); - // console.log('data: ', data); + if (!response.ok) { throw new Error( `Error getting model version by alias: ${ @@ -247,10 +247,4 @@ class ModelRegistry { } } - -let modelRegistry = new ModelRegistry(MLFLOW_TRACKING_URI); -// console.log(modelRegistry.setRegisteredModelAlias('tracking-quickstart', 'aliasTest', '1')); -// console.log(modelRegistry.deleteRegisteredModelAlias('tracking-quickstart', 'aliasTest')); -// console.log(modelRegistry.getModelVersionByAlias('sk-learn-random-forest-reg-model', 'the_best_model_ever')); - export { ModelRegistry }; diff --git a/mlflow/src/tracking_server/run_management.js b/mlflow/src/tracking_server/run_management.js index 879fe01b..c337483e 100644 --- a/mlflow/src/tracking_server/run_management.js +++ b/mlflow/src/tracking_server/run_management.js @@ -1,17 +1,3 @@ -let domain = 'http://localhost:' -const port = 5001; -if (port) { - domain = domain + port; -} - -const version = '2.0'; - -const MLFLOW_TRACKING_URI = domain + '/api/' + version + '/mlflow'; - -const path = 'artifacts'; - -// Can initiate the comments above the function by doing /**, right above the function - class RunManagement { constructor(trackingUri, path) { this.trackingUri = trackingUri; @@ -46,7 +32,7 @@ class RunManagement { // data is an empty object const data = await response.json(); - // console.log('data: ', data); + if (!response.ok) { throw new Error( `Error logging param: ${ @@ -80,7 +66,7 @@ class RunManagement { // data is an empty object const data = await response.json(); - // console.log('data: ', data); + if (!response.ok) { throw new Error( `Error logging param: ${ @@ -160,7 +146,7 @@ class RunManagement { }` ); } - // console.log('data: ', data); + return data; } @@ -207,8 +193,7 @@ class RunManagement { }` ); } - // console.log('data: ', data); - // console.log('data.runs: ', data.runs); + return data; } @@ -239,19 +224,9 @@ class RunManagement { }` ); } - console.log('data: ', data); + return data; }; } -let runManagement = new RunManagement(MLFLOW_TRACKING_URI, path); -// console.log(runManagement.listArtifacts('b3457c87f50440388da9d9ddabb1baaa', 'mlflow-artifacts:/784321942139901150/b3457c87f50440388da9d9ddabb1baaa/artifacts/iris_model')); -// console.log(runManagement.listArtifacts('b3457c87f50440388da9d9ddabb1baaa')); -// console.log(runManagement.searchRuns(['784321942139901150'])); -// console.log(runManagement.searchRuns()); -// console.log(runManagement.getMetricHistory('df87d99de65a42f5bc52d6f5774364b6')); -// console.log(runManagement.logParam('df87d99de65a42f5bc52d6f5774364b6','test2', '008')); -// console.log(runManagement.setTag('df87d99de65a42f5bc52d6f5774364b6', 'testTag1', 'testTag1Val')) -// console.log(runManagement.deleteTag('df87d99de65a42f5bc52d6f5774364b6', 'testTag1')) - export { RunManagement }; \ No newline at end of file diff --git a/mlflow/src/tracking_server/test.js b/mlflow/src/tracking_server/test.js new file mode 100644 index 00000000..7b09c14c --- /dev/null +++ b/mlflow/src/tracking_server/test.js @@ -0,0 +1,44 @@ +import { RunManagement } from "./run_management.js"; + +let domain = 'http://localhost:' +const port = 5001; +if (port) { + domain = domain + port; +} + +const version = '2.0'; + +const MLFLOW_TRACKING_URI = domain + '/api/' + version + '/mlflow'; + +const path = 'artifacts'; + +let runManagement = new RunManagement(MLFLOW_TRACKING_URI, path); +// console.log(runManagement.searchRuns(['784321942139901150'])); + +const test = async () => { + // console.log('hi'); + try { + let data = await runManagement.searchRuns(['784321942139901150']); + console.log('data: ', data); + } catch (err) { + console.log('err: ', err); + } +} + +test(); + +// let runManagement = new RunManagement(MLFLOW_TRACKING_URI, path); +// console.log(runManagement.listArtifacts('b3457c87f50440388da9d9ddabb1baaa', 'mlflow-artifacts:/784321942139901150/b3457c87f50440388da9d9ddabb1baaa/artifacts/iris_model')); +// console.log(runManagement.listArtifacts('b3457c87f50440388da9d9ddabb1baaa')); +// console.log(runManagement.searchRuns(['784321942139901150'])); +// console.log(runManagement.searchRuns()); +// console.log(runManagement.getMetricHistory('b3457c87f50440388da9d9ddabb1baaa', 'accuracy')); +// console.log(runManagement.logParam('b3457c87f50440388da9d9ddabb1baaa','test2', '008')); +// console.log(runManagement.setTag('b3457c87f50440388da9d9ddabb1baaa', 'testTag1', 'testTag1Val')) +// console.log(runManagement.deleteTag('b3457c87f50440388da9d9ddabb1baaa', 'testTag1')) + + +// let modelRegistry = new ModelRegistry(MLFLOW_TRACKING_URI); +// console.log(modelRegistry.setRegisteredModelAlias('tracking-quickstart', 'aliasTest', '1')); +// console.log(modelRegistry.deleteRegisteredModelAlias('tracking-quickstart', 'aliasTest')); +// console.log(modelRegistry.getModelVersionByAlias('sk-learn-random-forest-reg-model', 'the_best_model_ever')); \ No newline at end of file From 0ea6c5e1819d5c94facc4218bf1781589367b892 Mon Sep 17 00:00:00 2001 From: Austin Fraser Date: Thu, 29 Aug 2024 12:27:23 -0700 Subject: [PATCH 025/357] added tests to each function --- .../tracking_server/experiment_management.js | 126 +++++++++++++----- 1 file changed, 89 insertions(+), 37 deletions(-) diff --git a/mlflow/src/tracking_server/experiment_management.js b/mlflow/src/tracking_server/experiment_management.js index c6008936..2737ca6b 100644 --- a/mlflow/src/tracking_server/experiment_management.js +++ b/mlflow/src/tracking_server/experiment_management.js @@ -31,15 +31,20 @@ async function createExperiment(name, artifact_location = '', tags = []) { } const data = await response.json(); - console.log('data: ', data); + // console.log('return from createExperiment: ', data); return data; } catch (error) { console.error('Error creating experiment: ', error); } } -// run the next line to test ******************************************************************** -// createExperiment('test_experiment_postman16'); +// test **************************************************************************************************************************************** +const testCreateExperiment = async () => { + const log = await createExperiment('test_experiment_postman18'); + return console.log(log); +} +// uncomment below --- +// testCreateExperiment(); /** * Search experiments. @@ -90,15 +95,20 @@ async function searchExperiment( } const data = await response.json(); - console.log('data: ', data); + // console.log('return from searchExperiment: ', data); return data; } catch (error) { console.error('Error searching for experiment: ', error); } } -// run the next line to test ******************************************************************** -// searchExperiment("name = 'test_experiment_postman15'", 1); +// test **************************************************************************************************************************************** +const testSearchExperiment = async () => { + const log = await searchExperiment("name = 'test_experiment_postman15'", 1); + console.log(log); +} +// uncomment below --- +// testSearchExperiment(); /** * Get metadata for an experiment, querying by experiment ID. This method works on deleted experiments. @@ -126,15 +136,20 @@ async function getExperiment(experiment_id) { } const data = await response.json(); - console.log('data.experiment: ', data.experiment); - return data.experiment; + // console.log('return from getExperiment: ', data); + return data; } catch (error) { console.error('Error getting experiment: ', error); } } -// run the next line to test ******************************************************************** -// getExperiment('977566317259111173'); +// test **************************************************************************************************************************************** +const testGetExperiment = async () => { + const log = await getExperiment('977566317259111173'); + console.log(log); +} +// uncomment below --- +// testGetExperiment(); /** * Get metadata for an experiment, querying by experiment name. @@ -165,14 +180,20 @@ async function getExperimentByName(experiment_name) { } const data = await response.json(); - console.log('data.experiment: ', data.experiment); - return data.experiment; + // console.log('return from getExperimentByName: ', data); + return data; } catch (error) { console.error('Error getting experiment by name: ', error); } } -// run the next line to test ******************************************************************** +// test **************************************************************************************************************************************** // getExperimentByName('test_experiment_postman16'); +const testGetExperimentByName = async () => { + const log = await getExperimentByName('test_experiment_postman16'); + console.log(log); +} +// uncomment below --- +// testGetExperimentByName(); /** * Mark an experiment for deletion. @@ -200,17 +221,23 @@ async function deleteExperiment(experiment_id) { ); } - console.log(`Experiment ID ${experiment_id} successfully deleted`); + // console.log(`Experiment ID ${experiment_id} successfully deleted`); return `Experiment ID ${experiment_id} successfully deleted`; } catch (error) { console.error('Error deleting experiment: ', error); } } -// run the next line to test ******************************************************************** -// searchExperiment("name = 'SEARCH_AN_EXPERIMENT_NAME'", 1); -// deleteExperiment('PASTE_EXPERIMENT_ID_HERE'); -// getExperiment('PASTE_EXPERIMENT_ID_HERE'); +// test **************************************************************************************************************************************** +const testDeleteExperiment = async () => { + const log = await deleteExperiment('993400766971093020'); + console.log(log); + const log2 = await getExperiment('993400766971093020'); + console.log(log2); + restoreExperiment('993400766971093020'); +} +// uncomment below --- +// testDeleteExperiment(); /** * Restore an experiment marked for deletion. @@ -238,24 +265,28 @@ async function restoreExperiment(experiment_id) { ); } - console.log(`Experiment ID ${experiment_id} successfully restored`); + // console.log(`Experiment ID ${experiment_id} successfully restored`); return `Experiment ID ${experiment_id} successfully restored`; } catch (error) { console.error('Error restoring experiment: ', error); } } -// run the next line to test ******************************************************************** -// getExperimentByName('GET_AN_EXPERIMENT'); -// deleteExperiment('PASTE_EXPERIMENT_ID_HERE'); -// getExperiment('PASTE_EXPERIMENT_ID_HERE'); -// restoreExperiment('PASTE_EXPERIMENT_ID_HERE'); -// getExperiment('PASTE_EXPERIMENT_ID_HERE'); - -// getExperimentByName('test_experiment_postman16'); -// restoreExperiment('977566317259111173'); -// getExperiment('977566317259111173'); -// deleteExperiment('977566317259111173'); +// test **************************************************************************************************************************************** +const testRestoreExperiment = async () => { + const log = await getExperiment('977566317259111173'); + console.log(log); + const deleted = await deleteExperiment('977566317259111173'); + console.log(deleted); + const log2 = await getExperiment('977566317259111173'); + console.log(log2); + const log3 = await restoreExperiment('977566317259111173'); + console.log(log3); + const log4 = await getExperiment('977566317259111173'); + console.log(log4); +} +// uncomment below --- +// testRestoreExperiment(); /** * Update experiment name. @@ -287,18 +318,30 @@ async function updateExperiment(experiment_id, new_name) { ); } - console.log(`Experiment ID ${experiment_id} successfully updated - new name is ${new_name}`); + // console.log(`Experiment ID ${experiment_id} successfully updated - new name is ${new_name}`); return `Experiment ID ${experiment_id} successfully updated - new name is ${new_name}`; } catch (error) { console.error('Error updating experiment: ', error); } } -// run the next line to test ******************************************************************** +// test **************************************************************************************************************************************** // getExperimentByName('test_experiment_postman15'); // updateExperiment('668323101796317879', 'test_experiment_postman15'); // getExperimentByName('test_experiment_postman15'); +const testUpdateExperiment = async () => { + const log = await getExperiment('668323101796317879'); + console.log(log); + const log2 = await updateExperiment('668323101796317879', 'test_experiment_postman15_UPDATED_NAME'); + console.log(log2); + const log3 = await getExperiment('668323101796317879'); + console.log(log3); + const revert = await updateExperiment('668323101796317879', 'test_experiment_postman15'); +}; +// uncomment below --- +// testUpdateExperiment(); + /** * Set a tag on an experiment. * @@ -333,14 +376,23 @@ async function setExperimentTag(experiment_id, key, value) { ); } - console.log(`Set tag to experiment ID ${experiment_id} successfully`); + // console.log(`Set tag to experiment ID ${experiment_id} successfully`); return `Set tag to experiment ID ${experiment_id} successfully`; } catch (error) { console.error('Error setting tag: ', error); } } -// run the next line to test ******************************************************************** -// getExperimentByName('test_experiment_postman15'); -// setExperimentTag('668323101796317879', 'test_tag', 'test_value_UPDATE'); -// getExperimentByName('test_experiment_postman15'); \ No newline at end of file +// test **************************************************************************************************************************************** +const testSetExperimentTag = async () => { + const log = await getExperiment('691149904576236192'); + console.log(log); + console.log(log.experiment.tags); + const log2 = await setExperimentTag('691149904576236192', 'test_tag', 'test_value'); + console.log(log2); + const log3 = await getExperiment('691149904576236192'); + console.log(log3); + console.log(log3.experiment.tags); +}; +// uncomment below --- +// testSetExperimentTag(); \ No newline at end of file From a46f4eac4b5f9bc4f283f6cde496cf350e5bb454 Mon Sep 17 00:00:00 2001 From: Austin Fraser Date: Thu, 29 Aug 2024 12:33:12 -0700 Subject: [PATCH 026/357] ran Prettier --- .../tracking_server/experiment_management.js | 38 ++++++++++++------- 1 file changed, 24 insertions(+), 14 deletions(-) diff --git a/mlflow/src/tracking_server/experiment_management.js b/mlflow/src/tracking_server/experiment_management.js index 2737ca6b..8facb2d1 100644 --- a/mlflow/src/tracking_server/experiment_management.js +++ b/mlflow/src/tracking_server/experiment_management.js @@ -42,7 +42,7 @@ async function createExperiment(name, artifact_location = '', tags = []) { const testCreateExperiment = async () => { const log = await createExperiment('test_experiment_postman18'); return console.log(log); -} +}; // uncomment below --- // testCreateExperiment(); @@ -106,7 +106,7 @@ async function searchExperiment( const testSearchExperiment = async () => { const log = await searchExperiment("name = 'test_experiment_postman15'", 1); console.log(log); -} +}; // uncomment below --- // testSearchExperiment(); @@ -147,7 +147,7 @@ async function getExperiment(experiment_id) { const testGetExperiment = async () => { const log = await getExperiment('977566317259111173'); console.log(log); -} +}; // uncomment below --- // testGetExperiment(); @@ -191,13 +191,13 @@ async function getExperimentByName(experiment_name) { const testGetExperimentByName = async () => { const log = await getExperimentByName('test_experiment_postman16'); console.log(log); -} +}; // uncomment below --- // testGetExperimentByName(); /** * Mark an experiment for deletion. - * + * * @param {string} experiment_id ID of the associated experiment. (required) * @returns {string} Returns a string i.e. "Experiment ID 99999 successfully deleted" */ @@ -235,13 +235,13 @@ const testDeleteExperiment = async () => { const log2 = await getExperiment('993400766971093020'); console.log(log2); restoreExperiment('993400766971093020'); -} +}; // uncomment below --- // testDeleteExperiment(); /** * Restore an experiment marked for deletion. - * + * * @param {string} experiment_id ID of the associated experiment. (required) * @returns {string} Returns a string i.e. "Experiment ID 99999 successfully restored" */ @@ -284,13 +284,13 @@ const testRestoreExperiment = async () => { console.log(log3); const log4 = await getExperiment('977566317259111173'); console.log(log4); -} +}; // uncomment below --- // testRestoreExperiment(); /** * Update experiment name. - * + * * @param {string} experiment_id ID of the associated experiment. (required) * @param {string} new_name The experiment’s name is changed to the new name. The new name must be unique. (required) * @returns {string} Returns a string i.e. "Experiment ID 99999 successfully updated" @@ -333,18 +333,24 @@ async function updateExperiment(experiment_id, new_name) { const testUpdateExperiment = async () => { const log = await getExperiment('668323101796317879'); console.log(log); - const log2 = await updateExperiment('668323101796317879', 'test_experiment_postman15_UPDATED_NAME'); + const log2 = await updateExperiment( + '668323101796317879', + 'test_experiment_postman15_UPDATED_NAME' + ); console.log(log2); const log3 = await getExperiment('668323101796317879'); console.log(log3); - const revert = await updateExperiment('668323101796317879', 'test_experiment_postman15'); + const revert = await updateExperiment( + '668323101796317879', + 'test_experiment_postman15' + ); }; // uncomment below --- // testUpdateExperiment(); /** * Set a tag on an experiment. - * + * * @param {string} experiment_id ID of the experiment under which to log the tag. (required) * @param {string} key Name of the tag. (required) * @param {string} value String value of the tag being logged. (required) @@ -388,11 +394,15 @@ const testSetExperimentTag = async () => { const log = await getExperiment('691149904576236192'); console.log(log); console.log(log.experiment.tags); - const log2 = await setExperimentTag('691149904576236192', 'test_tag', 'test_value'); + const log2 = await setExperimentTag( + '691149904576236192', + 'test_tag', + 'test_value' + ); console.log(log2); const log3 = await getExperiment('691149904576236192'); console.log(log3); console.log(log3.experiment.tags); }; // uncomment below --- -// testSetExperimentTag(); \ No newline at end of file +// testSetExperimentTag(); From 245bb1ba4e619e48c418eff4dcd36401efab6efc Mon Sep 17 00:00:00 2001 From: Austin Fraser Date: Thu, 29 Aug 2024 19:23:21 -0700 Subject: [PATCH 027/357] refactored returns of some functions to be more specific, instead of just returning 'data' --- .../tracking_server/experiment_management.js | 18 +++++++----------- 1 file changed, 7 insertions(+), 11 deletions(-) diff --git a/mlflow/src/tracking_server/experiment_management.js b/mlflow/src/tracking_server/experiment_management.js index 8facb2d1..a85264e2 100644 --- a/mlflow/src/tracking_server/experiment_management.js +++ b/mlflow/src/tracking_server/experiment_management.js @@ -40,7 +40,7 @@ async function createExperiment(name, artifact_location = '', tags = []) { // test **************************************************************************************************************************************** const testCreateExperiment = async () => { - const log = await createExperiment('test_experiment_postman18'); + const log = await createExperiment('test_experiment_postman20'); return console.log(log); }; // uncomment below --- @@ -104,7 +104,7 @@ async function searchExperiment( // test **************************************************************************************************************************************** const testSearchExperiment = async () => { - const log = await searchExperiment("name = 'test_experiment_postman15'", 1); + const log = await searchExperiment("name LIKE 'test_%'", 1000); console.log(log); }; // uncomment below --- @@ -136,8 +136,8 @@ async function getExperiment(experiment_id) { } const data = await response.json(); - // console.log('return from getExperiment: ', data); - return data; + // console.log('return from getExperiment: ', data.experiment); + return data.experiment; } catch (error) { console.error('Error getting experiment: ', error); } @@ -180,8 +180,8 @@ async function getExperimentByName(experiment_name) { } const data = await response.json(); - // console.log('return from getExperimentByName: ', data); - return data; + // console.log('return from getExperimentByName: ', data.experiment); + return data.experiment; } catch (error) { console.error('Error getting experiment by name: ', error); } @@ -326,10 +326,6 @@ async function updateExperiment(experiment_id, new_name) { } // test **************************************************************************************************************************************** -// getExperimentByName('test_experiment_postman15'); -// updateExperiment('668323101796317879', 'test_experiment_postman15'); -// getExperimentByName('test_experiment_postman15'); - const testUpdateExperiment = async () => { const log = await getExperiment('668323101796317879'); console.log(log); @@ -397,7 +393,7 @@ const testSetExperimentTag = async () => { const log2 = await setExperimentTag( '691149904576236192', 'test_tag', - 'test_value' + 'test_value_LIVE_DEMO' ); console.log(log2); const log3 = await getExperiment('691149904576236192'); From cf3afd4ed4c10546596c00dd84fc62943fb38adf Mon Sep 17 00:00:00 2001 From: Austin Fraser Date: Thu, 29 Aug 2024 19:46:18 -0700 Subject: [PATCH 028/357] removed try/catch blocks from all functions --- .../tracking_server/experiment_management.js | 386 ++++++++---------- .../src/tracking_server/tempCodeRunnerFile.js | 2 - 2 files changed, 177 insertions(+), 211 deletions(-) delete mode 100644 mlflow/src/tracking_server/tempCodeRunnerFile.js diff --git a/mlflow/src/tracking_server/experiment_management.js b/mlflow/src/tracking_server/experiment_management.js index a85264e2..d9dadc6b 100644 --- a/mlflow/src/tracking_server/experiment_management.js +++ b/mlflow/src/tracking_server/experiment_management.js @@ -11,36 +11,32 @@ const MLFLOW_TRACKING_URI = 'http://localhost:5001/api/2.0/mlflow'; * @returns {Promise} Returns the ID of the newly created experiment in an object. */ async function createExperiment(name, artifact_location = '', tags = []) { - try { - if (!name) { - throw new Error('Experiment name is required'); - } - - const url = `${MLFLOW_TRACKING_URI}/experiments/create`; - const response = await fetch(url, { - method: 'POST', - headers: { 'Content-Type': 'application/json' }, - body: JSON.stringify({ name, artifact_location, tags }), - }); - - if (!response.ok) { - const errorBody = await response.json(); - throw new Error( - `HTTP error from tracking server, status: ${response.status}. ${errorBody.message}` - ); - } - - const data = await response.json(); - // console.log('return from createExperiment: ', data); - return data; - } catch (error) { - console.error('Error creating experiment: ', error); + if (!name) { + throw new Error('Experiment name is required'); } + + const url = `${MLFLOW_TRACKING_URI}/experiments/create`; + const response = await fetch(url, { + method: 'POST', + headers: { 'Content-Type': 'application/json' }, + body: JSON.stringify({ name, artifact_location, tags }), + }); + + if (!response.ok) { + const errorBody = await response.json(); + throw new Error( + `Error creating experiment from tracking server, status: ${response.status}. ${errorBody.message}` + ); + } + + const data = await response.json(); + // console.log('return from createExperiment: ', data); + return data; } // test **************************************************************************************************************************************** const testCreateExperiment = async () => { - const log = await createExperiment('test_experiment_postman20'); + const log = await createExperiment('test_experiment_postman21'); return console.log(log); }; // uncomment below --- @@ -66,45 +62,41 @@ async function searchExperiment( order_by = [], view_type = '' ) { - try { - if (!filter) { - throw new Error('Filter is required'); - } - if (!max_results) { - throw new Error('Max results is required'); - } - - const url = `${MLFLOW_TRACKING_URI}/experiments/search`; - const response = await fetch(url, { - method: 'POST', - headers: { 'Content-Type': 'application/json' }, - body: JSON.stringify({ - filter, - max_results, - page_token, - order_by, - view_type, - }), - }); - - if (!response.ok) { - const errorBody = await response.json(); - throw new Error( - `HTTP error from tracking server, status: ${response.status}. ${errorBody.message}` - ); - } - - const data = await response.json(); - // console.log('return from searchExperiment: ', data); - return data; - } catch (error) { - console.error('Error searching for experiment: ', error); + if (!filter) { + throw new Error('Filter is required'); + } + if (!max_results) { + throw new Error('Max results is required'); } + + const url = `${MLFLOW_TRACKING_URI}/experiments/search`; + const response = await fetch(url, { + method: 'POST', + headers: { 'Content-Type': 'application/json' }, + body: JSON.stringify({ + filter, + max_results, + page_token, + order_by, + view_type, + }), + }); + + if (!response.ok) { + const errorBody = await response.json(); + throw new Error( + `Error searching for experiment from tracking server, status: ${response.status}. ${errorBody.message}` + ); + } + + const data = await response.json(); + // console.log('return from searchExperiment: ', data); + return data; } // test **************************************************************************************************************************************** const testSearchExperiment = async () => { - const log = await searchExperiment("name LIKE 'test_%'", 1000); + const log = await searchExperiment("name LIKE 'test_%'", 5); console.log(log); }; // uncomment below --- @@ -117,30 +109,26 @@ const testSearchExperiment = async () => { * @returns {Promise} Returns object containing the matched experiment. */ async function getExperiment(experiment_id) { - try { - if (!experiment_id) { - throw new Error('Experiment ID is required'); - } - - const url = `${MLFLOW_TRACKING_URI}/experiments/get?experiment_id=${experiment_id}`; - const response = await fetch(url, { - method: 'GET', - headers: { 'Content-Type': 'application/json' }, - }); - - if (!response.ok) { - const errorBody = await response.json(); - throw new Error( - `HTTP error from tracking server, status: ${response.status}. ${errorBody.message}` - ); - } - - const data = await response.json(); - // console.log('return from getExperiment: ', data.experiment); - return data.experiment; - } catch (error) { - console.error('Error getting experiment: ', error); + if (!experiment_id) { + throw new Error('Experiment ID is required'); } + + const url = `${MLFLOW_TRACKING_URI}/experiments/get?experiment_id=${experiment_id}`; + const response = await fetch(url, { + method: 'GET', + headers: { 'Content-Type': 'application/json' }, + }); + + if (!response.ok) { + const errorBody = await response.json(); + throw new Error( + `Error getting experiment from tracking server, status: ${response.status}. ${errorBody.message}` + ); + } + + const data = await response.json(); + // console.log('return from getExperiment: ', data.experiment); + return data.experiment; } // test **************************************************************************************************************************************** @@ -161,30 +149,26 @@ const testGetExperiment = async () => { * @returns {Promise} Returns object containing the matched experiment. */ async function getExperimentByName(experiment_name) { - try { - if (!experiment_name) { - throw new Error('Experiment name is required'); - } - - const url = `${MLFLOW_TRACKING_URI}/experiments/get-by-name?experiment_name=${experiment_name}`; - const response = await fetch(url, { - method: 'GET', - headers: { 'Content-Type': 'application/json' }, - }); - - if (!response.ok) { - const errorBody = await response.json(); - throw new Error( - `HTTP error from tracking server, status: ${response.status}. ${errorBody.message}` - ); - } - - const data = await response.json(); - // console.log('return from getExperimentByName: ', data.experiment); - return data.experiment; - } catch (error) { - console.error('Error getting experiment by name: ', error); + if (!experiment_name) { + throw new Error('Experiment name is required'); } + + const url = `${MLFLOW_TRACKING_URI}/experiments/get-by-name?experiment_name=${experiment_name}`; + const response = await fetch(url, { + method: 'GET', + headers: { 'Content-Type': 'application/json' }, + }); + + if (!response.ok) { + const errorBody = await response.json(); + throw new Error( + `Error getting experiment by name from tracking server, status: ${response.status}. ${errorBody.message}` + ); + } + + const data = await response.json(); + // console.log('return from getExperimentByName: ', data.experiment); + return data.experiment; } // test **************************************************************************************************************************************** // getExperimentByName('test_experiment_postman16'); @@ -202,30 +186,26 @@ const testGetExperimentByName = async () => { * @returns {string} Returns a string i.e. "Experiment ID 99999 successfully deleted" */ async function deleteExperiment(experiment_id) { - try { - if (!experiment_id) { - throw new Error('Experiment ID is required'); - } - - const url = `${MLFLOW_TRACKING_URI}/experiments/delete`; - const response = await fetch(url, { - method: 'POST', - headers: { 'Content-Type': 'application/json' }, - body: JSON.stringify({ experiment_id }), - }); - - if (!response.ok) { - const errorBody = await response.json(); - throw new Error( - `HTTP error from tracking server, status: ${response.status}. ${errorBody.message}` - ); - } - - // console.log(`Experiment ID ${experiment_id} successfully deleted`); - return `Experiment ID ${experiment_id} successfully deleted`; - } catch (error) { - console.error('Error deleting experiment: ', error); + if (!experiment_id) { + throw new Error('Experiment ID is required'); + } + + const url = `${MLFLOW_TRACKING_URI}/experiments/delete`; + const response = await fetch(url, { + method: 'POST', + headers: { 'Content-Type': 'application/json' }, + body: JSON.stringify({ experiment_id }), + }); + + if (!response.ok) { + const errorBody = await response.json(); + throw new Error( + `Error deleting experiment from tracking server, status: ${response.status}. ${errorBody.message}` + ); } + + // console.log(`Experiment ID ${experiment_id} successfully deleted`); + return `Experiment ID ${experiment_id} successfully deleted`; } // test **************************************************************************************************************************************** @@ -246,30 +226,26 @@ const testDeleteExperiment = async () => { * @returns {string} Returns a string i.e. "Experiment ID 99999 successfully restored" */ async function restoreExperiment(experiment_id) { - try { - if (!experiment_id) { - throw new Error('Experiment ID is required'); - } - - const url = `${MLFLOW_TRACKING_URI}/experiments/restore`; - const response = await fetch(url, { - method: 'POST', - headers: { 'Content-Type': 'application/json' }, - body: JSON.stringify({ experiment_id }), - }); - - if (!response.ok) { - const errorBody = await response.json(); - throw new Error( - `HTTP error from tracking server, status: ${response.status}. ${errorBody.message}` - ); - } - - // console.log(`Experiment ID ${experiment_id} successfully restored`); - return `Experiment ID ${experiment_id} successfully restored`; - } catch (error) { - console.error('Error restoring experiment: ', error); + if (!experiment_id) { + throw new Error('Experiment ID is required'); + } + + const url = `${MLFLOW_TRACKING_URI}/experiments/restore`; + const response = await fetch(url, { + method: 'POST', + headers: { 'Content-Type': 'application/json' }, + body: JSON.stringify({ experiment_id }), + }); + + if (!response.ok) { + const errorBody = await response.json(); + throw new Error( + `Error restoring experiment from tracking server, status: ${response.status}. ${errorBody.message}` + ); } + + // console.log(`Experiment ID ${experiment_id} successfully restored`); + return `Experiment ID ${experiment_id} successfully restored`; } // test **************************************************************************************************************************************** @@ -296,33 +272,29 @@ const testRestoreExperiment = async () => { * @returns {string} Returns a string i.e. "Experiment ID 99999 successfully updated" */ async function updateExperiment(experiment_id, new_name) { - try { - if (!experiment_id) { - throw new Error('Experiment ID is required'); - } - if (!new_name) { - throw new Error('New name is required'); - } - - const url = `${MLFLOW_TRACKING_URI}/experiments/update`; - const response = await fetch(url, { - method: 'POST', - headers: { 'Content-Type': 'application/json' }, - body: JSON.stringify({ experiment_id, new_name }), - }); - - if (!response.ok) { - const errorBody = await response.json(); - throw new Error( - `HTTP error from tracking server, status: ${response.status}. ${errorBody.message}` - ); - } - - // console.log(`Experiment ID ${experiment_id} successfully updated - new name is ${new_name}`); - return `Experiment ID ${experiment_id} successfully updated - new name is ${new_name}`; - } catch (error) { - console.error('Error updating experiment: ', error); + if (!experiment_id) { + throw new Error('Experiment ID is required'); + } + if (!new_name) { + throw new Error('New name is required'); + } + + const url = `${MLFLOW_TRACKING_URI}/experiments/update`; + const response = await fetch(url, { + method: 'POST', + headers: { 'Content-Type': 'application/json' }, + body: JSON.stringify({ experiment_id, new_name }), + }); + + if (!response.ok) { + const errorBody = await response.json(); + throw new Error( + `Error updating experiment from tracking server, status: ${response.status}. ${errorBody.message}` + ); } + + // console.log(`Experiment ID ${experiment_id} successfully updated - new name is ${new_name}`); + return `Experiment ID ${experiment_id} successfully updated - new name is ${new_name}`; } // test **************************************************************************************************************************************** @@ -353,52 +325,48 @@ const testUpdateExperiment = async () => { * @returns {string} Returns a string, i.e. `Set tag to experiment ID 99999 successfully` */ async function setExperimentTag(experiment_id, key, value) { - try { - if (!experiment_id) { - throw new Error('Experiment ID is required'); - } - if (!key) { - throw new Error('Key is required'); - } - if (!value) { - throw new Error('Value is required'); - } - - const url = `${MLFLOW_TRACKING_URI}/experiments/set-experiment-tag`; - const response = await fetch(url, { - method: 'POST', - headers: { 'Content-Type': 'application/json' }, - body: JSON.stringify({ experiment_id, key, value }), - }); - - if (!response.ok) { - const errorBody = await response.json(); - throw new Error( - `HTTP error from tracking server, status: ${response.status}. ${errorBody.message}` - ); - } - - // console.log(`Set tag to experiment ID ${experiment_id} successfully`); - return `Set tag to experiment ID ${experiment_id} successfully`; - } catch (error) { - console.error('Error setting tag: ', error); + if (!experiment_id) { + throw new Error('Experiment ID is required'); + } + if (!key) { + throw new Error('Key is required'); + } + if (!value) { + throw new Error('Value is required'); } + + const url = `${MLFLOW_TRACKING_URI}/experiments/set-experiment-tag`; + const response = await fetch(url, { + method: 'POST', + headers: { 'Content-Type': 'application/json' }, + body: JSON.stringify({ experiment_id, key, value }), + }); + + if (!response.ok) { + const errorBody = await response.json(); + throw new Error( + `Error setting tag from tracking server, status: ${response.status}. ${errorBody.message}` + ); + } + + // console.log(`Set tag to experiment ID ${experiment_id} successfully`); + return `Set tag to experiment ID ${experiment_id} successfully`; } // test **************************************************************************************************************************************** const testSetExperimentTag = async () => { const log = await getExperiment('691149904576236192'); console.log(log); - console.log(log.experiment.tags); + console.log(log.tags); const log2 = await setExperimentTag( '691149904576236192', 'test_tag', - 'test_value_LIVE_DEMO' + 'test_value_TEST' ); console.log(log2); const log3 = await getExperiment('691149904576236192'); console.log(log3); - console.log(log3.experiment.tags); + console.log(log3.tags); }; // uncomment below --- // testSetExperimentTag(); diff --git a/mlflow/src/tracking_server/tempCodeRunnerFile.js b/mlflow/src/tracking_server/tempCodeRunnerFile.js deleted file mode 100644 index 56bf65d0..00000000 --- a/mlflow/src/tracking_server/tempCodeRunnerFile.js +++ /dev/null @@ -1,2 +0,0 @@ - - // console.log('data.runs: ', data.runs); \ No newline at end of file From 75226e25077da45ecf745d9d26b76611ef8947aa Mon Sep 17 00:00:00 2001 From: Stephany Ho Date: Thu, 29 Aug 2024 09:04:58 -0400 Subject: [PATCH 029/357] Added logMetric, logBatch, logModel, logInputs to Run Management --- mlflow/src/tracking_server/run_management.js | 235 +++++++++++++------ 1 file changed, 160 insertions(+), 75 deletions(-) diff --git a/mlflow/src/tracking_server/run_management.js b/mlflow/src/tracking_server/run_management.js index e30c60af..bcae797c 100644 --- a/mlflow/src/tracking_server/run_management.js +++ b/mlflow/src/tracking_server/run_management.js @@ -41,7 +41,7 @@ class RunManagement { if (!response.ok) { throw new Error( - `Error creating run: ${data.message || response.statusText}` + `Error in creating run: ${data.message || response.statusText}` ); } @@ -68,12 +68,10 @@ class RunManagement { }); if (!response.ok) { - throw new Error( - `Error deleting run: ${data.message || response.statusText}` - ); + throw new Error(`Error in deleting run: ${response.statusText}`); } - return; + return await response.json(); } /** @@ -96,12 +94,10 @@ class RunManagement { }); if (!response.ok) { - throw new Error( - `Error restoring run: ${data.message || response.statusText}` - ); + throw new Error(`Error in restoring run: ${response.statusText}`); } - return; + return await response.json(); } /** @@ -122,7 +118,7 @@ class RunManagement { if (!response.ok) { throw new Error( - `Error fetching run: ${data.message || response.statusText}` + `Error in fetching run: ${data.message || response.statusText}` ); } @@ -160,7 +156,7 @@ class RunManagement { if (!response.ok) { throw new Error( - `Error creating run: ${data.message || response.statusText}` + `Error in updating run: ${data.message || response.statusText}` ); } @@ -177,7 +173,30 @@ class RunManagement { * @param {number} [step=0] - The step at which to log the metric (optional) * @returns {Promise} - A promise that resolves when the metric is logged */ - async logMetric(run_id, key, value, timestamp, step = 0) {} + + // wait for getMetricHistory!!!! + async logMetric(run_id, key, value, timestamp = Date.now(), step = 0) { + if (!run_id || !key || !value) { + throw new Error('Run ID, key, value, timestamp are required.'); + } + + const url = `${this.trackingUri}/api/2.0/mlflow/runs/log-metric`; + + const body = { run_id, key, value, timestamp }; + if (step) body.step = step; + + const response = await fetch(url, { + method: 'POST', + headers: { 'Content-Type': 'application/json' }, + body: JSON.stringify(body), + }); + + if (!response.ok) { + throw new Error(`Error in logging metric: ${response.statusText}`); + } + + return await response.json(); + } /** * Logs a batch of metrics, params, and tags for a run. @@ -188,16 +207,59 @@ class RunManagement { * @param {Array<{key: string, value: string}>} [tags=[]] - The tags to log (up to 100 tags) (optional) * @returns {Promise} - A promise that resolves when the logging is complete */ - async logBatch(run_id, metrics = [], params = [], tags = []) {} + async logBatch(run_id, metrics = [], params = [], tags = []) { + if (!run_id) { + throw new Error('Run ID is required.'); + } + + const url = `${this.trackingUri}/api/2.0/mlflow/runs/log-batch`; + + const body = { run_id }; + if (metrics) body.step = metrics; + if (params) body.params = params; + if (tags) body.tags = tags; + + const response = await fetch(url, { + method: 'POST', + headers: { 'Content-Type': 'application/json' }, + body: JSON.stringify(body), + }); + + if (!response.ok) { + const responseBody = await response.text(); + console.error(`Response body: ${responseBody}`); + throw new Error(`Error in logging batch: ${response.statusText}`); + } + + return await response.json(); + } /** * Logs a model. * * @param {string} run_id - The ID of the run to log under (required) - * @param {object} model_json - The MLmodel data in JSON format (required) + * @param {string} model_json - The MLmodel data in JSON format (required) * @returns {Promise} - A promise that resolves when the model is successfully logged */ - async logModel(run_id, model_json) {} + async logModel(run_id, model_json) { + if (!run_id || !model_json) { + throw new Error('Run ID and MLmodel file are required.'); + } + + const url = `${this.trackingUri}/api/2.0/mlflow/runs/log-model`; + + const response = await fetch(url, { + method: 'POST', + headers: { 'Content-Type': 'application/json' }, + body: JSON.stringify({ run_id, model_json }), + }); + + if (!response.ok) { + throw new Error(`Error in logging model: ${response.statusText}`); + } + + return await response.json(); + } /** * Logs inputs. @@ -206,10 +268,29 @@ class RunManagement { * @param {Array} datasets - The dataset inputs in JSON format (required) * @returns {Promise} - A promise that resolves when the logging is complete */ - async logInputs(run_id, datasets) {} + + async logInputs(run_id, datasets) { + if (!run_id || !datasets) { + throw new Error('Run ID and datasets are required.'); + } + + const url = `${this.trackingUri}/api/2.0/mlflow/runs/log-inputs`; + + const response = await fetch(url, { + method: 'POST', + headers: { 'Content-Type': 'application/json' }, + body: JSON.stringify({ run_id, datasets }), + }); + + if (!response.ok) { + throw new Error(`Error in logging inputs: ${response.statusText}`); + } + + return await response.json(); + } /** - * + * * @param {string} run_id - ID of the run which to log the tag. Required * @param {string} key - Name of the tag. Maximum size depends on storage backend. All storage backends * are guaranteed to support key values up to 250 bytes in size. Required @@ -217,129 +298,117 @@ class RunManagement { * backend. All storage backends are guaranteed to support key values up to 5000 bytes in size. Required * @returns {Promise} - Empty promise object */ - async deleteTag (run_id, key) { + async deleteTag(run_id, key) { if (!run_id) { - throw new Error("run_id is required"); + throw new Error('run_id is required'); } else if (!key) { - throw new Error("key is required"); + throw new Error('key is required'); } const url = `${this.trackingUri}/runs/delete-tag`; const response = await fetch(url, { - method: "POST", + method: 'POST', headers: { - "Content-Type": "application/json", + 'Content-Type': 'application/json', }, - body: JSON.stringify({ run_id, key}), + body: JSON.stringify({ run_id, key }), }); // data is an empty object const data = await response.json(); if (!response.ok) { - throw new Error( - `Error logging param: ${ - response.statusText - }` - ); + throw new Error(`Error logging param: ${response.statusText}`); } return data; } /** - * + * * @param {string} run_id - ID of the run under which to log the param. Required * @param {string} key - Name of the param. Maximum size is 255 bytes. Required * @param {string} value - String value of the param being logged. Maximum size is 6000 bytes. Required * @returns {Promise} - Empty promise object * Note: A param can be logged only once for a run */ - async logParam (run_id, key, value) { + async logParam(run_id, key, value) { if (!run_id) { - throw new Error("run_id is required"); + throw new Error('run_id is required'); } else if (!key) { - throw new Error("key is required"); + throw new Error('key is required'); } else if (!value) { - throw new Error("value is required"); + throw new Error('value is required'); } const url = `${this.trackingUri}/runs/log-parameter`; const response = await fetch(url, { - method: "POST", + method: 'POST', headers: { - "Content-Type": "application/json", + 'Content-Type': 'application/json', }, body: JSON.stringify({ run_id, key, value }), }); const data = await response.json(); if (!response.ok) { - throw new Error( - `Error logging param: ${ - response.statusText - }` - ); + throw new Error(`Error logging param: ${response.statusText}`); } return data; } /** - * + * * @param {string} run_id - ID of the run from which to fetch metric values. Required * @param {string} metric_key - Name of the metric. Required * @param {string} page_token - Token indicating the page of metric history to fetch * @param {INT32} max_results - Maximum number of logged instances of a metric for a run to return per call. - * Backend servers may restrict the value of max_results depending on performance requirements. Requests that do not - * specify this value will behave as non-paginated queries where all metric history values for a given metric + * Backend servers may restrict the value of max_results depending on performance requirements. Requests that do not + * specify this value will behave as non-paginated queries where all metric history values for a given metric * within a run are returned in a single response. * @returns {Promise} - The values for the specified metric, as a promise object */ async getMetricHistory(run_id, metric_key, page_token, max_results) { if (!run_id) { - throw new Error("run_id is required"); + throw new Error('run_id is required'); } else if (!metric_key) { - throw new Error("metric_key is required"); + throw new Error('metric_key is required'); } const url = `${this.trackingUri}/metrics/get-history?run_id=${run_id}&metric_key=${metric_key}&page_token=${page_token}&max_results=${max_results}`; const response = await fetch(url); /** * data can have the fields: * metrics {An array of Metric} - All logged values for this metric - * next_page_token {string} - Token that can be used to issue a query for the next page of metric history values. A + * next_page_token {string} - Token that can be used to issue a query for the next page of metric history values. A * missing token indicates that no additional metrics are available to fetch. */ const data = await response.json(); @@ -355,33 +424,47 @@ class RunManagement { } /** - * + * * @param {Array<{key: string, value: string}>} experiment_ids - List of experiment IDs to search over. - * @param {string} filter - A filter expression over params, metrics, and tags, that allows returning a subset of runs. + * @param {string} filter - A filter expression over params, metrics, and tags, that allows returning a subset of runs. * The syntax is a subset of SQL that supports ANDing together binary operations between a param, metric, or tag and a constant. * Example: metrics.rmse < 1 and params.model_class = 'LogisticRegression' - * You can select columns with special characters (hyphen, space, period, etc.) by using + * You can select columns with special characters (hyphen, space, period, etc.) by using * double quotes: metrics."model class" = 'LinearRegression' and tags."user-name" = 'Tomas' * Supported operators are =, !=, >, >=, <, and <=. * @param {ViewType} run_view_type - Whether to display only active, only deleted, or all runs. Defaults to active runs. * @param {INT32} max_results - Maximum number of runs desired. If unspecified, defaults to 1000. All servers are * guaranteed to support a max_results theshold of at least 50,000 but may support more. Callers of this endpoint are * encouraged to pass max_results explicitly and leverage page_token to iterate through experiments. - * @param {Array<{key: string, value: string}>} order_by - List of columns to be ordered by, including attributes, params, metrics, - * and tags with an optional "DESC" or "ASC" annotation, where "ASC" is the default. - * Example: ["params.input DESC","metrics.alpha ASC", "metrics.rmse"] Tiebreaks are done by start_time DESC followed by run_id for + * @param {Array<{key: string, value: string}>} order_by - List of columns to be ordered by, including attributes, params, metrics, + * and tags with an optional "DESC" or "ASC" annotation, where "ASC" is the default. + * Example: ["params.input DESC","metrics.alpha ASC", "metrics.rmse"] Tiebreaks are done by start_time DESC followed by run_id for * runs with the same start time (and this is the default ordering criterion if order_by is not provided). - * @param {string} page_token + * @param {string} page_token * @returns {Promise Date: Thu, 29 Aug 2024 09:46:44 -0400 Subject: [PATCH 030/357] Merged with dev and resolved conflicts --- mlflow/package-lock.json | 2 +- mlflow/src/tracking_server/run_management.js | 1 - 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/mlflow/package-lock.json b/mlflow/package-lock.json index 9526dde2..4f1c429b 100644 --- a/mlflow/package-lock.json +++ b/mlflow/package-lock.json @@ -7,7 +7,7 @@ "": { "name": "mlflow", "version": "1.0.0", - "license": "ISC" + "license": "MIT" } } } diff --git a/mlflow/src/tracking_server/run_management.js b/mlflow/src/tracking_server/run_management.js index bcae797c..123cf4e5 100644 --- a/mlflow/src/tracking_server/run_management.js +++ b/mlflow/src/tracking_server/run_management.js @@ -174,7 +174,6 @@ class RunManagement { * @returns {Promise} - A promise that resolves when the metric is logged */ - // wait for getMetricHistory!!!! async logMetric(run_id, key, value, timestamp = Date.now(), step = 0) { if (!run_id || !key || !value) { throw new Error('Run ID, key, value, timestamp are required.'); From e80b8b26420e6648d6ee1e1727c1fd81784d3b70 Mon Sep 17 00:00:00 2001 From: Stephany Ho Date: Fri, 30 Aug 2024 12:51:24 -0400 Subject: [PATCH 031/357] Fixed a bug and added a testing file --- mlflow/src/tracking_server/run_management.js | 2 +- mlflow/src/tracking_server/testing.js | 172 +++++++++++++++++++ 2 files changed, 173 insertions(+), 1 deletion(-) create mode 100644 mlflow/src/tracking_server/testing.js diff --git a/mlflow/src/tracking_server/run_management.js b/mlflow/src/tracking_server/run_management.js index 123cf4e5..ada9d7b1 100644 --- a/mlflow/src/tracking_server/run_management.js +++ b/mlflow/src/tracking_server/run_management.js @@ -214,7 +214,7 @@ class RunManagement { const url = `${this.trackingUri}/api/2.0/mlflow/runs/log-batch`; const body = { run_id }; - if (metrics) body.step = metrics; + if (metrics) body.metrics = metrics; if (params) body.params = params; if (tags) body.tags = tags; diff --git a/mlflow/src/tracking_server/testing.js b/mlflow/src/tracking_server/testing.js new file mode 100644 index 00000000..c3995c17 --- /dev/null +++ b/mlflow/src/tracking_server/testing.js @@ -0,0 +1,172 @@ +import { RunManagement } from './run_management.js'; + +const myRunManagement = new RunManagement('http://127.0.0.1:5000'); + +async function testCreateRun(experiment_id) { + try { + const run = await myRunManagement.createRun(experiment_id); + console.log('Created run:', run); + } catch (error) { + console.error('Error:', error.message); + } +} + +// testCreateRun('415858823387303182'); + +async function testDeleteRun(run_id) { + try { + const run = await myRunManagement.deleteRun(run_id); + console.log(`Run ID ${run_id} deleted`); + } catch (error) { + console.error('Error:', error.message); + } +} + +// testDeleteRun('1d3829715bda4e4eb257f68363dacfa6'); + +async function testRestoreRun(run_id) { + try { + const run = await myRunManagement.restoreRun(run_id); + console.log(`Run ID ${run_id} restored`); + } catch (error) { + console.error('Error:', error.message); + } +} + +// testRestoreRun('1d3829715bda4e4eb257f68363dacfa6'); + +async function testGetRun(run_id) { + try { + const run = await myRunManagement.getRun(run_id); + console.log('Fetched run ID: ', run); + } catch (error) { + console.error('Error:', error.message); + } +} + +// testGetRun('0577e22f02e24d24b62949625306c256'); + +async function testUpdateRun(run_id, status, run_name) { + try { + const updatedRun = await myRunManagement.updateRun( + run_id, + status, + run_name + ); + console.log('Updated run: ', updatedRun); + } catch (error) { + console.error('Error:', error.message); + } +} + +// testUpdateRun( +// '0577e22f02e24d24b62949625306c256', +// 'FINISHED', +// 'victorious-bee-311' +// ); + +async function testLogMetric(run_id, key, value) { + try { + const loggedMetric = await myRunManagement.logMetric(run_id, key, value); + console.log('Metric logged successfully'); + } catch (error) { + console.error('Error: ', error.message); + } +} + +// testLogMetric('69c2298a1a374e989806ea89ab2b892a', 'metric-01', 0.9); + +async function testLogBatch(run_id, metrics, params, tags) { + try { + await myRunManagement.logBatch(run_id, metrics, params, tags); + } catch (error) { + console.error('Error in testLogBatch: ', error); + } +} + +// testLogBatch('521098fe3c6f42ee81fdb82cc1437fef'); +// testLogBatch( +// '0577e22f02e24d24b62949625306c256', +// [ +// { key: 'mae', value: 2.5, timestamp: 1552550804 }, +// { key: 'rmse', value: 2.7, timestamp: 1552550804 }, +// ], +// [{ key: 'model_class', value: 'LogisticRegression' }] +// ); +// testLogBatch( +// '1d3829715bda4e4eb257f68363dacfa6', +// [ +// { key: 'mae', value: 2.2, timestamp: 1552550804 }, +// { key: 'rmse', value: 2.9, timestamp: 1552550804 }, +// ], +// [{ key: 'model_class', value: 'LogisticRegression' }], +// [{ key: 'tag_name', value: 'testing' }] +// ); + +async function testLogModel(run_id, model_json) { + try { + const modelJson = JSON.stringify(model_json); + + await myRunManagement.logModel(run_id, modelJson); + console.log('Model logged successfully.'); + } catch (error) { + console.error('Error: ', error); + } +} + +// testLogModel('69c2298a1a374e989806ea89ab2b892a', { +// artifact_path: 'model', +// flavors: { +// python_function: { +// model_path: 'model.pkl', +// loader_module: 'mlflow.sklearn', +// python_version: '3.8.10', +// }, +// // sklearn: { +// // sklearn_version: '0.19.1', +// // pickled_model: 'model.pkl', +// // }, +// }, +// run_id: '69c2298a1a374e989806ea89ab2b892a', +// utc_time_created: '2024-08-28 12:00:00.000000', +// }); + +async function testLogInputs(run_id, datasets) { + try { + await myRunManagement.logInputs(run_id, datasets); + console.log('Datasets logged successfully.'); + } catch (error) { + console.error('Error logging datasets: ', error.message); + } +} + +// testLogInputs('4a6e21f64d9d4201b157e838501b8d9c', [ +// { +// name: 'wine quality - white', +// source: +// 'https://raw.githubusercontent.com/mlflow/mlflow/master/tests/datasets/winequality-white.csv', +// targets: 'quality', +// schema: { +// columns: [ +// { name: 'fixed acidity', type: 'double' }, +// { name: 'volatile acidity', type: 'double' }, +// { name: 'citric acid', type: 'double' }, +// { name: 'residual sugar', type: 'double' }, +// { name: 'chlorides', type: 'double' }, +// { name: 'free sulfur dioxide', type: 'double' }, +// { name: 'total sulfur dioxide', type: 'double' }, +// { name: 'density', type: 'double' }, +// { name: 'pH', type: 'double' }, +// { name: 'sulphates', type: 'double' }, +// { name: 'alcohol', type: 'double' }, +// { name: 'quality', type: 'long' }, +// ], +// }, +// // profile: { +// // num_rows: rawData.length, +// // num_elements: rawData.length * Object.keys(rawData[0]).length, +// // }, +// }, +// ]); + +// https://mlflow.org/docs/latest/python_api/mlflow.data.html#mlflow.data.dataset.Dataset From ffcd39514dd3efff11d215dae6cd79886f182e0f Mon Sep 17 00:00:00 2001 From: Yiqun Zheng Date: Fri, 30 Aug 2024 11:33:31 -0700 Subject: [PATCH 032/357] added model registry api wrappers --- mlflow/src/model_registry/model_registry.js | 203 ++++++++++++++++++-- 1 file changed, 189 insertions(+), 14 deletions(-) diff --git a/mlflow/src/model_registry/model_registry.js b/mlflow/src/model_registry/model_registry.js index 310fc75d..d3897d61 100644 --- a/mlflow/src/model_registry/model_registry.js +++ b/mlflow/src/model_registry/model_registry.js @@ -13,17 +13,17 @@ class ModelRegistry { * @param {string} [description=''] - Optional description for the model * @returns {Promise} The created registered model object */ - async createRegisteredModel(name, tags = [], description = "") { + async createRegisteredModel(name, tags = [], description = '') { if (!name) { - throw new Error("Model name is required"); + throw new Error('Model name is required'); } const url = `${this.trackingUri}/api/2.0/mlflow/registered-models/create`; const response = await fetch(url, { - method: "POST", + method: 'POST', headers: { - "Content-Type": "application/json", + 'Content-Type': 'application/json', }, body: JSON.stringify({ name, tags, description }), }); @@ -47,18 +47,62 @@ class ModelRegistry { * @returns {Promise} The registered model object */ async getRegisteredModel(name) { - // Implementation similar to createRegisteredModel + if (!name) { + throw new Error('Model name is required'); + } + + const url = `${ + this.trackingUri + }/api/2.0/mlflow/registered-models/get?name=${encodeURIComponent(name)}`; + + const response = await fetch(url); + const data = await response.json(); + + if (!response.ok) { + throw new Error( + `Error getting registered model: ${data.message || response.statusText}` + ); + } + + console.log(data); + console.log(data.registered_model); + return data.registered_model; } /** * Renames a registered model. + * Note: As of MLflow 2.15.1 renaming a model may cause it to lose its tags. + * If maintaining tags is crucial, consider re-applying them after renaming. * * @param {string} name - The current name of the registered model (required) * @param {string} newName - The new name for the registered model (required) * @returns {Promise} The updated registered model object */ async renameRegisteredModel(name, newName) { - // Implementation + if (!name || !newName) { + throw new Error('Both current name and new name are required'); + } + + const url = `${this.trackingUri}/api/2.0/mlflow/registered-models/rename`; + + const response = await fetch(url, { + method: 'POST', + headers: { + 'Content-Type': 'application/json', + }, + body: JSON.stringify({ name, new_name: newName }), + }); + + const data = await response.json(); + + if (!response.ok) { + throw new Error( + `Error renaming registered model: ${ + data.message || response.statusText + }` + ); + } + return data.registered_model; } /** @@ -69,7 +113,30 @@ class ModelRegistry { * @returns {Promise} The updated registered model object */ async updateRegisteredModel(name, description) { - // Implementation + if (!name) { + throw new Error('Model name is required'); + } + + const url = `${this.trackingUri}/api/2.0/mlflow/registered-models/update`; + + const response = await fetch(url, { + method: 'PATCH', + headers: { + 'Content-Type': 'application/json', + }, + body: JSON.stringify({ name, description }), + }); + + const data = await response.json(); + + if (!response.ok) { + throw new Error( + `Error updating registered model: ${ + data.message || response.statusText + }` + ); + } + return data.registered_model; } /** @@ -79,7 +146,28 @@ class ModelRegistry { * @returns {Promise} */ async deleteRegisteredModel(name) { - // Implementation + if (!name) { + throw new Error('Model name is required'); + } + + const url = `${this.trackingUri}/api/2.0/mlflow/registered-models/delete`; + + const response = await fetch(url, { + method: 'DELETE', + headers: { + 'Content-Type': 'application/json', + }, + body: JSON.stringify({ name }), + }); + + if (!response.ok) { + const data = await response.json(); + throw new Error( + `Error deleting registered model: ${ + data.message || response.statusText + }` + ); + } } /** @@ -90,7 +178,30 @@ class ModelRegistry { * @returns {Promise>} The latest model version objects */ async getLatestModelVersions(name, stages = []) { - // Implementation + if (!name) { + throw new Error('Model name is required'); + } + + const url = `${this.trackingUri}/api/2.0/mlflow/registered-models/get-latest-versions`; + + const response = await fetch(url, { + method: 'POST', + headers: { + 'Content-Type': 'application/json', + }, + body: JSON.stringify({ name, stages }), + }); + + const data = await response.json(); + + if (!response.ok) { + throw new Error( + `Error getting latest model versions: ${ + data.message || response.statusText + }` + ); + } + return data.model_versions; } /** @@ -103,7 +214,30 @@ class ModelRegistry { * @returns {Promise} Object containing matching models and next page token */ async searchRegisteredModels(filter, maxResults, orderBy, pageToken) { - // Implementation + const params = new URLSearchParams(); + if (filter) params.append('filter', filter); + if (maxResults) params.append('max_results', maxResults); + if (orderBy) params.append('order_by', orderBy.join(',')); + if (pageToken) params.append('page_token', pageToken); + + const url = `${ + this.trackingUri + }/api/2.0/mlflow/registered-models/search?${params.toString()}`; + + const response = await fetch(url); + const data = await response.json(); + + if (!response.ok) { + throw new Error( + `Error searching registered models: ${ + data.message || response.statusText + }` + ); + } + return { + registeredModels: data.registered_models, + nextPageToken: data.next_page_token, + }; } /** @@ -115,7 +249,28 @@ class ModelRegistry { * @returns {Promise} */ async setRegisteredModelTag(name, key, value) { - // Implementation + if (!name || !key || !value) { + throw new Error('Model name, tag key, and tag value are required'); + } + + const url = `${this.trackingUri}/api/2.0/mlflow/registered-models/set-tag`; + + const response = await fetch(url, { + method: 'POST', + headers: { + 'Content-Type': 'application/json', + }, + body: JSON.stringify({ name, key, value }), + }); + + if (!response.ok) { + const data = await response.json(); + throw new Error( + `Error setting registered model tag: ${ + data.message || response.statusText + }` + ); + } } /** @@ -126,8 +281,28 @@ class ModelRegistry { * @returns {Promise} */ async deleteRegisteredModelTag(name, key) { - // Implementation + if (!name || !key) { + throw new Error('Model name and tag key are required'); + } + + const url = `${this.trackingUri}/api/2.0/mlflow/registered-models/delete-tag`; + + const response = await fetch(url, { + method: 'DELETE', + headers: { + 'Content-Type': 'application/json', + }, + body: JSON.stringify({ name, key }), + }); + + if (!response.ok) { + const data = await response.json(); + throw new Error( + `Error deleting registered model tag: ${ + data.message || response.statusText + }` + ); + } } } - -export { ModelRegistry }; +export { ModelRegistry }; \ No newline at end of file From 04cd5a763b7cc64ec4d4527f13c765e6c3434d8e Mon Sep 17 00:00:00 2001 From: Austin Fraser Date: Sat, 31 Aug 2024 14:02:44 -0700 Subject: [PATCH 033/357] fixed return of createExperiment so that it returns an experiment ID as a string, instead of an object --- mlflow/src/tracking_server/experiment_management.js | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/mlflow/src/tracking_server/experiment_management.js b/mlflow/src/tracking_server/experiment_management.js index d9dadc6b..2ca0a04a 100644 --- a/mlflow/src/tracking_server/experiment_management.js +++ b/mlflow/src/tracking_server/experiment_management.js @@ -30,17 +30,17 @@ async function createExperiment(name, artifact_location = '', tags = []) { } const data = await response.json(); - // console.log('return from createExperiment: ', data); - return data; + // console.log('return from createExperiment: ', data.experiment_id); + return data.experiment_id; } // test **************************************************************************************************************************************** const testCreateExperiment = async () => { - const log = await createExperiment('test_experiment_postman21'); + const log = await createExperiment('test_experiment_postman22'); return console.log(log); }; // uncomment below --- -// testCreateExperiment(); +testCreateExperiment(); /** * Search experiments. From f28bc7e3028c85a27b2aed80e0f188150e570b79 Mon Sep 17 00:00:00 2001 From: Kyler-Chiago Date: Sat, 7 Sep 2024 09:54:02 -0700 Subject: [PATCH 034/357] temp --- mlflow/src/tracking_server/tempCodeRunnerFile.js | 1 + 1 file changed, 1 insertion(+) create mode 100644 mlflow/src/tracking_server/tempCodeRunnerFile.js diff --git a/mlflow/src/tracking_server/tempCodeRunnerFile.js b/mlflow/src/tracking_server/tempCodeRunnerFile.js new file mode 100644 index 00000000..70aac968 --- /dev/null +++ b/mlflow/src/tracking_server/tempCodeRunnerFile.js @@ -0,0 +1 @@ +uns(['7843219421399011 \ No newline at end of file From 14192feedca0a1efcc26ffb3d209fe5fd26c7968 Mon Sep 17 00:00:00 2001 From: winjolu Date: Sat, 7 Sep 2024 15:48:32 -0400 Subject: [PATCH 035/357] build: model version mgmt --- .../model_version_management.js | 462 ++++++++++++++++++ 1 file changed, 462 insertions(+) diff --git a/mlflow/src/model_registry/model_version_management.js b/mlflow/src/model_registry/model_version_management.js index e69de29b..56c8b4bc 100644 --- a/mlflow/src/model_registry/model_version_management.js +++ b/mlflow/src/model_registry/model_version_management.js @@ -0,0 +1,462 @@ +const trackingUri = "http://localhost:5001"; // MLflow server port +class ModelVersionManagement { + constructor(trackingUri) { + this.trackingUri = trackingUri; + console.log(`trackingUri: ${this.trackingUri}`); + } + + /** + * creates a new version of a registered model + * + * @param {string} modelName - the name of the registered model (required) + * @param {string} source - the source path where the model artifacts are stored (required) + * @param {string} [runId=null] - the id of the run that generated this version (optional) + * @returns {Promise} - the created model version object + */ + async createModelVersion(modelName, source, runId = null) { + // is model name provided? + if (!modelName) { + throw new Error('modelName is required'); + } + + // is source provided? + if (!source) { + throw new Error('source is required'); + } + + // construct url for create model version endpoint + const url = `${this.trackingUri}/api/2.0/mlflow/model-versions/create`; + + // build the request body with required and optional fields + const body = { + name: modelName, + source: source, + run_id: runId + }; + + // fire off a post request to create the model version + const response = await fetch(url, { + method: 'POST', + headers: { + 'Content-Type': 'application/json' + }, + body: JSON.stringify(body) + }); + + // parse the response + const data = await response.json(); + + // is response ok? else throw error + if (!response.ok) { + throw new Error(`Error creating model version: ${data.message || response.statusText}`); + } + + // return the model version obj + return data.model_version; + } + + /** + * fetches details of a specific model version. + * + * @param {string} modelName - the name of the registered model (required) + * @param {string} version - the version number of the model to fetch (required) + * @returns {Promise} - the fetched model version object + */ + async getModelVersion(modelName, version) { + // is model name provided? + if (!modelName) { + throw new Error('modelName is required'); + } + + // is version provided? + if (!version) { + throw new Error('version is required'); + } + + // construct url for get model version endpoint + const url = `${this.trackingUri}/api/2.0/mlflow/model-versions/get`; + + // build request query params + const params = new URLSearchParams({ + name: modelName, + version: version + }); + + // fire off a get request to fetch the model version + const response = await fetch(`${url}?${params}`, { + method: 'GET', + headers: { + 'Content-Type': 'application/json' + }, + }); + + // parse the response + const data = await response.json(); + + // is response ok? else throw error + if (!response.ok) { + throw new Error(`Error fetching model version: ${data.message || response.statusText}`); + } + + // return the model version obj + return data.model_version; + } + + /** + * updates a specific model version. + * + * @param {string} modelName - the name of the registered model (required) + * @param {string} version - the version number of the model to update (required) + * @param {Object} updates - the fields to update in the model version (required) + * @returns {Promise} - the updated model version object + */ + async updateModelVersion(modelName, version, updates) { + // is model name provided? + if (!modelName) { + throw new Error('modelName is required'); + } + + // is version provided? + if (!version) { + throw new Error('version is required'); + } + + // are updates provided? is obj? + if (!updates || typeof updates !== 'object') { + throw new Error('updates object is required'); + } + + // construct url for update model version endpoint + const url = `${this.trackingUri}/api/2.0/mlflow/model-versions/update`; + + // build the request body with update fields + const body = { + name: modelName, + version: version, + ...updates // spread updates into body + }; + + // fire off a patch request to update the model version + const response = await fetch(url, { + method: 'PATCH', + headers: { + 'Content-Type': 'application/json' + }, + body: JSON.stringify(body) + }); + + // parse the response + const data = await response.json(); + + // is response ok? else throw error + if (!response.ok) { + throw new Error(`Error updating model version: ${data.message || response.statusText}`); + } + + // return the updated model version obj + return data.model_version; + } + + /** + * deletes a specific model version. + * + * @param {string} modelName - the name of the registered model (required) + * @param {string} version - the version number of the model to delete (required) + * @returns {Promise} - a promise that resolves when the model version is deleted + */ + async deleteModelVersion(modelName, version) { + // is model name provided? + if (!modelName) { + throw new Error('modelName is required'); + } + // is version provided? + if (!version) { + throw new Error('version is required'); + } + + // construct url for delete model version endpoint + const url = `${this.trackingUri}/api/2.0/mlflow/model-versions/delete`; + + // build request query params + const params = new URLSearchParams({ + name: modelName, + version: version + }); + + // fire off a delete request to remove the model version + const response = await fetch(`${url}?${params}`, { + method: 'DELETE', + headers: { + 'Content-Type': 'application/json' + }, + }); + + // parse the response + const data = await response.json(); + + // is response ok? else throw error + if (!response.ok) { + throw new Error(`Error deleting model version: ${data.message || response.statusText}`); + } + + // return nothing, just resolve + return; + } + + /** + * searches for model versions based on provided filters. + * + * @param {string} [filter=''] - the filter criteria for searching model versions (optional) + * @param {number} [maxResults=100] - the maximum number of results to return (optional) + * @returns {Promise} - an array of model versions that match the search criteria + */ + async searchModelVersions(filter = '', maxResults = 100) { + // construct url for search model versions endpoint + const url = `${this.trackingUri}/api/2.0/mlflow/model-versions/search`; + + // build request query params with filter and maxResults + const params = new URLSearchParams({ + filter: filter, + max_results: maxResults + }); + + // fire off a get request to search for model versions + const response = await fetch(`${url}?${params}`, { + method: 'GET', + headers: { + 'Content-Type': 'application/json' + }, + }); + + // parse the response + const data = await response.json(); + + // is response ok? else throw error + if (!response.ok) { + throw new Error(`Error searching model versions: ${data.message || response.statusText}`); + } + + // return an array of model versions that match the criteria + return data.model_versions; + } + + /** + * retrieves the download uri for model version artifacts. + * + * @param {string} modelName - the name of the registered model (required) + * @param {string} version - the version number of the model to fetch the uri for (required) + * @returns {Promise} - the uri for downloading the model version artifacts + */ + async getDownloadUriForModelVersionArtifacts(modelName, version) { + // is model name provided? + if (!modelName) { + throw new Error('modelName is required'); + } + + // is version provided? + if (!version) { + throw new Error('version is required'); + } + + // construct url for get download uri for model version artifacts endpoint + const url = `${this.trackingUri}/api/2.0/mlflow/model-versions/get-download-uri`; + + // build request query params + const params = new URLSearchParams({ + name: modelName, + version: version + }); + + // fire off a get request to fetch the download uri + const response = await fetch(`${url}?${params}`, { + method: 'GET', + headers: { + 'Content-Type': 'application/json' + }, + }); + + // parse the response + const data = await response.json(); + + // is response ok? else throw error + if (!response.ok) { + throw new Error(`Error fetching download uri: ${data.message || response.statusText}`); + } + + // return the download uri as a string + return data.artifact_uri; + } + + /** + * transitions a model version to a different stage. + * + * @param {string} modelName - the name of the registered model (required) + * @param {string} version - the version number of the model to transition (required) + * @param {string} stage - the stage to transition the model version to (e.g., 'staging', 'production') (required) + * @returns {Promise} - the updated model version object after the stage transition + */ + async transitionModelVersionStage(modelName, version, stage) { + // is model name provided? + if (!modelName) { + throw new Error('modelName is required'); + } + + // is version provided? + if (!version) { + throw new Error('version is required'); + } + + // is stage provided? + if (!stage) { + throw new Error('stage is required'); + } + + // construct url for transition model version stage endpoint + const url = `${this.trackingUri}/api/2.0/mlflow/model-versions/transition-stage`; + + // build the request body with stage information + const body = { + name: modelName, + version: version, + stage: stage + }; + + // fire off a post request to transition the model version stage + const response = await fetch(url, { + method: 'POST', + headers: { + 'Content-Type': 'application/json' + }, + body: JSON.stringify(body) + }); + + // parse the response + const data = await response.json(); + + // is response ok? else throw error + if (!response.ok) { + throw new Error(`Error transitioning model version stage: ${data.message || response.statusText}`); + } + + // return the updated model version obj + return data.model_version; + } + + /** + * sets a tag on a specific model version. + * + * @param {string} modelName - the name of the registered model (required) + * @param {string} version - the version number of the model to tag (required) + * @param {string} key - the key of the tag (required) + * @param {string} value - the value of the tag (required) + * @returns {Promise} - a promise that resolves when the tag is set + */ + async setModelVersionTag(modelName, version, key, value) { + // is model name provided? + if (!modelName) { + throw new Error('modelName is required'); + } + + // is version provided? + if (!version) { + throw new Error('version is required'); + } + + // is key provided? + if (!key) { + throw new Error('key is required'); + } + + // is value provided? + if (!value) { + throw new Error('value is required'); + } + + // construct url for set model version tag endpoint + const url = `${this.trackingUri}/api/2.0/mlflow/model-versions/set-tag`; + + // build the request body with tag key and value + const body = { + name: modelName, + version: version, + key: key, + value: value + }; + + // fire off a post request to set the tag on the model version + const response = await fetch(url, { + method: 'POST', + headers: { + 'Content-Type': 'application/json' + }, + body: JSON.stringify(body) + }); + + // parse the response + const data = await response.json(); + + // is response ok? else throw error + if (!response.ok) { + throw new Error(`Error setting model version tag: ${data.message || response.statusText}`); + } + + // return nothing, just resolve + return; + } + + /** + * deletes a tag from a specific model version. + * + * @param {string} modelName - the name of the registered model (required) + * @param {string} version - the version number of the model to untag (required) + * @param {string} key - the key of the tag to delete (required) + * @returns {Promise} - a promise that resolves when the tag is deleted + */ + async deleteModelVersionTag(modelName, version, key) { + // is model name provided? + if (!modelName) { + throw new Error('modelName is required'); + } + + // is version provided? + if (!version) { + throw new Error('version is required'); + } + + // is key provided? + if (!key) { + throw new Error('key is required'); + } + + // construct url for delete model version tag endpoint + const url = `${this.trackingUri}/api/2.0/mlflow/model-versions/delete-tag`; + + // build request query params + const params = new URLSearchParams({ + name: modelName, + version: version, + key: key + }); + + // fire off a delete request to remove the tag from the model version + const response = await fetch(`${url}?${params}`, { + method: 'DELETE', + headers: { + 'Content-Type': 'application/json' + }, + }); + + // parse the response + const data = await response.json(); + + // is response ok? else throw error + if (!response.ok) { + throw new Error(`Error deleting model version tag: ${data.message || response.statusText}`); + } + + // return nothing, just resolve + return; + } +} + +export { ModelVersionManagement }; \ No newline at end of file From b1bcfdef5d7b3378e02011fc38a868648a3842f7 Mon Sep 17 00:00:00 2001 From: Yiqun Zheng Date: Sat, 7 Sep 2024 13:42:02 -0700 Subject: [PATCH 036/357] update .gitignore, added apiClient.js, refactored modelRegistry --- mlflow/.gitignore | 10 +++++- mlflow/src/model_registry/model_registry.js | 25 ++++++-------- mlflow/src/utils/apiClient.js | 38 +++++++++++++++++++++ 3 files changed, 57 insertions(+), 16 deletions(-) create mode 100644 mlflow/src/utils/apiClient.js diff --git a/mlflow/.gitignore b/mlflow/.gitignore index b512c09d..00b26ccf 100644 --- a/mlflow/.gitignore +++ b/mlflow/.gitignore @@ -1 +1,9 @@ -node_modules \ No newline at end of file +# Dependencies +node_modules/ + +# Misc +.DS_Store + +# Python / MLflow specific +.venv/ +mlruns/ \ No newline at end of file diff --git a/mlflow/src/model_registry/model_registry.js b/mlflow/src/model_registry/model_registry.js index d3897d61..0d81ae1d 100644 --- a/mlflow/src/model_registry/model_registry.js +++ b/mlflow/src/model_registry/model_registry.js @@ -1,4 +1,5 @@ //model_registry.js +import apiRequest from '../utils/apiClient.js'; class ModelRegistry { constructor(trackingUri) { @@ -12,23 +13,17 @@ class ModelRegistry { * @param {Array<{key: string, value: string}>} [tags=[]] - Optional tags for the model * @param {string} [description=''] - Optional description for the model * @returns {Promise} The created registered model object + * @throws {Error} - If the API request fails */ async createRegisteredModel(name, tags = [], description = '') { - if (!name) { - throw new Error('Model name is required'); - } - - const url = `${this.trackingUri}/api/2.0/mlflow/registered-models/create`; - - const response = await fetch(url, { - method: 'POST', - headers: { - 'Content-Type': 'application/json', - }, - body: JSON.stringify({ name, tags, description }), - }); - - const data = await response.json(); + const { response, data } = await apiRequest( + this.trackingUri, + 'registered-models/create', + { + method: 'POST', + body: { name, tags, description }, + } + ); if (!response.ok) { throw new Error( diff --git a/mlflow/src/utils/apiClient.js b/mlflow/src/utils/apiClient.js new file mode 100644 index 00000000..6d2acc04 --- /dev/null +++ b/mlflow/src/utils/apiClient.js @@ -0,0 +1,38 @@ +/** + * Utility function for making API requests to the MLflow server. + * + * @param {string} baseUrl - The base URL of the MLflow server + * @param {string} endpoint - The API endpoint + * @param {Object} options - Request options + * @param {string} options.method - HTTP method (GET, POST, PUT, PATCH, DELETE) + * @param {Object} [options.body] - Request body for POST, PUT, PATCH requests + * @param {Object} [options.params] - URL parameters + * @returns {Promise} - The response and data + */ +async function apiRequest(baseUrl, endpoint, options) { + let url = `${baseUrl}/api/2.0/mlflow/${endpoint}`; + const { method, body, params } = options; + + const fetchOptions = { + method, + headers: { + 'Content-Type': 'application/json', + }, + }; + + if (body) { + fetchOptions.body = JSON.stringify(body); + } + + if (params) { + const searchParams = new URLSearchParams(params); + url += `?${searchParams.toString()}`; + } + + const response = await fetch(url, fetchOptions); + const data = await response.json(); + + return { response, data }; +} + +export default apiRequest; From 40bc223602e073a808d1a8e6b3d268cca189b907 Mon Sep 17 00:00:00 2001 From: Stephany Ho Date: Sun, 8 Sep 2024 23:48:12 -0400 Subject: [PATCH 037/357] Add runComparison abstraction method --- .../abstraction/abstraction_run_management.js | 114 ++++++++++++++++++ 1 file changed, 114 insertions(+) create mode 100644 mlflow/src/abstraction/abstraction_run_management.js diff --git a/mlflow/src/abstraction/abstraction_run_management.js b/mlflow/src/abstraction/abstraction_run_management.js new file mode 100644 index 00000000..936c7d84 --- /dev/null +++ b/mlflow/src/abstraction/abstraction_run_management.js @@ -0,0 +1,114 @@ +import { RunManagement } from '../tracking_server/run_management.js'; + +class Abstraction { + constructor(trackingUri, path) { + this.trackingUri = trackingUri; + this.path = path; + this.RunManagement = new RunManagement(this.trackingUri, this.path); + } + + /** + * Compare runs within an experiment, return a structured comparison. + * + * @param {string} experimentId - The ID of the associated experiment. (required) + * @param {string} [filterString=''] - A filter expression over params, metrics, and tags, that allows returning a subset of runs. The syntax is a subset of SQL that supportts ANDing together binary operations between a param, metric, or tag and a constant. (optional) + * @param {Object<{key: string, value: number, mode: string}>} [criteria={}] - Specify one criteria for selecting the best run. Specify mode to be one of the following: exact, maximize, minimize, or range. (required) + * @returns {Promise} - The created output object. + */ + async runComparison(experimentId, filterString = '', criteria = {}) { + // convert the experimentId into an array for the searchRuns method + const experimentIdArray = [experimentId]; + const runsResponse = await this.RunManagement.searchRuns( + experimentIdArray, + filterString + ); + + const runs = runsResponse.runs; + + // extract and compare the specified criteria across runs + try { + const runSummary = await this._findBestRunByCriteria(runs, criteria); + console.log('runSummary: ', runSummary); + // console.log('Run Summary: ', JSON.stringify(runSummary, null, 2)); + return runSummary; + } catch (error) { + console.error(`Error in generating summary: ${error}`); + } + } + + async _findBestRunByCriteria(runs, criteria) { + // destructure criteria and initiate the runSummary object + const { key, value, mode } = criteria; + const runSummary = { + criteria: criteria, + valid_runs: [], + selection_criteria: { metric_key: key, mode: mode }, + message: '', + }; + + const createRunObject = (run) => ({ + run_id: run.info.run_id, + metrics: run.data.metrics || [], + params: run.data.params || {}, + tags: run.data.tags || {}, + }); + + for (const run of runs) { + // console.log(`Analyzing run: ${run.info.run_id}`); + // console.log(`Run metrics: ${JSON.stringify(run.data.metrics)}`); + + const metricObject = run.data.metrics.find((m) => m.key === key); + if (!metricObject) continue; + + const metricValue = metricObject.value; + + switch (mode) { + case 'exact': + // convert both to numbers for comparison + if (Number(metricValue) === Number(value)) { + return { + criteria: criteria, + best_run: createRunObject(run), + selection_criteria: { metric_key: key, mode: mode }, + message: 'Exact match found.', + }; + } + break; + case 'range': + const [minValue, maxValue] = value.map(Number); + if (metricValue >= minValue && metricValue <= maxValue) { + runSummary.valid_runs.push(createRunObject(run)); + } + break; + case 'minimize': + case 'maximize': + runSummary.valid_runs.push(createRunObject(run)); + break; + default: + throw new Error(`Unsupported mode: ${mode}`); + } + } + + // sort the valid_runs according to mode, extract best_run + // only minimize and maximize mode will show best_run + if (runSummary.valid_runs.length > 0) { + if (mode === 'minimize' || mode === 'maximize') { + runSummary.valid_runs.sort((a, b) => { + const aValue = a.metrics.find((m) => m.key === key).value; + const bValue = b.metrics.find((m) => m.key === key).value; + return mode === 'maximize' ? bValue - aValue : aValue - bValue; + }); + runSummary.best_run = runSummary.valid_runs[0]; + runSummary.message = `Found ${runSummary.valid_runs.length} runs. Best run selected.`; + } else if (mode === 'range') { + runSummary.message = `Found ${runSummary.valid_runs.length} runs within the specified range.`; + } + } else { + runSummary.message = 'No matching runs found.'; + } + + return runSummary; + } +} + +export { Abstraction }; From 61a81cc02a41fdd276c5d49e4d20897df63390b5 Mon Sep 17 00:00:00 2001 From: Austin Fraser Date: Sun, 8 Sep 2024 23:56:01 -0700 Subject: [PATCH 038/357] withStartExperimentRunByExperimentId --- .../tracking_server/experiment_management.js | 65 ++++++- mlflow/src/tracking_server/testing_AF.js | 171 ++++++++++++++++++ 2 files changed, 235 insertions(+), 1 deletion(-) create mode 100644 mlflow/src/tracking_server/testing_AF.js diff --git a/mlflow/src/tracking_server/experiment_management.js b/mlflow/src/tracking_server/experiment_management.js index 2ca0a04a..cf1b284d 100644 --- a/mlflow/src/tracking_server/experiment_management.js +++ b/mlflow/src/tracking_server/experiment_management.js @@ -1,4 +1,7 @@ const MLFLOW_TRACKING_URI = 'http://localhost:5001/api/2.0/mlflow'; +import { RunManagement } from "./run_management.js"; +const path = 'artifacts'; +const runManagement = new RunManagement("http://localhost:5001", path); /** * Create an experiment with a name. Returns the ID of the newly created experiment. @@ -40,7 +43,7 @@ const testCreateExperiment = async () => { return console.log(log); }; // uncomment below --- -testCreateExperiment(); +// testCreateExperiment(); /** * Search experiments. @@ -370,3 +373,63 @@ const testSetExperimentTag = async () => { }; // uncomment below --- // testSetExperimentTag(); + + + + + + +async function withStartExperimentRunByExperimentId(experiment_id, run_name = null, metrics = [], params = [], tags = [], model_json) { + // create run + const run = await runManagement.createRun(experiment_id, run_name, tags); + const runId = run.info.run_id; + + // log metric, params, and tags via logBatch + await runManagement.logBatch(runId, metrics, params, tags); + + // log model + let modelParsed = JSON.parse(model_json); + modelParsed.run_id = runId; + let modelJson = JSON.stringify(modelParsed); + await runManagement.logModel(runId, modelJson); + + // updateRun to finish it + const latestRun = await runManagement.updateRun(runId, 'FINISHED'); + + return latestRun; +} + +const testWithStartExperimentRunByExperimentId = async () => { + const metrics = [ + {key: 'metric1', value: .111, timestamp: Date.now()}, + {key: 'metric2', value: .222, timestamp: Date.now()}, + ]; + const params = [ + {key: 'testParam', value: 'testParamValue'}, + {key: 'testParam2', value: 'testParamValue2'} + ]; + const tags = [ + {key: 'testKey', value: 'testValue'}, + {key: 'testKey2', value: 'testValue2'} + ]; + const model = { + artifact_path: 'model', + flavors: { + python_function: { + model_path: 'model.pkl', + loader_module: 'mlflow.sklearn', + python_version: '3.8.10', + }, + }, + model_url: 'STRING', + model_uuid: 'STRING', + // run_id: runId, + utc_time_created: Date.now(), + mlflow_version: 'STRING' + }; + const modelJson = JSON.stringify(model); + const log = await withStartExperimentRunByExperimentId('977566317259111173', 'testRunName6', metrics, params, tags, modelJson); + return console.log(log); +}; + +// testWithStartExperimentRunByExperimentId(); \ No newline at end of file diff --git a/mlflow/src/tracking_server/testing_AF.js b/mlflow/src/tracking_server/testing_AF.js new file mode 100644 index 00000000..ea4198cb --- /dev/null +++ b/mlflow/src/tracking_server/testing_AF.js @@ -0,0 +1,171 @@ +import { RunManagement } from './run_management.js'; + +const myRunManagement = new RunManagement('http://localhost:5001'); + +async function testCreateRun(experiment_id) { + try { + const run = await myRunManagement.createRun(experiment_id); + console.log('Created run:', run); + } catch (error) { + console.error('Error:', error.message); + } +} + +// testCreateRun('977566317259111173'); + +async function testDeleteRun(run_id) { + try { + const run = await myRunManagement.deleteRun(run_id); + console.log(`Run ID ${run_id} deleted`); + } catch (error) { + console.error('Error:', error.message); + } +} + +// testDeleteRun('1d3829715bda4e4eb257f68363dacfa6'); + +async function testRestoreRun(run_id) { + try { + const run = await myRunManagement.restoreRun(run_id); + console.log(`Run ID ${run_id} restored`); + } catch (error) { + console.error('Error:', error.message); + } +} + +// testRestoreRun('1d3829715bda4e4eb257f68363dacfa6'); + +async function testGetRun(run_id) { + try { + const run = await myRunManagement.getRun(run_id); + console.log('Fetched run ID: ', run); + } catch (error) { + console.error('Error:', error.message); + } +} + +// testGetRun('0577e22f02e24d24b62949625306c256'); + +async function testUpdateRun(run_id, status, run_name) { + try { + const updatedRun = await myRunManagement.updateRun( + run_id, + status, + run_name + ); + console.log('Updated run: ', updatedRun); + } catch (error) { + console.error('Error:', error.message); + } +} + +// testUpdateRun( +// '0577e22f02e24d24b62949625306c256', +// 'FINISHED', +// 'victorious-bee-311' +// ); + +async function testLogMetric(run_id, key, value) { + try { + const loggedMetric = await myRunManagement.logMetric(run_id, key, value); + console.log('Metric logged successfully'); + } catch (error) { + console.error('Error: ', error.message); + } +} + +// testLogMetric('69c2298a1a374e989806ea89ab2b892a', 'metric-01', 0.9); + +async function testLogBatch(run_id, metrics, params, tags) { + try { + await myRunManagement.logBatch(run_id, metrics, params, tags); + } catch (error) { + console.error('Error in testLogBatch: ', error); + } +} + +// testLogBatch('521098fe3c6f42ee81fdb82cc1437fef'); +// testLogBatch( +// '0577e22f02e24d24b62949625306c256', +// [ +// { key: 'mae', value: 2.5, timestamp: 1552550804 }, +// { key: 'rmse', value: 2.7, timestamp: 1552550804 }, +// ], +// [{ key: 'model_class', value: 'LogisticRegression' }] +// ); +// testLogBatch( +// '1d3829715bda4e4eb257f68363dacfa6', +// [ +// { key: 'mae', value: 2.2, timestamp: 1552550804 }, +// { key: 'rmse', value: 2.9, timestamp: 1552550804 }, +// ], +// [{ key: 'model_class', value: 'LogisticRegression' }], +// [{ key: 'tag_name', value: 'testing' }] +// ); + +async function testLogModel(run_id, model_json) { + try { + const modelJson = JSON.stringify(model_json); + + await myRunManagement.logModel(run_id, modelJson); + console.log('Model logged successfully.'); + } catch (error) { + console.error('Error: ', error); + } +} + +// testLogModel('026e2e2e56b049e1bbea18cac27df99a', { +// artifact_path: 'model', +// flavors: { +// python_function: { +// model_path: 'model.pkl', +// loader_module: 'mlflow.sklearn', +// python_version: '3.8.10', +// }, +// // sklearn: { +// // sklearn_version: '0.19.1', +// // pickled_model: 'model.pkl', +// // }, +// }, +// utc_time_created: '2024-08-28 12:00:00.000000', +// }); + +async function testLogInputs(run_id, datasets) { + try { + await myRunManagement.logInputs(run_id, datasets); + console.log('Datasets logged successfully.'); + } catch (error) { + console.error('Error logging datasets: ', error.message); + } +} + +// testLogInputs('4a6e21f64d9d4201b157e838501b8d9c', [ +// { +// name: 'wine quality - white', +// source: +// 'https://raw.githubusercontent.com/mlflow/mlflow/master/tests/datasets/winequality-white.csv', +// targets: 'quality', +// schema: { +// columns: [ +// { name: 'fixed acidity', type: 'double' }, +// { name: 'volatile acidity', type: 'double' }, +// { name: 'citric acid', type: 'double' }, +// { name: 'residual sugar', type: 'double' }, +// { name: 'chlorides', type: 'double' }, +// { name: 'free sulfur dioxide', type: 'double' }, +// { name: 'total sulfur dioxide', type: 'double' }, +// { name: 'density', type: 'double' }, +// { name: 'pH', type: 'double' }, +// { name: 'sulphates', type: 'double' }, +// { name: 'alcohol', type: 'double' }, +// { name: 'quality', type: 'long' }, +// ], +// }, +// // profile: { +// // num_rows: rawData.length, +// // num_elements: rawData.length * Object.keys(rawData[0]).length, +// // }, +// }, +// ]); + +// https://mlflow.org/docs/latest/python_api/mlflow.data.html#mlflow.data.dataset.Dataset From 8dad9d3e4ccee116a819c902f9f27a1b6d586599 Mon Sep 17 00:00:00 2001 From: Austin Fraser Date: Mon, 9 Sep 2024 00:00:42 -0700 Subject: [PATCH 039/357] small fix to testWithStartExperimentRunByExperimentId --- mlflow/src/tracking_server/experiment_management.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mlflow/src/tracking_server/experiment_management.js b/mlflow/src/tracking_server/experiment_management.js index cf1b284d..8918ea30 100644 --- a/mlflow/src/tracking_server/experiment_management.js +++ b/mlflow/src/tracking_server/experiment_management.js @@ -428,7 +428,7 @@ const testWithStartExperimentRunByExperimentId = async () => { mlflow_version: 'STRING' }; const modelJson = JSON.stringify(model); - const log = await withStartExperimentRunByExperimentId('977566317259111173', 'testRunName6', metrics, params, tags, modelJson); + const log = await withStartExperimentRunByExperimentId('977566317259111173', undefined, metrics, params, tags, modelJson); return console.log(log); }; From ed4ae974926913b87f73081e1efbc7f7ebdb16c2 Mon Sep 17 00:00:00 2001 From: Austin Fraser Date: Mon, 9 Sep 2024 00:16:09 -0700 Subject: [PATCH 040/357] fixed withStartExperimentRunByExperimentId so that it expects model as an object, not JSON --- mlflow/src/tracking_server/experiment_management.js | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) diff --git a/mlflow/src/tracking_server/experiment_management.js b/mlflow/src/tracking_server/experiment_management.js index 8918ea30..ff38b07b 100644 --- a/mlflow/src/tracking_server/experiment_management.js +++ b/mlflow/src/tracking_server/experiment_management.js @@ -379,7 +379,7 @@ const testSetExperimentTag = async () => { -async function withStartExperimentRunByExperimentId(experiment_id, run_name = null, metrics = [], params = [], tags = [], model_json) { +async function withStartExperimentRunByExperimentId(experiment_id, run_name = null, metrics = [], params = [], tags = [], model) { // create run const run = await runManagement.createRun(experiment_id, run_name, tags); const runId = run.info.run_id; @@ -388,9 +388,9 @@ async function withStartExperimentRunByExperimentId(experiment_id, run_name = nu await runManagement.logBatch(runId, metrics, params, tags); // log model - let modelParsed = JSON.parse(model_json); - modelParsed.run_id = runId; - let modelJson = JSON.stringify(modelParsed); + // (model gets passed in as a JS object, not JSON - it gets JSON stringified here after adding a run_id property) + model.run_id = runId; + let modelJson = JSON.stringify(model); await runManagement.logModel(runId, modelJson); // updateRun to finish it @@ -427,9 +427,8 @@ const testWithStartExperimentRunByExperimentId = async () => { utc_time_created: Date.now(), mlflow_version: 'STRING' }; - const modelJson = JSON.stringify(model); - const log = await withStartExperimentRunByExperimentId('977566317259111173', undefined, metrics, params, tags, modelJson); + const log = await withStartExperimentRunByExperimentId('977566317259111173', undefined, metrics, params, tags, model); return console.log(log); }; -// testWithStartExperimentRunByExperimentId(); \ No newline at end of file +testWithStartExperimentRunByExperimentId(); \ No newline at end of file From 1bd4ef11adf92d414f6f607a493a04d36dffc456 Mon Sep 17 00:00:00 2001 From: Austin Fraser Date: Mon, 9 Sep 2024 10:01:25 -0700 Subject: [PATCH 041/357] withStartExperimentRunByExperimentName --- .../tracking_server/experiment_management.js | 109 +++++++++++++++++- 1 file changed, 105 insertions(+), 4 deletions(-) diff --git a/mlflow/src/tracking_server/experiment_management.js b/mlflow/src/tracking_server/experiment_management.js index ff38b07b..acf4ff18 100644 --- a/mlflow/src/tracking_server/experiment_management.js +++ b/mlflow/src/tracking_server/experiment_management.js @@ -39,7 +39,7 @@ async function createExperiment(name, artifact_location = '', tags = []) { // test **************************************************************************************************************************************** const testCreateExperiment = async () => { - const log = await createExperiment('test_experiment_postman22'); + const log = await createExperiment('test_experiment_postman24'); return console.log(log); }; // uncomment below --- @@ -378,8 +378,26 @@ const testSetExperimentTag = async () => { - +/** + * Full workflow of creating, naming and starting a run under an experiment (referenced by ID), + * logging metrics, params, and tags, logging the model, and finishing the run. + * + * @param {string} experiment_id ID of the experiment under which to log the run. (required) + * @param {string} run_name Name of the run to be created and run (optional) + * @param {Array<{key: string, value: number, timestamp: number, step?: number}>} [metrics] The metrics to log (up to 1000 metrics) (optional) + * @param {Array<{key: string, value: string}>} [params] The params to log (up to 100 params) (optional) + * @param {Array<{key: string, value: string}>} [tags=[]] The tags to log (up to 100 tags) (optional) + * @param {Object} model The ML model data to log to the run, represented as a Javascript object (required) + * @returns {Promise} The created run object with updated metadata + */ async function withStartExperimentRunByExperimentId(experiment_id, run_name = null, metrics = [], params = [], tags = [], model) { + if (!experiment_id) { + throw new Error('Experiment ID is required'); + } + if (!model) { + throw new Error('Model is required'); + } + // create run const run = await runManagement.createRun(experiment_id, run_name, tags); const runId = run.info.run_id; @@ -399,6 +417,7 @@ async function withStartExperimentRunByExperimentId(experiment_id, run_name = nu return latestRun; } +// test **************************************************************************************************************************************** const testWithStartExperimentRunByExperimentId = async () => { const metrics = [ {key: 'metric1', value: .111, timestamp: Date.now()}, @@ -423,12 +442,94 @@ const testWithStartExperimentRunByExperimentId = async () => { }, model_url: 'STRING', model_uuid: 'STRING', - // run_id: runId, utc_time_created: Date.now(), mlflow_version: 'STRING' }; const log = await withStartExperimentRunByExperimentId('977566317259111173', undefined, metrics, params, tags, model); return console.log(log); }; +// uncomment below --- +// testWithStartExperimentRunByExperimentId(); + + + +/** + * Full workflow of creating, naming and starting a run under an experiment (referenced by name), + * logging metrics, params, and tags, logging the model, and finishing the run. + * + * @param {string} experiment_name Name of the experiment under which to log the run. (required) + * @param {string} run_name Name of the run to be created and run (optional) + * @param {Array<{key: string, value: number, timestamp: number, step?: number}>} [metrics] The metrics to log (up to 1000 metrics) (optional) + * @param {Array<{key: string, value: string}>} [params] The params to log (up to 100 params) (optional) + * @param {Array<{key: string, value: string}>} [tags=[]] The tags to log (up to 100 tags) (optional) + * @param {Object} model The ML model data to log to the run, represented as a Javascript object (required) + * @returns {Promise} The created run object with updated metadata + */ +async function withStartExperimentRunByExperimentName(experiment_name, run_name = null, metrics = [], params = [], tags = [], model) { + if (!experiment_name) { + throw new Error('Experiment name is required'); + } + if (!model) { + throw new Error('Model is required'); + } + + let experiment_id; + try { + const exp = await getExperimentByName(experiment_name); + experiment_id = exp.experiment_id; + } catch { + experiment_id = await createExperiment(experiment_name); + } + + // create run + const run = await runManagement.createRun(experiment_id, run_name, tags); + const runId = run.info.run_id; + + // log metric, params, and tags via logBatch + await runManagement.logBatch(runId, metrics, params, tags); + + // log model + // (model gets passed in as a JS object, not JSON - it gets JSON stringified here after adding a run_id property) + model.run_id = runId; + let modelJson = JSON.stringify(model); + await runManagement.logModel(runId, modelJson); + + // updateRun to finish it + const latestRun = await runManagement.updateRun(runId, 'FINISHED'); + + return latestRun; +} -testWithStartExperimentRunByExperimentId(); \ No newline at end of file +// test **************************************************************************************************************************************** +const testWithStartExperimentRunByExperimentName = async () => { + const metrics = [ + {key: 'metric1', value: .111, timestamp: Date.now()}, + {key: 'metric2', value: .222, timestamp: Date.now()}, + ]; + const params = [ + {key: 'testParam', value: 'testParamValue'}, + {key: 'testParam2', value: 'testParamValue2'} + ]; + const tags = [ + {key: 'testKey', value: 'testValue'}, + {key: 'testKey2', value: 'testValue2'} + ]; + const model = { + artifact_path: 'model', + flavors: { + python_function: { + model_path: 'model.pkl', + loader_module: 'mlflow.sklearn', + python_version: '3.8.10', + }, + }, + model_url: 'STRING', + model_uuid: 'STRING', + utc_time_created: Date.now(), + mlflow_version: 'STRING' + }; + const log = await withStartExperimentRunByExperimentName('High level abstraction test', undefined, metrics, params, tags, model); + return console.log(log); +}; +// uncomment below --- +// testWithStartExperimentRunByExperimentName(); \ No newline at end of file From 5786d218622731e56f9833ef3673f8fbb8f477ad Mon Sep 17 00:00:00 2001 From: Stephany Ho Date: Mon, 9 Sep 2024 23:05:23 -0400 Subject: [PATCH 042/357] Revert "Add runComparison abstraction method" This reverts commit 40bc223602e073a808d1a8e6b3d268cca189b907. --- .../abstraction/abstraction_run_management.js | 114 ------------------ 1 file changed, 114 deletions(-) delete mode 100644 mlflow/src/abstraction/abstraction_run_management.js diff --git a/mlflow/src/abstraction/abstraction_run_management.js b/mlflow/src/abstraction/abstraction_run_management.js deleted file mode 100644 index 936c7d84..00000000 --- a/mlflow/src/abstraction/abstraction_run_management.js +++ /dev/null @@ -1,114 +0,0 @@ -import { RunManagement } from '../tracking_server/run_management.js'; - -class Abstraction { - constructor(trackingUri, path) { - this.trackingUri = trackingUri; - this.path = path; - this.RunManagement = new RunManagement(this.trackingUri, this.path); - } - - /** - * Compare runs within an experiment, return a structured comparison. - * - * @param {string} experimentId - The ID of the associated experiment. (required) - * @param {string} [filterString=''] - A filter expression over params, metrics, and tags, that allows returning a subset of runs. The syntax is a subset of SQL that supportts ANDing together binary operations between a param, metric, or tag and a constant. (optional) - * @param {Object<{key: string, value: number, mode: string}>} [criteria={}] - Specify one criteria for selecting the best run. Specify mode to be one of the following: exact, maximize, minimize, or range. (required) - * @returns {Promise} - The created output object. - */ - async runComparison(experimentId, filterString = '', criteria = {}) { - // convert the experimentId into an array for the searchRuns method - const experimentIdArray = [experimentId]; - const runsResponse = await this.RunManagement.searchRuns( - experimentIdArray, - filterString - ); - - const runs = runsResponse.runs; - - // extract and compare the specified criteria across runs - try { - const runSummary = await this._findBestRunByCriteria(runs, criteria); - console.log('runSummary: ', runSummary); - // console.log('Run Summary: ', JSON.stringify(runSummary, null, 2)); - return runSummary; - } catch (error) { - console.error(`Error in generating summary: ${error}`); - } - } - - async _findBestRunByCriteria(runs, criteria) { - // destructure criteria and initiate the runSummary object - const { key, value, mode } = criteria; - const runSummary = { - criteria: criteria, - valid_runs: [], - selection_criteria: { metric_key: key, mode: mode }, - message: '', - }; - - const createRunObject = (run) => ({ - run_id: run.info.run_id, - metrics: run.data.metrics || [], - params: run.data.params || {}, - tags: run.data.tags || {}, - }); - - for (const run of runs) { - // console.log(`Analyzing run: ${run.info.run_id}`); - // console.log(`Run metrics: ${JSON.stringify(run.data.metrics)}`); - - const metricObject = run.data.metrics.find((m) => m.key === key); - if (!metricObject) continue; - - const metricValue = metricObject.value; - - switch (mode) { - case 'exact': - // convert both to numbers for comparison - if (Number(metricValue) === Number(value)) { - return { - criteria: criteria, - best_run: createRunObject(run), - selection_criteria: { metric_key: key, mode: mode }, - message: 'Exact match found.', - }; - } - break; - case 'range': - const [minValue, maxValue] = value.map(Number); - if (metricValue >= minValue && metricValue <= maxValue) { - runSummary.valid_runs.push(createRunObject(run)); - } - break; - case 'minimize': - case 'maximize': - runSummary.valid_runs.push(createRunObject(run)); - break; - default: - throw new Error(`Unsupported mode: ${mode}`); - } - } - - // sort the valid_runs according to mode, extract best_run - // only minimize and maximize mode will show best_run - if (runSummary.valid_runs.length > 0) { - if (mode === 'minimize' || mode === 'maximize') { - runSummary.valid_runs.sort((a, b) => { - const aValue = a.metrics.find((m) => m.key === key).value; - const bValue = b.metrics.find((m) => m.key === key).value; - return mode === 'maximize' ? bValue - aValue : aValue - bValue; - }); - runSummary.best_run = runSummary.valid_runs[0]; - runSummary.message = `Found ${runSummary.valid_runs.length} runs. Best run selected.`; - } else if (mode === 'range') { - runSummary.message = `Found ${runSummary.valid_runs.length} runs within the specified range.`; - } - } else { - runSummary.message = 'No matching runs found.'; - } - - return runSummary; - } -} - -export { Abstraction }; From 8029c041be52a91eddd32d54aa076af562cabfc4 Mon Sep 17 00:00:00 2001 From: Kyler-Chiago Date: Mon, 9 Sep 2024 20:20:03 -0700 Subject: [PATCH 043/357] 4 files --- mlflow/src/model_registry/model_registry.js | 23 +-- .../model_version_management.js | 34 ++-- mlflow/src/tracking_server/run_management.js | 15 +- mlflow/src/workflows/ModelManager.js | 183 ++++++++++++++++++ 4 files changed, 208 insertions(+), 47 deletions(-) create mode 100644 mlflow/src/workflows/ModelManager.js diff --git a/mlflow/src/model_registry/model_registry.js b/mlflow/src/model_registry/model_registry.js index 7db5106a..47c0ef0b 100644 --- a/mlflow/src/model_registry/model_registry.js +++ b/mlflow/src/model_registry/model_registry.js @@ -1,15 +1,5 @@ //model_registry.js -let domain = 'http://localhost:' -const port = 5001; -if (port) { - domain = domain + port; -} - -const version = '2.0'; - -const MLFLOW_TRACKING_URI = domain + '/api/' + version + '/mlflow'; - class ModelRegistry { constructor(trackingUri) { this.trackingUri = trackingUri; @@ -19,7 +9,8 @@ class ModelRegistry { * Creates a new registered model. * * @param {string} name - The name of the model to register (required) - * @param {Array<{key: string, value: string}>} [tags=[]] - Optional tags for the model + * @param {Array<{key: string, value: string}>} [tags=[]] - Optional tags for the model. + * Must be formatted like: [{"key": "keyName", "value": "valueName"}] * @param {string} [description=''] - Optional description for the model * @returns {Promise} The created registered model object */ @@ -74,8 +65,6 @@ class ModelRegistry { ); } - console.log(data); - console.log(data.registered_model); return data.registered_model; } @@ -332,7 +321,7 @@ class ModelRegistry { throw new Error("version is required"); } - const url = `${this.trackingUri}/registered-models/alias`; + const url = `${this.trackingUri}/api/2.0/mlflow/registered-models/alias`; const response = await fetch(url, { method: "POST", headers: { @@ -347,7 +336,7 @@ class ModelRegistry { if (!response.ok) { throw new Error( `Error setting model alias: ${ - response.statusText + data.message || response.statusText }` ); } @@ -368,7 +357,7 @@ class ModelRegistry { throw new Error("alias is required"); } - const url = `${this.trackingUri}/registered-models/alias`; + const url = `${this.trackingUri}/api/2.0/mlflow/registered-models/alias`; const response = await fetch(url, { method: "DELETE", headers: { @@ -403,7 +392,7 @@ class ModelRegistry { } else if (!alias) { throw new Error("alias is required"); } - const url = `${this.trackingUri}/registered-models/alias`; + const url = `${this.trackingUri}/api/2.0/mlflow/registered-models/alias`; const response = await fetch(`${url}?name=${name}&alias=${alias}`); /** diff --git a/mlflow/src/model_registry/model_version_management.js b/mlflow/src/model_registry/model_version_management.js index 56c8b4bc..bde5cc60 100644 --- a/mlflow/src/model_registry/model_version_management.js +++ b/mlflow/src/model_registry/model_version_management.js @@ -1,8 +1,6 @@ -const trackingUri = "http://localhost:5001"; // MLflow server port class ModelVersionManagement { constructor(trackingUri) { this.trackingUri = trackingUri; - console.log(`trackingUri: ${this.trackingUri}`); } /** @@ -107,10 +105,10 @@ class ModelVersionManagement { * * @param {string} modelName - the name of the registered model (required) * @param {string} version - the version number of the model to update (required) - * @param {Object} updates - the fields to update in the model version (required) + * @param {string} description - * @returns {Promise} - the updated model version object */ - async updateModelVersion(modelName, version, updates) { + async updateModelVersion(modelName, version, description) { // is model name provided? if (!modelName) { throw new Error('modelName is required'); @@ -122,9 +120,9 @@ class ModelVersionManagement { } // are updates provided? is obj? - if (!updates || typeof updates !== 'object') { - throw new Error('updates object is required'); - } + // if (!updates || typeof updates !== 'object') { + // throw new Error('updates object is required'); + // } // construct url for update model version endpoint const url = `${this.trackingUri}/api/2.0/mlflow/model-versions/update`; @@ -133,7 +131,7 @@ class ModelVersionManagement { const body = { name: modelName, version: version, - ...updates // spread updates into body + description }; // fire off a patch request to update the model version @@ -177,18 +175,13 @@ class ModelVersionManagement { // construct url for delete model version endpoint const url = `${this.trackingUri}/api/2.0/mlflow/model-versions/delete`; - // build request query params - const params = new URLSearchParams({ - name: modelName, - version: version - }); - // fire off a delete request to remove the model version - const response = await fetch(`${url}?${params}`, { + const response = await fetch(url, { method: 'DELETE', headers: { 'Content-Type': 'application/json' }, + body: JSON.stringify({ name: modelName, version }) }); // parse the response @@ -221,12 +214,8 @@ class ModelVersionManagement { }); // fire off a get request to search for model versions - const response = await fetch(`${url}?${params}`, { - method: 'GET', - headers: { - 'Content-Type': 'application/json' - }, - }); + const response = await fetch(`${url}?${params}` + ); // parse the response const data = await response.json(); @@ -439,11 +428,12 @@ class ModelVersionManagement { }); // fire off a delete request to remove the tag from the model version - const response = await fetch(`${url}?${params}`, { + const response = await fetch(url, { method: 'DELETE', headers: { 'Content-Type': 'application/json' }, + body: JSON.stringify({name: modelName, version, key}), }); // parse the response diff --git a/mlflow/src/tracking_server/run_management.js b/mlflow/src/tracking_server/run_management.js index ada9d7b1..6bbb0204 100644 --- a/mlflow/src/tracking_server/run_management.js +++ b/mlflow/src/tracking_server/run_management.js @@ -1,7 +1,6 @@ class RunManagement { - constructor(trackingUri, path) { + constructor(trackingUri) { this.trackingUri = trackingUri; - this.path = path; } /** @@ -305,7 +304,7 @@ class RunManagement { } else if (!value) { throw new Error('value is required'); } - const url = `${this.trackingUri}/runs/set-tag`; + const url = `${this.trackingUri}/api/2.0/mlflow/runs/set-tag`; const response = await fetch(url, { method: 'POST', headers: { @@ -335,7 +334,7 @@ class RunManagement { } else if (!key) { throw new Error('key is required'); } - const url = `${this.trackingUri}/runs/delete-tag`; + const url = `${this.trackingUri}/api/2.0/mlflow/runs/delete-tag`; const response = await fetch(url, { method: 'POST', headers: { @@ -369,7 +368,7 @@ class RunManagement { } else if (!value) { throw new Error('value is required'); } - const url = `${this.trackingUri}/runs/log-parameter`; + const url = `${this.trackingUri}/api/2.0/mlflow/runs/log-parameter`; const response = await fetch(url, { method: 'POST', headers: { @@ -402,7 +401,7 @@ class RunManagement { } else if (!metric_key) { throw new Error('metric_key is required'); } - const url = `${this.trackingUri}/metrics/get-history?run_id=${run_id}&metric_key=${metric_key}&page_token=${page_token}&max_results=${max_results}`; + const url = `${this.trackingUri}/api/2.0/mlflow/metrics/get-history?run_id=${run_id}&metric_key=${metric_key}&page_token=${page_token}&max_results=${max_results}`; const response = await fetch(url); /** * data can have the fields: @@ -450,7 +449,7 @@ class RunManagement { order_by, page_token ) { - const url = `${this.trackingUri}/runs/search`; + const url = `${this.trackingUri}/api/2.0/mlflow/runs/search`; const response = await fetch(url, { method: 'POST', headers: { @@ -495,7 +494,7 @@ class RunManagement { throw new Error('run_id is required'); } const response = await fetch( - `${this.trackingUri}/${this.path}/list?run_id=${run_id}&run_uuid=${run_id}&path=${artifact_path}&page_token=${page_token}` + `${this.trackingUri}/api/2.0/mlflow/artifacts/list?run_id=${run_id}&run_uuid=${run_id}&path=${artifact_path}&page_token=${page_token}` ); /** * data can have the fields: diff --git a/mlflow/src/workflows/ModelManager.js b/mlflow/src/workflows/ModelManager.js new file mode 100644 index 00000000..51999fde --- /dev/null +++ b/mlflow/src/workflows/ModelManager.js @@ -0,0 +1,183 @@ +import { ModelRegistry } from '../model_registry/model_registry.js'; +import { ModelVersionManagement } from '../model_registry/model_version_management.js'; + +class ModelManager { + constructor(trackingUri) { + this.trackingUri = trackingUri; + this.modelRegistry = new ModelRegistry(trackingUri); + this.modelVersionManagement = new ModelVersionManagement(trackingUri); + } + + /** + * Description - Creates a new registered model and creates the first version of that model. + * @param {string} name - Name of the registered model. (Required) + * @param {string} versionSource - URI indicating the location of the model artifacts. (Required) + * @param {string} versionRun_id - MLflow run ID for correlation, if versionSource was generated + * by an experiment run in MLflow tracking server. + * @returns {Promise} - the updated model version object + */ + async createRegisteredModelWithVersion(name, versionSource, versionRun_id) { + await this.modelRegistry.createRegisteredModel(name); + const response = await this.modelVersionManagement.createModelVersion( + name, + versionSource, + versionRun_id + ); + return response; + } + + /** + * Description - Updates a registered model's description and tag. + * @param {string} name - Name of the registered model. (Required) + * @param {string} tagKey - Name of the tag. (Required) + * @param {string} tagValue - String value of the tag being logged. (Required) + * @param {string} description - Description of the registered model. + * @returns {Promise} - the updated registered model object + */ + async updateRegisteredModelDescriptionAndTag( + name, + tagKey, + tagValue, + description + ) { + await this.modelRegistry.setRegisteredModelTag(name, tagKey, tagValue); + const response = await this.modelRegistry.updateRegisteredModel( + name, + description + ); + return response; + } + + /** + * Description - Updates the latest version of the specified registered model's description. + * And adds a new alias, and tag key/value for that latest version. + * @param {string} name - Name of the registered model. (Required) + * @param {string} alias - Name of the alias. (Required) + * @param {string} description - The description for the model version. (Required) + * @param {string} key - Name of the tag. (Required) + * @param {string} value - Name of the value of the tag being logged. (Required) + * @returns {Promise} - the updated model version object + */ + async updateAllLatestModelVersion(name, alias, description, key, value) { + const data = await this.modelRegistry.getLatestModelVersions(name); + if (!data) { + throw new Error('Model has no version to update.'); + } else { + const [{ version }] = data; + await this.modelRegistry.setRegisteredModelAlias(name, alias, version); + await this.modelVersionManagement.setModelVersionTag( + name, + version, + key, + value + ); + const response = await this.modelVersionManagement.updateModelVersion( + name, + version, + description + ); + return response; + } + } + + /** + * Description - Adds a new tag key/value for the latest version of the specified registered model. + * @param {string} name - Name of the registered model. (Required) + * @param {string} key - Name of the tag. (Required) + * @param {string} value - Name of the value of the tag being logged. (Required) + * @returns {Promise} - a promise that resolves when the model version is deleted + */ + async setLatestModelVersionTag(name, key, value) { + const data = await this.modelRegistry.getLatestModelVersions(name); + if (!data) { + throw new Error('Model has no version to set tag for.'); + } else { + const [{ version }] = data; + this.modelVersionManagement.setModelVersionTag(name, version, key, value); + return; + } + } + + /** + * Description - Adds an alias for the latest version of the specified registered model. + * @param {string} name - Name of the registered model. (Required) + * @param {string} alias - Name of the alias. (Required) + * @returns {Promise} - a promise that resolves when the model version is deleted + */ + async setLatestModelVersionAlias(name, alias) { + const data = await this.modelRegistry.getLatestModelVersions(name); + if (!data) { + throw new Error('Model has no version to set alias for.'); + } else { + const [{ version }] = data; + this.modelRegistry.setRegisteredModelAlias(name, alias, version); + return; + } + } + + /** + * Description - Updates the description of the latest version of a registered model. + * @param {string} name - Name of the registered model. (Required) + * @param {string} description - The description for the model version. (Required) + * @returns {Promise} - the updated model version object + */ + async updateLatestModelVersion(name, description) { + const data = await this.modelRegistry.getLatestModelVersions(name); + if (!data) { + throw new Error('Model has no version to set description for.'); + } else { + const [{ version }] = data; + const response = await this.modelVersionManagement.updateModelVersion( + name, + version, + description + ); + return response; + } + } + + /** + * Description - Updates the specified version of the specified registered model's description. + * And adds a new alias, and tag key/value for that specified version. + * @param {string} name - Name of the registered model. (Required) + * @param {string} version - Model version number. (Required) + * @param {string} alias - Name of the alias. (Required) + * @param {string} description - The description for the model version. (Required) + * @param {string} key key - Name of the tag. (Required) + * @param {string} value - Name of the value of the tag being logged. (Required) + * @returns {Promise} - the updated model version object + */ + async updateAllModelVersion(name, version, alias, description, key, value) { + await this.modelRegistry.setRegisteredModelAlias(name, alias, version); + await this.modelVersionManagement.setModelVersionTag( + name, + version, + key, + value + ); + const response = await this.modelVersionManagement.updateModelVersion( + name, + version, + description + ); + return response; + } + + /** + * Description - Deletes the latest version of the specified registered model. + * @param {string} name - the model name + * @returns {Promise} - a promise that resolves when the model version is deleted + */ + async deleteLatestModelVersion(name) { + const data = await this.modelRegistry.getLatestModelVersions(name); + if (!data) { + throw new Error('Model has no version to delete.'); + } else { + const [{ version }] = data; + this.modelVersionManagement.deleteModelVersion(name, version); + return; + } + } +} + +export { ModelManager }; From f5c2c2457fe5bce7f69debbea07872318df457b6 Mon Sep 17 00:00:00 2001 From: Stephany Ho Date: Mon, 9 Sep 2024 23:21:54 -0400 Subject: [PATCH 044/357] Resolve conflicts and modified a file --- mlflow/src/tracking_server/run_management.js | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/mlflow/src/tracking_server/run_management.js b/mlflow/src/tracking_server/run_management.js index ada9d7b1..1c617eb6 100644 --- a/mlflow/src/tracking_server/run_management.js +++ b/mlflow/src/tracking_server/run_management.js @@ -201,8 +201,8 @@ class RunManagement { * Logs a batch of metrics, params, and tags for a run. * * @param {string} run_id - The ID of the run to log under (required) - * @param {Array<{key: string, value: number, timestamp: number, step?: number}>} [metrics] - The metrics to log (up to 1000 metrics) (optional) - * @param {Array<{key: string, value: string}>} [params] - The params to log (up to 100 params) (optional) + * @param {Array<{key: string, value: number, timestamp: number, step?: number}>} [metrics=[]] - The metrics to log (up to 1000 metrics) (optional) + * @param {Array<{key: string, value: string}>} [params=[]] - The params to log (up to 100 params) (optional) * @param {Array<{key: string, value: string}>} [tags=[]] - The tags to log (up to 100 tags) (optional) * @returns {Promise} - A promise that resolves when the logging is complete */ @@ -450,7 +450,7 @@ class RunManagement { order_by, page_token ) { - const url = `${this.trackingUri}/runs/search`; + const url = `${this.trackingUri}/api/2.0/mlflow/runs/search`; const response = await fetch(url, { method: 'POST', headers: { From 7f6e69e02e473e99f1f818739ded17a67d25aa77 Mon Sep 17 00:00:00 2001 From: Kyler-Chiago Date: Mon, 9 Sep 2024 20:22:41 -0700 Subject: [PATCH 045/357] 4 files real --- mlflow/src/tracking_server/tempCodeRunnerFile.js | 1 - 1 file changed, 1 deletion(-) delete mode 100644 mlflow/src/tracking_server/tempCodeRunnerFile.js diff --git a/mlflow/src/tracking_server/tempCodeRunnerFile.js b/mlflow/src/tracking_server/tempCodeRunnerFile.js deleted file mode 100644 index 70aac968..00000000 --- a/mlflow/src/tracking_server/tempCodeRunnerFile.js +++ /dev/null @@ -1 +0,0 @@ -uns(['7843219421399011 \ No newline at end of file From 2b3d7690d7e66c74f9f456d617d621e6cc1c735f Mon Sep 17 00:00:00 2001 From: Stephany Ho Date: Tue, 10 Sep 2024 13:20:02 -0400 Subject: [PATCH 046/357] Add runCleanup abstraction method --- .../abstraction/abstraction_run_management.js | 71 +++++++++++++++++++ mlflow/src/abstraction/testing.js | 36 ++++++++++ mlflow/src/tracking_server/run_management.js | 24 +++++-- 3 files changed, 126 insertions(+), 5 deletions(-) create mode 100644 mlflow/src/abstraction/abstraction_run_management.js create mode 100644 mlflow/src/abstraction/testing.js diff --git a/mlflow/src/abstraction/abstraction_run_management.js b/mlflow/src/abstraction/abstraction_run_management.js new file mode 100644 index 00000000..b02da4c1 --- /dev/null +++ b/mlflow/src/abstraction/abstraction_run_management.js @@ -0,0 +1,71 @@ +import { RunManagement } from '../tracking_server/run_management.js'; + +class Abstraction { + constructor(trackingUri) { + this.trackingUri = trackingUri; + this.RunManagement = new RunManagement(this.trackingUri); + } + + /** + * Delete runs that do not meet certain criteria and return the deleted runs. + * + * @param {string[]} experimentIds - The IDs of the associated experiments. (required) + * @param {string} queryString - SQL-like query string to filter runs to keep. (required) + * @param {boolean} [dryRun=true] - If true, only simulate the deletion. Defaults to true. (optional) + * @returns {Promise} - An object of deleted runs. + */ + async runCleanup(experimentIds, queryString, dryRun = true) { + const deletedRuns = []; + let pageToken = null; + const maxResults = 1000; + + try { + do { + // get all runs + const searchResult = await this.RunManagement.searchRuns( + experimentIds, + '', + null, // run_view_type + maxResults, + ['start_time DESC'], + pageToken + ); + + // get runs that match the keep crteria + const keepResult = await this.RunManagement.searchRuns( + experimentIds, + queryString, + null, // run_view_type + maxResults, + ['start_time DESC'], + pageToken + ); + + // create a Set of run IDs to keep for efficient lookup + const keepRunIds = new Set( + keepResult.runs.map((run) => run.info.run_id) + ); + + // check for runs that are not in keepRunIds + // if dryRun is false, delete from database, push to deletedRuns array + // if dryRun is true, push to deletedRuns array + for (const run of searchResult.runs || []) { + if (!keepRunIds.has(run.info.run_id)) { + if (!dryRun) { + await this.RunManagement.deleteRun(run.info.run_id); + } + deletedRuns.push(run); + } + } + + pageToken = searchResult.page_token; + } while (pageToken); + } catch (error) { + console.error('Error during run cleanup: ', error); + throw new Error('Failed to cleanup runs.'); + } + return { deletedRuns, total: deletedRuns.length, dryRun }; + } +} + +export { Abstraction }; diff --git a/mlflow/src/abstraction/testing.js b/mlflow/src/abstraction/testing.js new file mode 100644 index 00000000..68c447e8 --- /dev/null +++ b/mlflow/src/abstraction/testing.js @@ -0,0 +1,36 @@ +import { Abstraction } from './abstraction_run_management.js'; +import { RunManagement } from '../tracking_server/run_management.js'; + +const trackingUri = 'http://127.0.0.1:5000'; +const path = '/api/2.0/mlflow'; + +// const ab = new Abstraction(trackingUri, path); +const ab = new Abstraction(trackingUri); +const myRunManagement = new RunManagement(trackingUri); + +// // testing searchRuns method +// const runs = await myRunManagement.searchRuns(['463611670721534538'], ''); +// console.log('Search runs result: ', runs); + +// // dry run (simulation) +// try { +// const result = await ab.runCleanup( +// ['463611670721534538'], +// 'metrics.rmse > 2' +// ); +// console.log(result.deletedRuns); +// } catch (error) { +// console.error('Error: ', error.message, error.stack); +// } + +// // delete runs +// try { +// const result = await ab.runCleanup( +// ['463611670721534538'], +// 'metrics.mae > 2', +// true +// ); +// console.log(result); +// } catch (error) { +// console.error('Error: ', error.message, error.stack); +// } diff --git a/mlflow/src/tracking_server/run_management.js b/mlflow/src/tracking_server/run_management.js index 1c617eb6..e48c7f3c 100644 --- a/mlflow/src/tracking_server/run_management.js +++ b/mlflow/src/tracking_server/run_management.js @@ -471,16 +471,30 @@ class RunManagement { * next_page_token {string} - Token that can be used to retrieve the next page of run results. A missing token indicates * that there are no additional run results to be fetched. */ - const data = await response.json(); + // const data = await response.json(); + // if (!response.ok) { + // throw new Error( + // `Error finding run that satisfies expressions: ${ + // data.message || response.statusText + // }` + // ); + // } + + const textResponse = await response.text(); // Read as text first if (!response.ok) { throw new Error( - `Error finding run that satisfies expressions: ${ - data.message || response.statusText - }` + `Error finding run that satisfies expressions: ${textResponse}` ); } - return data; + try { + const data = JSON.parse(textResponse); // Parse text as JSON + return data; + } catch (e) { + throw new Error(`Failed to parse JSON: ${e.message}`); + } + + // return data; } /** From 16029192cd5e855f6a2a57f2b8132d566aa37fec Mon Sep 17 00:00:00 2001 From: Austin Fraser Date: Tue, 10 Sep 2024 16:04:07 -0700 Subject: [PATCH 047/357] experimentSummary --- .../tracking_server/experiment_management.js | 53 +++++++++++++------ mlflow/src/tracking_server/run_management.js | 2 +- 2 files changed, 38 insertions(+), 17 deletions(-) diff --git a/mlflow/src/tracking_server/experiment_management.js b/mlflow/src/tracking_server/experiment_management.js index acf4ff18..c4470f64 100644 --- a/mlflow/src/tracking_server/experiment_management.js +++ b/mlflow/src/tracking_server/experiment_management.js @@ -400,19 +400,19 @@ async function withStartExperimentRunByExperimentId(experiment_id, run_name = nu // create run const run = await runManagement.createRun(experiment_id, run_name, tags); - const runId = run.info.run_id; + const run_id = run.info.run_id; // log metric, params, and tags via logBatch - await runManagement.logBatch(runId, metrics, params, tags); + await runManagement.logBatch(run_id, metrics, params, tags); // log model // (model gets passed in as a JS object, not JSON - it gets JSON stringified here after adding a run_id property) - model.run_id = runId; - let modelJson = JSON.stringify(model); - await runManagement.logModel(runId, modelJson); + model.run_id = run_id; + let model_json = JSON.stringify(model); + await runManagement.logModel(run_id, model_json); // updateRun to finish it - const latestRun = await runManagement.updateRun(runId, 'FINISHED'); + const latestRun = await runManagement.updateRun(run_id, 'FINISHED'); return latestRun; } @@ -483,27 +483,27 @@ async function withStartExperimentRunByExperimentName(experiment_name, run_name // create run const run = await runManagement.createRun(experiment_id, run_name, tags); - const runId = run.info.run_id; + const run_id = run.info.run_id; // log metric, params, and tags via logBatch - await runManagement.logBatch(runId, metrics, params, tags); + await runManagement.logBatch(run_id, metrics, params, tags); // log model // (model gets passed in as a JS object, not JSON - it gets JSON stringified here after adding a run_id property) - model.run_id = runId; - let modelJson = JSON.stringify(model); - await runManagement.logModel(runId, modelJson); + model.run_id = run_id; + let model_json = JSON.stringify(model); + await runManagement.logModel(run_id, model_json); // updateRun to finish it - const latestRun = await runManagement.updateRun(runId, 'FINISHED'); + const latest_run = await runManagement.updateRun(run_id, 'FINISHED'); - return latestRun; + return latest_run; } // test **************************************************************************************************************************************** const testWithStartExperimentRunByExperimentName = async () => { const metrics = [ - {key: 'metric1', value: .111, timestamp: Date.now()}, + {key: 'metric1', value: .9, timestamp: Date.now()}, {key: 'metric2', value: .222, timestamp: Date.now()}, ]; const params = [ @@ -528,8 +528,29 @@ const testWithStartExperimentRunByExperimentName = async () => { utc_time_created: Date.now(), mlflow_version: 'STRING' }; - const log = await withStartExperimentRunByExperimentName('High level abstraction test', undefined, metrics, params, tags, model); + const log = await withStartExperimentRunByExperimentName('experimentSummary test', undefined, metrics, params, tags, model); + return console.log(log); +}; +// uncomment below --- +// testWithStartExperimentRunByExperimentName(); + + + +async function experimentSummary(experiment_id, primaryMetric, order) { + // use Search Runs to return all runs whose experiment ID matches the passed in one + // use Search Runs's order_by field to sort results array by primaryMetric + let orderString; + if (order === 1 || order === 'DESC') orderString = 'DESC' + else if (order === -1 || order === 'ASC') orderString = 'ASC'; + const arg = `metrics.${primaryMetric} ${orderString}`; + const data = await runManagement.searchRuns([experiment_id], undefined, undefined, undefined, [arg]); + return data.runs +}; + +// test **************************************************************************************************************************************** +const testExperimentSummary = async () => { + const log = await experimentSummary('787867007534323476', 'metric1', 'DESC'); return console.log(log); }; // uncomment below --- -// testWithStartExperimentRunByExperimentName(); \ No newline at end of file +// testExperimentSummary(); diff --git a/mlflow/src/tracking_server/run_management.js b/mlflow/src/tracking_server/run_management.js index ada9d7b1..9ea9f71b 100644 --- a/mlflow/src/tracking_server/run_management.js +++ b/mlflow/src/tracking_server/run_management.js @@ -450,7 +450,7 @@ class RunManagement { order_by, page_token ) { - const url = `${this.trackingUri}/runs/search`; + const url = `${this.trackingUri}/api/2.0/mlflow/runs/search`; const response = await fetch(url, { method: 'POST', headers: { From aefc19f87306d25ce49a5817386b1ce6bc449741 Mon Sep 17 00:00:00 2001 From: Austin Fraser Date: Tue, 10 Sep 2024 16:12:36 -0700 Subject: [PATCH 048/357] more JSdocs and code formatting --- .../tracking_server/experiment_management.js | 102 ++++++++++++------ 1 file changed, 68 insertions(+), 34 deletions(-) diff --git a/mlflow/src/tracking_server/experiment_management.js b/mlflow/src/tracking_server/experiment_management.js index c4470f64..35f40372 100644 --- a/mlflow/src/tracking_server/experiment_management.js +++ b/mlflow/src/tracking_server/experiment_management.js @@ -1,7 +1,7 @@ const MLFLOW_TRACKING_URI = 'http://localhost:5001/api/2.0/mlflow'; -import { RunManagement } from "./run_management.js"; +import { RunManagement } from './run_management.js'; const path = 'artifacts'; -const runManagement = new RunManagement("http://localhost:5001", path); +const runManagement = new RunManagement('http://localhost:5001', path); /** * Create an experiment with a name. Returns the ID of the newly created experiment. @@ -374,14 +374,10 @@ const testSetExperimentTag = async () => { // uncomment below --- // testSetExperimentTag(); - - - - /** * Full workflow of creating, naming and starting a run under an experiment (referenced by ID), * logging metrics, params, and tags, logging the model, and finishing the run. - * + * * @param {string} experiment_id ID of the experiment under which to log the run. (required) * @param {string} run_name Name of the run to be created and run (optional) * @param {Array<{key: string, value: number, timestamp: number, step?: number}>} [metrics] The metrics to log (up to 1000 metrics) (optional) @@ -390,7 +386,14 @@ const testSetExperimentTag = async () => { * @param {Object} model The ML model data to log to the run, represented as a Javascript object (required) * @returns {Promise} The created run object with updated metadata */ -async function withStartExperimentRunByExperimentId(experiment_id, run_name = null, metrics = [], params = [], tags = [], model) { +async function withStartExperimentRunByExperimentId( + experiment_id, + run_name = null, + metrics = [], + params = [], + tags = [], + model +) { if (!experiment_id) { throw new Error('Experiment ID is required'); } @@ -420,16 +423,16 @@ async function withStartExperimentRunByExperimentId(experiment_id, run_name = nu // test **************************************************************************************************************************************** const testWithStartExperimentRunByExperimentId = async () => { const metrics = [ - {key: 'metric1', value: .111, timestamp: Date.now()}, - {key: 'metric2', value: .222, timestamp: Date.now()}, + { key: 'metric1', value: 0.111, timestamp: Date.now() }, + { key: 'metric2', value: 0.222, timestamp: Date.now() }, ]; const params = [ - {key: 'testParam', value: 'testParamValue'}, - {key: 'testParam2', value: 'testParamValue2'} + { key: 'testParam', value: 'testParamValue' }, + { key: 'testParam2', value: 'testParamValue2' }, ]; const tags = [ - {key: 'testKey', value: 'testValue'}, - {key: 'testKey2', value: 'testValue2'} + { key: 'testKey', value: 'testValue' }, + { key: 'testKey2', value: 'testValue2' }, ]; const model = { artifact_path: 'model', @@ -443,20 +446,25 @@ const testWithStartExperimentRunByExperimentId = async () => { model_url: 'STRING', model_uuid: 'STRING', utc_time_created: Date.now(), - mlflow_version: 'STRING' + mlflow_version: 'STRING', }; - const log = await withStartExperimentRunByExperimentId('977566317259111173', undefined, metrics, params, tags, model); + const log = await withStartExperimentRunByExperimentId( + '977566317259111173', + undefined, + metrics, + params, + tags, + model + ); return console.log(log); }; // uncomment below --- // testWithStartExperimentRunByExperimentId(); - - /** * Full workflow of creating, naming and starting a run under an experiment (referenced by name), * logging metrics, params, and tags, logging the model, and finishing the run. - * + * * @param {string} experiment_name Name of the experiment under which to log the run. (required) * @param {string} run_name Name of the run to be created and run (optional) * @param {Array<{key: string, value: number, timestamp: number, step?: number}>} [metrics] The metrics to log (up to 1000 metrics) (optional) @@ -465,7 +473,14 @@ const testWithStartExperimentRunByExperimentId = async () => { * @param {Object} model The ML model data to log to the run, represented as a Javascript object (required) * @returns {Promise} The created run object with updated metadata */ -async function withStartExperimentRunByExperimentName(experiment_name, run_name = null, metrics = [], params = [], tags = [], model) { +async function withStartExperimentRunByExperimentName( + experiment_name, + run_name = null, + metrics = [], + params = [], + tags = [], + model +) { if (!experiment_name) { throw new Error('Experiment name is required'); } @@ -503,16 +518,16 @@ async function withStartExperimentRunByExperimentName(experiment_name, run_name // test **************************************************************************************************************************************** const testWithStartExperimentRunByExperimentName = async () => { const metrics = [ - {key: 'metric1', value: .9, timestamp: Date.now()}, - {key: 'metric2', value: .222, timestamp: Date.now()}, + { key: 'metric1', value: 0.9, timestamp: Date.now() }, + { key: 'metric2', value: 0.222, timestamp: Date.now() }, ]; const params = [ - {key: 'testParam', value: 'testParamValue'}, - {key: 'testParam2', value: 'testParamValue2'} + { key: 'testParam', value: 'testParamValue' }, + { key: 'testParam2', value: 'testParamValue2' }, ]; const tags = [ - {key: 'testKey', value: 'testValue'}, - {key: 'testKey2', value: 'testValue2'} + { key: 'testKey', value: 'testValue' }, + { key: 'testKey2', value: 'testValue2' }, ]; const model = { artifact_path: 'model', @@ -526,26 +541,45 @@ const testWithStartExperimentRunByExperimentName = async () => { model_url: 'STRING', model_uuid: 'STRING', utc_time_created: Date.now(), - mlflow_version: 'STRING' + mlflow_version: 'STRING', }; - const log = await withStartExperimentRunByExperimentName('experimentSummary test', undefined, metrics, params, tags, model); + const log = await withStartExperimentRunByExperimentName( + 'experimentSummary test', + undefined, + metrics, + params, + tags, + model + ); return console.log(log); }; // uncomment below --- // testWithStartExperimentRunByExperimentName(); - - +/** + * Returns an array of all the passed-in experiment's runs, sorted according to the passed-in metric + * + * @param {string} experiment_id + * @param {string} primaryMetric + * @param {string | number} order + * @returns Promise> An array of run objects belonging to the passed-in experiment ID, sorted according to the primary metric + */ async function experimentSummary(experiment_id, primaryMetric, order) { // use Search Runs to return all runs whose experiment ID matches the passed in one // use Search Runs's order_by field to sort results array by primaryMetric let orderString; - if (order === 1 || order === 'DESC') orderString = 'DESC' + if (order === 1 || order === 'DESC') orderString = 'DESC'; else if (order === -1 || order === 'ASC') orderString = 'ASC'; const arg = `metrics.${primaryMetric} ${orderString}`; - const data = await runManagement.searchRuns([experiment_id], undefined, undefined, undefined, [arg]); - return data.runs -}; + const data = await runManagement.searchRuns( + [experiment_id], + undefined, + undefined, + undefined, + [arg] + ); + return data.runs; +} // test **************************************************************************************************************************************** const testExperimentSummary = async () => { From 7dbe53368b8a8d4ed9defe9162b3466ae7b71c8a Mon Sep 17 00:00:00 2001 From: Austin Fraser Date: Tue, 10 Sep 2024 16:42:47 -0700 Subject: [PATCH 049/357] added to JSdocs --- mlflow/src/tracking_server/experiment_management.js | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/mlflow/src/tracking_server/experiment_management.js b/mlflow/src/tracking_server/experiment_management.js index 35f40372..3dde7de2 100644 --- a/mlflow/src/tracking_server/experiment_management.js +++ b/mlflow/src/tracking_server/experiment_management.js @@ -559,9 +559,9 @@ const testWithStartExperimentRunByExperimentName = async () => { /** * Returns an array of all the passed-in experiment's runs, sorted according to the passed-in metric * - * @param {string} experiment_id - * @param {string} primaryMetric - * @param {string | number} order + * @param {string} experiment_id The experiment whose runs will be evaluated (required) + * @param {string} primaryMetric The metric by which the results array will be sorted + * @param {string | number} order Sort order for the array: pass in 'DESC' or 1 for descending; 'ASC' or -1 for ascending * @returns Promise> An array of run objects belonging to the passed-in experiment ID, sorted according to the primary metric */ async function experimentSummary(experiment_id, primaryMetric, order) { From 40973ad26ff6ac14d703e7726d93c9a837c43e65 Mon Sep 17 00:00:00 2001 From: Kyler-Chiago Date: Tue, 10 Sep 2024 17:33:38 -0700 Subject: [PATCH 050/357] data.message || response.statusText for the error handling in model_registry and run_management --- mlflow/src/tracking_server/run_management.js | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/mlflow/src/tracking_server/run_management.js b/mlflow/src/tracking_server/run_management.js index 6bbb0204..ace52a44 100644 --- a/mlflow/src/tracking_server/run_management.js +++ b/mlflow/src/tracking_server/run_management.js @@ -67,7 +67,7 @@ class RunManagement { }); if (!response.ok) { - throw new Error(`Error in deleting run: ${response.statusText}`); + throw new Error(`Error in deleting run: ${data.message || response.statusText}`); } return await response.json(); @@ -93,7 +93,7 @@ class RunManagement { }); if (!response.ok) { - throw new Error(`Error in restoring run: ${response.statusText}`); + throw new Error(`Error in restoring run: ${data.message || response.statusText}`); } return await response.json(); @@ -190,7 +190,7 @@ class RunManagement { }); if (!response.ok) { - throw new Error(`Error in logging metric: ${response.statusText}`); + throw new Error(`Error in logging metric: ${data.message || response.statusText}`); } return await response.json(); @@ -226,7 +226,7 @@ class RunManagement { if (!response.ok) { const responseBody = await response.text(); console.error(`Response body: ${responseBody}`); - throw new Error(`Error in logging batch: ${response.statusText}`); + throw new Error(`Error in logging batch: ${data.message || response.statusText}`); } return await response.json(); @@ -253,7 +253,7 @@ class RunManagement { }); if (!response.ok) { - throw new Error(`Error in logging model: ${response.statusText}`); + throw new Error(`Error in logging model: ${data.message || response.statusText}`); } return await response.json(); @@ -281,7 +281,7 @@ class RunManagement { }); if (!response.ok) { - throw new Error(`Error in logging inputs: ${response.statusText}`); + throw new Error(`Error in logging inputs: ${data.message || response.statusText}`); } return await response.json(); @@ -317,7 +317,7 @@ class RunManagement { const data = await response.json(); if (!response.ok) { - throw new Error(`Error logging param: ${response.statusText}`); + throw new Error(`Error logging param: ${data.message || response.statusText}`); } return data; } @@ -347,7 +347,7 @@ class RunManagement { const data = await response.json(); if (!response.ok) { - throw new Error(`Error logging param: ${response.statusText}`); + throw new Error(`Error logging param: ${data.message || response.statusText}`); } return data; } @@ -379,7 +379,7 @@ class RunManagement { const data = await response.json(); if (!response.ok) { - throw new Error(`Error logging param: ${response.statusText}`); + throw new Error(`Error logging param: ${data.message || response.statusText}`); } return data; } From 72dfeed25869514e7c9ce063f293b623056bd55b Mon Sep 17 00:00:00 2001 From: Austin Fraser Date: Tue, 10 Sep 2024 18:47:50 -0700 Subject: [PATCH 051/357] model is no longer required field for withStartExperimentRunByExperimentName and withStartExperimentRunByExperimentId --- .../src/tracking_server/experiment_management.js | 14 ++++---------- 1 file changed, 4 insertions(+), 10 deletions(-) diff --git a/mlflow/src/tracking_server/experiment_management.js b/mlflow/src/tracking_server/experiment_management.js index 3dde7de2..85f11d4b 100644 --- a/mlflow/src/tracking_server/experiment_management.js +++ b/mlflow/src/tracking_server/experiment_management.js @@ -383,7 +383,7 @@ const testSetExperimentTag = async () => { * @param {Array<{key: string, value: number, timestamp: number, step?: number}>} [metrics] The metrics to log (up to 1000 metrics) (optional) * @param {Array<{key: string, value: string}>} [params] The params to log (up to 100 params) (optional) * @param {Array<{key: string, value: string}>} [tags=[]] The tags to log (up to 100 tags) (optional) - * @param {Object} model The ML model data to log to the run, represented as a Javascript object (required) + * @param {Object} model The ML model data to log to the run, represented as a Javascript object * @returns {Promise} The created run object with updated metadata */ async function withStartExperimentRunByExperimentId( @@ -397,9 +397,6 @@ async function withStartExperimentRunByExperimentId( if (!experiment_id) { throw new Error('Experiment ID is required'); } - if (!model) { - throw new Error('Model is required'); - } // create run const run = await runManagement.createRun(experiment_id, run_name, tags); @@ -470,7 +467,7 @@ const testWithStartExperimentRunByExperimentId = async () => { * @param {Array<{key: string, value: number, timestamp: number, step?: number}>} [metrics] The metrics to log (up to 1000 metrics) (optional) * @param {Array<{key: string, value: string}>} [params] The params to log (up to 100 params) (optional) * @param {Array<{key: string, value: string}>} [tags=[]] The tags to log (up to 100 tags) (optional) - * @param {Object} model The ML model data to log to the run, represented as a Javascript object (required) + * @param {Object} model The ML model data to log to the run, represented as a Javascript object * @returns {Promise} The created run object with updated metadata */ async function withStartExperimentRunByExperimentName( @@ -484,9 +481,6 @@ async function withStartExperimentRunByExperimentName( if (!experiment_name) { throw new Error('Experiment name is required'); } - if (!model) { - throw new Error('Model is required'); - } let experiment_id; try { @@ -583,8 +577,8 @@ async function experimentSummary(experiment_id, primaryMetric, order) { // test **************************************************************************************************************************************** const testExperimentSummary = async () => { - const log = await experimentSummary('787867007534323476', 'metric1', 'DESC'); + const log = await experimentSummary('787867007534323476', 'metric1', 'ASC'); return console.log(log); }; // uncomment below --- -// testExperimentSummary(); +testExperimentSummary(); From 7203ad6ae21c172a810bde3ad79f1a8279bd563b Mon Sep 17 00:00:00 2001 From: Yiqun Zheng Date: Tue, 10 Sep 2024 19:21:27 -0700 Subject: [PATCH 052/357] added tsconfig.json, tests folder, ts files --- mlflow/src/model_registry/modelRegistry.ts | 0 mlflow/src/model_registry/model_registry.js | 75 +++++++++------------ mlflow/src/utils/apiClient.js | 38 ----------- mlflow/src/utils/apiClient.ts | 50 ++++++++++++++ mlflow/tests/modelRegistryTest.js | 71 +++++++++++++++++++ mlflow/tsconfig.json | 15 +++++ 6 files changed, 168 insertions(+), 81 deletions(-) create mode 100644 mlflow/src/model_registry/modelRegistry.ts delete mode 100644 mlflow/src/utils/apiClient.js create mode 100644 mlflow/src/utils/apiClient.ts create mode 100644 mlflow/tests/modelRegistryTest.js create mode 100644 mlflow/tsconfig.json diff --git a/mlflow/src/model_registry/modelRegistry.ts b/mlflow/src/model_registry/modelRegistry.ts new file mode 100644 index 00000000..e69de29b diff --git a/mlflow/src/model_registry/model_registry.js b/mlflow/src/model_registry/model_registry.js index 7c8e0844..d470fc5c 100644 --- a/mlflow/src/model_registry/model_registry.js +++ b/mlflow/src/model_registry/model_registry.js @@ -1,15 +1,5 @@ //model_registry.js -import apiRequest from '../utils/apiClient.js'; - -let domain = 'http://localhost:' -const port = 5001; -if (port) { - domain = domain + port; -} - -const version = '2.0'; - -const MLFLOW_TRACKING_URI = domain + '/api/' + version + '/mlflow'; +import apiRequest from '../utils/apiClient.ts'; class ModelRegistry { constructor(trackingUri) { @@ -26,14 +16,21 @@ class ModelRegistry { * @throws {Error} - If the API request fails */ async createRegisteredModel(name, tags = [], description = '') { - const { response, data } = await apiRequest( - this.trackingUri, - 'registered-models/create', - { - method: 'POST', - body: { name, tags, description }, - } - ); + if (!name) { + throw new Error('Model name is required'); + } + + const url = `${this.trackingUri}/api/2.0/mlflow/registered-models/create`; + + const response = await fetch(url, { + method: 'POST', + headers: { + 'Content-Type': 'application/json', + }, + body: JSON.stringify({ name, tags, description }), + }); + + const data = await response.json(); if (!response.ok) { throw new Error( @@ -318,33 +315,29 @@ class ModelRegistry { * @param {string} version - The version number to alias (required) * @returns {Promise} */ - async setRegisteredModelAlias(name, alias, version) { + async setRegisteredModelAlias(name, alias, version) { if (!name) { - throw new Error("name is required"); + throw new Error('name is required'); } else if (!alias) { - throw new Error("alias is required"); + throw new Error('alias is required'); } else if (!version) { - throw new Error("version is required"); + throw new Error('version is required'); } const url = `${this.trackingUri}/registered-models/alias`; const response = await fetch(url, { - method: "POST", + method: 'POST', headers: { - "Content-Type": "application/json", + 'Content-Type': 'application/json', }, - body: JSON.stringify({ name, alias, version}), + body: JSON.stringify({ name, alias, version }), }); // data is an empty object const data = await response.json(); if (!response.ok) { - throw new Error( - `Error setting model alias: ${ - response.statusText - }` - ); + throw new Error(`Error setting model alias: ${response.statusText}`); } return data; } @@ -358,29 +351,25 @@ class ModelRegistry { */ async deleteRegisteredModelAlias(name, alias) { if (!name) { - throw new Error("name is required"); + throw new Error('name is required'); } else if (!alias) { - throw new Error("alias is required"); + throw new Error('alias is required'); } const url = `${this.trackingUri}/registered-models/alias`; const response = await fetch(url, { - method: "DELETE", + method: 'DELETE', headers: { - "Content-Type": "application/json", + 'Content-Type': 'application/json', }, - body: JSON.stringify({ name, alias}), + body: JSON.stringify({ name, alias }), }); // data is an empty object const data = await response.json(); if (!response.ok) { - throw new Error( - `Error deleting model alias: ${ - response.statusText - }` - ); + throw new Error(`Error deleting model alias: ${response.statusText}`); } return data; } @@ -394,9 +383,9 @@ class ModelRegistry { */ async getModelVersionByAlias(name, alias) { if (!name) { - throw new Error("name is required"); + throw new Error('name is required'); } else if (!alias) { - throw new Error("alias is required"); + throw new Error('alias is required'); } const url = `${this.trackingUri}/registered-models/alias`; const response = await fetch(`${url}?name=${name}&alias=${alias}`); diff --git a/mlflow/src/utils/apiClient.js b/mlflow/src/utils/apiClient.js deleted file mode 100644 index 6d2acc04..00000000 --- a/mlflow/src/utils/apiClient.js +++ /dev/null @@ -1,38 +0,0 @@ -/** - * Utility function for making API requests to the MLflow server. - * - * @param {string} baseUrl - The base URL of the MLflow server - * @param {string} endpoint - The API endpoint - * @param {Object} options - Request options - * @param {string} options.method - HTTP method (GET, POST, PUT, PATCH, DELETE) - * @param {Object} [options.body] - Request body for POST, PUT, PATCH requests - * @param {Object} [options.params] - URL parameters - * @returns {Promise} - The response and data - */ -async function apiRequest(baseUrl, endpoint, options) { - let url = `${baseUrl}/api/2.0/mlflow/${endpoint}`; - const { method, body, params } = options; - - const fetchOptions = { - method, - headers: { - 'Content-Type': 'application/json', - }, - }; - - if (body) { - fetchOptions.body = JSON.stringify(body); - } - - if (params) { - const searchParams = new URLSearchParams(params); - url += `?${searchParams.toString()}`; - } - - const response = await fetch(url, fetchOptions); - const data = await response.json(); - - return { response, data }; -} - -export default apiRequest; diff --git a/mlflow/src/utils/apiClient.ts b/mlflow/src/utils/apiClient.ts new file mode 100644 index 00000000..49a682d0 --- /dev/null +++ b/mlflow/src/utils/apiClient.ts @@ -0,0 +1,50 @@ +interface RequestOptions { + method: 'GET' | 'POST' | 'PUT' | 'PATCH' | 'DELETE'; + body?: Record; + params?: Record; +} + +interface ApiResponse { + response: Response; + data: T; +} + +/** + * Utility function for making API requests to the MLflow server. + * + * @param baseUrl - The base URL of the MLflow server + * @param endpoint - The API endpoint + * @param options - Request options + * @returns A promise that resolves to the response and data + */ +async function apiRequest( + baseUrl: string, + endpoint: string, + options: RequestOptions +): Promise> { + let url = `${baseUrl}/api/2.0/mlflow/${endpoint}`; + const { method, body, params } = options; + + const fetchOptions: RequestInit = { + method, + headers: { + 'Content-Type': 'application/json', + }, + }; + + if (body) { + fetchOptions.body = JSON.stringify(body); + } + + if (params) { + const searchParams = new URLSearchParams(params); + url += `?${searchParams.toString()}`; + } + + const response = await fetch(url, fetchOptions); + const data = (await response.json()) as T; + + return { response, data }; +} + +export default apiRequest; diff --git a/mlflow/tests/modelRegistryTest.js b/mlflow/tests/modelRegistryTest.js new file mode 100644 index 00000000..14ee0c88 --- /dev/null +++ b/mlflow/tests/modelRegistryTest.js @@ -0,0 +1,71 @@ +// usage_example.js +import { ModelRegistry } from '../src/model_registry/model_registry.js'; + +async function main() { + const trackingUri = 'http://localhost:5001'; + const modelRegistry = new ModelRegistry(trackingUri); + + try { + // Create a new registered model + const createdModel = await modelRegistry.createRegisteredModel; + 'MyModel1', + [{ key: 'framework', value: 'pytorch' }], + 'My first registered model'; + console.log('Created model:', createdModel); + + // // Get the registered model + // const retrievedModel = await modelRegistry.getRegisteredModel( + // 'sk-learn-random-forest-reg-model' + // ); + // console.log('Retrieved model:', retrievedModel); + + // // Rename the registered model + // const renamedModel = await modelRegistry.renameRegisteredModel( + // 'MyModel6', + // 'MyModel6New' + // ); + // console.log('Renamed model:', renamedModel); + + // // Update the model description + // const updatedModel = await modelRegistry.updateRegisteredModel( + // 'sk-learn-random-forest-reg-model', + // 'From tutorial sklearn' + // ); + // console.log('Updated model:', updatedModel); + + // // Get latest model versions + // const latestVersions = await modelRegistry.getLatestModelVersions( + // 'sk-learn-random-forest-reg-model' + // ); + // console.log('Latest versions:', latestVersions); + + // // Set a tag on the model + // await modelRegistry.setRegisteredModelTag( + // 'sk-learn-random-forest-reg-model', + // 'key1', + // 'value1' + // ); + // console.log('Tag set successfully'); + + // // Search for models + // const searchResults = await modelRegistry.searchRegisteredModels( + // "name LIKE 'My%'", + // 10, + // ['name ASC'], + // null + // ); + // console.log('Search results:', searchResults); + + // // Delete a tag from the model + // await modelRegistry.deleteRegisteredModelTag('MyNewModel', 'model_type'); + // console.log('Tag deleted successfully'); + + // Delete the model + // await modelRegistry.deleteRegisteredModel('MyModel5New'); + // console.log('Model deleted successfully'); + } catch (error) { + console.error('Error:', error.message); + } +} + +main(); diff --git a/mlflow/tsconfig.json b/mlflow/tsconfig.json new file mode 100644 index 00000000..97bc5606 --- /dev/null +++ b/mlflow/tsconfig.json @@ -0,0 +1,15 @@ +{ + "compilerOptions": { + "module": "ES6", + "target": "ES6", + "noImplicitAny": true, + "strict": true, + "forceConsistentCasingInFileNames": true, + "moduleResolution": "node", + "resolveJsonModule": true, + "outDir": "./dist", + "rootDir": "./src" + }, + "include": ["src/**/*.ts", "src/**/*.tsx"], + "exclude": ["node_modules"] +} From c40d15b5a8cdaa72d3c9e233936358c36223a393 Mon Sep 17 00:00:00 2001 From: Austin Fraser Date: Tue, 10 Sep 2024 19:33:38 -0700 Subject: [PATCH 053/357] rename experiment_management as ExperimentClient, rewrote ExperimentClient as a class, moved tests into separate untracked file --- mlflow/.gitignore | 3 +- .../src/tracking_server/ExperimentClient.js | 509 +++++++++++++++ .../tracking_server/experiment_management.js | 584 ------------------ 3 files changed, 511 insertions(+), 585 deletions(-) create mode 100644 mlflow/src/tracking_server/ExperimentClient.js delete mode 100644 mlflow/src/tracking_server/experiment_management.js diff --git a/mlflow/.gitignore b/mlflow/.gitignore index b512c09d..e27f460c 100644 --- a/mlflow/.gitignore +++ b/mlflow/.gitignore @@ -1 +1,2 @@ -node_modules \ No newline at end of file +node_modules +mlflow/src/tracking_server/ExperimentClient_testFile.js \ No newline at end of file diff --git a/mlflow/src/tracking_server/ExperimentClient.js b/mlflow/src/tracking_server/ExperimentClient.js new file mode 100644 index 00000000..de58afe6 --- /dev/null +++ b/mlflow/src/tracking_server/ExperimentClient.js @@ -0,0 +1,509 @@ +class ExperimentClient { + constructor(trackingUri) { + this.trackingUri = trackingUri; + } + + /** + * Create an experiment with a name. Returns the ID of the newly created experiment. + * Validates that another experiment with the same name does not already exist and fails if another experiment with the same name already exists. + * + * @param {string} name Experiment name. (required) + * @param {string} artifact_location Optional location where all artifacts for the experiment are stored. + * If not provided, the remote server will select an appropriate default. + * @param {Array<{key: string, value: string}>} tags Optional collection of tags to set on the experiment. + * @returns {Promise} Returns the ID of the newly created experiment in an object. + */ + async createExperiment(name, artifact_location = '', tags = []) { + if (!name) { + throw new Error('Experiment name is required'); + } + + const url = `${this.trackingUri}/api/2.0/mlflow/experiments/create`; + const response = await fetch(url, { + method: 'POST', + headers: { 'Content-Type': 'application/json' }, + body: JSON.stringify({ name, artifact_location, tags }), + }); + + if (!response.ok) { + const errorBody = await response.json(); + throw new Error( + `Error creating experiment from tracking server, status: ${response.status}. ${errorBody.message}` + ); + } + + const data = await response.json(); + // console.log('return from createExperiment: ', data.experiment_id); + return data.experiment_id; + } + + /** + * Search experiments. + * + * @param {string} filter A filter expression over experiment attributes and tags that allows returning a subset of experiments + * The syntax is a subset of SQL. (required) + * @param {int64} max_results Maximum number of experiments desired. (required) + * @param {string} page_token Optional token indicating the page of experiments to fetch. + * @param {Array} order_by Optional list of columns for ordering search results. + * @param {string} view_type Optional qualifier for type of experiments to be returned. + * See https://mlflow.org/docs/latest/rest-api.html#mlflowviewtype + * @returns {Promise} Returns object containing an array of experiment objects matching the filter, + * and optionally a next_page_token that can be used to retrieve the next page of experiments. + */ + async searchExperiment( + filter, + max_results, + page_token = '', + order_by = [], + view_type = '' + ) { + if (!filter) { + throw new Error('Filter is required'); + } + if (!max_results) { + throw new Error('Max results is required'); + } + + const url = `${this.trackingUri}/api/2.0/mlflow/experiments/search`; + const response = await fetch(url, { + method: 'POST', + headers: { 'Content-Type': 'application/json' }, + body: JSON.stringify({ + filter, + max_results, + page_token, + order_by, + view_type, + }), + }); + + if (!response.ok) { + const errorBody = await response.json(); + throw new Error( + `Error searching for experiment from tracking server, status: ${response.status}. ${errorBody.message}` + ); + } + + const data = await response.json(); + // console.log('return from searchExperiment: ', data); + return data; + } + + /** + * Get metadata for an experiment, querying by experiment ID. This method works on deleted experiments. + * + * @param {string} experiment_id ID of the associated experiment. (required) + * @returns {Promise} Returns object containing the matched experiment. + */ + async getExperiment(experiment_id) { + if (!experiment_id) { + throw new Error('Experiment ID is required'); + } + + const url = `${this.trackingUri}/api/2.0/mlflow/experiments/get?experiment_id=${experiment_id}`; + const response = await fetch(url, { + method: 'GET', + headers: { 'Content-Type': 'application/json' }, + }); + + if (!response.ok) { + const errorBody = await response.json(); + throw new Error( + `Error getting experiment from tracking server, status: ${response.status}. ${errorBody.message}` + ); + } + + const data = await response.json(); + // console.log('return from getExperiment: ', data.experiment); + return data.experiment; + } + + /** + * Get metadata for an experiment, querying by experiment name. + * This endpoint will return deleted experiments, + * but prefers the active experiment if an active and deleted experiment share the same name. + * If multiple deleted experiments share the same name, the API will return one of them. + * + * @param {string} experiment_name ID of the associated experiment. (required) + * @returns {Promise} Returns object containing the matched experiment. + */ + async getExperimentByName(experiment_name) { + if (!experiment_name) { + throw new Error('Experiment name is required'); + } + + const url = `${this.trackingUri}/api/2.0/mlflow/experiments/get-by-name?experiment_name=${experiment_name}`; + const response = await fetch(url, { + method: 'GET', + headers: { 'Content-Type': 'application/json' }, + }); + + if (!response.ok) { + const errorBody = await response.json(); + throw new Error( + `Error getting experiment by name from tracking server, status: ${response.status}. ${errorBody.message}` + ); + } + + const data = await response.json(); + // console.log('return from getExperimentByName: ', data.experiment); + return data.experiment; + } + + /** + * Mark an experiment for deletion. + * + * @param {string} experiment_id ID of the associated experiment. (required) + * @returns {string} Returns a string i.e. "Experiment ID 99999 successfully deleted" + */ + async deleteExperiment(experiment_id) { + if (!experiment_id) { + throw new Error('Experiment ID is required'); + } + + const url = `${this.trackingUri}/api/2.0/mlflow/experiments/delete`; + const response = await fetch(url, { + method: 'POST', + headers: { 'Content-Type': 'application/json' }, + body: JSON.stringify({ experiment_id }), + }); + + if (!response.ok) { + const errorBody = await response.json(); + throw new Error( + `Error deleting experiment from tracking server, status: ${response.status}. ${errorBody.message}` + ); + } + + // console.log(`Experiment ID ${experiment_id} successfully deleted`); + return `Experiment ID ${experiment_id} successfully deleted`; + } + + /** + * Restore an experiment marked for deletion. + * + * @param {string} experiment_id ID of the associated experiment. (required) + * @returns {string} Returns a string i.e. "Experiment ID 99999 successfully restored" + */ + async restoreExperiment(experiment_id) { + if (!experiment_id) { + throw new Error('Experiment ID is required'); + } + + const url = `${this.trackingUri}/api/2.0/mlflow/experiments/restore`; + const response = await fetch(url, { + method: 'POST', + headers: { 'Content-Type': 'application/json' }, + body: JSON.stringify({ experiment_id }), + }); + + if (!response.ok) { + const errorBody = await response.json(); + throw new Error( + `Error restoring experiment from tracking server, status: ${response.status}. ${errorBody.message}` + ); + } + + // console.log(`Experiment ID ${experiment_id} successfully restored`); + return `Experiment ID ${experiment_id} successfully restored`; + } + + /** + * Update experiment name. + * + * @param {string} experiment_id ID of the associated experiment. (required) + * @param {string} new_name The experiment’s name is changed to the new name. The new name must be unique. (required) + * @returns {string} Returns a string i.e. "Experiment ID 99999 successfully updated" + */ + async updateExperiment(experiment_id, new_name) { + if (!experiment_id) { + throw new Error('Experiment ID is required'); + } + if (!new_name) { + throw new Error('New name is required'); + } + + const url = `${this.trackingUri}/api/2.0/mlflow/experiments/update`; + const response = await fetch(url, { + method: 'POST', + headers: { 'Content-Type': 'application/json' }, + body: JSON.stringify({ experiment_id, new_name }), + }); + + if (!response.ok) { + const errorBody = await response.json(); + throw new Error( + `Error updating experiment from tracking server, status: ${response.status}. ${errorBody.message}` + ); + } + + // console.log(`Experiment ID ${experiment_id} successfully updated - new name is ${new_name}`); + return `Experiment ID ${experiment_id} successfully updated - new name is ${new_name}`; + } + + /** + * Set a tag on an experiment. + * + * @param {string} experiment_id ID of the experiment under which to log the tag. (required) + * @param {string} key Name of the tag. (required) + * @param {string} value String value of the tag being logged. (required) + * @returns {string} Returns a string, i.e. `Set tag to experiment ID 99999 successfully` + */ + async setExperimentTag(experiment_id, key, value) { + if (!experiment_id) { + throw new Error('Experiment ID is required'); + } + if (!key) { + throw new Error('Key is required'); + } + if (!value) { + throw new Error('Value is required'); + } + + const url = `${this.trackingUri}/api/2.0/mlflow/experiments/set-experiment-tag`; + const response = await fetch(url, { + method: 'POST', + headers: { 'Content-Type': 'application/json' }, + body: JSON.stringify({ experiment_id, key, value }), + }); + + if (!response.ok) { + const errorBody = await response.json(); + throw new Error( + `Error setting tag from tracking server, status: ${response.status}. ${errorBody.message}` + ); + } + + // console.log(`Set tag to experiment ID ${experiment_id} successfully`); + return `Set tag to experiment ID ${experiment_id} successfully`; + } +} + +export { ExperimentClient }; + + + + + + + + + + /** + * Full workflow of creating, naming and starting a run under an experiment (referenced by ID), + * logging metrics, params, and tags, logging the model, and finishing the run. + * + * @param {string} experiment_id ID of the experiment under which to log the run. (required) + * @param {string} run_name Name of the run to be created and run (optional) + * @param {Array<{key: string, value: number, timestamp: number, step?: number}>} [metrics] The metrics to log (up to 1000 metrics) (optional) + * @param {Array<{key: string, value: string}>} [params] The params to log (up to 100 params) (optional) + * @param {Array<{key: string, value: string}>} [tags=[]] The tags to log (up to 100 tags) (optional) + * @param {Object} model The ML model data to log to the run, represented as a Javascript object + * @returns {Promise} The created run object with updated metadata + */ + async function withStartExperimentRunByExperimentId( + experiment_id, + run_name = null, + metrics = [], + params = [], + tags = [], + model + ) { + if (!experiment_id) { + throw new Error('Experiment ID is required'); + } + + // create run + const run = await runManagement.createRun(experiment_id, run_name, tags); + const run_id = run.info.run_id; + + // log metric, params, and tags via logBatch + await runManagement.logBatch(run_id, metrics, params, tags); + + // log model + // (model gets passed in as a JS object, not JSON - it gets JSON stringified here after adding a run_id property) + model.run_id = run_id; + let model_json = JSON.stringify(model); + await runManagement.logModel(run_id, model_json); + + // updateRun to finish it + const latestRun = await runManagement.updateRun(run_id, 'FINISHED'); + + return latestRun; + } + + // test **************************************************************************************************************************************** + const testWithStartExperimentRunByExperimentId = async () => { + const metrics = [ + { key: 'metric1', value: 0.111, timestamp: Date.now() }, + { key: 'metric2', value: 0.222, timestamp: Date.now() }, + ]; + const params = [ + { key: 'testParam', value: 'testParamValue' }, + { key: 'testParam2', value: 'testParamValue2' }, + ]; + const tags = [ + { key: 'testKey', value: 'testValue' }, + { key: 'testKey2', value: 'testValue2' }, + ]; + const model = { + artifact_path: 'model', + flavors: { + python_function: { + model_path: 'model.pkl', + loader_module: 'mlflow.sklearn', + python_version: '3.8.10', + }, + }, + model_url: 'STRING', + model_uuid: 'STRING', + utc_time_created: Date.now(), + mlflow_version: 'STRING', + }; + const log = await withStartExperimentRunByExperimentId( + '977566317259111173', + undefined, + metrics, + params, + tags, + model + ); + return console.log(log); + }; + // uncomment below --- + // testWithStartExperimentRunByExperimentId(); + + /** + * Full workflow of creating, naming and starting a run under an experiment (referenced by name), + * logging metrics, params, and tags, logging the model, and finishing the run. + * + * @param {string} experiment_name Name of the experiment under which to log the run. (required) + * @param {string} run_name Name of the run to be created and run (optional) + * @param {Array<{key: string, value: number, timestamp: number, step?: number}>} [metrics] The metrics to log (up to 1000 metrics) (optional) + * @param {Array<{key: string, value: string}>} [params] The params to log (up to 100 params) (optional) + * @param {Array<{key: string, value: string}>} [tags=[]] The tags to log (up to 100 tags) (optional) + * @param {Object} model The ML model data to log to the run, represented as a Javascript object + * @returns {Promise} The created run object with updated metadata + */ + async function withStartExperimentRunByExperimentName( + experiment_name, + run_name = null, + metrics = [], + params = [], + tags = [], + model + ) { + if (!experiment_name) { + throw new Error('Experiment name is required'); + } + + let experiment_id; + try { + const exp = await getExperimentByName(experiment_name); + experiment_id = exp.experiment_id; + } catch { + experiment_id = await createExperiment(experiment_name); + } + + // create run + const run = await runManagement.createRun(experiment_id, run_name, tags); + const run_id = run.info.run_id; + + // log metric, params, and tags via logBatch + await runManagement.logBatch(run_id, metrics, params, tags); + + // log model + // (model gets passed in as a JS object, not JSON - it gets JSON stringified here after adding a run_id property) + model.run_id = run_id; + let model_json = JSON.stringify(model); + await runManagement.logModel(run_id, model_json); + + // updateRun to finish it + const latest_run = await runManagement.updateRun(run_id, 'FINISHED'); + + return latest_run; + } + + // test **************************************************************************************************************************************** + const testWithStartExperimentRunByExperimentName = async () => { + const metrics = [ + { key: 'metric1', value: 0.9, timestamp: Date.now() }, + { key: 'metric2', value: 0.222, timestamp: Date.now() }, + ]; + const params = [ + { key: 'testParam', value: 'testParamValue' }, + { key: 'testParam2', value: 'testParamValue2' }, + ]; + const tags = [ + { key: 'testKey', value: 'testValue' }, + { key: 'testKey2', value: 'testValue2' }, + ]; + const model = { + artifact_path: 'model', + flavors: { + python_function: { + model_path: 'model.pkl', + loader_module: 'mlflow.sklearn', + python_version: '3.8.10', + }, + }, + model_url: 'STRING', + model_uuid: 'STRING', + utc_time_created: Date.now(), + mlflow_version: 'STRING', + }; + const log = await withStartExperimentRunByExperimentName( + 'experimentSummary test', + undefined, + metrics, + params, + tags, + model + ); + return console.log(log); + }; + // uncomment below --- + // testWithStartExperimentRunByExperimentName(); + + /** + * Returns an array of all the passed-in experiment's runs, sorted according to the passed-in metric + * + * @param {string} experiment_id The experiment whose runs will be evaluated (required) + * @param {string} primaryMetric The metric by which the results array will be sorted + * @param {string | number} order Sort order for the array: pass in 'DESC' or 1 for descending; 'ASC' or -1 for ascending + * @returns Promise> An array of run objects belonging to the passed-in experiment ID, sorted according to the primary metric + */ + async function experimentSummary(experiment_id, primaryMetric, order) { + // use Search Runs to return all runs whose experiment ID matches the passed in one + // use Search Runs's order_by field to sort results array by primaryMetric + let orderString; + if (order === 1 || order === 'DESC') orderString = 'DESC'; + else if (order === -1 || order === 'ASC') orderString = 'ASC'; + const arg = `metrics.${primaryMetric} ${orderString}`; + const data = await runManagement.searchRuns( + [experiment_id], + undefined, + undefined, + undefined, + [arg] + ); + return data.runs; + } + + // test **************************************************************************************************************************************** + const testExperimentSummary = async () => { + const log = await experimentSummary('787867007534323476', 'metric1', 'ASC'); + return console.log(log); + }; + // uncomment below --- + // testExperimentSummary(); + + + + + +const MLFLOW_TRACKING_URI = 'http://localhost:5001/api/2.0/mlflow'; +import { RunManagement } from './run_management.js'; +const path = 'artifacts'; +const runManagement = new RunManagement('http://localhost:5001', path); + diff --git a/mlflow/src/tracking_server/experiment_management.js b/mlflow/src/tracking_server/experiment_management.js deleted file mode 100644 index 85f11d4b..00000000 --- a/mlflow/src/tracking_server/experiment_management.js +++ /dev/null @@ -1,584 +0,0 @@ -const MLFLOW_TRACKING_URI = 'http://localhost:5001/api/2.0/mlflow'; -import { RunManagement } from './run_management.js'; -const path = 'artifacts'; -const runManagement = new RunManagement('http://localhost:5001', path); - -/** - * Create an experiment with a name. Returns the ID of the newly created experiment. - * Validates that another experiment with the same name does not already exist and fails if another experiment with the same name already exists. - * - * @param {string} name Experiment name. (required) - * @param {string} artifact_location Optional location where all artifacts for the experiment are stored. - * If not provided, the remote server will select an appropriate default. - * @param {Array<{key: string, value: string}>} tags Optional collection of tags to set on the experiment. - * @returns {Promise} Returns the ID of the newly created experiment in an object. - */ -async function createExperiment(name, artifact_location = '', tags = []) { - if (!name) { - throw new Error('Experiment name is required'); - } - - const url = `${MLFLOW_TRACKING_URI}/experiments/create`; - const response = await fetch(url, { - method: 'POST', - headers: { 'Content-Type': 'application/json' }, - body: JSON.stringify({ name, artifact_location, tags }), - }); - - if (!response.ok) { - const errorBody = await response.json(); - throw new Error( - `Error creating experiment from tracking server, status: ${response.status}. ${errorBody.message}` - ); - } - - const data = await response.json(); - // console.log('return from createExperiment: ', data.experiment_id); - return data.experiment_id; -} - -// test **************************************************************************************************************************************** -const testCreateExperiment = async () => { - const log = await createExperiment('test_experiment_postman24'); - return console.log(log); -}; -// uncomment below --- -// testCreateExperiment(); - -/** - * Search experiments. - * - * @param {string} filter A filter expression over experiment attributes and tags that allows returning a subset of experiments - * The syntax is a subset of SQL. (required) - * @param {int64} max_results Maximum number of experiments desired. (required) - * @param {string} page_token Optional token indicating the page of experiments to fetch. - * @param {Array} order_by Optional list of columns for ordering search results. - * @param {string} view_type Optional qualifier for type of experiments to be returned. - * See https://mlflow.org/docs/latest/rest-api.html#mlflowviewtype - * @returns {Promise} Returns object containing an array of experiment objects matching the filter, - * and optionally a next_page_token that can be used to retrieve the next page of experiments. - */ -async function searchExperiment( - filter, - max_results, - page_token = '', - order_by = [], - view_type = '' -) { - if (!filter) { - throw new Error('Filter is required'); - } - if (!max_results) { - throw new Error('Max results is required'); - } - - const url = `${MLFLOW_TRACKING_URI}/experiments/search`; - const response = await fetch(url, { - method: 'POST', - headers: { 'Content-Type': 'application/json' }, - body: JSON.stringify({ - filter, - max_results, - page_token, - order_by, - view_type, - }), - }); - - if (!response.ok) { - const errorBody = await response.json(); - throw new Error( - `Error searching for experiment from tracking server, status: ${response.status}. ${errorBody.message}` - ); - } - - const data = await response.json(); - // console.log('return from searchExperiment: ', data); - return data; -} - -// test **************************************************************************************************************************************** -const testSearchExperiment = async () => { - const log = await searchExperiment("name LIKE 'test_%'", 5); - console.log(log); -}; -// uncomment below --- -// testSearchExperiment(); - -/** - * Get metadata for an experiment, querying by experiment ID. This method works on deleted experiments. - * - * @param {string} experiment_id ID of the associated experiment. (required) - * @returns {Promise} Returns object containing the matched experiment. - */ -async function getExperiment(experiment_id) { - if (!experiment_id) { - throw new Error('Experiment ID is required'); - } - - const url = `${MLFLOW_TRACKING_URI}/experiments/get?experiment_id=${experiment_id}`; - const response = await fetch(url, { - method: 'GET', - headers: { 'Content-Type': 'application/json' }, - }); - - if (!response.ok) { - const errorBody = await response.json(); - throw new Error( - `Error getting experiment from tracking server, status: ${response.status}. ${errorBody.message}` - ); - } - - const data = await response.json(); - // console.log('return from getExperiment: ', data.experiment); - return data.experiment; -} - -// test **************************************************************************************************************************************** -const testGetExperiment = async () => { - const log = await getExperiment('977566317259111173'); - console.log(log); -}; -// uncomment below --- -// testGetExperiment(); - -/** - * Get metadata for an experiment, querying by experiment name. - * This endpoint will return deleted experiments, - * but prefers the active experiment if an active and deleted experiment share the same name. - * If multiple deleted experiments share the same name, the API will return one of them. - * - * @param {string} experiment_name ID of the associated experiment. (required) - * @returns {Promise} Returns object containing the matched experiment. - */ -async function getExperimentByName(experiment_name) { - if (!experiment_name) { - throw new Error('Experiment name is required'); - } - - const url = `${MLFLOW_TRACKING_URI}/experiments/get-by-name?experiment_name=${experiment_name}`; - const response = await fetch(url, { - method: 'GET', - headers: { 'Content-Type': 'application/json' }, - }); - - if (!response.ok) { - const errorBody = await response.json(); - throw new Error( - `Error getting experiment by name from tracking server, status: ${response.status}. ${errorBody.message}` - ); - } - - const data = await response.json(); - // console.log('return from getExperimentByName: ', data.experiment); - return data.experiment; -} -// test **************************************************************************************************************************************** -// getExperimentByName('test_experiment_postman16'); -const testGetExperimentByName = async () => { - const log = await getExperimentByName('test_experiment_postman16'); - console.log(log); -}; -// uncomment below --- -// testGetExperimentByName(); - -/** - * Mark an experiment for deletion. - * - * @param {string} experiment_id ID of the associated experiment. (required) - * @returns {string} Returns a string i.e. "Experiment ID 99999 successfully deleted" - */ -async function deleteExperiment(experiment_id) { - if (!experiment_id) { - throw new Error('Experiment ID is required'); - } - - const url = `${MLFLOW_TRACKING_URI}/experiments/delete`; - const response = await fetch(url, { - method: 'POST', - headers: { 'Content-Type': 'application/json' }, - body: JSON.stringify({ experiment_id }), - }); - - if (!response.ok) { - const errorBody = await response.json(); - throw new Error( - `Error deleting experiment from tracking server, status: ${response.status}. ${errorBody.message}` - ); - } - - // console.log(`Experiment ID ${experiment_id} successfully deleted`); - return `Experiment ID ${experiment_id} successfully deleted`; -} - -// test **************************************************************************************************************************************** -const testDeleteExperiment = async () => { - const log = await deleteExperiment('993400766971093020'); - console.log(log); - const log2 = await getExperiment('993400766971093020'); - console.log(log2); - restoreExperiment('993400766971093020'); -}; -// uncomment below --- -// testDeleteExperiment(); - -/** - * Restore an experiment marked for deletion. - * - * @param {string} experiment_id ID of the associated experiment. (required) - * @returns {string} Returns a string i.e. "Experiment ID 99999 successfully restored" - */ -async function restoreExperiment(experiment_id) { - if (!experiment_id) { - throw new Error('Experiment ID is required'); - } - - const url = `${MLFLOW_TRACKING_URI}/experiments/restore`; - const response = await fetch(url, { - method: 'POST', - headers: { 'Content-Type': 'application/json' }, - body: JSON.stringify({ experiment_id }), - }); - - if (!response.ok) { - const errorBody = await response.json(); - throw new Error( - `Error restoring experiment from tracking server, status: ${response.status}. ${errorBody.message}` - ); - } - - // console.log(`Experiment ID ${experiment_id} successfully restored`); - return `Experiment ID ${experiment_id} successfully restored`; -} - -// test **************************************************************************************************************************************** -const testRestoreExperiment = async () => { - const log = await getExperiment('977566317259111173'); - console.log(log); - const deleted = await deleteExperiment('977566317259111173'); - console.log(deleted); - const log2 = await getExperiment('977566317259111173'); - console.log(log2); - const log3 = await restoreExperiment('977566317259111173'); - console.log(log3); - const log4 = await getExperiment('977566317259111173'); - console.log(log4); -}; -// uncomment below --- -// testRestoreExperiment(); - -/** - * Update experiment name. - * - * @param {string} experiment_id ID of the associated experiment. (required) - * @param {string} new_name The experiment’s name is changed to the new name. The new name must be unique. (required) - * @returns {string} Returns a string i.e. "Experiment ID 99999 successfully updated" - */ -async function updateExperiment(experiment_id, new_name) { - if (!experiment_id) { - throw new Error('Experiment ID is required'); - } - if (!new_name) { - throw new Error('New name is required'); - } - - const url = `${MLFLOW_TRACKING_URI}/experiments/update`; - const response = await fetch(url, { - method: 'POST', - headers: { 'Content-Type': 'application/json' }, - body: JSON.stringify({ experiment_id, new_name }), - }); - - if (!response.ok) { - const errorBody = await response.json(); - throw new Error( - `Error updating experiment from tracking server, status: ${response.status}. ${errorBody.message}` - ); - } - - // console.log(`Experiment ID ${experiment_id} successfully updated - new name is ${new_name}`); - return `Experiment ID ${experiment_id} successfully updated - new name is ${new_name}`; -} - -// test **************************************************************************************************************************************** -const testUpdateExperiment = async () => { - const log = await getExperiment('668323101796317879'); - console.log(log); - const log2 = await updateExperiment( - '668323101796317879', - 'test_experiment_postman15_UPDATED_NAME' - ); - console.log(log2); - const log3 = await getExperiment('668323101796317879'); - console.log(log3); - const revert = await updateExperiment( - '668323101796317879', - 'test_experiment_postman15' - ); -}; -// uncomment below --- -// testUpdateExperiment(); - -/** - * Set a tag on an experiment. - * - * @param {string} experiment_id ID of the experiment under which to log the tag. (required) - * @param {string} key Name of the tag. (required) - * @param {string} value String value of the tag being logged. (required) - * @returns {string} Returns a string, i.e. `Set tag to experiment ID 99999 successfully` - */ -async function setExperimentTag(experiment_id, key, value) { - if (!experiment_id) { - throw new Error('Experiment ID is required'); - } - if (!key) { - throw new Error('Key is required'); - } - if (!value) { - throw new Error('Value is required'); - } - - const url = `${MLFLOW_TRACKING_URI}/experiments/set-experiment-tag`; - const response = await fetch(url, { - method: 'POST', - headers: { 'Content-Type': 'application/json' }, - body: JSON.stringify({ experiment_id, key, value }), - }); - - if (!response.ok) { - const errorBody = await response.json(); - throw new Error( - `Error setting tag from tracking server, status: ${response.status}. ${errorBody.message}` - ); - } - - // console.log(`Set tag to experiment ID ${experiment_id} successfully`); - return `Set tag to experiment ID ${experiment_id} successfully`; -} - -// test **************************************************************************************************************************************** -const testSetExperimentTag = async () => { - const log = await getExperiment('691149904576236192'); - console.log(log); - console.log(log.tags); - const log2 = await setExperimentTag( - '691149904576236192', - 'test_tag', - 'test_value_TEST' - ); - console.log(log2); - const log3 = await getExperiment('691149904576236192'); - console.log(log3); - console.log(log3.tags); -}; -// uncomment below --- -// testSetExperimentTag(); - -/** - * Full workflow of creating, naming and starting a run under an experiment (referenced by ID), - * logging metrics, params, and tags, logging the model, and finishing the run. - * - * @param {string} experiment_id ID of the experiment under which to log the run. (required) - * @param {string} run_name Name of the run to be created and run (optional) - * @param {Array<{key: string, value: number, timestamp: number, step?: number}>} [metrics] The metrics to log (up to 1000 metrics) (optional) - * @param {Array<{key: string, value: string}>} [params] The params to log (up to 100 params) (optional) - * @param {Array<{key: string, value: string}>} [tags=[]] The tags to log (up to 100 tags) (optional) - * @param {Object} model The ML model data to log to the run, represented as a Javascript object - * @returns {Promise} The created run object with updated metadata - */ -async function withStartExperimentRunByExperimentId( - experiment_id, - run_name = null, - metrics = [], - params = [], - tags = [], - model -) { - if (!experiment_id) { - throw new Error('Experiment ID is required'); - } - - // create run - const run = await runManagement.createRun(experiment_id, run_name, tags); - const run_id = run.info.run_id; - - // log metric, params, and tags via logBatch - await runManagement.logBatch(run_id, metrics, params, tags); - - // log model - // (model gets passed in as a JS object, not JSON - it gets JSON stringified here after adding a run_id property) - model.run_id = run_id; - let model_json = JSON.stringify(model); - await runManagement.logModel(run_id, model_json); - - // updateRun to finish it - const latestRun = await runManagement.updateRun(run_id, 'FINISHED'); - - return latestRun; -} - -// test **************************************************************************************************************************************** -const testWithStartExperimentRunByExperimentId = async () => { - const metrics = [ - { key: 'metric1', value: 0.111, timestamp: Date.now() }, - { key: 'metric2', value: 0.222, timestamp: Date.now() }, - ]; - const params = [ - { key: 'testParam', value: 'testParamValue' }, - { key: 'testParam2', value: 'testParamValue2' }, - ]; - const tags = [ - { key: 'testKey', value: 'testValue' }, - { key: 'testKey2', value: 'testValue2' }, - ]; - const model = { - artifact_path: 'model', - flavors: { - python_function: { - model_path: 'model.pkl', - loader_module: 'mlflow.sklearn', - python_version: '3.8.10', - }, - }, - model_url: 'STRING', - model_uuid: 'STRING', - utc_time_created: Date.now(), - mlflow_version: 'STRING', - }; - const log = await withStartExperimentRunByExperimentId( - '977566317259111173', - undefined, - metrics, - params, - tags, - model - ); - return console.log(log); -}; -// uncomment below --- -// testWithStartExperimentRunByExperimentId(); - -/** - * Full workflow of creating, naming and starting a run under an experiment (referenced by name), - * logging metrics, params, and tags, logging the model, and finishing the run. - * - * @param {string} experiment_name Name of the experiment under which to log the run. (required) - * @param {string} run_name Name of the run to be created and run (optional) - * @param {Array<{key: string, value: number, timestamp: number, step?: number}>} [metrics] The metrics to log (up to 1000 metrics) (optional) - * @param {Array<{key: string, value: string}>} [params] The params to log (up to 100 params) (optional) - * @param {Array<{key: string, value: string}>} [tags=[]] The tags to log (up to 100 tags) (optional) - * @param {Object} model The ML model data to log to the run, represented as a Javascript object - * @returns {Promise} The created run object with updated metadata - */ -async function withStartExperimentRunByExperimentName( - experiment_name, - run_name = null, - metrics = [], - params = [], - tags = [], - model -) { - if (!experiment_name) { - throw new Error('Experiment name is required'); - } - - let experiment_id; - try { - const exp = await getExperimentByName(experiment_name); - experiment_id = exp.experiment_id; - } catch { - experiment_id = await createExperiment(experiment_name); - } - - // create run - const run = await runManagement.createRun(experiment_id, run_name, tags); - const run_id = run.info.run_id; - - // log metric, params, and tags via logBatch - await runManagement.logBatch(run_id, metrics, params, tags); - - // log model - // (model gets passed in as a JS object, not JSON - it gets JSON stringified here after adding a run_id property) - model.run_id = run_id; - let model_json = JSON.stringify(model); - await runManagement.logModel(run_id, model_json); - - // updateRun to finish it - const latest_run = await runManagement.updateRun(run_id, 'FINISHED'); - - return latest_run; -} - -// test **************************************************************************************************************************************** -const testWithStartExperimentRunByExperimentName = async () => { - const metrics = [ - { key: 'metric1', value: 0.9, timestamp: Date.now() }, - { key: 'metric2', value: 0.222, timestamp: Date.now() }, - ]; - const params = [ - { key: 'testParam', value: 'testParamValue' }, - { key: 'testParam2', value: 'testParamValue2' }, - ]; - const tags = [ - { key: 'testKey', value: 'testValue' }, - { key: 'testKey2', value: 'testValue2' }, - ]; - const model = { - artifact_path: 'model', - flavors: { - python_function: { - model_path: 'model.pkl', - loader_module: 'mlflow.sklearn', - python_version: '3.8.10', - }, - }, - model_url: 'STRING', - model_uuid: 'STRING', - utc_time_created: Date.now(), - mlflow_version: 'STRING', - }; - const log = await withStartExperimentRunByExperimentName( - 'experimentSummary test', - undefined, - metrics, - params, - tags, - model - ); - return console.log(log); -}; -// uncomment below --- -// testWithStartExperimentRunByExperimentName(); - -/** - * Returns an array of all the passed-in experiment's runs, sorted according to the passed-in metric - * - * @param {string} experiment_id The experiment whose runs will be evaluated (required) - * @param {string} primaryMetric The metric by which the results array will be sorted - * @param {string | number} order Sort order for the array: pass in 'DESC' or 1 for descending; 'ASC' or -1 for ascending - * @returns Promise> An array of run objects belonging to the passed-in experiment ID, sorted according to the primary metric - */ -async function experimentSummary(experiment_id, primaryMetric, order) { - // use Search Runs to return all runs whose experiment ID matches the passed in one - // use Search Runs's order_by field to sort results array by primaryMetric - let orderString; - if (order === 1 || order === 'DESC') orderString = 'DESC'; - else if (order === -1 || order === 'ASC') orderString = 'ASC'; - const arg = `metrics.${primaryMetric} ${orderString}`; - const data = await runManagement.searchRuns( - [experiment_id], - undefined, - undefined, - undefined, - [arg] - ); - return data.runs; -} - -// test **************************************************************************************************************************************** -const testExperimentSummary = async () => { - const log = await experimentSummary('787867007534323476', 'metric1', 'ASC'); - return console.log(log); -}; -// uncomment below --- -testExperimentSummary(); From a46eea4b25c1e7472a2e0962101d23e5d34397f6 Mon Sep 17 00:00:00 2001 From: Austin Fraser Date: Tue, 10 Sep 2024 19:35:40 -0700 Subject: [PATCH 054/357] added test file to gitignore list --- mlflow/.gitignore | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mlflow/.gitignore b/mlflow/.gitignore index e27f460c..8e58c584 100644 --- a/mlflow/.gitignore +++ b/mlflow/.gitignore @@ -1,2 +1,2 @@ node_modules -mlflow/src/tracking_server/ExperimentClient_testFile.js \ No newline at end of file +src/tracking_server/ExperimentClient_testFile.js \ No newline at end of file From c7ca6b4797b5e6ecd7cafdf4a91dd9d117897f12 Mon Sep 17 00:00:00 2001 From: Austin Fraser Date: Tue, 10 Sep 2024 19:49:06 -0700 Subject: [PATCH 055/357] deleteExperiment, restoreExperiment, updateExperiment, and setExperimentTag now do not return anything --- .../src/tracking_server/ExperimentClient.js | 24 +++++++++---------- 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/mlflow/src/tracking_server/ExperimentClient.js b/mlflow/src/tracking_server/ExperimentClient.js index de58afe6..50810a24 100644 --- a/mlflow/src/tracking_server/ExperimentClient.js +++ b/mlflow/src/tracking_server/ExperimentClient.js @@ -154,7 +154,7 @@ class ExperimentClient { * Mark an experiment for deletion. * * @param {string} experiment_id ID of the associated experiment. (required) - * @returns {string} Returns a string i.e. "Experiment ID 99999 successfully deleted" + * @returns {void} */ async deleteExperiment(experiment_id) { if (!experiment_id) { @@ -175,15 +175,15 @@ class ExperimentClient { ); } - // console.log(`Experiment ID ${experiment_id} successfully deleted`); - return `Experiment ID ${experiment_id} successfully deleted`; + console.log(`Experiment ID ${experiment_id} successfully deleted`); + // return `Experiment ID ${experiment_id} successfully deleted`; } /** * Restore an experiment marked for deletion. * * @param {string} experiment_id ID of the associated experiment. (required) - * @returns {string} Returns a string i.e. "Experiment ID 99999 successfully restored" + * @returns {void} */ async restoreExperiment(experiment_id) { if (!experiment_id) { @@ -204,8 +204,8 @@ class ExperimentClient { ); } - // console.log(`Experiment ID ${experiment_id} successfully restored`); - return `Experiment ID ${experiment_id} successfully restored`; + console.log(`Experiment ID ${experiment_id} successfully restored`); + // return `Experiment ID ${experiment_id} successfully restored`; } /** @@ -213,7 +213,7 @@ class ExperimentClient { * * @param {string} experiment_id ID of the associated experiment. (required) * @param {string} new_name The experiment’s name is changed to the new name. The new name must be unique. (required) - * @returns {string} Returns a string i.e. "Experiment ID 99999 successfully updated" + * @returns {void} */ async updateExperiment(experiment_id, new_name) { if (!experiment_id) { @@ -237,8 +237,8 @@ class ExperimentClient { ); } - // console.log(`Experiment ID ${experiment_id} successfully updated - new name is ${new_name}`); - return `Experiment ID ${experiment_id} successfully updated - new name is ${new_name}`; + console.log(`Experiment ID ${experiment_id} successfully updated - new name is ${new_name}`); + // return `Experiment ID ${experiment_id} successfully updated - new name is ${new_name}`; } /** @@ -247,7 +247,7 @@ class ExperimentClient { * @param {string} experiment_id ID of the experiment under which to log the tag. (required) * @param {string} key Name of the tag. (required) * @param {string} value String value of the tag being logged. (required) - * @returns {string} Returns a string, i.e. `Set tag to experiment ID 99999 successfully` + * @returns {void} */ async setExperimentTag(experiment_id, key, value) { if (!experiment_id) { @@ -274,8 +274,8 @@ class ExperimentClient { ); } - // console.log(`Set tag to experiment ID ${experiment_id} successfully`); - return `Set tag to experiment ID ${experiment_id} successfully`; + console.log(`Set tag to experiment ID ${experiment_id} successfully`); + // return `Set tag to experiment ID ${experiment_id} successfully`; } } From 45ebf56466c7a4e9b9ca937c1a822809c7561aed Mon Sep 17 00:00:00 2001 From: Austin Fraser Date: Tue, 10 Sep 2024 22:37:21 -0700 Subject: [PATCH 056/357] ExperimentManager file added, minor tweaks to ExperimentClient --- mlflow/.gitignore | 3 +- .../src/tracking_server/ExperimentClient.js | 238 +----------------- mlflow/src/workflows/ExperimentManager.js | 132 ++++++++++ 3 files changed, 138 insertions(+), 235 deletions(-) create mode 100644 mlflow/src/workflows/ExperimentManager.js diff --git a/mlflow/.gitignore b/mlflow/.gitignore index 8e58c584..7af338ff 100644 --- a/mlflow/.gitignore +++ b/mlflow/.gitignore @@ -1,2 +1,3 @@ node_modules -src/tracking_server/ExperimentClient_testFile.js \ No newline at end of file +src/tracking_server/ExperimentClient_testFile.js +src/workflows/ExperimentManager_testFile.js \ No newline at end of file diff --git a/mlflow/src/tracking_server/ExperimentClient.js b/mlflow/src/tracking_server/ExperimentClient.js index 50810a24..d63a16ec 100644 --- a/mlflow/src/tracking_server/ExperimentClient.js +++ b/mlflow/src/tracking_server/ExperimentClient.js @@ -8,8 +8,7 @@ class ExperimentClient { * Validates that another experiment with the same name does not already exist and fails if another experiment with the same name already exists. * * @param {string} name Experiment name. (required) - * @param {string} artifact_location Optional location where all artifacts for the experiment are stored. - * If not provided, the remote server will select an appropriate default. + * @param {string} artifact_location Optional location where all artifacts for the experiment are stored. If not provided, the remote server will select an appropriate default. * @param {Array<{key: string, value: string}>} tags Optional collection of tags to set on the experiment. * @returns {Promise} Returns the ID of the newly created experiment in an object. */ @@ -40,13 +39,11 @@ class ExperimentClient { /** * Search experiments. * - * @param {string} filter A filter expression over experiment attributes and tags that allows returning a subset of experiments - * The syntax is a subset of SQL. (required) + * @param {string} filter A filter expression over experiment attributes and tags that allows returning a subset of experiments. The syntax is a subset of SQL. (required) * @param {int64} max_results Maximum number of experiments desired. (required) * @param {string} page_token Optional token indicating the page of experiments to fetch. * @param {Array} order_by Optional list of columns for ordering search results. - * @param {string} view_type Optional qualifier for type of experiments to be returned. - * See https://mlflow.org/docs/latest/rest-api.html#mlflowviewtype + * @param {string} view_type Optional qualifier for type of experiments to be returned. See https://mlflow.org/docs/latest/rest-api.html#mlflowviewtype * @returns {Promise} Returns object containing an array of experiment objects matching the filter, * and optionally a next_page_token that can be used to retrieve the next page of experiments. */ @@ -279,231 +276,4 @@ class ExperimentClient { } } -export { ExperimentClient }; - - - - - - - - - - /** - * Full workflow of creating, naming and starting a run under an experiment (referenced by ID), - * logging metrics, params, and tags, logging the model, and finishing the run. - * - * @param {string} experiment_id ID of the experiment under which to log the run. (required) - * @param {string} run_name Name of the run to be created and run (optional) - * @param {Array<{key: string, value: number, timestamp: number, step?: number}>} [metrics] The metrics to log (up to 1000 metrics) (optional) - * @param {Array<{key: string, value: string}>} [params] The params to log (up to 100 params) (optional) - * @param {Array<{key: string, value: string}>} [tags=[]] The tags to log (up to 100 tags) (optional) - * @param {Object} model The ML model data to log to the run, represented as a Javascript object - * @returns {Promise} The created run object with updated metadata - */ - async function withStartExperimentRunByExperimentId( - experiment_id, - run_name = null, - metrics = [], - params = [], - tags = [], - model - ) { - if (!experiment_id) { - throw new Error('Experiment ID is required'); - } - - // create run - const run = await runManagement.createRun(experiment_id, run_name, tags); - const run_id = run.info.run_id; - - // log metric, params, and tags via logBatch - await runManagement.logBatch(run_id, metrics, params, tags); - - // log model - // (model gets passed in as a JS object, not JSON - it gets JSON stringified here after adding a run_id property) - model.run_id = run_id; - let model_json = JSON.stringify(model); - await runManagement.logModel(run_id, model_json); - - // updateRun to finish it - const latestRun = await runManagement.updateRun(run_id, 'FINISHED'); - - return latestRun; - } - - // test **************************************************************************************************************************************** - const testWithStartExperimentRunByExperimentId = async () => { - const metrics = [ - { key: 'metric1', value: 0.111, timestamp: Date.now() }, - { key: 'metric2', value: 0.222, timestamp: Date.now() }, - ]; - const params = [ - { key: 'testParam', value: 'testParamValue' }, - { key: 'testParam2', value: 'testParamValue2' }, - ]; - const tags = [ - { key: 'testKey', value: 'testValue' }, - { key: 'testKey2', value: 'testValue2' }, - ]; - const model = { - artifact_path: 'model', - flavors: { - python_function: { - model_path: 'model.pkl', - loader_module: 'mlflow.sklearn', - python_version: '3.8.10', - }, - }, - model_url: 'STRING', - model_uuid: 'STRING', - utc_time_created: Date.now(), - mlflow_version: 'STRING', - }; - const log = await withStartExperimentRunByExperimentId( - '977566317259111173', - undefined, - metrics, - params, - tags, - model - ); - return console.log(log); - }; - // uncomment below --- - // testWithStartExperimentRunByExperimentId(); - - /** - * Full workflow of creating, naming and starting a run under an experiment (referenced by name), - * logging metrics, params, and tags, logging the model, and finishing the run. - * - * @param {string} experiment_name Name of the experiment under which to log the run. (required) - * @param {string} run_name Name of the run to be created and run (optional) - * @param {Array<{key: string, value: number, timestamp: number, step?: number}>} [metrics] The metrics to log (up to 1000 metrics) (optional) - * @param {Array<{key: string, value: string}>} [params] The params to log (up to 100 params) (optional) - * @param {Array<{key: string, value: string}>} [tags=[]] The tags to log (up to 100 tags) (optional) - * @param {Object} model The ML model data to log to the run, represented as a Javascript object - * @returns {Promise} The created run object with updated metadata - */ - async function withStartExperimentRunByExperimentName( - experiment_name, - run_name = null, - metrics = [], - params = [], - tags = [], - model - ) { - if (!experiment_name) { - throw new Error('Experiment name is required'); - } - - let experiment_id; - try { - const exp = await getExperimentByName(experiment_name); - experiment_id = exp.experiment_id; - } catch { - experiment_id = await createExperiment(experiment_name); - } - - // create run - const run = await runManagement.createRun(experiment_id, run_name, tags); - const run_id = run.info.run_id; - - // log metric, params, and tags via logBatch - await runManagement.logBatch(run_id, metrics, params, tags); - - // log model - // (model gets passed in as a JS object, not JSON - it gets JSON stringified here after adding a run_id property) - model.run_id = run_id; - let model_json = JSON.stringify(model); - await runManagement.logModel(run_id, model_json); - - // updateRun to finish it - const latest_run = await runManagement.updateRun(run_id, 'FINISHED'); - - return latest_run; - } - - // test **************************************************************************************************************************************** - const testWithStartExperimentRunByExperimentName = async () => { - const metrics = [ - { key: 'metric1', value: 0.9, timestamp: Date.now() }, - { key: 'metric2', value: 0.222, timestamp: Date.now() }, - ]; - const params = [ - { key: 'testParam', value: 'testParamValue' }, - { key: 'testParam2', value: 'testParamValue2' }, - ]; - const tags = [ - { key: 'testKey', value: 'testValue' }, - { key: 'testKey2', value: 'testValue2' }, - ]; - const model = { - artifact_path: 'model', - flavors: { - python_function: { - model_path: 'model.pkl', - loader_module: 'mlflow.sklearn', - python_version: '3.8.10', - }, - }, - model_url: 'STRING', - model_uuid: 'STRING', - utc_time_created: Date.now(), - mlflow_version: 'STRING', - }; - const log = await withStartExperimentRunByExperimentName( - 'experimentSummary test', - undefined, - metrics, - params, - tags, - model - ); - return console.log(log); - }; - // uncomment below --- - // testWithStartExperimentRunByExperimentName(); - - /** - * Returns an array of all the passed-in experiment's runs, sorted according to the passed-in metric - * - * @param {string} experiment_id The experiment whose runs will be evaluated (required) - * @param {string} primaryMetric The metric by which the results array will be sorted - * @param {string | number} order Sort order for the array: pass in 'DESC' or 1 for descending; 'ASC' or -1 for ascending - * @returns Promise> An array of run objects belonging to the passed-in experiment ID, sorted according to the primary metric - */ - async function experimentSummary(experiment_id, primaryMetric, order) { - // use Search Runs to return all runs whose experiment ID matches the passed in one - // use Search Runs's order_by field to sort results array by primaryMetric - let orderString; - if (order === 1 || order === 'DESC') orderString = 'DESC'; - else if (order === -1 || order === 'ASC') orderString = 'ASC'; - const arg = `metrics.${primaryMetric} ${orderString}`; - const data = await runManagement.searchRuns( - [experiment_id], - undefined, - undefined, - undefined, - [arg] - ); - return data.runs; - } - - // test **************************************************************************************************************************************** - const testExperimentSummary = async () => { - const log = await experimentSummary('787867007534323476', 'metric1', 'ASC'); - return console.log(log); - }; - // uncomment below --- - // testExperimentSummary(); - - - - - -const MLFLOW_TRACKING_URI = 'http://localhost:5001/api/2.0/mlflow'; -import { RunManagement } from './run_management.js'; -const path = 'artifacts'; -const runManagement = new RunManagement('http://localhost:5001', path); - +export { ExperimentClient }; \ No newline at end of file diff --git a/mlflow/src/workflows/ExperimentManager.js b/mlflow/src/workflows/ExperimentManager.js new file mode 100644 index 00000000..edeba555 --- /dev/null +++ b/mlflow/src/workflows/ExperimentManager.js @@ -0,0 +1,132 @@ +import { ExperimentClient } from '../tracking_server/ExperimentClient.js'; +import { RunManagement } from '../tracking_server/run_management.js'; +const MLFLOW_TRACKING_URI = 'http://localhost:5001'; +const experimentClient = new ExperimentClient(MLFLOW_TRACKING_URI); +const runManagement = new RunManagement(MLFLOW_TRACKING_URI); + +class ExperimentManager { + constructor(trackingUri) { + this.trackingUri = trackingUri; + } + + /** + * Full workflow of creating, naming and starting a run under an experiment (referenced by ID), + * logging metrics, params, and tags, logging the model, and finishing the run. + * + * @param {string} experiment_id ID of the experiment under which to log the run. (required) + * @param {string} run_name Name of the run to be created and run (optional) + * @param {Array<{key: string, value: number, timestamp: number, step?: number}>} [metrics] The metrics to log (up to 1000 metrics) (optional) + * @param {Array<{key: string, value: string}>} [params] The params to log (up to 100 params) (optional) + * @param {Array<{key: string, value: string}>} [tags] The tags to log (up to 100 tags) (optional) + * @param {Object} model The ML model data to log to the run, represented as a Javascript object (optional) + * @returns {Promise} The created run object with updated metadata + */ + async withStartExperimentRunByExperimentId( + experiment_id, + run_name = null, + metrics = [], + params = [], + tags = [], + model + ) { + if (!experiment_id) { + throw new Error('Experiment ID is required'); + } + + // create run + const run = await runManagement.createRun(experiment_id, run_name, tags); + const run_id = run.info.run_id; + + // log metric, params, and tags via logBatch + await runManagement.logBatch(run_id, metrics, params, tags); + + // log model + // (model gets passed in as a JS object, not JSON - it gets JSON stringified here after adding a run_id property) + model.run_id = run_id; + let model_json = JSON.stringify(model); + await runManagement.logModel(run_id, model_json); + + // updateRun to finish it + const latestRun = await runManagement.updateRun(run_id, 'FINISHED'); + + return latestRun; + } + + /** + * Full workflow of creating, naming and starting a run under an experiment (referenced by name), + * logging metrics, params, and tags, logging the model, and finishing the run. + * + * @param {string} experiment_name Name of the experiment under which to log the run. (required) + * @param {string} run_name Name of the run to be created and run (optional) + * @param {Array<{key: string, value: number, timestamp: number, step?: number}>} [metrics] The metrics to log (up to 1000 metrics) (optional) + * @param {Array<{key: string, value: string}>} [params] The params to log (up to 100 params) (optional) + * @param {Array<{key: string, value: string}>} [tags] The tags to log (up to 100 tags) (optional) + * @param {Object} model The ML model data to log to the run, represented as a Javascript object (optional) + * @returns {Promise} The created run object with updated metadata + */ + async withStartExperimentRunByExperimentName( + experiment_name, + run_name = null, + metrics = [], + params = [], + tags = [], + model + ) { + if (!experiment_name) { + throw new Error('Experiment name is required'); + } + + let experiment_id; + try { + const exp = await experimentClient.getExperimentByName(experiment_name); + experiment_id = exp.experiment_id; + } catch { + experiment_id = await experimentClient.createExperiment(experiment_name); + } + + // create run + const run = await runManagement.createRun(experiment_id, run_name, tags); + const run_id = run.info.run_id; + + // log metric, params, and tags via logBatch + await runManagement.logBatch(run_id, metrics, params, tags); + + // log model + // (model gets passed in as a JS object, not JSON - it gets JSON stringified here after adding a run_id property) + model.run_id = run_id; + let model_json = JSON.stringify(model); + await runManagement.logModel(run_id, model_json); + + // updateRun to finish it + const latest_run = await runManagement.updateRun(run_id, 'FINISHED'); + + return latest_run; + } + + /** + * Returns an array of all the passed-in experiment's runs, sorted according to the passed-in metric + * + * @param {string} experiment_id The experiment whose runs will be evaluated (required) + * @param {string} primaryMetric The metric by which the results array will be sorted + * @param {string | number} order Sort order for the array: pass in 'DESC' or 1 for descending; 'ASC' or -1 for ascending + * @returns Promise> An array of run objects belonging to the passed-in experiment ID, sorted according to the primary metric + */ + async experimentSummary(experiment_id, primaryMetric, order) { + // use Search Runs to return all runs whose experiment ID matches the passed in one + // use Search Runs's order_by field to sort results array by primaryMetric + let orderString; + if (order === 1 || order === 'DESC') orderString = 'DESC'; + else if (order === -1 || order === 'ASC') orderString = 'ASC'; + const arg = `metrics.${primaryMetric} ${orderString}`; + const data = await runManagement.searchRuns( + [experiment_id], + undefined, + undefined, + undefined, + [arg] + ); + return data.runs; + } +} + +export { ExperimentManager }; \ No newline at end of file From 9e0c1c9117175b1bb292eeff6883cfd4bb8b59b6 Mon Sep 17 00:00:00 2001 From: Yiqun Zheng Date: Wed, 11 Sep 2024 10:53:39 -0700 Subject: [PATCH 057/357] modified package.json, created new files and dirs --- .../modelRegistry.ts => lib/index.ts} | 0 mlflow/package-lock.json | 223 ++++++++++++++++++ mlflow/package.json | 19 +- mlflow/src/MLflow.ts | 0 mlflow/src/index.ts | 0 .../src/model_registry/ModelRegistryClient.ts | 69 ++++++ mlflow/src/model_registry/model_registry.js | 8 +- .../src/utils/{apiClient.ts => ApiRequest.ts} | 4 +- ...stryTest.js => ModelRegistryClientTest.js} | 2 +- mlflow/{src/tracking_server => tests}/test.js | 23 +- .../{src/tracking_server => tests}/testing.js | 0 mlflow/tsconfig.json | 4 +- 12 files changed, 324 insertions(+), 28 deletions(-) rename mlflow/{src/model_registry/modelRegistry.ts => lib/index.ts} (100%) create mode 100644 mlflow/src/MLflow.ts create mode 100644 mlflow/src/index.ts create mode 100644 mlflow/src/model_registry/ModelRegistryClient.ts rename mlflow/src/utils/{apiClient.ts => ApiRequest.ts} (94%) rename mlflow/tests/{modelRegistryTest.js => ModelRegistryClientTest.js} (96%) rename mlflow/{src/tracking_server => tests}/test.js (80%) rename mlflow/{src/tracking_server => tests}/testing.js (100%) diff --git a/mlflow/src/model_registry/modelRegistry.ts b/mlflow/lib/index.ts similarity index 100% rename from mlflow/src/model_registry/modelRegistry.ts rename to mlflow/lib/index.ts diff --git a/mlflow/package-lock.json b/mlflow/package-lock.json index 4f1c429b..89eb916c 100644 --- a/mlflow/package-lock.json +++ b/mlflow/package-lock.json @@ -7,7 +7,230 @@ "": { "name": "mlflow", "version": "1.0.0", + "license": "MIT", + "devDependencies": { + "@types/node": "^22.5.4", + "ts-node": "^10.9.2", + "typescript": "^5.6.2" + } + }, + "node_modules/@cspotcode/source-map-support": { + "version": "0.8.1", + "resolved": "https://registry.npmjs.org/@cspotcode/source-map-support/-/source-map-support-0.8.1.tgz", + "integrity": "sha512-IchNf6dN4tHoMFIn/7OE8LWZ19Y6q/67Bmf6vnGREv8RSbBVb9LPJxEcnwrcwX6ixSvaiGoomAUvu4YSxXrVgw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jridgewell/trace-mapping": "0.3.9" + }, + "engines": { + "node": ">=12" + } + }, + "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, + "license": "MIT", + "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, "license": "MIT" + }, + "node_modules/@jridgewell/trace-mapping": { + "version": "0.3.9", + "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.9.tgz", + "integrity": "sha512-3Belt6tdc8bPgAtbcmdtNJlirVoTmEb5e2gC94PnkwEW9jI6CAHUeoG85tjWP5WquqfavoMtMwiG4P926ZKKuQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jridgewell/resolve-uri": "^3.0.3", + "@jridgewell/sourcemap-codec": "^1.4.10" + } + }, + "node_modules/@tsconfig/node10": { + "version": "1.0.11", + "resolved": "https://registry.npmjs.org/@tsconfig/node10/-/node10-1.0.11.tgz", + "integrity": "sha512-DcRjDCujK/kCk/cUe8Xz8ZSpm8mS3mNNpta+jGCA6USEDfktlNvm1+IuZ9eTcDbNk41BHwpHHeW+N1lKCz4zOw==", + "dev": true, + "license": "MIT" + }, + "node_modules/@tsconfig/node12": { + "version": "1.0.11", + "resolved": "https://registry.npmjs.org/@tsconfig/node12/-/node12-1.0.11.tgz", + "integrity": "sha512-cqefuRsh12pWyGsIoBKJA9luFu3mRxCA+ORZvA4ktLSzIuCUtWVxGIuXigEwO5/ywWFMZ2QEGKWvkZG1zDMTag==", + "dev": true, + "license": "MIT" + }, + "node_modules/@tsconfig/node14": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/@tsconfig/node14/-/node14-1.0.3.tgz", + "integrity": "sha512-ysT8mhdixWK6Hw3i1V2AeRqZ5WfXg1G43mqoYlM2nc6388Fq5jcXyr5mRsqViLx/GJYdoL0bfXD8nmF+Zn/Iow==", + "dev": true, + "license": "MIT" + }, + "node_modules/@tsconfig/node16": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/@tsconfig/node16/-/node16-1.0.4.tgz", + "integrity": "sha512-vxhUy4J8lyeyinH7Azl1pdd43GJhZH/tP2weN8TntQblOY+A0XbT8DJk1/oCPuOOyg/Ja757rG0CgHcWC8OfMA==", + "dev": true, + "license": "MIT" + }, + "node_modules/@types/node": { + "version": "22.5.4", + "resolved": "https://registry.npmjs.org/@types/node/-/node-22.5.4.tgz", + "integrity": "sha512-FDuKUJQm/ju9fT/SeX/6+gBzoPzlVCzfzmGkwKvRHQVxi4BntVbyIwf6a4Xn62mrvndLiml6z/UBXIdEVjQLXg==", + "dev": true, + "license": "MIT", + "dependencies": { + "undici-types": "~6.19.2" + } + }, + "node_modules/acorn": { + "version": "8.12.1", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.12.1.tgz", + "integrity": "sha512-tcpGyI9zbizT9JbV6oYE477V6mTlXvvi0T0G3SNIYE2apm/G5huBa1+K89VGeovbg+jycCrfhl3ADxErOuO6Jg==", + "dev": true, + "license": "MIT", + "bin": { + "acorn": "bin/acorn" + }, + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/acorn-walk": { + "version": "8.3.4", + "resolved": "https://registry.npmjs.org/acorn-walk/-/acorn-walk-8.3.4.tgz", + "integrity": "sha512-ueEepnujpqee2o5aIYnvHU6C0A42MNdsIDeqy5BydrkuC5R1ZuUFnm27EeFJGoEHJQgn3uleRvmTXaJgfXbt4g==", + "dev": true, + "license": "MIT", + "dependencies": { + "acorn": "^8.11.0" + }, + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/arg": { + "version": "4.1.3", + "resolved": "https://registry.npmjs.org/arg/-/arg-4.1.3.tgz", + "integrity": "sha512-58S9QDqG0Xx27YwPSt9fJxivjYl432YCwfDMfZ+71RAqUrZef7LrKQZ3LHLOwCS4FLNBplP533Zx895SeOCHvA==", + "dev": true, + "license": "MIT" + }, + "node_modules/create-require": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/create-require/-/create-require-1.1.1.tgz", + "integrity": "sha512-dcKFX3jn0MpIaXjisoRvexIJVEKzaq7z2rZKxf+MSr9TkdmHmsU4m2lcLojrj/FHl8mk5VxMmYA+ftRkP/3oKQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/diff": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/diff/-/diff-4.0.2.tgz", + "integrity": "sha512-58lmxKSA4BNyLz+HHMUzlOEpg09FV+ev6ZMe3vJihgdxzgcwZ8VoEEPmALCZG9LmqfVoNMMKpttIYTVG6uDY7A==", + "dev": true, + "license": "BSD-3-Clause", + "engines": { + "node": ">=0.3.1" + } + }, + "node_modules/make-error": { + "version": "1.3.6", + "resolved": "https://registry.npmjs.org/make-error/-/make-error-1.3.6.tgz", + "integrity": "sha512-s8UhlNe7vPKomQhC1qFelMokr/Sc3AgNbso3n74mVPA5LTZwkB9NlXf4XPamLxJE8h0gh73rM94xvwRT2CVInw==", + "dev": true, + "license": "ISC" + }, + "node_modules/ts-node": { + "version": "10.9.2", + "resolved": "https://registry.npmjs.org/ts-node/-/ts-node-10.9.2.tgz", + "integrity": "sha512-f0FFpIdcHgn8zcPSbf1dRevwt047YMnaiJM3u2w2RewrB+fob/zePZcrOyQoLMMO7aBIddLcQIEK5dYjkLnGrQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@cspotcode/source-map-support": "^0.8.0", + "@tsconfig/node10": "^1.0.7", + "@tsconfig/node12": "^1.0.7", + "@tsconfig/node14": "^1.0.0", + "@tsconfig/node16": "^1.0.2", + "acorn": "^8.4.1", + "acorn-walk": "^8.1.1", + "arg": "^4.1.0", + "create-require": "^1.1.0", + "diff": "^4.0.1", + "make-error": "^1.1.1", + "v8-compile-cache-lib": "^3.0.1", + "yn": "3.1.1" + }, + "bin": { + "ts-node": "dist/bin.js", + "ts-node-cwd": "dist/bin-cwd.js", + "ts-node-esm": "dist/bin-esm.js", + "ts-node-script": "dist/bin-script.js", + "ts-node-transpile-only": "dist/bin-transpile.js", + "ts-script": "dist/bin-script-deprecated.js" + }, + "peerDependencies": { + "@swc/core": ">=1.2.50", + "@swc/wasm": ">=1.2.50", + "@types/node": "*", + "typescript": ">=2.7" + }, + "peerDependenciesMeta": { + "@swc/core": { + "optional": true + }, + "@swc/wasm": { + "optional": true + } + } + }, + "node_modules/typescript": { + "version": "5.6.2", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.6.2.tgz", + "integrity": "sha512-NW8ByodCSNCwZeghjN3o+JX5OFH0Ojg6sadjEKY4huZ52TqbJTJnDo5+Tw98lSy63NZvi4n+ez5m2u5d4PkZyw==", + "dev": true, + "license": "Apache-2.0", + "bin": { + "tsc": "bin/tsc", + "tsserver": "bin/tsserver" + }, + "engines": { + "node": ">=14.17" + } + }, + "node_modules/undici-types": { + "version": "6.19.8", + "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-6.19.8.tgz", + "integrity": "sha512-ve2KP6f/JnbPBFyobGHuerC9g1FYGn/F8n1LWTwNxCEzd6IfqTwUQcNXgEtmmQ6DlRrC1hrSrBnCZPokRrDHjw==", + "dev": true, + "license": "MIT" + }, + "node_modules/v8-compile-cache-lib": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/v8-compile-cache-lib/-/v8-compile-cache-lib-3.0.1.tgz", + "integrity": "sha512-wa7YjyUGfNZngI/vtK0UHAN+lgDCxBPCylVXGp0zu59Fz5aiGtNXaq3DhIov063MorB+VfufLh3JlF2KdTK3xg==", + "dev": true, + "license": "MIT" + }, + "node_modules/yn": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/yn/-/yn-3.1.1.tgz", + "integrity": "sha512-Ux4ygGWsu2c7isFWe8Yu1YluJmqVhxqK2cLXNQA5AcC3QfbGNpM7fu0Y8b/z16pXLnFxZYvWhd3fhBY9DLmC6Q==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6" + } } } } diff --git a/mlflow/package.json b/mlflow/package.json index 40ff170d..cc7248c6 100644 --- a/mlflow/package.json +++ b/mlflow/package.json @@ -1,16 +1,27 @@ { "name": "mlflow", "version": "1.0.0", + "description": "JavaScript/Typescript library for MLflow", + "main": "lib/index.js", "type": "module", - "description": "JavaScript library for MLflow", - "main": "", + "types": "lib/index.d.ts", "scripts": { + "build": "tsc", "test": "echo \"Error: no test specified\" && exit 1" }, "keywords": [ "mlflow", - "machine learning" + "machine learning", + "typescript" ], "author": "", - "license": "MIT" + "license": "MIT", + "devDependencies": { + "@types/node": "^22.5.4", + "ts-node": "^10.9.2", + "typescript": "^5.6.2" + }, + "engines": { + "node": ">=22.7.0" + } } diff --git a/mlflow/src/MLflow.ts b/mlflow/src/MLflow.ts new file mode 100644 index 00000000..e69de29b diff --git a/mlflow/src/index.ts b/mlflow/src/index.ts new file mode 100644 index 00000000..e69de29b diff --git a/mlflow/src/model_registry/ModelRegistryClient.ts b/mlflow/src/model_registry/ModelRegistryClient.ts new file mode 100644 index 00000000..a5c0817f --- /dev/null +++ b/mlflow/src/model_registry/ModelRegistryClient.ts @@ -0,0 +1,69 @@ +import apiRequest from '../utils/ApiRequest'; + +class ModelRegistryClient { + private baseUrl: string; + + constructor(trackingUri: string) { + this.baseUrl = trackingUri; + } + + /** + * Creates a new registered model. + * + * @param name - The name of the model to register (required) + * @param tags - Optional An array of RegisteredModelTag. Each tag is an object with 'key' and 'value' properties. + * @param description - Optional description for the model + * @returns The created registered model object + * @throws Error - If the API request fails + */ + async createRegisteredModel( + name: string, + tags: Array<{ key: string; value: string }> = [], + description: string = '' + ): Promise { + const { response, data } = await apiRequest( + this.baseUrl, + 'registered-models/create', + { + method: 'POST', + body: { name, tags, description }, + } + ); + + if (!response.ok) { + throw new Error( + `Error creating registered model: ${ + data.message || response.statusText + }` + ); + } + + return data.registered_model; + } + + /** + * Gets a registered model. + * + * @param name - The name of the registered model to retrieve (required) + * @returns The registered model object + */ + async getRegisteredModel(name: string): Promise { + const { response, data } = await apiRequest( + this.baseUrl, + 'registered-models/get', + { + method: 'GET', + params: { name }, + } + ); + + if (!response.ok) { + throw new Error( + `Error getting registered model: ${data.message || response.statusText}` + ); + } + return data.registered_model; + } +} + +export default ModelRegistryClient; diff --git a/mlflow/src/model_registry/model_registry.js b/mlflow/src/model_registry/model_registry.js index 7fb5c571..397a32c5 100644 --- a/mlflow/src/model_registry/model_registry.js +++ b/mlflow/src/model_registry/model_registry.js @@ -335,15 +335,9 @@ class ModelRegistry { const data = await response.json(); if (!response.ok) { -<<<<<<< HEAD - throw new Error(`Error setting model alias: ${response.statusText}`); -======= throw new Error( - `Error setting model alias: ${ - data.message || response.statusText - }` + `Error setting model alias: ${data.message || response.statusText}` ); ->>>>>>> dev } return data; } diff --git a/mlflow/src/utils/apiClient.ts b/mlflow/src/utils/ApiRequest.ts similarity index 94% rename from mlflow/src/utils/apiClient.ts rename to mlflow/src/utils/ApiRequest.ts index 49a682d0..9f062fd2 100644 --- a/mlflow/src/utils/apiClient.ts +++ b/mlflow/src/utils/ApiRequest.ts @@ -4,7 +4,7 @@ interface RequestOptions { params?: Record; } -interface ApiResponse { +interface ApiResponse { response: Response; data: T; } @@ -17,7 +17,7 @@ interface ApiResponse { * @param options - Request options * @returns A promise that resolves to the response and data */ -async function apiRequest( +async function apiRequest( baseUrl: string, endpoint: string, options: RequestOptions diff --git a/mlflow/tests/modelRegistryTest.js b/mlflow/tests/ModelRegistryClientTest.js similarity index 96% rename from mlflow/tests/modelRegistryTest.js rename to mlflow/tests/ModelRegistryClientTest.js index 14ee0c88..cff11936 100644 --- a/mlflow/tests/modelRegistryTest.js +++ b/mlflow/tests/ModelRegistryClientTest.js @@ -1,5 +1,5 @@ // usage_example.js -import { ModelRegistry } from '../src/model_registry/model_registry.js'; +import { ModelRegistryClient } from '../src/model_registry/ModelRegistryClient.ts'; async function main() { const trackingUri = 'http://localhost:5001'; diff --git a/mlflow/src/tracking_server/test.js b/mlflow/tests/test.js similarity index 80% rename from mlflow/src/tracking_server/test.js rename to mlflow/tests/test.js index 7b09c14c..9d89127a 100644 --- a/mlflow/src/tracking_server/test.js +++ b/mlflow/tests/test.js @@ -1,6 +1,6 @@ -import { RunManagement } from "./run_management.js"; +import { RunManagement } from '../src/tracking_server/run_management.js'; -let domain = 'http://localhost:' +let domain = 'http://localhost:'; const port = 5001; if (port) { domain = domain + port; @@ -16,14 +16,14 @@ let runManagement = new RunManagement(MLFLOW_TRACKING_URI, path); // console.log(runManagement.searchRuns(['784321942139901150'])); const test = async () => { - // console.log('hi'); - try { - let data = await runManagement.searchRuns(['784321942139901150']); - console.log('data: ', data); - } catch (err) { - console.log('err: ', err); - } -} + // console.log('hi'); + try { + let data = await runManagement.searchRuns(['784321942139901150']); + console.log('data: ', data); + } catch (err) { + console.log('err: ', err); + } +}; test(); @@ -37,8 +37,7 @@ test(); // console.log(runManagement.setTag('b3457c87f50440388da9d9ddabb1baaa', 'testTag1', 'testTag1Val')) // console.log(runManagement.deleteTag('b3457c87f50440388da9d9ddabb1baaa', 'testTag1')) - // let modelRegistry = new ModelRegistry(MLFLOW_TRACKING_URI); // console.log(modelRegistry.setRegisteredModelAlias('tracking-quickstart', 'aliasTest', '1')); // console.log(modelRegistry.deleteRegisteredModelAlias('tracking-quickstart', 'aliasTest')); -// console.log(modelRegistry.getModelVersionByAlias('sk-learn-random-forest-reg-model', 'the_best_model_ever')); \ No newline at end of file +// console.log(modelRegistry.getModelVersionByAlias('sk-learn-random-forest-reg-model', 'the_best_model_ever')); diff --git a/mlflow/src/tracking_server/testing.js b/mlflow/tests/testing.js similarity index 100% rename from mlflow/src/tracking_server/testing.js rename to mlflow/tests/testing.js diff --git a/mlflow/tsconfig.json b/mlflow/tsconfig.json index 97bc5606..0653c12c 100644 --- a/mlflow/tsconfig.json +++ b/mlflow/tsconfig.json @@ -7,9 +7,9 @@ "forceConsistentCasingInFileNames": true, "moduleResolution": "node", "resolveJsonModule": true, - "outDir": "./dist", + "outDir": "./lib", "rootDir": "./src" }, - "include": ["src/**/*.ts", "src/**/*.tsx"], + "include": ["src/**/*.ts", "src/**/*.tsx", "tests/**/*"], "exclude": ["node_modules"] } From 6f4fa8cecf2cb1d30e66da0f622ee0864e1a79b0 Mon Sep 17 00:00:00 2001 From: Stephany Ho Date: Wed, 11 Sep 2024 15:59:20 -0400 Subject: [PATCH 058/357] Add moveRun abstraction method --- .../abstraction/abstraction_run_management.js | 71 ------ mlflow/src/tracking_server/run_management.js | 36 ++- mlflow/src/workflows/RunManager.js | 213 ++++++++++++++++++ .../src/{abstraction => workflows}/testing.js | 21 +- 4 files changed, 257 insertions(+), 84 deletions(-) delete mode 100644 mlflow/src/abstraction/abstraction_run_management.js create mode 100644 mlflow/src/workflows/RunManager.js rename mlflow/src/{abstraction => workflows}/testing.js (66%) diff --git a/mlflow/src/abstraction/abstraction_run_management.js b/mlflow/src/abstraction/abstraction_run_management.js deleted file mode 100644 index b02da4c1..00000000 --- a/mlflow/src/abstraction/abstraction_run_management.js +++ /dev/null @@ -1,71 +0,0 @@ -import { RunManagement } from '../tracking_server/run_management.js'; - -class Abstraction { - constructor(trackingUri) { - this.trackingUri = trackingUri; - this.RunManagement = new RunManagement(this.trackingUri); - } - - /** - * Delete runs that do not meet certain criteria and return the deleted runs. - * - * @param {string[]} experimentIds - The IDs of the associated experiments. (required) - * @param {string} queryString - SQL-like query string to filter runs to keep. (required) - * @param {boolean} [dryRun=true] - If true, only simulate the deletion. Defaults to true. (optional) - * @returns {Promise} - An object of deleted runs. - */ - async runCleanup(experimentIds, queryString, dryRun = true) { - const deletedRuns = []; - let pageToken = null; - const maxResults = 1000; - - try { - do { - // get all runs - const searchResult = await this.RunManagement.searchRuns( - experimentIds, - '', - null, // run_view_type - maxResults, - ['start_time DESC'], - pageToken - ); - - // get runs that match the keep crteria - const keepResult = await this.RunManagement.searchRuns( - experimentIds, - queryString, - null, // run_view_type - maxResults, - ['start_time DESC'], - pageToken - ); - - // create a Set of run IDs to keep for efficient lookup - const keepRunIds = new Set( - keepResult.runs.map((run) => run.info.run_id) - ); - - // check for runs that are not in keepRunIds - // if dryRun is false, delete from database, push to deletedRuns array - // if dryRun is true, push to deletedRuns array - for (const run of searchResult.runs || []) { - if (!keepRunIds.has(run.info.run_id)) { - if (!dryRun) { - await this.RunManagement.deleteRun(run.info.run_id); - } - deletedRuns.push(run); - } - } - - pageToken = searchResult.page_token; - } while (pageToken); - } catch (error) { - console.error('Error during run cleanup: ', error); - throw new Error('Failed to cleanup runs.'); - } - return { deletedRuns, total: deletedRuns.length, dryRun }; - } -} - -export { Abstraction }; diff --git a/mlflow/src/tracking_server/run_management.js b/mlflow/src/tracking_server/run_management.js index cad8dc3e..c4d38fdf 100644 --- a/mlflow/src/tracking_server/run_management.js +++ b/mlflow/src/tracking_server/run_management.js @@ -67,7 +67,9 @@ class RunManagement { }); if (!response.ok) { - throw new Error(`Error in deleting run: ${data.message || response.statusText}`); + throw new Error( + `Error in deleting run: ${data.message || response.statusText}` + ); } return await response.json(); @@ -93,7 +95,9 @@ class RunManagement { }); if (!response.ok) { - throw new Error(`Error in restoring run: ${data.message || response.statusText}`); + throw new Error( + `Error in restoring run: ${data.message || response.statusText}` + ); } return await response.json(); @@ -190,7 +194,9 @@ class RunManagement { }); if (!response.ok) { - throw new Error(`Error in logging metric: ${data.message || response.statusText}`); + throw new Error( + `Error in logging metric: ${data.message || response.statusText}` + ); } return await response.json(); @@ -226,7 +232,9 @@ class RunManagement { if (!response.ok) { const responseBody = await response.text(); console.error(`Response body: ${responseBody}`); - throw new Error(`Error in logging batch: ${data.message || response.statusText}`); + throw new Error( + `Error in logging batch: ${data.message || response.statusText}` + ); } return await response.json(); @@ -253,7 +261,9 @@ class RunManagement { }); if (!response.ok) { - throw new Error(`Error in logging model: ${data.message || response.statusText}`); + throw new Error( + `Error in logging model: ${data.message || response.statusText}` + ); } return await response.json(); @@ -281,7 +291,9 @@ class RunManagement { }); if (!response.ok) { - throw new Error(`Error in logging inputs: ${data.message || response.statusText}`); + throw new Error( + `Error in logging inputs: ${data.message || response.statusText}` + ); } return await response.json(); @@ -317,7 +329,9 @@ class RunManagement { const data = await response.json(); if (!response.ok) { - throw new Error(`Error logging param: ${data.message || response.statusText}`); + throw new Error( + `Error logging param: ${data.message || response.statusText}` + ); } return data; } @@ -347,7 +361,9 @@ class RunManagement { const data = await response.json(); if (!response.ok) { - throw new Error(`Error logging param: ${data.message || response.statusText}`); + throw new Error( + `Error logging param: ${data.message || response.statusText}` + ); } return data; } @@ -379,7 +395,9 @@ class RunManagement { const data = await response.json(); if (!response.ok) { - throw new Error(`Error logging param: ${data.message || response.statusText}`); + throw new Error( + `Error logging param: ${data.message || response.statusText}` + ); } return data; } diff --git a/mlflow/src/workflows/RunManager.js b/mlflow/src/workflows/RunManager.js new file mode 100644 index 00000000..b1c7270c --- /dev/null +++ b/mlflow/src/workflows/RunManager.js @@ -0,0 +1,213 @@ +import { RunManagement } from '../tracking_server/run_management.js'; +import { ModelVersionManagement } from '../model_registry/model_version_management.js'; + +class Abstraction { + constructor(trackingUri) { + this.trackingUri = trackingUri; + this.RunManagement = new RunManagement(this.trackingUri); + this.ModelVersionManagement = new ModelVersionManagement(this.trackingUri); + } + + /** + * Delete runs that do not meet certain criteria and return the deleted runs. + * + * @param {string[]} experimentIds - The IDs of the associated experiments. (required) + * @param {string} queryString - SQL-like query string to filter runs to keep. (required) + * @param {boolean} [dryRun=true] - If true, only simulate the deletion. Defaults to true. (optional) + * @returns {Promise} - An object of deleted runs. + */ + async runCleanup(experimentIds, queryString, dryRun = true) { + const deletedRuns = []; + let pageToken = null; + const maxResults = 1000; + + try { + do { + // get all runs + const searchResult = await this.RunManagement.searchRuns( + experimentIds, + '', + null, // run_view_type + maxResults, + ['start_time DESC'], + pageToken + ); + + // get runs that match the keep crteria + const keepResult = await this.RunManagement.searchRuns( + experimentIds, + queryString, + null, // run_view_type + maxResults, + ['start_time DESC'], + pageToken + ); + + // create a Set of run IDs to keep for efficient lookup + const keepRunIds = new Set( + keepResult.runs.map((run) => run.info.run_id) + ); + + // check for runs that are not in keepRunIds + // if dryRun is false, delete from database, push to deletedRuns array + // if dryRun is true, push to deletedRuns array + for (const run of searchResult.runs || []) { + if (!keepRunIds.has(run.info.run_id)) { + if (!dryRun) { + await this.RunManagement.deleteRun(run.info.run_id); + } + deletedRuns.push(run); + } + } + + pageToken = searchResult.page_token; + } while (pageToken); + } catch (error) { + console.error('Error during run cleanup: ', error); + throw new Error('Failed to cleanup runs.'); + } + return { deletedRuns, total: deletedRuns.length, dryRun }; + } + + /********************************************************************************************************** */ + + /** + * Move run from one experiment to another without artifactss and models. Artifacts and models detail tagged in new run as reference. + * + * @param {string} runId - The ID of the run to be moved. (required) + * @param {string} targetExperimentId - The ID of the target experiment. (required) + * @param {string} runName - The name of the new run in target experiment. (optional) + * @returns {Promise} - An object of move run detail. + */ + async moveRun(runId, targetExperimentId, runName = null) { + try { + // get original run + const originalRun = await this.RunManagement.getRun(runId); + + // create a new run in the target experiment + const newRun = await this.RunManagement.createRun( + targetExperimentId, + null, + originalRun.info.start_time + ); + + const newRunId = newRun.info.run_id; + + // copy run information + await this.RunManagement.updateRun(newRunId, originalRun.info.status); + if (originalRun.info.lifecycle_stage !== 'active') { + await this.RunManagement.setTag( + newRunId, + 'mlflow.lifecycleStage', + originalRun.info.lifecycle_stage + ); + } + + // copy parameters + if (originalRun.data.params) { + for (const param of originalRun.data.params) { + await this.RunManagement.logParam(newRunId, param.key, param.value); + } + } + + // copy metrics + if (originalRun.data.metrics) { + for (const metric of originalRun.data.metrics) { + await this.RunManagement.logMetric( + newRunId, + metric.key, + metric.value + ); + } + } + + // copy tags + if (originalRun.data.tags) { + for (const tag of originalRun.data.tags) { + await this.RunManagement.setTag(newRunId, tag.key, tag.value); + } + } + + // copy inputs + if ( + originalRun.inputs && + originalRun.inputs.dataset_inputs && + originalRun.inputs.dataset_inputs.length > 0 + ) { + // Log each dataset input separately + for (const datasetInput of originalRun.inputs.dataset_inputs) { + await this.RunManagement.logInputs(newRunId, [datasetInput]); + } + } + + // update the new run name + await this.RunManagement.setTag(newRunId, 'mlflow.runName', runName); + + // handle models (reference only) + const modelVersions = + await this.ModelVersionManagement.searchModelVersions( + `run_id = '${runId}'` + ); + if (modelVersions && modelVersions.length > 0) { + for (const model of modelVersions) { + await this.RunManagement.setTag( + newRunId, + `original_model_${model.name}`, + JSON.stringify({ + name: model.name, + version: model.version, + current_stage: model.current_stage, + source: model.source, + }) + ); + } + await this.RunManagement.setTag( + newRunId, + 'mlflow.note.models', + 'Models not moved -see original run' + ); + } + + // update the original run + await this.RunManagement.updateRun(runId, 'FINISHED', null, Date.now()); + + // set description for the new run + const description = + `This run was moved from experiment ${originalRun.info.experiment_id}, original run ID: ${runId}. ` + + `Original artifact URI: ${originalRun.info.artifact_uri}.`; + + await this.RunManagement.setTag( + newRunId, + 'mlflow.note.content', + description + ); + + // set additional tags for the new run + await this.RunManagement.setTag(newRunId, 'mlflow.source.run_id', runId); + + await this.RunManagement.setTag( + newRunId, + 'mlflow.source.experiment_id', + originalRun.info.experiment_id + ); + + await this.RunManagement.setTag( + newRunId, + 'mlflow.note.artifacts', + 'Artifacts not moved - reference original run' + ); + + // return object with move run details + return { + originalRunId: runId, + newRunId: newRunId, + targetExperimentId: targetExperimentId, + }; + } catch (error) { + console.error('Error moving run: ', error); + throw new Error('Failed to move run.'); + } + } +} + +export { Abstraction }; diff --git a/mlflow/src/abstraction/testing.js b/mlflow/src/workflows/testing.js similarity index 66% rename from mlflow/src/abstraction/testing.js rename to mlflow/src/workflows/testing.js index 68c447e8..56e65974 100644 --- a/mlflow/src/abstraction/testing.js +++ b/mlflow/src/workflows/testing.js @@ -1,4 +1,4 @@ -import { Abstraction } from './abstraction_run_management.js'; +import { Abstraction } from './RunManager.js'; import { RunManagement } from '../tracking_server/run_management.js'; const trackingUri = 'http://127.0.0.1:5000'; @@ -8,15 +8,15 @@ const path = '/api/2.0/mlflow'; const ab = new Abstraction(trackingUri); const myRunManagement = new RunManagement(trackingUri); -// // testing searchRuns method +// testing searchRuns method // const runs = await myRunManagement.searchRuns(['463611670721534538'], ''); // console.log('Search runs result: ', runs); // // dry run (simulation) // try { // const result = await ab.runCleanup( -// ['463611670721534538'], -// 'metrics.rmse > 2' +// ['284209273010848955'], +// 'metrics.accuracy > 0.9' // ); // console.log(result.deletedRuns); // } catch (error) { @@ -34,3 +34,16 @@ const myRunManagement = new RunManagement(trackingUri); // } catch (error) { // console.error('Error: ', error.message, error.stack); // } + +/************************************************************** */ + +// move run +// await ab.moveRun( +// 'c3178ac6ee414495b854361c95f9f517', +// '508915846877934148', +// 'meow' +// ); + +// check tags +// const run = await myRunManagement.getRun('c3178ac6ee414495b854361c95f9f517'); +// console.log(run.data.tags); From ead874f715da07bf5848bfc34ed8f14f7cb11455 Mon Sep 17 00:00:00 2001 From: Stephany Ho Date: Wed, 11 Sep 2024 19:14:17 -0400 Subject: [PATCH 059/357] Fix bug in RunManager.js --- mlflow/src/workflows/RunManager.js | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-) diff --git a/mlflow/src/workflows/RunManager.js b/mlflow/src/workflows/RunManager.js index b1c7270c..9fb3916e 100644 --- a/mlflow/src/workflows/RunManager.js +++ b/mlflow/src/workflows/RunManager.js @@ -141,7 +141,9 @@ class Abstraction { } // update the new run name - await this.RunManagement.setTag(newRunId, 'mlflow.runName', runName); + if (runName) { + await this.RunManagement.setTag(newRunId, 'mlflow.runName', runName); + } // handle models (reference only) const modelVersions = @@ -208,6 +210,17 @@ class Abstraction { throw new Error('Failed to move run.'); } } + + /********************************************************************************************************** */ + + /** + * Search runs and export run data to CSV. + * + * @param {string[]} experimentIds - The IDs of the associated experiments. (required) + * @param {string} queryString - SQL-like query string to filter runs to keep. (required) + * @returns {Promise} - An object of run datas in CSV format. + */ + async convertRunDataToCSV() {} } export { Abstraction }; From cbae81910114e36a33af58960486b31698994930 Mon Sep 17 00:00:00 2001 From: Austin Fraser Date: Wed, 11 Sep 2024 18:11:21 -0700 Subject: [PATCH 060/357] changed names to runExistingExperiment and runNewExperiment, changed functionality of runNewExperiment accordingly --- mlflow/src/workflows/ExperimentManager.js | 16 +++++----------- 1 file changed, 5 insertions(+), 11 deletions(-) diff --git a/mlflow/src/workflows/ExperimentManager.js b/mlflow/src/workflows/ExperimentManager.js index edeba555..273e2145 100644 --- a/mlflow/src/workflows/ExperimentManager.js +++ b/mlflow/src/workflows/ExperimentManager.js @@ -10,7 +10,7 @@ class ExperimentManager { } /** - * Full workflow of creating, naming and starting a run under an experiment (referenced by ID), + * Full workflow of creating, naming and starting a run under an existing experiment (referenced by ID), * logging metrics, params, and tags, logging the model, and finishing the run. * * @param {string} experiment_id ID of the experiment under which to log the run. (required) @@ -21,7 +21,7 @@ class ExperimentManager { * @param {Object} model The ML model data to log to the run, represented as a Javascript object (optional) * @returns {Promise} The created run object with updated metadata */ - async withStartExperimentRunByExperimentId( + async runExistingExperiment( experiment_id, run_name = null, metrics = [], @@ -53,7 +53,7 @@ class ExperimentManager { } /** - * Full workflow of creating, naming and starting a run under an experiment (referenced by name), + * Full workflow of creating, naming and starting a run under a new experiment, * logging metrics, params, and tags, logging the model, and finishing the run. * * @param {string} experiment_name Name of the experiment under which to log the run. (required) @@ -64,7 +64,7 @@ class ExperimentManager { * @param {Object} model The ML model data to log to the run, represented as a Javascript object (optional) * @returns {Promise} The created run object with updated metadata */ - async withStartExperimentRunByExperimentName( + async runNewExperiment( experiment_name, run_name = null, metrics = [], @@ -76,13 +76,7 @@ class ExperimentManager { throw new Error('Experiment name is required'); } - let experiment_id; - try { - const exp = await experimentClient.getExperimentByName(experiment_name); - experiment_id = exp.experiment_id; - } catch { - experiment_id = await experimentClient.createExperiment(experiment_name); - } + let experiment_id = await experimentClient.createExperiment(experiment_name); // create run const run = await runManagement.createRun(experiment_id, run_name, tags); From 0042c91f80857e9e4bf28e897eec7e9df1884049 Mon Sep 17 00:00:00 2001 From: Yiqun Zheng Date: Wed, 11 Sep 2024 19:40:31 -0700 Subject: [PATCH 061/357] modify config files and file structure --- mlflow/.gitignore | 5 +- mlflow/lib/index.ts | 0 mlflow/package-lock.json | 1061 ++++++++++++++++- mlflow/package.json | 17 +- mlflow/src/model_registry/model_registry.js | 2 +- mlflow/tests/ModelRegistryClientTest.ts | 25 + ...ryClientTest.js => model_registry_test.js} | 6 +- mlflow/tsconfig.json | 59 +- 8 files changed, 1152 insertions(+), 23 deletions(-) delete mode 100644 mlflow/lib/index.ts create mode 100644 mlflow/tests/ModelRegistryClientTest.ts rename mlflow/tests/{ModelRegistryClientTest.js => model_registry_test.js} (88%) diff --git a/mlflow/.gitignore b/mlflow/.gitignore index 00b26ccf..d9998bb7 100644 --- a/mlflow/.gitignore +++ b/mlflow/.gitignore @@ -6,4 +6,7 @@ node_modules/ # Python / MLflow specific .venv/ -mlruns/ \ No newline at end of file +mlruns/ + +# Temp +lib/ \ No newline at end of file diff --git a/mlflow/lib/index.ts b/mlflow/lib/index.ts deleted file mode 100644 index e69de29b..00000000 diff --git a/mlflow/package-lock.json b/mlflow/package-lock.json index 89eb916c..3d472c8b 100644 --- a/mlflow/package-lock.json +++ b/mlflow/package-lock.json @@ -1,17 +1,22 @@ { - "name": "mlflow", - "version": "1.0.0", + "name": "mlflow-js", + "version": "0.1.0", "lockfileVersion": 3, "requires": true, "packages": { "": { - "name": "mlflow", - "version": "1.0.0", + "name": "mlflow-js", + "version": "0.1.0", "license": "MIT", "devDependencies": { "@types/node": "^22.5.4", + "rimraf": "^6.0.1", "ts-node": "^10.9.2", + "tsx": "^4.19.0", "typescript": "^5.6.2" + }, + "engines": { + "node": ">=22.7.0" } }, "node_modules/@cspotcode/source-map-support": { @@ -27,6 +32,432 @@ "node": ">=12" } }, + "node_modules/@esbuild/aix-ppc64": { + "version": "0.23.1", + "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.23.1.tgz", + "integrity": "sha512-6VhYk1diRqrhBAqpJEdjASR/+WVRtfjpqKuNw11cLiaWpAT/Uu+nokB+UJnevzy/P9C/ty6AOe0dwueMrGh/iQ==", + "cpu": [ + "ppc64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "aix" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/android-arm": { + "version": "0.23.1", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.23.1.tgz", + "integrity": "sha512-uz6/tEy2IFm9RYOyvKl88zdzZfwEfKZmnX9Cj1BHjeSGNuGLuMD1kR8y5bteYmwqKm1tj8m4cb/aKEorr6fHWQ==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/android-arm64": { + "version": "0.23.1", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.23.1.tgz", + "integrity": "sha512-xw50ipykXcLstLeWH7WRdQuysJqejuAGPd30vd1i5zSyKK3WE+ijzHmLKxdiCMtH1pHz78rOg0BKSYOSB/2Khw==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/android-x64": { + "version": "0.23.1", + "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.23.1.tgz", + "integrity": "sha512-nlN9B69St9BwUoB+jkyU090bru8L0NA3yFvAd7k8dNsVH8bi9a8cUAUSEcEEgTp2z3dbEDGJGfP6VUnkQnlReg==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/darwin-arm64": { + "version": "0.23.1", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.23.1.tgz", + "integrity": "sha512-YsS2e3Wtgnw7Wq53XXBLcV6JhRsEq8hkfg91ESVadIrzr9wO6jJDMZnCQbHm1Guc5t/CdDiFSSfWP58FNuvT3Q==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/darwin-x64": { + "version": "0.23.1", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.23.1.tgz", + "integrity": "sha512-aClqdgTDVPSEGgoCS8QDG37Gu8yc9lTHNAQlsztQ6ENetKEO//b8y31MMu2ZaPbn4kVsIABzVLXYLhCGekGDqw==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/freebsd-arm64": { + "version": "0.23.1", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.23.1.tgz", + "integrity": "sha512-h1k6yS8/pN/NHlMl5+v4XPfikhJulk4G+tKGFIOwURBSFzE8bixw1ebjluLOjfwtLqY0kewfjLSrO6tN2MgIhA==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/freebsd-x64": { + "version": "0.23.1", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.23.1.tgz", + "integrity": "sha512-lK1eJeyk1ZX8UklqFd/3A60UuZ/6UVfGT2LuGo3Wp4/z7eRTRYY+0xOu2kpClP+vMTi9wKOfXi2vjUpO1Ro76g==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-arm": { + "version": "0.23.1", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.23.1.tgz", + "integrity": "sha512-CXXkzgn+dXAPs3WBwE+Kvnrf4WECwBdfjfeYHpMeVxWE0EceB6vhWGShs6wi0IYEqMSIzdOF1XjQ/Mkm5d7ZdQ==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-arm64": { + "version": "0.23.1", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.23.1.tgz", + "integrity": "sha512-/93bf2yxencYDnItMYV/v116zff6UyTjo4EtEQjUBeGiVpMmffDNUyD9UN2zV+V3LRV3/on4xdZ26NKzn6754g==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-ia32": { + "version": "0.23.1", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.23.1.tgz", + "integrity": "sha512-VTN4EuOHwXEkXzX5nTvVY4s7E/Krz7COC8xkftbbKRYAl96vPiUssGkeMELQMOnLOJ8k3BY1+ZY52tttZnHcXQ==", + "cpu": [ + "ia32" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-loong64": { + "version": "0.23.1", + "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.23.1.tgz", + "integrity": "sha512-Vx09LzEoBa5zDnieH8LSMRToj7ir/Jeq0Gu6qJ/1GcBq9GkfoEAoXvLiW1U9J1qE/Y/Oyaq33w5p2ZWrNNHNEw==", + "cpu": [ + "loong64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-mips64el": { + "version": "0.23.1", + "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.23.1.tgz", + "integrity": "sha512-nrFzzMQ7W4WRLNUOU5dlWAqa6yVeI0P78WKGUo7lg2HShq/yx+UYkeNSE0SSfSure0SqgnsxPvmAUu/vu0E+3Q==", + "cpu": [ + "mips64el" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-ppc64": { + "version": "0.23.1", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.23.1.tgz", + "integrity": "sha512-dKN8fgVqd0vUIjxuJI6P/9SSSe/mB9rvA98CSH2sJnlZ/OCZWO1DJvxj8jvKTfYUdGfcq2dDxoKaC6bHuTlgcw==", + "cpu": [ + "ppc64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-riscv64": { + "version": "0.23.1", + "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.23.1.tgz", + "integrity": "sha512-5AV4Pzp80fhHL83JM6LoA6pTQVWgB1HovMBsLQ9OZWLDqVY8MVobBXNSmAJi//Csh6tcY7e7Lny2Hg1tElMjIA==", + "cpu": [ + "riscv64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-s390x": { + "version": "0.23.1", + "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.23.1.tgz", + "integrity": "sha512-9ygs73tuFCe6f6m/Tb+9LtYxWR4c9yg7zjt2cYkjDbDpV/xVn+68cQxMXCjUpYwEkze2RcU/rMnfIXNRFmSoDw==", + "cpu": [ + "s390x" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-x64": { + "version": "0.23.1", + "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.23.1.tgz", + "integrity": "sha512-EV6+ovTsEXCPAp58g2dD68LxoP/wK5pRvgy0J/HxPGB009omFPv3Yet0HiaqvrIrgPTBuC6wCH1LTOY91EO5hQ==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/netbsd-x64": { + "version": "0.23.1", + "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.23.1.tgz", + "integrity": "sha512-aevEkCNu7KlPRpYLjwmdcuNz6bDFiE7Z8XC4CPqExjTvrHugh28QzUXVOZtiYghciKUacNktqxdpymplil1beA==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "netbsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/openbsd-arm64": { + "version": "0.23.1", + "resolved": "https://registry.npmjs.org/@esbuild/openbsd-arm64/-/openbsd-arm64-0.23.1.tgz", + "integrity": "sha512-3x37szhLexNA4bXhLrCC/LImN/YtWis6WXr1VESlfVtVeoFJBRINPJ3f0a/6LV8zpikqoUg4hyXw0sFBt5Cr+Q==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "openbsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/openbsd-x64": { + "version": "0.23.1", + "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.23.1.tgz", + "integrity": "sha512-aY2gMmKmPhxfU+0EdnN+XNtGbjfQgwZj43k8G3fyrDM/UdZww6xrWxmDkuz2eCZchqVeABjV5BpildOrUbBTqA==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "openbsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/sunos-x64": { + "version": "0.23.1", + "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.23.1.tgz", + "integrity": "sha512-RBRT2gqEl0IKQABT4XTj78tpk9v7ehp+mazn2HbUeZl1YMdaGAQqhapjGTCe7uw7y0frDi4gS0uHzhvpFuI1sA==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "sunos" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/win32-arm64": { + "version": "0.23.1", + "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.23.1.tgz", + "integrity": "sha512-4O+gPR5rEBe2FpKOVyiJ7wNDPA8nGzDuJ6gN4okSA1gEOYZ67N8JPk58tkWtdtPeLz7lBnY6I5L3jdsr3S+A6A==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/win32-ia32": { + "version": "0.23.1", + "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.23.1.tgz", + "integrity": "sha512-BcaL0Vn6QwCwre3Y717nVHZbAa4UBEigzFm6VdsVdT/MbZ38xoj1X9HPkZhbmaBGUD1W8vxAfffbDe8bA6AKnQ==", + "cpu": [ + "ia32" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/win32-x64": { + "version": "0.23.1", + "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.23.1.tgz", + "integrity": "sha512-BHpFFeslkWrXWyUPnbKm+xYYVYruCinGcftSBaa8zoF9hZO4BcSCFUvHVTtzpIY6YzUnYtuEhZ+C9iEXjxnasg==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@isaacs/cliui": { + "version": "8.0.2", + "resolved": "https://registry.npmjs.org/@isaacs/cliui/-/cliui-8.0.2.tgz", + "integrity": "sha512-O8jcjabXaleOG9DQ0+ARXWZBTfnP4WNAqzuiJK7ll44AmxGKv/J2M4TPjxjY3znBCfvBXFzucm1twdyFybFqEA==", + "dev": true, + "license": "ISC", + "dependencies": { + "string-width": "^5.1.2", + "string-width-cjs": "npm:string-width@^4.2.0", + "strip-ansi": "^7.0.1", + "strip-ansi-cjs": "npm:strip-ansi@^6.0.1", + "wrap-ansi": "^8.1.0", + "wrap-ansi-cjs": "npm:wrap-ansi@^7.0.0" + }, + "engines": { + "node": ">=12" + } + }, "node_modules/@jridgewell/resolve-uri": { "version": "3.1.2", "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.2.tgz", @@ -55,6 +486,17 @@ "@jridgewell/sourcemap-codec": "^1.4.10" } }, + "node_modules/@pkgjs/parseargs": { + "version": "0.11.0", + "resolved": "https://registry.npmjs.org/@pkgjs/parseargs/-/parseargs-0.11.0.tgz", + "integrity": "sha512-+1VkjdD0QBLPodGrJUeqarH8VAIvQODIbwh9XpP5Syisf7YoQgsJKPNFoqqLQlu+VQ/tVSshMR6loPMn8U+dPg==", + "dev": true, + "license": "MIT", + "optional": true, + "engines": { + "node": ">=14" + } + }, "node_modules/@tsconfig/node10": { "version": "1.0.11", "resolved": "https://registry.npmjs.org/@tsconfig/node10/-/node10-1.0.11.tgz", @@ -119,6 +561,32 @@ "node": ">=0.4.0" } }, + "node_modules/ansi-regex": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.1.0.tgz", + "integrity": "sha512-7HSX4QQb4CspciLpVFwyRe79O3xsIZDDLER21kERQ71oaPodF8jL725AgJMFAYbooIqolJoRLuM81SpeUkpkvA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/ansi-regex?sponsor=1" + } + }, + "node_modules/ansi-styles": { + "version": "6.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-6.2.1.tgz", + "integrity": "sha512-bN798gFfQX+viw3R7yrGWRqnrN2oRkEkUjjl4JNn4E8GxxbjtG3FbrEIIY3l8/hrwUwIeCZvi4QuOTP4MErVug==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, "node_modules/arg": { "version": "4.1.3", "resolved": "https://registry.npmjs.org/arg/-/arg-4.1.3.tgz", @@ -126,6 +594,43 @@ "dev": true, "license": "MIT" }, + "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, + "license": "MIT" + }, + "node_modules/brace-expansion": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", + "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", + "dev": true, + "license": "MIT", + "dependencies": { + "balanced-match": "^1.0.0" + } + }, + "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, + "license": "MIT", + "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, + "license": "MIT" + }, "node_modules/create-require": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/create-require/-/create-require-1.1.1.tgz", @@ -133,6 +638,21 @@ "dev": true, "license": "MIT" }, + "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, + "license": "MIT", + "dependencies": { + "path-key": "^3.1.0", + "shebang-command": "^2.0.0", + "which": "^2.0.1" + }, + "engines": { + "node": ">= 8" + } + }, "node_modules/diff": { "version": "4.0.2", "resolved": "https://registry.npmjs.org/diff/-/diff-4.0.2.tgz", @@ -143,6 +663,175 @@ "node": ">=0.3.1" } }, + "node_modules/eastasianwidth": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/eastasianwidth/-/eastasianwidth-0.2.0.tgz", + "integrity": "sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA==", + "dev": true, + "license": "MIT" + }, + "node_modules/emoji-regex": { + "version": "9.2.2", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-9.2.2.tgz", + "integrity": "sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==", + "dev": true, + "license": "MIT" + }, + "node_modules/esbuild": { + "version": "0.23.1", + "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.23.1.tgz", + "integrity": "sha512-VVNz/9Sa0bs5SELtn3f7qhJCDPCF5oMEl5cO9/SSinpE9hbPVvxbd572HH5AKiP7WD8INO53GgfDDhRjkylHEg==", + "dev": true, + "hasInstallScript": true, + "license": "MIT", + "bin": { + "esbuild": "bin/esbuild" + }, + "engines": { + "node": ">=18" + }, + "optionalDependencies": { + "@esbuild/aix-ppc64": "0.23.1", + "@esbuild/android-arm": "0.23.1", + "@esbuild/android-arm64": "0.23.1", + "@esbuild/android-x64": "0.23.1", + "@esbuild/darwin-arm64": "0.23.1", + "@esbuild/darwin-x64": "0.23.1", + "@esbuild/freebsd-arm64": "0.23.1", + "@esbuild/freebsd-x64": "0.23.1", + "@esbuild/linux-arm": "0.23.1", + "@esbuild/linux-arm64": "0.23.1", + "@esbuild/linux-ia32": "0.23.1", + "@esbuild/linux-loong64": "0.23.1", + "@esbuild/linux-mips64el": "0.23.1", + "@esbuild/linux-ppc64": "0.23.1", + "@esbuild/linux-riscv64": "0.23.1", + "@esbuild/linux-s390x": "0.23.1", + "@esbuild/linux-x64": "0.23.1", + "@esbuild/netbsd-x64": "0.23.1", + "@esbuild/openbsd-arm64": "0.23.1", + "@esbuild/openbsd-x64": "0.23.1", + "@esbuild/sunos-x64": "0.23.1", + "@esbuild/win32-arm64": "0.23.1", + "@esbuild/win32-ia32": "0.23.1", + "@esbuild/win32-x64": "0.23.1" + } + }, + "node_modules/foreground-child": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/foreground-child/-/foreground-child-3.3.0.tgz", + "integrity": "sha512-Ld2g8rrAyMYFXBhEqMz8ZAHBi4J4uS1i/CxGMDnjyFWddMXLVcDp051DZfu+t7+ab7Wv6SMqpWmyFIj5UbfFvg==", + "dev": true, + "license": "ISC", + "dependencies": { + "cross-spawn": "^7.0.0", + "signal-exit": "^4.0.1" + }, + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "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, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": "^8.16.0 || ^10.6.0 || >=11.0.0" + } + }, + "node_modules/get-tsconfig": { + "version": "4.8.0", + "resolved": "https://registry.npmjs.org/get-tsconfig/-/get-tsconfig-4.8.0.tgz", + "integrity": "sha512-Pgba6TExTZ0FJAn1qkJAjIeKoDJ3CsI2ChuLohJnZl/tTU8MVrq3b+2t5UOPfRa4RMsorClBjJALkJUMjG1PAw==", + "dev": true, + "license": "MIT", + "dependencies": { + "resolve-pkg-maps": "^1.0.0" + }, + "funding": { + "url": "https://github.com/privatenumber/get-tsconfig?sponsor=1" + } + }, + "node_modules/glob": { + "version": "11.0.0", + "resolved": "https://registry.npmjs.org/glob/-/glob-11.0.0.tgz", + "integrity": "sha512-9UiX/Bl6J2yaBbxKoEBRm4Cipxgok8kQYcOPEhScPwebu2I0HoQOuYdIO6S3hLuWoZgpDpwQZMzTFxgpkyT76g==", + "dev": true, + "license": "ISC", + "dependencies": { + "foreground-child": "^3.1.0", + "jackspeak": "^4.0.1", + "minimatch": "^10.0.0", + "minipass": "^7.1.2", + "package-json-from-dist": "^1.0.0", + "path-scurry": "^2.0.0" + }, + "bin": { + "glob": "dist/esm/bin.mjs" + }, + "engines": { + "node": "20 || >=22" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "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, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/isexe": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", + "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==", + "dev": true, + "license": "ISC" + }, + "node_modules/jackspeak": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/jackspeak/-/jackspeak-4.0.1.tgz", + "integrity": "sha512-cub8rahkh0Q/bw1+GxP7aeSe29hHHn2V4m29nnDlvCdlgU+3UGxkZp7Z53jLUdpX3jdTO0nJZUDl3xvbWc2Xog==", + "dev": true, + "license": "BlueOak-1.0.0", + "dependencies": { + "@isaacs/cliui": "^8.0.2" + }, + "engines": { + "node": "20 || >=22" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + }, + "optionalDependencies": { + "@pkgjs/parseargs": "^0.11.0" + } + }, + "node_modules/lru-cache": { + "version": "11.0.1", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-11.0.1.tgz", + "integrity": "sha512-CgeuL5uom6j/ZVrg7G/+1IXqRY8JXX4Hghfy5YE0EhoYQWvndP1kufu58cmZLNIDKnRhZrXfdS9urVWx98AipQ==", + "dev": true, + "license": "ISC", + "engines": { + "node": "20 || >=22" + } + }, "node_modules/make-error": { "version": "1.3.6", "resolved": "https://registry.npmjs.org/make-error/-/make-error-1.3.6.tgz", @@ -150,6 +839,236 @@ "dev": true, "license": "ISC" }, + "node_modules/minimatch": { + "version": "10.0.1", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-10.0.1.tgz", + "integrity": "sha512-ethXTt3SGGR+95gudmqJ1eNhRO7eGEGIgYA9vnPatK4/etz2MEVDno5GMCibdMTuBMyElzIlgxMna3K94XDIDQ==", + "dev": true, + "license": "ISC", + "dependencies": { + "brace-expansion": "^2.0.1" + }, + "engines": { + "node": "20 || >=22" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/minipass": { + "version": "7.1.2", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-7.1.2.tgz", + "integrity": "sha512-qOOzS1cBTWYF4BH8fVePDBOO9iptMnGUEZwNc/cMWnTV2nVLZ7VoNWEPHkYczZA0pdoA7dl6e7FL659nX9S2aw==", + "dev": true, + "license": "ISC", + "engines": { + "node": ">=16 || 14 >=14.17" + } + }, + "node_modules/package-json-from-dist": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/package-json-from-dist/-/package-json-from-dist-1.0.0.tgz", + "integrity": "sha512-dATvCeZN/8wQsGywez1mzHtTlP22H8OEfPrVMLNr4/eGa+ijtLn/6M5f0dY8UKNrC2O9UCU6SSoG3qRKnt7STw==", + "dev": true, + "license": "BlueOak-1.0.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, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/path-scurry": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/path-scurry/-/path-scurry-2.0.0.tgz", + "integrity": "sha512-ypGJsmGtdXUOeM5u93TyeIEfEhM6s+ljAhrk5vAvSx8uyY/02OvrZnA0YNGUrPXfpJMgI1ODd3nwz8Npx4O4cg==", + "dev": true, + "license": "BlueOak-1.0.0", + "dependencies": { + "lru-cache": "^11.0.0", + "minipass": "^7.1.2" + }, + "engines": { + "node": "20 || >=22" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/resolve-pkg-maps": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/resolve-pkg-maps/-/resolve-pkg-maps-1.0.0.tgz", + "integrity": "sha512-seS2Tj26TBVOC2NIc2rOe2y2ZO7efxITtLZcGSOnHHNOQ7CkiUBfw0Iw2ck6xkIhPwLhKNLS8BO+hEpngQlqzw==", + "dev": true, + "license": "MIT", + "funding": { + "url": "https://github.com/privatenumber/resolve-pkg-maps?sponsor=1" + } + }, + "node_modules/rimraf": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-6.0.1.tgz", + "integrity": "sha512-9dkvaxAsk/xNXSJzMgFqqMCuFgt2+KsOFek3TMLfo8NCPfWpBmqwyNn5Y+NX56QUYfCtsyhF3ayiboEoUmJk/A==", + "dev": true, + "license": "ISC", + "dependencies": { + "glob": "^11.0.0", + "package-json-from-dist": "^1.0.0" + }, + "bin": { + "rimraf": "dist/esm/bin.mjs" + }, + "engines": { + "node": "20 || >=22" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "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, + "license": "MIT", + "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, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/signal-exit": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-4.1.0.tgz", + "integrity": "sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==", + "dev": true, + "license": "ISC", + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/string-width": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-5.1.2.tgz", + "integrity": "sha512-HnLOCR3vjcY8beoNLtcjZ5/nxn2afmME6lhrDrebokqMap+XbeW8n9TXpPDOqdGK5qcI3oT0GKTW6wC7EMiVqA==", + "dev": true, + "license": "MIT", + "dependencies": { + "eastasianwidth": "^0.2.0", + "emoji-regex": "^9.2.2", + "strip-ansi": "^7.0.1" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/string-width-cjs": { + "name": "string-width", + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "dev": true, + "license": "MIT", + "dependencies": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/string-width-cjs/node_modules/ansi-regex": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/string-width-cjs/node_modules/emoji-regex": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", + "dev": true, + "license": "MIT" + }, + "node_modules/string-width-cjs/node_modules/strip-ansi": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-regex": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/strip-ansi": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.1.0.tgz", + "integrity": "sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-regex": "^6.0.1" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/strip-ansi?sponsor=1" + } + }, + "node_modules/strip-ansi-cjs": { + "name": "strip-ansi", + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-regex": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/strip-ansi-cjs/node_modules/ansi-regex": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, "node_modules/ts-node": { "version": "10.9.2", "resolved": "https://registry.npmjs.org/ts-node/-/ts-node-10.9.2.tgz", @@ -194,6 +1113,26 @@ } } }, + "node_modules/tsx": { + "version": "4.19.0", + "resolved": "https://registry.npmjs.org/tsx/-/tsx-4.19.0.tgz", + "integrity": "sha512-bV30kM7bsLZKZIOCHeMNVMJ32/LuJzLVajkQI/qf92J2Qr08ueLQvW00PUZGiuLPP760UINwupgUj8qrSCPUKg==", + "dev": true, + "license": "MIT", + "dependencies": { + "esbuild": "~0.23.0", + "get-tsconfig": "^4.7.5" + }, + "bin": { + "tsx": "dist/cli.mjs" + }, + "engines": { + "node": ">=18.0.0" + }, + "optionalDependencies": { + "fsevents": "~2.3.3" + } + }, "node_modules/typescript": { "version": "5.6.2", "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.6.2.tgz", @@ -222,6 +1161,120 @@ "dev": true, "license": "MIT" }, + "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, + "license": "ISC", + "dependencies": { + "isexe": "^2.0.0" + }, + "bin": { + "node-which": "bin/node-which" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/wrap-ansi": { + "version": "8.1.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-8.1.0.tgz", + "integrity": "sha512-si7QWI6zUMq56bESFvagtmzMdGOtoxfR+Sez11Mobfc7tm+VkUckk9bW2UeffTGVUbOksxmSw0AA2gs8g71NCQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-styles": "^6.1.0", + "string-width": "^5.0.1", + "strip-ansi": "^7.0.1" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/wrap-ansi?sponsor=1" + } + }, + "node_modules/wrap-ansi-cjs": { + "name": "wrap-ansi", + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", + "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-styles": "^4.0.0", + "string-width": "^4.1.0", + "strip-ansi": "^6.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/wrap-ansi?sponsor=1" + } + }, + "node_modules/wrap-ansi-cjs/node_modules/ansi-regex": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/wrap-ansi-cjs/node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "license": "MIT", + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/wrap-ansi-cjs/node_modules/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, + "license": "MIT" + }, + "node_modules/wrap-ansi-cjs/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, + "license": "MIT", + "dependencies": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/wrap-ansi-cjs/node_modules/strip-ansi": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-regex": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, "node_modules/yn": { "version": "3.1.1", "resolved": "https://registry.npmjs.org/yn/-/yn-3.1.1.tgz", diff --git a/mlflow/package.json b/mlflow/package.json index cc7248c6..823a78e6 100644 --- a/mlflow/package.json +++ b/mlflow/package.json @@ -1,24 +1,31 @@ { - "name": "mlflow", - "version": "1.0.0", + "name": "mlflow-js", + "version": "0.1.0", "description": "JavaScript/Typescript library for MLflow", "main": "lib/index.js", "type": "module", "types": "lib/index.d.ts", "scripts": { - "build": "tsc", - "test": "echo \"Error: no test specified\" && exit 1" + "clean": "rimraf lib", + "build": "npm run clean && tsc", + "test": "", + "lint": "", + "docs": "" }, "keywords": [ "mlflow", "machine learning", - "typescript" + "typescript", + "ai", + "data science" ], "author": "", "license": "MIT", "devDependencies": { "@types/node": "^22.5.4", + "rimraf": "^6.0.1", "ts-node": "^10.9.2", + "tsx": "^4.19.0", "typescript": "^5.6.2" }, "engines": { diff --git a/mlflow/src/model_registry/model_registry.js b/mlflow/src/model_registry/model_registry.js index 397a32c5..58b09617 100644 --- a/mlflow/src/model_registry/model_registry.js +++ b/mlflow/src/model_registry/model_registry.js @@ -406,4 +406,4 @@ class ModelRegistry { return data; } } -export { ModelRegistry }; \ No newline at end of file +export default ModelRegistry; \ No newline at end of file diff --git a/mlflow/tests/ModelRegistryClientTest.ts b/mlflow/tests/ModelRegistryClientTest.ts new file mode 100644 index 00000000..3ee3791a --- /dev/null +++ b/mlflow/tests/ModelRegistryClientTest.ts @@ -0,0 +1,25 @@ +import ModelRegistryClient from '../src/model_registry/ModelRegistryClient'; + +async function testModelRegistryClient() { + const client = new ModelRegistryClient('http://localhost:5001'); + + try { + // Test creating a registered model + console.log('Creating a new registered model...'); + const newModel = await client.createRegisteredModel( + 'test-model', + [{ key: 'test-tag', value: 'test-value' }], + 'This is a test model' + ); + console.log('Created model:', newModel); + + // Test getting the registered model + console.log('\nGetting the registered model...'); + const retrievedModel = await client.getRegisteredModel('test-model'); + console.log('Retrieved model:', retrievedModel); + } catch (error) { + console.error('Error:', error.message); + } +} + +testModelRegistryClient(); diff --git a/mlflow/tests/ModelRegistryClientTest.js b/mlflow/tests/model_registry_test.js similarity index 88% rename from mlflow/tests/ModelRegistryClientTest.js rename to mlflow/tests/model_registry_test.js index cff11936..8588b150 100644 --- a/mlflow/tests/ModelRegistryClientTest.js +++ b/mlflow/tests/model_registry_test.js @@ -1,9 +1,11 @@ -// usage_example.js -import { ModelRegistryClient } from '../src/model_registry/ModelRegistryClient.ts'; +import ModelRegistry from '../src/model_registry/model_registry.js'; +// import ModelRegistryClient from '../lib/model_registry/ModelRegistryClient.js'; +// import ApiRequest from '../lib/utils/ApiRequest.js'; async function main() { const trackingUri = 'http://localhost:5001'; const modelRegistry = new ModelRegistry(trackingUri); + // const modelRegistry = new ModelRegistryClient(trackingUri); try { // Create a new registered model diff --git a/mlflow/tsconfig.json b/mlflow/tsconfig.json index 0653c12c..92bd6038 100644 --- a/mlflow/tsconfig.json +++ b/mlflow/tsconfig.json @@ -1,15 +1,54 @@ { "compilerOptions": { - "module": "ES6", - "target": "ES6", - "noImplicitAny": true, - "strict": true, - "forceConsistentCasingInFileNames": true, + // Basic Options + "target": "ES2018", + "module": "ESNext", + "lib": ["ES2018"], + "outDir": "./lib", + "rootDir": "./src", + + // Module Resolution Options "moduleResolution": "node", + "baseUrl": "./src", + "paths": { + "*": ["*"] + }, + "esModuleInterop": true, "resolveJsonModule": true, - "outDir": "./lib", - "rootDir": "./src" + "moduleDetection": "force", + + // Strict Type-Checking Options + "strict": true, + "noImplicitAny": true, + "strictNullChecks": true, + "strictFunctionTypes": true, + "strictBindCallApply": true, + "strictPropertyInitialization": true, + "noImplicitThis": true, + "alwaysStrict": true, + + // Additional Checks + "noUnusedLocals": true, + "noUnusedParameters": true, + "noImplicitReturns": true, + "noFallthroughCasesInSwitch": true, + + // Experimental Options + "experimentalDecorators": true, + "emitDecoratorMetadata": true, + + // Advanced Options + "forceConsistentCasingInFileNames": true, + "skipLibCheck": true, + + // Source Map Options + "sourceMap": false, + + // Other Options + "declaration": true, + "removeComments": false, + "allowJs": false }, - "include": ["src/**/*.ts", "src/**/*.tsx", "tests/**/*"], - "exclude": ["node_modules"] -} + "include": ["src/**/*"], + "exclude": ["node_modules", "**/*.spec.ts"] +} \ No newline at end of file From 7985c5b23e6fdf19661c7948a4acbfd1a9a0854b Mon Sep 17 00:00:00 2001 From: Yiqun Zheng Date: Wed, 11 Sep 2024 20:17:46 -0700 Subject: [PATCH 062/357] ts compiling issue --- mlflow/tests/model_registry_test.js | 15 ++++++++++----- 1 file changed, 10 insertions(+), 5 deletions(-) diff --git a/mlflow/tests/model_registry_test.js b/mlflow/tests/model_registry_test.js index 8588b150..3b7d08c4 100644 --- a/mlflow/tests/model_registry_test.js +++ b/mlflow/tests/model_registry_test.js @@ -1,11 +1,16 @@ -import ModelRegistry from '../src/model_registry/model_registry.js'; -// import ModelRegistryClient from '../lib/model_registry/ModelRegistryClient.js'; -// import ApiRequest from '../lib/utils/ApiRequest.js'; +// import ModelRegistry from '../src/model_registry/model_registry.js'; +import ModelRegistryClient from '../lib/model_registry/ModelRegistryClient.js'; + +/** questions/issues: + * 1. need to manually change the import path by adding .js extension in the complied js file, + * since ts doesn't take extension and when ts is getting compiled, .js is not added automatically; + * 2. await error below with this imported compiled file: await' has no effect on the type of this expression.ts(80007) + * */ async function main() { const trackingUri = 'http://localhost:5001'; - const modelRegistry = new ModelRegistry(trackingUri); - // const modelRegistry = new ModelRegistryClient(trackingUri); + // const modelRegistry = new ModelRegistry(trackingUri); + const modelRegistry = new ModelRegistryClient(trackingUri); try { // Create a new registered model From 02e1c5b53791ca501084f6eac83b9c974afc37f5 Mon Sep 17 00:00:00 2001 From: Austin Fraser Date: Wed, 11 Sep 2024 23:21:46 -0700 Subject: [PATCH 063/357] moving ExperimentClient_testFile.js and ExperimentManager_testFile.js into tracked files, removed from .gitignore --- mlflow/.gitignore | 4 +- .../src/tracking_server/ExperimentClient.js | 68 +++++----- .../ExperimentClient_testFile.js | 118 ++++++++++++++++++ mlflow/src/workflows/ExperimentManager.js | 6 +- .../workflows/ExperimentManager_testFile.js | 110 ++++++++++++++++ 5 files changed, 268 insertions(+), 38 deletions(-) create mode 100644 mlflow/src/tracking_server/ExperimentClient_testFile.js create mode 100644 mlflow/src/workflows/ExperimentManager_testFile.js diff --git a/mlflow/.gitignore b/mlflow/.gitignore index 7af338ff..b512c09d 100644 --- a/mlflow/.gitignore +++ b/mlflow/.gitignore @@ -1,3 +1 @@ -node_modules -src/tracking_server/ExperimentClient_testFile.js -src/workflows/ExperimentManager_testFile.js \ No newline at end of file +node_modules \ No newline at end of file diff --git a/mlflow/src/tracking_server/ExperimentClient.js b/mlflow/src/tracking_server/ExperimentClient.js index d63a16ec..7af488f3 100644 --- a/mlflow/src/tracking_server/ExperimentClient.js +++ b/mlflow/src/tracking_server/ExperimentClient.js @@ -16,26 +16,26 @@ class ExperimentClient { if (!name) { throw new Error('Experiment name is required'); } - + const url = `${this.trackingUri}/api/2.0/mlflow/experiments/create`; const response = await fetch(url, { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ name, artifact_location, tags }), }); - + if (!response.ok) { const errorBody = await response.json(); throw new Error( `Error creating experiment from tracking server, status: ${response.status}. ${errorBody.message}` ); } - + const data = await response.json(); // console.log('return from createExperiment: ', data.experiment_id); return data.experiment_id; } - + /** * Search experiments. * @@ -60,7 +60,7 @@ class ExperimentClient { if (!max_results) { throw new Error('Max results is required'); } - + const url = `${this.trackingUri}/api/2.0/mlflow/experiments/search`; const response = await fetch(url, { method: 'POST', @@ -73,19 +73,19 @@ class ExperimentClient { view_type, }), }); - + if (!response.ok) { const errorBody = await response.json(); throw new Error( `Error searching for experiment from tracking server, status: ${response.status}. ${errorBody.message}` ); } - + const data = await response.json(); // console.log('return from searchExperiment: ', data); return data; } - + /** * Get metadata for an experiment, querying by experiment ID. This method works on deleted experiments. * @@ -96,25 +96,25 @@ class ExperimentClient { if (!experiment_id) { throw new Error('Experiment ID is required'); } - + const url = `${this.trackingUri}/api/2.0/mlflow/experiments/get?experiment_id=${experiment_id}`; const response = await fetch(url, { method: 'GET', headers: { 'Content-Type': 'application/json' }, }); - + if (!response.ok) { const errorBody = await response.json(); throw new Error( `Error getting experiment from tracking server, status: ${response.status}. ${errorBody.message}` ); } - + const data = await response.json(); // console.log('return from getExperiment: ', data.experiment); return data.experiment; } - + /** * Get metadata for an experiment, querying by experiment name. * This endpoint will return deleted experiments, @@ -128,25 +128,25 @@ class ExperimentClient { if (!experiment_name) { throw new Error('Experiment name is required'); } - + const url = `${this.trackingUri}/api/2.0/mlflow/experiments/get-by-name?experiment_name=${experiment_name}`; const response = await fetch(url, { method: 'GET', headers: { 'Content-Type': 'application/json' }, }); - + if (!response.ok) { const errorBody = await response.json(); throw new Error( `Error getting experiment by name from tracking server, status: ${response.status}. ${errorBody.message}` ); } - + const data = await response.json(); // console.log('return from getExperimentByName: ', data.experiment); return data.experiment; } - + /** * Mark an experiment for deletion. * @@ -157,25 +157,25 @@ class ExperimentClient { if (!experiment_id) { throw new Error('Experiment ID is required'); } - + const url = `${this.trackingUri}/api/2.0/mlflow/experiments/delete`; const response = await fetch(url, { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ experiment_id }), }); - + if (!response.ok) { const errorBody = await response.json(); throw new Error( `Error deleting experiment from tracking server, status: ${response.status}. ${errorBody.message}` ); } - + console.log(`Experiment ID ${experiment_id} successfully deleted`); // return `Experiment ID ${experiment_id} successfully deleted`; } - + /** * Restore an experiment marked for deletion. * @@ -186,25 +186,25 @@ class ExperimentClient { if (!experiment_id) { throw new Error('Experiment ID is required'); } - + const url = `${this.trackingUri}/api/2.0/mlflow/experiments/restore`; const response = await fetch(url, { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ experiment_id }), }); - + if (!response.ok) { const errorBody = await response.json(); throw new Error( `Error restoring experiment from tracking server, status: ${response.status}. ${errorBody.message}` ); } - + console.log(`Experiment ID ${experiment_id} successfully restored`); // return `Experiment ID ${experiment_id} successfully restored`; } - + /** * Update experiment name. * @@ -219,25 +219,27 @@ class ExperimentClient { if (!new_name) { throw new Error('New name is required'); } - + const url = `${this.trackingUri}/api/2.0/mlflow/experiments/update`; const response = await fetch(url, { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ experiment_id, new_name }), }); - + if (!response.ok) { const errorBody = await response.json(); throw new Error( `Error updating experiment from tracking server, status: ${response.status}. ${errorBody.message}` ); } - - console.log(`Experiment ID ${experiment_id} successfully updated - new name is ${new_name}`); + + console.log( + `Experiment ID ${experiment_id} successfully updated - new name is ${new_name}` + ); // return `Experiment ID ${experiment_id} successfully updated - new name is ${new_name}`; } - + /** * Set a tag on an experiment. * @@ -256,24 +258,24 @@ class ExperimentClient { if (!value) { throw new Error('Value is required'); } - + const url = `${this.trackingUri}/api/2.0/mlflow/experiments/set-experiment-tag`; const response = await fetch(url, { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ experiment_id, key, value }), }); - + if (!response.ok) { const errorBody = await response.json(); throw new Error( `Error setting tag from tracking server, status: ${response.status}. ${errorBody.message}` ); } - + console.log(`Set tag to experiment ID ${experiment_id} successfully`); // return `Set tag to experiment ID ${experiment_id} successfully`; } } -export { ExperimentClient }; \ No newline at end of file +export { ExperimentClient }; diff --git a/mlflow/src/tracking_server/ExperimentClient_testFile.js b/mlflow/src/tracking_server/ExperimentClient_testFile.js new file mode 100644 index 00000000..a671fab5 --- /dev/null +++ b/mlflow/src/tracking_server/ExperimentClient_testFile.js @@ -0,0 +1,118 @@ +import { ExperimentClient } from './ExperimentClient.js'; +const MLFLOW_TRACKING_URI = 'http://localhost:5001'; +let experimentClient = new ExperimentClient(MLFLOW_TRACKING_URI); + +const testCreateExperiment = async () => { + const num = Math.random().toString().slice(2, 11); + const name = `Test experiment ${num}`; + const log = await experimentClient.createExperiment(name); + return console.log(log); +}; +// testCreateExperiment(); + +const testSearchExperiment = async () => { + const num1 = Math.random().toString().slice(2, 11); + const name1 = `Search test ${num1}`; + const exp1 = await experimentClient.createExperiment(name1); + + const num2 = Math.random().toString().slice(2, 11); + const name2 = `Search test ${num2}`; + const exp2 = await experimentClient.createExperiment(name2); + + const num3 = Math.random().toString().slice(2, 11); + const name3 = `Search test ${num3}`; + const exp3 = await experimentClient.createExperiment(name3); + + const num4 = Math.random().toString().slice(2, 11); + const name4 = `Search test ${num4}`; + const exp4 = await experimentClient.createExperiment(name4); + + const num5 = Math.random().toString().slice(2, 11); + const name5 = `Search test ${num5}`; + const exp5 = await experimentClient.createExperiment(name5); + + const log = await experimentClient.searchExperiment( + "name LIKE 'Search test%'", + 4 + ); + console.log(log); +}; +// testSearchExperiment(); + +const testGetExperiment = async () => { + const num = Math.random().toString().slice(2, 11); + const name = `Test experiment ${num}`; + const exp = await experimentClient.createExperiment(name); + const log = await experimentClient.getExperiment(exp); + console.log(log); +}; +// testGetExperiment(); + +const testGetExperimentByName = async () => { + const num = Math.random().toString().slice(2, 11); + const name = `Test experiment ${num}`; + const exp = await experimentClient.createExperiment(name); + const log = await experimentClient.getExperimentByName(name); + console.log(log); +}; +// testGetExperimentByName(); + +const testDeleteExperiment = async () => { + const num = Math.random().toString().slice(2, 11); + const name = `Test experiment ${num}`; + const exp = await experimentClient.createExperiment(name); + const log = await experimentClient.deleteExperiment(exp); + // console.log(log); + const log2 = await experimentClient.getExperiment(exp); + console.log(log2); + experimentClient.restoreExperiment(exp); +}; +// testDeleteExperiment(); + +const testRestoreExperiment = async () => { + const num = Math.random().toString().slice(2, 11); + const name = `Test experiment ${num}`; + const exp = await experimentClient.createExperiment(name); + const log = await experimentClient.getExperiment(exp); + console.log(log); + const deleted = await experimentClient.deleteExperiment(exp); + const log2 = await experimentClient.getExperiment(exp); + console.log(log2); + const log3 = await experimentClient.restoreExperiment(exp); + const log4 = await experimentClient.getExperiment(exp); + console.log(log4); +}; +// testRestoreExperiment(); + +const testUpdateExperiment = async () => { + const num = Math.random().toString().slice(2, 11); + const name = `Test experiment ${num}`; + const exp = await experimentClient.createExperiment(name); + const log = await experimentClient.getExperiment(exp); + console.log(log); + const log2 = await experimentClient.updateExperiment( + exp, + `${name}_UPDATED_NAME` + ); + const log3 = await experimentClient.getExperiment(exp); + console.log(log3); + const revert = await experimentClient.updateExperiment(exp, name); +}; +// testUpdateExperiment(); + +const testSetExperimentTag = async () => { + const num = Math.random().toString().slice(2, 11); + const name = `Test experiment ${num}`; + const exp = await experimentClient.createExperiment(name); + const log = await experimentClient.getExperiment(exp); + console.log(log); + const num2 = Math.random().toString().slice(2, 11); + const log2 = await experimentClient.setExperimentTag( + exp, + 'test_tag', + `test_value_${num2}` + ); + const log3 = await experimentClient.getExperiment(exp); + console.log(log3); +}; +// testSetExperimentTag(); diff --git a/mlflow/src/workflows/ExperimentManager.js b/mlflow/src/workflows/ExperimentManager.js index 273e2145..108461fe 100644 --- a/mlflow/src/workflows/ExperimentManager.js +++ b/mlflow/src/workflows/ExperimentManager.js @@ -76,7 +76,9 @@ class ExperimentManager { throw new Error('Experiment name is required'); } - let experiment_id = await experimentClient.createExperiment(experiment_name); + let experiment_id = await experimentClient.createExperiment( + experiment_name + ); // create run const run = await runManagement.createRun(experiment_id, run_name, tags); @@ -123,4 +125,4 @@ class ExperimentManager { } } -export { ExperimentManager }; \ No newline at end of file +export { ExperimentManager }; diff --git a/mlflow/src/workflows/ExperimentManager_testFile.js b/mlflow/src/workflows/ExperimentManager_testFile.js new file mode 100644 index 00000000..b948bb14 --- /dev/null +++ b/mlflow/src/workflows/ExperimentManager_testFile.js @@ -0,0 +1,110 @@ +import { ExperimentManager } from './ExperimentManager.js'; +import { ExperimentClient } from '../tracking_server/ExperimentClient.js'; +const MLFLOW_TRACKING_URI = 'http://localhost:5001'; +const experimentManager = new ExperimentManager(MLFLOW_TRACKING_URI); +const experimentClient = new ExperimentClient(MLFLOW_TRACKING_URI); + +const testRunExistingExperiment = async () => { + // define fake data for metrics, params, tags, and model + const metrics = [ + { key: 'metric1', value: 0.111, timestamp: Date.now() }, + { key: 'metric2', value: 0.222, timestamp: Date.now() }, + ]; + const params = [ + { key: 'testParam', value: 'testParamValue' }, + { key: 'testParam2', value: 'testParamValue2' }, + ]; + const tags = [ + { key: 'testKey', value: 'testValue' }, + { key: 'testKey2', value: 'testValue2' }, + ]; + const model = { + artifact_path: 'model', + flavors: { + python_function: { + model_path: 'model.pkl', + loader_module: 'mlflow.sklearn', + python_version: '3.8.10', + }, + }, + model_url: 'STRING', + model_uuid: 'STRING', + utc_time_created: Date.now(), + mlflow_version: 'STRING', + }; + + // construct random name to avoid duplicate names in the tracking server + const num = Math.random().toString().slice(2, 11); + const name = `Test experiment ${num}`; + + // pass the randomized name into .createExperiment to create a new experiment. this stores its experiment ID under the 'exp' variable + const exp = await experimentClient.createExperiment(name); + + // call .runExistingExperiment on our newly created experiment, passing in the fake data, and store the results under the variable 'log' + const log = await experimentManager.runExistingExperiment( + exp, + undefined, + metrics, + params, + tags, + model + ); + return console.log(log); +}; +// testRunExistingExperiment(); + +const testRunNewExperiment = async () => { + // define fake data for metrics, params, tags, and model + const metrics = [ + { key: 'metric1', value: 0.9, timestamp: Date.now() }, + { key: 'metric2', value: 0.222, timestamp: Date.now() }, + ]; + const params = [ + { key: 'testParam', value: 'testParamValue' }, + { key: 'testParam2', value: 'testParamValue2' }, + ]; + const tags = [ + { key: 'testKey', value: 'testValue' }, + { key: 'testKey2', value: 'testValue2' }, + ]; + const model = { + artifact_path: 'model', + flavors: { + python_function: { + model_path: 'model.pkl', + loader_module: 'mlflow.sklearn', + python_version: '3.8.10', + }, + }, + model_url: 'STRING', + model_uuid: 'STRING', + utc_time_created: Date.now(), + mlflow_version: 'STRING', + }; + + // construct random name to avoid duplicate names in the tracking server + const num = Math.random().toString().slice(2, 11); + const name = `Test experiment ${num}`; + + // call .runNewExperiment using our randomly generated name, passing in the fake data, and store the results under the variable 'log' + const log = await experimentManager.runNewExperiment( + name, + undefined, + metrics, + params, + tags, + model + ); + return console.log(log); +}; +// testRunNewExperiment(); + +const testExperimentSummary = async () => { + const log = await experimentManager.experimentSummary( + '787867007534323476', + 'metric1', + 'DESC' + ); + return console.log(log); +}; +// testExperimentSummary(); From 36d63743fafbbcde9d427cfe1a4366b3e1bd5926 Mon Sep 17 00:00:00 2001 From: Stephany Ho Date: Thu, 12 Sep 2024 10:31:01 -0400 Subject: [PATCH 064/357] RunManager: change method names to cleanupRuns and copyRun, refactor cleanupRuns --- mlflow/src/tracking_server/testing.js | 172 -------------------------- mlflow/src/workflows/RunManager.js | 116 ++++++++--------- mlflow/src/workflows/testing.js | 49 -------- 3 files changed, 53 insertions(+), 284 deletions(-) delete mode 100644 mlflow/src/tracking_server/testing.js delete mode 100644 mlflow/src/workflows/testing.js diff --git a/mlflow/src/tracking_server/testing.js b/mlflow/src/tracking_server/testing.js deleted file mode 100644 index c3995c17..00000000 --- a/mlflow/src/tracking_server/testing.js +++ /dev/null @@ -1,172 +0,0 @@ -import { RunManagement } from './run_management.js'; - -const myRunManagement = new RunManagement('http://127.0.0.1:5000'); - -async function testCreateRun(experiment_id) { - try { - const run = await myRunManagement.createRun(experiment_id); - console.log('Created run:', run); - } catch (error) { - console.error('Error:', error.message); - } -} - -// testCreateRun('415858823387303182'); - -async function testDeleteRun(run_id) { - try { - const run = await myRunManagement.deleteRun(run_id); - console.log(`Run ID ${run_id} deleted`); - } catch (error) { - console.error('Error:', error.message); - } -} - -// testDeleteRun('1d3829715bda4e4eb257f68363dacfa6'); - -async function testRestoreRun(run_id) { - try { - const run = await myRunManagement.restoreRun(run_id); - console.log(`Run ID ${run_id} restored`); - } catch (error) { - console.error('Error:', error.message); - } -} - -// testRestoreRun('1d3829715bda4e4eb257f68363dacfa6'); - -async function testGetRun(run_id) { - try { - const run = await myRunManagement.getRun(run_id); - console.log('Fetched run ID: ', run); - } catch (error) { - console.error('Error:', error.message); - } -} - -// testGetRun('0577e22f02e24d24b62949625306c256'); - -async function testUpdateRun(run_id, status, run_name) { - try { - const updatedRun = await myRunManagement.updateRun( - run_id, - status, - run_name - ); - console.log('Updated run: ', updatedRun); - } catch (error) { - console.error('Error:', error.message); - } -} - -// testUpdateRun( -// '0577e22f02e24d24b62949625306c256', -// 'FINISHED', -// 'victorious-bee-311' -// ); - -async function testLogMetric(run_id, key, value) { - try { - const loggedMetric = await myRunManagement.logMetric(run_id, key, value); - console.log('Metric logged successfully'); - } catch (error) { - console.error('Error: ', error.message); - } -} - -// testLogMetric('69c2298a1a374e989806ea89ab2b892a', 'metric-01', 0.9); - -async function testLogBatch(run_id, metrics, params, tags) { - try { - await myRunManagement.logBatch(run_id, metrics, params, tags); - } catch (error) { - console.error('Error in testLogBatch: ', error); - } -} - -// testLogBatch('521098fe3c6f42ee81fdb82cc1437fef'); -// testLogBatch( -// '0577e22f02e24d24b62949625306c256', -// [ -// { key: 'mae', value: 2.5, timestamp: 1552550804 }, -// { key: 'rmse', value: 2.7, timestamp: 1552550804 }, -// ], -// [{ key: 'model_class', value: 'LogisticRegression' }] -// ); -// testLogBatch( -// '1d3829715bda4e4eb257f68363dacfa6', -// [ -// { key: 'mae', value: 2.2, timestamp: 1552550804 }, -// { key: 'rmse', value: 2.9, timestamp: 1552550804 }, -// ], -// [{ key: 'model_class', value: 'LogisticRegression' }], -// [{ key: 'tag_name', value: 'testing' }] -// ); - -async function testLogModel(run_id, model_json) { - try { - const modelJson = JSON.stringify(model_json); - - await myRunManagement.logModel(run_id, modelJson); - console.log('Model logged successfully.'); - } catch (error) { - console.error('Error: ', error); - } -} - -// testLogModel('69c2298a1a374e989806ea89ab2b892a', { -// artifact_path: 'model', -// flavors: { -// python_function: { -// model_path: 'model.pkl', -// loader_module: 'mlflow.sklearn', -// python_version: '3.8.10', -// }, -// // sklearn: { -// // sklearn_version: '0.19.1', -// // pickled_model: 'model.pkl', -// // }, -// }, -// run_id: '69c2298a1a374e989806ea89ab2b892a', -// utc_time_created: '2024-08-28 12:00:00.000000', -// }); - -async function testLogInputs(run_id, datasets) { - try { - await myRunManagement.logInputs(run_id, datasets); - console.log('Datasets logged successfully.'); - } catch (error) { - console.error('Error logging datasets: ', error.message); - } -} - -// testLogInputs('4a6e21f64d9d4201b157e838501b8d9c', [ -// { -// name: 'wine quality - white', -// source: -// 'https://raw.githubusercontent.com/mlflow/mlflow/master/tests/datasets/winequality-white.csv', -// targets: 'quality', -// schema: { -// columns: [ -// { name: 'fixed acidity', type: 'double' }, -// { name: 'volatile acidity', type: 'double' }, -// { name: 'citric acid', type: 'double' }, -// { name: 'residual sugar', type: 'double' }, -// { name: 'chlorides', type: 'double' }, -// { name: 'free sulfur dioxide', type: 'double' }, -// { name: 'total sulfur dioxide', type: 'double' }, -// { name: 'density', type: 'double' }, -// { name: 'pH', type: 'double' }, -// { name: 'sulphates', type: 'double' }, -// { name: 'alcohol', type: 'double' }, -// { name: 'quality', type: 'long' }, -// ], -// }, -// // profile: { -// // num_rows: rawData.length, -// // num_elements: rawData.length * Object.keys(rawData[0]).length, -// // }, -// }, -// ]); - -// https://mlflow.org/docs/latest/python_api/mlflow.data.html#mlflow.data.dataset.Dataset diff --git a/mlflow/src/workflows/RunManager.js b/mlflow/src/workflows/RunManager.js index 9fb3916e..82bba96f 100644 --- a/mlflow/src/workflows/RunManager.js +++ b/mlflow/src/workflows/RunManager.js @@ -1,10 +1,10 @@ -import { RunManagement } from '../tracking_server/run_management.js'; +import { RunClient } from '../tracking_server/RunClient.js'; import { ModelVersionManagement } from '../model_registry/model_version_management.js'; -class Abstraction { +class RunManager { constructor(trackingUri) { this.trackingUri = trackingUri; - this.RunManagement = new RunManagement(this.trackingUri); + this.RunClient = new RunClient(this.trackingUri); this.ModelVersionManagement = new ModelVersionManagement(this.trackingUri); } @@ -16,15 +16,16 @@ class Abstraction { * @param {boolean} [dryRun=true] - If true, only simulate the deletion. Defaults to true. (optional) * @returns {Promise} - An object of deleted runs. */ - async runCleanup(experimentIds, queryString, dryRun = true) { + async cleanupRuns(experimentIds, queryString, metricKey, dryRun = true) { const deletedRuns = []; + const keepRunIds = new Set(); let pageToken = null; const maxResults = 1000; try { do { // get all runs - const searchResult = await this.RunManagement.searchRuns( + const searchResult = await this.RunClient.searchRuns( experimentIds, '', null, // run_view_type @@ -34,7 +35,7 @@ class Abstraction { ); // get runs that match the keep crteria - const keepResult = await this.RunManagement.searchRuns( + const keepRunsResult = await this.RunClient.searchRuns( experimentIds, queryString, null, // run_view_type @@ -43,18 +44,29 @@ class Abstraction { pageToken ); - // create a Set of run IDs to keep for efficient lookup - const keepRunIds = new Set( - keepResult.runs.map((run) => run.info.run_id) - ); + // Add runs from keepRunsResult to keepResult + keepRunsResult.runs.forEach((run) => keepRunIds.add(run.info.run_id)); + + // Add runs without the specified metric key to keepRunIds + for (const run of searchResult.runs) { + if (Array.isArray(run.data.metrics)) { + const hasMetricKey = run.data.metrics.some( + (metric) => metric.key === metricKey + ); + if (!hasMetricKey) { + keepRunIds.add(run.info.run_id); + } + } else { + // If run.data.metrics is not an array (e.g., undefined), keep the run + keepRunIds.add(run.info.run_id); + } + } - // check for runs that are not in keepRunIds - // if dryRun is false, delete from database, push to deletedRuns array - // if dryRun is true, push to deletedRuns array - for (const run of searchResult.runs || []) { + // Delete runs that are not in keepRunIds + for (const run of searchResult.runs) { if (!keepRunIds.has(run.info.run_id)) { if (!dryRun) { - await this.RunManagement.deleteRun(run.info.run_id); + await this.RunClient.deleteRun(run.info.run_id); } deletedRuns.push(run); } @@ -72,20 +84,20 @@ class Abstraction { /********************************************************************************************************** */ /** - * Move run from one experiment to another without artifactss and models. Artifacts and models detail tagged in new run as reference. + * Copy run from one experiment to another without artifactss and models. Artifacts and models detail tagged in new run as reference. * - * @param {string} runId - The ID of the run to be moved. (required) + * @param {string} runId - The ID of the run to be copied. (required) * @param {string} targetExperimentId - The ID of the target experiment. (required) * @param {string} runName - The name of the new run in target experiment. (optional) - * @returns {Promise} - An object of move run detail. + * @returns {Promise} - An object detail of the copied run. */ - async moveRun(runId, targetExperimentId, runName = null) { + async copyRun(runId, targetExperimentId, runName = null) { try { // get original run - const originalRun = await this.RunManagement.getRun(runId); + const originalRun = await this.RunClient.getRun(runId); // create a new run in the target experiment - const newRun = await this.RunManagement.createRun( + const newRun = await this.RunClient.createRun( targetExperimentId, null, originalRun.info.start_time @@ -94,9 +106,9 @@ class Abstraction { const newRunId = newRun.info.run_id; // copy run information - await this.RunManagement.updateRun(newRunId, originalRun.info.status); + await this.RunClient.updateRun(newRunId, originalRun.info.status); if (originalRun.info.lifecycle_stage !== 'active') { - await this.RunManagement.setTag( + await this.RunClient.setTag( newRunId, 'mlflow.lifecycleStage', originalRun.info.lifecycle_stage @@ -106,25 +118,21 @@ class Abstraction { // copy parameters if (originalRun.data.params) { for (const param of originalRun.data.params) { - await this.RunManagement.logParam(newRunId, param.key, param.value); + await this.RunClient.logParam(newRunId, param.key, param.value); } } // copy metrics if (originalRun.data.metrics) { for (const metric of originalRun.data.metrics) { - await this.RunManagement.logMetric( - newRunId, - metric.key, - metric.value - ); + await this.RunClient.logMetric(newRunId, metric.key, metric.value); } } // copy tags if (originalRun.data.tags) { for (const tag of originalRun.data.tags) { - await this.RunManagement.setTag(newRunId, tag.key, tag.value); + await this.RunClient.setTag(newRunId, tag.key, tag.value); } } @@ -136,13 +144,13 @@ class Abstraction { ) { // Log each dataset input separately for (const datasetInput of originalRun.inputs.dataset_inputs) { - await this.RunManagement.logInputs(newRunId, [datasetInput]); + await this.RunClient.logInputs(newRunId, [datasetInput]); } } // update the new run name if (runName) { - await this.RunManagement.setTag(newRunId, 'mlflow.runName', runName); + await this.RunClient.setTag(newRunId, 'mlflow.runName', runName); } // handle models (reference only) @@ -152,7 +160,7 @@ class Abstraction { ); if (modelVersions && modelVersions.length > 0) { for (const model of modelVersions) { - await this.RunManagement.setTag( + await this.RunClient.setTag( newRunId, `original_model_${model.name}`, JSON.stringify({ @@ -163,64 +171,46 @@ class Abstraction { }) ); } - await this.RunManagement.setTag( + await this.RunClient.setTag( newRunId, 'mlflow.note.models', - 'Models not moved -see original run' + 'Models not copied -see original run' ); } - // update the original run - await this.RunManagement.updateRun(runId, 'FINISHED', null, Date.now()); - // set description for the new run const description = - `This run was moved from experiment ${originalRun.info.experiment_id}, original run ID: ${runId}. ` + + `This run was copied from experiment ${originalRun.info.experiment_id}, original run ID: ${runId}. ` + `Original artifact URI: ${originalRun.info.artifact_uri}.`; - await this.RunManagement.setTag( - newRunId, - 'mlflow.note.content', - description - ); + await this.RunClient.setTag(newRunId, 'mlflow.note.content', description); // set additional tags for the new run - await this.RunManagement.setTag(newRunId, 'mlflow.source.run_id', runId); + await this.RunClient.setTag(newRunId, 'mlflow.source.run_id', runId); - await this.RunManagement.setTag( + await this.RunClient.setTag( newRunId, 'mlflow.source.experiment_id', originalRun.info.experiment_id ); - await this.RunManagement.setTag( + await this.RunClient.setTag( newRunId, 'mlflow.note.artifacts', - 'Artifacts not moved - reference original run' + 'Artifacts not copied - reference original run' ); - // return object with move run details + // return copy run details return { originalRunId: runId, newRunId: newRunId, targetExperimentId: targetExperimentId, }; } catch (error) { - console.error('Error moving run: ', error); - throw new Error('Failed to move run.'); + console.error('Error copying run: ', error); + throw new Error('Failed to copy run.'); } } - - /********************************************************************************************************** */ - - /** - * Search runs and export run data to CSV. - * - * @param {string[]} experimentIds - The IDs of the associated experiments. (required) - * @param {string} queryString - SQL-like query string to filter runs to keep. (required) - * @returns {Promise} - An object of run datas in CSV format. - */ - async convertRunDataToCSV() {} } -export { Abstraction }; +export { RunManager }; diff --git a/mlflow/src/workflows/testing.js b/mlflow/src/workflows/testing.js deleted file mode 100644 index 56e65974..00000000 --- a/mlflow/src/workflows/testing.js +++ /dev/null @@ -1,49 +0,0 @@ -import { Abstraction } from './RunManager.js'; -import { RunManagement } from '../tracking_server/run_management.js'; - -const trackingUri = 'http://127.0.0.1:5000'; -const path = '/api/2.0/mlflow'; - -// const ab = new Abstraction(trackingUri, path); -const ab = new Abstraction(trackingUri); -const myRunManagement = new RunManagement(trackingUri); - -// testing searchRuns method -// const runs = await myRunManagement.searchRuns(['463611670721534538'], ''); -// console.log('Search runs result: ', runs); - -// // dry run (simulation) -// try { -// const result = await ab.runCleanup( -// ['284209273010848955'], -// 'metrics.accuracy > 0.9' -// ); -// console.log(result.deletedRuns); -// } catch (error) { -// console.error('Error: ', error.message, error.stack); -// } - -// // delete runs -// try { -// const result = await ab.runCleanup( -// ['463611670721534538'], -// 'metrics.mae > 2', -// true -// ); -// console.log(result); -// } catch (error) { -// console.error('Error: ', error.message, error.stack); -// } - -/************************************************************** */ - -// move run -// await ab.moveRun( -// 'c3178ac6ee414495b854361c95f9f517', -// '508915846877934148', -// 'meow' -// ); - -// check tags -// const run = await myRunManagement.getRun('c3178ac6ee414495b854361c95f9f517'); -// console.log(run.data.tags); From 3dd34196498bde9d7da93e3fd7224dc39d813366 Mon Sep 17 00:00:00 2001 From: Stephany Ho Date: Thu, 12 Sep 2024 12:43:26 -0400 Subject: [PATCH 065/357] Rename RunClient.js, refactor codes, fix updateRun, add description to methods --- .../{run_management.js => RunClient.js} | 240 ++++++++---------- 1 file changed, 100 insertions(+), 140 deletions(-) rename mlflow/src/tracking_server/{run_management.js => RunClient.js} (65%) diff --git a/mlflow/src/tracking_server/run_management.js b/mlflow/src/tracking_server/RunClient.js similarity index 65% rename from mlflow/src/tracking_server/run_management.js rename to mlflow/src/tracking_server/RunClient.js index c4d38fdf..62dffca2 100644 --- a/mlflow/src/tracking_server/run_management.js +++ b/mlflow/src/tracking_server/RunClient.js @@ -1,28 +1,32 @@ -class RunManagement { +class RunClient { constructor(trackingUri) { this.trackingUri = trackingUri; } /** - * Creates a new run. + * Create a new run within an experiment. A run is usually a single execution of a machine learning or data ETL pipeline. MLflow uses runs to track Param, Metric, and RunTag associated with a single execution. * - * @param {string} experiment_id - The ID of the associated experiment (required) - * @param {string} [run_name] - The name of the run (optional) - * @param {Array<{key: string, value: string}>} [tags=[]] - Additional metadata for the run (optional) - * @returns {Promise} - The created run object + * @param {string} experiment_id - ID of the associated experiment. (required) + * @param {string} [run_name] - Name of the run. + * @param {number} [start_time] - Unix timestamp in milliseconds of when the run started. + * @param {Array<{key: string, value: string}>} [tags=[]] - Additional metadata for the run. + * @returns {Promise} - A promise that resolves with the created run object. */ - async createRun(experiment_id, run_name = null, tags = []) { + async createRun( + experiment_id, + run_name = null, + start_time = null, + tags = [] + ) { if (!experiment_id) { throw new Error('Experiment ID is required'); } - const startTime = Date.now(); - const url = `${this.trackingUri}/api/2.0/mlflow/runs/create`; const body = { experiment_id, - start_time: startTime, + start_time: start_time !== null ? start_time : Date.now(), tags, }; @@ -40,7 +44,7 @@ class RunManagement { if (!response.ok) { throw new Error( - `Error in creating run: ${data.message || response.statusText}` + `Error creating run: ${data.message || response.statusText}` ); } @@ -48,10 +52,10 @@ class RunManagement { } /** - * Deletes a run. + * Mark a run for deletion. * - * @param {string} run_id - The ID of the run to delete (required) - * @returns {Promise} - A promise that resolves when the run is deleted + * @param {string} run_id - ID of the run to delete. (required) + * @returns {Promise} - A promise that resolves when the run is deleted. */ async deleteRun(run_id) { if (!run_id) { @@ -67,19 +71,15 @@ class RunManagement { }); if (!response.ok) { - throw new Error( - `Error in deleting run: ${data.message || response.statusText}` - ); + throw new Error(`Error deleting run: ${response.statusText}`); } - - return await response.json(); } /** - * Restores a run. + * Restore a deleted run. * - * @param {string} run_id - The ID of the run to restore (required) - * @returns {Promise} - A promise that resolves when the run is restored + * @param {string} run_id - ID of the run to restore. (required) + * @returns {Promise} - A promise that resolves when the run is restored. */ async restoreRun(run_id) { if (!run_id) { @@ -95,19 +95,15 @@ class RunManagement { }); if (!response.ok) { - throw new Error( - `Error in restoring run: ${data.message || response.statusText}` - ); + throw new Error(`Error restoring run: ${response.statusText}`); } - - return await response.json(); } /** - * Fetches a run. + * Get metadata, metrics, params, and tags for a run. In the case where multiple metrics with the same key are logged for a run, return only the value with the latest timestamp. If there are multiple values with the latest timestamp, return the maximum of these values. * - * @param {string} run_id - The ID of the run to fetch (required) - * @returns {Promise} - The fetched run object + * @param {string} run_id - ID of the run to fetch. (required) + * @returns {Promise} - A promise that resolves with the fetched run object. */ async getRun(run_id) { if (!run_id) { @@ -121,7 +117,7 @@ class RunManagement { if (!response.ok) { throw new Error( - `Error in fetching run: ${data.message || response.statusText}` + `Error fetching run: ${data.message || response.statusText}` ); } @@ -129,15 +125,15 @@ class RunManagement { } /** - * updates a run. + * Update run metadata. * - * @param {string} run_id - The ID of the run to update (required) - * @param {string} [status] - The status of the updated run (optional) - * @param {string} [run_name] - The updated name of the run (optional) - * @param {number} [end_time] - The end time fo the run in milliseconds since epoch (optional) - * @returns {Promise} - The updated metadata of the run object + * @param {string} run_id - ID of the run to update. (required) + * @param {string} [status] - Updated status of the run. + * @param {number} [end_time] - Unix timestamp in milliseconds of when the run ended. + * @param {string} [run_name] - Updated name of the run. + * @returns {Promise} - A promise that resolves with the updated metadata of the run object. */ - async updateRun(run_id, status = null, run_name = null, end_time = null) { + async updateRun(run_id, status = null, end_time = null, run_name = null) { if (!run_id) { throw new Error('Run ID is required.'); } @@ -146,8 +142,8 @@ class RunManagement { const body = { run_id }; if (status) body.status = status; - if (run_name) body.run_name = run_name; if (end_time) body.end_time = end_time; + if (run_name) body.run_name = run_name; const response = await fetch(url, { method: 'POST', @@ -159,7 +155,7 @@ class RunManagement { if (!response.ok) { throw new Error( - `Error in updating run: ${data.message || response.statusText}` + `Error updating run: ${data.message || response.statusText}` ); } @@ -167,19 +163,19 @@ class RunManagement { } /** - * Logs a metric for a run. + * Log a metric for a run. A metric is a key-value pair (string key, float value) with an associated timestamp. Examples include the various metrics that represent ML model accuracy. A metric can be logged multiple times. * - * @param {string} run_id - The ID of the run under which to log the metric (required) - * @param {string} key - The name of the metric (required) - * @param {number} value - The double value of the metric being logged (required) - * @param {number} timestamp - The unix timestamp in milliseconds at the time metric was logged (required) - * @param {number} [step=0] - The step at which to log the metric (optional) - * @returns {Promise} - A promise that resolves when the metric is logged + * @param {string} run_id - ID of the run under which to log the metric. (required) + * @param {string} key - Name of the metric. (required) + * @param {number} value - Double value of the metric being logged. (required) + * @param {number} timestamp - Unix timestamp in milliseconds at the time metric was logged. (required) + * @param {number} [step=0] - Step at which to log the metric. + * @returns {Promise} - A promise that resolves when the logging is complete. */ async logMetric(run_id, key, value, timestamp = Date.now(), step = 0) { - if (!run_id || !key || !value) { - throw new Error('Run ID, key, value, timestamp are required.'); + if (!run_id || !key || !value || !timestamp) { + throw new Error('Run ID, key, value, and timestamp are required.'); } const url = `${this.trackingUri}/api/2.0/mlflow/runs/log-metric`; @@ -194,22 +190,18 @@ class RunManagement { }); if (!response.ok) { - throw new Error( - `Error in logging metric: ${data.message || response.statusText}` - ); + throw new Error(`Error logging metric: ${response.statusText}`); } - - return await response.json(); } /** - * Logs a batch of metrics, params, and tags for a run. + * Log a batch of metrics, params, and tags for a run. If any data failed to be persisted, the server will respond with an error (non-200 status code). In case of error (due to internal server error or an invalid request), partial data may be written. * - * @param {string} run_id - The ID of the run to log under (required) - * @param {Array<{key: string, value: number, timestamp: number, step?: number}>} [metrics=[]] - The metrics to log (up to 1000 metrics) (optional) - * @param {Array<{key: string, value: string}>} [params=[]] - The params to log (up to 100 params) (optional) - * @param {Array<{key: string, value: string}>} [tags=[]] - The tags to log (up to 100 tags) (optional) - * @returns {Promise} - A promise that resolves when the logging is complete + * @param {string} run_id - ID of the run to log under. (required) + * @param {Array<{key: string, value: number, timestamp: number, step?: number}>} [metrics=[]] - Metrics to log. A single request can contain up to 1000 metrics, and up to 1000 metrics, params, and tags in total. + * @param {Array<{key: string, value: string}>} [params=[]] - Params to log. A single request can contain up to 100 params, and up to 1000 metrics, params, and tags in total. + * @param {Array<{key: string, value: string}>} [tags=[]] - Tags to log. A single request can contain up to 100 tags, and up to 1000 metrics, params, and tags in total. + * @returns {Promise} - A promise that resolves when the logging is complete. */ async logBatch(run_id, metrics = [], params = [], tags = []) { if (!run_id) { @@ -230,26 +222,20 @@ class RunManagement { }); if (!response.ok) { - const responseBody = await response.text(); - console.error(`Response body: ${responseBody}`); - throw new Error( - `Error in logging batch: ${data.message || response.statusText}` - ); + throw new Error(`Error logging batch: ${response.statusText}`); } - - return await response.json(); } /** * Logs a model. * - * @param {string} run_id - The ID of the run to log under (required) - * @param {string} model_json - The MLmodel data in JSON format (required) - * @returns {Promise} - A promise that resolves when the model is successfully logged + * @param {string} run_id - ID of the run to log under. (required) + * @param {string} model_json - MLmodel file in json format. (required) + * @returns {Promise} - A promise that resolves when the logging is complete. */ async logModel(run_id, model_json) { - if (!run_id || !model_json) { - throw new Error('Run ID and MLmodel file are required.'); + if (!run_id || model_json) { + throw new Error('Run ID and MLmodel data are required.'); } const url = `${this.trackingUri}/api/2.0/mlflow/runs/log-model`; @@ -261,20 +247,16 @@ class RunManagement { }); if (!response.ok) { - throw new Error( - `Error in logging model: ${data.message || response.statusText}` - ); + throw new Error(`Error logging model: ${response.statusText}`); } - - return await response.json(); } /** * Logs inputs. * - * @param {string} run_id - The ID of the run to log under (required) - * @param {Array} datasets - The dataset inputs in JSON format (required) - * @returns {Promise} - A promise that resolves when the logging is complete + * @param {string} run_id - ID of the run to log under. (required) + * @param {Array} datasets - The dataset inputs in JSON format. (required) + * @returns {Promise} - A promise that resolves when the logging is complete. */ async logInputs(run_id, datasets) { @@ -291,30 +273,27 @@ class RunManagement { }); if (!response.ok) { - throw new Error( - `Error in logging inputs: ${data.message || response.statusText}` - ); + throw new Error(`Error in logging inputs: ${response.statusText}`); } - - return await response.json(); } /** + * Set a tag on a run. Tags are run metadata that can be updated during a run and after a run completes. * - * @param {string} run_id - ID of the run which to log the tag. Required + * @param {string} run_id - ID of the run under which to log the tag. (required) * @param {string} key - Name of the tag. Maximum size depends on storage backend. All storage backends - * are guaranteed to support key values up to 250 bytes in size. Required + * are guaranteed to support key values up to 250 bytes in size. (required) * @param {string} value - String value of the tag being logged. Maximum size depends on storage - * backend. All storage backends are guaranteed to support key values up to 5000 bytes in size. Required - * @returns {Promise} - A promise that resolves when the logging is complete. */ async setTag(run_id, key, value) { if (!run_id) { - throw new Error('run_id is required'); + throw new Error('Run ID is required'); } else if (!key) { - throw new Error('key is required'); + throw new Error('Key is required'); } else if (!value) { - throw new Error('value is required'); + throw new Error('Value is required'); } const url = `${this.trackingUri}/api/2.0/mlflow/runs/set-tag`; const response = await fetch(url, { @@ -325,22 +304,17 @@ class RunManagement { body: JSON.stringify({ run_id, key, value }), }); - // data is an empty object - const data = await response.json(); - if (!response.ok) { - throw new Error( - `Error logging param: ${data.message || response.statusText}` - ); + throw new Error(`Error setting tag: ${response.statusText}`); } - return data; } /** + * Delete a tag on a run. Tags are run metadata that can be updated during a run and after a run completes. * - * @param {string} run_id - ID of the run that the tag was logged under. Required - * @param {string} key - Name of the tag. Maximum size is 255 bytes. Required - * @returns {Promise} - Empty promise object + * @param {string} run_id - ID of the run that the tag was logged under. (required) + * @param {string} key - Name of the tag. Maximum size is 255 bytes. (required) + * @returns {Promise} - A promise that resolves when the deletion is complete. */ async deleteTag(run_id, key) { if (!run_id) { @@ -369,11 +343,12 @@ class RunManagement { } /** + * Log a param used for a run. A param is a key-value pair (string key, string value). Examples include hyperparameters used for ML model training and constant dates and values used in an ETL pipeline. A param can be logged only once for a run. * - * @param {string} run_id - ID of the run under which to log the param. Required - * @param {string} key - Name of the param. Maximum size is 255 bytes. Required - * @param {string} value - String value of the param being logged. Maximum size is 6000 bytes. Required - * @returns {Promise} - Empty promise object + * @param {string} run_id - ID of the run under which to log the param. (required)) + * @param {string} key - Name of the param. Maximum size is 255 bytes. (required) + * @param {string} value - String value of the param being logged. Maximum size is 6000 bytes. (required) + * @returns {Promise} - A promise that resolves when the logging is complete. * Note: A param can be logged only once for a run */ async logParam(run_id, key, value) { @@ -393,25 +368,22 @@ class RunManagement { body: JSON.stringify({ run_id, key, value }), }); - const data = await response.json(); if (!response.ok) { - throw new Error( - `Error logging param: ${data.message || response.statusText}` - ); + throw new Error(`Error logging param: ${response.statusText}`); } - return data; } /** + * Get a list of all values for the specified metric for a given run. * - * @param {string} run_id - ID of the run from which to fetch metric values. Required - * @param {string} metric_key - Name of the metric. Required - * @param {string} page_token - Token indicating the page of metric history to fetch + * @param {string} run_id - ID of the run from which to fetch metric values. (required) + * @param {string} metric_key - Name of the metric. (required) + * @param {string} page_token - Token indicating the page of metric history to fetch. * @param {INT32} max_results - Maximum number of logged instances of a metric for a run to return per call. * Backend servers may restrict the value of max_results depending on performance requirements. Requests that do not * specify this value will behave as non-paginated queries where all metric history values for a given metric * within a run are returned in a single response. - * @returns {Promise} - The values for the specified metric, as a promise object + * @returns {Promise} - A promise that resolves with the values for the specified metric. */ async getMetricHistory(run_id, metric_key, page_token, max_results) { if (!run_id) { @@ -457,7 +429,7 @@ class RunManagement { * Example: ["params.input DESC","metrics.alpha ASC", "metrics.rmse"] Tiebreaks are done by start_time DESC followed by run_id for * runs with the same start time (and this is the default ordering criterion if order_by is not provided). * @param {string} page_token - * @returns {Promise} - The list artifacts for the specified run, as a promise object + * @param {string} run_id - ID of the run whose artifacts to list. (required) + * @param {string} artifact_path - Filter artifacts matching this path (a relative path from the root artifact directory). + * @param {string} page_token - Token indicating the page of artifact results to fetch. + * @returns {Promise} - A promise that resolves with a list artifacts for the specified run.t */ async listArtifacts(run_id, artifact_path = '', page_token = '') { if (!run_id) { @@ -548,4 +508,4 @@ class RunManagement { } } -export { RunManagement }; +export { RunClient }; From 82a31a0a20c48f42adbec41a41571008531ba4ec Mon Sep 17 00:00:00 2001 From: Stephany Ho Date: Thu, 12 Sep 2024 12:58:56 -0400 Subject: [PATCH 066/357] Refactor copyRun --- mlflow/src/workflows/RunManager.js | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/mlflow/src/workflows/RunManager.js b/mlflow/src/workflows/RunManager.js index 82bba96f..99a8461f 100644 --- a/mlflow/src/workflows/RunManager.js +++ b/mlflow/src/workflows/RunManager.js @@ -105,8 +105,14 @@ class RunManager { const newRunId = newRun.info.run_id; + const endTime = originalRun.info.end_time || undefined; + // copy run information - await this.RunClient.updateRun(newRunId, originalRun.info.status); + await this.RunClient.updateRun( + newRunId, + originalRun.info.status, + endTime + ); if (originalRun.info.lifecycle_stage !== 'active') { await this.RunClient.setTag( newRunId, From 0efd9e0e626c98f4950441a15123bb95a13e068b Mon Sep 17 00:00:00 2001 From: Stephany Ho Date: Thu, 12 Sep 2024 21:06:17 -0400 Subject: [PATCH 067/357] Commit minor changes before merging dev --- mlflow/src/tracking_server/RunClient.js | 2 +- mlflow/src/workflows/RunManager.js | 6 ++++-- 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/mlflow/src/tracking_server/RunClient.js b/mlflow/src/tracking_server/RunClient.js index 62dffca2..bcef9347 100644 --- a/mlflow/src/tracking_server/RunClient.js +++ b/mlflow/src/tracking_server/RunClient.js @@ -479,7 +479,7 @@ class RunClient { * @param {string} run_id - ID of the run whose artifacts to list. (required) * @param {string} artifact_path - Filter artifacts matching this path (a relative path from the root artifact directory). * @param {string} page_token - Token indicating the page of artifact results to fetch. - * @returns {Promise} - A promise that resolves with a list artifacts for the specified run.t + * @returns {Promise} - A promise that resolves with a list artifacts for the specified run. */ async listArtifacts(run_id, artifact_path = '', page_token = '') { if (!run_id) { diff --git a/mlflow/src/workflows/RunManager.js b/mlflow/src/workflows/RunManager.js index 99a8461f..fe2c23d9 100644 --- a/mlflow/src/workflows/RunManager.js +++ b/mlflow/src/workflows/RunManager.js @@ -9,7 +9,8 @@ class RunManager { } /** - * Delete runs that do not meet certain criteria and return the deleted runs. + * Delete runs that do not meet certain criteria and return deleted runs. + * Dry run is set to true by default. To delete, set dry run to false. * * @param {string[]} experimentIds - The IDs of the associated experiments. (required) * @param {string} queryString - SQL-like query string to filter runs to keep. (required) @@ -84,7 +85,8 @@ class RunManager { /********************************************************************************************************** */ /** - * Copy run from one experiment to another without artifactss and models. Artifacts and models detail tagged in new run as reference. + * Copy run from one experiment to another without artifactss and models. + * Artifacts and models detail tagged in new run as reference. * * @param {string} runId - The ID of the run to be copied. (required) * @param {string} targetExperimentId - The ID of the target experiment. (required) From f8a024cffad92a18acbd767f4e710e71795adb6e Mon Sep 17 00:00:00 2001 From: Austin Fraser Date: Thu, 12 Sep 2024 18:15:33 -0700 Subject: [PATCH 068/357] moving testing files into tests folder --- mlflow/src/tracking_server/testing_AF.js | 171 ------------------ .../ExperimentClient_testFile.js | 2 +- .../ExperimentManager_testFile.js | 4 +- 3 files changed, 3 insertions(+), 174 deletions(-) delete mode 100644 mlflow/src/tracking_server/testing_AF.js rename mlflow/{src/tracking_server => tests}/ExperimentClient_testFile.js (98%) rename mlflow/{src/workflows => tests}/ExperimentManager_testFile.js (95%) diff --git a/mlflow/src/tracking_server/testing_AF.js b/mlflow/src/tracking_server/testing_AF.js deleted file mode 100644 index ea4198cb..00000000 --- a/mlflow/src/tracking_server/testing_AF.js +++ /dev/null @@ -1,171 +0,0 @@ -import { RunManagement } from './run_management.js'; - -const myRunManagement = new RunManagement('http://localhost:5001'); - -async function testCreateRun(experiment_id) { - try { - const run = await myRunManagement.createRun(experiment_id); - console.log('Created run:', run); - } catch (error) { - console.error('Error:', error.message); - } -} - -// testCreateRun('977566317259111173'); - -async function testDeleteRun(run_id) { - try { - const run = await myRunManagement.deleteRun(run_id); - console.log(`Run ID ${run_id} deleted`); - } catch (error) { - console.error('Error:', error.message); - } -} - -// testDeleteRun('1d3829715bda4e4eb257f68363dacfa6'); - -async function testRestoreRun(run_id) { - try { - const run = await myRunManagement.restoreRun(run_id); - console.log(`Run ID ${run_id} restored`); - } catch (error) { - console.error('Error:', error.message); - } -} - -// testRestoreRun('1d3829715bda4e4eb257f68363dacfa6'); - -async function testGetRun(run_id) { - try { - const run = await myRunManagement.getRun(run_id); - console.log('Fetched run ID: ', run); - } catch (error) { - console.error('Error:', error.message); - } -} - -// testGetRun('0577e22f02e24d24b62949625306c256'); - -async function testUpdateRun(run_id, status, run_name) { - try { - const updatedRun = await myRunManagement.updateRun( - run_id, - status, - run_name - ); - console.log('Updated run: ', updatedRun); - } catch (error) { - console.error('Error:', error.message); - } -} - -// testUpdateRun( -// '0577e22f02e24d24b62949625306c256', -// 'FINISHED', -// 'victorious-bee-311' -// ); - -async function testLogMetric(run_id, key, value) { - try { - const loggedMetric = await myRunManagement.logMetric(run_id, key, value); - console.log('Metric logged successfully'); - } catch (error) { - console.error('Error: ', error.message); - } -} - -// testLogMetric('69c2298a1a374e989806ea89ab2b892a', 'metric-01', 0.9); - -async function testLogBatch(run_id, metrics, params, tags) { - try { - await myRunManagement.logBatch(run_id, metrics, params, tags); - } catch (error) { - console.error('Error in testLogBatch: ', error); - } -} - -// testLogBatch('521098fe3c6f42ee81fdb82cc1437fef'); -// testLogBatch( -// '0577e22f02e24d24b62949625306c256', -// [ -// { key: 'mae', value: 2.5, timestamp: 1552550804 }, -// { key: 'rmse', value: 2.7, timestamp: 1552550804 }, -// ], -// [{ key: 'model_class', value: 'LogisticRegression' }] -// ); -// testLogBatch( -// '1d3829715bda4e4eb257f68363dacfa6', -// [ -// { key: 'mae', value: 2.2, timestamp: 1552550804 }, -// { key: 'rmse', value: 2.9, timestamp: 1552550804 }, -// ], -// [{ key: 'model_class', value: 'LogisticRegression' }], -// [{ key: 'tag_name', value: 'testing' }] -// ); - -async function testLogModel(run_id, model_json) { - try { - const modelJson = JSON.stringify(model_json); - - await myRunManagement.logModel(run_id, modelJson); - console.log('Model logged successfully.'); - } catch (error) { - console.error('Error: ', error); - } -} - -// testLogModel('026e2e2e56b049e1bbea18cac27df99a', { -// artifact_path: 'model', -// flavors: { -// python_function: { -// model_path: 'model.pkl', -// loader_module: 'mlflow.sklearn', -// python_version: '3.8.10', -// }, -// // sklearn: { -// // sklearn_version: '0.19.1', -// // pickled_model: 'model.pkl', -// // }, -// }, -// utc_time_created: '2024-08-28 12:00:00.000000', -// }); - -async function testLogInputs(run_id, datasets) { - try { - await myRunManagement.logInputs(run_id, datasets); - console.log('Datasets logged successfully.'); - } catch (error) { - console.error('Error logging datasets: ', error.message); - } -} - -// testLogInputs('4a6e21f64d9d4201b157e838501b8d9c', [ -// { -// name: 'wine quality - white', -// source: -// 'https://raw.githubusercontent.com/mlflow/mlflow/master/tests/datasets/winequality-white.csv', -// targets: 'quality', -// schema: { -// columns: [ -// { name: 'fixed acidity', type: 'double' }, -// { name: 'volatile acidity', type: 'double' }, -// { name: 'citric acid', type: 'double' }, -// { name: 'residual sugar', type: 'double' }, -// { name: 'chlorides', type: 'double' }, -// { name: 'free sulfur dioxide', type: 'double' }, -// { name: 'total sulfur dioxide', type: 'double' }, -// { name: 'density', type: 'double' }, -// { name: 'pH', type: 'double' }, -// { name: 'sulphates', type: 'double' }, -// { name: 'alcohol', type: 'double' }, -// { name: 'quality', type: 'long' }, -// ], -// }, -// // profile: { -// // num_rows: rawData.length, -// // num_elements: rawData.length * Object.keys(rawData[0]).length, -// // }, -// }, -// ]); - -// https://mlflow.org/docs/latest/python_api/mlflow.data.html#mlflow.data.dataset.Dataset diff --git a/mlflow/src/tracking_server/ExperimentClient_testFile.js b/mlflow/tests/ExperimentClient_testFile.js similarity index 98% rename from mlflow/src/tracking_server/ExperimentClient_testFile.js rename to mlflow/tests/ExperimentClient_testFile.js index a671fab5..9f31fca5 100644 --- a/mlflow/src/tracking_server/ExperimentClient_testFile.js +++ b/mlflow/tests/ExperimentClient_testFile.js @@ -1,4 +1,4 @@ -import { ExperimentClient } from './ExperimentClient.js'; +import { ExperimentClient } from '../src/tracking_server/ExperimentClient.js'; const MLFLOW_TRACKING_URI = 'http://localhost:5001'; let experimentClient = new ExperimentClient(MLFLOW_TRACKING_URI); diff --git a/mlflow/src/workflows/ExperimentManager_testFile.js b/mlflow/tests/ExperimentManager_testFile.js similarity index 95% rename from mlflow/src/workflows/ExperimentManager_testFile.js rename to mlflow/tests/ExperimentManager_testFile.js index b948bb14..088b3259 100644 --- a/mlflow/src/workflows/ExperimentManager_testFile.js +++ b/mlflow/tests/ExperimentManager_testFile.js @@ -1,5 +1,5 @@ -import { ExperimentManager } from './ExperimentManager.js'; -import { ExperimentClient } from '../tracking_server/ExperimentClient.js'; +import { ExperimentManager } from '../src/workflows/ExperimentManager.js'; +import { ExperimentClient } from '../src/tracking_server/ExperimentClient.js'; const MLFLOW_TRACKING_URI = 'http://localhost:5001'; const experimentManager = new ExperimentManager(MLFLOW_TRACKING_URI); const experimentClient = new ExperimentClient(MLFLOW_TRACKING_URI); From 5f3396aad256c2f0d14c651013189200b9c11c15 Mon Sep 17 00:00:00 2001 From: Stephany Ho Date: Thu, 12 Sep 2024 21:25:30 -0400 Subject: [PATCH 069/357] Move test files to test after merge dev --- mlflow/tests/RunClientTestFile.js | 174 ++++++++++++++++++ .../RunManagerTestFile.js} | 11 +- mlflow/tsconfig.json | 8 +- 3 files changed, 186 insertions(+), 7 deletions(-) create mode 100644 mlflow/tests/RunClientTestFile.js rename mlflow/{src/workflows/RunManager_testFile.js => tests/RunManagerTestFile.js} (83%) diff --git a/mlflow/tests/RunClientTestFile.js b/mlflow/tests/RunClientTestFile.js new file mode 100644 index 00000000..e950b001 --- /dev/null +++ b/mlflow/tests/RunClientTestFile.js @@ -0,0 +1,174 @@ +import { RunClient } from '../src/tracking_server/RunClient.js'; + +const myRunClient = new RunClient('http://127.0.0.1:5000'); + +async function testCreateRun(experiment_id) { + try { + const run = await myRunClient.createRun(experiment_id); + console.log('Created run:', run); + } catch (error) { + console.error('Error:', error.message); + } +} + +// testCreateRun('463611670721534538'); + +async function testDeleteRun(run_id) { + try { + const run = await myRunClient.deleteRun(run_id); + console.log(`Run ID ${run_id} deleted`); + } catch (error) { + console.error('Error:', error.message); + } +} + +// testDeleteRun('1d3829715bda4e4eb257f68363dacfa6'); + +async function testRestoreRun(run_id) { + try { + const run = await myRunClient.restoreRun(run_id); + console.log(`Run ID ${run_id} restored`); + } catch (error) { + console.error('Error:', error.message); + } +} + +// testRestoreRun('1d3829715bda4e4eb257f68363dacfa6'); + +async function testGetRun(run_id) { + try { + const run = await myRunClient.getRun(run_id); + console.log('Fetched run ID: ', run); + } catch (error) { + console.error('Error:', error.message); + } +} + +// testGetRun('0577e22f02e24d24b62949625306c256'); + +async function testUpdateRun(run_id, status, end_time, run_name) { + try { + const updatedRun = await myRunClient.updateRun( + run_id, + status, + end_time, + run_name + ); + console.log('Updated run: ', updatedRun); + } catch (error) { + console.error('Error:', error.message); + } +} + +// await myRunClient.updateRun( +// '9acc6e77bc0c4273ab2105e8e6adc38b', +// 'FINISHED', +// '1631234567890', +// 'hey' +// ); + +async function testLogMetric(run_id, key, value) { + try { + const loggedMetric = await myRunClient.logMetric(run_id, key, value); + console.log('Metric logged successfully'); + } catch (error) { + console.error('Error: ', error.message); + } +} + +// testLogMetric('69c2298a1a374e989806ea89ab2b892a', 'metric-01', 0.9); + +async function testLogBatch(run_id, metrics, params, tags) { + try { + await myRunClient.logBatch(run_id, metrics, params, tags); + } catch (error) { + console.error('Error in testLogBatch: ', error); + } +} + +// testLogBatch('521098fe3c6f42ee81fdb82cc1437fef'); +// testLogBatch( +// '0577e22f02e24d24b62949625306c256', +// [ +// { key: 'mae', value: 2.5, timestamp: 1552550804 }, +// { key: 'rmse', value: 2.7, timestamp: 1552550804 }, +// ], +// [{ key: 'model_class', value: 'LogisticRegression' }] +// ); +// testLogBatch( +// '1d3829715bda4e4eb257f68363dacfa6', +// [ +// { key: 'mae', value: 2.2, timestamp: 1552550804 }, +// { key: 'rmse', value: 2.9, timestamp: 1552550804 }, +// ], +// [{ key: 'model_class', value: 'LogisticRegression' }], +// [{ key: 'tag_name', value: 'testing' }] +// ); + +async function testLogModel(run_id, model_json) { + try { + const modelJson = JSON.stringify(model_json); + + await myRunClient.logModel(run_id, modelJson); + console.log('Model logged successfully.'); + } catch (error) { + console.error('Error: ', error); + } +} + +// testLogModel('69c2298a1a374e989806ea89ab2b892a', { +// artifact_path: 'model', +// flavors: { +// python_function: { +// model_path: 'model.pkl', +// loader_module: 'mlflow.sklearn', +// python_version: '3.8.10', +// }, +// // sklearn: { +// // sklearn_version: '0.19.1', +// // pickled_model: 'model.pkl', +// // }, +// }, +// run_id: '69c2298a1a374e989806ea89ab2b892a', +// utc_time_created: '2024-08-28 12:00:00.000000', +// }); + +async function testLogInputs(run_id, datasets) { + try { + await myRunClient.logInputs(run_id, datasets); + console.log('Datasets logged successfully.'); + } catch (error) { + console.error('Error logging datasets: ', error.message); + } +} + +// testLogInputs('4a6e21f64d9d4201b157e838501b8d9c', [ +// { +// name: 'wine quality - white', +// source: +// 'https://raw.githubusercontent.com/mlflow/mlflow/master/tests/datasets/winequality-white.csv', +// targets: 'quality', +// schema: { +// columns: [ +// { name: 'fixed acidity', type: 'double' }, +// { name: 'volatile acidity', type: 'double' }, +// { name: 'citric acid', type: 'double' }, +// { name: 'residual sugar', type: 'double' }, +// { name: 'chlorides', type: 'double' }, +// { name: 'free sulfur dioxide', type: 'double' }, +// { name: 'total sulfur dioxide', type: 'double' }, +// { name: 'density', type: 'double' }, +// { name: 'pH', type: 'double' }, +// { name: 'sulphates', type: 'double' }, +// { name: 'alcohol', type: 'double' }, +// { name: 'quality', type: 'long' }, +// ], +// }, +// // profile: { +// // num_rows: rawData.length, +// // num_elements: rawData.length * Object.keys(rawData[0]).length, +// // }, +// }, +// ]); + +// https://mlflow.org/docs/latest/python_api/mlflow.data.html#mlflow.data.dataset.Dataset diff --git a/mlflow/src/workflows/RunManager_testFile.js b/mlflow/tests/RunManagerTestFile.js similarity index 83% rename from mlflow/src/workflows/RunManager_testFile.js rename to mlflow/tests/RunManagerTestFile.js index b2c1b0a4..bb79a602 100644 --- a/mlflow/src/workflows/RunManager_testFile.js +++ b/mlflow/tests/RunManagerTestFile.js @@ -1,5 +1,5 @@ -import { RunManager } from './RunManager.js'; -import { RunClient } from '../tracking_server/RunClient.js'; +import { RunManager } from '../src/workflows/RunManager.js'; +import { RunClient } from '../src/tracking_server/RunClient.js'; const trackingUri = 'http://127.0.0.1:5000'; const path = '/api/2.0/mlflow'; @@ -8,14 +8,15 @@ const path = '/api/2.0/mlflow'; const ab = new RunManager(trackingUri); const myRunClient = new RunClient(trackingUri); -// testing searchRuns method +// // testing searchRuns method // const runs = await myRunClient.searchRuns( // ['284209273010848955'], -// 'metrics.loss > 0.2' +// 'metrics.loss > 0.2', +// 'loss' // ); // console.log('Search runs result: ', runs); -// // dry run (simulation) +// // // dry run (simulation) // try { // const result = await ab.cleanupRuns( // ['284209273010848955'], diff --git a/mlflow/tsconfig.json b/mlflow/tsconfig.json index 92bd6038..4ed6fb91 100644 --- a/mlflow/tsconfig.json +++ b/mlflow/tsconfig.json @@ -49,6 +49,10 @@ "removeComments": false, "allowJs": false }, - "include": ["src/**/*"], + "include": [ + "src/**/*", + "tests/RunManager_testFile.js", + "tests/RunClient_testFile.js" + ], "exclude": ["node_modules", "**/*.spec.ts"] -} \ No newline at end of file +} From 485cf0fd7fc71ca9ec0839c2b2b7963dae6df3c8 Mon Sep 17 00:00:00 2001 From: Stephany Ho <36724788+seneyu@users.noreply.github.com> Date: Thu, 12 Sep 2024 22:04:41 -0400 Subject: [PATCH 070/357] Delete mlflow/tsconfig.json --- mlflow/tsconfig.json | 58 -------------------------------------------- 1 file changed, 58 deletions(-) delete mode 100644 mlflow/tsconfig.json diff --git a/mlflow/tsconfig.json b/mlflow/tsconfig.json deleted file mode 100644 index 4ed6fb91..00000000 --- a/mlflow/tsconfig.json +++ /dev/null @@ -1,58 +0,0 @@ -{ - "compilerOptions": { - // Basic Options - "target": "ES2018", - "module": "ESNext", - "lib": ["ES2018"], - "outDir": "./lib", - "rootDir": "./src", - - // Module Resolution Options - "moduleResolution": "node", - "baseUrl": "./src", - "paths": { - "*": ["*"] - }, - "esModuleInterop": true, - "resolveJsonModule": true, - "moduleDetection": "force", - - // Strict Type-Checking Options - "strict": true, - "noImplicitAny": true, - "strictNullChecks": true, - "strictFunctionTypes": true, - "strictBindCallApply": true, - "strictPropertyInitialization": true, - "noImplicitThis": true, - "alwaysStrict": true, - - // Additional Checks - "noUnusedLocals": true, - "noUnusedParameters": true, - "noImplicitReturns": true, - "noFallthroughCasesInSwitch": true, - - // Experimental Options - "experimentalDecorators": true, - "emitDecoratorMetadata": true, - - // Advanced Options - "forceConsistentCasingInFileNames": true, - "skipLibCheck": true, - - // Source Map Options - "sourceMap": false, - - // Other Options - "declaration": true, - "removeComments": false, - "allowJs": false - }, - "include": [ - "src/**/*", - "tests/RunManager_testFile.js", - "tests/RunClient_testFile.js" - ], - "exclude": ["node_modules", "**/*.spec.ts"] -} From 437653064440c22d715f560f1268a2c86568dee9 Mon Sep 17 00:00:00 2001 From: Yiqun Zheng Date: Thu, 12 Sep 2024 19:28:05 -0700 Subject: [PATCH 071/357] small change on test file --- mlflow/tests/model_registry_test.js | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/mlflow/tests/model_registry_test.js b/mlflow/tests/model_registry_test.js index 3b7d08c4..49c8b817 100644 --- a/mlflow/tests/model_registry_test.js +++ b/mlflow/tests/model_registry_test.js @@ -1,10 +1,9 @@ // import ModelRegistry from '../src/model_registry/model_registry.js'; import ModelRegistryClient from '../lib/model_registry/ModelRegistryClient.js'; -/** questions/issues: - * 1. need to manually change the import path by adding .js extension in the complied js file, - * since ts doesn't take extension and when ts is getting compiled, .js is not added automatically; - * 2. await error below with this imported compiled file: await' has no effect on the type of this expression.ts(80007) +/** issue: + * need to manually change the import path by adding .js extension in the complied js file, + * since ts file doesn't accept extension, and when ts is being compiled, extension is not added automatically; * */ async function main() { @@ -14,10 +13,11 @@ async function main() { try { // Create a new registered model - const createdModel = await modelRegistry.createRegisteredModel; - 'MyModel1', + const createdModel = await modelRegistry.createRegisteredModel( + 'MyModel1', [{ key: 'framework', value: 'pytorch' }], - 'My first registered model'; + 'My first registered model' + ); console.log('Created model:', createdModel); // // Get the registered model From fe1c5ef0445e48b6971e30a7a72414c0cdc0626b Mon Sep 17 00:00:00 2001 From: Yiqun Zheng Date: Thu, 12 Sep 2024 19:31:51 -0700 Subject: [PATCH 072/357] renamed model-registry and tracking dirs --- .../src/{model_registry => model-registry}/ModelRegistryClient.ts | 0 mlflow/src/{model_registry => model-registry}/model_registry.js | 0 .../model_version_management.js | 0 mlflow/src/{tracking_server => tracking}/experiment_management.js | 0 mlflow/src/{tracking_server => tracking}/run_management.js | 0 5 files changed, 0 insertions(+), 0 deletions(-) rename mlflow/src/{model_registry => model-registry}/ModelRegistryClient.ts (100%) rename mlflow/src/{model_registry => model-registry}/model_registry.js (100%) rename mlflow/src/{model_registry => model-registry}/model_version_management.js (100%) rename mlflow/src/{tracking_server => tracking}/experiment_management.js (100%) rename mlflow/src/{tracking_server => tracking}/run_management.js (100%) diff --git a/mlflow/src/model_registry/ModelRegistryClient.ts b/mlflow/src/model-registry/ModelRegistryClient.ts similarity index 100% rename from mlflow/src/model_registry/ModelRegistryClient.ts rename to mlflow/src/model-registry/ModelRegistryClient.ts diff --git a/mlflow/src/model_registry/model_registry.js b/mlflow/src/model-registry/model_registry.js similarity index 100% rename from mlflow/src/model_registry/model_registry.js rename to mlflow/src/model-registry/model_registry.js diff --git a/mlflow/src/model_registry/model_version_management.js b/mlflow/src/model-registry/model_version_management.js similarity index 100% rename from mlflow/src/model_registry/model_version_management.js rename to mlflow/src/model-registry/model_version_management.js diff --git a/mlflow/src/tracking_server/experiment_management.js b/mlflow/src/tracking/experiment_management.js similarity index 100% rename from mlflow/src/tracking_server/experiment_management.js rename to mlflow/src/tracking/experiment_management.js diff --git a/mlflow/src/tracking_server/run_management.js b/mlflow/src/tracking/run_management.js similarity index 100% rename from mlflow/src/tracking_server/run_management.js rename to mlflow/src/tracking/run_management.js From 05ad6cd340bf2e9f88e6555592b3d318be815fdc Mon Sep 17 00:00:00 2001 From: Yiqun Zheng Date: Thu, 12 Sep 2024 19:37:56 -0700 Subject: [PATCH 073/357] rename dirs --- .../src/{model_registry => model-registry}/ModelRegistryClient.ts | 0 mlflow/src/{model_registry => model-registry}/model_registry.js | 0 .../model_version_management.js | 0 mlflow/src/{tracking_server => tracking}/ExperimentClient.js | 0 mlflow/src/{tracking_server => tracking}/RunClient.js | 0 mlflow/src/{tracking_server => tracking}/experiment_management.js | 0 mlflow/src/{tracking_server => tracking}/run_management.js | 0 7 files changed, 0 insertions(+), 0 deletions(-) rename mlflow/src/{model_registry => model-registry}/ModelRegistryClient.ts (100%) rename mlflow/src/{model_registry => model-registry}/model_registry.js (100%) rename mlflow/src/{model_registry => model-registry}/model_version_management.js (100%) rename mlflow/src/{tracking_server => tracking}/ExperimentClient.js (100%) rename mlflow/src/{tracking_server => tracking}/RunClient.js (100%) rename mlflow/src/{tracking_server => tracking}/experiment_management.js (100%) rename mlflow/src/{tracking_server => tracking}/run_management.js (100%) diff --git a/mlflow/src/model_registry/ModelRegistryClient.ts b/mlflow/src/model-registry/ModelRegistryClient.ts similarity index 100% rename from mlflow/src/model_registry/ModelRegistryClient.ts rename to mlflow/src/model-registry/ModelRegistryClient.ts diff --git a/mlflow/src/model_registry/model_registry.js b/mlflow/src/model-registry/model_registry.js similarity index 100% rename from mlflow/src/model_registry/model_registry.js rename to mlflow/src/model-registry/model_registry.js diff --git a/mlflow/src/model_registry/model_version_management.js b/mlflow/src/model-registry/model_version_management.js similarity index 100% rename from mlflow/src/model_registry/model_version_management.js rename to mlflow/src/model-registry/model_version_management.js diff --git a/mlflow/src/tracking_server/ExperimentClient.js b/mlflow/src/tracking/ExperimentClient.js similarity index 100% rename from mlflow/src/tracking_server/ExperimentClient.js rename to mlflow/src/tracking/ExperimentClient.js diff --git a/mlflow/src/tracking_server/RunClient.js b/mlflow/src/tracking/RunClient.js similarity index 100% rename from mlflow/src/tracking_server/RunClient.js rename to mlflow/src/tracking/RunClient.js diff --git a/mlflow/src/tracking_server/experiment_management.js b/mlflow/src/tracking/experiment_management.js similarity index 100% rename from mlflow/src/tracking_server/experiment_management.js rename to mlflow/src/tracking/experiment_management.js diff --git a/mlflow/src/tracking_server/run_management.js b/mlflow/src/tracking/run_management.js similarity index 100% rename from mlflow/src/tracking_server/run_management.js rename to mlflow/src/tracking/run_management.js From 31d1c82f9a8f4b9ef81f6160aeca524fffbe1ce6 Mon Sep 17 00:00:00 2001 From: Yiqun Zheng Date: Thu, 12 Sep 2024 19:46:00 -0700 Subject: [PATCH 074/357] changed import path --- mlflow/src/workflows/ExperimentManager.js | 4 ++-- mlflow/src/workflows/ModelManager.js | 4 ++-- mlflow/src/workflows/RunManager.js | 4 ++-- mlflow/tests/ExperimentManager_testFile.js | 2 +- mlflow/tests/RunClientTestFile.js | 2 +- mlflow/tests/{test.js => RunClientTestKyler.js} | 2 +- mlflow/tests/RunManagerTestFile.js | 2 +- mlflow/tests/model_registry_test.js | 4 ++-- 8 files changed, 12 insertions(+), 12 deletions(-) rename mlflow/tests/{test.js => RunClientTestKyler.js} (95%) diff --git a/mlflow/src/workflows/ExperimentManager.js b/mlflow/src/workflows/ExperimentManager.js index 108461fe..60328e99 100644 --- a/mlflow/src/workflows/ExperimentManager.js +++ b/mlflow/src/workflows/ExperimentManager.js @@ -1,5 +1,5 @@ -import { ExperimentClient } from '../tracking_server/ExperimentClient.js'; -import { RunManagement } from '../tracking_server/run_management.js'; +import { ExperimentClient } from '../tracking/ExperimentClient.js'; +import { RunManagement } from '../tracking/run_management.js'; const MLFLOW_TRACKING_URI = 'http://localhost:5001'; const experimentClient = new ExperimentClient(MLFLOW_TRACKING_URI); const runManagement = new RunManagement(MLFLOW_TRACKING_URI); diff --git a/mlflow/src/workflows/ModelManager.js b/mlflow/src/workflows/ModelManager.js index 51999fde..e01ab0cf 100644 --- a/mlflow/src/workflows/ModelManager.js +++ b/mlflow/src/workflows/ModelManager.js @@ -1,5 +1,5 @@ -import { ModelRegistry } from '../model_registry/model_registry.js'; -import { ModelVersionManagement } from '../model_registry/model_version_management.js'; +import { ModelRegistry } from '../model-registry/model_registry.js'; +import { ModelVersionManagement } from '../model-registry/model_version_management.js'; class ModelManager { constructor(trackingUri) { diff --git a/mlflow/src/workflows/RunManager.js b/mlflow/src/workflows/RunManager.js index fe2c23d9..c0ee3926 100644 --- a/mlflow/src/workflows/RunManager.js +++ b/mlflow/src/workflows/RunManager.js @@ -1,5 +1,5 @@ -import { RunClient } from '../tracking_server/RunClient.js'; -import { ModelVersionManagement } from '../model_registry/model_version_management.js'; +import { RunClient } from '../tracking/RunClient.js'; +import { ModelVersionManagement } from '../model-registry/model_version_management.js'; class RunManager { constructor(trackingUri) { diff --git a/mlflow/tests/ExperimentManager_testFile.js b/mlflow/tests/ExperimentManager_testFile.js index 088b3259..d387d77f 100644 --- a/mlflow/tests/ExperimentManager_testFile.js +++ b/mlflow/tests/ExperimentManager_testFile.js @@ -1,5 +1,5 @@ import { ExperimentManager } from '../src/workflows/ExperimentManager.js'; -import { ExperimentClient } from '../src/tracking_server/ExperimentClient.js'; +import { ExperimentClient } from '../src/tracking/ExperimentClient.js'; const MLFLOW_TRACKING_URI = 'http://localhost:5001'; const experimentManager = new ExperimentManager(MLFLOW_TRACKING_URI); const experimentClient = new ExperimentClient(MLFLOW_TRACKING_URI); diff --git a/mlflow/tests/RunClientTestFile.js b/mlflow/tests/RunClientTestFile.js index e950b001..1f6bc5b4 100644 --- a/mlflow/tests/RunClientTestFile.js +++ b/mlflow/tests/RunClientTestFile.js @@ -1,4 +1,4 @@ -import { RunClient } from '../src/tracking_server/RunClient.js'; +import { RunClient } from '../src/tracking/RunClient.js'; const myRunClient = new RunClient('http://127.0.0.1:5000'); diff --git a/mlflow/tests/test.js b/mlflow/tests/RunClientTestKyler.js similarity index 95% rename from mlflow/tests/test.js rename to mlflow/tests/RunClientTestKyler.js index 9d89127a..402c8400 100644 --- a/mlflow/tests/test.js +++ b/mlflow/tests/RunClientTestKyler.js @@ -1,4 +1,4 @@ -import { RunManagement } from '../src/tracking_server/run_management.js'; +import { RunManagement } from '../src/tracking/run_management.js'; let domain = 'http://localhost:'; const port = 5001; diff --git a/mlflow/tests/RunManagerTestFile.js b/mlflow/tests/RunManagerTestFile.js index bb79a602..03504dc6 100644 --- a/mlflow/tests/RunManagerTestFile.js +++ b/mlflow/tests/RunManagerTestFile.js @@ -1,5 +1,5 @@ import { RunManager } from '../src/workflows/RunManager.js'; -import { RunClient } from '../src/tracking_server/RunClient.js'; +import { RunClient } from '../src/tracking/RunClient.js'; const trackingUri = 'http://127.0.0.1:5000'; const path = '/api/2.0/mlflow'; diff --git a/mlflow/tests/model_registry_test.js b/mlflow/tests/model_registry_test.js index 49c8b817..9e50582e 100644 --- a/mlflow/tests/model_registry_test.js +++ b/mlflow/tests/model_registry_test.js @@ -1,5 +1,5 @@ -// import ModelRegistry from '../src/model_registry/model_registry.js'; -import ModelRegistryClient from '../lib/model_registry/ModelRegistryClient.js'; +// import ModelRegistry from '../src/model-registry/model_registry.js'; +import ModelRegistryClient from '../lib/model-registry/ModelRegistryClient.js'; /** issue: * need to manually change the import path by adding .js extension in the complied js file, From 7e16070a1d5d6335fd03958a07da50359b231665 Mon Sep 17 00:00:00 2001 From: Yiqun Zheng Date: Fri, 13 Sep 2024 17:04:42 -0700 Subject: [PATCH 075/357] added back tsconfig., path name for a test file, pushed mlflow-website dir --- mlflow-website/.gitignore | 5 +++ mlflow-website/package.json | 11 +++++ mlflow/tests/ExperimentClient_testFile.js | 2 +- mlflow/tsconfig.json | 54 +++++++++++++++++++++++ 4 files changed, 71 insertions(+), 1 deletion(-) create mode 100644 mlflow-website/.gitignore create mode 100644 mlflow-website/package.json create mode 100644 mlflow/tsconfig.json diff --git a/mlflow-website/.gitignore b/mlflow-website/.gitignore new file mode 100644 index 00000000..6978e875 --- /dev/null +++ b/mlflow-website/.gitignore @@ -0,0 +1,5 @@ +# Dependencies +node_modules/ + +# Misc +.DS_Store \ No newline at end of file diff --git a/mlflow-website/package.json b/mlflow-website/package.json new file mode 100644 index 00000000..5a18a8d4 --- /dev/null +++ b/mlflow-website/package.json @@ -0,0 +1,11 @@ +{ + "name": "mlflow-website", + "version": "1.0.0", + "description": "website for mlflow-js", + "main": "index.js", + "scripts": { + "test": "echo \"Error: no test specified\" && exit 1" + }, + "author": "", + "license": "MIT" +} diff --git a/mlflow/tests/ExperimentClient_testFile.js b/mlflow/tests/ExperimentClient_testFile.js index 9f31fca5..efd6c204 100644 --- a/mlflow/tests/ExperimentClient_testFile.js +++ b/mlflow/tests/ExperimentClient_testFile.js @@ -1,4 +1,4 @@ -import { ExperimentClient } from '../src/tracking_server/ExperimentClient.js'; +import { ExperimentClient } from '../src/tracking/ExperimentClient.js'; const MLFLOW_TRACKING_URI = 'http://localhost:5001'; let experimentClient = new ExperimentClient(MLFLOW_TRACKING_URI); diff --git a/mlflow/tsconfig.json b/mlflow/tsconfig.json new file mode 100644 index 00000000..c57ccb46 --- /dev/null +++ b/mlflow/tsconfig.json @@ -0,0 +1,54 @@ +{ + "compilerOptions": { + // Basic Options + "target": "ES2018", + "module": "ESNext", + "lib": ["ES2018"], + "outDir": "./lib", + "rootDir": "./src", + + // Module Resolution Options + "moduleResolution": "node", + "baseUrl": "./src", + "paths": { + "*": ["*"] + }, + "esModuleInterop": true, + "resolveJsonModule": true, + "moduleDetection": "force", + + // Strict Type-Checking Options + "strict": true, + "noImplicitAny": true, + "strictNullChecks": true, + "strictFunctionTypes": true, + "strictBindCallApply": true, + "strictPropertyInitialization": true, + "noImplicitThis": true, + "alwaysStrict": true, + + // Additional Checks + "noUnusedLocals": true, + "noUnusedParameters": true, + "noImplicitReturns": true, + "noFallthroughCasesInSwitch": true, + + // Experimental Options + "experimentalDecorators": true, + "emitDecoratorMetadata": true, + + // Advanced Options + "forceConsistentCasingInFileNames": true, + "skipLibCheck": true, + + // Source Map Options + "sourceMap": false, + + // Other Options + "declaration": true, + "removeComments": false, + "allowJs": false + }, + "include": ["src/**/*"], + "exclude": ["node_modules", "**/*.spec.ts"] +} From 98793fdfdca421e2416c29b5d02e43e5ce359326 Mon Sep 17 00:00:00 2001 From: Yiqun Zheng Date: Fri, 13 Sep 2024 17:08:11 -0700 Subject: [PATCH 076/357] removed mlflow-website dir --- mlflow-website/.gitignore | 5 ----- mlflow-website/package.json | 11 ----------- 2 files changed, 16 deletions(-) delete mode 100644 mlflow-website/.gitignore delete mode 100644 mlflow-website/package.json diff --git a/mlflow-website/.gitignore b/mlflow-website/.gitignore deleted file mode 100644 index 6978e875..00000000 --- a/mlflow-website/.gitignore +++ /dev/null @@ -1,5 +0,0 @@ -# Dependencies -node_modules/ - -# Misc -.DS_Store \ No newline at end of file diff --git a/mlflow-website/package.json b/mlflow-website/package.json deleted file mode 100644 index 5a18a8d4..00000000 --- a/mlflow-website/package.json +++ /dev/null @@ -1,11 +0,0 @@ -{ - "name": "mlflow-website", - "version": "1.0.0", - "description": "website for mlflow-js", - "main": "index.js", - "scripts": { - "test": "echo \"Error: no test specified\" && exit 1" - }, - "author": "", - "license": "MIT" -} From 42c01b26935b89b8e20221f19f6c0dd96795c693 Mon Sep 17 00:00:00 2001 From: Yiqun Zheng <16813562+yiqunzheng@users.noreply.github.com> Date: Mon, 16 Sep 2024 15:11:31 -0700 Subject: [PATCH 077/357] test file changes: revised comments, fixed an import path --- mlflow/src/model-registry/ModelRegistryClient.ts | 1 + mlflow/tests/ModelRegistryClientTest.ts | 3 ++- mlflow/tests/model_registry_test.js | 5 ++--- 3 files changed, 5 insertions(+), 4 deletions(-) diff --git a/mlflow/src/model-registry/ModelRegistryClient.ts b/mlflow/src/model-registry/ModelRegistryClient.ts index a5c0817f..00cea337 100644 --- a/mlflow/src/model-registry/ModelRegistryClient.ts +++ b/mlflow/src/model-registry/ModelRegistryClient.ts @@ -46,6 +46,7 @@ class ModelRegistryClient { * * @param name - The name of the registered model to retrieve (required) * @returns The registered model object + * @throws Error - If the API request fails */ async getRegisteredModel(name: string): Promise { const { response, data } = await apiRequest( diff --git a/mlflow/tests/ModelRegistryClientTest.ts b/mlflow/tests/ModelRegistryClientTest.ts index 3ee3791a..a8500eaa 100644 --- a/mlflow/tests/ModelRegistryClientTest.ts +++ b/mlflow/tests/ModelRegistryClientTest.ts @@ -1,4 +1,5 @@ -import ModelRegistryClient from '../src/model_registry/ModelRegistryClient'; +// note: npx tsx +import ModelRegistryClient from '../src/model-registry/ModelRegistryClient'; async function testModelRegistryClient() { const client = new ModelRegistryClient('http://localhost:5001'); diff --git a/mlflow/tests/model_registry_test.js b/mlflow/tests/model_registry_test.js index 9e50582e..ed8c6669 100644 --- a/mlflow/tests/model_registry_test.js +++ b/mlflow/tests/model_registry_test.js @@ -2,9 +2,8 @@ import ModelRegistryClient from '../lib/model-registry/ModelRegistryClient.js'; /** issue: - * need to manually change the import path by adding .js extension in the complied js file, - * since ts file doesn't accept extension, and when ts is being compiled, extension is not added automatically; - * */ + * need to manually add .js extension in the complied ModelRegistryClient.js file + */ async function main() { const trackingUri = 'http://localhost:5001'; From e07f5797a902ba46d434e7fd8378b771c7d0c550 Mon Sep 17 00:00:00 2001 From: Yiqun Zheng <16813562+yiqunzheng@users.noreply.github.com> Date: Mon, 16 Sep 2024 16:29:47 -0700 Subject: [PATCH 078/357] revised .gitignore and added a temp folder --- mlflow/.gitignore | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/mlflow/.gitignore b/mlflow/.gitignore index d9998bb7..845fa117 100644 --- a/mlflow/.gitignore +++ b/mlflow/.gitignore @@ -8,5 +8,8 @@ node_modules/ .venv/ mlruns/ -# Temp -lib/ \ No newline at end of file +# Build output +lib/ + +# Temporary files +temp/ From 6502444c226d326117a7e128de0958b3d1f81bb2 Mon Sep 17 00:00:00 2001 From: Yiqun Zheng <16813562+yiqunzheng@users.noreply.github.com> Date: Mon, 30 Sep 2024 17:15:13 -0700 Subject: [PATCH 079/357] move my test file to temp --- mlflow/tests/model_registry_test.js | 77 ----------------------------- 1 file changed, 77 deletions(-) delete mode 100644 mlflow/tests/model_registry_test.js diff --git a/mlflow/tests/model_registry_test.js b/mlflow/tests/model_registry_test.js deleted file mode 100644 index ed8c6669..00000000 --- a/mlflow/tests/model_registry_test.js +++ /dev/null @@ -1,77 +0,0 @@ -// import ModelRegistry from '../src/model-registry/model_registry.js'; -import ModelRegistryClient from '../lib/model-registry/ModelRegistryClient.js'; - -/** issue: - * need to manually add .js extension in the complied ModelRegistryClient.js file - */ - -async function main() { - const trackingUri = 'http://localhost:5001'; - // const modelRegistry = new ModelRegistry(trackingUri); - const modelRegistry = new ModelRegistryClient(trackingUri); - - try { - // Create a new registered model - const createdModel = await modelRegistry.createRegisteredModel( - 'MyModel1', - [{ key: 'framework', value: 'pytorch' }], - 'My first registered model' - ); - console.log('Created model:', createdModel); - - // // Get the registered model - // const retrievedModel = await modelRegistry.getRegisteredModel( - // 'sk-learn-random-forest-reg-model' - // ); - // console.log('Retrieved model:', retrievedModel); - - // // Rename the registered model - // const renamedModel = await modelRegistry.renameRegisteredModel( - // 'MyModel6', - // 'MyModel6New' - // ); - // console.log('Renamed model:', renamedModel); - - // // Update the model description - // const updatedModel = await modelRegistry.updateRegisteredModel( - // 'sk-learn-random-forest-reg-model', - // 'From tutorial sklearn' - // ); - // console.log('Updated model:', updatedModel); - - // // Get latest model versions - // const latestVersions = await modelRegistry.getLatestModelVersions( - // 'sk-learn-random-forest-reg-model' - // ); - // console.log('Latest versions:', latestVersions); - - // // Set a tag on the model - // await modelRegistry.setRegisteredModelTag( - // 'sk-learn-random-forest-reg-model', - // 'key1', - // 'value1' - // ); - // console.log('Tag set successfully'); - - // // Search for models - // const searchResults = await modelRegistry.searchRegisteredModels( - // "name LIKE 'My%'", - // 10, - // ['name ASC'], - // null - // ); - // console.log('Search results:', searchResults); - - // // Delete a tag from the model - // await modelRegistry.deleteRegisteredModelTag('MyNewModel', 'model_type'); - // console.log('Tag deleted successfully'); - - // Delete the model - // await modelRegistry.deleteRegisteredModel('MyModel5New'); - // console.log('Model deleted successfully'); - } catch (error) { - console.error('Error:', error.message); - } -} - -main(); From 1c8b05f3a4e3e4f1a1a7f52247f0eff6d86efc27 Mon Sep 17 00:00:00 2001 From: Austin Fraser Date: Mon, 30 Sep 2024 19:55:35 -0700 Subject: [PATCH 080/357] started TS refactor on ExperimentClient --- mlflow/src/tracking/ExperimentClient.ts | 281 ++++++++++++++++++++++++ 1 file changed, 281 insertions(+) create mode 100644 mlflow/src/tracking/ExperimentClient.ts diff --git a/mlflow/src/tracking/ExperimentClient.ts b/mlflow/src/tracking/ExperimentClient.ts new file mode 100644 index 00000000..c371ee44 --- /dev/null +++ b/mlflow/src/tracking/ExperimentClient.ts @@ -0,0 +1,281 @@ +class ExperimentClient { + constructor(trackingUri) { + this.trackingUri = trackingUri; + } + + /** + * Create an experiment with a name. Returns the ID of the newly created experiment. + * Validates that another experiment with the same name does not already exist and fails if another experiment with the same name already exists. + * + * @param {string} name Experiment name. (required) + * @param {string} artifact_location Optional location where all artifacts for the experiment are stored. If not provided, the remote server will select an appropriate default. + * @param {Array<{key: string, value: string}>} tags Optional collection of tags to set on the experiment. + * @returns {Promise} Returns the ID of the newly created experiment in an object. + */ + async createExperiment(name: string, artifact_location?: string, tags?: string[]) { + if (!name) { + throw new Error('Experiment name is required'); + } + + const url = `${this.trackingUri}/api/2.0/mlflow/experiments/create`; + const response = await fetch(url, { + method: 'POST', + headers: { 'Content-Type': 'application/json' }, + body: JSON.stringify({ name, artifact_location, tags }), + }); + + if (!response.ok) { + const errorBody = await response.json(); + throw new Error( + `Error creating experiment from tracking server, status: ${response.status}. ${errorBody.message}` + ); + } + + const data = await response.json(); + // console.log('return from createExperiment: ', data.experiment_id); + return data.experiment_id; + } + + /** + * Search experiments. + * + * @param {string} filter A filter expression over experiment attributes and tags that allows returning a subset of experiments. The syntax is a subset of SQL. (required) + * @param {int64} max_results Maximum number of experiments desired. (required) + * @param {string} page_token Optional token indicating the page of experiments to fetch. + * @param {Array} order_by Optional list of columns for ordering search results. + * @param {string} view_type Optional qualifier for type of experiments to be returned. See https://mlflow.org/docs/latest/rest-api.html#mlflowviewtype + * @returns {Promise} Returns object containing an array of experiment objects matching the filter, + * and optionally a next_page_token that can be used to retrieve the next page of experiments. + */ + async searchExperiment( + filter, + max_results, + page_token = '', + order_by = [], + view_type = '' + ) { + if (!filter) { + throw new Error('Filter is required'); + } + if (!max_results) { + throw new Error('Max results is required'); + } + + const url = `${this.trackingUri}/api/2.0/mlflow/experiments/search`; + const response = await fetch(url, { + method: 'POST', + headers: { 'Content-Type': 'application/json' }, + body: JSON.stringify({ + filter, + max_results, + page_token, + order_by, + view_type, + }), + }); + + if (!response.ok) { + const errorBody = await response.json(); + throw new Error( + `Error searching for experiment from tracking server, status: ${response.status}. ${errorBody.message}` + ); + } + + const data = await response.json(); + // console.log('return from searchExperiment: ', data); + return data; + } + + /** + * Get metadata for an experiment, querying by experiment ID. This method works on deleted experiments. + * + * @param {string} experiment_id ID of the associated experiment. (required) + * @returns {Promise} Returns object containing the matched experiment. + */ + async getExperiment(experiment_id) { + if (!experiment_id) { + throw new Error('Experiment ID is required'); + } + + const url = `${this.trackingUri}/api/2.0/mlflow/experiments/get?experiment_id=${experiment_id}`; + const response = await fetch(url, { + method: 'GET', + headers: { 'Content-Type': 'application/json' }, + }); + + if (!response.ok) { + const errorBody = await response.json(); + throw new Error( + `Error getting experiment from tracking server, status: ${response.status}. ${errorBody.message}` + ); + } + + const data = await response.json(); + // console.log('return from getExperiment: ', data.experiment); + return data.experiment; + } + + /** + * Get metadata for an experiment, querying by experiment name. + * This endpoint will return deleted experiments, + * but prefers the active experiment if an active and deleted experiment share the same name. + * If multiple deleted experiments share the same name, the API will return one of them. + * + * @param {string} experiment_name ID of the associated experiment. (required) + * @returns {Promise} Returns object containing the matched experiment. + */ + async getExperimentByName(experiment_name) { + if (!experiment_name) { + throw new Error('Experiment name is required'); + } + + const url = `${this.trackingUri}/api/2.0/mlflow/experiments/get-by-name?experiment_name=${experiment_name}`; + const response = await fetch(url, { + method: 'GET', + headers: { 'Content-Type': 'application/json' }, + }); + + if (!response.ok) { + const errorBody = await response.json(); + throw new Error( + `Error getting experiment by name from tracking server, status: ${response.status}. ${errorBody.message}` + ); + } + + const data = await response.json(); + // console.log('return from getExperimentByName: ', data.experiment); + return data.experiment; + } + + /** + * Mark an experiment for deletion. + * + * @param {string} experiment_id ID of the associated experiment. (required) + * @returns {void} + */ + async deleteExperiment(experiment_id) { + if (!experiment_id) { + throw new Error('Experiment ID is required'); + } + + const url = `${this.trackingUri}/api/2.0/mlflow/experiments/delete`; + const response = await fetch(url, { + method: 'POST', + headers: { 'Content-Type': 'application/json' }, + body: JSON.stringify({ experiment_id }), + }); + + if (!response.ok) { + const errorBody = await response.json(); + throw new Error( + `Error deleting experiment from tracking server, status: ${response.status}. ${errorBody.message}` + ); + } + + console.log(`Experiment ID ${experiment_id} successfully deleted`); + // return `Experiment ID ${experiment_id} successfully deleted`; + } + + /** + * Restore an experiment marked for deletion. + * + * @param {string} experiment_id ID of the associated experiment. (required) + * @returns {void} + */ + async restoreExperiment(experiment_id) { + if (!experiment_id) { + throw new Error('Experiment ID is required'); + } + + const url = `${this.trackingUri}/api/2.0/mlflow/experiments/restore`; + const response = await fetch(url, { + method: 'POST', + headers: { 'Content-Type': 'application/json' }, + body: JSON.stringify({ experiment_id }), + }); + + if (!response.ok) { + const errorBody = await response.json(); + throw new Error( + `Error restoring experiment from tracking server, status: ${response.status}. ${errorBody.message}` + ); + } + + console.log(`Experiment ID ${experiment_id} successfully restored`); + // return `Experiment ID ${experiment_id} successfully restored`; + } + + /** + * Update experiment name. + * + * @param {string} experiment_id ID of the associated experiment. (required) + * @param {string} new_name The experiment’s name is changed to the new name. The new name must be unique. (required) + * @returns {void} + */ + async updateExperiment(experiment_id, new_name) { + if (!experiment_id) { + throw new Error('Experiment ID is required'); + } + if (!new_name) { + throw new Error('New name is required'); + } + + const url = `${this.trackingUri}/api/2.0/mlflow/experiments/update`; + const response = await fetch(url, { + method: 'POST', + headers: { 'Content-Type': 'application/json' }, + body: JSON.stringify({ experiment_id, new_name }), + }); + + if (!response.ok) { + const errorBody = await response.json(); + throw new Error( + `Error updating experiment from tracking server, status: ${response.status}. ${errorBody.message}` + ); + } + + console.log( + `Experiment ID ${experiment_id} successfully updated - new name is ${new_name}` + ); + // return `Experiment ID ${experiment_id} successfully updated - new name is ${new_name}`; + } + + /** + * Set a tag on an experiment. + * + * @param {string} experiment_id ID of the experiment under which to log the tag. (required) + * @param {string} key Name of the tag. (required) + * @param {string} value String value of the tag being logged. (required) + * @returns {void} + */ + async setExperimentTag(experiment_id, key, value) { + if (!experiment_id) { + throw new Error('Experiment ID is required'); + } + if (!key) { + throw new Error('Key is required'); + } + if (!value) { + throw new Error('Value is required'); + } + + const url = `${this.trackingUri}/api/2.0/mlflow/experiments/set-experiment-tag`; + const response = await fetch(url, { + method: 'POST', + headers: { 'Content-Type': 'application/json' }, + body: JSON.stringify({ experiment_id, key, value }), + }); + + if (!response.ok) { + const errorBody = await response.json(); + throw new Error( + `Error setting tag from tracking server, status: ${response.status}. ${errorBody.message}` + ); + } + + console.log(`Set tag to experiment ID ${experiment_id} successfully`); + // return `Set tag to experiment ID ${experiment_id} successfully`; + } +} + +export { ExperimentClient }; From 63a5fef2383cb63796dd016c6834bbc629837dd0 Mon Sep 17 00:00:00 2001 From: Yiqun Zheng <16813562+yiqunzheng@users.noreply.github.com> Date: Tue, 1 Oct 2024 15:41:41 -0700 Subject: [PATCH 081/357] create ModelRegistryClient.ts and its integration test --- .../src/model-registry/ModelRegistryClient.ts | 321 +++++++++++++- mlflow/src/model-registry/model_registry.js | 409 ------------------ mlflow/tests/ModelRegistryClientTest.ts | 197 ++++++++- 3 files changed, 504 insertions(+), 423 deletions(-) delete mode 100644 mlflow/src/model-registry/model_registry.js diff --git a/mlflow/src/model-registry/ModelRegistryClient.ts b/mlflow/src/model-registry/ModelRegistryClient.ts index 00cea337..a45829be 100644 --- a/mlflow/src/model-registry/ModelRegistryClient.ts +++ b/mlflow/src/model-registry/ModelRegistryClient.ts @@ -11,15 +11,15 @@ class ModelRegistryClient { * Creates a new registered model. * * @param name - The name of the model to register (required) - * @param tags - Optional An array of RegisteredModelTag. Each tag is an object with 'key' and 'value' properties. + * @param tags - Optional tags for the model * @param description - Optional description for the model * @returns The created registered model object - * @throws Error - If the API request fails + * @throws Error if the API request fails */ async createRegisteredModel( name: string, - tags: Array<{ key: string; value: string }> = [], - description: string = '' + tags?: Array<{ key: string; value: string }>, + description?: string ): Promise { const { response, data } = await apiRequest( this.baseUrl, @@ -42,11 +42,11 @@ class ModelRegistryClient { } /** - * Gets a registered model. + * Retrieves a registered model by name. * * @param name - The name of the registered model to retrieve (required) * @returns The registered model object - * @throws Error - If the API request fails + * @throws Error if the API request fails */ async getRegisteredModel(name: string): Promise { const { response, data } = await apiRequest( @@ -65,6 +65,313 @@ class ModelRegistryClient { } return data.registered_model; } + + /** + * Renames a registered model. + * + * @param name - The current name of the registered model (required) + * @param newName - The new name for the registered model (required) + * @returns The updated registered model object + * @throws Error if the API request fails + */ + async renameRegisteredModel(name: string, newName: string): Promise { + const { response, data } = await apiRequest( + this.baseUrl, + 'registered-models/rename', + { + method: 'POST', + body: { name, new_name: newName }, + } + ); + + if (!response.ok) { + throw new Error( + `Error renaming registered model: ${ + data.message || response.statusText + }` + ); + } + return data.registered_model; + } + + /** + * Updates a registered model's description. + * + * @param name - The name of the registered model to update (required) + * @param description - The new description for the model + * @returns The updated registered model object + * @throws Error if the API request fails + */ + async updateRegisteredModel( + name: string, + description?: string + ): Promise { + const { response, data } = await apiRequest( + this.baseUrl, + 'registered-models/update', + { + method: 'PATCH', + body: { name, description }, + } + ); + + if (!response.ok) { + throw new Error( + `Error updating registered model: ${ + data.message || response.statusText + }` + ); + } + + return data.registered_model; + } + + /** + * Deletes a registered model. + * + * @param name - The name of the registered model to delete (required) + * @throws Error if the API request fails + */ + async deleteRegisteredModel(name: string): Promise { + const { response, data } = await apiRequest( + this.baseUrl, + 'registered-models/delete', + { + method: 'DELETE', + body: { name }, + } + ); + + if (!response.ok) { + throw new Error( + `Error deleting registered model: ${ + data.message || response.statusText + }` + ); + } + + return; + } + + /** + * Gets the latest versions of a registered model. + * + * @param name - The name of the registered model (required) + * @param stages - Array of stages to filter the versions by + * @returns An array of the latest model versions + * @throws Error if the API request fails + */ + async getLatestModelVersions(name: string, stages?: string[]): Promise { + const { response, data } = await apiRequest( + this.baseUrl, + 'registered-models/get-latest-versions', + { + method: 'POST', + body: { name, stages }, + } + ); + + if (!response.ok) { + throw new Error( + `Error getting latest versions: ${data.message || response.statusText}` + ); + } + + return data.model_versions; + } + + /** + * Searches for registered models based on filter criteria. + * + * @param filter - Filter string to apply to the search + * @param maxResults - Maximum number of results to return + * @param orderBy - Array of fields to order the results by + * @param pageToken - Token for pagination + * @returns An object containing the search results and pagination information + * @throws Error if the API request fails + */ + async searchRegisteredModels( + filter?: string, + maxResults?: number, + orderBy?: string[], + pageToken?: string + ): Promise { + const params: Record = {}; + if (filter) params.filter = filter; + if (maxResults) params.max_results = maxResults.toString(); + if (orderBy) params.order_by = orderBy.join(','); + if (pageToken) params.page_token = pageToken; + + const { response, data } = await apiRequest( + this.baseUrl, + 'registered-models/search', + { + method: 'GET', + params, + } + ); + + if (!response.ok) { + throw new Error( + `Error searching registered models: ${ + data.message || response.statusText + }` + ); + } + + return data; + } + + /** + * Sets a tag on a registered model. + * + * @param name - The name of the registered model (required) + * @param key - The key of the tag (required) + * @param value - The value of the tag (required) + * @throws Error if the API request fails + */ + async setRegisteredModelTag( + name: string, + key: string, + value: string + ): Promise { + const { response, data } = await apiRequest( + this.baseUrl, + 'registered-models/set-tag', + { + method: 'POST', + body: { name, key, value }, + } + ); + + if (!response.ok) { + throw new Error( + `Error setting registered model tag: ${ + data.message || response.statusText + }` + ); + } + + return; + } + + /** + * Deletes a tag from a registered model. + * + * @param name - The name of the registered model (required) + * @param key - The key of the tag to delete (required) + * @throws Error if the API request fails + */ + async deleteRegisteredModelTag(name: string, key: string): Promise { + const { response, data } = await apiRequest( + this.baseUrl, + 'registered-models/delete-tag', + { + method: 'DELETE', + body: { name, key }, + } + ); + + if (!response.ok) { + throw new Error( + `Error deleting registered model tag: ${ + data.message || response.statusText + }` + ); + } + + return; + } + + /** + * Sets an alias for a specific version of a registered model. + * + * @param name - The name of the registered model (required) + * @param alias - The alias to set (required) + * @param version - The version number to associate with the alias (required) + * @throws Error if the API request fails + */ + async setRegisteredModelAlias( + name: string, + alias: string, + version: string + ): Promise { + const { response, data } = await apiRequest( + this.baseUrl, + 'registered-models/alias', + { + method: 'POST', + body: { name, alias, version }, + } + ); + + if (!response.ok) { + throw new Error( + `Error setting registered model alias: ${ + data.message || response.statusText + }` + ); + } + + return; + } + + /** + * Deletes an alias from a registered model. + * + * @param name - The name of the registered model (required) + * @param alias - The alias to delete (required) + * @throws Error if the API request fails + */ + async deleteRegisteredModelAlias(name: string, alias: string): Promise { + const { response, data } = await apiRequest( + this.baseUrl, + 'registered-models/alias', + { + method: 'DELETE', + body: { name, alias }, + } + ); + + if (!response.ok) { + throw new Error( + `Error deleting registered model alias: ${ + data.message || response.statusText + }` + ); + } + + return; + } + + /** + * Retrieves a model version using its alias. + * + * @param name - The name of the registered model (required) + * @param alias - The alias of the model version to retrieve (required) + * @returns The model version object + * @throws Error if the API request fails + */ + async getModelVersionByAlias(name: string, alias: string): Promise { + const { response, data } = await apiRequest( + this.baseUrl, + 'registered-models/alias', + { + method: 'GET', + params: { name, alias }, + } + ); + + if (!response.ok) { + throw new Error( + `Error getting model version by alias: ${ + data.message || response.statusText + }` + ); + } + + return data.model_version; + } } -export default ModelRegistryClient; +export default ModelRegistryClient; \ No newline at end of file diff --git a/mlflow/src/model-registry/model_registry.js b/mlflow/src/model-registry/model_registry.js deleted file mode 100644 index 58b09617..00000000 --- a/mlflow/src/model-registry/model_registry.js +++ /dev/null @@ -1,409 +0,0 @@ -//model_registry.js - -class ModelRegistry { - constructor(trackingUri) { - this.trackingUri = trackingUri; - } - - /** - * Creates a new registered model. - * - * @param {string} name - The name of the model to register (required) - * @param {Array<{key: string, value: string}>} [tags=[]] - Optional tags for the model. - * Must be formatted like: [{"key": "keyName", "value": "valueName"}] - * @param {string} [description=''] - Optional description for the model - * @returns {Promise} The created registered model object - * @throws {Error} - If the API request fails - */ - async createRegisteredModel(name, tags = [], description = '') { - if (!name) { - throw new Error('Model name is required'); - } - - const url = `${this.trackingUri}/api/2.0/mlflow/registered-models/create`; - - const response = await fetch(url, { - method: 'POST', - headers: { - 'Content-Type': 'application/json', - }, - body: JSON.stringify({ name, tags, description }), - }); - - const data = await response.json(); - - if (!response.ok) { - throw new Error( - `Error creating registered model: ${ - data.message || response.statusText - }` - ); - } - return data.registered_model; - } - - /** - * Gets a registered model. - * - * @param {string} name - The name of the registered model to retrieve (required) - * @returns {Promise} The registered model object - */ - async getRegisteredModel(name) { - if (!name) { - throw new Error('Model name is required'); - } - - const url = `${ - this.trackingUri - }/api/2.0/mlflow/registered-models/get?name=${encodeURIComponent(name)}`; - - const response = await fetch(url); - const data = await response.json(); - - if (!response.ok) { - throw new Error( - `Error getting registered model: ${data.message || response.statusText}` - ); - } - - return data.registered_model; - } - - /** - * Renames a registered model. - * Note: As of MLflow 2.15.1 renaming a model may cause it to lose its tags. - * If maintaining tags is crucial, consider re-applying them after renaming. - * - * @param {string} name - The current name of the registered model (required) - * @param {string} newName - The new name for the registered model (required) - * @returns {Promise} The updated registered model object - */ - async renameRegisteredModel(name, newName) { - if (!name || !newName) { - throw new Error('Both current name and new name are required'); - } - - const url = `${this.trackingUri}/api/2.0/mlflow/registered-models/rename`; - - const response = await fetch(url, { - method: 'POST', - headers: { - 'Content-Type': 'application/json', - }, - body: JSON.stringify({ name, new_name: newName }), - }); - - const data = await response.json(); - - if (!response.ok) { - throw new Error( - `Error renaming registered model: ${ - data.message || response.statusText - }` - ); - } - return data.registered_model; - } - - /** - * Updates a registered model. - * - * @param {string} name - The name of the registered model to update (required) - * @param {string} [description] - The new description for the model - * @returns {Promise} The updated registered model object - */ - async updateRegisteredModel(name, description) { - if (!name) { - throw new Error('Model name is required'); - } - - const url = `${this.trackingUri}/api/2.0/mlflow/registered-models/update`; - - const response = await fetch(url, { - method: 'PATCH', - headers: { - 'Content-Type': 'application/json', - }, - body: JSON.stringify({ name, description }), - }); - - const data = await response.json(); - - if (!response.ok) { - throw new Error( - `Error updating registered model: ${ - data.message || response.statusText - }` - ); - } - return data.registered_model; - } - - /** - * Deletes a registered model. - * - * @param {string} name - The name of the registered model to delete (required) - * @returns {Promise} - */ - async deleteRegisteredModel(name) { - if (!name) { - throw new Error('Model name is required'); - } - - const url = `${this.trackingUri}/api/2.0/mlflow/registered-models/delete`; - - const response = await fetch(url, { - method: 'DELETE', - headers: { - 'Content-Type': 'application/json', - }, - body: JSON.stringify({ name }), - }); - - if (!response.ok) { - const data = await response.json(); - throw new Error( - `Error deleting registered model: ${ - data.message || response.statusText - }` - ); - } - } - - /** - * Gets the latest model versions for a registered model. - * - * @param {string} name - The name of the registered model (required) - * @param {Array} [stages=[]] - The stages to get the latest versions from - * @returns {Promise>} The latest model version objects - */ - async getLatestModelVersions(name, stages = []) { - if (!name) { - throw new Error('Model name is required'); - } - - const url = `${this.trackingUri}/api/2.0/mlflow/registered-models/get-latest-versions`; - - const response = await fetch(url, { - method: 'POST', - headers: { - 'Content-Type': 'application/json', - }, - body: JSON.stringify({ name, stages }), - }); - - const data = await response.json(); - - if (!response.ok) { - throw new Error( - `Error getting latest model versions: ${ - data.message || response.statusText - }` - ); - } - return data.model_versions; - } - - /** - * Searches for registered models. - * - * @param {string} [filter] - String filter condition - * @param {number} [maxResults] - Maximum number of models desired - * @param {Array} [orderBy] - List of columns for ordering search results - * @param {string} [pageToken] - Token for pagination - * @returns {Promise} Object containing matching models and next page token - */ - async searchRegisteredModels(filter, maxResults, orderBy, pageToken) { - const params = new URLSearchParams(); - if (filter) params.append('filter', filter); - if (maxResults) params.append('max_results', maxResults); - if (orderBy) params.append('order_by', orderBy.join(',')); - if (pageToken) params.append('page_token', pageToken); - - const url = `${ - this.trackingUri - }/api/2.0/mlflow/registered-models/search?${params.toString()}`; - - const response = await fetch(url); - const data = await response.json(); - - if (!response.ok) { - throw new Error( - `Error searching registered models: ${ - data.message || response.statusText - }` - ); - } - return { - registeredModels: data.registered_models, - nextPageToken: data.next_page_token, - }; - } - - /** - * Sets a tag on a registered model. - * - * @param {string} name - The name of the registered model (required) - * @param {string} key - The tag key (required) - * @param {string} value - The tag value (required) - * @returns {Promise} - */ - async setRegisteredModelTag(name, key, value) { - if (!name || !key || !value) { - throw new Error('Model name, tag key, and tag value are required'); - } - - const url = `${this.trackingUri}/api/2.0/mlflow/registered-models/set-tag`; - - const response = await fetch(url, { - method: 'POST', - headers: { - 'Content-Type': 'application/json', - }, - body: JSON.stringify({ name, key, value }), - }); - - if (!response.ok) { - const data = await response.json(); - throw new Error( - `Error setting registered model tag: ${ - data.message || response.statusText - }` - ); - } - } - - /** - * Deletes a tag from a registered model. - * - * @param {string} name - The name of the registered model (required) - * @param {string} key - The tag key to delete (required) - * @returns {Promise} - */ - async deleteRegisteredModelTag(name, key) { - if (!name || !key) { - throw new Error('Model name and tag key are required'); - } - - const url = `${this.trackingUri}/api/2.0/mlflow/registered-models/delete-tag`; - - const response = await fetch(url, { - method: 'DELETE', - headers: { - 'Content-Type': 'application/json', - }, - body: JSON.stringify({ name, key }), - }); - - if (!response.ok) { - const data = await response.json(); - throw new Error( - `Error deleting registered model tag: ${ - data.message || response.statusText - }` - ); - } - } - - /** - * Sets an alias for a registered model version. - \* - * @param {string} name - The name of the registered model (required) - * @param {string} alias - The alias to set (required) - * @param {string} version - The version number to alias (required) - * @returns {Promise} - */ - async setRegisteredModelAlias(name, alias, version) { - if (!name) { - throw new Error('name is required'); - } else if (!alias) { - throw new Error('alias is required'); - } else if (!version) { - throw new Error('version is required'); - } - - const url = `${this.trackingUri}/api/2.0/mlflow/registered-models/alias`; - const response = await fetch(url, { - method: 'POST', - headers: { - 'Content-Type': 'application/json', - }, - body: JSON.stringify({ name, alias, version }), - }); - - // data is an empty object - const data = await response.json(); - - if (!response.ok) { - throw new Error( - `Error setting model alias: ${data.message || response.statusText}` - ); - } - return data; - } - - /** - * Deletes an alias for a registered model. - \* - * @param {string} name - The name of the registered model (required) - * @param {string} alias - The alias to delete (required) - * @returns {Promise} - */ - async deleteRegisteredModelAlias(name, alias) { - if (!name) { - throw new Error('name is required'); - } else if (!alias) { - throw new Error('alias is required'); - } - - const url = `${this.trackingUri}/api/2.0/mlflow/registered-models/alias`; - const response = await fetch(url, { - method: 'DELETE', - headers: { - 'Content-Type': 'application/json', - }, - body: JSON.stringify({ name, alias }), - }); - - // data is an empty object - const data = await response.json(); - - if (!response.ok) { - throw new Error(`Error deleting model alias: ${response.statusText}`); - } - return data; - } - - /** - * Gets a model version by its alias. - \* - * @param {string} name - The name of the registered model (required) - * @param {string} alias - The alias of the model version to retrieve (required) - * @returns {Promise} The model version object - */ - async getModelVersionByAlias(name, alias) { - if (!name) { - throw new Error('name is required'); - } else if (!alias) { - throw new Error('alias is required'); - } - const url = `${this.trackingUri}/api/2.0/mlflow/registered-models/alias`; - const response = await fetch(`${url}?name=${name}&alias=${alias}`); - - /** - * data has the field: - * model_version - */ - const data = await response.json(); - - if (!response.ok) { - throw new Error( - `Error getting model version by alias: ${ - data.message || response.statusText - }` - ); - } - return data; - } -} -export default ModelRegistry; \ No newline at end of file diff --git a/mlflow/tests/ModelRegistryClientTest.ts b/mlflow/tests/ModelRegistryClientTest.ts index a8500eaa..8967c3c7 100644 --- a/mlflow/tests/ModelRegistryClientTest.ts +++ b/mlflow/tests/ModelRegistryClientTest.ts @@ -1,23 +1,206 @@ -// note: npx tsx import ModelRegistryClient from '../src/model-registry/ModelRegistryClient'; +import apiRequest from '../src/utils/ApiRequest'; + +async function createRun( + client: ModelRegistryClient, + experimentId: string +): Promise { + const { response, data } = await apiRequest( + (client as any).baseUrl, + 'runs/create', + { + method: 'POST', + body: { experiment_id: experimentId }, + } + ); + + if (!response.ok) { + throw new Error( + `Error creating run: ${data.message || response.statusText}` + ); + } + + return data.run; +} + +async function getRun( + client: ModelRegistryClient, + runId: string +): Promise { + const { response, data } = await apiRequest( + (client as any).baseUrl, + 'runs/get', + { + method: 'GET', + params: { run_id: runId }, + } + ); + + if (!response.ok) { + throw new Error( + `Error getting run: ${data.message || response.statusText}` + ); + } + + return data.run; +} + +async function createModelVersion( + client: ModelRegistryClient, + name: string, + source: string, + runId: string +): Promise { + const { response, data } = await apiRequest( + (client as any).baseUrl, + 'model-versions/create', + { + method: 'POST', + body: { name, source, run_id: runId }, + } + ); + + if (!response.ok) { + throw new Error( + `Error creating model version: ${data.message || response.statusText}` + ); + } + + return data.model_version; +} async function testModelRegistryClient() { const client = new ModelRegistryClient('http://localhost:5001'); + const timestamp = Date.now(); + const baseName = `test-model-${timestamp}`; + const renamedBaseName = `renamed-test-model-${timestamp}`; + const customAlias = `test-alias-v1-${timestamp}`; try { - // Test creating a registered model - console.log('Creating a new registered model...'); + // 1. Test creating a registered model + console.log('1. Creating a new registered model...'); const newModel = await client.createRegisteredModel( - 'test-model', + baseName, [{ key: 'test-tag', value: 'test-value' }], 'This is a test model' ); console.log('Created model:', newModel); - // Test getting the registered model - console.log('\nGetting the registered model...'); - const retrievedModel = await client.getRegisteredModel('test-model'); + // 2. Test getting the registered model + console.log('\n2. Getting the registered model...'); + const retrievedModel = await client.getRegisteredModel(baseName); console.log('Retrieved model:', retrievedModel); + + // 3. Test renaming the registered model + console.log('\n3. Renaming the registered model...'); + const renamedModel = await client.renameRegisteredModel( + baseName, + renamedBaseName + ); + console.log('Renamed model:', renamedModel); + + // 4. Test updating the model description + console.log('\n4. Updating the model description...'); + const updatedModel = await client.updateRegisteredModel( + renamedBaseName, + 'Updated description' + ); + console.log('Updated model:', updatedModel); + + // 5. Create a run + console.log('\n5. Creating a run...'); + const run = await createRun(client, '0'); // Using '0' as the default experiment ID + console.log('Created run:', run); + + // 6. Get the run to retrieve the artifact URI + console.log('\n6. Getting run details...'); + const runDetails = await getRun(client, run.info.run_id); + console.log('Run artifact URI:', runDetails.info.artifact_uri); + + // 7. Test creating a model version + console.log('\n7. Creating a model version...'); + const modelVersion = await createModelVersion( + client, + renamedBaseName, + runDetails.info.artifact_uri + '/model', // Assuming 'model' as the artifact path + run.info.run_id + ); + console.log('Created model version:', modelVersion); + + // 8. Test getting latest versions + console.log('\n8. Getting latest versions...'); + const latestVersions = await client.getLatestModelVersions(renamedBaseName); + console.log('Latest versions:', latestVersions); + + // 9. Test searching for models with pagination + console.log('\n9. Searching for models with pagination...'); + + // Create additional models to ensure we have enough for pagination + for (let i = 0; i < 5; i++) { + await client.createRegisteredModel(`${renamedBaseName}-extra-${i}`); + } + + // Perform initial search with a small max_results to force pagination + const initialSearchResults = await client.searchRegisteredModels( + `name LIKE '${renamedBaseName}%'`, + 3, // Small max_results to force pagination + ['name ASC'] + ); + console.log( + 'Initial search results:', + initialSearchResults.registered_models + ); + console.log('Next page token:', initialSearchResults.next_page_token); + + if (initialSearchResults.next_page_token) { + // Perform second search using the page token + const secondSearchResults = await client.searchRegisteredModels( + `name LIKE '${renamedBaseName}%'`, + 3, + ['name ASC'], + initialSearchResults.next_page_token + ); + console.log( + 'Second search results:', + secondSearchResults.registered_models + ); + console.log('Next page token:', secondSearchResults.next_page_token); + } else { + console.log('No more pages available'); + } + + // 10. Test setting a tag + console.log('\n10. Setting a new tag...'); + await client.setRegisteredModelTag(renamedBaseName, 'new-tag', 'new-value'); + console.log('Tag set successfully'); + + // 11. Test deleting a tag + console.log('\n11. Deleting a tag...'); + await client.deleteRegisteredModelTag(renamedBaseName, 'new-tag'); + console.log('Tag deleted successfully'); + + // 12. Test setting an alias + console.log('\n12. Setting an alias...'); + await client.setRegisteredModelAlias(renamedBaseName, customAlias, '1'); + console.log('Alias set successfully'); + + // 13. Test getting a model version by alias + console.log('\n13. Getting model version by alias...'); + const aliasedVersion = await client.getModelVersionByAlias( + renamedBaseName, + customAlias + ); + console.log('Aliased version:', aliasedVersion); + + // 14. Test deleting an alias + console.log('\n14. Deleting an alias...'); + await client.deleteRegisteredModelAlias(renamedBaseName, customAlias); + console.log('Alias deleted successfully'); + + // 15. Test deleting the registered model + console.log('\n15. Deleting the registered model...'); + await client.deleteRegisteredModel(renamedBaseName); + console.log('Model deleted successfully'); } catch (error) { console.error('Error:', error.message); } From f56b6c3e5ceefbd99685e7f83ac73eb2f26df12c Mon Sep 17 00:00:00 2001 From: Yiqun Zheng <16813562+yiqunzheng@users.noreply.github.com> Date: Tue, 1 Oct 2024 16:26:18 -0700 Subject: [PATCH 082/357] change util file name to camalCase and change default export to named export for utils --- mlflow/src/model-registry/ModelRegistryClient.ts | 8 ++++---- mlflow/src/utils/ApiRequest.ts | 4 ++-- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/mlflow/src/model-registry/ModelRegistryClient.ts b/mlflow/src/model-registry/ModelRegistryClient.ts index a45829be..6731216b 100644 --- a/mlflow/src/model-registry/ModelRegistryClient.ts +++ b/mlflow/src/model-registry/ModelRegistryClient.ts @@ -1,4 +1,4 @@ -import apiRequest from '../utils/ApiRequest'; +import { apiRequest } from '../utils/apiRequest'; class ModelRegistryClient { private baseUrl: string; @@ -11,8 +11,8 @@ class ModelRegistryClient { * Creates a new registered model. * * @param name - The name of the model to register (required) - * @param tags - Optional tags for the model - * @param description - Optional description for the model + * @param tags - Tags for the model + * @param description - Description for the model * @returns The created registered model object * @throws Error if the API request fails */ @@ -374,4 +374,4 @@ class ModelRegistryClient { } } -export default ModelRegistryClient; \ No newline at end of file +export default ModelRegistryClient; diff --git a/mlflow/src/utils/ApiRequest.ts b/mlflow/src/utils/ApiRequest.ts index 9f062fd2..71eb6464 100644 --- a/mlflow/src/utils/ApiRequest.ts +++ b/mlflow/src/utils/ApiRequest.ts @@ -17,7 +17,7 @@ interface ApiResponse { * @param options - Request options * @returns A promise that resolves to the response and data */ -async function apiRequest( +export async function apiRequest( baseUrl: string, endpoint: string, options: RequestOptions @@ -47,4 +47,4 @@ async function apiRequest( return { response, data }; } -export default apiRequest; + From eabc9a5fa208c33c0d24bf295b94eca4f7727c0a Mon Sep 17 00:00:00 2001 From: Yiqun Zheng <16813562+yiqunzheng@users.noreply.github.com> Date: Tue, 1 Oct 2024 16:29:22 -0700 Subject: [PATCH 083/357] change util import and path --- mlflow/tests/ModelRegistryClientTest.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mlflow/tests/ModelRegistryClientTest.ts b/mlflow/tests/ModelRegistryClientTest.ts index 8967c3c7..ec1f4176 100644 --- a/mlflow/tests/ModelRegistryClientTest.ts +++ b/mlflow/tests/ModelRegistryClientTest.ts @@ -1,5 +1,5 @@ import ModelRegistryClient from '../src/model-registry/ModelRegistryClient'; -import apiRequest from '../src/utils/ApiRequest'; +import { apiRequest } from '../src/utils/apiRequest'; async function createRun( client: ModelRegistryClient, From 8f0b305a1d99e512e86b9cfa832946f7cf0e5209 Mon Sep 17 00:00:00 2001 From: Yiqun Zheng <16813562+yiqunzheng@users.noreply.github.com> Date: Tue, 1 Oct 2024 16:36:28 -0700 Subject: [PATCH 084/357] change import sorting alphabetically --- mlflow/tests/ModelRegistryClientTest.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mlflow/tests/ModelRegistryClientTest.ts b/mlflow/tests/ModelRegistryClientTest.ts index ec1f4176..57732fa2 100644 --- a/mlflow/tests/ModelRegistryClientTest.ts +++ b/mlflow/tests/ModelRegistryClientTest.ts @@ -1,5 +1,5 @@ -import ModelRegistryClient from '../src/model-registry/ModelRegistryClient'; import { apiRequest } from '../src/utils/apiRequest'; +import ModelRegistryClient from '../src/model-registry/ModelRegistryClient'; async function createRun( client: ModelRegistryClient, From 4b696c72a0886787e59ba74ebb3e02532c29fb0d Mon Sep 17 00:00:00 2001 From: Yiqun Zheng <16813562+yiqunzheng@users.noreply.github.com> Date: Tue, 1 Oct 2024 17:12:50 -0700 Subject: [PATCH 085/357] revise jsdoc --- .../src/model-registry/ModelRegistryClient.ts | 99 ++++++++++--------- 1 file changed, 52 insertions(+), 47 deletions(-) diff --git a/mlflow/src/model-registry/ModelRegistryClient.ts b/mlflow/src/model-registry/ModelRegistryClient.ts index 6731216b..8ecc0e00 100644 --- a/mlflow/src/model-registry/ModelRegistryClient.ts +++ b/mlflow/src/model-registry/ModelRegistryClient.ts @@ -10,11 +10,11 @@ class ModelRegistryClient { /** * Creates a new registered model. * - * @param name - The name of the model to register (required) - * @param tags - Tags for the model - * @param description - Description for the model - * @returns The created registered model object - * @throws Error if the API request fails + * @param {string} name - The name of the model to register (required) + * @param {Array<{key: string, value: string}>} [tags] - Optional tags for the model + * @param {string} [description] - Optional description for the model + * @returns {Promise} The created registered model object + * @throws {ApiError} If the API request fails */ async createRegisteredModel( name: string, @@ -44,9 +44,9 @@ class ModelRegistryClient { /** * Retrieves a registered model by name. * - * @param name - The name of the registered model to retrieve (required) - * @returns The registered model object - * @throws Error if the API request fails + * @param {string} name - The name of the registered model to retrieve (required) + * @returns {Promise} The registered model object + * @throws {ApiError} If the API request fails */ async getRegisteredModel(name: string): Promise { const { response, data } = await apiRequest( @@ -69,10 +69,10 @@ class ModelRegistryClient { /** * Renames a registered model. * - * @param name - The current name of the registered model (required) - * @param newName - The new name for the registered model (required) - * @returns The updated registered model object - * @throws Error if the API request fails + * @param {string} name - The current name of the registered model (required) + * @param {string} newName - The new name for the registered model (required) + * @returns {Promise} The updated registered model object + * @throws {ApiError} If the API request fails */ async renameRegisteredModel(name: string, newName: string): Promise { const { response, data } = await apiRequest( @@ -97,10 +97,10 @@ class ModelRegistryClient { /** * Updates a registered model's description. * - * @param name - The name of the registered model to update (required) - * @param description - The new description for the model - * @returns The updated registered model object - * @throws Error if the API request fails + * @param {string} name - The name of the registered model to update (required) + * @param {string} [description] - The new description for the model + * @returns {Promise} The updated registered model object + * @throws {ApiError} If the API request fails */ async updateRegisteredModel( name: string, @@ -129,8 +129,9 @@ class ModelRegistryClient { /** * Deletes a registered model. * - * @param name - The name of the registered model to delete (required) - * @throws Error if the API request fails + * @param {string} name - The name of the registered model to delete (required) + * @returns {Promise} + * @throws {ApiError} If the API request fails */ async deleteRegisteredModel(name: string): Promise { const { response, data } = await apiRequest( @@ -156,10 +157,10 @@ class ModelRegistryClient { /** * Gets the latest versions of a registered model. * - * @param name - The name of the registered model (required) - * @param stages - Array of stages to filter the versions by - * @returns An array of the latest model versions - * @throws Error if the API request fails + * @param {string} name - The name of the registered model (required) + * @param {string[]} [stages] - Optional array of stages to filter the versions by + * @returns {Promise} An array of the latest model versions + * @throws {ApiError} If the API request fails */ async getLatestModelVersions(name: string, stages?: string[]): Promise { const { response, data } = await apiRequest( @@ -183,12 +184,12 @@ class ModelRegistryClient { /** * Searches for registered models based on filter criteria. * - * @param filter - Filter string to apply to the search - * @param maxResults - Maximum number of results to return - * @param orderBy - Array of fields to order the results by - * @param pageToken - Token for pagination - * @returns An object containing the search results and pagination information - * @throws Error if the API request fails + * @param {string} [filter] - Optional filter string to apply to the search + * @param {number} [maxResults] - Optional maximum number of results to return + * @param {string[]} [orderBy] - Optional array of fields to order the results by + * @param {string} [pageToken] - Optional token for pagination + * @returns {Promise<{registered_models: RegisteredModel[], next_page_token: string}>} An object containing the search results and pagination information + * @throws {ApiError} If the API request fails */ async searchRegisteredModels( filter?: string, @@ -225,10 +226,11 @@ class ModelRegistryClient { /** * Sets a tag on a registered model. * - * @param name - The name of the registered model (required) - * @param key - The key of the tag (required) - * @param value - The value of the tag (required) - * @throws Error if the API request fails + * @param {string} name - The name of the registered model (required) + * @param {string} key - The key of the tag (required) + * @param {string} value - The value of the tag (required) + * @returns {Promise} + * @throws {ApiError} If the API request fails */ async setRegisteredModelTag( name: string, @@ -258,9 +260,10 @@ class ModelRegistryClient { /** * Deletes a tag from a registered model. * - * @param name - The name of the registered model (required) - * @param key - The key of the tag to delete (required) - * @throws Error if the API request fails + * @param {string} name - The name of the registered model (required) + * @param {string} key - The key of the tag to delete (required) + * @returns {Promise} + * @throws {ApiError} If the API request fails */ async deleteRegisteredModelTag(name: string, key: string): Promise { const { response, data } = await apiRequest( @@ -286,10 +289,11 @@ class ModelRegistryClient { /** * Sets an alias for a specific version of a registered model. * - * @param name - The name of the registered model (required) - * @param alias - The alias to set (required) - * @param version - The version number to associate with the alias (required) - * @throws Error if the API request fails + * @param {string} name - The name of the registered model (required) + * @param {string} alias - The alias to set (required) + * @param {string} version - The version number to associate with the alias (required) + * @returns {Promise} + * @throws {ApiError} If the API request fails */ async setRegisteredModelAlias( name: string, @@ -319,9 +323,10 @@ class ModelRegistryClient { /** * Deletes an alias from a registered model. * - * @param name - The name of the registered model (required) - * @param alias - The alias to delete (required) - * @throws Error if the API request fails + * @param {string} name - The name of the registered model (required) + * @param {string} alias - The alias to delete (required) + * @returns {Promise} + * @throws {ApiError} If the API request fails */ async deleteRegisteredModelAlias(name: string, alias: string): Promise { const { response, data } = await apiRequest( @@ -347,10 +352,10 @@ class ModelRegistryClient { /** * Retrieves a model version using its alias. * - * @param name - The name of the registered model (required) - * @param alias - The alias of the model version to retrieve (required) - * @returns The model version object - * @throws Error if the API request fails + * @param {string} name - The name of the registered model (required) + * @param {string} alias - The alias of the model version to retrieve (required) + * @returns {Promise} The model version object + * @throws {ApiError} If the API request fails */ async getModelVersionByAlias(name: string, alias: string): Promise { const { response, data } = await apiRequest( @@ -374,4 +379,4 @@ class ModelRegistryClient { } } -export default ModelRegistryClient; +export default ModelRegistryClient; \ No newline at end of file From cd8678ab55fcf1e86612601ffa7eeaa549738dbf Mon Sep 17 00:00:00 2001 From: Austin Fraser Date: Tue, 1 Oct 2024 17:33:49 -0700 Subject: [PATCH 086/357] committing austin- refactor before switching branches --- mlflow/src/tracking/ExperimentClient.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mlflow/src/tracking/ExperimentClient.ts b/mlflow/src/tracking/ExperimentClient.ts index c371ee44..de4bb862 100644 --- a/mlflow/src/tracking/ExperimentClient.ts +++ b/mlflow/src/tracking/ExperimentClient.ts @@ -1,5 +1,5 @@ class ExperimentClient { - constructor(trackingUri) { + constructor(trackingUri: string) { this.trackingUri = trackingUri; } From 25600ac6fb39ca4359d2b7428b4a18e45591d5dd Mon Sep 17 00:00:00 2001 From: Stephany Ho Date: Tue, 1 Oct 2024 20:48:57 -0400 Subject: [PATCH 087/357] Refactor RunClient.ts and run_management.js --- mlflow/src/tracking/RunClient.js | 511 -------------------------- mlflow/src/tracking/RunClient.ts | 509 +++++++++++++++++++++++++ mlflow/src/tracking/run_management.js | 59 +-- 3 files changed, 546 insertions(+), 533 deletions(-) delete mode 100644 mlflow/src/tracking/RunClient.js create mode 100644 mlflow/src/tracking/RunClient.ts diff --git a/mlflow/src/tracking/RunClient.js b/mlflow/src/tracking/RunClient.js deleted file mode 100644 index bcef9347..00000000 --- a/mlflow/src/tracking/RunClient.js +++ /dev/null @@ -1,511 +0,0 @@ -class RunClient { - constructor(trackingUri) { - this.trackingUri = trackingUri; - } - - /** - * Create a new run within an experiment. A run is usually a single execution of a machine learning or data ETL pipeline. MLflow uses runs to track Param, Metric, and RunTag associated with a single execution. - * - * @param {string} experiment_id - ID of the associated experiment. (required) - * @param {string} [run_name] - Name of the run. - * @param {number} [start_time] - Unix timestamp in milliseconds of when the run started. - * @param {Array<{key: string, value: string}>} [tags=[]] - Additional metadata for the run. - * @returns {Promise} - A promise that resolves with the created run object. - */ - async createRun( - experiment_id, - run_name = null, - start_time = null, - tags = [] - ) { - if (!experiment_id) { - throw new Error('Experiment ID is required'); - } - - const url = `${this.trackingUri}/api/2.0/mlflow/runs/create`; - - const body = { - experiment_id, - start_time: start_time !== null ? start_time : Date.now(), - tags, - }; - - if (run_name) { - body.run_name = run_name; - } - - const response = await fetch(url, { - method: 'POST', - headers: { 'Content-Type': 'application/json' }, - body: JSON.stringify(body), - }); - - const data = await response.json(); - - if (!response.ok) { - throw new Error( - `Error creating run: ${data.message || response.statusText}` - ); - } - - return data.run; - } - - /** - * Mark a run for deletion. - * - * @param {string} run_id - ID of the run to delete. (required) - * @returns {Promise} - A promise that resolves when the run is deleted. - */ - async deleteRun(run_id) { - if (!run_id) { - throw new Error('Run ID is required.'); - } - - const url = `${this.trackingUri}/api/2.0/mlflow/runs/delete`; - - const response = await fetch(url, { - method: 'POST', - headers: { 'Content-Type': 'application/json' }, - body: JSON.stringify({ run_id }), - }); - - if (!response.ok) { - throw new Error(`Error deleting run: ${response.statusText}`); - } - } - - /** - * Restore a deleted run. - * - * @param {string} run_id - ID of the run to restore. (required) - * @returns {Promise} - A promise that resolves when the run is restored. - */ - async restoreRun(run_id) { - if (!run_id) { - throw new Error('Run ID is required.'); - } - - const url = `${this.trackingUri}/api/2.0/mlflow/runs/restore`; - - const response = await fetch(url, { - method: 'POST', - headers: { 'Content-Type': 'application/json' }, - body: JSON.stringify({ run_id }), - }); - - if (!response.ok) { - throw new Error(`Error restoring run: ${response.statusText}`); - } - } - - /** - * Get metadata, metrics, params, and tags for a run. In the case where multiple metrics with the same key are logged for a run, return only the value with the latest timestamp. If there are multiple values with the latest timestamp, return the maximum of these values. - * - * @param {string} run_id - ID of the run to fetch. (required) - * @returns {Promise} - A promise that resolves with the fetched run object. - */ - async getRun(run_id) { - if (!run_id) { - throw new Error('Run ID is required.'); - } - - const url = `${this.trackingUri}/api/2.0/mlflow/runs/get?run_id=${run_id}`; - - const response = await fetch(url); - const data = await response.json(); - - if (!response.ok) { - throw new Error( - `Error fetching run: ${data.message || response.statusText}` - ); - } - - return data.run; - } - - /** - * Update run metadata. - * - * @param {string} run_id - ID of the run to update. (required) - * @param {string} [status] - Updated status of the run. - * @param {number} [end_time] - Unix timestamp in milliseconds of when the run ended. - * @param {string} [run_name] - Updated name of the run. - * @returns {Promise} - A promise that resolves with the updated metadata of the run object. - */ - async updateRun(run_id, status = null, end_time = null, run_name = null) { - if (!run_id) { - throw new Error('Run ID is required.'); - } - - const url = `${this.trackingUri}/api/2.0/mlflow/runs/update`; - - const body = { run_id }; - if (status) body.status = status; - if (end_time) body.end_time = end_time; - if (run_name) body.run_name = run_name; - - const response = await fetch(url, { - method: 'POST', - headers: { 'Content-Type': 'application/json' }, - body: JSON.stringify(body), - }); - - const data = await response.json(); - - if (!response.ok) { - throw new Error( - `Error updating run: ${data.message || response.statusText}` - ); - } - - return data; - } - - /** - * Log a metric for a run. A metric is a key-value pair (string key, float value) with an associated timestamp. Examples include the various metrics that represent ML model accuracy. A metric can be logged multiple times. - * - * @param {string} run_id - ID of the run under which to log the metric. (required) - * @param {string} key - Name of the metric. (required) - * @param {number} value - Double value of the metric being logged. (required) - * @param {number} timestamp - Unix timestamp in milliseconds at the time metric was logged. (required) - * @param {number} [step=0] - Step at which to log the metric. - * @returns {Promise} - A promise that resolves when the logging is complete. - */ - - async logMetric(run_id, key, value, timestamp = Date.now(), step = 0) { - if (!run_id || !key || !value || !timestamp) { - throw new Error('Run ID, key, value, and timestamp are required.'); - } - - const url = `${this.trackingUri}/api/2.0/mlflow/runs/log-metric`; - - const body = { run_id, key, value, timestamp }; - if (step) body.step = step; - - const response = await fetch(url, { - method: 'POST', - headers: { 'Content-Type': 'application/json' }, - body: JSON.stringify(body), - }); - - if (!response.ok) { - throw new Error(`Error logging metric: ${response.statusText}`); - } - } - - /** - * Log a batch of metrics, params, and tags for a run. If any data failed to be persisted, the server will respond with an error (non-200 status code). In case of error (due to internal server error or an invalid request), partial data may be written. - * - * @param {string} run_id - ID of the run to log under. (required) - * @param {Array<{key: string, value: number, timestamp: number, step?: number}>} [metrics=[]] - Metrics to log. A single request can contain up to 1000 metrics, and up to 1000 metrics, params, and tags in total. - * @param {Array<{key: string, value: string}>} [params=[]] - Params to log. A single request can contain up to 100 params, and up to 1000 metrics, params, and tags in total. - * @param {Array<{key: string, value: string}>} [tags=[]] - Tags to log. A single request can contain up to 100 tags, and up to 1000 metrics, params, and tags in total. - * @returns {Promise} - A promise that resolves when the logging is complete. - */ - async logBatch(run_id, metrics = [], params = [], tags = []) { - if (!run_id) { - throw new Error('Run ID is required.'); - } - - const url = `${this.trackingUri}/api/2.0/mlflow/runs/log-batch`; - - const body = { run_id }; - if (metrics) body.metrics = metrics; - if (params) body.params = params; - if (tags) body.tags = tags; - - const response = await fetch(url, { - method: 'POST', - headers: { 'Content-Type': 'application/json' }, - body: JSON.stringify(body), - }); - - if (!response.ok) { - throw new Error(`Error logging batch: ${response.statusText}`); - } - } - - /** - * Logs a model. - * - * @param {string} run_id - ID of the run to log under. (required) - * @param {string} model_json - MLmodel file in json format. (required) - * @returns {Promise} - A promise that resolves when the logging is complete. - */ - async logModel(run_id, model_json) { - if (!run_id || model_json) { - throw new Error('Run ID and MLmodel data are required.'); - } - - const url = `${this.trackingUri}/api/2.0/mlflow/runs/log-model`; - - const response = await fetch(url, { - method: 'POST', - headers: { 'Content-Type': 'application/json' }, - body: JSON.stringify({ run_id, model_json }), - }); - - if (!response.ok) { - throw new Error(`Error logging model: ${response.statusText}`); - } - } - - /** - * Logs inputs. - * - * @param {string} run_id - ID of the run to log under. (required) - * @param {Array} datasets - The dataset inputs in JSON format. (required) - * @returns {Promise} - A promise that resolves when the logging is complete. - */ - - async logInputs(run_id, datasets) { - if (!run_id || !datasets) { - throw new Error('Run ID and datasets are required.'); - } - - const url = `${this.trackingUri}/api/2.0/mlflow/runs/log-inputs`; - - const response = await fetch(url, { - method: 'POST', - headers: { 'Content-Type': 'application/json' }, - body: JSON.stringify({ run_id, datasets }), - }); - - if (!response.ok) { - throw new Error(`Error in logging inputs: ${response.statusText}`); - } - } - - /** - * Set a tag on a run. Tags are run metadata that can be updated during a run and after a run completes. - * - * @param {string} run_id - ID of the run under which to log the tag. (required) - * @param {string} key - Name of the tag. Maximum size depends on storage backend. All storage backends - * are guaranteed to support key values up to 250 bytes in size. (required) - * @param {string} value - String value of the tag being logged. Maximum size depends on storage - * backend. All storage backends are guaranteed to support key values up to 5000 bytes in size. (required) - * @returns {Promise} - A promise that resolves when the logging is complete. - */ - async setTag(run_id, key, value) { - if (!run_id) { - throw new Error('Run ID is required'); - } else if (!key) { - throw new Error('Key is required'); - } else if (!value) { - throw new Error('Value is required'); - } - const url = `${this.trackingUri}/api/2.0/mlflow/runs/set-tag`; - const response = await fetch(url, { - method: 'POST', - headers: { - 'Content-Type': 'application/json', - }, - body: JSON.stringify({ run_id, key, value }), - }); - - if (!response.ok) { - throw new Error(`Error setting tag: ${response.statusText}`); - } - } - - /** - * Delete a tag on a run. Tags are run metadata that can be updated during a run and after a run completes. - * - * @param {string} run_id - ID of the run that the tag was logged under. (required) - * @param {string} key - Name of the tag. Maximum size is 255 bytes. (required) - * @returns {Promise} - A promise that resolves when the deletion is complete. - */ - async deleteTag(run_id, key) { - if (!run_id) { - throw new Error('run_id is required'); - } else if (!key) { - throw new Error('key is required'); - } - const url = `${this.trackingUri}/api/2.0/mlflow/runs/delete-tag`; - const response = await fetch(url, { - method: 'POST', - headers: { - 'Content-Type': 'application/json', - }, - body: JSON.stringify({ run_id, key }), - }); - - // data is an empty object - const data = await response.json(); - - if (!response.ok) { - throw new Error( - `Error logging param: ${data.message || response.statusText}` - ); - } - return data; - } - - /** - * Log a param used for a run. A param is a key-value pair (string key, string value). Examples include hyperparameters used for ML model training and constant dates and values used in an ETL pipeline. A param can be logged only once for a run. - * - * @param {string} run_id - ID of the run under which to log the param. (required)) - * @param {string} key - Name of the param. Maximum size is 255 bytes. (required) - * @param {string} value - String value of the param being logged. Maximum size is 6000 bytes. (required) - * @returns {Promise} - A promise that resolves when the logging is complete. - * Note: A param can be logged only once for a run - */ - async logParam(run_id, key, value) { - if (!run_id) { - throw new Error('run_id is required'); - } else if (!key) { - throw new Error('key is required'); - } else if (!value) { - throw new Error('value is required'); - } - const url = `${this.trackingUri}/api/2.0/mlflow/runs/log-parameter`; - const response = await fetch(url, { - method: 'POST', - headers: { - 'Content-Type': 'application/json', - }, - body: JSON.stringify({ run_id, key, value }), - }); - - if (!response.ok) { - throw new Error(`Error logging param: ${response.statusText}`); - } - } - - /** - * Get a list of all values for the specified metric for a given run. - * - * @param {string} run_id - ID of the run from which to fetch metric values. (required) - * @param {string} metric_key - Name of the metric. (required) - * @param {string} page_token - Token indicating the page of metric history to fetch. - * @param {INT32} max_results - Maximum number of logged instances of a metric for a run to return per call. - * Backend servers may restrict the value of max_results depending on performance requirements. Requests that do not - * specify this value will behave as non-paginated queries where all metric history values for a given metric - * within a run are returned in a single response. - * @returns {Promise} - A promise that resolves with the values for the specified metric. - */ - async getMetricHistory(run_id, metric_key, page_token, max_results) { - if (!run_id) { - throw new Error('run_id is required'); - } else if (!metric_key) { - throw new Error('metric_key is required'); - } - const url = `${this.trackingUri}/api/2.0/mlflow/metrics/get-history?run_id=${run_id}&metric_key=${metric_key}&page_token=${page_token}&max_results=${max_results}`; - const response = await fetch(url); - /** - * data can have the fields: - * metrics {An array of Metric} - All logged values for this metric - * next_page_token {string} - Token that can be used to issue a query for the next page of metric history values. A - * missing token indicates that no additional metrics are available to fetch. - */ - const data = await response.json(); - if (!response.ok) { - throw new Error( - `Error finding metric for given run: ${ - data.message || response.statusText - }` - ); - } - - return data; - } - - /** - * - * @param {Array<{key: string, value: string}>} experiment_ids - List of experiment IDs to search over. - * @param {string} filter - A filter expression over params, metrics, and tags, that allows returning a subset of runs. - * The syntax is a subset of SQL that supports ANDing together binary operations between a param, metric, or tag and a constant. - * Example: metrics.rmse < 1 and params.model_class = 'LogisticRegression' - * You can select columns with special characters (hyphen, space, period, etc.) by using - * double quotes: metrics."model class" = 'LinearRegression' and tags."user-name" = 'Tomas' - * Supported operators are =, !=, >, >=, <, and <=. - * @param {ViewType} run_view_type - Whether to display only active, only deleted, or all runs. Defaults to active runs. - * @param {INT32} max_results - Maximum number of runs desired. If unspecified, defaults to 1000. All servers are - * guaranteed to support a max_results theshold of at least 50,000 but may support more. Callers of this endpoint are - * encouraged to pass max_results explicitly and leverage page_token to iterate through experiments. - * @param {Array<{key: string, value: string}>} order_by - List of columns to be ordered by, including attributes, params, metrics, - * and tags with an optional "DESC" or "ASC" annotation, where "ASC" is the default. - * Example: ["params.input DESC","metrics.alpha ASC", "metrics.rmse"] Tiebreaks are done by start_time DESC followed by run_id for - * runs with the same start time (and this is the default ordering criterion if order_by is not provided). - * @param {string} page_token - * @returns {Promise} - A promise that resolves with a list artifacts for the specified run. - */ - async listArtifacts(run_id, artifact_path = '', page_token = '') { - if (!run_id) { - throw new Error('run_id is required'); - } - const response = await fetch( - `${this.trackingUri}/api/2.0/mlflow/artifacts/list?run_id=${run_id}&run_uuid=${run_id}&path=${artifact_path}&page_token=${page_token}` - ); - /** - * data can have the fields: - * root_uri {string} - Root artifact directory for the run - * files {An array of FileInfo} - File location and metadata for artifacts - * next_page_token {string} - Token that can be used to retrieve the next page of artifact results. A missing token indicates - * that there are no additional artifact results to be fetched. - */ - const data = await response.json(); - if (!response.ok) { - throw new Error( - `Error retrieving artifacts from run: ${ - data.message || response.statusText - }` - ); - } - - return data; - } -} - -export { RunClient }; diff --git a/mlflow/src/tracking/RunClient.ts b/mlflow/src/tracking/RunClient.ts new file mode 100644 index 00000000..f12f7174 --- /dev/null +++ b/mlflow/src/tracking/RunClient.ts @@ -0,0 +1,509 @@ +import { apiRequest } from '../utils/apiRequest'; + +interface InputTag { + key: string; + value: string; +} + +interface Dataset { + name: string; + digest: string; + source_type: string; + source: string; + schema?: string; + profile?: string; +} + +interface DatasetInput { + tags: InputTag[]; + dataset: Dataset; +} + +class RunClient { + private baseUrl: string; + + constructor(trackingUri: string) { + this.baseUrl = trackingUri; + } + + /** + * Create a new run within an experiment. A run is usually a single execution of a machine learning or data + * ETL pipeline. MLflow uses runs to track Param, Metric, and RunTag associated with a single execution. + * + * @param experiment_id - ID of the associated experiment. (required) + * @param run_name - Name of the run. + * @param start_time - Unix timestamp in milliseconds of when the run started. + * @param tags - Additional metadata for the run. + * @returns A promise that resolves with the created run object. + * @throws Error - If the API request fails. + */ + async createRun( + experiment_id: string, + run_name?: string, + start_time: number = Date.now(), + tags?: Array<{ key: string; value: string }> + ): Promise { + const { response, data } = await apiRequest(this.baseUrl, 'runs/create', { + method: 'POST', + body: { experiment_id, run_name, start_time, tags }, + }); + + if (!response.ok) { + throw new Error( + `Error creating run: ${data.message || response.statusText}` + ); + } + + return data.run; + } + + /** + * Mark a run for deletion. + * + * @param run_id - ID of the run to delete. (required) + * @returns A promise that resolves when the run is deleted. + * @throws Error - If the API request fails. + */ + async deleteRun(run_id: string): Promise { + const { response, data } = await apiRequest(this.baseUrl, 'runs/delete', { + method: 'POST', + body: { run_id }, + }); + + if (!response.ok) { + throw new Error( + `Error deleting run: ${data.message || response.statusText}` + ); + } + + return; + } + + /** + * Restore a deleted run. + * + * @param run_id - ID of the run to restore. (required) + * @returns A promise that resolves when the run is restored. + * @throws Error - If the API request fails. + */ + async restoreRun(run_id: string): Promise { + const { response, data } = await apiRequest(this.baseUrl, 'runs/restore', { + method: 'POST', + body: { run_id }, + }); + + if (!response.ok) { + throw new Error( + `Error restoring run: ${data.message || response.statusText}` + ); + } + + return; + } + + /** + * Get metadata, metrics, params, and tags for a run. In the case where multiple metrics with the same key + * are logged for a run, return only the value with the latest timestamp. If there are multiple values with + * the latest timestamp, return the maximum of these values. + * + * @param run_id - ID of the run to fetch. (required) + * @returns A promise that resolves with the fetched run object. + * @throws Error - If the API request fails. + */ + async getRun(run_id: string): Promise { + const { response, data } = await apiRequest(this.baseUrl, 'runs/get', { + method: 'GET', + params: { run_id }, + }); + + if (!response.ok) { + throw new Error( + `Error fetching run: ${data.message || response.statusText}` + ); + } + + return data.run; + } + + /** + * Update run metadata. + * + * @param run_id - ID of the run to update. (required) + * @param status - Updated status of the run. + * @param end_time - Unix timestamp in milliseconds of when the run ended. + * @param run_name - Updated name of the run. + * @returns A promise that resolves with the updated metadata of the run. + * @throws Error - If the API request fails. + */ + async updateRun( + run_id: string, + status?: 'RUNNING' | 'SCHEDULED' | 'FINISHED' | 'FAILED' | 'KILLED', + end_time?: number, + run_name?: string + ): Promise { + const { response, data } = await apiRequest(this.baseUrl, 'runs/update', { + method: 'POST', + body: { run_id, status, end_time, run_name }, + }); + + if (!response.ok) { + throw new Error( + `Error updating run: ${data.message || response.statusText}` + ); + } + + return data; + } + + /** + * Log a metric for a run. A metric is a key-value pair (string key, float value) with an associated timestamp. + * Examples include the various metrics that represent ML model accuracy. A metric can be logged multiple times. + * + * @param run_id - ID of the run under which to log the metric. (required) + * @param key - Name of the metric. (required) + * @param value - Double value of the metric being logged. (required) + * @param timestamp - Unix timestamp in milliseconds at the time metric was logged. (required) + * @param step - Step at which to log the metric. + * @returns A promise that resolves when the logging is complete. + * @throws Error - If the API request fails. + */ + + async logMetric( + run_id: string, + key: string, + value: number, + timestamp: number = Date.now(), + step?: number + ): Promise { + const { response, data } = await apiRequest( + this.baseUrl, + 'runs/log-metric', + { + method: 'POST', + body: { run_id, key, value, timestamp, step }, + } + ); + + if (!response.ok) { + throw new Error( + `Error logging metric: ${data.message || response.statusText}` + ); + } + + return; + } + + /** + * Log a batch of metrics, params, and tags for a run. If any data failed to be persisted, the server will + * respond with an error (non-200 status code). In case of error (due to internal server error or an invalid + * request), partial data may be written. + * + * @param run_id - ID of the run to log under. (required) + * @param metrics- Metrics to log. A single request can contain up to 1000 metrics, and up to 1000 metrics, + * params, and tags in total. + * @param params - Params to log. A single request can contain up to 100 params, and up to 1000 metrics, + * params, and tags in total. + * @param tags - Tags to log. A single request can contain up to 100 tags, and up to 1000 metrics, params, + * and tags in total. + * @returns A promise that resolves when the logging is complete. + * @throws Error - If the API request fails. + */ + async logBatch( + run_id: string, + metrics?: Array<{ + key: string; + value: number; + timestamp: number; + step?: number; + }>, + params?: Array<{ key: string; value: string }>, + tags?: Array<{ key: string; value: string }> + ): Promise { + const { response, data } = await apiRequest( + this.baseUrl, + 'runs/log-batch', + { + method: 'POST', + body: { run_id, metrics, params, tags }, + } + ); + + if (!response.ok) { + throw new Error( + `Error logging batch: ${data.message || response.statusText}` + ); + } + + return; + } + + /** + * Logs a model. + * + * @param run_id - ID of the run to log under. (required) + * @param model_json - MLmodel file in json format. (required) + * @returns A promise that resolves when the logging is complete. + * @throws Error - If the API request fails. + */ + async logModel(run_id: string, model_json: string): Promise { + const { response, data } = await apiRequest( + this.baseUrl, + 'runs/log-model', + { + method: 'POST', + body: { run_id, model_json }, + } + ); + + if (!response.ok) { + throw new Error( + `Error logging model: ${data.message || response.statusText}` + ); + } + + return; + } + + /** + * Logs inputs. + * + * @param run_id - ID of the run to log under. (required) + * @param datasets - Dataset inputs. (required) + * @returns A promise that resolves when the logging is complete. + * @throws Error - If the API request fails. + */ + + async logInputs(run_id: string, datasets: DatasetInput[]): Promise { + const { response, data } = await apiRequest( + this.baseUrl, + 'runs/log-inputs', + { + method: 'POST', + body: { run_id, datasets }, + } + ); + + if (!response.ok) { + throw new Error( + `Error in logging inputs: ${data.message || response.statusText}` + ); + } + + return; + } + + /** + * Set a tag on a run. Tags are run metadata that can be updated during a run and after a run completes. + * + * @param run_id - ID of the run under which to log the tag. (required) + * @param key - Name of the tag. Maximum size depends on storage backend. All storage backends are guaranteed + * to support key values up to 250 bytes in size. (required) + * @param value - String value of the tag being logged. Maximum size depends on storage backend. All storage + * backends are guaranteed to support key values up to 5000 bytes in size. (required) + * @returns A promise that resolves when the logging is complete. + * @throws Error - If the API request fails. + */ + async setTag(run_id: string, key: string, value: string): Promise { + const { response, data } = await apiRequest(this.baseUrl, 'runs/set-tag', { + method: 'POST', + body: { run_id, key, value }, + }); + + if (!response.ok) { + throw new Error( + `Error setting tag: ${data.message || response.statusText}` + ); + } + + return; + } + + /** + * Delete a tag on a run. Tags are run metadata that can be updated during a run and after a run completes. + * + * @param run_id - ID of the run that the tag was logged under. (required) + * @param key - Name of the tag. Maximum size is 255 bytes. (required) + * @returns A promise that resolves when the deletion is complete. + * @throws Error - If the API request fails. + */ + async deleteTag(run_id: string, key: string): Promise { + const { response, data } = await apiRequest( + this.baseUrl, + 'runs/delete-tag', + { + method: 'POST', + body: { run_id, key }, + } + ); + + if (!response.ok) { + throw new Error( + `Error deleting tag: ${data.message || response.statusText}` + ); + } + + return; + } + + /** + * Log a param used for a run. A param is a key-value pair (string key, string value). Examples include + * hyperparameters used for ML model training and constant dates and values used in an ETL pipeline. + * A param can be logged only once for a run. + * + * @param run_id - ID of the run under which to log the param. (required)) + * @param key - Name of the param. Maximum size is 255 bytes. (required) + * @param value - String value of the param being logged. Maximum size is 6000 bytes. (required) + * @returns A promise that resolves when the logging is complete. + * @throws Error - If the API request fails. + */ + async logParam(run_id: string, key: string, value: string): Promise { + const { response, data } = await apiRequest( + this.baseUrl, + 'runs/log-parameter', + { + method: 'POST', + body: { run_id, key, value }, + } + ); + + if (!response.ok) { + throw new Error( + `Error logging param: ${data.message || response.statusText}` + ); + } + + return; + } + + /** + * Get a list of all values for the specified metric for a given run. + * + * @param run_id - ID of the run from which to fetch metric values. (required) + * @param metric_key - Name of the metric. (required) + * @param page_token - Token indicating the page of metric history to fetch. + * @param max_results - Maximum number of logged instances of a metric for a run to return per call. + * Backend servers may restrict the value of max_results depending on performance requirements. Requests that + * do not specify this value will behave as non-paginated queries where all metric history values for a given + * metric within a run are returned in a single response. + * @returns A promise that resolves with the values for the specified metric. + * @throws Error - If the API request fails. + */ + async getMetricHistory( + run_id: string, + metric_key: string, + page_token?: string, + max_results?: number + ): Promise { + const params: Record = { run_id, metric_key }; + + if (page_token !== undefined) params.page_token = page_token; + if (max_results !== undefined) params.max_results = max_results.toString(); + + const { response, data } = await apiRequest( + this.baseUrl, + `metrics/get-history`, + { + method: 'GET', + params, + } + ); + + if (!response.ok) { + throw new Error( + `Error fetching metric history: ${data.message || response.statusText}` + ); + } + + return data; + } + + /** + * Search for runs that satisfy expressions. Search expressions can use Metric and Param keys. + * + * @param experiment_ids - List of experiment IDs to search over. + * @param filter - A filter expression over params, metrics, and tags, that allows returning a subset of runs. + * The syntax is a subset of SQL that supports ANDing together binary operations between a param, metric, or + * tag and a constant. + * Example: metrics.rmse < 1 and params.model_class = 'LogisticRegression' + * You can select columns with special characters (hyphen, space, period, etc.) by using double quotes: + * metrics."model class" = 'LinearRegression' and tags."user-name" = 'Tomas' + * Supported operators are =, !=, >, >=, <, and <=. + * @param {ViewType} run_view_type - Whether to display only active, only deleted, or all runs. Defaults to active runs. + * @param max_results - Maximum number of runs desired. If unspecified, defaults to 1000. All servers are + * guaranteed to support a max_results theshold of at least 50,000 but may support more. Callers of this endpoint are + * encouraged to pass max_results explicitly and leverage page_token to iterate through experiments. + * @param order_by - List of columns to be ordered by, including attributes, params, metrics, and tags with an optional + * "DESC" or "ASC" annotation, where "ASC" is the default. + * Example: ["params.input DESC","metrics.alpha ASC", "metrics.rmse"] Tiebreaks are done by start_time DESC followed by + * run_id for runs with the same start time (and this is the default ordering criterion if order_by is not provided). + * @param page_token - Token that can be used to retrieve the next page of run results. A missing token indicates that + * there are no additional run results to be fetched. + * @returns A promise that resovles with the runs that match the search criteria. + * @throws Error - If the API request fails. + */ + async searchRuns( + experiment_ids: string[], + filter: string, + run_view_type?: 'ACTIVE_ONLY' | 'DELETED_ONLY' | 'ALL', + max_results?: number, + order_by?: string[], + page_token?: string + ): Promise { + const { response, data } = await apiRequest(this.baseUrl, 'runs/search', { + method: 'POST', + body: { + experiment_ids, + filter, + run_view_type, + max_results, + order_by, + page_token, + }, + }); + + if (!response.ok) { + throw new Error( + `Error fetching runs that satisfies expressions: ${ + data.message || response.statusText + }` + ); + } + + return data; + } + + /** + * List artifacts for a run. Takes an optional artifact_path prefix which if specified, the response contains only + * artifacts with the specified prefix. + * + * @param run_id - ID of the run whose artifacts to list. (required) + * @param path - Filter artifacts matching this path (a relative path from the root artifact directory). + * @param page_token - Token indicating the page of artifact results to fetch. + * @returns A promise that resolves with a list artifacts for the specified run. + * @throws Error - If the API request fails. + */ + async listArtifacts( + run_id: string, + path: string, + page_token: string + ): Promise { + const { response, data } = await apiRequest( + this.baseUrl, + 'artifacts/list', + { + method: 'GET', + params: { run_id, path, page_token }, + } + ); + + if (!response.ok) { + throw new Error( + `Error listing artifacts: ${data.message || response.statusText}` + ); + } + + return data; + } +} + +export default RunClient; diff --git a/mlflow/src/tracking/run_management.js b/mlflow/src/tracking/run_management.js index bcef9347..c4b69c46 100644 --- a/mlflow/src/tracking/run_management.js +++ b/mlflow/src/tracking/run_management.js @@ -10,7 +10,7 @@ class RunClient { * @param {string} [run_name] - Name of the run. * @param {number} [start_time] - Unix timestamp in milliseconds of when the run started. * @param {Array<{key: string, value: string}>} [tags=[]] - Additional metadata for the run. - * @returns {Promise} - A promise that resolves with the created run object. + * @returns {Promise} - A promise that resolves with the created run object. */ async createRun( experiment_id, @@ -73,6 +73,8 @@ class RunClient { if (!response.ok) { throw new Error(`Error deleting run: ${response.statusText}`); } + + return; } /** @@ -97,13 +99,15 @@ class RunClient { if (!response.ok) { throw new Error(`Error restoring run: ${response.statusText}`); } + + return; } /** * Get metadata, metrics, params, and tags for a run. In the case where multiple metrics with the same key are logged for a run, return only the value with the latest timestamp. If there are multiple values with the latest timestamp, return the maximum of these values. * * @param {string} run_id - ID of the run to fetch. (required) - * @returns {Promise} - A promise that resolves with the fetched run object. + * @returns {Promise} - A promise that resolves with the fetched run object. */ async getRun(run_id) { if (!run_id) { @@ -131,7 +135,7 @@ class RunClient { * @param {string} [status] - Updated status of the run. * @param {number} [end_time] - Unix timestamp in milliseconds of when the run ended. * @param {string} [run_name] - Updated name of the run. - * @returns {Promise} - A promise that resolves with the updated metadata of the run object. + * @returns {Promise} - A promise that resolves with the updated metadata of the run object. */ async updateRun(run_id, status = null, end_time = null, run_name = null) { if (!run_id) { @@ -192,6 +196,8 @@ class RunClient { if (!response.ok) { throw new Error(`Error logging metric: ${response.statusText}`); } + + return; } /** @@ -224,6 +230,8 @@ class RunClient { if (!response.ok) { throw new Error(`Error logging batch: ${response.statusText}`); } + + return; } /** @@ -231,7 +239,7 @@ class RunClient { * * @param {string} run_id - ID of the run to log under. (required) * @param {string} model_json - MLmodel file in json format. (required) - * @returns {Promise} - A promise that resolves when the logging is complete. + * @returns {Promise} - A promise that resolves when the logging is complete. */ async logModel(run_id, model_json) { if (!run_id || model_json) { @@ -249,6 +257,8 @@ class RunClient { if (!response.ok) { throw new Error(`Error logging model: ${response.statusText}`); } + + return; } /** @@ -275,6 +285,8 @@ class RunClient { if (!response.ok) { throw new Error(`Error in logging inputs: ${response.statusText}`); } + + return; } /** @@ -285,7 +297,7 @@ class RunClient { * are guaranteed to support key values up to 250 bytes in size. (required) * @param {string} value - String value of the tag being logged. Maximum size depends on storage * backend. All storage backends are guaranteed to support key values up to 5000 bytes in size. (required) - * @returns {Promise} - A promise that resolves when the logging is complete. + * @returns {Promise} - A promise that resolves when the logging is complete. */ async setTag(run_id, key, value) { if (!run_id) { @@ -307,6 +319,8 @@ class RunClient { if (!response.ok) { throw new Error(`Error setting tag: ${response.statusText}`); } + + return; } /** @@ -314,7 +328,7 @@ class RunClient { * * @param {string} run_id - ID of the run that the tag was logged under. (required) * @param {string} key - Name of the tag. Maximum size is 255 bytes. (required) - * @returns {Promise} - A promise that resolves when the deletion is complete. + * @returns {Promise} - A promise that resolves when the deletion is complete. */ async deleteTag(run_id, key) { if (!run_id) { @@ -336,10 +350,10 @@ class RunClient { if (!response.ok) { throw new Error( - `Error logging param: ${data.message || response.statusText}` + `Error deleting tag: ${data.message || response.statusText}` ); } - return data; + return; } /** @@ -348,8 +362,7 @@ class RunClient { * @param {string} run_id - ID of the run under which to log the param. (required)) * @param {string} key - Name of the param. Maximum size is 255 bytes. (required) * @param {string} value - String value of the param being logged. Maximum size is 6000 bytes. (required) - * @returns {Promise} - A promise that resolves when the logging is complete. - * Note: A param can be logged only once for a run + * @returns {Promise} - A promise that resolves when the logging is complete. */ async logParam(run_id, key, value) { if (!run_id) { @@ -379,11 +392,11 @@ class RunClient { * @param {string} run_id - ID of the run from which to fetch metric values. (required) * @param {string} metric_key - Name of the metric. (required) * @param {string} page_token - Token indicating the page of metric history to fetch. - * @param {INT32} max_results - Maximum number of logged instances of a metric for a run to return per call. + * @param {number} max_results - Maximum number of logged instances of a metric for a run to return per call. * Backend servers may restrict the value of max_results depending on performance requirements. Requests that do not * specify this value will behave as non-paginated queries where all metric history values for a given metric * within a run are returned in a single response. - * @returns {Promise} - A promise that resolves with the values for the specified metric. + * @returns {Promise} - A promise that resolves with the values for the specified metric. */ async getMetricHistory(run_id, metric_key, page_token, max_results) { if (!run_id) { @@ -412,24 +425,26 @@ class RunClient { } /** + * Search for runs that satisfy expressions. Search expressions can use Metric and Param keys. * - * @param {Array<{key: string, value: string}>} experiment_ids - List of experiment IDs to search over. + * @param {Array} experiment_ids - List of experiment IDs to search over. * @param {string} filter - A filter expression over params, metrics, and tags, that allows returning a subset of runs. * The syntax is a subset of SQL that supports ANDing together binary operations between a param, metric, or tag and a constant. * Example: metrics.rmse < 1 and params.model_class = 'LogisticRegression' * You can select columns with special characters (hyphen, space, period, etc.) by using * double quotes: metrics."model class" = 'LinearRegression' and tags."user-name" = 'Tomas' * Supported operators are =, !=, >, >=, <, and <=. - * @param {ViewType} run_view_type - Whether to display only active, only deleted, or all runs. Defaults to active runs. - * @param {INT32} max_results - Maximum number of runs desired. If unspecified, defaults to 1000. All servers are + * @param {string} run_view_type - Whether to display only active, only deleted, or all runs. Defaults to active runs. + * @param {number} max_results - Maximum number of runs desired. If unspecified, defaults to 1000. All servers are * guaranteed to support a max_results theshold of at least 50,000 but may support more. Callers of this endpoint are * encouraged to pass max_results explicitly and leverage page_token to iterate through experiments. - * @param {Array<{key: string, value: string}>} order_by - List of columns to be ordered by, including attributes, params, metrics, + * @param {Array} order_by - List of columns to be ordered by, including attributes, params, metrics, * and tags with an optional "DESC" or "ASC" annotation, where "ASC" is the default. * Example: ["params.input DESC","metrics.alpha ASC", "metrics.rmse"] Tiebreaks are done by start_time DESC followed by run_id for * runs with the same start time (and this is the default ordering criterion if order_by is not provided). - * @param {string} page_token - * @returns {Promise} - A promise that resovles with the runs that match the search criteria. */ async searchRuns( experiment_ids, @@ -477,16 +492,16 @@ class RunClient { * List artifacts for a run. Takes an optional artifact_path prefix which if specified, the response contains only artifacts with the specified prefix. * * @param {string} run_id - ID of the run whose artifacts to list. (required) - * @param {string} artifact_path - Filter artifacts matching this path (a relative path from the root artifact directory). + * @param {string} path - Filter artifacts matching this path (a relative path from the root artifact directory). * @param {string} page_token - Token indicating the page of artifact results to fetch. - * @returns {Promise} - A promise that resolves with a list artifacts for the specified run. + * @returns {Promise} - A promise that resolves with a list artifacts for the specified run. */ - async listArtifacts(run_id, artifact_path = '', page_token = '') { + async listArtifacts(run_id, path = '', page_token = '') { if (!run_id) { throw new Error('run_id is required'); } const response = await fetch( - `${this.trackingUri}/api/2.0/mlflow/artifacts/list?run_id=${run_id}&run_uuid=${run_id}&path=${artifact_path}&page_token=${page_token}` + `${this.trackingUri}/api/2.0/mlflow/artifacts/list?run_id=${run_id}&run_uuid=${run_id}&path=${path}&page_token=${page_token}` ); /** * data can have the fields: From 6ed8ea02602469f5f1a9682c8f5165318b6614a8 Mon Sep 17 00:00:00 2001 From: Kyler-Chiago Date: Tue, 1 Oct 2024 18:15:27 -0700 Subject: [PATCH 088/357] oops, accidentally updated local dev --- mlflow/package-lock.json | 44 +-- .../src/model-registry/ModelVersionClient.ts | 335 ++++++++++++++++++ mlflow/src/workflows/ModelManager.ts | 242 +++++++++++++ mlflow/tests/ModelVersionClientTest.ts | 28 ++ 4 files changed, 620 insertions(+), 29 deletions(-) create mode 100644 mlflow/src/model-registry/ModelVersionClient.ts create mode 100644 mlflow/src/workflows/ModelManager.ts create mode 100644 mlflow/tests/ModelVersionClientTest.ts diff --git a/mlflow/package-lock.json b/mlflow/package-lock.json index 3d472c8b..d932090e 100644 --- a/mlflow/package-lock.json +++ b/mlflow/package-lock.json @@ -486,17 +486,6 @@ "@jridgewell/sourcemap-codec": "^1.4.10" } }, - "node_modules/@pkgjs/parseargs": { - "version": "0.11.0", - "resolved": "https://registry.npmjs.org/@pkgjs/parseargs/-/parseargs-0.11.0.tgz", - "integrity": "sha512-+1VkjdD0QBLPodGrJUeqarH8VAIvQODIbwh9XpP5Syisf7YoQgsJKPNFoqqLQlu+VQ/tVSshMR6loPMn8U+dPg==", - "dev": true, - "license": "MIT", - "optional": true, - "engines": { - "node": ">=14" - } - }, "node_modules/@tsconfig/node10": { "version": "1.0.11", "resolved": "https://registry.npmjs.org/@tsconfig/node10/-/node10-1.0.11.tgz", @@ -526,9 +515,9 @@ "license": "MIT" }, "node_modules/@types/node": { - "version": "22.5.4", - "resolved": "https://registry.npmjs.org/@types/node/-/node-22.5.4.tgz", - "integrity": "sha512-FDuKUJQm/ju9fT/SeX/6+gBzoPzlVCzfzmGkwKvRHQVxi4BntVbyIwf6a4Xn62mrvndLiml6z/UBXIdEVjQLXg==", + "version": "22.7.4", + "resolved": "https://registry.npmjs.org/@types/node/-/node-22.7.4.tgz", + "integrity": "sha512-y+NPi1rFzDs1NdQHHToqeiX2TIS79SWEAw9GYhkkx8bD0ChpfqC+n2j5OXOCpzfojBEBt6DnEnnG9MY0zk1XLg==", "dev": true, "license": "MIT", "dependencies": { @@ -750,9 +739,9 @@ } }, "node_modules/get-tsconfig": { - "version": "4.8.0", - "resolved": "https://registry.npmjs.org/get-tsconfig/-/get-tsconfig-4.8.0.tgz", - "integrity": "sha512-Pgba6TExTZ0FJAn1qkJAjIeKoDJ3CsI2ChuLohJnZl/tTU8MVrq3b+2t5UOPfRa4RMsorClBjJALkJUMjG1PAw==", + "version": "4.8.1", + "resolved": "https://registry.npmjs.org/get-tsconfig/-/get-tsconfig-4.8.1.tgz", + "integrity": "sha512-k9PN+cFBmaLWtVz29SkUoqU5O0slLuHJXt/2P+tMVFT+phsSGXGkp9t3rQIqdz0e+06EHNGs3oM6ZX1s2zHxRg==", "dev": true, "license": "MIT", "dependencies": { @@ -804,9 +793,9 @@ "license": "ISC" }, "node_modules/jackspeak": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/jackspeak/-/jackspeak-4.0.1.tgz", - "integrity": "sha512-cub8rahkh0Q/bw1+GxP7aeSe29hHHn2V4m29nnDlvCdlgU+3UGxkZp7Z53jLUdpX3jdTO0nJZUDl3xvbWc2Xog==", + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/jackspeak/-/jackspeak-4.0.2.tgz", + "integrity": "sha512-bZsjR/iRjl1Nk1UkjGpAzLNfQtzuijhn2g+pbZb98HQ1Gk8vM9hfbxeMBP+M2/UUdwj0RqGG3mlvk2MsAqwvEw==", "dev": true, "license": "BlueOak-1.0.0", "dependencies": { @@ -817,9 +806,6 @@ }, "funding": { "url": "https://github.com/sponsors/isaacs" - }, - "optionalDependencies": { - "@pkgjs/parseargs": "^0.11.0" } }, "node_modules/lru-cache": { @@ -866,9 +852,9 @@ } }, "node_modules/package-json-from-dist": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/package-json-from-dist/-/package-json-from-dist-1.0.0.tgz", - "integrity": "sha512-dATvCeZN/8wQsGywez1mzHtTlP22H8OEfPrVMLNr4/eGa+ijtLn/6M5f0dY8UKNrC2O9UCU6SSoG3qRKnt7STw==", + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/package-json-from-dist/-/package-json-from-dist-1.0.1.tgz", + "integrity": "sha512-UEZIS3/by4OC8vL3P2dTXRETpebLI2NiI5vIrjaD/5UtrkFX/tNbwjTSRAGC/+7CAo2pIcBaRgWmcBBHcsaCIw==", "dev": true, "license": "BlueOak-1.0.0" }, @@ -1114,9 +1100,9 @@ } }, "node_modules/tsx": { - "version": "4.19.0", - "resolved": "https://registry.npmjs.org/tsx/-/tsx-4.19.0.tgz", - "integrity": "sha512-bV30kM7bsLZKZIOCHeMNVMJ32/LuJzLVajkQI/qf92J2Qr08ueLQvW00PUZGiuLPP760UINwupgUj8qrSCPUKg==", + "version": "4.19.1", + "resolved": "https://registry.npmjs.org/tsx/-/tsx-4.19.1.tgz", + "integrity": "sha512-0flMz1lh74BR4wOvBjuh9olbnwqCPc35OOlfyzHba0Dc+QNUeWX/Gq2YTbnwcWPO3BMd8fkzRVrHcsR+a7z7rA==", "dev": true, "license": "MIT", "dependencies": { diff --git a/mlflow/src/model-registry/ModelVersionClient.ts b/mlflow/src/model-registry/ModelVersionClient.ts new file mode 100644 index 00000000..515b573b --- /dev/null +++ b/mlflow/src/model-registry/ModelVersionClient.ts @@ -0,0 +1,335 @@ +import { apiRequest } from "utils/ApiRequest"; + +class ModelVersionClient { + private baseUrl: string; + + constructor(trackingUri: string) { + this.baseUrl = trackingUri; + } + + /** + * Description - Creates a new version of a model + * @param modelName - the name of the registered model (required) + * @param source - the source path where the model artifacts are stored (required) + * @param run_id - the id of the run that generated this version (optional) + * @param tags - Tag of key/value pairs for the model version (optional) + * @param run_link - MLflow run link - the exact link of the run that generated this + * model version (optional) + * @param description - Description of the model version (optional) + * @returns - the created model version object + */ + async createModelVersion( + modelName: string, + source: string, + run_id?: string, + tags?: Array<{ key: string; value: string }>, + run_link?: string, + description?: string + ): Promise { + // fire off a post request to create the model versions + const { response, data } = await apiRequest( + this.baseUrl, + 'model-versions/create', + { + method: 'POST', + body: { name: modelName, source, run_id, tags, run_link, description }, + } + ); + + // is response ok? else throw error + if (!response.ok) { + throw new Error( + `Error creating model version: ${data.message || response.statusText}` + ); + } + + // return the model version obj + return data.model_version; + } + + /** + * Description - Gets the specified version of the model + * @param modelName - the name of the registered model (Required) + * @param version - the version number of the model to fetch (Required) + * @returns - the fetched model version object + */ + async getModelVersion(modelName: string, version: string): Promise { + // fire off a get request to fetch the model version + const { response, data } = await apiRequest( + this.baseUrl, + 'model-versions/get', + { + method: 'GET', + params: { name: modelName, version }, + } + ); + + // is response ok? else throw error + if (!response.ok) { + throw new Error( + `Error fetching model version: ${data.message || response.statusText}` + ); + } + + // return the model version obj + return data.model_version; + } + + /** + * Description - updates a specific model version. + * @param {string} modelName - the name of the registered model (Required) + * @param {string} version - the version number of the model to update (Required) + * @param {string} description - The description of the model version (Optional) + * @returns {Promise} - the updated model version object + */ + async updateModelVersion( + modelName: string, + version: string, + description?: string + ): Promise { + // fire off a patch request to update the model version + const { response, data } = await apiRequest( + this.baseUrl, + 'model-versions/update', + { + method: 'PATCH', + body: { name: modelName, version, description }, + } + ); + + // is response ok? else throw error + if (!response.ok) { + throw new Error( + `Error updating model version: ${data.message || response.statusText}` + ); + } + + // return the updated model version obj + return data.model_version; + } + + /** + * Description - deletes a specific model version. + * @param modelName - the name of the registered model (Required) + * @param version - the version number of the model to delete (Required) + * @returns - an empty promise object that resolves when the model version is deleted + */ + async deleteModelVersion(modelName: string, version: string): Promise { + // fire off a delete request to remove the model version + const { response, data } = await apiRequest( + this.baseUrl, + 'model-versions/delete', + { + method: 'DELETE', + body: { name: modelName, version }, + } + ); + + // is response ok? else throw error + if (!response.ok) { + throw new Error( + `Error deleting model version: ${data.message || response.statusText}` + ); + } + + // return nothing, just resolve + return; + } + + /** + * Description - searches for model versions based on provided filters. + * @param filter - the filter criteria for searching model versions (Optional) + * @param maxResults - the maximum number of results to return (Optional) + * @param order_by - List of columns to be ordered by (Optional) + * @param page_token - Pagination token to go to next page based on previous search query (Optional) + * @returns - an array of model versions that match the search criteria + */ + async searchModelVersions( + filter?: string, + maxResults?: number, + order_by?: Array, + page_token?: string + ): Promise> { + // let filter2: string = filter?.toString(); + const body: { [key: string]: any } = {}; + if (filter) { + body.filter = filter; + } + if (maxResults) { + body.maxResults = maxResults; + } + if (order_by) { + body.order_by = order_by; + } + if (page_token) { + body.page_token = page_token; + } + + // fire off a get request to search for model versions + const { response, data } = await apiRequest( + this.baseUrl, + 'model-versions/search', + { + method: 'GET', + params: body, + } + ); + + // is response ok? else throw error + if (!response.ok) { + throw new Error( + `Error searching model versions: ${data.message || response.statusText}` + ); + } + + // return an array of model versions that match the criteria + return data.model_versions; + } + + /** + * Description - retrieves the download uri for model version artifacts. + * @param - the name of the registered model (Required) + * @param - the version number of the model to fetch the uri for (Required) + * @returns - the uri for downloading the model version artifacts + */ + async getDownloadUriForModelVersionArtifacts( + modelName: string, + version: string + ): Promise { + // fire off a get request to fetch the download uri + const { response, data } = await apiRequest( + this.baseUrl, + 'model-versions/get-download-uri', + { + method: 'GET', + params: { name: modelName, version }, + } + ); + + // is response ok? else throw error + if (!response.ok) { + throw new Error( + `Error fetching download uri: ${data.message || response.statusText}` + ); + } + + // return the download uri as a string + return data.artifact_uri; + } + + /** + * transitions a model version to a different stage. + * + * @param modelName - the name of the registered model (Required) + * @param version - the version number of the model to transition (Required) + * @param stage - the stage to transition the model version to (e.g., 'staging', 'production') (Required) + * @param archive_existing_versions - This flag dictates whether all existing model + * versions in that stage should be atomically moved to the "archived" stage. This ensures + * that at-most-one model version exists in the target stage. (Required) + * @returns - the updated model version object after the stage transition + */ + async transitionModelVersionStage( + modelName: string, + version: string, + stage: string, + archive_existing_versions: boolean + ): Promise { + // fire off a post request to transition the model version stage + const { response, data } = await apiRequest( + this.baseUrl, + 'model-versions/transition-stage', + { + method: 'POST', + body: { name: modelName, version, stage, archive_existing_versions }, + } + ); + + // is response ok? else throw error + if (!response.ok) { + throw new Error( + `Error transitioning model version stage: ${ + data.message || response.statusText + }` + ); + } + + // return the updated model version obj + return data.model_version; + } + + /** + * sets a tag on a specific model version. + * + * @param modelName - the name of the registered model (required) + * @param version - the version number of the model to tag (required) + * @param key - the key of the tag (required) + * @param value - the value of the tag (required) + * @returns - a promise that resolves when the tag is set + */ + async setModelVersionTag( + modelName: string, + version: string, + key: string, + value: string + ): Promise { + // fire off a post request to set the tag on the model version + const { response, data } = await apiRequest( + this.baseUrl, + 'model-versions/set-tag', + { + method: 'POST', + body: { name: modelName, version, key, value }, + } + ); + + // is response ok? else throw error + if (!response.ok) { + throw new Error( + `Error setting model version tag: ${ + data.message || response.statusText + }` + ); + } + + // return nothing, just resolve + return; + } + + /** + * deletes a tag from a specific model version. + * + * @param modelName - the name of the registered model (required) + * @param version - the version number of the model to untag (required) + * @param key - the key of the tag to delete (required) + * @returns - a promise that resolves when the tag is deleted + */ + async deleteModelVersionTag( + modelName: string, + version: string, + key: string + ): Promise { + // fire off a delete request to remove the tag from the model version + const { response, data } = await apiRequest( + this.baseUrl, + 'model-versions/delete-tag', + { + method: 'DELETE', + body: { name: modelName, version, key }, + } + ); + + // is response ok? else throw error + if (!response.ok) { + throw new Error( + `Error deleting model version tag: ${ + data.message || response.statusText + }` + ); + } + + // return nothing, just resolve + return; + } +} + +export default ModelVersionClient; diff --git a/mlflow/src/workflows/ModelManager.ts b/mlflow/src/workflows/ModelManager.ts new file mode 100644 index 00000000..80630755 --- /dev/null +++ b/mlflow/src/workflows/ModelManager.ts @@ -0,0 +1,242 @@ +// import RunClient from '../tracking/RunClient'; +import ModelRegistryClient from "../model-registry/ModelRegistryClient"; +import ModelVersionClient from "../model-registry/ModelVersionClient"; + +class ModelManager { + private modelRegistry: ModelRegistryClient; + private modelVersion: ModelVersionClient; + + constructor(trackingUri: string) { + this.modelRegistry = new ModelRegistryClient(trackingUri); + this.modelVersion = new ModelVersionClient(trackingUri); + // this.runClient = new RunClient(trackingUri); + } + + /** + * Description - Creates a new registered model and creates the first version of that model. + * @param {string} name - Name of the registered model. (Required) + * @param {string} versionSource - URI indicating the location of the model artifacts. (Required) + * @param {string} versionRun_id - MLflow run ID for correlation, if versionSource was generated + * by an experiment run in MLflow tracking server. + * @returns {Promise} - the updated model version object + */ + async createRegisteredModelWithVersion(name: string, versionSource: string, versionRun_id: string): Promise { + await this.modelRegistry.createRegisteredModel(name); + const response = await this.modelVersion.createModelVersion( + name, + versionSource, + versionRun_id + ); + return response; + } + + /** + * Description - Updates a registered model's description and tag. + * @param name - Name of the registered model. (Required) + * @param tagKey - Name of the tag. (Required) + * @param tagValue - String value of the tag being logged. (Required) + * @param description - Description of the registered model. + * @returns - the updated registered model object + */ + async updateRegisteredModelDescriptionAndTag( + name: string, + tagKey: string, + tagValue: string, + description: string + ): Promise { + await this.modelRegistry.setRegisteredModelTag(name, tagKey, tagValue); + const response = await this.modelRegistry.updateRegisteredModel( + name, + description + ); + return response; + } + + /** + * Description - Updates the latest version of the specified registered model's description. + * And adds a new alias, and tag key/value for that latest version. + * @param name - Name of the registered model. (Required) + * @param alias - Name of the alias. (Required) + * @param description - The description for the model version. (Required) + * @param key - Name of the tag. (Required) + * @param value - Name of the value of the tag being logged. (Required) + * @returns - the updated model version object + */ + async updateAllLatestModelVersion(name: string, alias: string, description: string, key: string, value: string): Promise { + const data = await this.modelRegistry.getLatestModelVersions(name); + if (!data) { + throw new Error('Model has no version to update.'); + } else { + const [{ version }] = data; + await this.modelRegistry.setRegisteredModelAlias(name, alias, version); + await this.modelVersion.setModelVersionTag( + name, + version, + key, + value + ); + const response = await this.modelVersion.updateModelVersion( + name, + version, + description + ); + return response; + } + } + + /** + * Description - Adds a new tag key/value for the latest version of the specified registered model. + * @param name - Name of the registered model. (Required) + * @param key - Name of the tag. (Required) + * @param value - Name of the value of the tag being logged. (Required) + * @returns - a promise that resolves when the model version is deleted + */ + async setLatestModelVersionTag(name: string, key: string, value: string): Promise { + const data = await this.modelRegistry.getLatestModelVersions(name); + if (!data) { + throw new Error('Model has no version to set tag for.'); + } else { + const [{ version }] = data; + this.modelVersion.setModelVersionTag(name, version, key, value); + return; + } + } + + /** + * Description - Adds an alias for the latest version of the specified registered model. + * @param name - Name of the registered model. (Required) + * @param alias - Name of the alias. (Required) + * @returns - a promise that resolves when the model version is deleted + */ + async setLatestModelVersionAlias(name: string, alias: string): Promise { + const data = await this.modelRegistry.getLatestModelVersions(name); + if (!data) { + throw new Error('Model has no version to set alias for.'); + } else { + const [{ version }] = data; + this.modelRegistry.setRegisteredModelAlias(name, alias, version); + return; + } + } + + /** + * Description - Updates the description of the latest version of a registered model. + * @param name - Name of the registered model. (Required) + * @param description - The description for the model version. (Required) + * @returns - the updated model version object + */ + async updateLatestModelVersion(name: string, description: string): Promise { + const data = await this.modelRegistry.getLatestModelVersions(name); + if (!data) { + throw new Error('Model has no version to set description for.'); + } else { + const [{ version }] = data; + const response = await this.modelVersion.updateModelVersion( + name, + version, + description + ); + return response; + } + } + + /** + * Description - Updates the specified version of the specified registered model's description. + * And adds a new alias, and tag key/value for that specified version. + * @param name - Name of the registered model. (Required) + * @param version - Model version number. (Required) + * @param alias - Name of the alias. (Required) + * @param description - The description for the model version. (Required) + * @param key key - Name of the tag. (Required) + * @param value - Name of the value of the tag being logged. (Required) + * @returns - the updated model version object + */ + async updateAllModelVersion(name: string, version: string, alias: string, description: string, key: string, value: string): Promise { + await this.modelRegistry.setRegisteredModelAlias(name, alias, version); + await this.modelVersion.setModelVersionTag( + name, + version, + key, + value + ); + const response = await this.modelVersion.updateModelVersion( + name, + version, + description + ); + return response; + } + + /** + * Description - Deletes the latest version of the specified registered model. + * @param name - the model name + * @returns - a promise that resolves when the model version is deleted + */ + async deleteLatestModelVersion(name: string): Promise { + const data = await this.modelRegistry.getLatestModelVersions(name); + if (!data) { + throw new Error('Model has no version to delete.'); + } else { + const [{ version }] = data; + this.modelVersion.deleteModelVersion(name, version); + return; + } + } + + // Set it up so they can specify if they want the specified metric that is the greatest value, or the lowest value + + // Probably make it so it can also make a new model version if there's already a version of that modelName + /** + * Description - Looks through the runs with the given experiment id and through their metrics + * looking for the specified metric that has the highest or lowest value (can be specified). + * Then it creates a new model with the specified model name and creates a version of that + * model from the run with the best metric. + * @param {string[]} experiment_ids - An array containing an experiment id. (Required) + * @param {string} filterMetric - The name of the metric that we're filtering by. (Required) + * @param {string} metricMinOrMax - A string specifying if we want the minimum or maximum + * value of the specified metric. (Required) + * @param {string} modelName - The name of the new model that will be created. (Required) + */ + async createModelFromRunWithBestMetric( + experiment_ids: string[], + filterMetric: string, + metricMinOrMax: string, + modelName: string + ) { + const { runs } = await this.runClient.searchRuns( + experiment_ids, + `metrics.${filterMetric} != -99999` + ); + let num; + if (metricMinOrMax === 'min') { + num = Infinity; + } else if (metricMinOrMax === 'max') { + num = -Infinity; + } + let bestRun; + for (let i = 0; i < runs.length; i++) { + for (let x = 0; x < runs[i].data.metrics.length; x++) { + if (runs[i].data.metrics[x].key === `${filterMetric}`) { + if (metricMinOrMax === 'min' && num > runs[i].data.metrics[x].value) { + num = runs[i].data.metrics[x].value; + bestRun = runs[i]; + } else if ( + metricMinOrMax === 'max' && + num < runs[i].data.metrics[x].value + ) { + num = runs[i].data.metrics[x].value; + bestRun = runs[i]; + } + } + } + } + await this.modelRegistry.createRegisteredModel(modelName); + await this.modelVersion.createModelVersion( + modelName, + bestRun.info.artifact_uri, + bestRun.info.run_id + ); + } +} + +export { ModelManager }; diff --git a/mlflow/tests/ModelVersionClientTest.ts b/mlflow/tests/ModelVersionClientTest.ts new file mode 100644 index 00000000..1a9af073 --- /dev/null +++ b/mlflow/tests/ModelVersionClientTest.ts @@ -0,0 +1,28 @@ +// import ModelVersionClient from '../src/model-registry/ModelVersionClient'; +// import ModelVersionClient from '' +// import ModelVersionClient +// import ModelVersionClient from '../src/model-registry/ModelVersionClient'; + +// async function testModelVersionClient() { +// const client = new ModelVersionClient('http://localhost:5001'); + +// try { +// // Test creating a registered model +// console.log('Creating a new registered model...'); +// const newModel = await client.createModelVersion( +// 'test-modelVersion12321', +// "mlflow-artifacts:/784321942139901150/b3457c87f50440388da9d9ddabb1baaa/artifacts/iris_model", +// "b3457c87f50440388da9d9ddabb1baaa" +// ); +// console.log('Created model:', newModel); + +// // Test getting the registered model +// // console.log('\nGetting the registered model...'); +// // const retrievedModel = await client.getRegisteredModel('test-model'); +// // console.log('Retrieved model:', retrievedModel); +// } catch (error) { +// console.error('Error:', error.message); +// } +// } + +// testModelVersionClient(); \ No newline at end of file From 20d3914a63566ff245f98db0dde72eba41bc287c Mon Sep 17 00:00:00 2001 From: Kyler-Chiago Date: Tue, 1 Oct 2024 18:35:01 -0700 Subject: [PATCH 089/357] closer --- .../src/model-registry/ModelVersionClient.ts | 81 ++-- .../model_version_management.js | 452 ------------------ mlflow/src/workflows/ModelManager.ts | 80 ++-- mlflow/tests/ModelVersionClientTest.ts | 42 +- 4 files changed, 106 insertions(+), 549 deletions(-) delete mode 100644 mlflow/src/model-registry/model_version_management.js diff --git a/mlflow/src/model-registry/ModelVersionClient.ts b/mlflow/src/model-registry/ModelVersionClient.ts index 515b573b..f8e34bd4 100644 --- a/mlflow/src/model-registry/ModelVersionClient.ts +++ b/mlflow/src/model-registry/ModelVersionClient.ts @@ -9,14 +9,15 @@ class ModelVersionClient { /** * Description - Creates a new version of a model - * @param modelName - the name of the registered model (required) - * @param source - the source path where the model artifacts are stored (required) - * @param run_id - the id of the run that generated this version (optional) - * @param tags - Tag of key/value pairs for the model version (optional) - * @param run_link - MLflow run link - the exact link of the run that generated this + * @param {string} modelName - the name of the registered model (required) + * @param {string} source - the source path where the model artifacts are stored (required) + * @param {string} run_id - the id of the run that generated this version (optional) + * @param {string[]} tags - Tag of key/value pairs for the model version (optional) + * @param {string} run_link - MLflow run link - the exact link of the run that generated this * model version (optional) - * @param description - Description of the model version (optional) - * @returns - the created model version object + * @param {string} description - Description of the model version (optional) + * @returns {Promise} - the created model version object + * @throws {ApiError} If the API request fails */ async createModelVersion( modelName: string, @@ -49,9 +50,10 @@ class ModelVersionClient { /** * Description - Gets the specified version of the model - * @param modelName - the name of the registered model (Required) - * @param version - the version number of the model to fetch (Required) - * @returns - the fetched model version object + * @param {string} modelName - the name of the registered model (Required) + * @param {string} version - the version number of the model to fetch (Required) + * @returns {Promise} - the created model version object + * @throws {ApiError} If the API request fails */ async getModelVersion(modelName: string, version: string): Promise { // fire off a get request to fetch the model version @@ -80,7 +82,8 @@ class ModelVersionClient { * @param {string} modelName - the name of the registered model (Required) * @param {string} version - the version number of the model to update (Required) * @param {string} description - The description of the model version (Optional) - * @returns {Promise} - the updated model version object + * @returns {Promise} - the created model version object + * @throws {ApiError} If the API request fails */ async updateModelVersion( modelName: string, @@ -110,9 +113,10 @@ class ModelVersionClient { /** * Description - deletes a specific model version. - * @param modelName - the name of the registered model (Required) - * @param version - the version number of the model to delete (Required) - * @returns - an empty promise object that resolves when the model version is deleted + * @param {string} modelName - the name of the registered model (Required) + * @param {string} version - the version number of the model to delete (Required) + * @returns {Promise} + * @throws {ApiError} If the API request fails */ async deleteModelVersion(modelName: string, version: string): Promise { // fire off a delete request to remove the model version @@ -138,11 +142,12 @@ class ModelVersionClient { /** * Description - searches for model versions based on provided filters. - * @param filter - the filter criteria for searching model versions (Optional) - * @param maxResults - the maximum number of results to return (Optional) - * @param order_by - List of columns to be ordered by (Optional) - * @param page_token - Pagination token to go to next page based on previous search query (Optional) - * @returns - an array of model versions that match the search criteria + * @param {string} filter - the filter criteria for searching model versions (Optional) + * @param {number} maxResults - the maximum number of results to return (Optional) + * @param {string[]} order_by - List of columns to be ordered by (Optional) + * @param {string} page_token - Pagination token to go to next page based on previous search query (Optional) + * @returns {Promise} - an array of model versions that match the search criteria + * @throws {ApiError} If the API request fails */ async searchModelVersions( filter?: string, @@ -188,9 +193,10 @@ class ModelVersionClient { /** * Description - retrieves the download uri for model version artifacts. - * @param - the name of the registered model (Required) - * @param - the version number of the model to fetch the uri for (Required) - * @returns - the uri for downloading the model version artifacts + * @param {string} modelName - the name of the registered model (Required) + * @param {string} version - the version number of the model to fetch the uri for (Required) + * @returns {Promise} - the uri for downloading the model version artifacts + * @throws {ApiError} If the API request fails */ async getDownloadUriForModelVersionArtifacts( modelName: string, @@ -220,13 +226,14 @@ class ModelVersionClient { /** * transitions a model version to a different stage. * - * @param modelName - the name of the registered model (Required) - * @param version - the version number of the model to transition (Required) - * @param stage - the stage to transition the model version to (e.g., 'staging', 'production') (Required) - * @param archive_existing_versions - This flag dictates whether all existing model + * @param {string} modelName - the name of the registered model (Required) + * @param {string} version - the version number of the model to transition (Required) + * @param {string} stage - the stage to transition the model version to (e.g., 'staging', 'production') (Required) + * @param {boolean} archive_existing_versions - This flag dictates whether all existing model * versions in that stage should be atomically moved to the "archived" stage. This ensures * that at-most-one model version exists in the target stage. (Required) - * @returns - the updated model version object after the stage transition + * @returns {Promise} - the updated model version object after the stage transition + * @throws {ApiError} If the API request fails */ async transitionModelVersionStage( modelName: string, @@ -260,11 +267,12 @@ class ModelVersionClient { /** * sets a tag on a specific model version. * - * @param modelName - the name of the registered model (required) - * @param version - the version number of the model to tag (required) - * @param key - the key of the tag (required) - * @param value - the value of the tag (required) - * @returns - a promise that resolves when the tag is set + * @param {string} modelName - the name of the registered model (required) + * @param {string} version - the version number of the model to tag (required) + * @param {string} key - the key of the tag (required) + * @param {string} value - the value of the tag (required) + * @returns {Promise} + * @throws {ApiError} If the API request fails */ async setModelVersionTag( modelName: string, @@ -298,10 +306,11 @@ class ModelVersionClient { /** * deletes a tag from a specific model version. * - * @param modelName - the name of the registered model (required) - * @param version - the version number of the model to untag (required) - * @param key - the key of the tag to delete (required) - * @returns - a promise that resolves when the tag is deleted + * @param {string} modelName - the name of the registered model (required) + * @param {string} version - the version number of the model to untag (required) + * @param {string} key - the key of the tag to delete (required) + * @returns {Promise} + * @throws {ApiError} If the API request fails */ async deleteModelVersionTag( modelName: string, diff --git a/mlflow/src/model-registry/model_version_management.js b/mlflow/src/model-registry/model_version_management.js deleted file mode 100644 index bde5cc60..00000000 --- a/mlflow/src/model-registry/model_version_management.js +++ /dev/null @@ -1,452 +0,0 @@ -class ModelVersionManagement { - constructor(trackingUri) { - this.trackingUri = trackingUri; - } - - /** - * creates a new version of a registered model - * - * @param {string} modelName - the name of the registered model (required) - * @param {string} source - the source path where the model artifacts are stored (required) - * @param {string} [runId=null] - the id of the run that generated this version (optional) - * @returns {Promise} - the created model version object - */ - async createModelVersion(modelName, source, runId = null) { - // is model name provided? - if (!modelName) { - throw new Error('modelName is required'); - } - - // is source provided? - if (!source) { - throw new Error('source is required'); - } - - // construct url for create model version endpoint - const url = `${this.trackingUri}/api/2.0/mlflow/model-versions/create`; - - // build the request body with required and optional fields - const body = { - name: modelName, - source: source, - run_id: runId - }; - - // fire off a post request to create the model version - const response = await fetch(url, { - method: 'POST', - headers: { - 'Content-Type': 'application/json' - }, - body: JSON.stringify(body) - }); - - // parse the response - const data = await response.json(); - - // is response ok? else throw error - if (!response.ok) { - throw new Error(`Error creating model version: ${data.message || response.statusText}`); - } - - // return the model version obj - return data.model_version; - } - - /** - * fetches details of a specific model version. - * - * @param {string} modelName - the name of the registered model (required) - * @param {string} version - the version number of the model to fetch (required) - * @returns {Promise} - the fetched model version object - */ - async getModelVersion(modelName, version) { - // is model name provided? - if (!modelName) { - throw new Error('modelName is required'); - } - - // is version provided? - if (!version) { - throw new Error('version is required'); - } - - // construct url for get model version endpoint - const url = `${this.trackingUri}/api/2.0/mlflow/model-versions/get`; - - // build request query params - const params = new URLSearchParams({ - name: modelName, - version: version - }); - - // fire off a get request to fetch the model version - const response = await fetch(`${url}?${params}`, { - method: 'GET', - headers: { - 'Content-Type': 'application/json' - }, - }); - - // parse the response - const data = await response.json(); - - // is response ok? else throw error - if (!response.ok) { - throw new Error(`Error fetching model version: ${data.message || response.statusText}`); - } - - // return the model version obj - return data.model_version; - } - - /** - * updates a specific model version. - * - * @param {string} modelName - the name of the registered model (required) - * @param {string} version - the version number of the model to update (required) - * @param {string} description - - * @returns {Promise} - the updated model version object - */ - async updateModelVersion(modelName, version, description) { - // is model name provided? - if (!modelName) { - throw new Error('modelName is required'); - } - - // is version provided? - if (!version) { - throw new Error('version is required'); - } - - // are updates provided? is obj? - // if (!updates || typeof updates !== 'object') { - // throw new Error('updates object is required'); - // } - - // construct url for update model version endpoint - const url = `${this.trackingUri}/api/2.0/mlflow/model-versions/update`; - - // build the request body with update fields - const body = { - name: modelName, - version: version, - description - }; - - // fire off a patch request to update the model version - const response = await fetch(url, { - method: 'PATCH', - headers: { - 'Content-Type': 'application/json' - }, - body: JSON.stringify(body) - }); - - // parse the response - const data = await response.json(); - - // is response ok? else throw error - if (!response.ok) { - throw new Error(`Error updating model version: ${data.message || response.statusText}`); - } - - // return the updated model version obj - return data.model_version; - } - - /** - * deletes a specific model version. - * - * @param {string} modelName - the name of the registered model (required) - * @param {string} version - the version number of the model to delete (required) - * @returns {Promise} - a promise that resolves when the model version is deleted - */ - async deleteModelVersion(modelName, version) { - // is model name provided? - if (!modelName) { - throw new Error('modelName is required'); - } - // is version provided? - if (!version) { - throw new Error('version is required'); - } - - // construct url for delete model version endpoint - const url = `${this.trackingUri}/api/2.0/mlflow/model-versions/delete`; - - // fire off a delete request to remove the model version - const response = await fetch(url, { - method: 'DELETE', - headers: { - 'Content-Type': 'application/json' - }, - body: JSON.stringify({ name: modelName, version }) - }); - - // parse the response - const data = await response.json(); - - // is response ok? else throw error - if (!response.ok) { - throw new Error(`Error deleting model version: ${data.message || response.statusText}`); - } - - // return nothing, just resolve - return; - } - - /** - * searches for model versions based on provided filters. - * - * @param {string} [filter=''] - the filter criteria for searching model versions (optional) - * @param {number} [maxResults=100] - the maximum number of results to return (optional) - * @returns {Promise} - an array of model versions that match the search criteria - */ - async searchModelVersions(filter = '', maxResults = 100) { - // construct url for search model versions endpoint - const url = `${this.trackingUri}/api/2.0/mlflow/model-versions/search`; - - // build request query params with filter and maxResults - const params = new URLSearchParams({ - filter: filter, - max_results: maxResults - }); - - // fire off a get request to search for model versions - const response = await fetch(`${url}?${params}` - ); - - // parse the response - const data = await response.json(); - - // is response ok? else throw error - if (!response.ok) { - throw new Error(`Error searching model versions: ${data.message || response.statusText}`); - } - - // return an array of model versions that match the criteria - return data.model_versions; - } - - /** - * retrieves the download uri for model version artifacts. - * - * @param {string} modelName - the name of the registered model (required) - * @param {string} version - the version number of the model to fetch the uri for (required) - * @returns {Promise} - the uri for downloading the model version artifacts - */ - async getDownloadUriForModelVersionArtifacts(modelName, version) { - // is model name provided? - if (!modelName) { - throw new Error('modelName is required'); - } - - // is version provided? - if (!version) { - throw new Error('version is required'); - } - - // construct url for get download uri for model version artifacts endpoint - const url = `${this.trackingUri}/api/2.0/mlflow/model-versions/get-download-uri`; - - // build request query params - const params = new URLSearchParams({ - name: modelName, - version: version - }); - - // fire off a get request to fetch the download uri - const response = await fetch(`${url}?${params}`, { - method: 'GET', - headers: { - 'Content-Type': 'application/json' - }, - }); - - // parse the response - const data = await response.json(); - - // is response ok? else throw error - if (!response.ok) { - throw new Error(`Error fetching download uri: ${data.message || response.statusText}`); - } - - // return the download uri as a string - return data.artifact_uri; - } - - /** - * transitions a model version to a different stage. - * - * @param {string} modelName - the name of the registered model (required) - * @param {string} version - the version number of the model to transition (required) - * @param {string} stage - the stage to transition the model version to (e.g., 'staging', 'production') (required) - * @returns {Promise} - the updated model version object after the stage transition - */ - async transitionModelVersionStage(modelName, version, stage) { - // is model name provided? - if (!modelName) { - throw new Error('modelName is required'); - } - - // is version provided? - if (!version) { - throw new Error('version is required'); - } - - // is stage provided? - if (!stage) { - throw new Error('stage is required'); - } - - // construct url for transition model version stage endpoint - const url = `${this.trackingUri}/api/2.0/mlflow/model-versions/transition-stage`; - - // build the request body with stage information - const body = { - name: modelName, - version: version, - stage: stage - }; - - // fire off a post request to transition the model version stage - const response = await fetch(url, { - method: 'POST', - headers: { - 'Content-Type': 'application/json' - }, - body: JSON.stringify(body) - }); - - // parse the response - const data = await response.json(); - - // is response ok? else throw error - if (!response.ok) { - throw new Error(`Error transitioning model version stage: ${data.message || response.statusText}`); - } - - // return the updated model version obj - return data.model_version; - } - - /** - * sets a tag on a specific model version. - * - * @param {string} modelName - the name of the registered model (required) - * @param {string} version - the version number of the model to tag (required) - * @param {string} key - the key of the tag (required) - * @param {string} value - the value of the tag (required) - * @returns {Promise} - a promise that resolves when the tag is set - */ - async setModelVersionTag(modelName, version, key, value) { - // is model name provided? - if (!modelName) { - throw new Error('modelName is required'); - } - - // is version provided? - if (!version) { - throw new Error('version is required'); - } - - // is key provided? - if (!key) { - throw new Error('key is required'); - } - - // is value provided? - if (!value) { - throw new Error('value is required'); - } - - // construct url for set model version tag endpoint - const url = `${this.trackingUri}/api/2.0/mlflow/model-versions/set-tag`; - - // build the request body with tag key and value - const body = { - name: modelName, - version: version, - key: key, - value: value - }; - - // fire off a post request to set the tag on the model version - const response = await fetch(url, { - method: 'POST', - headers: { - 'Content-Type': 'application/json' - }, - body: JSON.stringify(body) - }); - - // parse the response - const data = await response.json(); - - // is response ok? else throw error - if (!response.ok) { - throw new Error(`Error setting model version tag: ${data.message || response.statusText}`); - } - - // return nothing, just resolve - return; - } - - /** - * deletes a tag from a specific model version. - * - * @param {string} modelName - the name of the registered model (required) - * @param {string} version - the version number of the model to untag (required) - * @param {string} key - the key of the tag to delete (required) - * @returns {Promise} - a promise that resolves when the tag is deleted - */ - async deleteModelVersionTag(modelName, version, key) { - // is model name provided? - if (!modelName) { - throw new Error('modelName is required'); - } - - // is version provided? - if (!version) { - throw new Error('version is required'); - } - - // is key provided? - if (!key) { - throw new Error('key is required'); - } - - // construct url for delete model version tag endpoint - const url = `${this.trackingUri}/api/2.0/mlflow/model-versions/delete-tag`; - - // build request query params - const params = new URLSearchParams({ - name: modelName, - version: version, - key: key - }); - - // fire off a delete request to remove the tag from the model version - const response = await fetch(url, { - method: 'DELETE', - headers: { - 'Content-Type': 'application/json' - }, - body: JSON.stringify({name: modelName, version, key}), - }); - - // parse the response - const data = await response.json(); - - // is response ok? else throw error - if (!response.ok) { - throw new Error(`Error deleting model version tag: ${data.message || response.statusText}`); - } - - // return nothing, just resolve - return; - } -} - -export { ModelVersionManagement }; \ No newline at end of file diff --git a/mlflow/src/workflows/ModelManager.ts b/mlflow/src/workflows/ModelManager.ts index 80630755..da93e4e3 100644 --- a/mlflow/src/workflows/ModelManager.ts +++ b/mlflow/src/workflows/ModelManager.ts @@ -197,46 +197,46 @@ class ModelManager { * value of the specified metric. (Required) * @param {string} modelName - The name of the new model that will be created. (Required) */ - async createModelFromRunWithBestMetric( - experiment_ids: string[], - filterMetric: string, - metricMinOrMax: string, - modelName: string - ) { - const { runs } = await this.runClient.searchRuns( - experiment_ids, - `metrics.${filterMetric} != -99999` - ); - let num; - if (metricMinOrMax === 'min') { - num = Infinity; - } else if (metricMinOrMax === 'max') { - num = -Infinity; - } - let bestRun; - for (let i = 0; i < runs.length; i++) { - for (let x = 0; x < runs[i].data.metrics.length; x++) { - if (runs[i].data.metrics[x].key === `${filterMetric}`) { - if (metricMinOrMax === 'min' && num > runs[i].data.metrics[x].value) { - num = runs[i].data.metrics[x].value; - bestRun = runs[i]; - } else if ( - metricMinOrMax === 'max' && - num < runs[i].data.metrics[x].value - ) { - num = runs[i].data.metrics[x].value; - bestRun = runs[i]; - } - } - } - } - await this.modelRegistry.createRegisteredModel(modelName); - await this.modelVersion.createModelVersion( - modelName, - bestRun.info.artifact_uri, - bestRun.info.run_id - ); - } + // async createModelFromRunWithBestMetric( + // experiment_ids: string[], + // filterMetric: string, + // metricMinOrMax: string, + // modelName: string + // ) { + // const { runs } = await this.runClient.searchRuns( + // experiment_ids, + // `metrics.${filterMetric} != -99999` + // ); + // let num; + // if (metricMinOrMax === 'min') { + // num = Infinity; + // } else if (metricMinOrMax === 'max') { + // num = -Infinity; + // } + // let bestRun; + // for (let i = 0; i < runs.length; i++) { + // for (let x = 0; x < runs[i].data.metrics.length; x++) { + // if (runs[i].data.metrics[x].key === `${filterMetric}`) { + // if (metricMinOrMax === 'min' && num > runs[i].data.metrics[x].value) { + // num = runs[i].data.metrics[x].value; + // bestRun = runs[i]; + // } else if ( + // metricMinOrMax === 'max' && + // num < runs[i].data.metrics[x].value + // ) { + // num = runs[i].data.metrics[x].value; + // bestRun = runs[i]; + // } + // } + // } + // } + // await this.modelRegistry.createRegisteredModel(modelName); + // await this.modelVersion.createModelVersion( + // modelName, + // bestRun.info.artifact_uri, + // bestRun.info.run_id + // ); + // } } export { ModelManager }; diff --git a/mlflow/tests/ModelVersionClientTest.ts b/mlflow/tests/ModelVersionClientTest.ts index 1a9af073..40e6d79f 100644 --- a/mlflow/tests/ModelVersionClientTest.ts +++ b/mlflow/tests/ModelVersionClientTest.ts @@ -1,28 +1,28 @@ -// import ModelVersionClient from '../src/model-registry/ModelVersionClient'; +import ModelVersionClient from '../src/model-registry/ModelVersionClient'; // import ModelVersionClient from '' // import ModelVersionClient // import ModelVersionClient from '../src/model-registry/ModelVersionClient'; -// async function testModelVersionClient() { -// const client = new ModelVersionClient('http://localhost:5001'); +async function testModelVersionClient() { + const client = new ModelVersionClient('http://localhost:5001'); -// try { -// // Test creating a registered model -// console.log('Creating a new registered model...'); -// const newModel = await client.createModelVersion( -// 'test-modelVersion12321', -// "mlflow-artifacts:/784321942139901150/b3457c87f50440388da9d9ddabb1baaa/artifacts/iris_model", -// "b3457c87f50440388da9d9ddabb1baaa" -// ); -// console.log('Created model:', newModel); + try { + // Test creating a registered model + console.log('Creating a new registered model version...'); + const newModelVersion = await client.createModelVersion( + 'test-modelVersion12321', + "mlflow-artifacts:/784321942139901150/b3457c87f50440388da9d9ddabb1baaa/artifacts/iris_model", + "b3457c87f50440388da9d9ddabb1baaa" + ); + console.log('Created model version:', newModelVersion); -// // Test getting the registered model -// // console.log('\nGetting the registered model...'); -// // const retrievedModel = await client.getRegisteredModel('test-model'); -// // console.log('Retrieved model:', retrievedModel); -// } catch (error) { -// console.error('Error:', error.message); -// } -// } + // Test getting the registered model + // console.log('\nGetting the registered model...'); + // const retrievedModel = await client.getRegisteredModel('test-model'); + // console.log('Retrieved model:', retrievedModel); + } catch (error) { + console.error('Error:', error.message); + } + } -// testModelVersionClient(); \ No newline at end of file + testModelVersionClient(); \ No newline at end of file From e280e074a01d41fbda564eae0df11ffe431f5763 Mon Sep 17 00:00:00 2001 From: Yiqun Zheng <16813562+yiqunzheng@users.noreply.github.com> Date: Tue, 1 Oct 2024 19:30:35 -0700 Subject: [PATCH 090/357] add apiError class in util and refactor model registry class accordingly --- .../src/model-registry/ModelRegistryClient.ts | 67 ++++++++++++------- mlflow/src/utils/apiError.ts | 9 +++ 2 files changed, 51 insertions(+), 25 deletions(-) create mode 100644 mlflow/src/utils/apiError.ts diff --git a/mlflow/src/model-registry/ModelRegistryClient.ts b/mlflow/src/model-registry/ModelRegistryClient.ts index 8ecc0e00..5908538d 100644 --- a/mlflow/src/model-registry/ModelRegistryClient.ts +++ b/mlflow/src/model-registry/ModelRegistryClient.ts @@ -1,3 +1,4 @@ +import { ApiError } from '../utils/apiError'; import { apiRequest } from '../utils/apiRequest'; class ModelRegistryClient { @@ -31,10 +32,11 @@ class ModelRegistryClient { ); if (!response.ok) { - throw new Error( + throw new ApiError( `Error creating registered model: ${ data.message || response.statusText - }` + }`, + response.status ); } @@ -59,10 +61,14 @@ class ModelRegistryClient { ); if (!response.ok) { - throw new Error( - `Error getting registered model: ${data.message || response.statusText}` + throw new ApiError( + `Error getting registered model: ${ + data.message || response.statusText + }`, + response.status ); } + return data.registered_model; } @@ -85,12 +91,14 @@ class ModelRegistryClient { ); if (!response.ok) { - throw new Error( + throw new ApiError( `Error renaming registered model: ${ data.message || response.statusText - }` + }`, + response.status ); } + return data.registered_model; } @@ -116,10 +124,11 @@ class ModelRegistryClient { ); if (!response.ok) { - throw new Error( + throw new ApiError( `Error updating registered model: ${ data.message || response.statusText - }` + }`, + response.status ); } @@ -144,10 +153,11 @@ class ModelRegistryClient { ); if (!response.ok) { - throw new Error( + throw new ApiError( `Error deleting registered model: ${ data.message || response.statusText - }` + }`, + response.status ); } @@ -173,8 +183,9 @@ class ModelRegistryClient { ); if (!response.ok) { - throw new Error( - `Error getting latest versions: ${data.message || response.statusText}` + throw new ApiError( + `Error getting latest versions: ${data.message || response.statusText}`, + response.status ); } @@ -213,10 +224,11 @@ class ModelRegistryClient { ); if (!response.ok) { - throw new Error( + throw new ApiError( `Error searching registered models: ${ data.message || response.statusText - }` + }`, + response.status ); } @@ -247,10 +259,11 @@ class ModelRegistryClient { ); if (!response.ok) { - throw new Error( + throw new ApiError( `Error setting registered model tag: ${ data.message || response.statusText - }` + }`, + response.status ); } @@ -276,10 +289,11 @@ class ModelRegistryClient { ); if (!response.ok) { - throw new Error( + throw new ApiError( `Error deleting registered model tag: ${ data.message || response.statusText - }` + }`, + response.status ); } @@ -310,10 +324,11 @@ class ModelRegistryClient { ); if (!response.ok) { - throw new Error( + throw new ApiError( `Error setting registered model alias: ${ data.message || response.statusText - }` + }`, + response.status ); } @@ -339,10 +354,11 @@ class ModelRegistryClient { ); if (!response.ok) { - throw new Error( + throw new ApiError( `Error deleting registered model alias: ${ data.message || response.statusText - }` + }`, + response.status ); } @@ -368,10 +384,11 @@ class ModelRegistryClient { ); if (!response.ok) { - throw new Error( + throw new ApiError( `Error getting model version by alias: ${ data.message || response.statusText - }` + }`, + response.status ); } @@ -379,4 +396,4 @@ class ModelRegistryClient { } } -export default ModelRegistryClient; \ No newline at end of file +export default ModelRegistryClient; diff --git a/mlflow/src/utils/apiError.ts b/mlflow/src/utils/apiError.ts new file mode 100644 index 00000000..f062e00b --- /dev/null +++ b/mlflow/src/utils/apiError.ts @@ -0,0 +1,9 @@ +export class ApiError extends Error { + statusCode: number; + + constructor(message: string, statusCode: number) { + super(message); + this.name = 'ApiError'; + this.statusCode = statusCode; + } +} From 06dd7d895fedbd8be8bc7e875ebdee4162d8c3b3 Mon Sep 17 00:00:00 2001 From: Kyler-Chiago Date: Tue, 1 Oct 2024 19:36:39 -0700 Subject: [PATCH 091/357] ModelVersionClient.ts and basic testing for it done --- mlflow/package-lock.json | 2 +- mlflow/package.json | 2 +- .../src/model-registry/ModelRegistryClient.ts | 3 +- .../src/model-registry/ModelVersionClient.ts | 64 ++++----- mlflow/tests/ModelVersionClientTest.ts | 132 ++++++++++++++---- 5 files changed, 144 insertions(+), 59 deletions(-) diff --git a/mlflow/package-lock.json b/mlflow/package-lock.json index d932090e..74865e82 100644 --- a/mlflow/package-lock.json +++ b/mlflow/package-lock.json @@ -12,7 +12,7 @@ "@types/node": "^22.5.4", "rimraf": "^6.0.1", "ts-node": "^10.9.2", - "tsx": "^4.19.0", + "tsx": "^4.19.1", "typescript": "^5.6.2" }, "engines": { diff --git a/mlflow/package.json b/mlflow/package.json index 823a78e6..e3cb1c59 100644 --- a/mlflow/package.json +++ b/mlflow/package.json @@ -25,7 +25,7 @@ "@types/node": "^22.5.4", "rimraf": "^6.0.1", "ts-node": "^10.9.2", - "tsx": "^4.19.0", + "tsx": "^4.19.1", "typescript": "^5.6.2" }, "engines": { diff --git a/mlflow/src/model-registry/ModelRegistryClient.ts b/mlflow/src/model-registry/ModelRegistryClient.ts index 8ecc0e00..38785377 100644 --- a/mlflow/src/model-registry/ModelRegistryClient.ts +++ b/mlflow/src/model-registry/ModelRegistryClient.ts @@ -1,4 +1,5 @@ -import { apiRequest } from '../utils/apiRequest'; +// import { apiRequest } from '../utils/apiRequest'; +import { apiRequest } from "utils/ApiRequest"; class ModelRegistryClient { private baseUrl: string; diff --git a/mlflow/src/model-registry/ModelVersionClient.ts b/mlflow/src/model-registry/ModelVersionClient.ts index f8e34bd4..23738f92 100644 --- a/mlflow/src/model-registry/ModelVersionClient.ts +++ b/mlflow/src/model-registry/ModelVersionClient.ts @@ -1,4 +1,4 @@ -import { apiRequest } from "utils/ApiRequest"; +import { apiRequest } from 'utils/ApiRequest'; class ModelVersionClient { private baseUrl: string; @@ -111,35 +111,6 @@ class ModelVersionClient { return data.model_version; } - /** - * Description - deletes a specific model version. - * @param {string} modelName - the name of the registered model (Required) - * @param {string} version - the version number of the model to delete (Required) - * @returns {Promise} - * @throws {ApiError} If the API request fails - */ - async deleteModelVersion(modelName: string, version: string): Promise { - // fire off a delete request to remove the model version - const { response, data } = await apiRequest( - this.baseUrl, - 'model-versions/delete', - { - method: 'DELETE', - body: { name: modelName, version }, - } - ); - - // is response ok? else throw error - if (!response.ok) { - throw new Error( - `Error deleting model version: ${data.message || response.statusText}` - ); - } - - // return nothing, just resolve - return; - } - /** * Description - searches for model versions based on provided filters. * @param {string} filter - the filter criteria for searching model versions (Optional) @@ -271,7 +242,7 @@ class ModelVersionClient { * @param {string} version - the version number of the model to tag (required) * @param {string} key - the key of the tag (required) * @param {string} value - the value of the tag (required) - * @returns {Promise} + * @returns {Promise} * @throws {ApiError} If the API request fails */ async setModelVersionTag( @@ -309,7 +280,7 @@ class ModelVersionClient { * @param {string} modelName - the name of the registered model (required) * @param {string} version - the version number of the model to untag (required) * @param {string} key - the key of the tag to delete (required) - * @returns {Promise} + * @returns {Promise} * @throws {ApiError} If the API request fails */ async deleteModelVersionTag( @@ -339,6 +310,35 @@ class ModelVersionClient { // return nothing, just resolve return; } + + /** + * Description - deletes a specific model version. + * @param {string} modelName - the name of the registered model (Required) + * @param {string} version - the version number of the model to delete (Required) + * @returns {Promise} + * @throws {ApiError} If the API request fails + */ + async deleteModelVersion(modelName: string, version: string): Promise { + // fire off a delete request to remove the model version + const { response, data } = await apiRequest( + this.baseUrl, + 'model-versions/delete', + { + method: 'DELETE', + body: { name: modelName, version }, + } + ); + + // is response ok? else throw error + if (!response.ok) { + throw new Error( + `Error deleting model version: ${data.message || response.statusText}` + ); + } + + // return nothing, just resolve + return; + } } export default ModelVersionClient; diff --git a/mlflow/tests/ModelVersionClientTest.ts b/mlflow/tests/ModelVersionClientTest.ts index 40e6d79f..44c7bffb 100644 --- a/mlflow/tests/ModelVersionClientTest.ts +++ b/mlflow/tests/ModelVersionClientTest.ts @@ -1,28 +1,112 @@ import ModelVersionClient from '../src/model-registry/ModelVersionClient'; -// import ModelVersionClient from '' -// import ModelVersionClient -// import ModelVersionClient from '../src/model-registry/ModelVersionClient'; +import ModelRegistryClient from '../src/model-registry/ModelRegistryClient'; + +// To test: cd /home/kchia/github/mlflow-js/mlflow +// npx tsx tests/ModelVersionClientTest.ts async function testModelVersionClient() { - const client = new ModelVersionClient('http://localhost:5001'); - - try { - // Test creating a registered model - console.log('Creating a new registered model version...'); - const newModelVersion = await client.createModelVersion( - 'test-modelVersion12321', - "mlflow-artifacts:/784321942139901150/b3457c87f50440388da9d9ddabb1baaa/artifacts/iris_model", - "b3457c87f50440388da9d9ddabb1baaa" - ); - console.log('Created model version:', newModelVersion); - - // Test getting the registered model - // console.log('\nGetting the registered model...'); - // const retrievedModel = await client.getRegisteredModel('test-model'); - // console.log('Retrieved model:', retrievedModel); - } catch (error) { - console.error('Error:', error.message); - } + const client = new ModelVersionClient('http://localhost:5001'); + const modelRegistryClient = new ModelRegistryClient('http://localhost:5001'); + const timestamp = Date.now(); + const modelVersionName = `testVersion-${timestamp}`; + const modelName = `test-model-${timestamp}`; + const renamedBaseName = `renamed-test-model-${timestamp}`; + const artifactSource = 'mlflow-artifacts:/784321942139901150/b3457c87f50440388da9d9ddabb1baaa/artifacts/iris_model'; + const run_id = 'b3457c87f50440388da9d9ddabb1baaa'; + const modelVersionDescription1 = 'This is test version 1 description'; + const modelVersionKey = 'version_1_key'; + const modelVersionValue = 'version_1_value'; + // const customAlias = `test-alias-v1-${timestamp}`; + + try { + // Creating a new registered model to test on + await modelRegistryClient.createRegisteredModel( + modelName, + [{ key: 'test-tag', value: 'test-value' }], + 'This is a test model' + ); + + // 1. Creating a registered model version + console.log('1. Creating a new registered model version...'); + const createdModelVersion = await client.createModelVersion( + modelName, + artifactSource, + run_id, + [{ key: 'test-tag', value: 'test-value' }], + ); + console.log('Created model version: ', createdModelVersion); + + // 2. Getting the specified version of the model + console.log('2. Getting the specified version of a model...'); + const retrievedModelVersion = await client.getModelVersion(modelName, '1'); + console.log('Retrieved model version: ', retrievedModelVersion); + + // 3. Updating a model version's description + console.log('3. Updating the specified version of a model\'s description...'); + const updatedModelVersionDescription = await client.updateModelVersion( + modelName, + '1', + modelVersionDescription1 + ); + console.log('Updated model version description: ', updatedModelVersionDescription); + + // 4. Searching for model versions based on provided filters + // Still need to test page_token + console.log('4. Seaching for model versions based on provided filters...'); + const filteredModelVersions = await client.searchModelVersions( + `name='${modelName}'`, + 5, + ["name"] + ) + console.log('Filtered model version(s): ', filteredModelVersions); + + // 5. Retrieving the download uri for model version artifacts. + console.log('5. Retrieving the download uri for model version artifacts...') + const downloadURI = await client.getDownloadUriForModelVersionArtifacts( + modelName, + '1' + ) + console.log('Download URI for ModelVersion Artifacts: ', downloadURI); + + // 6. Transitioning model version stage. + console.log('6. Transitioning model version stage...'); + const transitionedModelVersion = await client.transitionModelVersionStage( + modelName, + '1', + 'production', + true + ) + console.log('Transitioned model version: ', transitionedModelVersion); + + // 7. Setting model version tag + console.log('7. Setting model version tag...'); + const modelVersionTag = await client.setModelVersionTag( + modelName, + '1', + modelVersionKey, + modelVersionValue + ) + console.log('Set model version tag'); + + // 8. Deleting model version tag + console.log('8. Deleting model version tag...'); + const deletedModelVersionTag = await client.deleteModelVersionTag( + modelName, + '1', + modelVersionKey + ) + console.log('Deleted model version tag'); + + // 9. Deleting model version + console.log('9. Deleting model version...'); + const deletedModelVersion = await client.deleteModelVersion( + modelName, + '1', + ) + console.log('Deleted model version'); + } catch (error) { + console.error('Error:', error.message); } - - testModelVersionClient(); \ No newline at end of file +} + +testModelVersionClient(); From 91a3f5aaa98fccf2495f87548f4ef58fefd7e4d2 Mon Sep 17 00:00:00 2001 From: Yiqun Zheng <16813562+yiqunzheng@users.noreply.github.com> Date: Tue, 1 Oct 2024 19:38:08 -0700 Subject: [PATCH 092/357] Rename ApiRequest.ts to apiRequest.ts --- mlflow/src/utils/{ApiRequest.ts => apiRequest.ts} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename mlflow/src/utils/{ApiRequest.ts => apiRequest.ts} (100%) diff --git a/mlflow/src/utils/ApiRequest.ts b/mlflow/src/utils/apiRequest.ts similarity index 100% rename from mlflow/src/utils/ApiRequest.ts rename to mlflow/src/utils/apiRequest.ts From 6a7045695959d0f6ceabb5538fd5093cb52c81f2 Mon Sep 17 00:00:00 2001 From: Kyler-Chiago Date: Tue, 1 Oct 2024 19:45:22 -0700 Subject: [PATCH 093/357] yes --- mlflow/src/model-registry/ModelRegistryClient.ts | 2 +- mlflow/src/model-registry/ModelVersionClient.ts | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/mlflow/src/model-registry/ModelRegistryClient.ts b/mlflow/src/model-registry/ModelRegistryClient.ts index 38785377..4187774e 100644 --- a/mlflow/src/model-registry/ModelRegistryClient.ts +++ b/mlflow/src/model-registry/ModelRegistryClient.ts @@ -1,5 +1,5 @@ // import { apiRequest } from '../utils/apiRequest'; -import { apiRequest } from "utils/ApiRequest"; +import { apiRequest } from "../utils/ApiRequest"; class ModelRegistryClient { private baseUrl: string; diff --git a/mlflow/src/model-registry/ModelVersionClient.ts b/mlflow/src/model-registry/ModelVersionClient.ts index 23738f92..c884a81c 100644 --- a/mlflow/src/model-registry/ModelVersionClient.ts +++ b/mlflow/src/model-registry/ModelVersionClient.ts @@ -1,4 +1,4 @@ -import { apiRequest } from 'utils/ApiRequest'; +import { apiRequest } from '../utils/ApiRequest'; class ModelVersionClient { private baseUrl: string; From 59fa2244f5a2b68dc10520535629fb131f356a4b Mon Sep 17 00:00:00 2001 From: Kyler-Chiago Date: Tue, 1 Oct 2024 20:16:12 -0700 Subject: [PATCH 094/357] changed Error to ApiError in ModelVersionClient --- .../src/model-registry/ModelVersionClient.ts | 46 +++++++++++-------- 1 file changed, 28 insertions(+), 18 deletions(-) diff --git a/mlflow/src/model-registry/ModelVersionClient.ts b/mlflow/src/model-registry/ModelVersionClient.ts index c553a3ac..f4f8cbbf 100644 --- a/mlflow/src/model-registry/ModelVersionClient.ts +++ b/mlflow/src/model-registry/ModelVersionClient.ts @@ -1,3 +1,4 @@ +import { ApiError } from '../utils/apiError'; import { apiRequest } from '../utils/apiRequest'; class ModelVersionClient { @@ -39,8 +40,9 @@ class ModelVersionClient { // is response ok? else throw error if (!response.ok) { - throw new Error( - `Error creating model version: ${data.message || response.statusText}` + throw new ApiError( + `Error creating model version: ${data.message || response.statusText}`, + response.status ); } @@ -68,8 +70,9 @@ class ModelVersionClient { // is response ok? else throw error if (!response.ok) { - throw new Error( - `Error fetching model version: ${data.message || response.statusText}` + throw new ApiError( + `Error fetching model version: ${data.message || response.statusText}`, + response.status ); } @@ -102,8 +105,9 @@ class ModelVersionClient { // is response ok? else throw error if (!response.ok) { - throw new Error( - `Error updating model version: ${data.message || response.statusText}` + throw new ApiError( + `Error updating model version: ${data.message || response.statusText}`, + response.status ); } @@ -153,8 +157,9 @@ class ModelVersionClient { // is response ok? else throw error if (!response.ok) { - throw new Error( - `Error searching model versions: ${data.message || response.statusText}` + throw new ApiError( + `Error searching model versions: ${data.message || response.statusText}`, + response.status ); } @@ -185,8 +190,9 @@ class ModelVersionClient { // is response ok? else throw error if (!response.ok) { - throw new Error( - `Error fetching download uri: ${data.message || response.statusText}` + throw new ApiError( + `Error fetching download uri: ${data.message || response.statusText}`, + response.status ); } @@ -224,10 +230,11 @@ class ModelVersionClient { // is response ok? else throw error if (!response.ok) { - throw new Error( + throw new ApiError( `Error transitioning model version stage: ${ data.message || response.statusText - }` + }`, + response.status ); } @@ -263,10 +270,11 @@ class ModelVersionClient { // is response ok? else throw error if (!response.ok) { - throw new Error( + throw new ApiError( `Error setting model version tag: ${ data.message || response.statusText - }` + }`, + response.status ); } @@ -300,10 +308,11 @@ class ModelVersionClient { // is response ok? else throw error if (!response.ok) { - throw new Error( + throw new ApiError( `Error deleting model version tag: ${ data.message || response.statusText - }` + }`, + response.status ); } @@ -331,8 +340,9 @@ class ModelVersionClient { // is response ok? else throw error if (!response.ok) { - throw new Error( - `Error deleting model version: ${data.message || response.statusText}` + throw new ApiError( + `Error deleting model version: ${data.message || response.statusText}`, + response.status ); } From ab8687cf7949a3143bd518a4c14cb12aa459accc Mon Sep 17 00:00:00 2001 From: Kyler-Chiago Date: Tue, 1 Oct 2024 20:28:21 -0700 Subject: [PATCH 095/357] yes --- mlflow/tests/ModelVersionClientTest.ts | 3 --- 1 file changed, 3 deletions(-) diff --git a/mlflow/tests/ModelVersionClientTest.ts b/mlflow/tests/ModelVersionClientTest.ts index 44c7bffb..b6c7349e 100644 --- a/mlflow/tests/ModelVersionClientTest.ts +++ b/mlflow/tests/ModelVersionClientTest.ts @@ -8,15 +8,12 @@ async function testModelVersionClient() { const client = new ModelVersionClient('http://localhost:5001'); const modelRegistryClient = new ModelRegistryClient('http://localhost:5001'); const timestamp = Date.now(); - const modelVersionName = `testVersion-${timestamp}`; const modelName = `test-model-${timestamp}`; - const renamedBaseName = `renamed-test-model-${timestamp}`; const artifactSource = 'mlflow-artifacts:/784321942139901150/b3457c87f50440388da9d9ddabb1baaa/artifacts/iris_model'; const run_id = 'b3457c87f50440388da9d9ddabb1baaa'; const modelVersionDescription1 = 'This is test version 1 description'; const modelVersionKey = 'version_1_key'; const modelVersionValue = 'version_1_value'; - // const customAlias = `test-alias-v1-${timestamp}`; try { // Creating a new registered model to test on From 3d19adfd41910b846398386486785b110dfdceaa Mon Sep 17 00:00:00 2001 From: Kyler-Chiago Date: Tue, 1 Oct 2024 22:58:51 -0700 Subject: [PATCH 096/357] small comment change --- mlflow/tests/ModelVersionClientTest.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mlflow/tests/ModelVersionClientTest.ts b/mlflow/tests/ModelVersionClientTest.ts index b6c7349e..b6bbdaa8 100644 --- a/mlflow/tests/ModelVersionClientTest.ts +++ b/mlflow/tests/ModelVersionClientTest.ts @@ -1,7 +1,7 @@ import ModelVersionClient from '../src/model-registry/ModelVersionClient'; import ModelRegistryClient from '../src/model-registry/ModelRegistryClient'; -// To test: cd /home/kchia/github/mlflow-js/mlflow +// To test: // npx tsx tests/ModelVersionClientTest.ts async function testModelVersionClient() { From 59e5f94a2487bf1e7fbac0fd8b1d7f0d7b70457a Mon Sep 17 00:00:00 2001 From: Stephany Ho Date: Wed, 2 Oct 2024 11:10:33 -0400 Subject: [PATCH 097/357] Upload RunClientTest.ts and some changes in RunClient.ts --- mlflow/src/tracking/RunClient.ts | 50 ++++---- mlflow/tests/RunClientTest.ts | 196 +++++++++++++++++++++++++++++++ 2 files changed, 223 insertions(+), 23 deletions(-) create mode 100644 mlflow/tests/RunClientTest.ts diff --git a/mlflow/src/tracking/RunClient.ts b/mlflow/src/tracking/RunClient.ts index f12f7174..d6f35331 100644 --- a/mlflow/src/tracking/RunClient.ts +++ b/mlflow/src/tracking/RunClient.ts @@ -1,24 +1,6 @@ +import { run } from 'node:test'; import { apiRequest } from '../utils/apiRequest'; -interface InputTag { - key: string; - value: string; -} - -interface Dataset { - name: string; - digest: string; - source_type: string; - source: string; - schema?: string; - profile?: string; -} - -interface DatasetInput { - tags: InputTag[]; - dataset: Dataset; -} - class RunClient { private baseUrl: string; @@ -26,6 +8,10 @@ class RunClient { this.baseUrl = trackingUri; } + getBaseUrl(): string { + return this.baseUrl; + } + /** * Create a new run within an experiment. A run is usually a single execution of a machine learning or data * ETL pipeline. MLflow uses runs to track Param, Metric, and RunTag associated with a single execution. @@ -273,7 +259,20 @@ class RunClient { * @throws Error - If the API request fails. */ - async logInputs(run_id: string, datasets: DatasetInput[]): Promise { + async logInputs( + run_id: string, + datasets: Array<{ + tags?: Array<{ key: string; value: string }>; + dataset: { + name: string; + digest: string; + source_type: string; + source: string; + schema?: string; + profile?: string; + }; + }> + ): Promise { const { response, data } = await apiRequest( this.baseUrl, 'runs/log-inputs', @@ -482,17 +481,22 @@ class RunClient { * @returns A promise that resolves with a list artifacts for the specified run. * @throws Error - If the API request fails. */ + async listArtifacts( run_id: string, - path: string, - page_token: string + path?: string, + page_token?: string ): Promise { + const params: Record = { run_id }; + if (path !== undefined) params.path = path; + if (page_token !== undefined) params.page_token = page_token; + const { response, data } = await apiRequest( this.baseUrl, 'artifacts/list', { method: 'GET', - params: { run_id, path, page_token }, + params, } ); diff --git a/mlflow/tests/RunClientTest.ts b/mlflow/tests/RunClientTest.ts new file mode 100644 index 00000000..d333437d --- /dev/null +++ b/mlflow/tests/RunClientTest.ts @@ -0,0 +1,196 @@ +import { apiRequest } from '../src/utils/apiRequest'; +import RunClient from '../src/tracking/RunClient'; + +async function createExperiment( + client: RunClient, + name: string +): Promise { + const { response, data } = await apiRequest( + client.getBaseUrl(), + 'experiments/create', + { + method: 'POST', + body: { name }, + } + ); + + console.log('Response status:', response.status); + console.log( + 'Response headers:', + Object.fromEntries(response.headers.entries()) + ); + console.log('Response body:', data); + + if (!response.ok) { + throw new Error( + `Error creating experiment: ${data.message || response.statusText}` + ); + } + + return data.experiment_id; +} + +async function testRunClient(): Promise { + const client = new RunClient('http://127.0.0.1:5000'); + + try { + // createRun + console.log('Creating experiment...'); + const experiment_id = await createExperiment(client, 'Experiment 5'); + console.log('Created experiment ID: ', experiment_id); + + console.log('Creating run...'); + // const run = await client.createRun(experiment_id); + const run = await client.createRun(experiment_id); + console.log('Created run: ', run); + + // deleteRun + const runId = (run as any).info.run_id; + console.log(`Deleting run ID: ${runId}...`); + await client.deleteRun(runId); + console.log('Deleted run: ', runId); + + // restoreRun + console.log(`Restoring run ID: ${runId}...`); + await client.restoreRun(runId); + console.log('Restored run: ', runId); + + // getRun + console.log(`Fetching run ID: ${runId}...`); + const fetchedRun = await client.getRun(runId); + console.log('Fetched run: ', fetchedRun); + + // updateRun + console.log(`Updating run for run ID: ${runId}...`); + const updatedRun = await client.updateRun( + runId, + 'FINISHED', + 1728881022624, + 'Ruby' + ); + console.log('Updated run: ', updatedRun); + + // logMetric + console.log(`Logging metric for run ID: ${runId}...`); + await client.logMetric(runId, 'accuracy', 0.9); + console.log('Logged metric'); + + // logBatch + console.log('Creating another run...'); + const run2 = await client.createRun(experiment_id); + console.log('Created run2: ', run2); + const run2Id = (run2 as any).info.run_id; + + console.log(`Loggning batch for run ID: ${run2Id}...`); + await client.logBatch( + run2Id, + [ + { key: 'accuracy', value: 0.83, timestamp: 1694000700000 }, + { key: 'loss', value: 0.18, timestamp: 1694000700000 }, + ], + [ + { key: 'learning_rate', value: '0.0001' }, + { key: 'batch_size', value: '256' }, + ], + [ + { key: 'model_type', value: 'GradientBoosting' }, + { key: 'data_version', value: 'v1.7' }, + ] + ); + console.log('Logged batch'); + + // logModel + console.log(`Logging model for run ID: ${run2Id}...`); + const model = { + artifact_path: 'pytorch_dnn', + flavors: { + python_function: { + env: 'conda.yaml', + loader_module: 'mlflow.pytorch', + model_path: 'model.pth', + python_version: '3.8.10', + }, + pytorch: { + model_data: 'model.pth', + pytorch_version: '1.9.0', + code: 'model-code', + }, + }, + mlflow_version: '1.20.2', + model_uuid: '123e4567-e89b-12d3-a456-426614174001', + utc_time_created: '2023-09-14 10:15:00.000000', + run_id: run2Id, + }; + + const model_json = JSON.stringify(model); + + await client.logModel(run2Id, model_json); + console.log('Logged model'); + + // logInputs + console.log(`Logging inputs for run ID: ${run2Id}...`); + const datasets = [ + { + tags: [ + { key: 'version', value: '1.0' }, + { key: 'environment', value: 'production' }, + ], + dataset: { + name: 'test_dataset', + digest: 'abc123', + source_type: 'local', + source: '/path/to/data.csv', + }, + }, + ]; + + await client.logInputs(run2Id, datasets); + console.log('Logged inputs'); + + // setTag + console.log('Creating another run...'); + const run3 = await client.createRun(experiment_id); + console.log('Created run3: ', run3); + const run3Id = (run3 as any).info.run_id; + + console.log(`Setting tag for run ID ${run3Id}...`); + await client.setTag(run3Id, 'accuracy', '0.99'); + console.log('Finished setting tag'); + + // deleteTag + console.log(`Deleting tag for run ID: ${run3Id}...`); + await client.deleteTag(run3Id, 'accuracy'); + console.log('Deleted tag'); + + // logParam + console.log(`Logging param for run ID: ${run3Id}...`); + await client.logParam(run3Id, 'learning_rate', '0.001'); + console.log('Logged param'); + + // getMetricHistory + console.log(`Logging metric for run ID: ${run3Id}...`); + await client.logMetric(run3Id, 'accuracy', 0.95); + console.log('Logged metric'); + + console.log(`Fetching metric history for run ID: ${run3Id}...`); + const metricHistory = await client.getMetricHistory(run3Id, 'accuracy'); + console.log('Fetched metric history: ', metricHistory); + + // searchRuns + console.log(`Searching runs for experiment ID: 643644329517739250...`); + const searchedRuns = await client.searchRuns( + ['643644329517739250'], + 'metrics.accuracy<0.9' + ); + console.log('Searched runs: ', searchedRuns); + + // listArtifacts + console.log(`Listing artifacts for run ID ${run3Id}...`); + const artifacts = await client.listArtifacts(run3Id); + console.log('Artifacts: ', artifacts); + } catch (error) { + console.error('Error: ', error.message); + } +} + +testRunClient(); From 36d2df1a8cbefbf90e368754c2365302c9972aa7 Mon Sep 17 00:00:00 2001 From: Yiqun Zheng <16813562+yiqunzheng@users.noreply.github.com> Date: Wed, 2 Oct 2024 09:03:29 -0700 Subject: [PATCH 098/357] Rename MLflow.ts to mlflow.ts --- mlflow/src/{MLflow.ts => mlflow.ts} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename mlflow/src/{MLflow.ts => mlflow.ts} (100%) diff --git a/mlflow/src/MLflow.ts b/mlflow/src/mlflow.ts similarity index 100% rename from mlflow/src/MLflow.ts rename to mlflow/src/mlflow.ts From e4d68f2a511116a346b7cd5eefb565c884003632 Mon Sep 17 00:00:00 2001 From: Stephany Ho Date: Wed, 2 Oct 2024 12:08:16 -0400 Subject: [PATCH 099/357] Refactor ApiError handling in RunClient --- mlflow/src/tracking/RunClient.ts | 255 ++++++++++++++++--------------- mlflow/tests/RunClientTest.ts | 4 +- 2 files changed, 136 insertions(+), 123 deletions(-) diff --git a/mlflow/src/tracking/RunClient.ts b/mlflow/src/tracking/RunClient.ts index d6f35331..81ded45e 100644 --- a/mlflow/src/tracking/RunClient.ts +++ b/mlflow/src/tracking/RunClient.ts @@ -1,4 +1,4 @@ -import { run } from 'node:test'; +import { ApiError } from '../utils/apiError'; import { apiRequest } from '../utils/apiRequest'; class RunClient { @@ -8,35 +8,32 @@ class RunClient { this.baseUrl = trackingUri; } - getBaseUrl(): string { - return this.baseUrl; - } - /** * Create a new run within an experiment. A run is usually a single execution of a machine learning or data * ETL pipeline. MLflow uses runs to track Param, Metric, and RunTag associated with a single execution. * - * @param experiment_id - ID of the associated experiment. (required) - * @param run_name - Name of the run. - * @param start_time - Unix timestamp in milliseconds of when the run started. - * @param tags - Additional metadata for the run. - * @returns A promise that resolves with the created run object. - * @throws Error - If the API request fails. + * @param {string} experiment_id - ID of the associated experiment. (required) + * @param {string} run_name - Name of the run. + * @param {number} start_time - Unix timestamp in milliseconds of when the run started. + * @param {Array<{ key: string; value: string }>} [tags] - Additional metadata for the run. + * @returns {Promise} A promise that resolves with the created run object. + * @throws {ApiError} If the API request fails. */ async createRun( experiment_id: string, run_name?: string, start_time: number = Date.now(), tags?: Array<{ key: string; value: string }> - ): Promise { + ): Promise { const { response, data } = await apiRequest(this.baseUrl, 'runs/create', { method: 'POST', body: { experiment_id, run_name, start_time, tags }, }); if (!response.ok) { - throw new Error( - `Error creating run: ${data.message || response.statusText}` + throw new ApiError( + `Error creating run: ${data.message || response.statusText}`, + response.status ); } @@ -46,9 +43,9 @@ class RunClient { /** * Mark a run for deletion. * - * @param run_id - ID of the run to delete. (required) - * @returns A promise that resolves when the run is deleted. - * @throws Error - If the API request fails. + * @param {string} run_id - ID of the run to delete. (required) + * @returns {Promise} A promise that resolves when the run is deleted. + * @throws {ApiError} If the API request fails. */ async deleteRun(run_id: string): Promise { const { response, data } = await apiRequest(this.baseUrl, 'runs/delete', { @@ -57,8 +54,9 @@ class RunClient { }); if (!response.ok) { - throw new Error( - `Error deleting run: ${data.message || response.statusText}` + throw new ApiError( + `Error deleting run: ${data.message || response.statusText}`, + response.status ); } @@ -68,9 +66,9 @@ class RunClient { /** * Restore a deleted run. * - * @param run_id - ID of the run to restore. (required) - * @returns A promise that resolves when the run is restored. - * @throws Error - If the API request fails. + * @param {string} run_id - ID of the run to restore. (required) + * @returns {Promise} A promise that resolves when the run is restored. + * @throws {ApiError} If the API request fails. */ async restoreRun(run_id: string): Promise { const { response, data } = await apiRequest(this.baseUrl, 'runs/restore', { @@ -79,8 +77,9 @@ class RunClient { }); if (!response.ok) { - throw new Error( - `Error restoring run: ${data.message || response.statusText}` + throw new ApiError( + `Error restoring run: ${data.message || response.statusText}`, + response.status ); } @@ -92,19 +91,20 @@ class RunClient { * are logged for a run, return only the value with the latest timestamp. If there are multiple values with * the latest timestamp, return the maximum of these values. * - * @param run_id - ID of the run to fetch. (required) - * @returns A promise that resolves with the fetched run object. - * @throws Error - If the API request fails. + * @param {string} run_id - ID of the run to fetch. (required) + * @returns {Promise} A promise that resolves with the fetched run object. + * @throws {ApiError} If the API request fails */ - async getRun(run_id: string): Promise { + async getRun(run_id: string): Promise { const { response, data } = await apiRequest(this.baseUrl, 'runs/get', { method: 'GET', params: { run_id }, }); if (!response.ok) { - throw new Error( - `Error fetching run: ${data.message || response.statusText}` + throw new ApiError( + `Error fetching run: ${data.message || response.statusText}`, + response.status ); } @@ -114,27 +114,28 @@ class RunClient { /** * Update run metadata. * - * @param run_id - ID of the run to update. (required) - * @param status - Updated status of the run. - * @param end_time - Unix timestamp in milliseconds of when the run ended. - * @param run_name - Updated name of the run. - * @returns A promise that resolves with the updated metadata of the run. - * @throws Error - If the API request fails. + * @param {string} run_id - ID of the run to update. (required) + * @param {string} status - Updated status of the run. + * @param {number} end_time - Unix timestamp in milliseconds of when the run ended. + * @param {string} run_name - Updated name of the run. + * @returns {Promise} A promise that resolves with the updated metadata of the run. + * @throws {ApiError} If the API request fails. */ async updateRun( run_id: string, status?: 'RUNNING' | 'SCHEDULED' | 'FINISHED' | 'FAILED' | 'KILLED', end_time?: number, run_name?: string - ): Promise { + ): Promise { const { response, data } = await apiRequest(this.baseUrl, 'runs/update', { method: 'POST', body: { run_id, status, end_time, run_name }, }); if (!response.ok) { - throw new Error( - `Error updating run: ${data.message || response.statusText}` + throw new ApiError( + `Error updating run: ${data.message || response.statusText}`, + response.status ); } @@ -145,13 +146,13 @@ class RunClient { * Log a metric for a run. A metric is a key-value pair (string key, float value) with an associated timestamp. * Examples include the various metrics that represent ML model accuracy. A metric can be logged multiple times. * - * @param run_id - ID of the run under which to log the metric. (required) - * @param key - Name of the metric. (required) - * @param value - Double value of the metric being logged. (required) - * @param timestamp - Unix timestamp in milliseconds at the time metric was logged. (required) - * @param step - Step at which to log the metric. - * @returns A promise that resolves when the logging is complete. - * @throws Error - If the API request fails. + * @param {string} run_id - ID of the run under which to log the metric. (required) + * @param {string} key - Name of the metric. (required) + * @param {number} value - Double value of the metric being logged. (required) + * @param {number} timestamp - Unix timestamp in milliseconds at the time metric was logged. (required) + * @param {number} step - Step at which to log the metric. + * @returns {Promise} A promise that resolves when the logging is complete. + * @throws {ApiError} If the API request fails. */ async logMetric( @@ -171,8 +172,9 @@ class RunClient { ); if (!response.ok) { - throw new Error( - `Error logging metric: ${data.message || response.statusText}` + throw new ApiError( + `Error logging metric: ${data.message || response.statusText}`, + response.status ); } @@ -184,15 +186,15 @@ class RunClient { * respond with an error (non-200 status code). In case of error (due to internal server error or an invalid * request), partial data may be written. * - * @param run_id - ID of the run to log under. (required) - * @param metrics- Metrics to log. A single request can contain up to 1000 metrics, and up to 1000 metrics, - * params, and tags in total. - * @param params - Params to log. A single request can contain up to 100 params, and up to 1000 metrics, - * params, and tags in total. - * @param tags - Tags to log. A single request can contain up to 100 tags, and up to 1000 metrics, params, - * and tags in total. - * @returns A promise that resolves when the logging is complete. - * @throws Error - If the API request fails. + * @param {string} run_id - ID of the run to log under. (required) + * @param {Array<{key: string; value: number; timestamp: number; step: number}>} [metrics]- Metrics to log. + * A single request can contain up to 1000 metrics, and up to 1000 metrics, params, and tags in total. + * @param {Array<{ key: string; value: string }>} [params] - Params to log. A single request can contain up + * to 100 params, and up to 1000 metrics, params, and tags in total. + * @param {Array<{ key: string; value: string }>} [tags] - Tags to log. A single request can contain up to + * 100 tags, and up to 1000 metrics, params, and tags in total. + * @returns {Promise} A promise that resolves when the logging is complete. + * @throws {ApiError} If the API request fails. */ async logBatch( run_id: string, @@ -215,8 +217,9 @@ class RunClient { ); if (!response.ok) { - throw new Error( - `Error logging batch: ${data.message || response.statusText}` + throw new ApiError( + `Error logging batch: ${data.message || response.statusText}`, + response.status ); } @@ -226,10 +229,11 @@ class RunClient { /** * Logs a model. * - * @param run_id - ID of the run to log under. (required) - * @param model_json - MLmodel file in json format. (required) - * @returns A promise that resolves when the logging is complete. - * @throws Error - If the API request fails. + * @param {string} run_id - ID of the run to log under. (required) + * @param {string} model_json - MLmodel file in json format. Should conform to the MLflow model format, + * including fields like artifact_path, flavors, model_uuid, utc_time_created, and run_id. (required) + * @returns {Promise} A promise that resolves when the logging is complete. + * @throws {ApiError} If the API request fails. */ async logModel(run_id: string, model_json: string): Promise { const { response, data } = await apiRequest( @@ -242,8 +246,9 @@ class RunClient { ); if (!response.ok) { - throw new Error( - `Error logging model: ${data.message || response.statusText}` + throw new ApiError( + `Error logging model: ${data.message || response.statusText}`, + response.status ); } @@ -253,10 +258,11 @@ class RunClient { /** * Logs inputs. * - * @param run_id - ID of the run to log under. (required) - * @param datasets - Dataset inputs. (required) - * @returns A promise that resolves when the logging is complete. - * @throws Error - If the API request fails. + * @param {string} run_id - ID of the run to log under. (required) + * @param {Array} [datasets] - Dataset inputs. Each object should have a 'dataset' property with 'name', + * 'digest', 'source_type', and 'source' fields. Optional 'tags' array can be included for each dataset. (required) + * @returns {Promise} A promise that resolves when the logging is complete. + * @throws {ApiError} If the API request fails. */ async logInputs( @@ -283,8 +289,9 @@ class RunClient { ); if (!response.ok) { - throw new Error( - `Error in logging inputs: ${data.message || response.statusText}` + throw new ApiError( + `Error in logging inputs: ${data.message || response.statusText}`, + response.status ); } @@ -294,13 +301,13 @@ class RunClient { /** * Set a tag on a run. Tags are run metadata that can be updated during a run and after a run completes. * - * @param run_id - ID of the run under which to log the tag. (required) - * @param key - Name of the tag. Maximum size depends on storage backend. All storage backends are guaranteed + * @param {string} run_id - ID of the run under which to log the tag. (required) + * @param {string} key - Name of the tag. Maximum size depends on storage backend. All storage backends are guaranteed * to support key values up to 250 bytes in size. (required) - * @param value - String value of the tag being logged. Maximum size depends on storage backend. All storage + * @param {string} value - String value of the tag being logged. Maximum size depends on storage backend. All storage * backends are guaranteed to support key values up to 5000 bytes in size. (required) - * @returns A promise that resolves when the logging is complete. - * @throws Error - If the API request fails. + * @returns {Promise} A promise that resolves when the logging is complete. + * @throws {ApiError} If the API request fails. */ async setTag(run_id: string, key: string, value: string): Promise { const { response, data } = await apiRequest(this.baseUrl, 'runs/set-tag', { @@ -309,8 +316,9 @@ class RunClient { }); if (!response.ok) { - throw new Error( - `Error setting tag: ${data.message || response.statusText}` + throw new ApiError( + `Error setting tag: ${data.message || response.statusText}`, + response.status ); } @@ -320,10 +328,10 @@ class RunClient { /** * Delete a tag on a run. Tags are run metadata that can be updated during a run and after a run completes. * - * @param run_id - ID of the run that the tag was logged under. (required) - * @param key - Name of the tag. Maximum size is 255 bytes. (required) - * @returns A promise that resolves when the deletion is complete. - * @throws Error - If the API request fails. + * @param {string} run_id - ID of the run that the tag was logged under. (required) + * @param {string} key - Name of the tag. Maximum size is 255 bytes. (required) + * @returns {Promise} A promise that resolves when the deletion is complete. + * @throws {ApiError} If the API request fails. */ async deleteTag(run_id: string, key: string): Promise { const { response, data } = await apiRequest( @@ -336,8 +344,9 @@ class RunClient { ); if (!response.ok) { - throw new Error( - `Error deleting tag: ${data.message || response.statusText}` + throw new ApiError( + `Error deleting tag: ${data.message || response.statusText}`, + response.status ); } @@ -349,11 +358,11 @@ class RunClient { * hyperparameters used for ML model training and constant dates and values used in an ETL pipeline. * A param can be logged only once for a run. * - * @param run_id - ID of the run under which to log the param. (required)) - * @param key - Name of the param. Maximum size is 255 bytes. (required) - * @param value - String value of the param being logged. Maximum size is 6000 bytes. (required) - * @returns A promise that resolves when the logging is complete. - * @throws Error - If the API request fails. + * @param {string} run_id - ID of the run under which to log the param. (required)) + * @param {string} key - Name of the param. Maximum size is 255 bytes. (required) + * @param {string} value - String value of the param being logged. Maximum size is 6000 bytes. (required) + * @returns {Promise} A promise that resolves when the logging is complete. + * @throws {ApiError} If the API request fails. */ async logParam(run_id: string, key: string, value: string): Promise { const { response, data } = await apiRequest( @@ -366,8 +375,9 @@ class RunClient { ); if (!response.ok) { - throw new Error( - `Error logging param: ${data.message || response.statusText}` + throw new ApiError( + `Error logging param: ${data.message || response.statusText}`, + response.status ); } @@ -377,22 +387,22 @@ class RunClient { /** * Get a list of all values for the specified metric for a given run. * - * @param run_id - ID of the run from which to fetch metric values. (required) - * @param metric_key - Name of the metric. (required) - * @param page_token - Token indicating the page of metric history to fetch. - * @param max_results - Maximum number of logged instances of a metric for a run to return per call. + * @param {string} run_id - ID of the run from which to fetch metric values. (required) + * @param {string} metric_key - Name of the metric. (required) + * @param {string} page_token - Token indicating the page of metric history to fetch. + * @param {number} max_results - Maximum number of logged instances of a metric for a run to return per call. * Backend servers may restrict the value of max_results depending on performance requirements. Requests that * do not specify this value will behave as non-paginated queries where all metric history values for a given * metric within a run are returned in a single response. - * @returns A promise that resolves with the values for the specified metric. - * @throws Error - If the API request fails. + * @returns {Promise} A promise that resolves with the values for the specified metric. + * @throws {ApiError} If the API request fails. */ async getMetricHistory( run_id: string, metric_key: string, page_token?: string, max_results?: number - ): Promise { + ): Promise { const params: Record = { run_id, metric_key }; if (page_token !== undefined) params.page_token = page_token; @@ -408,8 +418,9 @@ class RunClient { ); if (!response.ok) { - throw new Error( - `Error fetching metric history: ${data.message || response.statusText}` + throw new ApiError( + `Error fetching metric history: ${data.message || response.statusText}`, + response.status ); } @@ -419,35 +430,35 @@ class RunClient { /** * Search for runs that satisfy expressions. Search expressions can use Metric and Param keys. * - * @param experiment_ids - List of experiment IDs to search over. - * @param filter - A filter expression over params, metrics, and tags, that allows returning a subset of runs. + * @param {Array} [experiment_ids] - List of experiment IDs to search over. + * @param {string} filter - A filter expression over params, metrics, and tags, that allows returning a subset of runs. * The syntax is a subset of SQL that supports ANDing together binary operations between a param, metric, or * tag and a constant. * Example: metrics.rmse < 1 and params.model_class = 'LogisticRegression' * You can select columns with special characters (hyphen, space, period, etc.) by using double quotes: * metrics."model class" = 'LinearRegression' and tags."user-name" = 'Tomas' * Supported operators are =, !=, >, >=, <, and <=. - * @param {ViewType} run_view_type - Whether to display only active, only deleted, or all runs. Defaults to active runs. - * @param max_results - Maximum number of runs desired. If unspecified, defaults to 1000. All servers are + * @param {string} run_view_type - Whether to display only active, only deleted, or all runs. Defaults to active runs. + * @param {number} max_results - Maximum number of runs desired. If unspecified, defaults to 1000. All servers are * guaranteed to support a max_results theshold of at least 50,000 but may support more. Callers of this endpoint are * encouraged to pass max_results explicitly and leverage page_token to iterate through experiments. - * @param order_by - List of columns to be ordered by, including attributes, params, metrics, and tags with an optional + * @param {Array} [order_by] - List of columns to be ordered by, including attributes, params, metrics, and tags with an optional * "DESC" or "ASC" annotation, where "ASC" is the default. * Example: ["params.input DESC","metrics.alpha ASC", "metrics.rmse"] Tiebreaks are done by start_time DESC followed by * run_id for runs with the same start time (and this is the default ordering criterion if order_by is not provided). - * @param page_token - Token that can be used to retrieve the next page of run results. A missing token indicates that + * @param {string} page_token - Token that can be used to retrieve the next page of run results. A missing token indicates that * there are no additional run results to be fetched. - * @returns A promise that resovles with the runs that match the search criteria. - * @throws Error - If the API request fails. + * @returns {Promise} A promise that resovles with the runs that match the search criteria. + * @throws {ApiError} If the API request fails. */ async searchRuns( - experiment_ids: string[], + experiment_ids: Array, filter: string, run_view_type?: 'ACTIVE_ONLY' | 'DELETED_ONLY' | 'ALL', max_results?: number, - order_by?: string[], + order_by?: Array, page_token?: string - ): Promise { + ): Promise { const { response, data } = await apiRequest(this.baseUrl, 'runs/search', { method: 'POST', body: { @@ -461,10 +472,11 @@ class RunClient { }); if (!response.ok) { - throw new Error( + throw new ApiError( `Error fetching runs that satisfies expressions: ${ data.message || response.statusText - }` + }`, + response.status ); } @@ -475,18 +487,18 @@ class RunClient { * List artifacts for a run. Takes an optional artifact_path prefix which if specified, the response contains only * artifacts with the specified prefix. * - * @param run_id - ID of the run whose artifacts to list. (required) - * @param path - Filter artifacts matching this path (a relative path from the root artifact directory). - * @param page_token - Token indicating the page of artifact results to fetch. - * @returns A promise that resolves with a list artifacts for the specified run. - * @throws Error - If the API request fails. + * @param {string} run_id - ID of the run whose artifacts to list. (required) + * @param {string} path - Filter artifacts matching this path (a relative path from the root artifact directory). + * @param {string} page_token - Token indicating the page of artifact results to fetch. + * @returns {Promise} A promise that resolves with a list artifacts for the specified run. + * @throws {ApiError} If the API request fails. */ async listArtifacts( run_id: string, path?: string, page_token?: string - ): Promise { + ): Promise { const params: Record = { run_id }; if (path !== undefined) params.path = path; if (page_token !== undefined) params.page_token = page_token; @@ -501,8 +513,9 @@ class RunClient { ); if (!response.ok) { - throw new Error( - `Error listing artifacts: ${data.message || response.statusText}` + throw new ApiError( + `Error listing artifacts: ${data.message || response.statusText}`, + response.status ); } diff --git a/mlflow/tests/RunClientTest.ts b/mlflow/tests/RunClientTest.ts index d333437d..28a16456 100644 --- a/mlflow/tests/RunClientTest.ts +++ b/mlflow/tests/RunClientTest.ts @@ -6,7 +6,7 @@ async function createExperiment( name: string ): Promise { const { response, data } = await apiRequest( - client.getBaseUrl(), + (client as any).baseUrl, 'experiments/create', { method: 'POST', @@ -36,7 +36,7 @@ async function testRunClient(): Promise { try { // createRun console.log('Creating experiment...'); - const experiment_id = await createExperiment(client, 'Experiment 5'); + const experiment_id = await createExperiment(client, 'Experiment 8'); console.log('Created experiment ID: ', experiment_id); console.log('Creating run...'); From 92122b07b6cb8856427d61d35bfbb17450fae025 Mon Sep 17 00:00:00 2001 From: Stephany Ho Date: Wed, 2 Oct 2024 15:23:54 -0400 Subject: [PATCH 100/357] Refactor RunManager to ts and create test file --- mlflow/src/workflows/RunManager.ts | 264 +++++++++++++++++++++++++++++ mlflow/tests/RunClientTest.ts | 16 +- mlflow/tests/RunManagerTestFile.ts | 191 +++++++++++++++++++++ 3 files changed, 459 insertions(+), 12 deletions(-) create mode 100644 mlflow/src/workflows/RunManager.ts create mode 100644 mlflow/tests/RunManagerTestFile.ts diff --git a/mlflow/src/workflows/RunManager.ts b/mlflow/src/workflows/RunManager.ts new file mode 100644 index 00000000..18a8877a --- /dev/null +++ b/mlflow/src/workflows/RunManager.ts @@ -0,0 +1,264 @@ +import RunClient from '../tracking/RunClient'; +import ModelVersionClient from '../model-registry/ModelVersionClient'; + +interface Run { + info: { + run_id: string; + run_name: string; + experiment_id: string; + status: string; + start_time: number; + end_time: number; + artifact_uri: string; + lifecycle_stage: string; + }; + data: { + metrics: Array<{ key: string; value: number }>; + params: Array<{ key: string; value: number }>; + tags: Array<{ key: string; value: number }>; + }; + inputs: Array<{ + tags?: Array<{ key: string; value: string }>; + dataset: { + name: string; + digest: string; + source_type: string; + source: string; + schema?: string; + profile?: string; + }; + }>; +} + +class RunManager { + private runClient: RunClient; + private modelVersion: ModelVersionClient; + + constructor(trackingUri: string) { + this.runClient = new RunClient(trackingUri); + this.modelVersion = new ModelVersionClient(trackingUri); + } + + /** + * Delete runs that do not meet certain criteria and return deleted runs. + * Dry run is set to true by default. To delete, set dry run to false. + * + * @param {Array} [experimentIds] - The IDs of the associated experiments. (required) + * @param {string} query_string - SQL-like query string to filter runs to keep. (required) + * @param {string} metric_key - The metric key for comparison. (required) + * @param {boolean} [dryRun=true] - If true, only simulate the deletion. Defaults to true. (optional) + * @returns {Promise} - An object of deleted runs. + */ + async cleanupRuns( + experimentIds: Array, + query_string: string, + metric_key: string, + dryRun = true + ): Promise { + const deletedRuns = []; + const keepRunIds = new Set(); + let pageToken = null; + const maxResults = 1000; + + try { + do { + // get all runs + const searchResult = await this.runClient.searchRuns( + experimentIds, + '', + undefined, // run_view_type + maxResults, + ['start_time DESC'], + pageToken + ); + + // get runs that match the keep crteria + const keepRunsResult = await this.runClient.searchRuns( + experimentIds, + query_string, + undefined, // run_view_type + maxResults, + ['start_time DESC'], + pageToken + ); + + // Add runs from keepRunsResult to keepResult + keepRunsResult.runs.forEach((run: Run) => + keepRunIds.add(run.info.run_id) + ); + + // Add runs without the specified metric key to keepRunIds + for (const run of searchResult.runs) { + if (Array.isArray(run.data.metrics)) { + const hasMetricKey = run.data.metrics.some( + (metric: { key: string }) => metric.key === metric_key + ); + if (!hasMetricKey) { + keepRunIds.add(run.info.run_id); + } + } else { + // If run.data.metrics is not an array (e.g., undefined), keep the run + keepRunIds.add(run.info.run_id); + } + } + + // Delete runs that are not in keepRunIds + for (const run of searchResult.runs) { + if (!keepRunIds.has(run.info.run_id)) { + if (!dryRun) { + await this.runClient.deleteRun(run.info.run_id); + } + deletedRuns.push(run); + } + } + + pageToken = searchResult.page_token; + } while (pageToken); + } catch (error) { + console.error('Error during run cleanup: ', error); + throw new Error('Failed to cleanup runs.'); + } + return { deletedRuns, total: deletedRuns.length, dryRun }; + } + + /** + * Copy run from one experiment to another without artifactss and models. + * Artifacts and models detail tagged in new run as reference. + * + * @param {string} runId - The ID of the run to be copied. (required) + * @param {string} targetExperimentId - The ID of the target experiment. (required) + * @param {string} runName - The name of the new run in target experiment. (optional) + * @returns {Promise} - An object detail of the copied run. + */ + async copyRun( + runId: string, + targetExperimentId: string, + runName = null + ): Promise { + try { + // get original run + const originalRun = await this.runClient.getRun(runId); + + // create a new run in the target experiment + const newRun = await this.runClient.createRun( + targetExperimentId, + undefined, + originalRun.info.start_time + ); + + const newRunId = newRun.info.run_id; + + const endTime = originalRun.info.end_time || undefined; + + // copy run information + await this.runClient.updateRun( + newRunId, + originalRun.info.status, + endTime + ); + if (originalRun.info.lifecycle_stage !== 'active') { + await this.runClient.setTag( + newRunId, + 'mlflow.lifecycleStage', + originalRun.info.lifecycle_stage + ); + } + + // copy parameters + if (originalRun.data.params) { + for (const param of originalRun.data.params) { + await this.runClient.logParam(newRunId, param.key, param.value); + } + } + + // copy metrics + if (originalRun.data.metrics) { + for (const metric of originalRun.data.metrics) { + await this.runClient.logMetric(newRunId, metric.key, metric.value); + } + } + + // copy tags + if (originalRun.data.tags) { + for (const tag of originalRun.data.tags) { + await this.runClient.setTag(newRunId, tag.key, tag.value); + } + } + + // copy inputs + if ( + originalRun.inputs && + originalRun.inputs.dataset_inputs && + originalRun.inputs.dataset_inputs.length > 0 + ) { + // Log each dataset input separately + for (const datasetInput of originalRun.inputs.dataset_inputs) { + await this.runClient.logInputs(newRunId, [datasetInput]); + } + } + + // update the new run name + if (runName) { + await this.runClient.setTag(newRunId, 'mlflow.runName', runName); + } + + // handle models (reference only) + const modelVersions = await this.modelVersion.searchModelVersions( + `run_id = '${runId}'` + ); + if (modelVersions && modelVersions.length > 0) { + for (const model of modelVersions) { + await this.runClient.setTag( + newRunId, + `original_model_${model.name}`, + JSON.stringify({ + name: model.name, + version: model.version, + current_stage: model.current_stage, + source: model.source, + }) + ); + } + await this.runClient.setTag( + newRunId, + 'mlflow.note.models', + 'Models not copied -see original run' + ); + } + + // set description for the new run + const description = + `This run was copied from experiment ${originalRun.info.experiment_id}, original run ID: ${runId}. ` + + `Original artifact URI: ${originalRun.info.artifact_uri}.`; + + await this.runClient.setTag(newRunId, 'mlflow.note.content', description); + + // set additional tags for the new run + await this.runClient.setTag(newRunId, 'mlflow.source.run_id', runId); + + await this.runClient.setTag( + newRunId, + 'mlflow.source.experiment_id', + originalRun.info.experiment_id + ); + + await this.runClient.setTag( + newRunId, + 'mlflow.note.artifacts', + 'Artifacts not copied - reference original run' + ); + + // return copy run details + return { + originalRunId: runId, + newRunId: newRunId, + targetExperimentId: targetExperimentId, + }; + } catch (error) { + console.error('Error copying run: ', error); + throw new Error('Failed to copy run.'); + } + } +} + +export default RunManager; diff --git a/mlflow/tests/RunClientTest.ts b/mlflow/tests/RunClientTest.ts index 28a16456..93483caa 100644 --- a/mlflow/tests/RunClientTest.ts +++ b/mlflow/tests/RunClientTest.ts @@ -14,13 +14,6 @@ async function createExperiment( } ); - console.log('Response status:', response.status); - console.log( - 'Response headers:', - Object.fromEntries(response.headers.entries()) - ); - console.log('Response body:', data); - if (!response.ok) { throw new Error( `Error creating experiment: ${data.message || response.statusText}` @@ -40,12 +33,11 @@ async function testRunClient(): Promise { console.log('Created experiment ID: ', experiment_id); console.log('Creating run...'); - // const run = await client.createRun(experiment_id); const run = await client.createRun(experiment_id); console.log('Created run: ', run); // deleteRun - const runId = (run as any).info.run_id; + const runId = run.info.run_id; console.log(`Deleting run ID: ${runId}...`); await client.deleteRun(runId); console.log('Deleted run: ', runId); @@ -79,9 +71,9 @@ async function testRunClient(): Promise { console.log('Creating another run...'); const run2 = await client.createRun(experiment_id); console.log('Created run2: ', run2); - const run2Id = (run2 as any).info.run_id; + const run2Id = run2.info.run_id; - console.log(`Loggning batch for run ID: ${run2Id}...`); + console.log(`Logging batch for run ID: ${run2Id}...`); await client.logBatch( run2Id, [ @@ -151,7 +143,7 @@ async function testRunClient(): Promise { console.log('Creating another run...'); const run3 = await client.createRun(experiment_id); console.log('Created run3: ', run3); - const run3Id = (run3 as any).info.run_id; + const run3Id = run3.info.run_id; console.log(`Setting tag for run ID ${run3Id}...`); await client.setTag(run3Id, 'accuracy', '0.99'); diff --git a/mlflow/tests/RunManagerTestFile.ts b/mlflow/tests/RunManagerTestFile.ts new file mode 100644 index 00000000..ea6bf494 --- /dev/null +++ b/mlflow/tests/RunManagerTestFile.ts @@ -0,0 +1,191 @@ +import { apiRequest } from '../src/utils/apiRequest'; +import RunClient from '../src/tracking/RunClient'; +import RunManager from '../src/workflows/RunManager'; + +// helper functions +async function createExperiment( + myRunClient: RunClient, + name: string +): Promise { + const { response, data } = await apiRequest( + (myRunClient as any).baseUrl, + 'experiments/create', + { + method: 'POST', + body: { name }, + } + ); + + if (!response.ok) { + throw new Error( + `Error creating experiment: ${data.message || response.statusText}` + ); + } + + return data.experiment_id; +} + +// test code for cleanupRuns +async function testCleanupRuns(): Promise { + const myRunClient = new RunClient('http://127.0.0.1:5000'); + const myRunManager = new RunManager('http://127.0.0.1:5000'); + + try { + // create 2 experiments + console.log('Creating experiment Test Cleanup Run 1...'); + const experiment_id1 = await createExperiment( + myRunClient, + 'Test Cleanup Run 1' + ); + + console.log('Creating experiment Test Cleanup Run 2...'); + const experiment_id2 = await createExperiment( + myRunClient, + 'Test Cleanup Run 2' + ); + + // create two runs for each experiment + console.log('Creating runs...'); + const run1 = await myRunClient.createRun(experiment_id1); + const run2 = await myRunClient.createRun(experiment_id1); + console.log('Created runs for Test Cleanup Run 3'); + const run3 = await myRunClient.createRun(experiment_id2); + const run4 = await myRunClient.createRun(experiment_id2); + console.log('Created runs for Test Cleanup Run 4'); + + // log metrics + const run1_id = run1.info.run_id; + const run2_id = run2.info.run_id; + const run3_id = run3.info.run_id; + const run4_id = run4.info.run_id; + + console.log(`Logging metric for run ID ${run1_id} and ${run2_id}`); + await myRunClient.logMetric(run1_id, 'accuracy', 0.85); + await myRunClient.logMetric(run2_id, 'accuracy', 0.96); + + console.log(`Logging metric for run ID ${run3_id} and ${run4_id}`); + await myRunClient.logMetric(run3_id, 'accuracy', 0.93); + await myRunClient.logMetric(run4_id, 'accuracy', 0.99); + + // use cleanupRuns to sort runs to keep + console.log('Cleaning up runs...'); + const deletedRuns = await myRunManager.cleanupRuns( + [experiment_id1, experiment_id2], + 'metric.accuracy > 0.95', + 'accuracy' + ); + + console.log('Details of runs being filtered out: ', deletedRuns); + } catch (error) { + console.error('Error: ', error.message); + } +} + +// test code for copyRun + +async function testCopyRun(): Promise { + const myRunClient = new RunClient('http://127.0.0.1:5000'); + const myRunManager = new RunManager('http://127.0.0.1:5000'); + + try { + console.log('Testing copy run...'); + + // create a new experiment + console.log('Creating a new experiment and log batch for the new run...'); + const experiment_id1 = await createExperiment( + myRunClient, + 'Test Copy Run 1' + ); + + // create a new run in the newly created experiment + console.log('Creating run...'); + const run = await myRunClient.createRun(experiment_id1); + console.log('Created run: ', run); + + // log batch for that run ID + const runId = run.info.run_id; + console.log('Logging batch for run ID: ', runId); + await myRunClient.logBatch( + runId, + [ + { key: 'accuracy', value: 0.83, timestamp: 1694000700000 }, + { key: 'loss', value: 0.18, timestamp: 1694000700000 }, + ], + [ + { key: 'learning_rate', value: '0.0001' }, + { key: 'batch_size', value: '256' }, + ], + [ + { key: 'model_type', value: 'GradientBoosting' }, + { key: 'data_version', value: 'v1.7' }, + ] + ); + console.log('Logged batch'); + + // log inputs for that run ID + console.log('Logging inputs for run ID: ', runId); + + const datasets = [ + { + tags: [ + { key: 'version', value: '1.0' }, + { key: 'environment', value: 'production' }, + ], + dataset: { + name: 'test_dataset', + digest: 'abc123', + source_type: 'local', + source: '/path/to/data.csv', + }, + }, + ]; + + await myRunClient.logInputs(runId, datasets); + console.log('Logged inputs'); + + // log model for that run ID + console.log('Logging model for run ID: ', runId); + + const model = { + artifact_path: 'pytorch_dnn', + flavors: { + python_function: { + env: 'conda.yaml', + loader_module: 'mlflow.pytorch', + model_path: 'model.pth', + python_version: '3.8.10', + }, + pytorch: { + model_data: 'model.pth', + pytorch_version: '1.9.0', + code: 'model-code', + }, + }, + mlflow_version: '1.20.2', + model_uuid: '123e4567-e89b-12d3-a456-426614174001', + utc_time_created: '2023-09-14 10:15:00.000000', + run_id: runId, + }; + + const model_json = JSON.stringify(model); + await myRunClient.logModel(runId, model_json); + console.log('Logged model'); + + // create another experiment + console.log('Create a target experiment...'); + const experiment_id2 = await createExperiment( + myRunClient, + 'Test Copy Run 2' + ); + + // copy previous run to this newly created experiment + console.log('Copying run...'); + const copiedRun = await myRunManager.copyRun(runId, experiment_id2); + console.log('Copied run: ', copiedRun); + } catch (error) { + console.error('Error: ', error.message); + } +} + +testCopyRun(); +testCleanupRuns(); From 9d5c862f7a7bda66e6eeb5f740275ce02243cc36 Mon Sep 17 00:00:00 2001 From: Yiqun Zheng <16813562+yiqunzheng@users.noreply.github.com> Date: Wed, 2 Oct 2024 14:07:13 -0700 Subject: [PATCH 101/357] add path config in tsconfig --- mlflow/tsconfig.json | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/mlflow/tsconfig.json b/mlflow/tsconfig.json index c57ccb46..73f0e590 100644 --- a/mlflow/tsconfig.json +++ b/mlflow/tsconfig.json @@ -11,7 +11,10 @@ "moduleResolution": "node", "baseUrl": "./src", "paths": { - "*": ["*"] + "@model-registry/*": ["model-registry/*"], + "@tracking/*": ["tracking/*"], + "@utils/*": ["utils/*"], + "@workflows/*": ["workflows/*"] }, "esModuleInterop": true, "resolveJsonModule": true, From c1b2e835313fbe75d44a69b2fa7be4f33bf028dc Mon Sep 17 00:00:00 2001 From: Yiqun Zheng <16813562+yiqunzheng@users.noreply.github.com> Date: Wed, 2 Oct 2024 14:19:15 -0700 Subject: [PATCH 102/357] change import path using path aliases --- mlflow/src/model-registry/ModelRegistryClient.ts | 4 ++-- mlflow/tests/ModelRegistryClientTest.ts | 4 ++-- mlflow/tsconfig.json | 12 +++++++----- 3 files changed, 11 insertions(+), 9 deletions(-) diff --git a/mlflow/src/model-registry/ModelRegistryClient.ts b/mlflow/src/model-registry/ModelRegistryClient.ts index 5908538d..26c58809 100644 --- a/mlflow/src/model-registry/ModelRegistryClient.ts +++ b/mlflow/src/model-registry/ModelRegistryClient.ts @@ -1,5 +1,5 @@ -import { ApiError } from '../utils/apiError'; -import { apiRequest } from '../utils/apiRequest'; +import { ApiError } from '@utils/apiError'; +import { apiRequest } from '@utils/apiRequest'; class ModelRegistryClient { private baseUrl: string; diff --git a/mlflow/tests/ModelRegistryClientTest.ts b/mlflow/tests/ModelRegistryClientTest.ts index 57732fa2..205ee650 100644 --- a/mlflow/tests/ModelRegistryClientTest.ts +++ b/mlflow/tests/ModelRegistryClientTest.ts @@ -1,5 +1,5 @@ -import { apiRequest } from '../src/utils/apiRequest'; -import ModelRegistryClient from '../src/model-registry/ModelRegistryClient'; +import { apiRequest } from '@utils/apiRequest'; +import ModelRegistryClient from '@model-registry/ModelRegistryClient'; async function createRun( client: ModelRegistryClient, diff --git a/mlflow/tsconfig.json b/mlflow/tsconfig.json index 73f0e590..da733471 100644 --- a/mlflow/tsconfig.json +++ b/mlflow/tsconfig.json @@ -9,12 +9,14 @@ // Module Resolution Options "moduleResolution": "node", - "baseUrl": "./src", + "baseUrl": ".", "paths": { - "@model-registry/*": ["model-registry/*"], - "@tracking/*": ["tracking/*"], - "@utils/*": ["utils/*"], - "@workflows/*": ["workflows/*"] + "@src/*": ["src/*"], + "@model-registry/*": ["src/model-registry/*"], + "@tracking/*": ["src/tracking/*"], + "@utils/*": ["src/utils/*"], + "@workflows/*": ["src/workflows/*"], + "@tests/*": ["tests/*"] }, "esModuleInterop": true, "resolveJsonModule": true, From db31caff46de2b68706126c8070a27878193c98c Mon Sep 17 00:00:00 2001 From: Yiqun Zheng <16813562+yiqunzheng@users.noreply.github.com> Date: Wed, 2 Oct 2024 14:28:55 -0700 Subject: [PATCH 103/357] add code standards --- mlflow/docs/typescript-code-standards.md | 82 ++++++++++++++++++++++++ 1 file changed, 82 insertions(+) create mode 100644 mlflow/docs/typescript-code-standards.md diff --git a/mlflow/docs/typescript-code-standards.md b/mlflow/docs/typescript-code-standards.md new file mode 100644 index 00000000..2777b52e --- /dev/null +++ b/mlflow/docs/typescript-code-standards.md @@ -0,0 +1,82 @@ +# TypeScript Code Standards + +## File Structure and Naming +- Use PascalCase for class files (e.g., `ModelRegistryClient.ts`) +- Use camelCase for utility files (e.g., `apiRequest.ts`) +- Use kebab-case for directory names (e.g., `model-registry`) + +## Imports and Exports +- Use named exports for utilities and interfaces +- Use default exports for main classes +- Group and sort imports: + 1. External libraries + 2. Internal modules + 3. Relative imports +- Within each group, sort alphabetically +- For imports from other modules, use the path aliases defined in tsconfig.json +- For imports within the same directory, use relative imports + +## Naming Conventions +- PascalCase for classes and interfaces +- camelCase for methods, variables, and functions +- UPPER_SNAKE_CASE for constants + +## Documentation +- Use JSDoc comments for classes, methods, and functions +- Include parameter descriptions, return types, and thrown exceptions +- Example: + ```typescript + /** + * Creates a new registered model. + * @param {string} name - The name of the model to register + * @param {RegisteredModelTag[]} [tags] - Optional tags for the model + * @param {string} [description] - Optional description for the model + * @returns {Promise} The created registered model object + * @throws {ApiError} If the API request fails + */ + ``` + +## Error Handling +- For simple API calls, use the ApiError class: + ```typescript + if (!response.ok) { + throw new ApiError( + `Error: ${data.message || response.statusText}`, + response.status + ); +} + ``` +- For complex functions, use try/catch blocks: + ```typescript +try { + // complex operation +} catch (error) { + if (error instanceof ApiError) { + console.error(`API Error (${error.statusCode}): ${error.message}`); + } else { + console.error('An unexpected error occurred:', error); + } +} + ``` + +## Asynchronous Code +- Use async/await for asynchronous operations + +## Type Annotations +- Use TypeScript type annotations consistently +- Create interfaces for complex object structures +- Use generics where appropriate + +## Class and Method Structure +- Utilize TypeScript features like access modifiers (public, private) +- Use method signatures with proper TypeScript types + +## Formatting +- Use 2 spaces for indentation +- Use single quotes for strings +- Add semicolons at the end of statements + +## Consistency +- Maintain consistent style and patterns throughout the codebase +- When in doubt, follow the existing patterns in the project + From 6a126526844ddcc3e018f8aaa58a04035e33e9e4 Mon Sep 17 00:00:00 2001 From: Kyler-Chiago Date: Wed, 2 Oct 2024 17:15:41 -0700 Subject: [PATCH 104/357] working without local files --- mlflow/tests/ModelVersionClientTest.ts | 33 ++++++++++++++++++++++---- 1 file changed, 29 insertions(+), 4 deletions(-) diff --git a/mlflow/tests/ModelVersionClientTest.ts b/mlflow/tests/ModelVersionClientTest.ts index b6bbdaa8..c8e58b14 100644 --- a/mlflow/tests/ModelVersionClientTest.ts +++ b/mlflow/tests/ModelVersionClientTest.ts @@ -1,16 +1,37 @@ +import { apiRequest } from '../src/utils/apiRequest'; import ModelVersionClient from '../src/model-registry/ModelVersionClient'; import ModelRegistryClient from '../src/model-registry/ModelRegistryClient'; // To test: // npx tsx tests/ModelVersionClientTest.ts +async function createRun( + client: ModelRegistryClient, + experimentId: string +): Promise { + const { response, data } = await apiRequest( + (client as any).baseUrl, + 'runs/create', + { + method: 'POST', + body: { experiment_id: experimentId }, + } + ); + + if (!response.ok) { + throw new Error( + `Error creating run: ${data.message || response.statusText}` + ); + } + + return data.run; +} + async function testModelVersionClient() { const client = new ModelVersionClient('http://localhost:5001'); const modelRegistryClient = new ModelRegistryClient('http://localhost:5001'); const timestamp = Date.now(); const modelName = `test-model-${timestamp}`; - const artifactSource = 'mlflow-artifacts:/784321942139901150/b3457c87f50440388da9d9ddabb1baaa/artifacts/iris_model'; - const run_id = 'b3457c87f50440388da9d9ddabb1baaa'; const modelVersionDescription1 = 'This is test version 1 description'; const modelVersionKey = 'version_1_key'; const modelVersionValue = 'version_1_value'; @@ -23,12 +44,16 @@ async function testModelVersionClient() { 'This is a test model' ); + console.log('\n5. Creating a run...'); + const run = await createRun(modelRegistryClient, '0'); // Using '0' as the default experiment ID + console.log('Created run:', run); + // 1. Creating a registered model version console.log('1. Creating a new registered model version...'); const createdModelVersion = await client.createModelVersion( modelName, - artifactSource, - run_id, + run.info.artifact_uri, + run.info.run_id, [{ key: 'test-tag', value: 'test-value' }], ); console.log('Created model version: ', createdModelVersion); From 926c2bc639e239b95eb74922cb9e6fbb7ca9dd95 Mon Sep 17 00:00:00 2001 From: Austin Fraser Date: Wed, 2 Oct 2024 17:16:52 -0700 Subject: [PATCH 105/357] more progress on ExperimentClient.ts --- mlflow/src/tracking/ExperimentClient.ts | 42 +++++++++++++++++-------- 1 file changed, 29 insertions(+), 13 deletions(-) diff --git a/mlflow/src/tracking/ExperimentClient.ts b/mlflow/src/tracking/ExperimentClient.ts index de4bb862..89d87468 100644 --- a/mlflow/src/tracking/ExperimentClient.ts +++ b/mlflow/src/tracking/ExperimentClient.ts @@ -1,4 +1,7 @@ +import { apiRequest } from '../utils/apiRequest'; + class ExperimentClient { + trackingUri: string; constructor(trackingUri: string) { this.trackingUri = trackingUri; } @@ -12,17 +15,30 @@ class ExperimentClient { * @param {Array<{key: string, value: string}>} tags Optional collection of tags to set on the experiment. * @returns {Promise} Returns the ID of the newly created experiment in an object. */ - async createExperiment(name: string, artifact_location?: string, tags?: string[]) { + async createExperiment( + name: string, + artifact_location?: string, + tags?: Array<{key: string, value: string}> + ): Promise { if (!name) { throw new Error('Experiment name is required'); } - const url = `${this.trackingUri}/api/2.0/mlflow/experiments/create`; - const response = await fetch(url, { - method: 'POST', - headers: { 'Content-Type': 'application/json' }, - body: JSON.stringify({ name, artifact_location, tags }), - }); + const { response, data } = await apiRequest( + this.trackingUri, + 'experiments/create', + { + method: 'POST', + body: { name, artifact_location, tags }, + } + ); + + // const url = `${this.trackingUri}/api/2.0/mlflow/experiments/create`; + // const response = await fetch(url, { + // method: 'POST', + // headers: { 'Content-Type': 'application/json' }, + // body: JSON.stringify({ name, artifact_location, tags }), + // }); if (!response.ok) { const errorBody = await response.json(); @@ -31,7 +47,7 @@ class ExperimentClient { ); } - const data = await response.json(); + // const data = await response.json(); // console.log('return from createExperiment: ', data.experiment_id); return data.experiment_id; } @@ -42,16 +58,16 @@ class ExperimentClient { * @param {string} filter A filter expression over experiment attributes and tags that allows returning a subset of experiments. The syntax is a subset of SQL. (required) * @param {int64} max_results Maximum number of experiments desired. (required) * @param {string} page_token Optional token indicating the page of experiments to fetch. - * @param {Array} order_by Optional list of columns for ordering search results. + * @param {string[]} order_by Optional list of columns for ordering search results. * @param {string} view_type Optional qualifier for type of experiments to be returned. See https://mlflow.org/docs/latest/rest-api.html#mlflowviewtype * @returns {Promise} Returns object containing an array of experiment objects matching the filter, * and optionally a next_page_token that can be used to retrieve the next page of experiments. */ async searchExperiment( - filter, - max_results, - page_token = '', - order_by = [], + filter: string, + max_results: number, + page_token?: string, + order_by?: string[], view_type = '' ) { if (!filter) { From cf223d3b47feccf153a4ca9b57fd50f8e4b10227 Mon Sep 17 00:00:00 2001 From: Kyler-Chiago Date: Wed, 2 Oct 2024 17:20:36 -0700 Subject: [PATCH 106/357] removed comments --- mlflow/tests/ModelVersionClientTest.ts | 3 --- 1 file changed, 3 deletions(-) diff --git a/mlflow/tests/ModelVersionClientTest.ts b/mlflow/tests/ModelVersionClientTest.ts index c8e58b14..00b89ddd 100644 --- a/mlflow/tests/ModelVersionClientTest.ts +++ b/mlflow/tests/ModelVersionClientTest.ts @@ -2,9 +2,6 @@ import { apiRequest } from '../src/utils/apiRequest'; import ModelVersionClient from '../src/model-registry/ModelVersionClient'; import ModelRegistryClient from '../src/model-registry/ModelRegistryClient'; -// To test: -// npx tsx tests/ModelVersionClientTest.ts - async function createRun( client: ModelRegistryClient, experimentId: string From 469cf779f51e689cc4337eef2383d652066af852 Mon Sep 17 00:00:00 2001 From: Kyler-Chiago Date: Wed, 2 Oct 2024 17:22:39 -0700 Subject: [PATCH 107/357] comments update --- .../src/model-registry/ModelVersionClient.ts | 28 +++++++++++-------- 1 file changed, 17 insertions(+), 11 deletions(-) diff --git a/mlflow/src/model-registry/ModelVersionClient.ts b/mlflow/src/model-registry/ModelVersionClient.ts index f4f8cbbf..741e8c76 100644 --- a/mlflow/src/model-registry/ModelVersionClient.ts +++ b/mlflow/src/model-registry/ModelVersionClient.ts @@ -9,7 +9,8 @@ class ModelVersionClient { } /** - * Description - Creates a new version of a model + * Creates a new version of a model + * * @param {string} modelName - the name of the registered model (required) * @param {string} source - the source path where the model artifacts are stored (required) * @param {string} run_id - the id of the run that generated this version (optional) @@ -51,7 +52,8 @@ class ModelVersionClient { } /** - * Description - Gets the specified version of the model + * Gets the specified version of the model + * * @param {string} modelName - the name of the registered model (Required) * @param {string} version - the version number of the model to fetch (Required) * @returns {Promise} - the created model version object @@ -81,7 +83,8 @@ class ModelVersionClient { } /** - * Description - updates a specific model version. + * Updates a specific model version. + * * @param {string} modelName - the name of the registered model (Required) * @param {string} version - the version number of the model to update (Required) * @param {string} description - The description of the model version (Optional) @@ -116,7 +119,8 @@ class ModelVersionClient { } /** - * Description - searches for model versions based on provided filters. + * Searches for model versions based on provided filters. + * * @param {string} filter - the filter criteria for searching model versions (Optional) * @param {number} maxResults - the maximum number of results to return (Optional) * @param {string[]} order_by - List of columns to be ordered by (Optional) @@ -168,7 +172,8 @@ class ModelVersionClient { } /** - * Description - retrieves the download uri for model version artifacts. + * Retrieves the download uri for model version artifacts. + * * @param {string} modelName - the name of the registered model (Required) * @param {string} version - the version number of the model to fetch the uri for (Required) * @returns {Promise} - the uri for downloading the model version artifacts @@ -201,8 +206,8 @@ class ModelVersionClient { } /** - * transitions a model version to a different stage. - * + * Transitions a model version to a different stage. + * * @param {string} modelName - the name of the registered model (Required) * @param {string} version - the version number of the model to transition (Required) * @param {string} stage - the stage to transition the model version to (e.g., 'staging', 'production') (Required) @@ -243,8 +248,8 @@ class ModelVersionClient { } /** - * sets a tag on a specific model version. - * + * Sets a tag on a specific model version. + * * @param {string} modelName - the name of the registered model (required) * @param {string} version - the version number of the model to tag (required) * @param {string} key - the key of the tag (required) @@ -283,7 +288,7 @@ class ModelVersionClient { } /** - * deletes a tag from a specific model version. + * Deletes a tag from a specific model version. * * @param {string} modelName - the name of the registered model (required) * @param {string} version - the version number of the model to untag (required) @@ -321,7 +326,8 @@ class ModelVersionClient { } /** - * Description - deletes a specific model version. + * Deletes a specific model version. + * * @param {string} modelName - the name of the registered model (Required) * @param {string} version - the version number of the model to delete (Required) * @returns {Promise} From eb788d13a14e3ac60389d8d7cb6de65a2ee1c2ec Mon Sep 17 00:00:00 2001 From: Yiqun Zheng <16813562+yiqunzheng@users.noreply.github.com> Date: Wed, 2 Oct 2024 17:43:07 -0700 Subject: [PATCH 108/357] fix code standards --- mlflow/docs/typescript-code-standards.md | 18 ++++++++++++------ 1 file changed, 12 insertions(+), 6 deletions(-) diff --git a/mlflow/docs/typescript-code-standards.md b/mlflow/docs/typescript-code-standards.md index 2777b52e..2e4a497e 100644 --- a/mlflow/docs/typescript-code-standards.md +++ b/mlflow/docs/typescript-code-standards.md @@ -36,28 +36,34 @@ */ ``` -## Error Handling +## Error Handling Guide + - For simple API calls, use the ApiError class: - ```typescript - if (!response.ok) { + +```typescript +if (!response.ok) { throw new ApiError( `Error: ${data.message || response.statusText}`, response.status ); } - ``` +``` + - For complex functions, use try/catch blocks: - ```typescript + +```typescript try { // complex operation } catch (error) { if (error instanceof ApiError) { console.error(`API Error (${error.statusCode}): ${error.message}`); + throw error; } else { console.error('An unexpected error occurred:', error); + throw new Error; } } - ``` +``` ## Asynchronous Code - Use async/await for asynchronous operations From 8e7d197e762f06d39d4fdcb7a0b99f11f68d2670 Mon Sep 17 00:00:00 2001 From: Austin Fraser Date: Wed, 2 Oct 2024 18:17:11 -0700 Subject: [PATCH 109/357] ExperimentClient.ts first pass --- mlflow/src/tracking/ExperimentClient.ts | 233 ++++++++++++++---------- 1 file changed, 132 insertions(+), 101 deletions(-) diff --git a/mlflow/src/tracking/ExperimentClient.ts b/mlflow/src/tracking/ExperimentClient.ts index 89d87468..ae7142a6 100644 --- a/mlflow/src/tracking/ExperimentClient.ts +++ b/mlflow/src/tracking/ExperimentClient.ts @@ -1,4 +1,5 @@ -import { apiRequest } from '../utils/apiRequest'; +import { ApiError } from '@utils/apiError'; +import { apiRequest } from '@utils/apiRequest'; class ExperimentClient { trackingUri: string; @@ -14,6 +15,7 @@ class ExperimentClient { * @param {string} artifact_location Optional location where all artifacts for the experiment are stored. If not provided, the remote server will select an appropriate default. * @param {Array<{key: string, value: string}>} tags Optional collection of tags to set on the experiment. * @returns {Promise} Returns the ID of the newly created experiment in an object. + * @throws {ApiError} If the API request fails */ async createExperiment( name: string, @@ -33,22 +35,15 @@ class ExperimentClient { } ); - // const url = `${this.trackingUri}/api/2.0/mlflow/experiments/create`; - // const response = await fetch(url, { - // method: 'POST', - // headers: { 'Content-Type': 'application/json' }, - // body: JSON.stringify({ name, artifact_location, tags }), - // }); - if (!response.ok) { - const errorBody = await response.json(); - throw new Error( - `Error creating experiment from tracking server, status: ${response.status}. ${errorBody.message}` + throw new ApiError( + `Error creating experiment from tracking server: ${ + data.message || response.statusText + }`, + response.status ); } - - // const data = await response.json(); - // console.log('return from createExperiment: ', data.experiment_id); + return data.experiment_id; } @@ -56,20 +51,21 @@ class ExperimentClient { * Search experiments. * * @param {string} filter A filter expression over experiment attributes and tags that allows returning a subset of experiments. The syntax is a subset of SQL. (required) - * @param {int64} max_results Maximum number of experiments desired. (required) + * @param {number} max_results Maximum number of experiments desired. (required) * @param {string} page_token Optional token indicating the page of experiments to fetch. * @param {string[]} order_by Optional list of columns for ordering search results. * @param {string} view_type Optional qualifier for type of experiments to be returned. See https://mlflow.org/docs/latest/rest-api.html#mlflowviewtype * @returns {Promise} Returns object containing an array of experiment objects matching the filter, * and optionally a next_page_token that can be used to retrieve the next page of experiments. + * @throws {ApiError} If the API request fails */ async searchExperiment( filter: string, max_results: number, page_token?: string, order_by?: string[], - view_type = '' - ) { + view_type?: string + ): Promise { if (!filter) { throw new Error('Filter is required'); } @@ -77,28 +73,24 @@ class ExperimentClient { throw new Error('Max results is required'); } - const url = `${this.trackingUri}/api/2.0/mlflow/experiments/search`; - const response = await fetch(url, { - method: 'POST', - headers: { 'Content-Type': 'application/json' }, - body: JSON.stringify({ - filter, - max_results, - page_token, - order_by, - view_type, - }), - }); + const { response, data } = await apiRequest( + this.trackingUri, + 'experiments/search', + { + method: 'POST', + body: { filter, max_results, page_token, order_by, view_type }, + } + ); if (!response.ok) { - const errorBody = await response.json(); - throw new Error( - `Error searching for experiment from tracking server, status: ${response.status}. ${errorBody.message}` + throw new ApiError( + `Error searching for experiment from tracking server: ${ + data.message || response.statusText + }`, + response.status ); } - const data = await response.json(); - // console.log('return from searchExperiment: ', data); return data; } @@ -107,27 +99,33 @@ class ExperimentClient { * * @param {string} experiment_id ID of the associated experiment. (required) * @returns {Promise} Returns object containing the matched experiment. + * @throws {ApiError} If the API request fails */ - async getExperiment(experiment_id) { + async getExperiment( + experiment_id: string + ): Promise { if (!experiment_id) { throw new Error('Experiment ID is required'); } - const url = `${this.trackingUri}/api/2.0/mlflow/experiments/get?experiment_id=${experiment_id}`; - const response = await fetch(url, { - method: 'GET', - headers: { 'Content-Type': 'application/json' }, - }); + const { response, data } = await apiRequest( + this.trackingUri, + 'experiments/get', + { + method: 'GET', + params: { experiment_id } + } + ); if (!response.ok) { - const errorBody = await response.json(); - throw new Error( - `Error getting experiment from tracking server, status: ${response.status}. ${errorBody.message}` + throw new ApiError( + `Error getting experiment from tracking server: ${ + data.message || response.statusText + }`, + response.status ); } - const data = await response.json(); - // console.log('return from getExperiment: ', data.experiment); return data.experiment; } @@ -139,27 +137,33 @@ class ExperimentClient { * * @param {string} experiment_name ID of the associated experiment. (required) * @returns {Promise} Returns object containing the matched experiment. + * @throws {ApiError} If the API request fails */ - async getExperimentByName(experiment_name) { + async getExperimentByName( + experiment_name: string + ): Promise { if (!experiment_name) { throw new Error('Experiment name is required'); } - const url = `${this.trackingUri}/api/2.0/mlflow/experiments/get-by-name?experiment_name=${experiment_name}`; - const response = await fetch(url, { - method: 'GET', - headers: { 'Content-Type': 'application/json' }, - }); + const { response, data } = await apiRequest( + this.trackingUri, + 'experiments/get-by-name', + { + method: 'GET', + params: { experiment_name } + } + ); if (!response.ok) { - const errorBody = await response.json(); - throw new Error( - `Error getting experiment by name from tracking server, status: ${response.status}. ${errorBody.message}` + throw new ApiError( + `Error getting experiment by name from tracking server: ${ + data.message || response.statusText + }`, + response.status ); } - const data = await response.json(); - // console.log('return from getExperimentByName: ', data.experiment); return data.experiment; } @@ -168,28 +172,34 @@ class ExperimentClient { * * @param {string} experiment_id ID of the associated experiment. (required) * @returns {void} + * @throws {ApiError} If the API request fails */ - async deleteExperiment(experiment_id) { + async deleteExperiment( + experiment_id: string + ): Promise { if (!experiment_id) { throw new Error('Experiment ID is required'); } - const url = `${this.trackingUri}/api/2.0/mlflow/experiments/delete`; - const response = await fetch(url, { - method: 'POST', - headers: { 'Content-Type': 'application/json' }, - body: JSON.stringify({ experiment_id }), - }); + const { response, data } = await apiRequest( + this.trackingUri, + 'experiments/delete', + { + method: 'POST', + body: { experiment_id }, + } + ); if (!response.ok) { - const errorBody = await response.json(); - throw new Error( - `Error deleting experiment from tracking server, status: ${response.status}. ${errorBody.message}` + throw new ApiError( + `Error deleting experiment from tracking server: ${ + data.message || response.statusText + }`, + response.status ); } console.log(`Experiment ID ${experiment_id} successfully deleted`); - // return `Experiment ID ${experiment_id} successfully deleted`; } /** @@ -197,28 +207,34 @@ class ExperimentClient { * * @param {string} experiment_id ID of the associated experiment. (required) * @returns {void} + * @throws {ApiError} If the API request fails */ - async restoreExperiment(experiment_id) { + async restoreExperiment( + experiment_id: string + ): Promise { if (!experiment_id) { throw new Error('Experiment ID is required'); } - const url = `${this.trackingUri}/api/2.0/mlflow/experiments/restore`; - const response = await fetch(url, { - method: 'POST', - headers: { 'Content-Type': 'application/json' }, - body: JSON.stringify({ experiment_id }), - }); + const { response, data } = await apiRequest( + this.trackingUri, + 'experiments/restore', + { + method: 'POST', + body: { experiment_id }, + } + ); if (!response.ok) { - const errorBody = await response.json(); - throw new Error( - `Error restoring experiment from tracking server, status: ${response.status}. ${errorBody.message}` + throw new ApiError( + `Error restoring experiment from tracking server: ${ + data.message || response.statusText + }`, + response.status ); } console.log(`Experiment ID ${experiment_id} successfully restored`); - // return `Experiment ID ${experiment_id} successfully restored`; } /** @@ -227,8 +243,12 @@ class ExperimentClient { * @param {string} experiment_id ID of the associated experiment. (required) * @param {string} new_name The experiment’s name is changed to the new name. The new name must be unique. (required) * @returns {void} + * @throws {ApiError} If the API request fails */ - async updateExperiment(experiment_id, new_name) { + async updateExperiment( + experiment_id: string, + new_name: string + ): Promise { if (!experiment_id) { throw new Error('Experiment ID is required'); } @@ -236,24 +256,27 @@ class ExperimentClient { throw new Error('New name is required'); } - const url = `${this.trackingUri}/api/2.0/mlflow/experiments/update`; - const response = await fetch(url, { - method: 'POST', - headers: { 'Content-Type': 'application/json' }, - body: JSON.stringify({ experiment_id, new_name }), - }); + const { response, data } = await apiRequest( + this.trackingUri, + 'experiments/update', + { + method: 'POST', + body: { experiment_id, new_name }, + } + ); if (!response.ok) { - const errorBody = await response.json(); - throw new Error( - `Error updating experiment from tracking server, status: ${response.status}. ${errorBody.message}` + throw new ApiError( + `Error updating experiment from tracking server: ${ + data.message || response.statusText + }`, + response.status ); } console.log( `Experiment ID ${experiment_id} successfully updated - new name is ${new_name}` ); - // return `Experiment ID ${experiment_id} successfully updated - new name is ${new_name}`; } /** @@ -263,8 +286,13 @@ class ExperimentClient { * @param {string} key Name of the tag. (required) * @param {string} value String value of the tag being logged. (required) * @returns {void} + * @throws {ApiError} If the API request fails */ - async setExperimentTag(experiment_id, key, value) { + async setExperimentTag( + experiment_id: string, + key: string, + value: string + ): Promise { if (!experiment_id) { throw new Error('Experiment ID is required'); } @@ -275,23 +303,26 @@ class ExperimentClient { throw new Error('Value is required'); } - const url = `${this.trackingUri}/api/2.0/mlflow/experiments/set-experiment-tag`; - const response = await fetch(url, { - method: 'POST', - headers: { 'Content-Type': 'application/json' }, - body: JSON.stringify({ experiment_id, key, value }), - }); + const { response, data } = await apiRequest( + this.trackingUri, + 'experiments/set-experiment-tag', + { + method: 'POST', + body: { experiment_id, key, value }, + } + ); if (!response.ok) { - const errorBody = await response.json(); - throw new Error( - `Error setting tag from tracking server, status: ${response.status}. ${errorBody.message}` + throw new ApiError( + `Error setting tag from tracking server: ${ + data.message || response.statusText + }`, + response.status ); } console.log(`Set tag to experiment ID ${experiment_id} successfully`); - // return `Set tag to experiment ID ${experiment_id} successfully`; } } -export { ExperimentClient }; +export default ExperimentClient; \ No newline at end of file From 0107a5e00a96a1003c7054c528b5e415ea15beb7 Mon Sep 17 00:00:00 2001 From: Kyler-Chiago Date: Wed, 2 Oct 2024 18:38:13 -0700 Subject: [PATCH 110/357] updated model manager to try/catch block and comments on the functions --- mlflow/src/workflows/ModelManager.ts | 423 +++++++++++++++++---------- mlflow/tests/ModelManagerTest.ts | 58 ++++ 2 files changed, 331 insertions(+), 150 deletions(-) create mode 100644 mlflow/tests/ModelManagerTest.ts diff --git a/mlflow/src/workflows/ModelManager.ts b/mlflow/src/workflows/ModelManager.ts index da93e4e3..d2aa9262 100644 --- a/mlflow/src/workflows/ModelManager.ts +++ b/mlflow/src/workflows/ModelManager.ts @@ -1,6 +1,7 @@ // import RunClient from '../tracking/RunClient'; -import ModelRegistryClient from "../model-registry/ModelRegistryClient"; -import ModelVersionClient from "../model-registry/ModelVersionClient"; +import ModelRegistryClient from '../model-registry/ModelRegistryClient'; +import ModelVersionClient from '../model-registry/ModelVersionClient'; +import { ApiError } from 'utils/apiError'; class ModelManager { private modelRegistry: ModelRegistryClient; @@ -13,30 +14,47 @@ class ModelManager { } /** - * Description - Creates a new registered model and creates the first version of that model. + * Creates a new registered model and creates the first version of that model. + * * @param {string} name - Name of the registered model. (Required) * @param {string} versionSource - URI indicating the location of the model artifacts. (Required) * @param {string} versionRun_id - MLflow run ID for correlation, if versionSource was generated * by an experiment run in MLflow tracking server. * @returns {Promise} - the updated model version object */ - async createRegisteredModelWithVersion(name: string, versionSource: string, versionRun_id: string): Promise { - await this.modelRegistry.createRegisteredModel(name); - const response = await this.modelVersion.createModelVersion( - name, - versionSource, - versionRun_id - ); - return response; + async createRegisteredModelWithVersion( + name: string, + versionSource: string, + versionRun_id: string + ): Promise { + try { + await this.modelRegistry.createRegisteredModel(name); + const response = await this.modelVersion.createModelVersion( + name, + versionSource, + versionRun_id + ); + + return response; + } catch (error) { + if (error instanceof ApiError) { + console.error(`API Error (${error.statusCode}): ${error.message}`); + throw error; + } else { + console.error('An unexpected error occurred:', error); + throw new Error(); + } + } } /** - * Description - Updates a registered model's description and tag. - * @param name - Name of the registered model. (Required) - * @param tagKey - Name of the tag. (Required) - * @param tagValue - String value of the tag being logged. (Required) - * @param description - Description of the registered model. - * @returns - the updated registered model object + * Updates a registered model's description and tag. + * + * @param {string} name - Name of the registered model. (Required) + * @param {string} tagKey - Name of the tag. (Required) + * @param {string} tagValue - String value of the tag being logged. (Required) + * @param {string} description - Description of the registered model. + * @returns {Promise} - the updated registered model object */ async updateRegisteredModelDescriptionAndTag( name: string, @@ -44,142 +62,234 @@ class ModelManager { tagValue: string, description: string ): Promise { - await this.modelRegistry.setRegisteredModelTag(name, tagKey, tagValue); - const response = await this.modelRegistry.updateRegisteredModel( - name, - description - ); - return response; + try { + await this.modelRegistry.setRegisteredModelTag(name, tagKey, tagValue); + const response = await this.modelRegistry.updateRegisteredModel( + name, + description + ); + return response; + } catch (error) { + if (error instanceof ApiError) { + console.error(`API Error (${error.statusCode}): ${error.message}`); + throw error; + } else { + console.error('An unexpected error occurred:', error); + throw new Error(); + } + } } /** - * Description - Updates the latest version of the specified registered model's description. + * Updates the latest version of the specified registered model's description. * And adds a new alias, and tag key/value for that latest version. - * @param name - Name of the registered model. (Required) - * @param alias - Name of the alias. (Required) - * @param description - The description for the model version. (Required) - * @param key - Name of the tag. (Required) - * @param value - Name of the value of the tag being logged. (Required) - * @returns - the updated model version object + * + * @param {string} name - Name of the registered model. (Required) + * @param {string} alias - Name of the alias. (Required) + * @param {string} description - The description for the model version. (Required) + * @param {string} key - Name of the tag. (Required) + * @param {string} value - Name of the value of the tag being logged. (Required) + * @returns {Promise} - the updated model version object */ - async updateAllLatestModelVersion(name: string, alias: string, description: string, key: string, value: string): Promise { - const data = await this.modelRegistry.getLatestModelVersions(name); - if (!data) { - throw new Error('Model has no version to update.'); - } else { - const [{ version }] = data; - await this.modelRegistry.setRegisteredModelAlias(name, alias, version); - await this.modelVersion.setModelVersionTag( - name, - version, - key, - value - ); - const response = await this.modelVersion.updateModelVersion( - name, - version, - description - ); - return response; + async updateAllLatestModelVersion( + name: string, + alias: string, + description: string, + key: string, + value: string + ): Promise { + try { + // complex operation + const data = await this.modelRegistry.getLatestModelVersions(name); + if (!data) { + throw new Error('Model has no version to update.'); + } else { + const [{ version }] = data; + await this.modelRegistry.setRegisteredModelAlias(name, alias, version); + await this.modelVersion.setModelVersionTag(name, version, key, value); + const response = await this.modelVersion.updateModelVersion( + name, + version, + description + ); + return response; + } + } catch (error) { + if (error instanceof ApiError) { + console.error(`API Error (${error.statusCode}): ${error.message}`); + throw error; + } else { + console.error('An unexpected error occurred:', error); + throw new Error(); + } } } /** - * Description - Adds a new tag key/value for the latest version of the specified registered model. - * @param name - Name of the registered model. (Required) - * @param key - Name of the tag. (Required) - * @param value - Name of the value of the tag being logged. (Required) - * @returns - a promise that resolves when the model version is deleted + * Adds a new tag key/value for the latest version of the specified registered model. + * + * @param {string} name - Name of the registered model. (Required) + * @param {string} key - Name of the tag. (Required) + * @param {string} value - Name of the value of the tag being logged. (Required) + * @returns {Promise} - a promise that resolves when the model version is deleted */ - async setLatestModelVersionTag(name: string, key: string, value: string): Promise { - const data = await this.modelRegistry.getLatestModelVersions(name); - if (!data) { - throw new Error('Model has no version to set tag for.'); - } else { - const [{ version }] = data; - this.modelVersion.setModelVersionTag(name, version, key, value); - return; + async setLatestModelVersionTag( + name: string, + key: string, + value: string + ): Promise { + try { + // complex operation + const data = await this.modelRegistry.getLatestModelVersions(name); + if (!data) { + throw new Error('Model has no version to set tag for.'); + } else { + const [{ version }] = data; + this.modelVersion.setModelVersionTag(name, version, key, value); + return; + } + } catch (error) { + if (error instanceof ApiError) { + console.error(`API Error (${error.statusCode}): ${error.message}`); + throw error; + } else { + console.error('An unexpected error occurred:', error); + throw new Error(); + } } } /** - * Description - Adds an alias for the latest version of the specified registered model. - * @param name - Name of the registered model. (Required) - * @param alias - Name of the alias. (Required) - * @returns - a promise that resolves when the model version is deleted + * Adds an alias for the latest version of the specified registered model. + * + * @param {string} name - Name of the registered model. (Required) + * @param {string} alias - Name of the alias. (Required) + * @returns {Promise} - a promise that resolves when the model version is deleted */ async setLatestModelVersionAlias(name: string, alias: string): Promise { - const data = await this.modelRegistry.getLatestModelVersions(name); - if (!data) { - throw new Error('Model has no version to set alias for.'); - } else { - const [{ version }] = data; - this.modelRegistry.setRegisteredModelAlias(name, alias, version); - return; + try { + // complex operation + const data = await this.modelRegistry.getLatestModelVersions(name); + if (!data) { + throw new Error('Model has no version to set alias for.'); + } else { + const [{ version }] = data; + this.modelRegistry.setRegisteredModelAlias(name, alias, version); + return; + } + } catch (error) { + if (error instanceof ApiError) { + console.error(`API Error (${error.statusCode}): ${error.message}`); + throw error; + } else { + console.error('An unexpected error occurred:', error); + throw new Error(); + } + } + } + + /** + * Updates the description of the latest version of a registered model. + * + * @param {string} name - Name of the registered model. (Required) + * @param {string} description - The description for the model version. (Required) + * @returns {Promise} - the updated model version object + */ + async updateLatestModelVersion( + name: string, + description: string + ): Promise { + try { + // complex operation + const data = await this.modelRegistry.getLatestModelVersions(name); + if (!data) { + throw new Error('Model has no version to set description for.'); + } else { + const [{ version }] = data; + const response = await this.modelVersion.updateModelVersion( + name, + version, + description + ); + return response; + } + } catch (error) { + if (error instanceof ApiError) { + console.error(`API Error (${error.statusCode}): ${error.message}`); + throw error; + } else { + console.error('An unexpected error occurred:', error); + throw new Error(); + } } } /** - * Description - Updates the description of the latest version of a registered model. - * @param name - Name of the registered model. (Required) - * @param description - The description for the model version. (Required) - * @returns - the updated model version object + * Updates the specified version of the specified registered model's description. + * And adds a new alias, and tag key/value for that specified version. + * + * @param {string} name - Name of the registered model. (Required) + * @param {string} version - Model version number. (Required) + * @param {string} alias - Name of the alias. (Required) + * @param {string} description - The description for the model version. (Required) + * @param {string} key key - Name of the tag. (Required) + * @param {string} value - Name of the value of the tag being logged. (Required) + * @returns {Promise} - the updated model version object */ - async updateLatestModelVersion(name: string, description: string): Promise { - const data = await this.modelRegistry.getLatestModelVersions(name); - if (!data) { - throw new Error('Model has no version to set description for.'); - } else { - const [{ version }] = data; + async updateAllModelVersion( + name: string, + version: string, + alias: string, + description: string, + key: string, + value: string + ): Promise { + try { + // complex operation + await this.modelRegistry.setRegisteredModelAlias(name, alias, version); + await this.modelVersion.setModelVersionTag(name, version, key, value); const response = await this.modelVersion.updateModelVersion( name, version, description ); return response; + } catch (error) { + if (error instanceof ApiError) { + console.error(`API Error (${error.statusCode}): ${error.message}`); + throw error; + } else { + console.error('An unexpected error occurred:', error); + throw new Error(); + } } } /** - * Description - Updates the specified version of the specified registered model's description. - * And adds a new alias, and tag key/value for that specified version. - * @param name - Name of the registered model. (Required) - * @param version - Model version number. (Required) - * @param alias - Name of the alias. (Required) - * @param description - The description for the model version. (Required) - * @param key key - Name of the tag. (Required) - * @param value - Name of the value of the tag being logged. (Required) - * @returns - the updated model version object - */ - async updateAllModelVersion(name: string, version: string, alias: string, description: string, key: string, value: string): Promise { - await this.modelRegistry.setRegisteredModelAlias(name, alias, version); - await this.modelVersion.setModelVersionTag( - name, - version, - key, - value - ); - const response = await this.modelVersion.updateModelVersion( - name, - version, - description - ); - return response; - } - - /** - * Description - Deletes the latest version of the specified registered model. - * @param name - the model name + * Deletes the latest version of the specified registered model. + * + * @param {string} name - the model name * @returns - a promise that resolves when the model version is deleted */ async deleteLatestModelVersion(name: string): Promise { - const data = await this.modelRegistry.getLatestModelVersions(name); - if (!data) { - throw new Error('Model has no version to delete.'); - } else { - const [{ version }] = data; - this.modelVersion.deleteModelVersion(name, version); - return; + try { + // complex operation + const data = await this.modelRegistry.getLatestModelVersions(name); + if (!data) { + throw new Error('Model has no version to delete.'); + } else { + const [{ version }] = data; + this.modelVersion.deleteModelVersion(name, version); + return; + } + } catch (error) { + if (error instanceof ApiError) { + console.error(`API Error (${error.statusCode}): ${error.message}`); + throw error; + } else { + console.error('An unexpected error occurred:', error); + throw new Error(); + } } } @@ -187,10 +297,11 @@ class ModelManager { // Probably make it so it can also make a new model version if there's already a version of that modelName /** - * Description - Looks through the runs with the given experiment id and through their metrics + * Looks through the runs with the given experiment id and through their metrics * looking for the specified metric that has the highest or lowest value (can be specified). * Then it creates a new model with the specified model name and creates a version of that * model from the run with the best metric. + * * @param {string[]} experiment_ids - An array containing an experiment id. (Required) * @param {string} filterMetric - The name of the metric that we're filtering by. (Required) * @param {string} metricMinOrMax - A string specifying if we want the minimum or maximum @@ -202,40 +313,52 @@ class ModelManager { // filterMetric: string, // metricMinOrMax: string, // modelName: string - // ) { - // const { runs } = await this.runClient.searchRuns( - // experiment_ids, - // `metrics.${filterMetric} != -99999` - // ); - // let num; - // if (metricMinOrMax === 'min') { - // num = Infinity; - // } else if (metricMinOrMax === 'max') { - // num = -Infinity; - // } - // let bestRun; - // for (let i = 0; i < runs.length; i++) { - // for (let x = 0; x < runs[i].data.metrics.length; x++) { - // if (runs[i].data.metrics[x].key === `${filterMetric}`) { - // if (metricMinOrMax === 'min' && num > runs[i].data.metrics[x].value) { - // num = runs[i].data.metrics[x].value; - // bestRun = runs[i]; - // } else if ( - // metricMinOrMax === 'max' && - // num < runs[i].data.metrics[x].value - // ) { - // num = runs[i].data.metrics[x].value; - // bestRun = runs[i]; + // ): Promise { + // try { + // // complex operation + // const { runs } = await this.runClient.searchRuns( + // experiment_ids, + // `metrics.${filterMetric} != -99999` + // ); + // let num; + // if (metricMinOrMax === 'min') { + // num = Infinity; + // } else if (metricMinOrMax === 'max') { + // num = -Infinity; + // } + // let bestRun; + // for (let i = 0; i < runs.length; i++) { + // for (let x = 0; x < runs[i].data.metrics.length; x++) { + // if (runs[i].data.metrics[x].key === `${filterMetric}`) { + // if ( + // metricMinOrMax === 'min' && + // num > runs[i].data.metrics[x].value + // ) { + // num = runs[i].data.metrics[x].value; + // bestRun = runs[i]; + // } else if ( + // metricMinOrMax === 'max' && + // num < runs[i].data.metrics[x].value + // ) { + // num = runs[i].data.metrics[x].value; + // bestRun = runs[i]; + // } // } // } // } + // await this.modelRegistry.createRegisteredModel(modelName); + // await this.modelVersion.createModelVersion( + // modelName, + // bestRun.info.artifact_uri, + // bestRun.info.run_id + // ); + // } catch (error) { + // if (error instanceof ApiError) { + // console.error(`API Error (${error.statusCode}): ${error.message}`); + // } else { + // console.error('An unexpected error occurred:', error); + // } // } - // await this.modelRegistry.createRegisteredModel(modelName); - // await this.modelVersion.createModelVersion( - // modelName, - // bestRun.info.artifact_uri, - // bestRun.info.run_id - // ); // } } diff --git a/mlflow/tests/ModelManagerTest.ts b/mlflow/tests/ModelManagerTest.ts new file mode 100644 index 00000000..7de0324f --- /dev/null +++ b/mlflow/tests/ModelManagerTest.ts @@ -0,0 +1,58 @@ +import { ModelManager } from '../src/workflows/ModelManager'; +import { apiRequest } from '../src/utils/apiRequest'; +import ModelVersionClient from '../src/model-registry/ModelVersionClient'; +import ModelRegistryClient from '../src/model-registry/ModelRegistryClient'; + +const timestamp = Date.now(); +const modelName = `test-model-${timestamp}`; +const modelVersionDescription1 = 'This is test version 1 description'; +const modelVersionKey = 'version_1_key'; +const modelVersionValue = 'version_1_value'; + +async function createRun( + client: ModelRegistryClient, + experimentId: string +): Promise { + const { response, data } = await apiRequest( + (client as any).baseUrl, + 'runs/create', + { + method: 'POST', + body: { experiment_id: experimentId }, + } + ); + + if (!response.ok) { + throw new Error( + `Error creating run: ${data.message || response.statusText}` + ); + } + + return data.run; +} + +async function testModelManager() { + const modelRegistryClient = new ModelRegistryClient('http://localhost:5001'); + + // Uncommenting this gives us an API Error in createRegisteredModelWithVersion + await modelRegistryClient.createRegisteredModel( + modelName, + [{ key: 'test-tag', value: 'test-value' }], + 'This is a test model' + ); + + console.log('\n5. Creating a run...'); + const run = await createRun(modelRegistryClient, '0'); // Using '0' as the default experiment ID + console.log('Created run:', run); + + console.log('1. Creating a new registered model with a version'); + const modelManager = new ModelManager('http://localhost:5001'); + const newModelVersion = await modelManager.createRegisteredModelWithVersion( + modelName, + run.info.artifact_uri, + run.info.run_id + ); + console.log('Created Model Version: ', newModelVersion); +} + +testModelManager(); From b6f181736e582c5eb8ab476dd9e9cf050df1e93a Mon Sep 17 00:00:00 2001 From: Austin Fraser Date: Wed, 2 Oct 2024 18:49:41 -0700 Subject: [PATCH 111/357] added ExperimentClientTestFile.ts --- mlflow/src/tracking/ExperimentClient.ts | 8 +- mlflow/tests/ExperimentClientTestFile.ts | 118 +++++++++++++++++++++++ 2 files changed, 123 insertions(+), 3 deletions(-) create mode 100644 mlflow/tests/ExperimentClientTestFile.ts diff --git a/mlflow/src/tracking/ExperimentClient.ts b/mlflow/src/tracking/ExperimentClient.ts index ae7142a6..ed51e7ce 100644 --- a/mlflow/src/tracking/ExperimentClient.ts +++ b/mlflow/src/tracking/ExperimentClient.ts @@ -1,5 +1,7 @@ -import { ApiError } from '@utils/apiError'; -import { apiRequest } from '@utils/apiRequest'; +// import { ApiError } from '@utils/apiError'; +import { ApiError } from '../utils/apiError'; +// import { apiRequest } from '@utils/apiRequest'; +import { apiRequest } from '../utils/apiRequest'; class ExperimentClient { trackingUri: string; @@ -197,7 +199,7 @@ class ExperimentClient { }`, response.status ); - } + }; console.log(`Experiment ID ${experiment_id} successfully deleted`); } diff --git a/mlflow/tests/ExperimentClientTestFile.ts b/mlflow/tests/ExperimentClientTestFile.ts new file mode 100644 index 00000000..98449681 --- /dev/null +++ b/mlflow/tests/ExperimentClientTestFile.ts @@ -0,0 +1,118 @@ +import ExperimentClient from '../src/tracking/ExperimentClient.ts'; +const MLFLOW_TRACKING_URI = 'http://localhost:5001'; +let experimentClient = new ExperimentClient(MLFLOW_TRACKING_URI); + +const testCreateExperiment = async () => { + const num = Math.random().toString().slice(2, 11); + const name = `Test experiment ${num}`; + const log = await experimentClient.createExperiment(name); + return console.log(log); +}; +// testCreateExperiment(); + +const testSearchExperiment = async () => { + const num1 = Math.random().toString().slice(2, 11); + const name1 = `Search test ${num1}`; + const exp1 = await experimentClient.createExperiment(name1); + + const num2 = Math.random().toString().slice(2, 11); + const name2 = `Search test ${num2}`; + const exp2 = await experimentClient.createExperiment(name2); + + const num3 = Math.random().toString().slice(2, 11); + const name3 = `Search test ${num3}`; + const exp3 = await experimentClient.createExperiment(name3); + + const num4 = Math.random().toString().slice(2, 11); + const name4 = `Search test ${num4}`; + const exp4 = await experimentClient.createExperiment(name4); + + const num5 = Math.random().toString().slice(2, 11); + const name5 = `Search test ${num5}`; + const exp5 = await experimentClient.createExperiment(name5); + + const log = await experimentClient.searchExperiment( + "name LIKE 'Search test%'", + 4 + ); + console.log(log); +}; +// testSearchExperiment(); + +const testGetExperiment = async () => { + const num = Math.random().toString().slice(2, 11); + const name = `Test experiment ${num}`; + const exp = await experimentClient.createExperiment(name); + const log = await experimentClient.getExperiment(exp); + console.log(log); +}; +// testGetExperiment(); + +const testGetExperimentByName = async () => { + const num = Math.random().toString().slice(2, 11); + const name = `Test experiment ${num}`; + const exp = await experimentClient.createExperiment(name); + const log = await experimentClient.getExperimentByName(name); + console.log(log); +}; +// testGetExperimentByName(); + +const testDeleteExperiment = async () => { + const num = Math.random().toString().slice(2, 11); + const name = `Test experiment ${num}`; + const exp = await experimentClient.createExperiment(name); + const log = await experimentClient.deleteExperiment(exp); + // console.log(log); + const log2 = await experimentClient.getExperiment(exp); + console.log(log2); + experimentClient.restoreExperiment(exp); +}; +// testDeleteExperiment(); + +const testRestoreExperiment = async () => { + const num = Math.random().toString().slice(2, 11); + const name = `Test experiment ${num}`; + const exp = await experimentClient.createExperiment(name); + const log = await experimentClient.getExperiment(exp); + console.log(log); + const deleted = await experimentClient.deleteExperiment(exp); + const log2 = await experimentClient.getExperiment(exp); + console.log(log2); + const log3 = await experimentClient.restoreExperiment(exp); + const log4 = await experimentClient.getExperiment(exp); + console.log(log4); +}; +// testRestoreExperiment(); + +const testUpdateExperiment = async () => { + const num = Math.random().toString().slice(2, 11); + const name = `Test experiment ${num}`; + const exp = await experimentClient.createExperiment(name); + const log = await experimentClient.getExperiment(exp); + console.log(log); + const log2 = await experimentClient.updateExperiment( + exp, + `${name}_UPDATED_NAME` + ); + const log3 = await experimentClient.getExperiment(exp); + console.log(log3); + const revert = await experimentClient.updateExperiment(exp, name); +}; +// testUpdateExperiment(); + +const testSetExperimentTag = async () => { + const num = Math.random().toString().slice(2, 11); + const name = `Test experiment ${num}`; + const exp = await experimentClient.createExperiment(name); + const log = await experimentClient.getExperiment(exp); + console.log(log); + const num2 = Math.random().toString().slice(2, 11); + const log2 = await experimentClient.setExperimentTag( + exp, + 'test_tag', + `test_value_${num2}` + ); + const log3 = await experimentClient.getExperiment(exp); + console.log(log3); +}; +// testSetExperimentTag(); From 6d4fb4d679e6e90d6c48b5d8daad0fdc4aadc7ca Mon Sep 17 00:00:00 2001 From: Kyler-Chiago Date: Wed, 2 Oct 2024 19:21:12 -0700 Subject: [PATCH 112/357] finished modelManager test file --- mlflow/src/workflows/ModelManager.ts | 13 +--- mlflow/tests/ModelManagerTest.ts | 96 +++++++++++++++++++++++----- 2 files changed, 82 insertions(+), 27 deletions(-) diff --git a/mlflow/src/workflows/ModelManager.ts b/mlflow/src/workflows/ModelManager.ts index d2aa9262..1a504564 100644 --- a/mlflow/src/workflows/ModelManager.ts +++ b/mlflow/src/workflows/ModelManager.ts @@ -99,7 +99,6 @@ class ModelManager { value: string ): Promise { try { - // complex operation const data = await this.modelRegistry.getLatestModelVersions(name); if (!data) { throw new Error('Model has no version to update.'); @@ -139,7 +138,6 @@ class ModelManager { value: string ): Promise { try { - // complex operation const data = await this.modelRegistry.getLatestModelVersions(name); if (!data) { throw new Error('Model has no version to set tag for.'); @@ -168,7 +166,6 @@ class ModelManager { */ async setLatestModelVersionAlias(name: string, alias: string): Promise { try { - // complex operation const data = await this.modelRegistry.getLatestModelVersions(name); if (!data) { throw new Error('Model has no version to set alias for.'); @@ -200,7 +197,6 @@ class ModelManager { description: string ): Promise { try { - // complex operation const data = await this.modelRegistry.getLatestModelVersions(name); if (!data) { throw new Error('Model has no version to set description for.'); @@ -231,21 +227,20 @@ class ModelManager { * @param {string} name - Name of the registered model. (Required) * @param {string} version - Model version number. (Required) * @param {string} alias - Name of the alias. (Required) - * @param {string} description - The description for the model version. (Required) * @param {string} key key - Name of the tag. (Required) * @param {string} value - Name of the value of the tag being logged. (Required) + * @param {string} description - The description for the model version. (Required) * @returns {Promise} - the updated model version object */ async updateAllModelVersion( name: string, version: string, alias: string, - description: string, key: string, - value: string + value: string, + description: string, ): Promise { try { - // complex operation await this.modelRegistry.setRegisteredModelAlias(name, alias, version); await this.modelVersion.setModelVersionTag(name, version, key, value); const response = await this.modelVersion.updateModelVersion( @@ -273,7 +268,6 @@ class ModelManager { */ async deleteLatestModelVersion(name: string): Promise { try { - // complex operation const data = await this.modelRegistry.getLatestModelVersions(name); if (!data) { throw new Error('Model has no version to delete.'); @@ -315,7 +309,6 @@ class ModelManager { // modelName: string // ): Promise { // try { - // // complex operation // const { runs } = await this.runClient.searchRuns( // experiment_ids, // `metrics.${filterMetric} != -99999` diff --git a/mlflow/tests/ModelManagerTest.ts b/mlflow/tests/ModelManagerTest.ts index 7de0324f..df3177f9 100644 --- a/mlflow/tests/ModelManagerTest.ts +++ b/mlflow/tests/ModelManagerTest.ts @@ -1,14 +1,7 @@ import { ModelManager } from '../src/workflows/ModelManager'; import { apiRequest } from '../src/utils/apiRequest'; -import ModelVersionClient from '../src/model-registry/ModelVersionClient'; import ModelRegistryClient from '../src/model-registry/ModelRegistryClient'; -const timestamp = Date.now(); -const modelName = `test-model-${timestamp}`; -const modelVersionDescription1 = 'This is test version 1 description'; -const modelVersionKey = 'version_1_key'; -const modelVersionValue = 'version_1_value'; - async function createRun( client: ModelRegistryClient, experimentId: string @@ -31,28 +24,97 @@ async function createRun( return data.run; } +// npx tsx tests/ModelManagerTest.ts + async function testModelManager() { const modelRegistryClient = new ModelRegistryClient('http://localhost:5001'); - - // Uncommenting this gives us an API Error in createRegisteredModelWithVersion - await modelRegistryClient.createRegisteredModel( - modelName, - [{ key: 'test-tag', value: 'test-value' }], - 'This is a test model' - ); + const modelManager = new ModelManager('http://localhost:5001'); + const timestamp = Date.now(); + const modelName = `test-model-${timestamp}`; + const modelDescription = `test-model-description-${timestamp}`; + const modelTagKey = `test-model-tagKey-${timestamp}`; + const modelTagValue = `test-model-tagValue-${timestamp}`; + const modelVersionDescription = `This is test version 1 description: ${timestamp}`; + const modelVersionTagKey = `version_1_key_${timestamp}`; + const modelVersionTagValue = `version_1_value_${timestamp}`; + const modelVersionAlias = `version_1_alias_${timestamp}`; + const modelVersion = '1'; console.log('\n5. Creating a run...'); const run = await createRun(modelRegistryClient, '0'); // Using '0' as the default experiment ID console.log('Created run:', run); - console.log('1. Creating a new registered model with a version'); - const modelManager = new ModelManager('http://localhost:5001'); + console.log('1. Creating a new registered model with a version...'); const newModelVersion = await modelManager.createRegisteredModelWithVersion( modelName, run.info.artifact_uri, run.info.run_id ); - console.log('Created Model Version: ', newModelVersion); + console.log(`Created ${modelName} Version: `, newModelVersion); + + console.log("2. Updating a model's description and tag..."); + const updatedModelDescriptionAndTag = + await modelManager.updateRegisteredModelDescriptionAndTag( + modelName, + modelTagKey, + modelTagValue, + modelDescription + ); + console.log( + `Updated ${modelName} description and tag: `, + updatedModelDescriptionAndTag + ); + + console.log( + "3. Updating the latest model version's alias, tag, and description..." + ); + const updatedLatestModelVersionAll = await modelManager.updateAllLatestModelVersion( + modelName, + modelVersionAlias, + modelVersionDescription, + modelVersionTagKey, + modelVersionTagValue + ); + console.log(`Updated latest version of ${modelName}'s alias, tag, and description: `, updatedLatestModelVersionAll); + + console.log("4. Updating the latest model version's tag..."); + const updatedModelVersionTag = await modelManager.setLatestModelVersionTag( + modelName, + modelVersionTagKey, + modelVersionTagValue + ); + console.log(`Updated ${modelName} version tag`); + + console.log('5. Updating the latest model version\'s alias...'); + const updatedModelVersionAlias = await modelManager.setLatestModelVersionAlias( + modelName, + modelVersionAlias + ) + console.log(`Updated ${modelName} version alias`); + + console.log('6. Updating the description of the latest model version...'); + const updatedModelVersionDescription = await modelManager.updateLatestModelVersion( + modelName, + modelDescription + ); + console.log(`Updated ${modelName} version description: `, updatedModelVersionDescription); + + console.log('7. Updating the specified version\'s alias, tag, and description...'); + const updatedModelVersionAll = await modelManager.updateAllModelVersion( + modelName, + modelVersion, + modelVersionAlias, + modelVersionTagKey, + modelVersionTagValue, + modelVersionDescription + ); + console.log('Updated model version: ', updatedModelVersionAll); + + console.log(`8. Deleting the latest version of the model...`); + const deletedModelVersion = await modelManager.deleteLatestModelVersion( + modelName + ); + console.log(`Deleted Latest version of ${modelName}`) } testModelManager(); From 3636a69a4f990bcf93fbd97fa62e5ad6b1ffb568 Mon Sep 17 00:00:00 2001 From: Kyler-Chiago Date: Wed, 2 Oct 2024 19:24:36 -0700 Subject: [PATCH 113/357] yes --- mlflow/tests/ModelManagerTest.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mlflow/tests/ModelManagerTest.ts b/mlflow/tests/ModelManagerTest.ts index df3177f9..8d524de3 100644 --- a/mlflow/tests/ModelManagerTest.ts +++ b/mlflow/tests/ModelManagerTest.ts @@ -114,7 +114,7 @@ async function testModelManager() { const deletedModelVersion = await modelManager.deleteLatestModelVersion( modelName ); - console.log(`Deleted Latest version of ${modelName}`) + console.log(`Deleted Latest version of ${modelName}`); } testModelManager(); From b55e77c7517862da682cb08021bd308d502eb647 Mon Sep 17 00:00:00 2001 From: Stephany Ho Date: Wed, 2 Oct 2024 22:28:21 -0400 Subject: [PATCH 114/357] Fix ts path aliases and error handling --- mlflow/src/tracking/RunClient.ts | 4 ++-- mlflow/src/workflows/RunManager.ts | 24 +++++++++++++++------ mlflow/tests/RunClientTest.ts | 34 ++++++++++++++++-------------- mlflow/tests/RunManagerTestFile.ts | 10 ++++----- 4 files changed, 42 insertions(+), 30 deletions(-) diff --git a/mlflow/src/tracking/RunClient.ts b/mlflow/src/tracking/RunClient.ts index 81ded45e..ba0d6ce8 100644 --- a/mlflow/src/tracking/RunClient.ts +++ b/mlflow/src/tracking/RunClient.ts @@ -1,5 +1,5 @@ -import { ApiError } from '../utils/apiError'; -import { apiRequest } from '../utils/apiRequest'; +import { ApiError } from '@src/utils/apiError'; +import { apiRequest } from '@src/utils/apiRequest'; class RunClient { private baseUrl: string; diff --git a/mlflow/src/workflows/RunManager.ts b/mlflow/src/workflows/RunManager.ts index 18a8877a..38405d84 100644 --- a/mlflow/src/workflows/RunManager.ts +++ b/mlflow/src/workflows/RunManager.ts @@ -1,5 +1,6 @@ -import RunClient from '../tracking/RunClient'; -import ModelVersionClient from '../model-registry/ModelVersionClient'; +import RunClient from '@src/tracking/RunClient'; +import ModelVersionClient from '@src/model-registry/ModelVersionClient'; +import { ApiError } from '@src/utils/apiError'; interface Run { info: { @@ -114,11 +115,16 @@ class RunManager { pageToken = searchResult.page_token; } while (pageToken); + + return { deletedRuns, total: deletedRuns.length, dryRun }; } catch (error) { - console.error('Error during run cleanup: ', error); - throw new Error('Failed to cleanup runs.'); + if (error instanceof ApiError) { + console.error(`API Error (${error.statusCode}): ${error.message}`); + } else { + console.error('An unexpected error occurred: ', error); + } + throw error; } - return { deletedRuns, total: deletedRuns.length, dryRun }; } /** @@ -255,8 +261,12 @@ class RunManager { targetExperimentId: targetExperimentId, }; } catch (error) { - console.error('Error copying run: ', error); - throw new Error('Failed to copy run.'); + if (error instanceof ApiError) { + console.error(`API Error (${error.statusCode}): ${error.message}`); + } else { + console.error('An unexpected error occurred: ', error); + } + throw error; } } } diff --git a/mlflow/tests/RunClientTest.ts b/mlflow/tests/RunClientTest.ts index 93483caa..40e93d33 100644 --- a/mlflow/tests/RunClientTest.ts +++ b/mlflow/tests/RunClientTest.ts @@ -29,31 +29,31 @@ async function testRunClient(): Promise { try { // createRun console.log('Creating experiment...'); - const experiment_id = await createExperiment(client, 'Experiment 8'); + const experiment_id = await createExperiment(client, 'Experiment 9'); console.log('Created experiment ID: ', experiment_id); - console.log('Creating run...'); + console.log('1. Creating run...'); const run = await client.createRun(experiment_id); console.log('Created run: ', run); // deleteRun const runId = run.info.run_id; - console.log(`Deleting run ID: ${runId}...`); + console.log(`\n2. Deleting run ID: ${runId}...`); await client.deleteRun(runId); console.log('Deleted run: ', runId); // restoreRun - console.log(`Restoring run ID: ${runId}...`); + console.log(`\n3. Restoring run ID: ${runId}...`); await client.restoreRun(runId); console.log('Restored run: ', runId); // getRun - console.log(`Fetching run ID: ${runId}...`); + console.log(`\n4. Fetching run ID: ${runId}...`); const fetchedRun = await client.getRun(runId); console.log('Fetched run: ', fetchedRun); // updateRun - console.log(`Updating run for run ID: ${runId}...`); + console.log(`\n5. Updating run for run ID: ${runId}...`); const updatedRun = await client.updateRun( runId, 'FINISHED', @@ -63,7 +63,7 @@ async function testRunClient(): Promise { console.log('Updated run: ', updatedRun); // logMetric - console.log(`Logging metric for run ID: ${runId}...`); + console.log(`\n6. Logging metric for run ID: ${runId}...`); await client.logMetric(runId, 'accuracy', 0.9); console.log('Logged metric'); @@ -73,7 +73,7 @@ async function testRunClient(): Promise { console.log('Created run2: ', run2); const run2Id = run2.info.run_id; - console.log(`Logging batch for run ID: ${run2Id}...`); + console.log(`\n7. Logging batch for run ID: ${run2Id}...`); await client.logBatch( run2Id, [ @@ -92,7 +92,7 @@ async function testRunClient(): Promise { console.log('Logged batch'); // logModel - console.log(`Logging model for run ID: ${run2Id}...`); + console.log(`\n8. Logging model for run ID: ${run2Id}...`); const model = { artifact_path: 'pytorch_dnn', flavors: { @@ -120,7 +120,7 @@ async function testRunClient(): Promise { console.log('Logged model'); // logInputs - console.log(`Logging inputs for run ID: ${run2Id}...`); + console.log(`\n9. Logging inputs for run ID: ${run2Id}...`); const datasets = [ { tags: [ @@ -145,17 +145,17 @@ async function testRunClient(): Promise { console.log('Created run3: ', run3); const run3Id = run3.info.run_id; - console.log(`Setting tag for run ID ${run3Id}...`); + console.log(`\n10. Setting tag for run ID ${run3Id}...`); await client.setTag(run3Id, 'accuracy', '0.99'); console.log('Finished setting tag'); // deleteTag - console.log(`Deleting tag for run ID: ${run3Id}...`); + console.log(`\n11. Deleting tag for run ID: ${run3Id}...`); await client.deleteTag(run3Id, 'accuracy'); console.log('Deleted tag'); // logParam - console.log(`Logging param for run ID: ${run3Id}...`); + console.log(`\n12. Logging param for run ID: ${run3Id}...`); await client.logParam(run3Id, 'learning_rate', '0.001'); console.log('Logged param'); @@ -164,12 +164,14 @@ async function testRunClient(): Promise { await client.logMetric(run3Id, 'accuracy', 0.95); console.log('Logged metric'); - console.log(`Fetching metric history for run ID: ${run3Id}...`); + console.log(`\n13. Fetching metric history for run ID: ${run3Id}...`); const metricHistory = await client.getMetricHistory(run3Id, 'accuracy'); console.log('Fetched metric history: ', metricHistory); // searchRuns - console.log(`Searching runs for experiment ID: 643644329517739250...`); + console.log( + `\n14. Searching runs for experiment ID: 643644329517739250...` + ); const searchedRuns = await client.searchRuns( ['643644329517739250'], 'metrics.accuracy<0.9' @@ -177,7 +179,7 @@ async function testRunClient(): Promise { console.log('Searched runs: ', searchedRuns); // listArtifacts - console.log(`Listing artifacts for run ID ${run3Id}...`); + console.log(`\n15. Listing artifacts for run ID ${run3Id}...`); const artifacts = await client.listArtifacts(run3Id); console.log('Artifacts: ', artifacts); } catch (error) { diff --git a/mlflow/tests/RunManagerTestFile.ts b/mlflow/tests/RunManagerTestFile.ts index ea6bf494..af97b9a2 100644 --- a/mlflow/tests/RunManagerTestFile.ts +++ b/mlflow/tests/RunManagerTestFile.ts @@ -48,10 +48,10 @@ async function testCleanupRuns(): Promise { console.log('Creating runs...'); const run1 = await myRunClient.createRun(experiment_id1); const run2 = await myRunClient.createRun(experiment_id1); - console.log('Created runs for Test Cleanup Run 3'); + console.log('Created runs for Test Cleanup Run 1'); const run3 = await myRunClient.createRun(experiment_id2); const run4 = await myRunClient.createRun(experiment_id2); - console.log('Created runs for Test Cleanup Run 4'); + console.log('Created runs for Test Cleanup Run 2'); // log metrics const run1_id = run1.info.run_id; @@ -94,7 +94,7 @@ async function testCopyRun(): Promise { console.log('Creating a new experiment and log batch for the new run...'); const experiment_id1 = await createExperiment( myRunClient, - 'Test Copy Run 1' + 'Test Copy Run 5' ); // create a new run in the newly created experiment @@ -175,7 +175,7 @@ async function testCopyRun(): Promise { console.log('Create a target experiment...'); const experiment_id2 = await createExperiment( myRunClient, - 'Test Copy Run 2' + 'Test Copy Run 6' ); // copy previous run to this newly created experiment @@ -183,7 +183,7 @@ async function testCopyRun(): Promise { const copiedRun = await myRunManager.copyRun(runId, experiment_id2); console.log('Copied run: ', copiedRun); } catch (error) { - console.error('Error: ', error.message); + if (error) console.error('Error: ', error.message); } } From 2ff0d96df50915f2db37d73091a9f91772a90e26 Mon Sep 17 00:00:00 2001 From: Kyler-Chiago Date: Wed, 2 Oct 2024 19:30:57 -0700 Subject: [PATCH 115/357] yes --- mlflow/tests/ModelManagerTest.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/mlflow/tests/ModelManagerTest.ts b/mlflow/tests/ModelManagerTest.ts index 8d524de3..6f566561 100644 --- a/mlflow/tests/ModelManagerTest.ts +++ b/mlflow/tests/ModelManagerTest.ts @@ -24,8 +24,6 @@ async function createRun( return data.run; } -// npx tsx tests/ModelManagerTest.ts - async function testModelManager() { const modelRegistryClient = new ModelRegistryClient('http://localhost:5001'); const modelManager = new ModelManager('http://localhost:5001'); @@ -115,6 +113,8 @@ async function testModelManager() { modelName ); console.log(`Deleted Latest version of ${modelName}`); + + console.log('9. ') } testModelManager(); From 5501e71d0caea38dab8c7c31bf3d5b159c50dda1 Mon Sep 17 00:00:00 2001 From: Kyler-Chiago Date: Wed, 2 Oct 2024 19:37:35 -0700 Subject: [PATCH 116/357] @ syntax used for import in ModelManager --- mlflow/src/workflows/ModelManager.ts | 8 ++++---- mlflow/tests/ModelRegistryClientTest.ts | 4 ++-- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/mlflow/src/workflows/ModelManager.ts b/mlflow/src/workflows/ModelManager.ts index 1a504564..8f42f224 100644 --- a/mlflow/src/workflows/ModelManager.ts +++ b/mlflow/src/workflows/ModelManager.ts @@ -1,7 +1,7 @@ -// import RunClient from '../tracking/RunClient'; -import ModelRegistryClient from '../model-registry/ModelRegistryClient'; -import ModelVersionClient from '../model-registry/ModelVersionClient'; -import { ApiError } from 'utils/apiError'; +// import RunClient from '@tracking/RunClient'; +import ModelRegistryClient from '@model-registry/ModelRegistryClient'; +import ModelVersionClient from '@model-registry/ModelVersionClient'; +import { ApiError } from '@utils/apiError'; class ModelManager { private modelRegistry: ModelRegistryClient; diff --git a/mlflow/tests/ModelRegistryClientTest.ts b/mlflow/tests/ModelRegistryClientTest.ts index 205ee650..57732fa2 100644 --- a/mlflow/tests/ModelRegistryClientTest.ts +++ b/mlflow/tests/ModelRegistryClientTest.ts @@ -1,5 +1,5 @@ -import { apiRequest } from '@utils/apiRequest'; -import ModelRegistryClient from '@model-registry/ModelRegistryClient'; +import { apiRequest } from '../src/utils/apiRequest'; +import ModelRegistryClient from '../src/model-registry/ModelRegistryClient'; async function createRun( client: ModelRegistryClient, From 2f7a9d5e509edd16c358a9e7a99174bca442bdd5 Mon Sep 17 00:00:00 2001 From: Kyler-Chiago Date: Wed, 2 Oct 2024 19:38:14 -0700 Subject: [PATCH 117/357] @ syntax used for import in ModelVersionClient --- mlflow/src/model-registry/ModelVersionClient.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/mlflow/src/model-registry/ModelVersionClient.ts b/mlflow/src/model-registry/ModelVersionClient.ts index 741e8c76..7e22edff 100644 --- a/mlflow/src/model-registry/ModelVersionClient.ts +++ b/mlflow/src/model-registry/ModelVersionClient.ts @@ -1,5 +1,5 @@ -import { ApiError } from '../utils/apiError'; -import { apiRequest } from '../utils/apiRequest'; +import { ApiError } from '@utils/apiError'; +import { apiRequest } from '@utils/apiRequest'; class ModelVersionClient { private baseUrl: string; From c9b3e54a2185e5530052ef9c5cddb06e442d7651 Mon Sep 17 00:00:00 2001 From: Stephany Ho Date: Wed, 2 Oct 2024 22:38:23 -0400 Subject: [PATCH 118/357] Clean up files --- mlflow/src/tracking/run_management.js | 526 -------------------------- 1 file changed, 526 deletions(-) delete mode 100644 mlflow/src/tracking/run_management.js diff --git a/mlflow/src/tracking/run_management.js b/mlflow/src/tracking/run_management.js deleted file mode 100644 index c4b69c46..00000000 --- a/mlflow/src/tracking/run_management.js +++ /dev/null @@ -1,526 +0,0 @@ -class RunClient { - constructor(trackingUri) { - this.trackingUri = trackingUri; - } - - /** - * Create a new run within an experiment. A run is usually a single execution of a machine learning or data ETL pipeline. MLflow uses runs to track Param, Metric, and RunTag associated with a single execution. - * - * @param {string} experiment_id - ID of the associated experiment. (required) - * @param {string} [run_name] - Name of the run. - * @param {number} [start_time] - Unix timestamp in milliseconds of when the run started. - * @param {Array<{key: string, value: string}>} [tags=[]] - Additional metadata for the run. - * @returns {Promise} - A promise that resolves with the created run object. - */ - async createRun( - experiment_id, - run_name = null, - start_time = null, - tags = [] - ) { - if (!experiment_id) { - throw new Error('Experiment ID is required'); - } - - const url = `${this.trackingUri}/api/2.0/mlflow/runs/create`; - - const body = { - experiment_id, - start_time: start_time !== null ? start_time : Date.now(), - tags, - }; - - if (run_name) { - body.run_name = run_name; - } - - const response = await fetch(url, { - method: 'POST', - headers: { 'Content-Type': 'application/json' }, - body: JSON.stringify(body), - }); - - const data = await response.json(); - - if (!response.ok) { - throw new Error( - `Error creating run: ${data.message || response.statusText}` - ); - } - - return data.run; - } - - /** - * Mark a run for deletion. - * - * @param {string} run_id - ID of the run to delete. (required) - * @returns {Promise} - A promise that resolves when the run is deleted. - */ - async deleteRun(run_id) { - if (!run_id) { - throw new Error('Run ID is required.'); - } - - const url = `${this.trackingUri}/api/2.0/mlflow/runs/delete`; - - const response = await fetch(url, { - method: 'POST', - headers: { 'Content-Type': 'application/json' }, - body: JSON.stringify({ run_id }), - }); - - if (!response.ok) { - throw new Error(`Error deleting run: ${response.statusText}`); - } - - return; - } - - /** - * Restore a deleted run. - * - * @param {string} run_id - ID of the run to restore. (required) - * @returns {Promise} - A promise that resolves when the run is restored. - */ - async restoreRun(run_id) { - if (!run_id) { - throw new Error('Run ID is required.'); - } - - const url = `${this.trackingUri}/api/2.0/mlflow/runs/restore`; - - const response = await fetch(url, { - method: 'POST', - headers: { 'Content-Type': 'application/json' }, - body: JSON.stringify({ run_id }), - }); - - if (!response.ok) { - throw new Error(`Error restoring run: ${response.statusText}`); - } - - return; - } - - /** - * Get metadata, metrics, params, and tags for a run. In the case where multiple metrics with the same key are logged for a run, return only the value with the latest timestamp. If there are multiple values with the latest timestamp, return the maximum of these values. - * - * @param {string} run_id - ID of the run to fetch. (required) - * @returns {Promise} - A promise that resolves with the fetched run object. - */ - async getRun(run_id) { - if (!run_id) { - throw new Error('Run ID is required.'); - } - - const url = `${this.trackingUri}/api/2.0/mlflow/runs/get?run_id=${run_id}`; - - const response = await fetch(url); - const data = await response.json(); - - if (!response.ok) { - throw new Error( - `Error fetching run: ${data.message || response.statusText}` - ); - } - - return data.run; - } - - /** - * Update run metadata. - * - * @param {string} run_id - ID of the run to update. (required) - * @param {string} [status] - Updated status of the run. - * @param {number} [end_time] - Unix timestamp in milliseconds of when the run ended. - * @param {string} [run_name] - Updated name of the run. - * @returns {Promise} - A promise that resolves with the updated metadata of the run object. - */ - async updateRun(run_id, status = null, end_time = null, run_name = null) { - if (!run_id) { - throw new Error('Run ID is required.'); - } - - const url = `${this.trackingUri}/api/2.0/mlflow/runs/update`; - - const body = { run_id }; - if (status) body.status = status; - if (end_time) body.end_time = end_time; - if (run_name) body.run_name = run_name; - - const response = await fetch(url, { - method: 'POST', - headers: { 'Content-Type': 'application/json' }, - body: JSON.stringify(body), - }); - - const data = await response.json(); - - if (!response.ok) { - throw new Error( - `Error updating run: ${data.message || response.statusText}` - ); - } - - return data; - } - - /** - * Log a metric for a run. A metric is a key-value pair (string key, float value) with an associated timestamp. Examples include the various metrics that represent ML model accuracy. A metric can be logged multiple times. - * - * @param {string} run_id - ID of the run under which to log the metric. (required) - * @param {string} key - Name of the metric. (required) - * @param {number} value - Double value of the metric being logged. (required) - * @param {number} timestamp - Unix timestamp in milliseconds at the time metric was logged. (required) - * @param {number} [step=0] - Step at which to log the metric. - * @returns {Promise} - A promise that resolves when the logging is complete. - */ - - async logMetric(run_id, key, value, timestamp = Date.now(), step = 0) { - if (!run_id || !key || !value || !timestamp) { - throw new Error('Run ID, key, value, and timestamp are required.'); - } - - const url = `${this.trackingUri}/api/2.0/mlflow/runs/log-metric`; - - const body = { run_id, key, value, timestamp }; - if (step) body.step = step; - - const response = await fetch(url, { - method: 'POST', - headers: { 'Content-Type': 'application/json' }, - body: JSON.stringify(body), - }); - - if (!response.ok) { - throw new Error(`Error logging metric: ${response.statusText}`); - } - - return; - } - - /** - * Log a batch of metrics, params, and tags for a run. If any data failed to be persisted, the server will respond with an error (non-200 status code). In case of error (due to internal server error or an invalid request), partial data may be written. - * - * @param {string} run_id - ID of the run to log under. (required) - * @param {Array<{key: string, value: number, timestamp: number, step?: number}>} [metrics=[]] - Metrics to log. A single request can contain up to 1000 metrics, and up to 1000 metrics, params, and tags in total. - * @param {Array<{key: string, value: string}>} [params=[]] - Params to log. A single request can contain up to 100 params, and up to 1000 metrics, params, and tags in total. - * @param {Array<{key: string, value: string}>} [tags=[]] - Tags to log. A single request can contain up to 100 tags, and up to 1000 metrics, params, and tags in total. - * @returns {Promise} - A promise that resolves when the logging is complete. - */ - async logBatch(run_id, metrics = [], params = [], tags = []) { - if (!run_id) { - throw new Error('Run ID is required.'); - } - - const url = `${this.trackingUri}/api/2.0/mlflow/runs/log-batch`; - - const body = { run_id }; - if (metrics) body.metrics = metrics; - if (params) body.params = params; - if (tags) body.tags = tags; - - const response = await fetch(url, { - method: 'POST', - headers: { 'Content-Type': 'application/json' }, - body: JSON.stringify(body), - }); - - if (!response.ok) { - throw new Error(`Error logging batch: ${response.statusText}`); - } - - return; - } - - /** - * Logs a model. - * - * @param {string} run_id - ID of the run to log under. (required) - * @param {string} model_json - MLmodel file in json format. (required) - * @returns {Promise} - A promise that resolves when the logging is complete. - */ - async logModel(run_id, model_json) { - if (!run_id || model_json) { - throw new Error('Run ID and MLmodel data are required.'); - } - - const url = `${this.trackingUri}/api/2.0/mlflow/runs/log-model`; - - const response = await fetch(url, { - method: 'POST', - headers: { 'Content-Type': 'application/json' }, - body: JSON.stringify({ run_id, model_json }), - }); - - if (!response.ok) { - throw new Error(`Error logging model: ${response.statusText}`); - } - - return; - } - - /** - * Logs inputs. - * - * @param {string} run_id - ID of the run to log under. (required) - * @param {Array} datasets - The dataset inputs in JSON format. (required) - * @returns {Promise} - A promise that resolves when the logging is complete. - */ - - async logInputs(run_id, datasets) { - if (!run_id || !datasets) { - throw new Error('Run ID and datasets are required.'); - } - - const url = `${this.trackingUri}/api/2.0/mlflow/runs/log-inputs`; - - const response = await fetch(url, { - method: 'POST', - headers: { 'Content-Type': 'application/json' }, - body: JSON.stringify({ run_id, datasets }), - }); - - if (!response.ok) { - throw new Error(`Error in logging inputs: ${response.statusText}`); - } - - return; - } - - /** - * Set a tag on a run. Tags are run metadata that can be updated during a run and after a run completes. - * - * @param {string} run_id - ID of the run under which to log the tag. (required) - * @param {string} key - Name of the tag. Maximum size depends on storage backend. All storage backends - * are guaranteed to support key values up to 250 bytes in size. (required) - * @param {string} value - String value of the tag being logged. Maximum size depends on storage - * backend. All storage backends are guaranteed to support key values up to 5000 bytes in size. (required) - * @returns {Promise} - A promise that resolves when the logging is complete. - */ - async setTag(run_id, key, value) { - if (!run_id) { - throw new Error('Run ID is required'); - } else if (!key) { - throw new Error('Key is required'); - } else if (!value) { - throw new Error('Value is required'); - } - const url = `${this.trackingUri}/api/2.0/mlflow/runs/set-tag`; - const response = await fetch(url, { - method: 'POST', - headers: { - 'Content-Type': 'application/json', - }, - body: JSON.stringify({ run_id, key, value }), - }); - - if (!response.ok) { - throw new Error(`Error setting tag: ${response.statusText}`); - } - - return; - } - - /** - * Delete a tag on a run. Tags are run metadata that can be updated during a run and after a run completes. - * - * @param {string} run_id - ID of the run that the tag was logged under. (required) - * @param {string} key - Name of the tag. Maximum size is 255 bytes. (required) - * @returns {Promise} - A promise that resolves when the deletion is complete. - */ - async deleteTag(run_id, key) { - if (!run_id) { - throw new Error('run_id is required'); - } else if (!key) { - throw new Error('key is required'); - } - const url = `${this.trackingUri}/api/2.0/mlflow/runs/delete-tag`; - const response = await fetch(url, { - method: 'POST', - headers: { - 'Content-Type': 'application/json', - }, - body: JSON.stringify({ run_id, key }), - }); - - // data is an empty object - const data = await response.json(); - - if (!response.ok) { - throw new Error( - `Error deleting tag: ${data.message || response.statusText}` - ); - } - return; - } - - /** - * Log a param used for a run. A param is a key-value pair (string key, string value). Examples include hyperparameters used for ML model training and constant dates and values used in an ETL pipeline. A param can be logged only once for a run. - * - * @param {string} run_id - ID of the run under which to log the param. (required)) - * @param {string} key - Name of the param. Maximum size is 255 bytes. (required) - * @param {string} value - String value of the param being logged. Maximum size is 6000 bytes. (required) - * @returns {Promise} - A promise that resolves when the logging is complete. - */ - async logParam(run_id, key, value) { - if (!run_id) { - throw new Error('run_id is required'); - } else if (!key) { - throw new Error('key is required'); - } else if (!value) { - throw new Error('value is required'); - } - const url = `${this.trackingUri}/api/2.0/mlflow/runs/log-parameter`; - const response = await fetch(url, { - method: 'POST', - headers: { - 'Content-Type': 'application/json', - }, - body: JSON.stringify({ run_id, key, value }), - }); - - if (!response.ok) { - throw new Error(`Error logging param: ${response.statusText}`); - } - } - - /** - * Get a list of all values for the specified metric for a given run. - * - * @param {string} run_id - ID of the run from which to fetch metric values. (required) - * @param {string} metric_key - Name of the metric. (required) - * @param {string} page_token - Token indicating the page of metric history to fetch. - * @param {number} max_results - Maximum number of logged instances of a metric for a run to return per call. - * Backend servers may restrict the value of max_results depending on performance requirements. Requests that do not - * specify this value will behave as non-paginated queries where all metric history values for a given metric - * within a run are returned in a single response. - * @returns {Promise} - A promise that resolves with the values for the specified metric. - */ - async getMetricHistory(run_id, metric_key, page_token, max_results) { - if (!run_id) { - throw new Error('run_id is required'); - } else if (!metric_key) { - throw new Error('metric_key is required'); - } - const url = `${this.trackingUri}/api/2.0/mlflow/metrics/get-history?run_id=${run_id}&metric_key=${metric_key}&page_token=${page_token}&max_results=${max_results}`; - const response = await fetch(url); - /** - * data can have the fields: - * metrics {An array of Metric} - All logged values for this metric - * next_page_token {string} - Token that can be used to issue a query for the next page of metric history values. A - * missing token indicates that no additional metrics are available to fetch. - */ - const data = await response.json(); - if (!response.ok) { - throw new Error( - `Error finding metric for given run: ${ - data.message || response.statusText - }` - ); - } - - return data; - } - - /** - * Search for runs that satisfy expressions. Search expressions can use Metric and Param keys. - * - * @param {Array} experiment_ids - List of experiment IDs to search over. - * @param {string} filter - A filter expression over params, metrics, and tags, that allows returning a subset of runs. - * The syntax is a subset of SQL that supports ANDing together binary operations between a param, metric, or tag and a constant. - * Example: metrics.rmse < 1 and params.model_class = 'LogisticRegression' - * You can select columns with special characters (hyphen, space, period, etc.) by using - * double quotes: metrics."model class" = 'LinearRegression' and tags."user-name" = 'Tomas' - * Supported operators are =, !=, >, >=, <, and <=. - * @param {string} run_view_type - Whether to display only active, only deleted, or all runs. Defaults to active runs. - * @param {number} max_results - Maximum number of runs desired. If unspecified, defaults to 1000. All servers are - * guaranteed to support a max_results theshold of at least 50,000 but may support more. Callers of this endpoint are - * encouraged to pass max_results explicitly and leverage page_token to iterate through experiments. - * @param {Array} order_by - List of columns to be ordered by, including attributes, params, metrics, - * and tags with an optional "DESC" or "ASC" annotation, where "ASC" is the default. - * Example: ["params.input DESC","metrics.alpha ASC", "metrics.rmse"] Tiebreaks are done by start_time DESC followed by run_id for - * runs with the same start time (and this is the default ordering criterion if order_by is not provided). - * @param {string} page_token - Token that can be used to retrieve the next page of run results. A missing token indicates that - * there are no additional run results to be fetched. - * @returns {Promise} - A promise that resovles with the runs that match the search criteria. - */ - async searchRuns( - experiment_ids, - filter, - run_view_type, - max_results, - order_by, - page_token - ) { - const url = `${this.trackingUri}/api/2.0/mlflow/runs/search`; - const response = await fetch(url, { - method: 'POST', - headers: { - 'Content-Type': 'application/json', - }, - body: JSON.stringify({ - experiment_ids, - filter, - run_view_type, - max_results, - order_by, - page_token, - }), - }); - /** - * data can have the fields: - * runs {An array of Run} - Runs that match the search criteria - * next_page_token {string} - Token that can be used to retrieve the next page of run results. A missing token indicates - * that there are no additional run results to be fetched. - */ - const data = await response.json(); - - if (!response.ok) { - throw new Error( - `Error finding run that satisfies expressions: ${ - data.message || response.statusText - }` - ); - } - - return data; - } - - /** - * List artifacts for a run. Takes an optional artifact_path prefix which if specified, the response contains only artifacts with the specified prefix. - * - * @param {string} run_id - ID of the run whose artifacts to list. (required) - * @param {string} path - Filter artifacts matching this path (a relative path from the root artifact directory). - * @param {string} page_token - Token indicating the page of artifact results to fetch. - * @returns {Promise} - A promise that resolves with a list artifacts for the specified run. - */ - async listArtifacts(run_id, path = '', page_token = '') { - if (!run_id) { - throw new Error('run_id is required'); - } - const response = await fetch( - `${this.trackingUri}/api/2.0/mlflow/artifacts/list?run_id=${run_id}&run_uuid=${run_id}&path=${path}&page_token=${page_token}` - ); - /** - * data can have the fields: - * root_uri {string} - Root artifact directory for the run - * files {An array of FileInfo} - File location and metadata for artifacts - * next_page_token {string} - Token that can be used to retrieve the next page of artifact results. A missing token indicates - * that there are no additional artifact results to be fetched. - */ - const data = await response.json(); - if (!response.ok) { - throw new Error( - `Error retrieving artifacts from run: ${ - data.message || response.statusText - }` - ); - } - - return data; - } -} - -export { RunClient }; From 14adefb7be708d2d085df846500df580e784f5c6 Mon Sep 17 00:00:00 2001 From: Kyler-Chiago Date: Wed, 2 Oct 2024 19:49:18 -0700 Subject: [PATCH 119/357] yes --- mlflow/src/workflows/ModelManager.ts | 16 ++++++++++++---- mlflow/tests/ModelManagerTest.ts | 4 +++- 2 files changed, 15 insertions(+), 5 deletions(-) diff --git a/mlflow/src/workflows/ModelManager.ts b/mlflow/src/workflows/ModelManager.ts index 8f42f224..55438f06 100644 --- a/mlflow/src/workflows/ModelManager.ts +++ b/mlflow/src/workflows/ModelManager.ts @@ -21,6 +21,7 @@ class ModelManager { * @param {string} versionRun_id - MLflow run ID for correlation, if versionSource was generated * by an experiment run in MLflow tracking server. * @returns {Promise} - the updated model version object + * @throws {ApiError | Error} If request fails */ async createRegisteredModelWithVersion( name: string, @@ -55,6 +56,7 @@ class ModelManager { * @param {string} tagValue - String value of the tag being logged. (Required) * @param {string} description - Description of the registered model. * @returns {Promise} - the updated registered model object + * @throws {ApiError | Error} If request fails */ async updateRegisteredModelDescriptionAndTag( name: string, @@ -90,6 +92,7 @@ class ModelManager { * @param {string} key - Name of the tag. (Required) * @param {string} value - Name of the value of the tag being logged. (Required) * @returns {Promise} - the updated model version object + * @throws {ApiError | Error} If request fails */ async updateAllLatestModelVersion( name: string, @@ -131,6 +134,7 @@ class ModelManager { * @param {string} key - Name of the tag. (Required) * @param {string} value - Name of the value of the tag being logged. (Required) * @returns {Promise} - a promise that resolves when the model version is deleted + * @throws {ApiError | Error} If request fails */ async setLatestModelVersionTag( name: string, @@ -163,6 +167,7 @@ class ModelManager { * @param {string} name - Name of the registered model. (Required) * @param {string} alias - Name of the alias. (Required) * @returns {Promise} - a promise that resolves when the model version is deleted + * @throws {ApiError | Error} If request fails */ async setLatestModelVersionAlias(name: string, alias: string): Promise { try { @@ -191,6 +196,7 @@ class ModelManager { * @param {string} name - Name of the registered model. (Required) * @param {string} description - The description for the model version. (Required) * @returns {Promise} - the updated model version object + * @throws {ApiError | Error} If request fails */ async updateLatestModelVersion( name: string, @@ -231,6 +237,7 @@ class ModelManager { * @param {string} value - Name of the value of the tag being logged. (Required) * @param {string} description - The description for the model version. (Required) * @returns {Promise} - the updated model version object + * @throws {ApiError | Error} If request fails */ async updateAllModelVersion( name: string, @@ -238,7 +245,7 @@ class ModelManager { alias: string, key: string, value: string, - description: string, + description: string ): Promise { try { await this.modelRegistry.setRegisteredModelAlias(name, alias, version); @@ -265,6 +272,7 @@ class ModelManager { * * @param {string} name - the model name * @returns - a promise that resolves when the model version is deleted + * @throws {ApiError | Error} If request fails */ async deleteLatestModelVersion(name: string): Promise { try { @@ -287,9 +295,6 @@ class ModelManager { } } - // Set it up so they can specify if they want the specified metric that is the greatest value, or the lowest value - - // Probably make it so it can also make a new model version if there's already a version of that modelName /** * Looks through the runs with the given experiment id and through their metrics * looking for the specified metric that has the highest or lowest value (can be specified). @@ -301,6 +306,8 @@ class ModelManager { * @param {string} metricMinOrMax - A string specifying if we want the minimum or maximum * value of the specified metric. (Required) * @param {string} modelName - The name of the new model that will be created. (Required) + * @returns {Promise} + * @throws {ApiError | Error} If request fails */ // async createModelFromRunWithBestMetric( // experiment_ids: string[], @@ -345,6 +352,7 @@ class ModelManager { // bestRun.info.artifact_uri, // bestRun.info.run_id // ); + // return // } catch (error) { // if (error instanceof ApiError) { // console.error(`API Error (${error.statusCode}): ${error.message}`); diff --git a/mlflow/tests/ModelManagerTest.ts b/mlflow/tests/ModelManagerTest.ts index 6f566561..42e2a9db 100644 --- a/mlflow/tests/ModelManagerTest.ts +++ b/mlflow/tests/ModelManagerTest.ts @@ -114,7 +114,9 @@ async function testModelManager() { ); console.log(`Deleted Latest version of ${modelName}`); - console.log('9. ') + console.log('9. Creating model from run with best metric...'); + + console.log(`Created ${modelName} from run with best metric`) } testModelManager(); From ea92415ead7dfad1ffe6e3825bf541bd208de111 Mon Sep 17 00:00:00 2001 From: Yiqun Zheng <16813562+yiqunzheng@users.noreply.github.com> Date: Wed, 2 Oct 2024 19:55:10 -0700 Subject: [PATCH 120/357] fix path config in tsconfig.json --- mlflow/tsconfig.json | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/mlflow/tsconfig.json b/mlflow/tsconfig.json index da733471..88e5b25e 100644 --- a/mlflow/tsconfig.json +++ b/mlflow/tsconfig.json @@ -15,8 +15,7 @@ "@model-registry/*": ["src/model-registry/*"], "@tracking/*": ["src/tracking/*"], "@utils/*": ["src/utils/*"], - "@workflows/*": ["src/workflows/*"], - "@tests/*": ["tests/*"] + "@workflows/*": ["src/workflows/*"] }, "esModuleInterop": true, "resolveJsonModule": true, From 4d4ca65ab8c57e348c23d269f40884fa65d581bb Mon Sep 17 00:00:00 2001 From: Yiqun Zheng <16813562+yiqunzheng@users.noreply.github.com> Date: Wed, 2 Oct 2024 20:01:44 -0700 Subject: [PATCH 121/357] add tech design doc --- mlflow/docs/code-standards.md | 88 ++++++++++++++++++++++++ mlflow/docs/tech-design-doc.md | 120 +++++++++++++++++++++++++++++++++ 2 files changed, 208 insertions(+) create mode 100644 mlflow/docs/code-standards.md create mode 100644 mlflow/docs/tech-design-doc.md diff --git a/mlflow/docs/code-standards.md b/mlflow/docs/code-standards.md new file mode 100644 index 00000000..2e4a497e --- /dev/null +++ b/mlflow/docs/code-standards.md @@ -0,0 +1,88 @@ +# TypeScript Code Standards + +## File Structure and Naming +- Use PascalCase for class files (e.g., `ModelRegistryClient.ts`) +- Use camelCase for utility files (e.g., `apiRequest.ts`) +- Use kebab-case for directory names (e.g., `model-registry`) + +## Imports and Exports +- Use named exports for utilities and interfaces +- Use default exports for main classes +- Group and sort imports: + 1. External libraries + 2. Internal modules + 3. Relative imports +- Within each group, sort alphabetically +- For imports from other modules, use the path aliases defined in tsconfig.json +- For imports within the same directory, use relative imports + +## Naming Conventions +- PascalCase for classes and interfaces +- camelCase for methods, variables, and functions +- UPPER_SNAKE_CASE for constants + +## Documentation +- Use JSDoc comments for classes, methods, and functions +- Include parameter descriptions, return types, and thrown exceptions +- Example: + ```typescript + /** + * Creates a new registered model. + * @param {string} name - The name of the model to register + * @param {RegisteredModelTag[]} [tags] - Optional tags for the model + * @param {string} [description] - Optional description for the model + * @returns {Promise} The created registered model object + * @throws {ApiError} If the API request fails + */ + ``` + +## Error Handling Guide + +- For simple API calls, use the ApiError class: + +```typescript +if (!response.ok) { + throw new ApiError( + `Error: ${data.message || response.statusText}`, + response.status + ); +} +``` + +- For complex functions, use try/catch blocks: + +```typescript +try { + // complex operation +} catch (error) { + if (error instanceof ApiError) { + console.error(`API Error (${error.statusCode}): ${error.message}`); + throw error; + } else { + console.error('An unexpected error occurred:', error); + throw new Error; + } +} +``` + +## Asynchronous Code +- Use async/await for asynchronous operations + +## Type Annotations +- Use TypeScript type annotations consistently +- Create interfaces for complex object structures +- Use generics where appropriate + +## Class and Method Structure +- Utilize TypeScript features like access modifiers (public, private) +- Use method signatures with proper TypeScript types + +## Formatting +- Use 2 spaces for indentation +- Use single quotes for strings +- Add semicolons at the end of statements + +## Consistency +- Maintain consistent style and patterns throughout the codebase +- When in doubt, follow the existing patterns in the project + diff --git a/mlflow/docs/tech-design-doc.md b/mlflow/docs/tech-design-doc.md new file mode 100644 index 00000000..de422410 --- /dev/null +++ b/mlflow/docs/tech-design-doc.md @@ -0,0 +1,120 @@ +# MLflow JavaScript Library Technical Design Document + + +## 1. Overview + + +The MLflow-JS library aims to provide a comprehensive and intuitive interface for interacting with MLflow services in a JavaScript/Typescript environment. It simplifies the integration with MLflow REST APIs by offering high-level methods for tracking, model management, and advanced workflows. + + +## 2. Architecture + + +The library follows a modular architecture with a main `MLflow` class serving as the primary entry point and separate clients for different MLflow components and workflow managers. + + +### 2.1 Core Components + + +1. **MLflow**: Main class providing access to high-level abstractions and other components. +2. **Tracking**: Module for interacting with MLflow's tracking server. +3. **Model Registry**: Module for managing models in MLflow's model registry. +4. **Workflows**: Higher-level abstractions for common workflows. +5. **Utils**: Utility functions and classes used across the library. + + +### 2.2 Folder Structure + + +``` +mlflow-js/ +├── src/ +│ ├── tracking/ +│ │ ├── ExperimentClient.ts +│ │ ├── RunClient.ts +│ ├── model-registry/ +│ │ ├── ModelRegistryClient.ts +│ │ └── ModelVersionClient.ts +│ ├── workflows/ +│ │ ├── ExperimentManager.ts +│ │ ├── RunManager.ts +│ │ └── ModelManager.ts +│ ├── utils/ +│ │ ├── apiRequest.ts +│ │ └── apiError.ts +│ ├── mlflow.ts +│ └── index.ts +├── tests/ +├── lib/ +├── examples/ +└── docs/ +``` + + +## 3. Component Details + + +### 3.1 MLflow Class + + +The `MLflow` class serves as the main entry point for the library. It provides: +- Access to High-level abstractions for common workflows +- Access to tracking and model registry components + + +### 3.2 Tracking Module + + +Includes clients for interacting with MLflow's tracking server: +- `ExperimentClient`: Manage experiments +- `RunClient`: Create and manage runs, log metrics/params/artifacts + + +### 3.3 Model Registry Module + + +Provides functionality for model management: +- `ModelRegistryClient`: Register and manage models +- `ModelVersionClient`: Handle model versioning and stage transitions + + +### 3.4 Workflows + + +Higher-level abstractions for common workflows: +- `ExperimentManager`: Manage experiment lifecycles +- `RunManager`: Simplify run creation and management +- `ModelManager`: Streamline model registration and promotion + + +### 3.5 Utils + + +Utility classes and functions: +- `apiRequest`: Handle HTTP requests to MLflow server +- `ApiError`: Custom error class for API-related errors + + +## 4. Data Flow + + +1. User interacts with `MLflow` instance +2. `MLflow` delegates to appropriate abstraction or client +3. Client/abstraction uses `ApiRequest` to make HTTP requests +4. `ApiRequest` sends request to MLflow server +5. Response is processed and returned to user + + +## 5. Testing Strategy + + +- Integration tests for API interactions +- End-to-end tests with a real MLflow server and ML model + + +## 6. Documentation + + +- Comprehensive API documentation generated from JSDoc comments +- Usage examples for common scenarios +- Tutorials for getting started and advanced usage From eb8622c55a4ee23512be728407e38edd774756ac Mon Sep 17 00:00:00 2001 From: Kyler-Chiago Date: Wed, 2 Oct 2024 20:07:05 -0700 Subject: [PATCH 122/357] about to make test for modelManager.createModelFromRunWithBestMetric --- mlflow/tests/ModelManagerTest.ts | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/mlflow/tests/ModelManagerTest.ts b/mlflow/tests/ModelManagerTest.ts index 42e2a9db..b53b6211 100644 --- a/mlflow/tests/ModelManagerTest.ts +++ b/mlflow/tests/ModelManagerTest.ts @@ -115,8 +115,10 @@ async function testModelManager() { console.log(`Deleted Latest version of ${modelName}`); console.log('9. Creating model from run with best metric...'); + // const bestModel = await modelManager.createModelFromRunWithBestMetric( - console.log(`Created ${modelName} from run with best metric`) + // ) + // console.log(`Created ${modelName} from run with best metric`) } testModelManager(); From 0d77c507f8c75214448bf752716cd554c90080d9 Mon Sep 17 00:00:00 2001 From: Stephany Ho Date: Wed, 2 Oct 2024 23:19:57 -0400 Subject: [PATCH 123/357] Resolved conflicts after merging dev --- mlflow/src/workflows/RunManager.ts | 31 +++++++++++++++++++----------- mlflow/tests/RunManagerTestFile.ts | 4 ++-- 2 files changed, 22 insertions(+), 13 deletions(-) diff --git a/mlflow/src/workflows/RunManager.ts b/mlflow/src/workflows/RunManager.ts index 38405d84..e5318cfb 100644 --- a/mlflow/src/workflows/RunManager.ts +++ b/mlflow/src/workflows/RunManager.ts @@ -214,21 +214,30 @@ class RunManager { ); if (modelVersions && modelVersions.length > 0) { for (const model of modelVersions) { - await this.runClient.setTag( - newRunId, - `original_model_${model.name}`, - JSON.stringify({ - name: model.name, - version: model.version, - current_stage: model.current_stage, - source: model.source, - }) - ); + if ( + typeof model === 'object' && + model !== null && + 'name' in model && + 'version' in model && + 'current_stage' in model && + 'source' in model + ) { + await this.runClient.setTag( + newRunId, + `original_model_${model.name}`, + JSON.stringify({ + name: model.name, + version: model.version, + current_stage: model.current_stage, + source: model.source, + }) + ); + } } await this.runClient.setTag( newRunId, 'mlflow.note.models', - 'Models not copied -see original run' + 'Models not copied, see original run.' ); } diff --git a/mlflow/tests/RunManagerTestFile.ts b/mlflow/tests/RunManagerTestFile.ts index af97b9a2..85527923 100644 --- a/mlflow/tests/RunManagerTestFile.ts +++ b/mlflow/tests/RunManagerTestFile.ts @@ -94,7 +94,7 @@ async function testCopyRun(): Promise { console.log('Creating a new experiment and log batch for the new run...'); const experiment_id1 = await createExperiment( myRunClient, - 'Test Copy Run 5' + 'Test Copy Run 1' ); // create a new run in the newly created experiment @@ -175,7 +175,7 @@ async function testCopyRun(): Promise { console.log('Create a target experiment...'); const experiment_id2 = await createExperiment( myRunClient, - 'Test Copy Run 6' + 'Test Copy Run 2' ); // copy previous run to this newly created experiment From 5e36484763260643d783a38e98a43caf071879ad Mon Sep 17 00:00:00 2001 From: Stephany Ho Date: Thu, 3 Oct 2024 20:48:23 -0400 Subject: [PATCH 124/357] Minor changes to path aliases --- mlflow/src/tracking/RunClient.ts | 4 ++-- mlflow/src/workflows/RunManager.ts | 6 +++--- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/mlflow/src/tracking/RunClient.ts b/mlflow/src/tracking/RunClient.ts index ba0d6ce8..ef26e139 100644 --- a/mlflow/src/tracking/RunClient.ts +++ b/mlflow/src/tracking/RunClient.ts @@ -1,5 +1,5 @@ -import { ApiError } from '@src/utils/apiError'; -import { apiRequest } from '@src/utils/apiRequest'; +import { ApiError } from '@utils/apiError'; +import { apiRequest } from '@utils/apiRequest'; class RunClient { private baseUrl: string; diff --git a/mlflow/src/workflows/RunManager.ts b/mlflow/src/workflows/RunManager.ts index e5318cfb..ac4bea05 100644 --- a/mlflow/src/workflows/RunManager.ts +++ b/mlflow/src/workflows/RunManager.ts @@ -1,6 +1,6 @@ -import RunClient from '@src/tracking/RunClient'; -import ModelVersionClient from '@src/model-registry/ModelVersionClient'; -import { ApiError } from '@src/utils/apiError'; +import RunClient from '@tracking/RunClient'; +import ModelVersionClient from '@model-registry/ModelVersionClient'; +import { ApiError } from '@utils/apiError'; interface Run { info: { From 656f3d087677415729a7f84040ebc83386c8f17f Mon Sep 17 00:00:00 2001 From: Austin Fraser Date: Thu, 3 Oct 2024 18:11:23 -0700 Subject: [PATCH 125/357] started ExperimentManager.ts --- mlflow/src/workflows/ExperimentManager.js | 1 - mlflow/src/workflows/ExperimentManager.ts | 132 ++++++++++++++++++++++ 2 files changed, 132 insertions(+), 1 deletion(-) create mode 100644 mlflow/src/workflows/ExperimentManager.ts diff --git a/mlflow/src/workflows/ExperimentManager.js b/mlflow/src/workflows/ExperimentManager.js index 60328e99..5347fd57 100644 --- a/mlflow/src/workflows/ExperimentManager.js +++ b/mlflow/src/workflows/ExperimentManager.js @@ -1,6 +1,5 @@ import { ExperimentClient } from '../tracking/ExperimentClient.js'; import { RunManagement } from '../tracking/run_management.js'; -const MLFLOW_TRACKING_URI = 'http://localhost:5001'; const experimentClient = new ExperimentClient(MLFLOW_TRACKING_URI); const runManagement = new RunManagement(MLFLOW_TRACKING_URI); diff --git a/mlflow/src/workflows/ExperimentManager.ts b/mlflow/src/workflows/ExperimentManager.ts new file mode 100644 index 00000000..4c5f9320 --- /dev/null +++ b/mlflow/src/workflows/ExperimentManager.ts @@ -0,0 +1,132 @@ +import ExperimentClient from '@tracking/ExperimentClient'; +import { RunClient } from '@tracking/RunClient'; + +class ExperimentManager { + private trackingUri: string; + private experimentClient: ExperimentClient; + private runClient: RunClient; + constructor(trackingUri: string) { + this.trackingUri = trackingUri; + this.experimentClient = new ExperimentClient(trackingUri); + this.runClient = new RunClient(trackingUri); + } + + /** + * Full workflow of creating, naming and starting a run under an existing experiment (referenced by ID), + * logging metrics, params, and tags, logging the model, and finishing the run. + * + * @param {string} experiment_id ID of the experiment under which to log the run. (required) + * @param {string} run_name Name of the run to be created and run (optional) + * @param {Array<{key: string, value: number, timestamp: number, step?: number}>} [metrics] The metrics to log (up to 1000 metrics) (optional) + * @param {Array<{key: string, value: string}>} [params] The params to log (up to 100 params) (optional) + * @param {Array<{key: string, value: string}>} [tags] The tags to log (up to 100 tags) (optional) + * @param {{artifact_path: string, flavors: Object, model_url: string, model_uuid: string, utc_time_created: number, mlflow_version: string}} model The ML model data to log to the run, represented as a Javascript object (optional) + * @returns {Promise} The created run object with updated metadata + */ + async runExistingExperiment( + experiment_id: string, + run_name?: string, + metrics?: Array<{key: string, value: number, timestamp: number, step?: number}>, + params?: Array<{key: string, value: string}>, + tags?: Array<{key: string, value: string}>, + model?: {artifact_path: string, flavors: Object, model_url: string, model_uuid: string, utc_time_created: number, mlflow_version: string, run_id?: string} + ) { + if (!experiment_id) { + throw new Error('Experiment ID is required'); + } + + // create run + const run = await this.runClient.createRun(experiment_id, run_name, tags); + const run_id = run.info.run_id; + + // log metric, params, and tags via logBatch + await this.runClient.logBatch(run_id, metrics, params, tags); + + // log model + // (model gets passed in as a JS object, not JSON - it gets JSON stringified here after adding a run_id property) + if (model) { + model.run_id = run_id; + let model_json = JSON.stringify(model); + await this.runClient.logModel(run_id, model_json); + } + + // updateRun to finish it + const latestRun = await this.runClient.updateRun(run_id, 'FINISHED'); + + return latestRun; + } + + /** + * Full workflow of creating, naming and starting a run under a new experiment, + * logging metrics, params, and tags, logging the model, and finishing the run. + * + * @param {string} experiment_name Name of the experiment under which to log the run. (required) + * @param {string} run_name Name of the run to be created and run (optional) + * @param {Array<{key: string, value: number, timestamp: number, step?: number}>} [metrics] The metrics to log (up to 1000 metrics) (optional) + * @param {Array<{key: string, value: string}>} [params] The params to log (up to 100 params) (optional) + * @param {Array<{key: string, value: string}>} [tags] The tags to log (up to 100 tags) (optional) + * @param {Object} model The ML model data to log to the run, represented as a Javascript object (optional) + * @returns {Promise} The created run object with updated metadata + */ + async runNewExperiment( + experiment_name, + run_name = null, + metrics = [], + params = [], + tags = [], + model + ) { + if (!experiment_name) { + throw new Error('Experiment name is required'); + } + + let experiment_id = await this.experimentClient.createExperiment( + experiment_name + ); + + // create run + const run = await this.runClient.createRun(experiment_id, run_name, tags); + const run_id = run.info.run_id; + + // log metric, params, and tags via logBatch + await this.runClient.logBatch(run_id, metrics, params, tags); + + // log model + // (model gets passed in as a JS object, not JSON - it gets JSON stringified here after adding a run_id property) + model.run_id = run_id; + let model_json = JSON.stringify(model); + await this.runClient.logModel(run_id, model_json); + + // updateRun to finish it + const latest_run = await this.runClient.updateRun(run_id, 'FINISHED'); + + return latest_run; + } + + /** + * Returns an array of all the passed-in experiment's runs, sorted according to the passed-in metric + * + * @param {string} experiment_id The experiment whose runs will be evaluated (required) + * @param {string} primaryMetric The metric by which the results array will be sorted + * @param {string | number} order Sort order for the array: pass in 'DESC' or 1 for descending; 'ASC' or -1 for ascending + * @returns Promise> An array of run objects belonging to the passed-in experiment ID, sorted according to the primary metric + */ + async experimentSummary(experiment_id, primaryMetric, order) { + // use Search Runs to return all runs whose experiment ID matches the passed in one + // use Search Runs's order_by field to sort results array by primaryMetric + let orderString; + if (order === 1 || order === 'DESC') orderString = 'DESC'; + else if (order === -1 || order === 'ASC') orderString = 'ASC'; + const arg = `metrics.${primaryMetric} ${orderString}`; + const data = await this.runClient.searchRuns( + [experiment_id], + undefined, + undefined, + undefined, + [arg] + ); + return data.runs; + } +} + +export default ExperimentManager; From d25153ede1e6acdb4e1b73044f3f7b33c6a792c1 Mon Sep 17 00:00:00 2001 From: Kyler-Chiago Date: Thu, 3 Oct 2024 18:50:58 -0700 Subject: [PATCH 126/357] yes --- mlflow/tests/ModelManagerTest.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mlflow/tests/ModelManagerTest.ts b/mlflow/tests/ModelManagerTest.ts index b53b6211..3f0bbd89 100644 --- a/mlflow/tests/ModelManagerTest.ts +++ b/mlflow/tests/ModelManagerTest.ts @@ -118,7 +118,7 @@ async function testModelManager() { // const bestModel = await modelManager.createModelFromRunWithBestMetric( // ) - // console.log(`Created ${modelName} from run with best metric`) + // console.log(`Created ${modelName} from run with best metric`); } testModelManager(); From aa6b8ef68bae1344d094d087ef045b1136355702 Mon Sep 17 00:00:00 2001 From: Kyler-Chiago Date: Thu, 3 Oct 2024 18:51:51 -0700 Subject: [PATCH 127/357] update comments --- mlflow/tests/ModelManagerTest.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mlflow/tests/ModelManagerTest.ts b/mlflow/tests/ModelManagerTest.ts index 3f0bbd89..a9689295 100644 --- a/mlflow/tests/ModelManagerTest.ts +++ b/mlflow/tests/ModelManagerTest.ts @@ -117,7 +117,7 @@ async function testModelManager() { console.log('9. Creating model from run with best metric...'); // const bestModel = await modelManager.createModelFromRunWithBestMetric( - // ) + // ); // console.log(`Created ${modelName} from run with best metric`); } From 65206db08a375b5985474ac808898c0386901879 Mon Sep 17 00:00:00 2001 From: Kyler-Chiago Date: Thu, 3 Oct 2024 18:55:39 -0700 Subject: [PATCH 128/357] removed some old js files --- mlflow/src/workflows/ModelManager.js | 183 --------------------------- mlflow/tests/RunClientTestKyler.js | 43 ------- mlflow/tests/RunManagerTestFile.js | 50 -------- 3 files changed, 276 deletions(-) delete mode 100644 mlflow/src/workflows/ModelManager.js delete mode 100644 mlflow/tests/RunClientTestKyler.js delete mode 100644 mlflow/tests/RunManagerTestFile.js diff --git a/mlflow/src/workflows/ModelManager.js b/mlflow/src/workflows/ModelManager.js deleted file mode 100644 index e01ab0cf..00000000 --- a/mlflow/src/workflows/ModelManager.js +++ /dev/null @@ -1,183 +0,0 @@ -import { ModelRegistry } from '../model-registry/model_registry.js'; -import { ModelVersionManagement } from '../model-registry/model_version_management.js'; - -class ModelManager { - constructor(trackingUri) { - this.trackingUri = trackingUri; - this.modelRegistry = new ModelRegistry(trackingUri); - this.modelVersionManagement = new ModelVersionManagement(trackingUri); - } - - /** - * Description - Creates a new registered model and creates the first version of that model. - * @param {string} name - Name of the registered model. (Required) - * @param {string} versionSource - URI indicating the location of the model artifacts. (Required) - * @param {string} versionRun_id - MLflow run ID for correlation, if versionSource was generated - * by an experiment run in MLflow tracking server. - * @returns {Promise} - the updated model version object - */ - async createRegisteredModelWithVersion(name, versionSource, versionRun_id) { - await this.modelRegistry.createRegisteredModel(name); - const response = await this.modelVersionManagement.createModelVersion( - name, - versionSource, - versionRun_id - ); - return response; - } - - /** - * Description - Updates a registered model's description and tag. - * @param {string} name - Name of the registered model. (Required) - * @param {string} tagKey - Name of the tag. (Required) - * @param {string} tagValue - String value of the tag being logged. (Required) - * @param {string} description - Description of the registered model. - * @returns {Promise} - the updated registered model object - */ - async updateRegisteredModelDescriptionAndTag( - name, - tagKey, - tagValue, - description - ) { - await this.modelRegistry.setRegisteredModelTag(name, tagKey, tagValue); - const response = await this.modelRegistry.updateRegisteredModel( - name, - description - ); - return response; - } - - /** - * Description - Updates the latest version of the specified registered model's description. - * And adds a new alias, and tag key/value for that latest version. - * @param {string} name - Name of the registered model. (Required) - * @param {string} alias - Name of the alias. (Required) - * @param {string} description - The description for the model version. (Required) - * @param {string} key - Name of the tag. (Required) - * @param {string} value - Name of the value of the tag being logged. (Required) - * @returns {Promise} - the updated model version object - */ - async updateAllLatestModelVersion(name, alias, description, key, value) { - const data = await this.modelRegistry.getLatestModelVersions(name); - if (!data) { - throw new Error('Model has no version to update.'); - } else { - const [{ version }] = data; - await this.modelRegistry.setRegisteredModelAlias(name, alias, version); - await this.modelVersionManagement.setModelVersionTag( - name, - version, - key, - value - ); - const response = await this.modelVersionManagement.updateModelVersion( - name, - version, - description - ); - return response; - } - } - - /** - * Description - Adds a new tag key/value for the latest version of the specified registered model. - * @param {string} name - Name of the registered model. (Required) - * @param {string} key - Name of the tag. (Required) - * @param {string} value - Name of the value of the tag being logged. (Required) - * @returns {Promise} - a promise that resolves when the model version is deleted - */ - async setLatestModelVersionTag(name, key, value) { - const data = await this.modelRegistry.getLatestModelVersions(name); - if (!data) { - throw new Error('Model has no version to set tag for.'); - } else { - const [{ version }] = data; - this.modelVersionManagement.setModelVersionTag(name, version, key, value); - return; - } - } - - /** - * Description - Adds an alias for the latest version of the specified registered model. - * @param {string} name - Name of the registered model. (Required) - * @param {string} alias - Name of the alias. (Required) - * @returns {Promise} - a promise that resolves when the model version is deleted - */ - async setLatestModelVersionAlias(name, alias) { - const data = await this.modelRegistry.getLatestModelVersions(name); - if (!data) { - throw new Error('Model has no version to set alias for.'); - } else { - const [{ version }] = data; - this.modelRegistry.setRegisteredModelAlias(name, alias, version); - return; - } - } - - /** - * Description - Updates the description of the latest version of a registered model. - * @param {string} name - Name of the registered model. (Required) - * @param {string} description - The description for the model version. (Required) - * @returns {Promise} - the updated model version object - */ - async updateLatestModelVersion(name, description) { - const data = await this.modelRegistry.getLatestModelVersions(name); - if (!data) { - throw new Error('Model has no version to set description for.'); - } else { - const [{ version }] = data; - const response = await this.modelVersionManagement.updateModelVersion( - name, - version, - description - ); - return response; - } - } - - /** - * Description - Updates the specified version of the specified registered model's description. - * And adds a new alias, and tag key/value for that specified version. - * @param {string} name - Name of the registered model. (Required) - * @param {string} version - Model version number. (Required) - * @param {string} alias - Name of the alias. (Required) - * @param {string} description - The description for the model version. (Required) - * @param {string} key key - Name of the tag. (Required) - * @param {string} value - Name of the value of the tag being logged. (Required) - * @returns {Promise} - the updated model version object - */ - async updateAllModelVersion(name, version, alias, description, key, value) { - await this.modelRegistry.setRegisteredModelAlias(name, alias, version); - await this.modelVersionManagement.setModelVersionTag( - name, - version, - key, - value - ); - const response = await this.modelVersionManagement.updateModelVersion( - name, - version, - description - ); - return response; - } - - /** - * Description - Deletes the latest version of the specified registered model. - * @param {string} name - the model name - * @returns {Promise} - a promise that resolves when the model version is deleted - */ - async deleteLatestModelVersion(name) { - const data = await this.modelRegistry.getLatestModelVersions(name); - if (!data) { - throw new Error('Model has no version to delete.'); - } else { - const [{ version }] = data; - this.modelVersionManagement.deleteModelVersion(name, version); - return; - } - } -} - -export { ModelManager }; diff --git a/mlflow/tests/RunClientTestKyler.js b/mlflow/tests/RunClientTestKyler.js deleted file mode 100644 index 402c8400..00000000 --- a/mlflow/tests/RunClientTestKyler.js +++ /dev/null @@ -1,43 +0,0 @@ -import { RunManagement } from '../src/tracking/run_management.js'; - -let domain = 'http://localhost:'; -const port = 5001; -if (port) { - domain = domain + port; -} - -const version = '2.0'; - -const MLFLOW_TRACKING_URI = domain + '/api/' + version + '/mlflow'; - -const path = 'artifacts'; - -let runManagement = new RunManagement(MLFLOW_TRACKING_URI, path); -// console.log(runManagement.searchRuns(['784321942139901150'])); - -const test = async () => { - // console.log('hi'); - try { - let data = await runManagement.searchRuns(['784321942139901150']); - console.log('data: ', data); - } catch (err) { - console.log('err: ', err); - } -}; - -test(); - -// let runManagement = new RunManagement(MLFLOW_TRACKING_URI, path); -// console.log(runManagement.listArtifacts('b3457c87f50440388da9d9ddabb1baaa', 'mlflow-artifacts:/784321942139901150/b3457c87f50440388da9d9ddabb1baaa/artifacts/iris_model')); -// console.log(runManagement.listArtifacts('b3457c87f50440388da9d9ddabb1baaa')); -// console.log(runManagement.searchRuns(['784321942139901150'])); -// console.log(runManagement.searchRuns()); -// console.log(runManagement.getMetricHistory('b3457c87f50440388da9d9ddabb1baaa', 'accuracy')); -// console.log(runManagement.logParam('b3457c87f50440388da9d9ddabb1baaa','test2', '008')); -// console.log(runManagement.setTag('b3457c87f50440388da9d9ddabb1baaa', 'testTag1', 'testTag1Val')) -// console.log(runManagement.deleteTag('b3457c87f50440388da9d9ddabb1baaa', 'testTag1')) - -// let modelRegistry = new ModelRegistry(MLFLOW_TRACKING_URI); -// console.log(modelRegistry.setRegisteredModelAlias('tracking-quickstart', 'aliasTest', '1')); -// console.log(modelRegistry.deleteRegisteredModelAlias('tracking-quickstart', 'aliasTest')); -// console.log(modelRegistry.getModelVersionByAlias('sk-learn-random-forest-reg-model', 'the_best_model_ever')); diff --git a/mlflow/tests/RunManagerTestFile.js b/mlflow/tests/RunManagerTestFile.js deleted file mode 100644 index 03504dc6..00000000 --- a/mlflow/tests/RunManagerTestFile.js +++ /dev/null @@ -1,50 +0,0 @@ -import { RunManager } from '../src/workflows/RunManager.js'; -import { RunClient } from '../src/tracking/RunClient.js'; - -const trackingUri = 'http://127.0.0.1:5000'; -const path = '/api/2.0/mlflow'; - -// const ab = new Abstraction(trackingUri, path); -const ab = new RunManager(trackingUri); -const myRunClient = new RunClient(trackingUri); - -// // testing searchRuns method -// const runs = await myRunClient.searchRuns( -// ['284209273010848955'], -// 'metrics.loss > 0.2', -// 'loss' -// ); -// console.log('Search runs result: ', runs); - -// // // dry run (simulation) -// try { -// const result = await ab.cleanupRuns( -// ['284209273010848955'], -// 'metrics.loss > 0.2', -// 'loss' -// ); -// console.log(result); -// } catch (error) { -// console.error('Error: ', error.message, error.stack); -// } - -// // delete runs -// try { -// const result = await ab.cleanupRuns( -// ['463611670721534538'], -// 'metrics.mae > 2', -// true -// ); -// console.log(result); -// } catch (error) { -// console.error('Error: ', error.message, error.stack); -// } - -/************************************************************** */ - -// // copy run -// await ab.copyRun('ccef2857b95847d4b4f208d1b57b789a', '463611670721534538'); - -// // check tags -// const run = await myRunClient.getRun('967234581cd24677a355d3987dad7b5d'); -// console.log(run.data.tags); From 9ddded1b91ab93d2033c3f2aa50b441fec2cc060 Mon Sep 17 00:00:00 2001 From: Kyler-Chiago Date: Thu, 3 Oct 2024 18:59:05 -0700 Subject: [PATCH 129/357] uncommented relevant code from ModelManager that uses RunClient --- mlflow/src/workflows/ModelManager.ts | 109 ++++++++++++++------------- 1 file changed, 55 insertions(+), 54 deletions(-) diff --git a/mlflow/src/workflows/ModelManager.ts b/mlflow/src/workflows/ModelManager.ts index 55438f06..dc2defec 100644 --- a/mlflow/src/workflows/ModelManager.ts +++ b/mlflow/src/workflows/ModelManager.ts @@ -1,4 +1,4 @@ -// import RunClient from '@tracking/RunClient'; +import RunClient from '@tracking/RunClient'; import ModelRegistryClient from '@model-registry/ModelRegistryClient'; import ModelVersionClient from '@model-registry/ModelVersionClient'; import { ApiError } from '@utils/apiError'; @@ -6,11 +6,12 @@ import { ApiError } from '@utils/apiError'; class ModelManager { private modelRegistry: ModelRegistryClient; private modelVersion: ModelVersionClient; + private runClient: RunClient; constructor(trackingUri: string) { this.modelRegistry = new ModelRegistryClient(trackingUri); this.modelVersion = new ModelVersionClient(trackingUri); - // this.runClient = new RunClient(trackingUri); + this.runClient = new RunClient(trackingUri); } /** @@ -309,58 +310,58 @@ class ModelManager { * @returns {Promise} * @throws {ApiError | Error} If request fails */ - // async createModelFromRunWithBestMetric( - // experiment_ids: string[], - // filterMetric: string, - // metricMinOrMax: string, - // modelName: string - // ): Promise { - // try { - // const { runs } = await this.runClient.searchRuns( - // experiment_ids, - // `metrics.${filterMetric} != -99999` - // ); - // let num; - // if (metricMinOrMax === 'min') { - // num = Infinity; - // } else if (metricMinOrMax === 'max') { - // num = -Infinity; - // } - // let bestRun; - // for (let i = 0; i < runs.length; i++) { - // for (let x = 0; x < runs[i].data.metrics.length; x++) { - // if (runs[i].data.metrics[x].key === `${filterMetric}`) { - // if ( - // metricMinOrMax === 'min' && - // num > runs[i].data.metrics[x].value - // ) { - // num = runs[i].data.metrics[x].value; - // bestRun = runs[i]; - // } else if ( - // metricMinOrMax === 'max' && - // num < runs[i].data.metrics[x].value - // ) { - // num = runs[i].data.metrics[x].value; - // bestRun = runs[i]; - // } - // } - // } - // } - // await this.modelRegistry.createRegisteredModel(modelName); - // await this.modelVersion.createModelVersion( - // modelName, - // bestRun.info.artifact_uri, - // bestRun.info.run_id - // ); - // return - // } catch (error) { - // if (error instanceof ApiError) { - // console.error(`API Error (${error.statusCode}): ${error.message}`); - // } else { - // console.error('An unexpected error occurred:', error); - // } - // } - // } + async createModelFromRunWithBestMetric( + experiment_ids: string[], + filterMetric: string, + metricMinOrMax: string, + modelName: string + ): Promise { + try { + const { runs } = await this.runClient.searchRuns( + experiment_ids, + `metrics.${filterMetric} != -99999` + ); + let num; + if (metricMinOrMax === 'min') { + num = Infinity; + } else if (metricMinOrMax === 'max') { + num = -Infinity; + } + let bestRun; + for (let i = 0; i < runs.length; i++) { + for (let x = 0; x < runs[i].data.metrics.length; x++) { + if (runs[i].data.metrics[x].key === `${filterMetric}`) { + if ( + metricMinOrMax === 'min' && + num > runs[i].data.metrics[x].value + ) { + num = runs[i].data.metrics[x].value; + bestRun = runs[i]; + } else if ( + metricMinOrMax === 'max' && + num < runs[i].data.metrics[x].value + ) { + num = runs[i].data.metrics[x].value; + bestRun = runs[i]; + } + } + } + } + await this.modelRegistry.createRegisteredModel(modelName); + await this.modelVersion.createModelVersion( + modelName, + bestRun.info.artifact_uri, + bestRun.info.run_id + ); + return + } catch (error) { + if (error instanceof ApiError) { + console.error(`API Error (${error.statusCode}): ${error.message}`); + } else { + console.error('An unexpected error occurred:', error); + } + } + } } export { ModelManager }; From 309f64953ae6688718ca082eb45f47c83673ce03 Mon Sep 17 00:00:00 2001 From: Yiqun Zheng <16813562+yiqunzheng@users.noreply.github.com> Date: Thu, 3 Oct 2024 19:33:38 -0700 Subject: [PATCH 130/357] small docs revision --- mlflow/docs/tech-design-doc.md | 1 + mlflow/docs/typescript-code-standards.md | 88 ------------------------ 2 files changed, 1 insertion(+), 88 deletions(-) delete mode 100644 mlflow/docs/typescript-code-standards.md diff --git a/mlflow/docs/tech-design-doc.md b/mlflow/docs/tech-design-doc.md index de422410..aa6b81e5 100644 --- a/mlflow/docs/tech-design-doc.md +++ b/mlflow/docs/tech-design-doc.md @@ -46,6 +46,7 @@ mlflow-js/ │ └── index.ts ├── tests/ ├── lib/ +│ └── index.js ├── examples/ └── docs/ ``` diff --git a/mlflow/docs/typescript-code-standards.md b/mlflow/docs/typescript-code-standards.md deleted file mode 100644 index 2e4a497e..00000000 --- a/mlflow/docs/typescript-code-standards.md +++ /dev/null @@ -1,88 +0,0 @@ -# TypeScript Code Standards - -## File Structure and Naming -- Use PascalCase for class files (e.g., `ModelRegistryClient.ts`) -- Use camelCase for utility files (e.g., `apiRequest.ts`) -- Use kebab-case for directory names (e.g., `model-registry`) - -## Imports and Exports -- Use named exports for utilities and interfaces -- Use default exports for main classes -- Group and sort imports: - 1. External libraries - 2. Internal modules - 3. Relative imports -- Within each group, sort alphabetically -- For imports from other modules, use the path aliases defined in tsconfig.json -- For imports within the same directory, use relative imports - -## Naming Conventions -- PascalCase for classes and interfaces -- camelCase for methods, variables, and functions -- UPPER_SNAKE_CASE for constants - -## Documentation -- Use JSDoc comments for classes, methods, and functions -- Include parameter descriptions, return types, and thrown exceptions -- Example: - ```typescript - /** - * Creates a new registered model. - * @param {string} name - The name of the model to register - * @param {RegisteredModelTag[]} [tags] - Optional tags for the model - * @param {string} [description] - Optional description for the model - * @returns {Promise} The created registered model object - * @throws {ApiError} If the API request fails - */ - ``` - -## Error Handling Guide - -- For simple API calls, use the ApiError class: - -```typescript -if (!response.ok) { - throw new ApiError( - `Error: ${data.message || response.statusText}`, - response.status - ); -} -``` - -- For complex functions, use try/catch blocks: - -```typescript -try { - // complex operation -} catch (error) { - if (error instanceof ApiError) { - console.error(`API Error (${error.statusCode}): ${error.message}`); - throw error; - } else { - console.error('An unexpected error occurred:', error); - throw new Error; - } -} -``` - -## Asynchronous Code -- Use async/await for asynchronous operations - -## Type Annotations -- Use TypeScript type annotations consistently -- Create interfaces for complex object structures -- Use generics where appropriate - -## Class and Method Structure -- Utilize TypeScript features like access modifiers (public, private) -- Use method signatures with proper TypeScript types - -## Formatting -- Use 2 spaces for indentation -- Use single quotes for strings -- Add semicolons at the end of statements - -## Consistency -- Maintain consistent style and patterns throughout the codebase -- When in doubt, follow the existing patterns in the project - From d260474d1a267b72f09fbf71abd75776fce6e6d1 Mon Sep 17 00:00:00 2001 From: Kyler-Chiago Date: Thu, 3 Oct 2024 19:42:17 -0700 Subject: [PATCH 131/357] before tests for modelManager.createModelFromRunWithBestMetric --- mlflow/tests/ModelManagerTest.ts | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/mlflow/tests/ModelManagerTest.ts b/mlflow/tests/ModelManagerTest.ts index a9689295..2810077c 100644 --- a/mlflow/tests/ModelManagerTest.ts +++ b/mlflow/tests/ModelManagerTest.ts @@ -115,10 +115,10 @@ async function testModelManager() { console.log(`Deleted Latest version of ${modelName}`); console.log('9. Creating model from run with best metric...'); - // const bestModel = await modelManager.createModelFromRunWithBestMetric( + const bestModel = await modelManager.createModelFromRunWithBestMetric( - // ); - // console.log(`Created ${modelName} from run with best metric`); + ); + console.log(`Created ${modelName} from run with best metric`); } testModelManager(); From c99164c4d2d1347eb519a0445476c4c90ea7882e Mon Sep 17 00:00:00 2001 From: Kyler-Chiago Date: Thu, 3 Oct 2024 19:56:24 -0700 Subject: [PATCH 132/357] about to set up tests for modelManager.createModelFromRunWithBestMetric --- mlflow/src/workflows/ModelManager.ts | 3 ++- mlflow/tests/ModelManagerTest.ts | 5 ++++- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/mlflow/src/workflows/ModelManager.ts b/mlflow/src/workflows/ModelManager.ts index dc2defec..ddc47418 100644 --- a/mlflow/src/workflows/ModelManager.ts +++ b/mlflow/src/workflows/ModelManager.ts @@ -305,7 +305,8 @@ class ModelManager { * @param {string[]} experiment_ids - An array containing an experiment id. (Required) * @param {string} filterMetric - The name of the metric that we're filtering by. (Required) * @param {string} metricMinOrMax - A string specifying if we want the minimum or maximum - * value of the specified metric. (Required) + * value of the specified metric. Can be either 'min' or + * 'max'(Required) * @param {string} modelName - The name of the new model that will be created. (Required) * @returns {Promise} * @throws {ApiError | Error} If request fails diff --git a/mlflow/tests/ModelManagerTest.ts b/mlflow/tests/ModelManagerTest.ts index 2810077c..1462fe75 100644 --- a/mlflow/tests/ModelManagerTest.ts +++ b/mlflow/tests/ModelManagerTest.ts @@ -116,7 +116,10 @@ async function testModelManager() { console.log('9. Creating model from run with best metric...'); const bestModel = await modelManager.createModelFromRunWithBestMetric( - + [run.info.experiment_id], + + 'max', + modelName, ); console.log(`Created ${modelName} from run with best metric`); } From 9d12ff51e7b947a53be7f1012d44d2ab0bb52d78 Mon Sep 17 00:00:00 2001 From: Kyler-Chiago Date: Thu, 3 Oct 2024 20:50:22 -0700 Subject: [PATCH 133/357] wrote test for modelManager.createModelFromRunWithBestMetric --- mlflow/tests/ModelManagerTest.ts | 21 ++++++++++++++++++--- 1 file changed, 18 insertions(+), 3 deletions(-) diff --git a/mlflow/tests/ModelManagerTest.ts b/mlflow/tests/ModelManagerTest.ts index 1462fe75..9fd9c856 100644 --- a/mlflow/tests/ModelManagerTest.ts +++ b/mlflow/tests/ModelManagerTest.ts @@ -1,5 +1,6 @@ import { ModelManager } from '../src/workflows/ModelManager'; import { apiRequest } from '../src/utils/apiRequest'; +import RunClient from '../src/tracking/RunClient'; import ModelRegistryClient from '../src/model-registry/ModelRegistryClient'; async function createRun( @@ -27,8 +28,10 @@ async function createRun( async function testModelManager() { const modelRegistryClient = new ModelRegistryClient('http://localhost:5001'); const modelManager = new ModelManager('http://localhost:5001'); + const runClient = new RunClient('http://localhost:5001'); const timestamp = Date.now(); const modelName = `test-model-${timestamp}`; + const modelName2 = `test-model2-${timestamp}`; const modelDescription = `test-model-description-${timestamp}`; const modelTagKey = `test-model-tagKey-${timestamp}`; const modelTagValue = `test-model-tagValue-${timestamp}`; @@ -37,6 +40,8 @@ async function testModelManager() { const modelVersionTagValue = `version_1_value_${timestamp}`; const modelVersionAlias = `version_1_alias_${timestamp}`; const modelVersion = '1'; + const runMetricKey = `test_run_metric_key_${timestamp}`; + const runMetricValue = timestamp; console.log('\n5. Creating a run...'); const run = await createRun(modelRegistryClient, '0'); // Using '0' as the default experiment ID @@ -115,13 +120,23 @@ async function testModelManager() { console.log(`Deleted Latest version of ${modelName}`); console.log('9. Creating model from run with best metric...'); + await runClient.logMetric( + run.info.run_id, + runMetricKey, + runMetricValue + ); + + const runData = await runClient.getRun( + run.info.run_id + ); + const bestModel = await modelManager.createModelFromRunWithBestMetric( [run.info.experiment_id], - + runData.data.metrics[0].key, 'max', - modelName, + modelName2, ); - console.log(`Created ${modelName} from run with best metric`); + console.log(`Created ${modelName2} from run with best metric`); } testModelManager(); From 53557c2fabfe760ca369e2c12ed54d457338712f Mon Sep 17 00:00:00 2001 From: Yiqun Zheng <16813562+yiqunzheng@users.noreply.github.com> Date: Fri, 4 Oct 2024 13:44:58 -0700 Subject: [PATCH 134/357] change modelmanger to default export --- mlflow/src/workflows/ModelManager.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mlflow/src/workflows/ModelManager.ts b/mlflow/src/workflows/ModelManager.ts index 8f42f224..8d1a6e67 100644 --- a/mlflow/src/workflows/ModelManager.ts +++ b/mlflow/src/workflows/ModelManager.ts @@ -355,4 +355,4 @@ class ModelManager { // } } -export { ModelManager }; +export default ModelManager; From a6fb40c98e59aa19a579793eba35f65564f3b7a6 Mon Sep 17 00:00:00 2001 From: Yiqun Zheng <16813562+yiqunzheng@users.noreply.github.com> Date: Fri, 4 Oct 2024 13:45:31 -0700 Subject: [PATCH 135/357] add mlflow.ts --- mlflow/src/mlflow.ts | 84 ++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 84 insertions(+) diff --git a/mlflow/src/mlflow.ts b/mlflow/src/mlflow.ts index e69de29b..bf7fa189 100644 --- a/mlflow/src/mlflow.ts +++ b/mlflow/src/mlflow.ts @@ -0,0 +1,84 @@ +// src/Mlflow.ts + +// import ExperimentClient from './tracking/ExperimentClient'; +import RunClient from './tracking/RunClient'; +import ModelRegistryClient from './model-registry/ModelRegistryClient'; +import ModelVersionClient from './model-registry/ModelVersionClient'; +// import ExperimentManager from './workflows/ExperimentManager'; +import RunManager from './workflows/RunManager'; +import ModelManager from './workflows/ModelManager'; + +class Mlflow { + private components: { + // experimentClient: ExperimentClient; + runClient: RunClient; + modelRegistryClient: ModelRegistryClient; + modelVersionClient: ModelVersionClient; + // experimentManager: ExperimentManager; + runManager: RunManager; + modelManager: ModelManager; + }; + + constructor(trackingUri: string) { + this.components = { + // experimentClient: new ExperimentClient(trackingUri), + runClient: new RunClient(trackingUri), + modelRegistryClient: new ModelRegistryClient(trackingUri), + modelVersionClient: new ModelVersionClient(trackingUri), + // experimentManager: new ExperimentManager(trackingUri), + runManager: new RunManager(trackingUri), + modelManager: new ModelManager(trackingUri), + }; + + this.initializeMethods(); + } + + private initializeMethods(): void { + Object.keys(this.components).forEach((componentName) => { + const component = + this.components[componentName as keyof typeof this.components]; + Object.getOwnPropertyNames(Object.getPrototypeOf(component)) + .filter( + (name) => + typeof (component as any)[name] === 'function' && + name !== 'constructor' + ) + .forEach((methodName) => { + (this as any)[methodName] = (...args: any[]) => + (component as any)[methodName](...args); + }); + }); + } + + // Getter methods for direct access to clients and managers + + // getExperimentClient(): ExperimentClient { + // return this.components.experimentClient; + // } + + getRunClient(): RunClient { + return this.components.runClient; + } + + getModelRegistryClient(): ModelRegistryClient { + return this.components.modelRegistryClient; + } + + getModelVersionClient(): ModelVersionClient { + return this.components.modelVersionClient; + } + + // getExperimentManager(): ExperimentManager { + // return this.components.experimentManager; + // } + + getRunManager(): RunManager { + return this.components.runManager; + } + + getModelManager(): ModelManager { + return this.components.modelManager; + } +} + +export default Mlflow; From d5d6980737c7ab7cab0f6239fce1a0ed07fa5020 Mon Sep 17 00:00:00 2001 From: Yiqun Zheng <16813562+yiqunzheng@users.noreply.github.com> Date: Fri, 4 Oct 2024 13:45:46 -0700 Subject: [PATCH 136/357] add index.ts --- mlflow/src/index.ts | 3 +++ 1 file changed, 3 insertions(+) diff --git a/mlflow/src/index.ts b/mlflow/src/index.ts index e69de29b..3643f61e 100644 --- a/mlflow/src/index.ts +++ b/mlflow/src/index.ts @@ -0,0 +1,3 @@ +import Mlflow from './mlflow'; + +export default Mlflow; From 9be3b898f535044f608c376616c27063ef3c539d Mon Sep 17 00:00:00 2001 From: Kyler-Chiago Date: Sat, 5 Oct 2024 10:40:08 -0700 Subject: [PATCH 137/357] completed modelManager.createModelFromRunWithBestMetric test --- mlflow/tests/ModelManagerTest.ts | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/mlflow/tests/ModelManagerTest.ts b/mlflow/tests/ModelManagerTest.ts index 9fd9c856..03f89430 100644 --- a/mlflow/tests/ModelManagerTest.ts +++ b/mlflow/tests/ModelManagerTest.ts @@ -41,7 +41,8 @@ async function testModelManager() { const modelVersionAlias = `version_1_alias_${timestamp}`; const modelVersion = '1'; const runMetricKey = `test_run_metric_key_${timestamp}`; - const runMetricValue = timestamp; + const runMetricValueHigh = 2; + const runMetricValueLow = 1; console.log('\n5. Creating a run...'); const run = await createRun(modelRegistryClient, '0'); // Using '0' as the default experiment ID @@ -120,10 +121,19 @@ async function testModelManager() { console.log(`Deleted Latest version of ${modelName}`); console.log('9. Creating model from run with best metric...'); + const run2 = await createRun(modelRegistryClient, '0'); // Using '0' as the default experiment ID + console.log('Created run:', run2); + await runClient.logMetric( run.info.run_id, runMetricKey, - runMetricValue + runMetricValueHigh + ); + + await runClient.logMetric( + run2.info.run_id, + runMetricKey, + runMetricValueHigh ); const runData = await runClient.getRun( From 1b3f6b46f9c9431eff424a313197f714e57dec31 Mon Sep 17 00:00:00 2001 From: Kyler-Chiago Date: Sat, 5 Oct 2024 10:52:00 -0700 Subject: [PATCH 138/357] export default ModelManager --- mlflow/src/workflows/ModelManager.ts | 4 ++-- mlflow/tests/ModelManagerTest.ts | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/mlflow/src/workflows/ModelManager.ts b/mlflow/src/workflows/ModelManager.ts index ddc47418..106d6212 100644 --- a/mlflow/src/workflows/ModelManager.ts +++ b/mlflow/src/workflows/ModelManager.ts @@ -316,7 +316,7 @@ class ModelManager { filterMetric: string, metricMinOrMax: string, modelName: string - ): Promise { + ): Promise { try { const { runs } = await this.runClient.searchRuns( experiment_ids, @@ -365,4 +365,4 @@ class ModelManager { } } -export { ModelManager }; +export default ModelManager; diff --git a/mlflow/tests/ModelManagerTest.ts b/mlflow/tests/ModelManagerTest.ts index 03f89430..1eb8d7d0 100644 --- a/mlflow/tests/ModelManagerTest.ts +++ b/mlflow/tests/ModelManagerTest.ts @@ -1,7 +1,7 @@ -import { ModelManager } from '../src/workflows/ModelManager'; import { apiRequest } from '../src/utils/apiRequest'; -import RunClient from '../src/tracking/RunClient'; +import ModelManager from '../src/workflows/ModelManager'; import ModelRegistryClient from '../src/model-registry/ModelRegistryClient'; +import RunClient from '../src/tracking/RunClient'; async function createRun( client: ModelRegistryClient, From 1f844f1a2865ab0b451f8a02b31a7c84899dbba1 Mon Sep 17 00:00:00 2001 From: Austin Fraser Date: Sat, 5 Oct 2024 11:08:53 -0700 Subject: [PATCH 139/357] finished work on refactor --- mlflow/src/tracking/ExperimentClient.ts | 36 ---- mlflow/src/workflows/ExperimentManager.ts | 226 +++++++++++++++------- mlflow/tests/ExperimentManagerTestFile.ts | 110 +++++++++++ 3 files changed, 263 insertions(+), 109 deletions(-) create mode 100644 mlflow/tests/ExperimentManagerTestFile.ts diff --git a/mlflow/src/tracking/ExperimentClient.ts b/mlflow/src/tracking/ExperimentClient.ts index ed51e7ce..5b156ef6 100644 --- a/mlflow/src/tracking/ExperimentClient.ts +++ b/mlflow/src/tracking/ExperimentClient.ts @@ -24,9 +24,6 @@ class ExperimentClient { artifact_location?: string, tags?: Array<{key: string, value: string}> ): Promise { - if (!name) { - throw new Error('Experiment name is required'); - } const { response, data } = await apiRequest( this.trackingUri, @@ -68,12 +65,6 @@ class ExperimentClient { order_by?: string[], view_type?: string ): Promise { - if (!filter) { - throw new Error('Filter is required'); - } - if (!max_results) { - throw new Error('Max results is required'); - } const { response, data } = await apiRequest( this.trackingUri, @@ -106,9 +97,6 @@ class ExperimentClient { async getExperiment( experiment_id: string ): Promise { - if (!experiment_id) { - throw new Error('Experiment ID is required'); - } const { response, data } = await apiRequest( this.trackingUri, @@ -144,9 +132,6 @@ class ExperimentClient { async getExperimentByName( experiment_name: string ): Promise { - if (!experiment_name) { - throw new Error('Experiment name is required'); - } const { response, data } = await apiRequest( this.trackingUri, @@ -179,9 +164,6 @@ class ExperimentClient { async deleteExperiment( experiment_id: string ): Promise { - if (!experiment_id) { - throw new Error('Experiment ID is required'); - } const { response, data } = await apiRequest( this.trackingUri, @@ -214,9 +196,6 @@ class ExperimentClient { async restoreExperiment( experiment_id: string ): Promise { - if (!experiment_id) { - throw new Error('Experiment ID is required'); - } const { response, data } = await apiRequest( this.trackingUri, @@ -251,12 +230,6 @@ class ExperimentClient { experiment_id: string, new_name: string ): Promise { - if (!experiment_id) { - throw new Error('Experiment ID is required'); - } - if (!new_name) { - throw new Error('New name is required'); - } const { response, data } = await apiRequest( this.trackingUri, @@ -295,15 +268,6 @@ class ExperimentClient { key: string, value: string ): Promise { - if (!experiment_id) { - throw new Error('Experiment ID is required'); - } - if (!key) { - throw new Error('Key is required'); - } - if (!value) { - throw new Error('Value is required'); - } const { response, data } = await apiRequest( this.trackingUri, diff --git a/mlflow/src/workflows/ExperimentManager.ts b/mlflow/src/workflows/ExperimentManager.ts index 4c5f9320..4b7648c9 100644 --- a/mlflow/src/workflows/ExperimentManager.ts +++ b/mlflow/src/workflows/ExperimentManager.ts @@ -1,5 +1,9 @@ -import ExperimentClient from '@tracking/ExperimentClient'; -import { RunClient } from '@tracking/RunClient'; +// import ExperimentClient from '@tracking/ExperimentClient'; +import ExperimentClient from '../tracking/ExperimentClient'; +// import RunClient from '@tracking/RunClient'; +import RunClient from '../tracking/RunClient'; +// import { ApiError } from '@utils/apiError'; +import { ApiError } from '../utils/apiError'; class ExperimentManager { private trackingUri: string; @@ -30,30 +34,37 @@ class ExperimentManager { params?: Array<{key: string, value: string}>, tags?: Array<{key: string, value: string}>, model?: {artifact_path: string, flavors: Object, model_url: string, model_uuid: string, utc_time_created: number, mlflow_version: string, run_id?: string} - ) { - if (!experiment_id) { - throw new Error('Experiment ID is required'); + ): Promise { + + try { + // create run + const run = await this.runClient.createRun(experiment_id, run_name); + const run_id = run.info.run_id; + + // log metric, params, and tags via logBatch + await this.runClient.logBatch(run_id, metrics, params, tags); + + // log model + // (model gets passed in as a JS object, not JSON - it gets JSON stringified here after adding a run_id property) + if (model) { + model.run_id = run_id; + let model_json = JSON.stringify(model); + await this.runClient.logModel(run_id, model_json); + } + + // updateRun to finish it + const latestRun = await this.runClient.updateRun(run_id, 'FINISHED'); + + return latestRun; + } catch (error) { + if (error instanceof ApiError) { + console.error(`API Error (${error.statusCode}): ${error.message}`); + throw error; + } else { + console.error('An unexpected error occurred:', error); + throw new Error; + } } - - // create run - const run = await this.runClient.createRun(experiment_id, run_name, tags); - const run_id = run.info.run_id; - - // log metric, params, and tags via logBatch - await this.runClient.logBatch(run_id, metrics, params, tags); - - // log model - // (model gets passed in as a JS object, not JSON - it gets JSON stringified here after adding a run_id property) - if (model) { - model.run_id = run_id; - let model_json = JSON.stringify(model); - await this.runClient.logModel(run_id, model_json); - } - - // updateRun to finish it - const latestRun = await this.runClient.updateRun(run_id, 'FINISHED'); - - return latestRun; } /** @@ -69,63 +80,132 @@ class ExperimentManager { * @returns {Promise} The created run object with updated metadata */ async runNewExperiment( - experiment_name, - run_name = null, - metrics = [], - params = [], - tags = [], - model - ) { - if (!experiment_name) { - throw new Error('Experiment name is required'); + experiment_name: string, + run_name: string, + metrics: Array<{key: string, value: number, timestamp: number, step?: number}>, + params?: Array<{key: string, value: string}>, + tags?: Array<{key: string, value: string}>, + model?: {artifact_path: string, flavors: Object, model_url: string, model_uuid: string, utc_time_created: number, mlflow_version: string, run_id?: string} + ): Promise { + + try { + let experiment_id = await this.experimentClient.createExperiment(experiment_name); + + // create run + const run = await this.runClient.createRun(experiment_id, run_name); + const run_id = run.info.run_id; + + // log metric, params, and tags via logBatch + await this.runClient.logBatch(run_id, metrics, params, tags); + + // log model + // (model gets passed in as a JS object, not JSON - it gets JSON stringified here after adding a run_id property) + if (model) { + model.run_id = run_id; + let model_json = JSON.stringify(model); + await this.runClient.logModel(run_id, model_json); + } + + // updateRun to finish it + const latest_run = await this.runClient.updateRun(run_id, 'FINISHED'); + + return latest_run; + } + catch (error) { + if (error instanceof ApiError) { + console.error(`API Error (${error.statusCode}): ${error.message}`); + throw error; + } else { + console.error('An unexpected error occurred:', error); + throw new Error; + } } - - let experiment_id = await this.experimentClient.createExperiment( - experiment_name - ); - - // create run - const run = await this.runClient.createRun(experiment_id, run_name, tags); - const run_id = run.info.run_id; - - // log metric, params, and tags via logBatch - await this.runClient.logBatch(run_id, metrics, params, tags); - - // log model - // (model gets passed in as a JS object, not JSON - it gets JSON stringified here after adding a run_id property) - model.run_id = run_id; - let model_json = JSON.stringify(model); - await this.runClient.logModel(run_id, model_json); - - // updateRun to finish it - const latest_run = await this.runClient.updateRun(run_id, 'FINISHED'); - - return latest_run; } /** * Returns an array of all the passed-in experiment's runs, sorted according to the passed-in metric * * @param {string} experiment_id The experiment whose runs will be evaluated (required) - * @param {string} primaryMetric The metric by which the results array will be sorted + * @param {string} primaryMetric The metric by which the results array will be sorted (required) * @param {string | number} order Sort order for the array: pass in 'DESC' or 1 for descending; 'ASC' or -1 for ascending - * @returns Promise> An array of run objects belonging to the passed-in experiment ID, sorted according to the primary metric + * @returns {Promise>} An array of run objects belonging to the passed-in experiment ID, sorted according to the primary metric */ - async experimentSummary(experiment_id, primaryMetric, order) { - // use Search Runs to return all runs whose experiment ID matches the passed in one - // use Search Runs's order_by field to sort results array by primaryMetric - let orderString; - if (order === 1 || order === 'DESC') orderString = 'DESC'; - else if (order === -1 || order === 'ASC') orderString = 'ASC'; - const arg = `metrics.${primaryMetric} ${orderString}`; - const data = await this.runClient.searchRuns( - [experiment_id], - undefined, - undefined, - undefined, - [arg] - ); - return data.runs; + + async experimentSummary( + experiment_id: string, + primaryMetric: string, + order?: 'ASC' | 'DESC' | 1 | -1 + ): Promise { + + try { + interface RunInfo { + run_id: string; + run_name: string; + experiment_id: string; + status: string; + start_time: number; + end_time: number; + artifact_uri: string; + lifecycle_stage: string; + } + + interface RunData { + metrics: Array<{ key: string; value: number; timestamp: number; step?: number }>; + params: Array<{ key: string; value: string }>; + tags: Array<{ key: string; value: string }>; + } + + interface Run { + info: RunInfo; + data: RunData; + inputs: Array<{ + tags?: Array<{ key: string; value: string }>; + dataset: { + name: string; + digest: string; + source_type: string; + source: string; + schema?: string; + profile?: string; + }; + }>; + [key: string]: any; // Allow dynamic keys like primaryMetric + } + + // use Search Runs to return all runs whose experiment ID matches the passed in one + // use Search Runs's order_by field to sort results array by primaryMetric + let orderString; + if (order === 1 || order === 'DESC') orderString = 'DESC'; + else if (order === -1 || order === 'ASC') orderString = 'ASC'; + const arg = `metrics.${primaryMetric} ${orderString}`; + const data = await this.runClient.searchRuns( + [experiment_id], + '', + undefined, + undefined, + [arg] + ); + + data.runs.forEach((el: Run) => { + const arr = el.data.metrics; + let val: number | undefined; + arr.forEach((obj: {key: string, value: number, timestamp: number, step?: number}) => { + if (obj.key === primaryMetric) val = obj.value; + }) + el[primaryMetric] = val; + }); + + return data.runs; + } + catch (error) { + if (error instanceof ApiError) { + console.error(`API Error (${error.statusCode}): ${error.message}`); + throw error; + } else { + console.error('An unexpected error occurred:', error); + throw new Error; + } + } } } diff --git a/mlflow/tests/ExperimentManagerTestFile.ts b/mlflow/tests/ExperimentManagerTestFile.ts new file mode 100644 index 00000000..e55fc7c9 --- /dev/null +++ b/mlflow/tests/ExperimentManagerTestFile.ts @@ -0,0 +1,110 @@ +import ExperimentManager from '../src/workflows/ExperimentManager.js'; +import ExperimentClient from '../src/tracking/ExperimentClient.js'; +const MLFLOW_TRACKING_URI = 'http://localhost:5001'; +const experimentManager = new ExperimentManager(MLFLOW_TRACKING_URI); +const experimentClient = new ExperimentClient(MLFLOW_TRACKING_URI); + +const testRunExistingExperiment = async () => { + // define fake data for metrics, params, tags, and model + const metrics = [ + { key: 'metric1', value: 0.111, timestamp: Date.now() }, + { key: 'metric2', value: 0.222, timestamp: Date.now() }, + ]; + const params = [ + { key: 'testParam', value: 'testParamValue' }, + { key: 'testParam2', value: 'testParamValue2' }, + ]; + const tags = [ + { key: 'testKey', value: 'testValue' }, + { key: 'testKey2', value: 'testValue2' }, + ]; + const model = { + artifact_path: 'model', + flavors: { + python_function: { + model_path: 'model.pkl', + loader_module: 'mlflow.sklearn', + python_version: '3.8.10', + }, + }, + model_url: 'STRING', + model_uuid: 'STRING', + utc_time_created: Date.now(), + mlflow_version: 'STRING', + }; + + // construct random name to avoid duplicate names in the tracking server + const num = Math.random().toString().slice(2, 11); + const name = `Test experiment ${num}`; + + // pass the randomized name into .createExperiment to create a new experiment. this stores its experiment ID under the 'exp' variable + const exp = await experimentClient.createExperiment(name); + + // call .runExistingExperiment on our newly created experiment, passing in the fake data, and store the results under the variable 'log' + const log = await experimentManager.runExistingExperiment( + exp, + undefined, + metrics, + params, + tags, + model + ); + return console.log(log); +}; +// testRunExistingExperiment(); + +const testRunNewExperiment = async () => { + // define fake data for metrics, params, tags, and model + const metrics = [ + { key: 'metric1', value: 0.9, timestamp: Date.now() }, + { key: 'metric2', value: 0.222, timestamp: Date.now() }, + ]; + const params = [ + { key: 'testParam', value: 'testParamValue' }, + { key: 'testParam2', value: 'testParamValue2' }, + ]; + const tags = [ + { key: 'testKey', value: 'testValue' }, + { key: 'testKey2', value: 'testValue2' }, + ]; + const model = { + artifact_path: 'model', + flavors: { + python_function: { + model_path: 'model.pkl', + loader_module: 'mlflow.sklearn', + python_version: '3.8.10', + }, + }, + model_url: 'STRING', + model_uuid: 'STRING', + utc_time_created: Date.now(), + mlflow_version: 'STRING', + }; + + // construct random name to avoid duplicate names in the tracking server + const num = Math.random().toString().slice(2, 11); + const name = `Test experiment ${num}`; + + // call .runNewExperiment using our randomly generated name, passing in the fake data, and store the results under the variable 'log' + const log = await experimentManager.runNewExperiment( + name, + '', + metrics, + params, + tags, + model + ); + return console.log(log); +}; +// testRunNewExperiment(); + +const testExperimentSummary = async () => { + const log = await experimentManager.experimentSummary( + '787867007534323476', + 'metric1', + 'DESC' + ); + return console.log(log); +}; +testExperimentSummary(); From 1d04d7c92ffa0236ad6287890c475f8d7bb30acd Mon Sep 17 00:00:00 2001 From: Austin Fraser Date: Sat, 5 Oct 2024 11:36:18 -0700 Subject: [PATCH 140/357] fixed import issue, was working in wrong directory so dependencies werent installing in right place --- mlflow/src/tracking/ExperimentClient.js | 281 -------------- mlflow/src/tracking/ExperimentClient.ts | 8 +- mlflow/src/tracking/experiment_management.js | 372 ------------------- mlflow/src/workflows/ExperimentManager.js | 127 ------- mlflow/src/workflows/ExperimentManager.ts | 12 +- mlflow/tests/ExperimentClient_testFile.js | 118 ------ mlflow/tests/ExperimentManagerTestFile.ts | 4 +- mlflow/tests/ExperimentManager_testFile.js | 110 ------ 8 files changed, 12 insertions(+), 1020 deletions(-) delete mode 100644 mlflow/src/tracking/ExperimentClient.js delete mode 100644 mlflow/src/tracking/experiment_management.js delete mode 100644 mlflow/src/workflows/ExperimentManager.js delete mode 100644 mlflow/tests/ExperimentClient_testFile.js delete mode 100644 mlflow/tests/ExperimentManager_testFile.js diff --git a/mlflow/src/tracking/ExperimentClient.js b/mlflow/src/tracking/ExperimentClient.js deleted file mode 100644 index 7af488f3..00000000 --- a/mlflow/src/tracking/ExperimentClient.js +++ /dev/null @@ -1,281 +0,0 @@ -class ExperimentClient { - constructor(trackingUri) { - this.trackingUri = trackingUri; - } - - /** - * Create an experiment with a name. Returns the ID of the newly created experiment. - * Validates that another experiment with the same name does not already exist and fails if another experiment with the same name already exists. - * - * @param {string} name Experiment name. (required) - * @param {string} artifact_location Optional location where all artifacts for the experiment are stored. If not provided, the remote server will select an appropriate default. - * @param {Array<{key: string, value: string}>} tags Optional collection of tags to set on the experiment. - * @returns {Promise} Returns the ID of the newly created experiment in an object. - */ - async createExperiment(name, artifact_location = '', tags = []) { - if (!name) { - throw new Error('Experiment name is required'); - } - - const url = `${this.trackingUri}/api/2.0/mlflow/experiments/create`; - const response = await fetch(url, { - method: 'POST', - headers: { 'Content-Type': 'application/json' }, - body: JSON.stringify({ name, artifact_location, tags }), - }); - - if (!response.ok) { - const errorBody = await response.json(); - throw new Error( - `Error creating experiment from tracking server, status: ${response.status}. ${errorBody.message}` - ); - } - - const data = await response.json(); - // console.log('return from createExperiment: ', data.experiment_id); - return data.experiment_id; - } - - /** - * Search experiments. - * - * @param {string} filter A filter expression over experiment attributes and tags that allows returning a subset of experiments. The syntax is a subset of SQL. (required) - * @param {int64} max_results Maximum number of experiments desired. (required) - * @param {string} page_token Optional token indicating the page of experiments to fetch. - * @param {Array} order_by Optional list of columns for ordering search results. - * @param {string} view_type Optional qualifier for type of experiments to be returned. See https://mlflow.org/docs/latest/rest-api.html#mlflowviewtype - * @returns {Promise} Returns object containing an array of experiment objects matching the filter, - * and optionally a next_page_token that can be used to retrieve the next page of experiments. - */ - async searchExperiment( - filter, - max_results, - page_token = '', - order_by = [], - view_type = '' - ) { - if (!filter) { - throw new Error('Filter is required'); - } - if (!max_results) { - throw new Error('Max results is required'); - } - - const url = `${this.trackingUri}/api/2.0/mlflow/experiments/search`; - const response = await fetch(url, { - method: 'POST', - headers: { 'Content-Type': 'application/json' }, - body: JSON.stringify({ - filter, - max_results, - page_token, - order_by, - view_type, - }), - }); - - if (!response.ok) { - const errorBody = await response.json(); - throw new Error( - `Error searching for experiment from tracking server, status: ${response.status}. ${errorBody.message}` - ); - } - - const data = await response.json(); - // console.log('return from searchExperiment: ', data); - return data; - } - - /** - * Get metadata for an experiment, querying by experiment ID. This method works on deleted experiments. - * - * @param {string} experiment_id ID of the associated experiment. (required) - * @returns {Promise} Returns object containing the matched experiment. - */ - async getExperiment(experiment_id) { - if (!experiment_id) { - throw new Error('Experiment ID is required'); - } - - const url = `${this.trackingUri}/api/2.0/mlflow/experiments/get?experiment_id=${experiment_id}`; - const response = await fetch(url, { - method: 'GET', - headers: { 'Content-Type': 'application/json' }, - }); - - if (!response.ok) { - const errorBody = await response.json(); - throw new Error( - `Error getting experiment from tracking server, status: ${response.status}. ${errorBody.message}` - ); - } - - const data = await response.json(); - // console.log('return from getExperiment: ', data.experiment); - return data.experiment; - } - - /** - * Get metadata for an experiment, querying by experiment name. - * This endpoint will return deleted experiments, - * but prefers the active experiment if an active and deleted experiment share the same name. - * If multiple deleted experiments share the same name, the API will return one of them. - * - * @param {string} experiment_name ID of the associated experiment. (required) - * @returns {Promise} Returns object containing the matched experiment. - */ - async getExperimentByName(experiment_name) { - if (!experiment_name) { - throw new Error('Experiment name is required'); - } - - const url = `${this.trackingUri}/api/2.0/mlflow/experiments/get-by-name?experiment_name=${experiment_name}`; - const response = await fetch(url, { - method: 'GET', - headers: { 'Content-Type': 'application/json' }, - }); - - if (!response.ok) { - const errorBody = await response.json(); - throw new Error( - `Error getting experiment by name from tracking server, status: ${response.status}. ${errorBody.message}` - ); - } - - const data = await response.json(); - // console.log('return from getExperimentByName: ', data.experiment); - return data.experiment; - } - - /** - * Mark an experiment for deletion. - * - * @param {string} experiment_id ID of the associated experiment. (required) - * @returns {void} - */ - async deleteExperiment(experiment_id) { - if (!experiment_id) { - throw new Error('Experiment ID is required'); - } - - const url = `${this.trackingUri}/api/2.0/mlflow/experiments/delete`; - const response = await fetch(url, { - method: 'POST', - headers: { 'Content-Type': 'application/json' }, - body: JSON.stringify({ experiment_id }), - }); - - if (!response.ok) { - const errorBody = await response.json(); - throw new Error( - `Error deleting experiment from tracking server, status: ${response.status}. ${errorBody.message}` - ); - } - - console.log(`Experiment ID ${experiment_id} successfully deleted`); - // return `Experiment ID ${experiment_id} successfully deleted`; - } - - /** - * Restore an experiment marked for deletion. - * - * @param {string} experiment_id ID of the associated experiment. (required) - * @returns {void} - */ - async restoreExperiment(experiment_id) { - if (!experiment_id) { - throw new Error('Experiment ID is required'); - } - - const url = `${this.trackingUri}/api/2.0/mlflow/experiments/restore`; - const response = await fetch(url, { - method: 'POST', - headers: { 'Content-Type': 'application/json' }, - body: JSON.stringify({ experiment_id }), - }); - - if (!response.ok) { - const errorBody = await response.json(); - throw new Error( - `Error restoring experiment from tracking server, status: ${response.status}. ${errorBody.message}` - ); - } - - console.log(`Experiment ID ${experiment_id} successfully restored`); - // return `Experiment ID ${experiment_id} successfully restored`; - } - - /** - * Update experiment name. - * - * @param {string} experiment_id ID of the associated experiment. (required) - * @param {string} new_name The experiment’s name is changed to the new name. The new name must be unique. (required) - * @returns {void} - */ - async updateExperiment(experiment_id, new_name) { - if (!experiment_id) { - throw new Error('Experiment ID is required'); - } - if (!new_name) { - throw new Error('New name is required'); - } - - const url = `${this.trackingUri}/api/2.0/mlflow/experiments/update`; - const response = await fetch(url, { - method: 'POST', - headers: { 'Content-Type': 'application/json' }, - body: JSON.stringify({ experiment_id, new_name }), - }); - - if (!response.ok) { - const errorBody = await response.json(); - throw new Error( - `Error updating experiment from tracking server, status: ${response.status}. ${errorBody.message}` - ); - } - - console.log( - `Experiment ID ${experiment_id} successfully updated - new name is ${new_name}` - ); - // return `Experiment ID ${experiment_id} successfully updated - new name is ${new_name}`; - } - - /** - * Set a tag on an experiment. - * - * @param {string} experiment_id ID of the experiment under which to log the tag. (required) - * @param {string} key Name of the tag. (required) - * @param {string} value String value of the tag being logged. (required) - * @returns {void} - */ - async setExperimentTag(experiment_id, key, value) { - if (!experiment_id) { - throw new Error('Experiment ID is required'); - } - if (!key) { - throw new Error('Key is required'); - } - if (!value) { - throw new Error('Value is required'); - } - - const url = `${this.trackingUri}/api/2.0/mlflow/experiments/set-experiment-tag`; - const response = await fetch(url, { - method: 'POST', - headers: { 'Content-Type': 'application/json' }, - body: JSON.stringify({ experiment_id, key, value }), - }); - - if (!response.ok) { - const errorBody = await response.json(); - throw new Error( - `Error setting tag from tracking server, status: ${response.status}. ${errorBody.message}` - ); - } - - console.log(`Set tag to experiment ID ${experiment_id} successfully`); - // return `Set tag to experiment ID ${experiment_id} successfully`; - } -} - -export { ExperimentClient }; diff --git a/mlflow/src/tracking/ExperimentClient.ts b/mlflow/src/tracking/ExperimentClient.ts index 5b156ef6..e0d3c6a1 100644 --- a/mlflow/src/tracking/ExperimentClient.ts +++ b/mlflow/src/tracking/ExperimentClient.ts @@ -1,7 +1,7 @@ -// import { ApiError } from '@utils/apiError'; -import { ApiError } from '../utils/apiError'; -// import { apiRequest } from '@utils/apiRequest'; -import { apiRequest } from '../utils/apiRequest'; +import { ApiError } from '@utils/apiError'; +// import { ApiError } from '../utils/apiError'; +import { apiRequest } from '@utils/apiRequest'; +// import { apiRequest } from '../utils/apiRequest'; class ExperimentClient { trackingUri: string; diff --git a/mlflow/src/tracking/experiment_management.js b/mlflow/src/tracking/experiment_management.js deleted file mode 100644 index 2ca0a04a..00000000 --- a/mlflow/src/tracking/experiment_management.js +++ /dev/null @@ -1,372 +0,0 @@ -const MLFLOW_TRACKING_URI = 'http://localhost:5001/api/2.0/mlflow'; - -/** - * Create an experiment with a name. Returns the ID of the newly created experiment. - * Validates that another experiment with the same name does not already exist and fails if another experiment with the same name already exists. - * - * @param {string} name Experiment name. (required) - * @param {string} artifact_location Optional location where all artifacts for the experiment are stored. - * If not provided, the remote server will select an appropriate default. - * @param {Array<{key: string, value: string}>} tags Optional collection of tags to set on the experiment. - * @returns {Promise} Returns the ID of the newly created experiment in an object. - */ -async function createExperiment(name, artifact_location = '', tags = []) { - if (!name) { - throw new Error('Experiment name is required'); - } - - const url = `${MLFLOW_TRACKING_URI}/experiments/create`; - const response = await fetch(url, { - method: 'POST', - headers: { 'Content-Type': 'application/json' }, - body: JSON.stringify({ name, artifact_location, tags }), - }); - - if (!response.ok) { - const errorBody = await response.json(); - throw new Error( - `Error creating experiment from tracking server, status: ${response.status}. ${errorBody.message}` - ); - } - - const data = await response.json(); - // console.log('return from createExperiment: ', data.experiment_id); - return data.experiment_id; -} - -// test **************************************************************************************************************************************** -const testCreateExperiment = async () => { - const log = await createExperiment('test_experiment_postman22'); - return console.log(log); -}; -// uncomment below --- -testCreateExperiment(); - -/** - * Search experiments. - * - * @param {string} filter A filter expression over experiment attributes and tags that allows returning a subset of experiments - * The syntax is a subset of SQL. (required) - * @param {int64} max_results Maximum number of experiments desired. (required) - * @param {string} page_token Optional token indicating the page of experiments to fetch. - * @param {Array} order_by Optional list of columns for ordering search results. - * @param {string} view_type Optional qualifier for type of experiments to be returned. - * See https://mlflow.org/docs/latest/rest-api.html#mlflowviewtype - * @returns {Promise} Returns object containing an array of experiment objects matching the filter, - * and optionally a next_page_token that can be used to retrieve the next page of experiments. - */ -async function searchExperiment( - filter, - max_results, - page_token = '', - order_by = [], - view_type = '' -) { - if (!filter) { - throw new Error('Filter is required'); - } - if (!max_results) { - throw new Error('Max results is required'); - } - - const url = `${MLFLOW_TRACKING_URI}/experiments/search`; - const response = await fetch(url, { - method: 'POST', - headers: { 'Content-Type': 'application/json' }, - body: JSON.stringify({ - filter, - max_results, - page_token, - order_by, - view_type, - }), - }); - - if (!response.ok) { - const errorBody = await response.json(); - throw new Error( - `Error searching for experiment from tracking server, status: ${response.status}. ${errorBody.message}` - ); - } - - const data = await response.json(); - // console.log('return from searchExperiment: ', data); - return data; -} - -// test **************************************************************************************************************************************** -const testSearchExperiment = async () => { - const log = await searchExperiment("name LIKE 'test_%'", 5); - console.log(log); -}; -// uncomment below --- -// testSearchExperiment(); - -/** - * Get metadata for an experiment, querying by experiment ID. This method works on deleted experiments. - * - * @param {string} experiment_id ID of the associated experiment. (required) - * @returns {Promise} Returns object containing the matched experiment. - */ -async function getExperiment(experiment_id) { - if (!experiment_id) { - throw new Error('Experiment ID is required'); - } - - const url = `${MLFLOW_TRACKING_URI}/experiments/get?experiment_id=${experiment_id}`; - const response = await fetch(url, { - method: 'GET', - headers: { 'Content-Type': 'application/json' }, - }); - - if (!response.ok) { - const errorBody = await response.json(); - throw new Error( - `Error getting experiment from tracking server, status: ${response.status}. ${errorBody.message}` - ); - } - - const data = await response.json(); - // console.log('return from getExperiment: ', data.experiment); - return data.experiment; -} - -// test **************************************************************************************************************************************** -const testGetExperiment = async () => { - const log = await getExperiment('977566317259111173'); - console.log(log); -}; -// uncomment below --- -// testGetExperiment(); - -/** - * Get metadata for an experiment, querying by experiment name. - * This endpoint will return deleted experiments, - * but prefers the active experiment if an active and deleted experiment share the same name. - * If multiple deleted experiments share the same name, the API will return one of them. - * - * @param {string} experiment_name ID of the associated experiment. (required) - * @returns {Promise} Returns object containing the matched experiment. - */ -async function getExperimentByName(experiment_name) { - if (!experiment_name) { - throw new Error('Experiment name is required'); - } - - const url = `${MLFLOW_TRACKING_URI}/experiments/get-by-name?experiment_name=${experiment_name}`; - const response = await fetch(url, { - method: 'GET', - headers: { 'Content-Type': 'application/json' }, - }); - - if (!response.ok) { - const errorBody = await response.json(); - throw new Error( - `Error getting experiment by name from tracking server, status: ${response.status}. ${errorBody.message}` - ); - } - - const data = await response.json(); - // console.log('return from getExperimentByName: ', data.experiment); - return data.experiment; -} -// test **************************************************************************************************************************************** -// getExperimentByName('test_experiment_postman16'); -const testGetExperimentByName = async () => { - const log = await getExperimentByName('test_experiment_postman16'); - console.log(log); -}; -// uncomment below --- -// testGetExperimentByName(); - -/** - * Mark an experiment for deletion. - * - * @param {string} experiment_id ID of the associated experiment. (required) - * @returns {string} Returns a string i.e. "Experiment ID 99999 successfully deleted" - */ -async function deleteExperiment(experiment_id) { - if (!experiment_id) { - throw new Error('Experiment ID is required'); - } - - const url = `${MLFLOW_TRACKING_URI}/experiments/delete`; - const response = await fetch(url, { - method: 'POST', - headers: { 'Content-Type': 'application/json' }, - body: JSON.stringify({ experiment_id }), - }); - - if (!response.ok) { - const errorBody = await response.json(); - throw new Error( - `Error deleting experiment from tracking server, status: ${response.status}. ${errorBody.message}` - ); - } - - // console.log(`Experiment ID ${experiment_id} successfully deleted`); - return `Experiment ID ${experiment_id} successfully deleted`; -} - -// test **************************************************************************************************************************************** -const testDeleteExperiment = async () => { - const log = await deleteExperiment('993400766971093020'); - console.log(log); - const log2 = await getExperiment('993400766971093020'); - console.log(log2); - restoreExperiment('993400766971093020'); -}; -// uncomment below --- -// testDeleteExperiment(); - -/** - * Restore an experiment marked for deletion. - * - * @param {string} experiment_id ID of the associated experiment. (required) - * @returns {string} Returns a string i.e. "Experiment ID 99999 successfully restored" - */ -async function restoreExperiment(experiment_id) { - if (!experiment_id) { - throw new Error('Experiment ID is required'); - } - - const url = `${MLFLOW_TRACKING_URI}/experiments/restore`; - const response = await fetch(url, { - method: 'POST', - headers: { 'Content-Type': 'application/json' }, - body: JSON.stringify({ experiment_id }), - }); - - if (!response.ok) { - const errorBody = await response.json(); - throw new Error( - `Error restoring experiment from tracking server, status: ${response.status}. ${errorBody.message}` - ); - } - - // console.log(`Experiment ID ${experiment_id} successfully restored`); - return `Experiment ID ${experiment_id} successfully restored`; -} - -// test **************************************************************************************************************************************** -const testRestoreExperiment = async () => { - const log = await getExperiment('977566317259111173'); - console.log(log); - const deleted = await deleteExperiment('977566317259111173'); - console.log(deleted); - const log2 = await getExperiment('977566317259111173'); - console.log(log2); - const log3 = await restoreExperiment('977566317259111173'); - console.log(log3); - const log4 = await getExperiment('977566317259111173'); - console.log(log4); -}; -// uncomment below --- -// testRestoreExperiment(); - -/** - * Update experiment name. - * - * @param {string} experiment_id ID of the associated experiment. (required) - * @param {string} new_name The experiment’s name is changed to the new name. The new name must be unique. (required) - * @returns {string} Returns a string i.e. "Experiment ID 99999 successfully updated" - */ -async function updateExperiment(experiment_id, new_name) { - if (!experiment_id) { - throw new Error('Experiment ID is required'); - } - if (!new_name) { - throw new Error('New name is required'); - } - - const url = `${MLFLOW_TRACKING_URI}/experiments/update`; - const response = await fetch(url, { - method: 'POST', - headers: { 'Content-Type': 'application/json' }, - body: JSON.stringify({ experiment_id, new_name }), - }); - - if (!response.ok) { - const errorBody = await response.json(); - throw new Error( - `Error updating experiment from tracking server, status: ${response.status}. ${errorBody.message}` - ); - } - - // console.log(`Experiment ID ${experiment_id} successfully updated - new name is ${new_name}`); - return `Experiment ID ${experiment_id} successfully updated - new name is ${new_name}`; -} - -// test **************************************************************************************************************************************** -const testUpdateExperiment = async () => { - const log = await getExperiment('668323101796317879'); - console.log(log); - const log2 = await updateExperiment( - '668323101796317879', - 'test_experiment_postman15_UPDATED_NAME' - ); - console.log(log2); - const log3 = await getExperiment('668323101796317879'); - console.log(log3); - const revert = await updateExperiment( - '668323101796317879', - 'test_experiment_postman15' - ); -}; -// uncomment below --- -// testUpdateExperiment(); - -/** - * Set a tag on an experiment. - * - * @param {string} experiment_id ID of the experiment under which to log the tag. (required) - * @param {string} key Name of the tag. (required) - * @param {string} value String value of the tag being logged. (required) - * @returns {string} Returns a string, i.e. `Set tag to experiment ID 99999 successfully` - */ -async function setExperimentTag(experiment_id, key, value) { - if (!experiment_id) { - throw new Error('Experiment ID is required'); - } - if (!key) { - throw new Error('Key is required'); - } - if (!value) { - throw new Error('Value is required'); - } - - const url = `${MLFLOW_TRACKING_URI}/experiments/set-experiment-tag`; - const response = await fetch(url, { - method: 'POST', - headers: { 'Content-Type': 'application/json' }, - body: JSON.stringify({ experiment_id, key, value }), - }); - - if (!response.ok) { - const errorBody = await response.json(); - throw new Error( - `Error setting tag from tracking server, status: ${response.status}. ${errorBody.message}` - ); - } - - // console.log(`Set tag to experiment ID ${experiment_id} successfully`); - return `Set tag to experiment ID ${experiment_id} successfully`; -} - -// test **************************************************************************************************************************************** -const testSetExperimentTag = async () => { - const log = await getExperiment('691149904576236192'); - console.log(log); - console.log(log.tags); - const log2 = await setExperimentTag( - '691149904576236192', - 'test_tag', - 'test_value_TEST' - ); - console.log(log2); - const log3 = await getExperiment('691149904576236192'); - console.log(log3); - console.log(log3.tags); -}; -// uncomment below --- -// testSetExperimentTag(); diff --git a/mlflow/src/workflows/ExperimentManager.js b/mlflow/src/workflows/ExperimentManager.js deleted file mode 100644 index 5347fd57..00000000 --- a/mlflow/src/workflows/ExperimentManager.js +++ /dev/null @@ -1,127 +0,0 @@ -import { ExperimentClient } from '../tracking/ExperimentClient.js'; -import { RunManagement } from '../tracking/run_management.js'; -const experimentClient = new ExperimentClient(MLFLOW_TRACKING_URI); -const runManagement = new RunManagement(MLFLOW_TRACKING_URI); - -class ExperimentManager { - constructor(trackingUri) { - this.trackingUri = trackingUri; - } - - /** - * Full workflow of creating, naming and starting a run under an existing experiment (referenced by ID), - * logging metrics, params, and tags, logging the model, and finishing the run. - * - * @param {string} experiment_id ID of the experiment under which to log the run. (required) - * @param {string} run_name Name of the run to be created and run (optional) - * @param {Array<{key: string, value: number, timestamp: number, step?: number}>} [metrics] The metrics to log (up to 1000 metrics) (optional) - * @param {Array<{key: string, value: string}>} [params] The params to log (up to 100 params) (optional) - * @param {Array<{key: string, value: string}>} [tags] The tags to log (up to 100 tags) (optional) - * @param {Object} model The ML model data to log to the run, represented as a Javascript object (optional) - * @returns {Promise} The created run object with updated metadata - */ - async runExistingExperiment( - experiment_id, - run_name = null, - metrics = [], - params = [], - tags = [], - model - ) { - if (!experiment_id) { - throw new Error('Experiment ID is required'); - } - - // create run - const run = await runManagement.createRun(experiment_id, run_name, tags); - const run_id = run.info.run_id; - - // log metric, params, and tags via logBatch - await runManagement.logBatch(run_id, metrics, params, tags); - - // log model - // (model gets passed in as a JS object, not JSON - it gets JSON stringified here after adding a run_id property) - model.run_id = run_id; - let model_json = JSON.stringify(model); - await runManagement.logModel(run_id, model_json); - - // updateRun to finish it - const latestRun = await runManagement.updateRun(run_id, 'FINISHED'); - - return latestRun; - } - - /** - * Full workflow of creating, naming and starting a run under a new experiment, - * logging metrics, params, and tags, logging the model, and finishing the run. - * - * @param {string} experiment_name Name of the experiment under which to log the run. (required) - * @param {string} run_name Name of the run to be created and run (optional) - * @param {Array<{key: string, value: number, timestamp: number, step?: number}>} [metrics] The metrics to log (up to 1000 metrics) (optional) - * @param {Array<{key: string, value: string}>} [params] The params to log (up to 100 params) (optional) - * @param {Array<{key: string, value: string}>} [tags] The tags to log (up to 100 tags) (optional) - * @param {Object} model The ML model data to log to the run, represented as a Javascript object (optional) - * @returns {Promise} The created run object with updated metadata - */ - async runNewExperiment( - experiment_name, - run_name = null, - metrics = [], - params = [], - tags = [], - model - ) { - if (!experiment_name) { - throw new Error('Experiment name is required'); - } - - let experiment_id = await experimentClient.createExperiment( - experiment_name - ); - - // create run - const run = await runManagement.createRun(experiment_id, run_name, tags); - const run_id = run.info.run_id; - - // log metric, params, and tags via logBatch - await runManagement.logBatch(run_id, metrics, params, tags); - - // log model - // (model gets passed in as a JS object, not JSON - it gets JSON stringified here after adding a run_id property) - model.run_id = run_id; - let model_json = JSON.stringify(model); - await runManagement.logModel(run_id, model_json); - - // updateRun to finish it - const latest_run = await runManagement.updateRun(run_id, 'FINISHED'); - - return latest_run; - } - - /** - * Returns an array of all the passed-in experiment's runs, sorted according to the passed-in metric - * - * @param {string} experiment_id The experiment whose runs will be evaluated (required) - * @param {string} primaryMetric The metric by which the results array will be sorted - * @param {string | number} order Sort order for the array: pass in 'DESC' or 1 for descending; 'ASC' or -1 for ascending - * @returns Promise> An array of run objects belonging to the passed-in experiment ID, sorted according to the primary metric - */ - async experimentSummary(experiment_id, primaryMetric, order) { - // use Search Runs to return all runs whose experiment ID matches the passed in one - // use Search Runs's order_by field to sort results array by primaryMetric - let orderString; - if (order === 1 || order === 'DESC') orderString = 'DESC'; - else if (order === -1 || order === 'ASC') orderString = 'ASC'; - const arg = `metrics.${primaryMetric} ${orderString}`; - const data = await runManagement.searchRuns( - [experiment_id], - undefined, - undefined, - undefined, - [arg] - ); - return data.runs; - } -} - -export { ExperimentManager }; diff --git a/mlflow/src/workflows/ExperimentManager.ts b/mlflow/src/workflows/ExperimentManager.ts index 4b7648c9..960205f9 100644 --- a/mlflow/src/workflows/ExperimentManager.ts +++ b/mlflow/src/workflows/ExperimentManager.ts @@ -1,9 +1,9 @@ -// import ExperimentClient from '@tracking/ExperimentClient'; -import ExperimentClient from '../tracking/ExperimentClient'; -// import RunClient from '@tracking/RunClient'; -import RunClient from '../tracking/RunClient'; -// import { ApiError } from '@utils/apiError'; -import { ApiError } from '../utils/apiError'; +import ExperimentClient from '@tracking/ExperimentClient'; +// import ExperimentClient from '../tracking/ExperimentClient'; +import RunClient from '@tracking/RunClient'; +// import RunClient from '../tracking/RunClient'; +import { ApiError } from '@utils/apiError'; +// import { ApiError } from '../utils/apiError'; class ExperimentManager { private trackingUri: string; diff --git a/mlflow/tests/ExperimentClient_testFile.js b/mlflow/tests/ExperimentClient_testFile.js deleted file mode 100644 index efd6c204..00000000 --- a/mlflow/tests/ExperimentClient_testFile.js +++ /dev/null @@ -1,118 +0,0 @@ -import { ExperimentClient } from '../src/tracking/ExperimentClient.js'; -const MLFLOW_TRACKING_URI = 'http://localhost:5001'; -let experimentClient = new ExperimentClient(MLFLOW_TRACKING_URI); - -const testCreateExperiment = async () => { - const num = Math.random().toString().slice(2, 11); - const name = `Test experiment ${num}`; - const log = await experimentClient.createExperiment(name); - return console.log(log); -}; -// testCreateExperiment(); - -const testSearchExperiment = async () => { - const num1 = Math.random().toString().slice(2, 11); - const name1 = `Search test ${num1}`; - const exp1 = await experimentClient.createExperiment(name1); - - const num2 = Math.random().toString().slice(2, 11); - const name2 = `Search test ${num2}`; - const exp2 = await experimentClient.createExperiment(name2); - - const num3 = Math.random().toString().slice(2, 11); - const name3 = `Search test ${num3}`; - const exp3 = await experimentClient.createExperiment(name3); - - const num4 = Math.random().toString().slice(2, 11); - const name4 = `Search test ${num4}`; - const exp4 = await experimentClient.createExperiment(name4); - - const num5 = Math.random().toString().slice(2, 11); - const name5 = `Search test ${num5}`; - const exp5 = await experimentClient.createExperiment(name5); - - const log = await experimentClient.searchExperiment( - "name LIKE 'Search test%'", - 4 - ); - console.log(log); -}; -// testSearchExperiment(); - -const testGetExperiment = async () => { - const num = Math.random().toString().slice(2, 11); - const name = `Test experiment ${num}`; - const exp = await experimentClient.createExperiment(name); - const log = await experimentClient.getExperiment(exp); - console.log(log); -}; -// testGetExperiment(); - -const testGetExperimentByName = async () => { - const num = Math.random().toString().slice(2, 11); - const name = `Test experiment ${num}`; - const exp = await experimentClient.createExperiment(name); - const log = await experimentClient.getExperimentByName(name); - console.log(log); -}; -// testGetExperimentByName(); - -const testDeleteExperiment = async () => { - const num = Math.random().toString().slice(2, 11); - const name = `Test experiment ${num}`; - const exp = await experimentClient.createExperiment(name); - const log = await experimentClient.deleteExperiment(exp); - // console.log(log); - const log2 = await experimentClient.getExperiment(exp); - console.log(log2); - experimentClient.restoreExperiment(exp); -}; -// testDeleteExperiment(); - -const testRestoreExperiment = async () => { - const num = Math.random().toString().slice(2, 11); - const name = `Test experiment ${num}`; - const exp = await experimentClient.createExperiment(name); - const log = await experimentClient.getExperiment(exp); - console.log(log); - const deleted = await experimentClient.deleteExperiment(exp); - const log2 = await experimentClient.getExperiment(exp); - console.log(log2); - const log3 = await experimentClient.restoreExperiment(exp); - const log4 = await experimentClient.getExperiment(exp); - console.log(log4); -}; -// testRestoreExperiment(); - -const testUpdateExperiment = async () => { - const num = Math.random().toString().slice(2, 11); - const name = `Test experiment ${num}`; - const exp = await experimentClient.createExperiment(name); - const log = await experimentClient.getExperiment(exp); - console.log(log); - const log2 = await experimentClient.updateExperiment( - exp, - `${name}_UPDATED_NAME` - ); - const log3 = await experimentClient.getExperiment(exp); - console.log(log3); - const revert = await experimentClient.updateExperiment(exp, name); -}; -// testUpdateExperiment(); - -const testSetExperimentTag = async () => { - const num = Math.random().toString().slice(2, 11); - const name = `Test experiment ${num}`; - const exp = await experimentClient.createExperiment(name); - const log = await experimentClient.getExperiment(exp); - console.log(log); - const num2 = Math.random().toString().slice(2, 11); - const log2 = await experimentClient.setExperimentTag( - exp, - 'test_tag', - `test_value_${num2}` - ); - const log3 = await experimentClient.getExperiment(exp); - console.log(log3); -}; -// testSetExperimentTag(); diff --git a/mlflow/tests/ExperimentManagerTestFile.ts b/mlflow/tests/ExperimentManagerTestFile.ts index e55fc7c9..5d60a80f 100644 --- a/mlflow/tests/ExperimentManagerTestFile.ts +++ b/mlflow/tests/ExperimentManagerTestFile.ts @@ -1,5 +1,5 @@ -import ExperimentManager from '../src/workflows/ExperimentManager.js'; -import ExperimentClient from '../src/tracking/ExperimentClient.js'; +import ExperimentManager from '../src/workflows/ExperimentManager'; +import ExperimentClient from '../src/tracking/ExperimentClient'; const MLFLOW_TRACKING_URI = 'http://localhost:5001'; const experimentManager = new ExperimentManager(MLFLOW_TRACKING_URI); const experimentClient = new ExperimentClient(MLFLOW_TRACKING_URI); diff --git a/mlflow/tests/ExperimentManager_testFile.js b/mlflow/tests/ExperimentManager_testFile.js deleted file mode 100644 index d387d77f..00000000 --- a/mlflow/tests/ExperimentManager_testFile.js +++ /dev/null @@ -1,110 +0,0 @@ -import { ExperimentManager } from '../src/workflows/ExperimentManager.js'; -import { ExperimentClient } from '../src/tracking/ExperimentClient.js'; -const MLFLOW_TRACKING_URI = 'http://localhost:5001'; -const experimentManager = new ExperimentManager(MLFLOW_TRACKING_URI); -const experimentClient = new ExperimentClient(MLFLOW_TRACKING_URI); - -const testRunExistingExperiment = async () => { - // define fake data for metrics, params, tags, and model - const metrics = [ - { key: 'metric1', value: 0.111, timestamp: Date.now() }, - { key: 'metric2', value: 0.222, timestamp: Date.now() }, - ]; - const params = [ - { key: 'testParam', value: 'testParamValue' }, - { key: 'testParam2', value: 'testParamValue2' }, - ]; - const tags = [ - { key: 'testKey', value: 'testValue' }, - { key: 'testKey2', value: 'testValue2' }, - ]; - const model = { - artifact_path: 'model', - flavors: { - python_function: { - model_path: 'model.pkl', - loader_module: 'mlflow.sklearn', - python_version: '3.8.10', - }, - }, - model_url: 'STRING', - model_uuid: 'STRING', - utc_time_created: Date.now(), - mlflow_version: 'STRING', - }; - - // construct random name to avoid duplicate names in the tracking server - const num = Math.random().toString().slice(2, 11); - const name = `Test experiment ${num}`; - - // pass the randomized name into .createExperiment to create a new experiment. this stores its experiment ID under the 'exp' variable - const exp = await experimentClient.createExperiment(name); - - // call .runExistingExperiment on our newly created experiment, passing in the fake data, and store the results under the variable 'log' - const log = await experimentManager.runExistingExperiment( - exp, - undefined, - metrics, - params, - tags, - model - ); - return console.log(log); -}; -// testRunExistingExperiment(); - -const testRunNewExperiment = async () => { - // define fake data for metrics, params, tags, and model - const metrics = [ - { key: 'metric1', value: 0.9, timestamp: Date.now() }, - { key: 'metric2', value: 0.222, timestamp: Date.now() }, - ]; - const params = [ - { key: 'testParam', value: 'testParamValue' }, - { key: 'testParam2', value: 'testParamValue2' }, - ]; - const tags = [ - { key: 'testKey', value: 'testValue' }, - { key: 'testKey2', value: 'testValue2' }, - ]; - const model = { - artifact_path: 'model', - flavors: { - python_function: { - model_path: 'model.pkl', - loader_module: 'mlflow.sklearn', - python_version: '3.8.10', - }, - }, - model_url: 'STRING', - model_uuid: 'STRING', - utc_time_created: Date.now(), - mlflow_version: 'STRING', - }; - - // construct random name to avoid duplicate names in the tracking server - const num = Math.random().toString().slice(2, 11); - const name = `Test experiment ${num}`; - - // call .runNewExperiment using our randomly generated name, passing in the fake data, and store the results under the variable 'log' - const log = await experimentManager.runNewExperiment( - name, - undefined, - metrics, - params, - tags, - model - ); - return console.log(log); -}; -// testRunNewExperiment(); - -const testExperimentSummary = async () => { - const log = await experimentManager.experimentSummary( - '787867007534323476', - 'metric1', - 'DESC' - ); - return console.log(log); -}; -// testExperimentSummary(); From 195d692d5dd42a8638af2dee73fd756542de0cff Mon Sep 17 00:00:00 2001 From: Austin Fraser Date: Sat, 5 Oct 2024 11:37:12 -0700 Subject: [PATCH 141/357] minor cleanup of unneeded comments --- mlflow/src/tracking/ExperimentClient.ts | 2 -- mlflow/src/workflows/ExperimentManager.ts | 3 --- 2 files changed, 5 deletions(-) diff --git a/mlflow/src/tracking/ExperimentClient.ts b/mlflow/src/tracking/ExperimentClient.ts index e0d3c6a1..080e68da 100644 --- a/mlflow/src/tracking/ExperimentClient.ts +++ b/mlflow/src/tracking/ExperimentClient.ts @@ -1,7 +1,5 @@ import { ApiError } from '@utils/apiError'; -// import { ApiError } from '../utils/apiError'; import { apiRequest } from '@utils/apiRequest'; -// import { apiRequest } from '../utils/apiRequest'; class ExperimentClient { trackingUri: string; diff --git a/mlflow/src/workflows/ExperimentManager.ts b/mlflow/src/workflows/ExperimentManager.ts index 960205f9..07345830 100644 --- a/mlflow/src/workflows/ExperimentManager.ts +++ b/mlflow/src/workflows/ExperimentManager.ts @@ -1,9 +1,6 @@ import ExperimentClient from '@tracking/ExperimentClient'; -// import ExperimentClient from '../tracking/ExperimentClient'; import RunClient from '@tracking/RunClient'; -// import RunClient from '../tracking/RunClient'; import { ApiError } from '@utils/apiError'; -// import { ApiError } from '../utils/apiError'; class ExperimentManager { private trackingUri: string; From cef911c7277ef1c3e0f47d33d7117c215585e523 Mon Sep 17 00:00:00 2001 From: Yiqun Zheng <16813562+yiqunzheng@users.noreply.github.com> Date: Sat, 5 Oct 2024 11:54:56 -0700 Subject: [PATCH 142/357] add mlflow.js --- mlflow/src/mlflow.js | 68 ++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 68 insertions(+) create mode 100644 mlflow/src/mlflow.js diff --git a/mlflow/src/mlflow.js b/mlflow/src/mlflow.js new file mode 100644 index 00000000..88859e44 --- /dev/null +++ b/mlflow/src/mlflow.js @@ -0,0 +1,68 @@ +import ExperimentClient from './tracking/ExperimentClient'; +import ExperimentManager from './workflows/ExperimentManager'; +import RunClient from './tracking/RunClient'; +import RunManager from './workflows/RunManager'; +import ModelRegistryClient from './model-registry/ModelRegistryClient'; +import ModelVersionClient from './model-registry/ModelVersionClient'; +import ModelManager from './workflows/ModelManager'; + +class Mlflow { + constructor(trackingUri) { + this.components = { + experimentClient: new ExperimentClient(trackingUri), + runClient: new RunClient(trackingUri), + modelRegistryClient: new ModelRegistryClient(trackingUri), + modelVersionClient: new ModelVersionClient(trackingUri), + experimentManager: new ExperimentManager(trackingUri), + runManager: new RunManager(trackingUri), + modelManager: new ModelManager(trackingUri), + }; + + this.initializeMethods(); + } + + initializeMethods() { + Object.keys(this.components).forEach((componentName) => { + const component = this.components[componentName]; + Object.getOwnPropertyNames(Object.getPrototypeOf(component)) + .filter( + (name) => + typeof component[name] === 'function' && name !== 'constructor' + ) + .forEach((methodName) => { + this[methodName] = (...args) => component[methodName](...args); + }); + }); + } + + // Getter methods for direct access to clients and managers + getExperimentClient() { + return this.components.experimentClient; + } + + getRunClient() { + return this.components.runClient; + } + + getModelRegistryClient() { + return this.components.modelRegistryClient; + } + + getModelVersionClient() { + return this.components.modelVersionClient; + } + + getExperimentManager() { + return this.components.experimentManager; + } + + getRunManager() { + return this.components.runManager; + } + + getModelManager() { + return this.components.modelManager; + } +} + +export default Mlflow; From 617df515ed2d6c702b47523ddcd11f6667944481 Mon Sep 17 00:00:00 2001 From: Yiqun Zheng <16813562+yiqunzheng@users.noreply.github.com> Date: Sat, 5 Oct 2024 12:11:21 -0700 Subject: [PATCH 143/357] add index.js --- mlflow/src/index.js | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 mlflow/src/index.js diff --git a/mlflow/src/index.js b/mlflow/src/index.js new file mode 100644 index 00000000..fdd3ed88 --- /dev/null +++ b/mlflow/src/index.js @@ -0,0 +1,3 @@ +import Mlflow from './mlflow.js'; + +export default Mlflow; From 6d5d51a261c5d5e44574f91043cab208570cd038 Mon Sep 17 00:00:00 2001 From: Yiqun Zheng <16813562+yiqunzheng@users.noreply.github.com> Date: Sat, 5 Oct 2024 14:00:42 -0700 Subject: [PATCH 144/357] modify mlflow.js --- mlflow/src/index.ts | 3 -- mlflow/src/mlflow.js | 4 +-- mlflow/src/mlflow.ts | 84 -------------------------------------------- 3 files changed, 2 insertions(+), 89 deletions(-) delete mode 100644 mlflow/src/index.ts delete mode 100644 mlflow/src/mlflow.ts diff --git a/mlflow/src/index.ts b/mlflow/src/index.ts deleted file mode 100644 index 3643f61e..00000000 --- a/mlflow/src/index.ts +++ /dev/null @@ -1,3 +0,0 @@ -import Mlflow from './mlflow'; - -export default Mlflow; diff --git a/mlflow/src/mlflow.js b/mlflow/src/mlflow.js index 88859e44..496fde33 100644 --- a/mlflow/src/mlflow.js +++ b/mlflow/src/mlflow.js @@ -10,11 +10,11 @@ class Mlflow { constructor(trackingUri) { this.components = { experimentClient: new ExperimentClient(trackingUri), + experimentManager: new ExperimentManager(trackingUri), runClient: new RunClient(trackingUri), + runManager: new RunManager(trackingUri), modelRegistryClient: new ModelRegistryClient(trackingUri), modelVersionClient: new ModelVersionClient(trackingUri), - experimentManager: new ExperimentManager(trackingUri), - runManager: new RunManager(trackingUri), modelManager: new ModelManager(trackingUri), }; diff --git a/mlflow/src/mlflow.ts b/mlflow/src/mlflow.ts deleted file mode 100644 index bf7fa189..00000000 --- a/mlflow/src/mlflow.ts +++ /dev/null @@ -1,84 +0,0 @@ -// src/Mlflow.ts - -// import ExperimentClient from './tracking/ExperimentClient'; -import RunClient from './tracking/RunClient'; -import ModelRegistryClient from './model-registry/ModelRegistryClient'; -import ModelVersionClient from './model-registry/ModelVersionClient'; -// import ExperimentManager from './workflows/ExperimentManager'; -import RunManager from './workflows/RunManager'; -import ModelManager from './workflows/ModelManager'; - -class Mlflow { - private components: { - // experimentClient: ExperimentClient; - runClient: RunClient; - modelRegistryClient: ModelRegistryClient; - modelVersionClient: ModelVersionClient; - // experimentManager: ExperimentManager; - runManager: RunManager; - modelManager: ModelManager; - }; - - constructor(trackingUri: string) { - this.components = { - // experimentClient: new ExperimentClient(trackingUri), - runClient: new RunClient(trackingUri), - modelRegistryClient: new ModelRegistryClient(trackingUri), - modelVersionClient: new ModelVersionClient(trackingUri), - // experimentManager: new ExperimentManager(trackingUri), - runManager: new RunManager(trackingUri), - modelManager: new ModelManager(trackingUri), - }; - - this.initializeMethods(); - } - - private initializeMethods(): void { - Object.keys(this.components).forEach((componentName) => { - const component = - this.components[componentName as keyof typeof this.components]; - Object.getOwnPropertyNames(Object.getPrototypeOf(component)) - .filter( - (name) => - typeof (component as any)[name] === 'function' && - name !== 'constructor' - ) - .forEach((methodName) => { - (this as any)[methodName] = (...args: any[]) => - (component as any)[methodName](...args); - }); - }); - } - - // Getter methods for direct access to clients and managers - - // getExperimentClient(): ExperimentClient { - // return this.components.experimentClient; - // } - - getRunClient(): RunClient { - return this.components.runClient; - } - - getModelRegistryClient(): ModelRegistryClient { - return this.components.modelRegistryClient; - } - - getModelVersionClient(): ModelVersionClient { - return this.components.modelVersionClient; - } - - // getExperimentManager(): ExperimentManager { - // return this.components.experimentManager; - // } - - getRunManager(): RunManager { - return this.components.runManager; - } - - getModelManager(): ModelManager { - return this.components.modelManager; - } -} - -export default Mlflow; From fa639fa7a686380dbcf5cce4531e781879b38802 Mon Sep 17 00:00:00 2001 From: Yiqun Zheng <16813562+yiqunzheng@users.noreply.github.com> Date: Sat, 5 Oct 2024 14:22:43 -0700 Subject: [PATCH 145/357] add dynamic delegation approach to design doc --- mlflow/docs/tech-design-doc.md | 1 + 1 file changed, 1 insertion(+) diff --git a/mlflow/docs/tech-design-doc.md b/mlflow/docs/tech-design-doc.md index aa6b81e5..850f2acb 100644 --- a/mlflow/docs/tech-design-doc.md +++ b/mlflow/docs/tech-design-doc.md @@ -61,6 +61,7 @@ mlflow-js/ The `MLflow` class serves as the main entry point for the library. It provides: - Access to High-level abstractions for common workflows - Access to tracking and model registry components +- Dynamic Method Delegation Approach/Dynamic Method Binding and getter access ### 3.2 Tracking Module From 64a44eaaac0c38363a0c0d048f9a5106d1120af3 Mon Sep 17 00:00:00 2001 From: Stephany Ho Date: Sat, 5 Oct 2024 23:21:10 -0400 Subject: [PATCH 146/357] Add tsc-alias: .js extension for emitted js files --- mlflow/package-lock.json | 466 ++++++++++++++++++++++++++++++++++++++- mlflow/package.json | 13 +- mlflow/tsconfig.json | 16 +- 3 files changed, 483 insertions(+), 12 deletions(-) diff --git a/mlflow/package-lock.json b/mlflow/package-lock.json index 74865e82..74a6ee1d 100644 --- a/mlflow/package-lock.json +++ b/mlflow/package-lock.json @@ -1,17 +1,18 @@ { "name": "mlflow-js", - "version": "0.1.0", + "version": "1.0.0", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "mlflow-js", - "version": "0.1.0", + "version": "1.0.0", "license": "MIT", "devDependencies": { "@types/node": "^22.5.4", "rimraf": "^6.0.1", "ts-node": "^10.9.2", + "tsc-alias": "^1.8.10", "tsx": "^4.19.1", "typescript": "^5.6.2" }, @@ -486,6 +487,41 @@ "@jridgewell/sourcemap-codec": "^1.4.10" } }, + "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/@tsconfig/node10": { "version": "1.0.11", "resolved": "https://registry.npmjs.org/@tsconfig/node10/-/node10-1.0.11.tgz", @@ -576,6 +612,31 @@ "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/anymatch/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/arg": { "version": "4.1.3", "resolved": "https://registry.npmjs.org/arg/-/arg-4.1.3.tgz", @@ -583,6 +644,15 @@ "dev": true, "license": "MIT" }, + "node_modules/array-union": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/array-union/-/array-union-2.1.0.tgz", + "integrity": "sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw==", + "dev": true, + "engines": { + "node": ">=8" + } + }, "node_modules/balanced-match": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", @@ -590,6 +660,18 @@ "dev": true, "license": "MIT" }, + "node_modules/binary-extensions": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.3.0.tgz", + "integrity": "sha512-Ceh+7ox5qe7LJuLHoY0feh3pHuUDHAcRUeyL2VYghZwfpkNIy/+8Ocg0a3UuSoYzavmylwuLWQOf3hl0jjMMIw==", + "dev": true, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/brace-expansion": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", @@ -600,6 +682,42 @@ "balanced-match": "^1.0.0" } }, + "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/chokidar": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.6.0.tgz", + "integrity": "sha512-7VT13fmjotKpGipCW9JEQAusEPE+Ei8nl6/g4FBAmIm0GOOLMua9NDDo/DWp0ZAxCr3cPq5ZpBqmPAQgDda2Pw==", + "dev": true, + "dependencies": { + "anymatch": "~3.1.2", + "braces": "~3.0.2", + "glob-parent": "~5.1.2", + "is-binary-path": "~2.1.0", + "is-glob": "~4.0.1", + "normalize-path": "~3.0.0", + "readdirp": "~3.6.0" + }, + "engines": { + "node": ">= 8.10.0" + }, + "funding": { + "url": "https://paulmillr.com/funding/" + }, + "optionalDependencies": { + "fsevents": "~2.3.2" + } + }, "node_modules/color-convert": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", @@ -620,6 +738,15 @@ "dev": true, "license": "MIT" }, + "node_modules/commander": { + "version": "9.5.0", + "resolved": "https://registry.npmjs.org/commander/-/commander-9.5.0.tgz", + "integrity": "sha512-KRs7WVDKg86PWiuAqhDrAQnTXZKraVcCc6vFdL14qrZ/DcWwuRo7VoiYXalXO7S5GKpqYiVEwCbgFDfxNHKJBQ==", + "dev": true, + "engines": { + "node": "^12.20.0 || >=14" + } + }, "node_modules/create-require": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/create-require/-/create-require-1.1.1.tgz", @@ -652,6 +779,18 @@ "node": ">=0.3.1" } }, + "node_modules/dir-glob": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/dir-glob/-/dir-glob-3.0.1.tgz", + "integrity": "sha512-WkrWp9GR4KXfKGYzOLmTuGVi1UWFfws377n9cc55/tb6DuqyF6pcQ5AbiHEshaDpY9v6oaSr2XCDidGmMwdzIA==", + "dev": true, + "dependencies": { + "path-type": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, "node_modules/eastasianwidth": { "version": "0.2.0", "resolved": "https://registry.npmjs.org/eastasianwidth/-/eastasianwidth-0.2.0.tgz", @@ -706,6 +845,43 @@ "@esbuild/win32-x64": "0.23.1" } }, + "node_modules/fast-glob": { + "version": "3.3.2", + "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.3.2.tgz", + "integrity": "sha512-oX2ruAFQwf/Orj8m737Y5adxDQO0LAB7/S5MnxCdTNDd4p6BsyIVsv9JQsATbTSq8KHRpLwIHbVlUNatxd+1Ow==", + "dev": true, + "dependencies": { + "@nodelib/fs.stat": "^2.0.2", + "@nodelib/fs.walk": "^1.2.3", + "glob-parent": "^5.1.2", + "merge2": "^1.3.0", + "micromatch": "^4.0.4" + }, + "engines": { + "node": ">=8.6.0" + } + }, + "node_modules/fastq": { + "version": "1.17.1", + "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.17.1.tgz", + "integrity": "sha512-sRVD3lWVIXWg6By68ZN7vho9a1pQcN/WBFaAAsDDFzlJjvoGx0P8z7V1t72grFJfJhu3YPZBuu25f7Kaw2jN1w==", + "dev": true, + "dependencies": { + "reusify": "^1.0.4" + } + }, + "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/foreground-child": { "version": "3.3.0", "resolved": "https://registry.npmjs.org/foreground-child/-/foreground-child-3.3.0.tgz", @@ -775,6 +951,68 @@ "url": "https://github.com/sponsors/isaacs" } }, + "node_modules/glob-parent": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", + "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", + "dev": true, + "dependencies": { + "is-glob": "^4.0.1" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/globby": { + "version": "11.1.0", + "resolved": "https://registry.npmjs.org/globby/-/globby-11.1.0.tgz", + "integrity": "sha512-jhIXaOzy1sb8IyocaruWSn1TjmnBVs8Ayhcy83rmxNJ8q2uWKCAj3CnJY+KpGSXCueAPc0i05kVvVKtP1t9S3g==", + "dev": true, + "dependencies": { + "array-union": "^2.1.0", + "dir-glob": "^3.0.1", + "fast-glob": "^3.2.9", + "ignore": "^5.2.0", + "merge2": "^1.4.1", + "slash": "^3.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/ignore": { + "version": "5.3.2", + "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.3.2.tgz", + "integrity": "sha512-hsBTNUqQTDwkWtcdYI2i06Y/nUBEsNEDJKjWdigLvegy8kDuJAS8uRlpkkcQpyEXL0Z/pjDy5HBmMjRCJ2gq+g==", + "dev": true, + "engines": { + "node": ">= 4" + } + }, + "node_modules/is-binary-path": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz", + "integrity": "sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==", + "dev": true, + "dependencies": { + "binary-extensions": "^2.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/is-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-fullwidth-code-point": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", @@ -785,6 +1023,27 @@ "node": ">=8" } }, + "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-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/isexe": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", @@ -825,6 +1084,40 @@ "dev": true, "license": "ISC" }, + "node_modules/merge2": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/merge2/-/merge2-1.4.1.tgz", + "integrity": "sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==", + "dev": true, + "engines": { + "node": ">= 8" + } + }, + "node_modules/micromatch": { + "version": "4.0.8", + "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.8.tgz", + "integrity": "sha512-PXwfBhYu0hBCPw8Dn0E+WDYb7af3dSLVWKi3HGv84IdF4TyFoC0ysxFd0Goxw7nSv4T/PzEJQxsYsEiFCKo2BA==", + "dev": true, + "dependencies": { + "braces": "^3.0.3", + "picomatch": "^2.3.1" + }, + "engines": { + "node": ">=8.6" + } + }, + "node_modules/micromatch/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/minimatch": { "version": "10.0.1", "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-10.0.1.tgz", @@ -851,6 +1144,28 @@ "node": ">=16 || 14 >=14.17" } }, + "node_modules/mylas": { + "version": "2.1.13", + "resolved": "https://registry.npmjs.org/mylas/-/mylas-2.1.13.tgz", + "integrity": "sha512-+MrqnJRtxdF+xngFfUUkIMQrUUL0KsxbADUkn23Z/4ibGg192Q+z+CQyiYwvWTsYjJygmMR8+w3ZDa98Zh6ESg==", + "dev": true, + "engines": { + "node": ">=12.0.0" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/raouldeheer" + } + }, + "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/package-json-from-dist": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/package-json-from-dist/-/package-json-from-dist-1.0.1.tgz", @@ -885,6 +1200,80 @@ "url": "https://github.com/sponsors/isaacs" } }, + "node_modules/path-type": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/path-type/-/path-type-4.0.0.tgz", + "integrity": "sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/plimit-lit": { + "version": "1.6.1", + "resolved": "https://registry.npmjs.org/plimit-lit/-/plimit-lit-1.6.1.tgz", + "integrity": "sha512-B7+VDyb8Tl6oMJT9oSO2CW8XC/T4UcJGrwOVoNGwOQsQYhlpfajmrMj5xeejqaASq3V/EqThyOeATEOMuSEXiA==", + "dev": true, + "dependencies": { + "queue-lit": "^1.5.1" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/queue-lit": { + "version": "1.5.2", + "resolved": "https://registry.npmjs.org/queue-lit/-/queue-lit-1.5.2.tgz", + "integrity": "sha512-tLc36IOPeMAubu8BkW8YDBV+WyIgKlYU7zUNs0J5Vk9skSZ4JfGlPOqplP0aHdfv7HL0B2Pg6nwiq60Qc6M2Hw==", + "dev": true, + "engines": { + "node": ">=12" + } + }, + "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/readdirp": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz", + "integrity": "sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==", + "dev": true, + "dependencies": { + "picomatch": "^2.2.1" + }, + "engines": { + "node": ">=8.10.0" + } + }, + "node_modules/readdirp/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/resolve-pkg-maps": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/resolve-pkg-maps/-/resolve-pkg-maps-1.0.0.tgz", @@ -895,6 +1284,16 @@ "url": "https://github.com/privatenumber/resolve-pkg-maps?sponsor=1" } }, + "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": "6.0.1", "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-6.0.1.tgz", @@ -915,6 +1314,29 @@ "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/shebang-command": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", @@ -951,6 +1373,15 @@ "url": "https://github.com/sponsors/isaacs" } }, + "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/string-width": { "version": "5.1.2", "resolved": "https://registry.npmjs.org/string-width/-/string-width-5.1.2.tgz", @@ -1055,6 +1486,18 @@ "node": ">=8" } }, + "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/ts-node": { "version": "10.9.2", "resolved": "https://registry.npmjs.org/ts-node/-/ts-node-10.9.2.tgz", @@ -1099,6 +1542,24 @@ } } }, + "node_modules/tsc-alias": { + "version": "1.8.10", + "resolved": "https://registry.npmjs.org/tsc-alias/-/tsc-alias-1.8.10.tgz", + "integrity": "sha512-Ibv4KAWfFkFdKJxnWfVtdOmB0Zi1RJVxcbPGiCDsFpCQSsmpWyuzHG3rQyI5YkobWwxFPEyQfu1hdo4qLG2zPw==", + "dev": true, + "license": "MIT", + "dependencies": { + "chokidar": "^3.5.3", + "commander": "^9.0.0", + "globby": "^11.0.4", + "mylas": "^2.1.9", + "normalize-path": "^3.0.0", + "plimit-lit": "^1.2.6" + }, + "bin": { + "tsc-alias": "dist/bin/index.js" + } + }, "node_modules/tsx": { "version": "4.19.1", "resolved": "https://registry.npmjs.org/tsx/-/tsx-4.19.1.tgz", @@ -1124,7 +1585,6 @@ "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.6.2.tgz", "integrity": "sha512-NW8ByodCSNCwZeghjN3o+JX5OFH0Ojg6sadjEKY4huZ52TqbJTJnDo5+Tw98lSy63NZvi4n+ez5m2u5d4PkZyw==", "dev": true, - "license": "Apache-2.0", "bin": { "tsc": "bin/tsc", "tsserver": "bin/tsserver" diff --git a/mlflow/package.json b/mlflow/package.json index e3cb1c59..f4199db5 100644 --- a/mlflow/package.json +++ b/mlflow/package.json @@ -1,13 +1,19 @@ { "name": "mlflow-js", - "version": "0.1.0", + "version": "1.0.0", "description": "JavaScript/Typescript library for MLflow", - "main": "lib/index.js", "type": "module", + "main": "lib/index.js", "types": "lib/index.d.ts", + "files": [ + "lib" + ], + "exports": { + ".": "./lib/index.js" + }, "scripts": { "clean": "rimraf lib", - "build": "npm run clean && tsc", + "build": "npm run clean && tsc -p tsconfig.json && tsc-alias -p tsconfig.json", "test": "", "lint": "", "docs": "" @@ -25,6 +31,7 @@ "@types/node": "^22.5.4", "rimraf": "^6.0.1", "ts-node": "^10.9.2", + "tsc-alias": "^1.8.10", "tsx": "^4.19.1", "typescript": "^5.6.2" }, diff --git a/mlflow/tsconfig.json b/mlflow/tsconfig.json index 88e5b25e..39b8395c 100644 --- a/mlflow/tsconfig.json +++ b/mlflow/tsconfig.json @@ -4,8 +4,8 @@ "target": "ES2018", "module": "ESNext", "lib": ["ES2018"], - "outDir": "./lib", "rootDir": "./src", + "outDir": "./lib", // Module Resolution Options "moduleResolution": "node", @@ -19,7 +19,7 @@ }, "esModuleInterop": true, "resolveJsonModule": true, - "moduleDetection": "force", + // "moduleDetection": "force", // Strict Type-Checking Options "strict": true, @@ -45,14 +45,18 @@ "forceConsistentCasingInFileNames": true, "skipLibCheck": true, - // Source Map Options - "sourceMap": false, - // Other Options "declaration": true, + "declarationMap": true, + "sourceMap": true, "removeComments": false, "allowJs": false }, "include": ["src/**/*"], - "exclude": ["node_modules", "**/*.spec.ts"] + "exclude": ["node_modules", "**/*.spec.ts"], + "tsc-alias": { + "resolveFullPaths": true, + "outDir": "./lib", + "extensionReplacement": [{ "from": ".ts", "to": ".js" }] + } } From 1d2bf357f3bc7527f09b6d5a00d414f7c994e1fc Mon Sep 17 00:00:00 2001 From: Kyler-Chiago Date: Thu, 10 Oct 2024 21:02:23 -0700 Subject: [PATCH 147/357] merged origin dev into local dev --- mlflow/eslint.config.mjs | 9 + mlflow/package-lock.json | 1554 +++++++++++++++++++++++++++++++++++++- mlflow/package.json | 6 +- 3 files changed, 1542 insertions(+), 27 deletions(-) create mode 100644 mlflow/eslint.config.mjs diff --git a/mlflow/eslint.config.mjs b/mlflow/eslint.config.mjs new file mode 100644 index 00000000..7d3e80e0 --- /dev/null +++ b/mlflow/eslint.config.mjs @@ -0,0 +1,9 @@ +// @ts-check + +import eslint from '@eslint/js'; +import tseslint from 'typescript-eslint'; + +export default tseslint.config( + eslint.configs.recommended, + ...tseslint.configs.recommended, +); \ No newline at end of file diff --git a/mlflow/package-lock.json b/mlflow/package-lock.json index 74865e82..226a9b30 100644 --- a/mlflow/package-lock.json +++ b/mlflow/package-lock.json @@ -9,11 +9,15 @@ "version": "0.1.0", "license": "MIT", "devDependencies": { + "@eslint/js": "^9.12.0", + "@types/eslint__js": "^8.42.3", "@types/node": "^22.5.4", + "eslint": "^9.12.0", "rimraf": "^6.0.1", "ts-node": "^10.9.2", "tsx": "^4.19.1", - "typescript": "^5.6.2" + "typescript": "^5.6.2", + "typescript-eslint": "^8.8.0" }, "engines": { "node": ">=22.7.0" @@ -440,6 +444,227 @@ "node": ">=18" } }, + "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, + "license": "MIT", + "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/eslint-utils/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, + "license": "Apache-2.0", + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/@eslint-community/regexpp": { + "version": "4.11.1", + "resolved": "https://registry.npmjs.org/@eslint-community/regexpp/-/regexpp-4.11.1.tgz", + "integrity": "sha512-m4DVN9ZqskZoLU5GlWZadwDnYo3vAEydiUayB9widCl9ffWx2IvPnp6n3on5rJmziJSw9Bv+Z3ChDVdMwXCY8Q==", + "dev": true, + "license": "MIT", + "engines": { + "node": "^12.0.0 || ^14.0.0 || >=16.0.0" + } + }, + "node_modules/@eslint/config-array": { + "version": "0.18.0", + "resolved": "https://registry.npmjs.org/@eslint/config-array/-/config-array-0.18.0.tgz", + "integrity": "sha512-fTxvnS1sRMu3+JjXwJG0j/i4RT9u4qJ+lqS/yCGap4lH4zZGzQ7tu+xZqQmcMZq5OBZDL4QRxQzRjkWcGt8IVw==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "@eslint/object-schema": "^2.1.4", + "debug": "^4.3.1", + "minimatch": "^3.1.2" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + } + }, + "node_modules/@eslint/config-array/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, + "license": "MIT", + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "node_modules/@eslint/config-array/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, + "license": "ISC", + "dependencies": { + "brace-expansion": "^1.1.7" + }, + "engines": { + "node": "*" + } + }, + "node_modules/@eslint/core": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/@eslint/core/-/core-0.6.0.tgz", + "integrity": "sha512-8I2Q8ykA4J0x0o7cg67FPVnehcqWTBehu/lmY+bolPFHGjh49YzGBMXTvpqVgEbBdvNCSxj6iFgiIyHzf03lzg==", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + } + }, + "node_modules/@eslint/eslintrc": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-3.1.0.tgz", + "integrity": "sha512-4Bfj15dVJdoy3RfZmmo86RK1Fwzn6SstsvK9JS+BaVKqC6QQQQyXekNaC+g+LKNgkQ+2VhGAzm6hO40AhMR3zQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "ajv": "^6.12.4", + "debug": "^4.3.2", + "espree": "^10.0.1", + "globals": "^14.0.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": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/@eslint/eslintrc/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, + "license": "MIT", + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "node_modules/@eslint/eslintrc/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, + "license": "ISC", + "dependencies": { + "brace-expansion": "^1.1.7" + }, + "engines": { + "node": "*" + } + }, + "node_modules/@eslint/js": { + "version": "9.12.0", + "resolved": "https://registry.npmjs.org/@eslint/js/-/js-9.12.0.tgz", + "integrity": "sha512-eohesHH8WFRUprDNyEREgqP6beG6htMeUYeCpkEgBCieCMme5r9zFWjzAJp//9S+Kub4rqE+jXe9Cp1a7IYIIA==", + "dev": true, + "license": "MIT", + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + } + }, + "node_modules/@eslint/object-schema": { + "version": "2.1.4", + "resolved": "https://registry.npmjs.org/@eslint/object-schema/-/object-schema-2.1.4.tgz", + "integrity": "sha512-BsWiH1yFGjXXS2yvrf5LyuoSIIbPrGUWob917o+BTKuZ7qJdxX8aJLRxs1fS9n6r7vESrq1OUqb68dANcFXuQQ==", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + } + }, + "node_modules/@eslint/plugin-kit": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/@eslint/plugin-kit/-/plugin-kit-0.2.0.tgz", + "integrity": "sha512-vH9PiIMMwvhCx31Af3HiGzsVNULDbyVkHXwlemn/B0TFj/00ho3y55efXrUZTfQipxoHC5u4xq6zblww1zm1Ig==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "levn": "^0.4.1" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + } + }, + "node_modules/@humanfs/core": { + "version": "0.19.0", + "resolved": "https://registry.npmjs.org/@humanfs/core/-/core-0.19.0.tgz", + "integrity": "sha512-2cbWIHbZVEweE853g8jymffCA+NCMiuqeECeBBLm8dg2oFdjuGJhgN4UAbI+6v0CKbbhvtXA4qV8YR5Ji86nmw==", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": ">=18.18.0" + } + }, + "node_modules/@humanfs/node": { + "version": "0.16.5", + "resolved": "https://registry.npmjs.org/@humanfs/node/-/node-0.16.5.tgz", + "integrity": "sha512-KSPA4umqSG4LHYRodq31VDwKAvaTF4xmVlzM8Aeh4PlU1JQ3IG0wiA8C25d3RQ9nJyM3mBHyI53K06VVL/oFFg==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "@humanfs/core": "^0.19.0", + "@humanwhocodes/retry": "^0.3.0" + }, + "engines": { + "node": ">=18.18.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, + "license": "Apache-2.0", + "engines": { + "node": ">=12.22" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/nzakas" + } + }, + "node_modules/@humanwhocodes/retry": { + "version": "0.3.1", + "resolved": "https://registry.npmjs.org/@humanwhocodes/retry/-/retry-0.3.1.tgz", + "integrity": "sha512-JBxkERygn7Bv/GbN5Rv8Ul6LVknS+5Bp6RgDC/O8gEBU/yeH5Ui5C/OlWrTb6qct7LjjfT6Re2NxB0ln0yYybA==", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": ">=18.18" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/nzakas" + } + }, "node_modules/@isaacs/cliui": { "version": "8.0.2", "resolved": "https://registry.npmjs.org/@isaacs/cliui/-/cliui-8.0.2.tgz", @@ -486,6 +711,44 @@ "@jridgewell/sourcemap-codec": "^1.4.10" } }, + "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, + "license": "MIT", + "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, + "license": "MIT", + "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, + "license": "MIT", + "dependencies": { + "@nodelib/fs.scandir": "2.1.5", + "fastq": "^1.6.0" + }, + "engines": { + "node": ">= 8" + } + }, "node_modules/@tsconfig/node10": { "version": "1.0.11", "resolved": "https://registry.npmjs.org/@tsconfig/node10/-/node10-1.0.11.tgz", @@ -514,6 +777,41 @@ "dev": true, "license": "MIT" }, + "node_modules/@types/eslint": { + "version": "9.6.1", + "resolved": "https://registry.npmjs.org/@types/eslint/-/eslint-9.6.1.tgz", + "integrity": "sha512-FXx2pKgId/WyYo2jXw63kk7/+TY7u7AziEJxJAnSFzHlqTAS3Ync6SvgYAN/k4/PQpnnVuzoMuVnByKK2qp0ag==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/estree": "*", + "@types/json-schema": "*" + } + }, + "node_modules/@types/eslint__js": { + "version": "8.42.3", + "resolved": "https://registry.npmjs.org/@types/eslint__js/-/eslint__js-8.42.3.tgz", + "integrity": "sha512-alfG737uhmPdnvkrLdZLcEKJ/B8s9Y4hrZ+YAdzUeoArBlSUERA2E87ROfOaS4jd/C45fzOoZzidLc1IPwLqOw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/eslint": "*" + } + }, + "node_modules/@types/estree": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.6.tgz", + "integrity": "sha512-AYnb1nQyY49te+VRAVgmzfcgjYS91mY5P0TKUDCLEM+gNnA+3T6rWITXRLYCpahpqSQbN5cE+gHpnPyXjHWxcw==", + "dev": true, + "license": "MIT" + }, + "node_modules/@types/json-schema": { + "version": "7.0.15", + "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.15.tgz", + "integrity": "sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA==", + "dev": true, + "license": "MIT" + }, "node_modules/@types/node": { "version": "22.7.4", "resolved": "https://registry.npmjs.org/@types/node/-/node-22.7.4.tgz", @@ -524,6 +822,225 @@ "undici-types": "~6.19.2" } }, + "node_modules/@typescript-eslint/eslint-plugin": { + "version": "8.8.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-8.8.0.tgz", + "integrity": "sha512-wORFWjU30B2WJ/aXBfOm1LX9v9nyt9D3jsSOxC3cCaTQGCW5k4jNpmjFv3U7p/7s4yvdjHzwtv2Sd2dOyhjS0A==", + "dev": true, + "license": "MIT", + "dependencies": { + "@eslint-community/regexpp": "^4.10.0", + "@typescript-eslint/scope-manager": "8.8.0", + "@typescript-eslint/type-utils": "8.8.0", + "@typescript-eslint/utils": "8.8.0", + "@typescript-eslint/visitor-keys": "8.8.0", + "graphemer": "^1.4.0", + "ignore": "^5.3.1", + "natural-compare": "^1.4.0", + "ts-api-utils": "^1.3.0" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "@typescript-eslint/parser": "^8.0.0 || ^8.0.0-alpha.0", + "eslint": "^8.57.0 || ^9.0.0" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, + "node_modules/@typescript-eslint/parser": { + "version": "8.8.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-8.8.0.tgz", + "integrity": "sha512-uEFUsgR+tl8GmzmLjRqz+VrDv4eoaMqMXW7ruXfgThaAShO9JTciKpEsB+TvnfFfbg5IpujgMXVV36gOJRLtZg==", + "dev": true, + "license": "BSD-2-Clause", + "dependencies": { + "@typescript-eslint/scope-manager": "8.8.0", + "@typescript-eslint/types": "8.8.0", + "@typescript-eslint/typescript-estree": "8.8.0", + "@typescript-eslint/visitor-keys": "8.8.0", + "debug": "^4.3.4" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "eslint": "^8.57.0 || ^9.0.0" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, + "node_modules/@typescript-eslint/scope-manager": { + "version": "8.8.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-8.8.0.tgz", + "integrity": "sha512-EL8eaGC6gx3jDd8GwEFEV091210U97J0jeEHrAYvIYosmEGet4wJ+g0SYmLu+oRiAwbSA5AVrt6DxLHfdd+bUg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@typescript-eslint/types": "8.8.0", + "@typescript-eslint/visitor-keys": "8.8.0" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + } + }, + "node_modules/@typescript-eslint/type-utils": { + "version": "8.8.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-8.8.0.tgz", + "integrity": "sha512-IKwJSS7bCqyCeG4NVGxnOP6lLT9Okc3Zj8hLO96bpMkJab+10HIfJbMouLrlpyOr3yrQ1cA413YPFiGd1mW9/Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "@typescript-eslint/typescript-estree": "8.8.0", + "@typescript-eslint/utils": "8.8.0", + "debug": "^4.3.4", + "ts-api-utils": "^1.3.0" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, + "node_modules/@typescript-eslint/types": { + "version": "8.8.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-8.8.0.tgz", + "integrity": "sha512-QJwc50hRCgBd/k12sTykOJbESe1RrzmX6COk8Y525C9l7oweZ+1lw9JiU56im7Amm8swlz00DRIlxMYLizr2Vw==", + "dev": true, + "license": "MIT", + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + } + }, + "node_modules/@typescript-eslint/typescript-estree": { + "version": "8.8.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-8.8.0.tgz", + "integrity": "sha512-ZaMJwc/0ckLz5DaAZ+pNLmHv8AMVGtfWxZe/x2JVEkD5LnmhWiQMMcYT7IY7gkdJuzJ9P14fRy28lUrlDSWYdw==", + "dev": true, + "license": "BSD-2-Clause", + "dependencies": { + "@typescript-eslint/types": "8.8.0", + "@typescript-eslint/visitor-keys": "8.8.0", + "debug": "^4.3.4", + "fast-glob": "^3.3.2", + "is-glob": "^4.0.3", + "minimatch": "^9.0.4", + "semver": "^7.6.0", + "ts-api-utils": "^1.3.0" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, + "node_modules/@typescript-eslint/typescript-estree/node_modules/minimatch": { + "version": "9.0.5", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.5.tgz", + "integrity": "sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow==", + "dev": true, + "license": "ISC", + "dependencies": { + "brace-expansion": "^2.0.1" + }, + "engines": { + "node": ">=16 || 14 >=14.17" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/@typescript-eslint/utils": { + "version": "8.8.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-8.8.0.tgz", + "integrity": "sha512-QE2MgfOTem00qrlPgyByaCHay9yb1+9BjnMFnSFkUKQfu7adBXDTnCAivURnuPPAG/qiB+kzKkZKmKfaMT0zVg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@eslint-community/eslint-utils": "^4.4.0", + "@typescript-eslint/scope-manager": "8.8.0", + "@typescript-eslint/types": "8.8.0", + "@typescript-eslint/typescript-estree": "8.8.0" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "eslint": "^8.57.0 || ^9.0.0" + } + }, + "node_modules/@typescript-eslint/visitor-keys": { + "version": "8.8.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-8.8.0.tgz", + "integrity": "sha512-8mq51Lx6Hpmd7HnA2fcHQo3YgfX1qbccxQOgZcb4tvasu//zXRaA1j5ZRFeCw/VRAdFi4mRM9DnZw0Nu0Q2d1g==", + "dev": true, + "license": "MIT", + "dependencies": { + "@typescript-eslint/types": "8.8.0", + "eslint-visitor-keys": "^3.4.3" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + } + }, + "node_modules/@typescript-eslint/visitor-keys/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, + "license": "Apache-2.0", + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, "node_modules/acorn": { "version": "8.12.1", "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.12.1.tgz", @@ -537,6 +1054,16 @@ "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, + "license": "MIT", + "peerDependencies": { + "acorn": "^6.0.0 || ^7.0.0 || ^8.0.0" + } + }, "node_modules/acorn-walk": { "version": "8.3.4", "resolved": "https://registry.npmjs.org/acorn-walk/-/acorn-walk-8.3.4.tgz", @@ -550,6 +1077,23 @@ "node": ">=0.4.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, + "license": "MIT", + "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-regex": { "version": "6.1.0", "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.1.0.tgz", @@ -570,34 +1114,97 @@ "dev": true, "license": "MIT", "engines": { - "node": ">=12" + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/arg": { + "version": "4.1.3", + "resolved": "https://registry.npmjs.org/arg/-/arg-4.1.3.tgz", + "integrity": "sha512-58S9QDqG0Xx27YwPSt9fJxivjYl432YCwfDMfZ+71RAqUrZef7LrKQZ3LHLOwCS4FLNBplP533Zx895SeOCHvA==", + "dev": true, + "license": "MIT" + }, + "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, + "license": "Python-2.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, + "license": "MIT" + }, + "node_modules/brace-expansion": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", + "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", + "dev": true, + "license": "MIT", + "dependencies": { + "balanced-match": "^1.0.0" + } + }, + "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, + "license": "MIT", + "dependencies": { + "fill-range": "^7.1.1" + }, + "engines": { + "node": ">=8" + } + }, + "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, + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "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, + "license": "MIT", + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" }, "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" + "url": "https://github.com/chalk/chalk?sponsor=1" } }, - "node_modules/arg": { - "version": "4.1.3", - "resolved": "https://registry.npmjs.org/arg/-/arg-4.1.3.tgz", - "integrity": "sha512-58S9QDqG0Xx27YwPSt9fJxivjYl432YCwfDMfZ+71RAqUrZef7LrKQZ3LHLOwCS4FLNBplP533Zx895SeOCHvA==", - "dev": true, - "license": "MIT" - }, - "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, - "license": "MIT" - }, - "node_modules/brace-expansion": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", - "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", + "node_modules/chalk/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, "license": "MIT", "dependencies": { - "balanced-match": "^1.0.0" + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" } }, "node_modules/color-convert": { @@ -620,6 +1227,13 @@ "dev": true, "license": "MIT" }, + "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, + "license": "MIT" + }, "node_modules/create-require": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/create-require/-/create-require-1.1.1.tgz", @@ -642,6 +1256,31 @@ "node": ">= 8" } }, + "node_modules/debug": { + "version": "4.3.7", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.7.tgz", + "integrity": "sha512-Er2nc/H7RrMXZBFCEim6TCmMk02Z8vLC2Rbi1KEBggpo0fS6l0S1nnapwmIi3yW/+GOJap1Krg4w0Hg80oCqgQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "ms": "^2.1.3" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "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, + "license": "MIT" + }, "node_modules/diff": { "version": "4.0.2", "resolved": "https://registry.npmjs.org/diff/-/diff-4.0.2.tgz", @@ -706,6 +1345,323 @@ "@esbuild/win32-x64": "0.23.1" } }, + "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, + "license": "MIT", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/eslint": { + "version": "9.12.0", + "resolved": "https://registry.npmjs.org/eslint/-/eslint-9.12.0.tgz", + "integrity": "sha512-UVIOlTEWxwIopRL1wgSQYdnVDcEvs2wyaO6DGo5mXqe3r16IoCNWkR29iHhyaP4cICWjbgbmFUGAhh0GJRuGZw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@eslint-community/eslint-utils": "^4.2.0", + "@eslint-community/regexpp": "^4.11.0", + "@eslint/config-array": "^0.18.0", + "@eslint/core": "^0.6.0", + "@eslint/eslintrc": "^3.1.0", + "@eslint/js": "9.12.0", + "@eslint/plugin-kit": "^0.2.0", + "@humanfs/node": "^0.16.5", + "@humanwhocodes/module-importer": "^1.0.1", + "@humanwhocodes/retry": "^0.3.1", + "@types/estree": "^1.0.6", + "@types/json-schema": "^7.0.15", + "ajv": "^6.12.4", + "chalk": "^4.0.0", + "cross-spawn": "^7.0.2", + "debug": "^4.3.2", + "escape-string-regexp": "^4.0.0", + "eslint-scope": "^8.1.0", + "eslint-visitor-keys": "^4.1.0", + "espree": "^10.2.0", + "esquery": "^1.5.0", + "esutils": "^2.0.2", + "fast-deep-equal": "^3.1.3", + "file-entry-cache": "^8.0.0", + "find-up": "^5.0.0", + "glob-parent": "^6.0.2", + "ignore": "^5.2.0", + "imurmurhash": "^0.1.4", + "is-glob": "^4.0.0", + "json-stable-stringify-without-jsonify": "^1.0.1", + "lodash.merge": "^4.6.2", + "minimatch": "^3.1.2", + "natural-compare": "^1.4.0", + "optionator": "^0.9.3", + "text-table": "^0.2.0" + }, + "bin": { + "eslint": "bin/eslint.js" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "url": "https://eslint.org/donate" + }, + "peerDependencies": { + "jiti": "*" + }, + "peerDependenciesMeta": { + "jiti": { + "optional": true + } + } + }, + "node_modules/eslint-scope": { + "version": "8.1.0", + "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-8.1.0.tgz", + "integrity": "sha512-14dSvlhaVhKKsa9Fx1l8A17s7ah7Ef7wCakJ10LYk6+GYmP9yDti2oq2SEwcyndt6knfcZyhyxwY3i9yL78EQw==", + "dev": true, + "license": "BSD-2-Clause", + "dependencies": { + "esrecurse": "^4.3.0", + "estraverse": "^5.2.0" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/eslint-visitor-keys": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-4.1.0.tgz", + "integrity": "sha512-Q7lok0mqMUSf5a/AdAZkA5a/gHcO6snwQClVNNvFKCAVlxXucdU8pKydU5ZVZjBx5xr37vGbFFWtLQYreLzrZg==", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/eslint/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, + "license": "MIT", + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "node_modules/eslint/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, + "license": "ISC", + "dependencies": { + "brace-expansion": "^1.1.7" + }, + "engines": { + "node": "*" + } + }, + "node_modules/espree": { + "version": "10.2.0", + "resolved": "https://registry.npmjs.org/espree/-/espree-10.2.0.tgz", + "integrity": "sha512-upbkBJbckcCNBDBDXEbuhjbP68n+scUd3k/U2EkyM9nw+I/jPiL4cLF/Al06CF96wRltFda16sxDFrxsI1v0/g==", + "dev": true, + "license": "BSD-2-Clause", + "dependencies": { + "acorn": "^8.12.0", + "acorn-jsx": "^5.3.2", + "eslint-visitor-keys": "^4.1.0" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/esquery": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.6.0.tgz", + "integrity": "sha512-ca9pw9fomFcKPvFLXhBKUK90ZvGibiGOvRJNbjljY7s7uq/5YO4BOzcYtJqExdx99rF6aAcnRxHmcUHcz6sQsg==", + "dev": true, + "license": "BSD-3-Clause", + "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, + "license": "BSD-2-Clause", + "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, + "license": "BSD-2-Clause", + "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, + "license": "BSD-2-Clause", + "engines": { + "node": ">=0.10.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, + "license": "MIT" + }, + "node_modules/fast-glob": { + "version": "3.3.2", + "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.3.2.tgz", + "integrity": "sha512-oX2ruAFQwf/Orj8m737Y5adxDQO0LAB7/S5MnxCdTNDd4p6BsyIVsv9JQsATbTSq8KHRpLwIHbVlUNatxd+1Ow==", + "dev": true, + "license": "MIT", + "dependencies": { + "@nodelib/fs.stat": "^2.0.2", + "@nodelib/fs.walk": "^1.2.3", + "glob-parent": "^5.1.2", + "merge2": "^1.3.0", + "micromatch": "^4.0.4" + }, + "engines": { + "node": ">=8.6.0" + } + }, + "node_modules/fast-glob/node_modules/glob-parent": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", + "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", + "dev": true, + "license": "ISC", + "dependencies": { + "is-glob": "^4.0.1" + }, + "engines": { + "node": ">= 6" + } + }, + "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, + "license": "MIT" + }, + "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, + "license": "MIT" + }, + "node_modules/fastq": { + "version": "1.17.1", + "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.17.1.tgz", + "integrity": "sha512-sRVD3lWVIXWg6By68ZN7vho9a1pQcN/WBFaAAsDDFzlJjvoGx0P8z7V1t72grFJfJhu3YPZBuu25f7Kaw2jN1w==", + "dev": true, + "license": "ISC", + "dependencies": { + "reusify": "^1.0.4" + } + }, + "node_modules/file-entry-cache": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-8.0.0.tgz", + "integrity": "sha512-XXTUwCvisa5oacNGRP9SfNtYBNAMi+RPwBFmblZEF7N7swHYQS6/Zfk7SRwx4D5j3CH211YNRco1DEMNVfZCnQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "flat-cache": "^4.0.0" + }, + "engines": { + "node": ">=16.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, + "license": "MIT", + "dependencies": { + "to-regex-range": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "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, + "license": "MIT", + "dependencies": { + "locate-path": "^6.0.0", + "path-exists": "^4.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/flat-cache": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-4.0.1.tgz", + "integrity": "sha512-f7ccFPK3SXFHpx15UIGyRJ/FJQctuKZ0zVuN3frBo4HnK3cay9VEW0R6yPYFHC0AgqhukPzKjq22t5DmAyqGyw==", + "dev": true, + "license": "MIT", + "dependencies": { + "flatted": "^3.2.9", + "keyv": "^4.5.4" + }, + "engines": { + "node": ">=16" + } + }, + "node_modules/flatted": { + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.3.1.tgz", + "integrity": "sha512-X8cqMLLie7KsNUDSdzeN8FYK9rEt4Dt67OsG/DNGnYTSDBG4uFAJFBnUeiV+zCVAvwFy56IjM9sH51jVaEhNxw==", + "dev": true, + "license": "ISC" + }, "node_modules/foreground-child": { "version": "3.3.0", "resolved": "https://registry.npmjs.org/foreground-child/-/foreground-child-3.3.0.tgz", @@ -769,10 +1725,100 @@ "glob": "dist/esm/bin.mjs" }, "engines": { - "node": "20 || >=22" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" + "node": "20 || >=22" + }, + "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, + "license": "ISC", + "dependencies": { + "is-glob": "^4.0.3" + }, + "engines": { + "node": ">=10.13.0" + } + }, + "node_modules/globals": { + "version": "14.0.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-14.0.0.tgz", + "integrity": "sha512-oahGvuMGQlPw/ivIYBjVSrWAfWLBeku5tpPE2fOPLi+WHffIWbuh2tCjhyQhTBPMf5E9jDEH4FOmTYgYwbKwtQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/graphemer": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/graphemer/-/graphemer-1.4.0.tgz", + "integrity": "sha512-EtKwoO6kxCL9WO5xipiHTZlSzBm7WLT627TqC/uVRd0HKmq8NXyebnNYxDoBi7wt8eTWrUrKXCOVaFq9x1kgag==", + "dev": true, + "license": "MIT" + }, + "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, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/ignore": { + "version": "5.3.2", + "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.3.2.tgz", + "integrity": "sha512-hsBTNUqQTDwkWtcdYI2i06Y/nUBEsNEDJKjWdigLvegy8kDuJAS8uRlpkkcQpyEXL0Z/pjDy5HBmMjRCJ2gq+g==", + "dev": true, + "license": "MIT", + "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, + "license": "MIT", + "dependencies": { + "parent-module": "^1.0.0", + "resolve-from": "^4.0.0" + }, + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/imurmurhash": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz", + "integrity": "sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.8.19" + } + }, + "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, + "license": "MIT", + "engines": { + "node": ">=0.10.0" } }, "node_modules/is-fullwidth-code-point": { @@ -785,6 +1831,29 @@ "node": ">=8" } }, + "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, + "license": "MIT", + "dependencies": { + "is-extglob": "^2.1.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "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, + "license": "MIT", + "engines": { + "node": ">=0.12.0" + } + }, "node_modules/isexe": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", @@ -808,6 +1877,87 @@ "url": "https://github.com/sponsors/isaacs" } }, + "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, + "license": "MIT", + "dependencies": { + "argparse": "^2.0.1" + }, + "bin": { + "js-yaml": "bin/js-yaml.js" + } + }, + "node_modules/json-buffer": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/json-buffer/-/json-buffer-3.0.1.tgz", + "integrity": "sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ==", + "dev": true, + "license": "MIT" + }, + "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, + "license": "MIT" + }, + "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, + "license": "MIT" + }, + "node_modules/keyv": { + "version": "4.5.4", + "resolved": "https://registry.npmjs.org/keyv/-/keyv-4.5.4.tgz", + "integrity": "sha512-oxVHkHR/EJf2CNXnWxRLW6mg7JyCCUcG0DtEGmL2ctUo1PNTin1PUil+r/+4r5MpVgC/fn1kjsx7mjSujKqIpw==", + "dev": true, + "license": "MIT", + "dependencies": { + "json-buffer": "3.0.1" + } + }, + "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, + "license": "MIT", + "dependencies": { + "prelude-ls": "^1.2.1", + "type-check": "~0.4.0" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "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, + "license": "MIT", + "dependencies": { + "p-locate": "^5.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "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, + "license": "MIT" + }, "node_modules/lru-cache": { "version": "11.0.1", "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-11.0.1.tgz", @@ -825,6 +1975,30 @@ "dev": true, "license": "ISC" }, + "node_modules/merge2": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/merge2/-/merge2-1.4.1.tgz", + "integrity": "sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 8" + } + }, + "node_modules/micromatch": { + "version": "4.0.8", + "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.8.tgz", + "integrity": "sha512-PXwfBhYu0hBCPw8Dn0E+WDYb7af3dSLVWKi3HGv84IdF4TyFoC0ysxFd0Goxw7nSv4T/PzEJQxsYsEiFCKo2BA==", + "dev": true, + "license": "MIT", + "dependencies": { + "braces": "^3.0.3", + "picomatch": "^2.3.1" + }, + "engines": { + "node": ">=8.6" + } + }, "node_modules/minimatch": { "version": "10.0.1", "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-10.0.1.tgz", @@ -851,6 +2025,70 @@ "node": ">=16 || 14 >=14.17" } }, + "node_modules/ms": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", + "dev": true, + "license": "MIT" + }, + "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, + "license": "MIT" + }, + "node_modules/optionator": { + "version": "0.9.4", + "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.9.4.tgz", + "integrity": "sha512-6IpQ7mKUxRcZNLIObR0hz7lxsapSSIYNZJwXPGeF0mTVqGKFIXj1DQcMoT22S3ROcLyY/rz0PWaWZ9ayWmad9g==", + "dev": true, + "license": "MIT", + "dependencies": { + "deep-is": "^0.1.3", + "fast-levenshtein": "^2.0.6", + "levn": "^0.4.1", + "prelude-ls": "^1.2.1", + "type-check": "^0.4.0", + "word-wrap": "^1.2.5" + }, + "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, + "license": "MIT", + "dependencies": { + "yocto-queue": "^0.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "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, + "license": "MIT", + "dependencies": { + "p-limit": "^3.0.2" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/package-json-from-dist": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/package-json-from-dist/-/package-json-from-dist-1.0.1.tgz", @@ -858,6 +2096,29 @@ "dev": true, "license": "BlueOak-1.0.0" }, + "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, + "license": "MIT", + "dependencies": { + "callsites": "^3.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "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, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, "node_modules/path-key": { "version": "3.1.1", "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", @@ -885,6 +2146,70 @@ "url": "https://github.com/sponsors/isaacs" } }, + "node_modules/picomatch": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", + "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8.6" + }, + "funding": { + "url": "https://github.com/sponsors/jonschlinkert" + } + }, + "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, + "license": "MIT", + "engines": { + "node": ">= 0.8.0" + } + }, + "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, + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "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" + } + ], + "license": "MIT" + }, + "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, + "license": "MIT", + "engines": { + "node": ">=4" + } + }, "node_modules/resolve-pkg-maps": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/resolve-pkg-maps/-/resolve-pkg-maps-1.0.0.tgz", @@ -895,6 +2220,17 @@ "url": "https://github.com/privatenumber/resolve-pkg-maps?sponsor=1" } }, + "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, + "license": "MIT", + "engines": { + "iojs": ">=1.0.0", + "node": ">=0.10.0" + } + }, "node_modules/rimraf": { "version": "6.0.1", "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-6.0.1.tgz", @@ -915,6 +2251,43 @@ "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" + } + ], + "license": "MIT", + "dependencies": { + "queue-microtask": "^1.2.2" + } + }, + "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, + "license": "ISC", + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, "node_modules/shebang-command": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", @@ -1055,6 +2428,65 @@ "node": ">=8" } }, + "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, + "license": "MIT", + "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, + "license": "MIT", + "dependencies": { + "has-flag": "^4.0.0" + }, + "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, + "license": "MIT" + }, + "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, + "license": "MIT", + "dependencies": { + "is-number": "^7.0.0" + }, + "engines": { + "node": ">=8.0" + } + }, + "node_modules/ts-api-utils": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/ts-api-utils/-/ts-api-utils-1.3.0.tgz", + "integrity": "sha512-UQMIo7pb8WRomKR1/+MFVLTroIvDVtMX3K6OUir8ynLyzB8Jeriont2bTAtmNPa1ekAgN7YPDyf6V+ygrdU+eQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=16" + }, + "peerDependencies": { + "typescript": ">=4.2.0" + } + }, "node_modules/ts-node": { "version": "10.9.2", "resolved": "https://registry.npmjs.org/ts-node/-/ts-node-10.9.2.tgz", @@ -1119,6 +2551,19 @@ "fsevents": "~2.3.3" } }, + "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, + "license": "MIT", + "dependencies": { + "prelude-ls": "^1.2.1" + }, + "engines": { + "node": ">= 0.8.0" + } + }, "node_modules/typescript": { "version": "5.6.2", "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.6.2.tgz", @@ -1133,6 +2578,30 @@ "node": ">=14.17" } }, + "node_modules/typescript-eslint": { + "version": "8.8.0", + "resolved": "https://registry.npmjs.org/typescript-eslint/-/typescript-eslint-8.8.0.tgz", + "integrity": "sha512-BjIT/VwJ8+0rVO01ZQ2ZVnjE1svFBiRczcpr1t1Yxt7sT25VSbPfrJtDsQ8uQTy2pilX5nI9gwxhUyLULNentw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@typescript-eslint/eslint-plugin": "8.8.0", + "@typescript-eslint/parser": "8.8.0", + "@typescript-eslint/utils": "8.8.0" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, "node_modules/undici-types": { "version": "6.19.8", "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-6.19.8.tgz", @@ -1140,6 +2609,16 @@ "dev": true, "license": "MIT" }, + "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, + "license": "BSD-2-Clause", + "dependencies": { + "punycode": "^2.1.0" + } + }, "node_modules/v8-compile-cache-lib": { "version": "3.0.1", "resolved": "https://registry.npmjs.org/v8-compile-cache-lib/-/v8-compile-cache-lib-3.0.1.tgz", @@ -1163,6 +2642,16 @@ "node": ">= 8" } }, + "node_modules/word-wrap": { + "version": "1.2.5", + "resolved": "https://registry.npmjs.org/word-wrap/-/word-wrap-1.2.5.tgz", + "integrity": "sha512-BN22B5eaMMI9UMtjrGd5g5eCYPpCPDUy0FJXbYsaT5zYxjFOckS53SQDE3pWkVoWpHXVb3BrYcEN4Twa55B5cA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, "node_modules/wrap-ansi": { "version": "8.1.0", "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-8.1.0.tgz", @@ -1270,6 +2759,19 @@ "engines": { "node": ">=6" } + }, + "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, + "license": "MIT", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } } } } diff --git a/mlflow/package.json b/mlflow/package.json index e3cb1c59..a264e819 100644 --- a/mlflow/package.json +++ b/mlflow/package.json @@ -22,11 +22,15 @@ "author": "", "license": "MIT", "devDependencies": { + "@eslint/js": "^9.12.0", + "@types/eslint__js": "^8.42.3", "@types/node": "^22.5.4", + "eslint": "^9.12.0", "rimraf": "^6.0.1", "ts-node": "^10.9.2", "tsx": "^4.19.1", - "typescript": "^5.6.2" + "typescript": "^5.6.2", + "typescript-eslint": "^8.8.0" }, "engines": { "node": ">=22.7.0" From d09fb0ab55e9491aa6546de3fe2f6efa36468b5a Mon Sep 17 00:00:00 2001 From: Kyler-Chiago Date: Mon, 14 Oct 2024 19:16:07 -0700 Subject: [PATCH 148/357] making progress on eslint --- mlflow/package.json | 2 +- mlflow/src/workflows/RunManager.js | 224 ----------------------------- mlflow/tests/RunClientTestFile.js | 174 ---------------------- 3 files changed, 1 insertion(+), 399 deletions(-) delete mode 100644 mlflow/src/workflows/RunManager.js delete mode 100644 mlflow/tests/RunClientTestFile.js diff --git a/mlflow/package.json b/mlflow/package.json index a264e819..c3dcbf13 100644 --- a/mlflow/package.json +++ b/mlflow/package.json @@ -9,7 +9,7 @@ "clean": "rimraf lib", "build": "npm run clean && tsc", "test": "", - "lint": "", + "lint": "eslint .", "docs": "" }, "keywords": [ diff --git a/mlflow/src/workflows/RunManager.js b/mlflow/src/workflows/RunManager.js deleted file mode 100644 index c0ee3926..00000000 --- a/mlflow/src/workflows/RunManager.js +++ /dev/null @@ -1,224 +0,0 @@ -import { RunClient } from '../tracking/RunClient.js'; -import { ModelVersionManagement } from '../model-registry/model_version_management.js'; - -class RunManager { - constructor(trackingUri) { - this.trackingUri = trackingUri; - this.RunClient = new RunClient(this.trackingUri); - this.ModelVersionManagement = new ModelVersionManagement(this.trackingUri); - } - - /** - * Delete runs that do not meet certain criteria and return deleted runs. - * Dry run is set to true by default. To delete, set dry run to false. - * - * @param {string[]} experimentIds - The IDs of the associated experiments. (required) - * @param {string} queryString - SQL-like query string to filter runs to keep. (required) - * @param {boolean} [dryRun=true] - If true, only simulate the deletion. Defaults to true. (optional) - * @returns {Promise} - An object of deleted runs. - */ - async cleanupRuns(experimentIds, queryString, metricKey, dryRun = true) { - const deletedRuns = []; - const keepRunIds = new Set(); - let pageToken = null; - const maxResults = 1000; - - try { - do { - // get all runs - const searchResult = await this.RunClient.searchRuns( - experimentIds, - '', - null, // run_view_type - maxResults, - ['start_time DESC'], - pageToken - ); - - // get runs that match the keep crteria - const keepRunsResult = await this.RunClient.searchRuns( - experimentIds, - queryString, - null, // run_view_type - maxResults, - ['start_time DESC'], - pageToken - ); - - // Add runs from keepRunsResult to keepResult - keepRunsResult.runs.forEach((run) => keepRunIds.add(run.info.run_id)); - - // Add runs without the specified metric key to keepRunIds - for (const run of searchResult.runs) { - if (Array.isArray(run.data.metrics)) { - const hasMetricKey = run.data.metrics.some( - (metric) => metric.key === metricKey - ); - if (!hasMetricKey) { - keepRunIds.add(run.info.run_id); - } - } else { - // If run.data.metrics is not an array (e.g., undefined), keep the run - keepRunIds.add(run.info.run_id); - } - } - - // Delete runs that are not in keepRunIds - for (const run of searchResult.runs) { - if (!keepRunIds.has(run.info.run_id)) { - if (!dryRun) { - await this.RunClient.deleteRun(run.info.run_id); - } - deletedRuns.push(run); - } - } - - pageToken = searchResult.page_token; - } while (pageToken); - } catch (error) { - console.error('Error during run cleanup: ', error); - throw new Error('Failed to cleanup runs.'); - } - return { deletedRuns, total: deletedRuns.length, dryRun }; - } - - /********************************************************************************************************** */ - - /** - * Copy run from one experiment to another without artifactss and models. - * Artifacts and models detail tagged in new run as reference. - * - * @param {string} runId - The ID of the run to be copied. (required) - * @param {string} targetExperimentId - The ID of the target experiment. (required) - * @param {string} runName - The name of the new run in target experiment. (optional) - * @returns {Promise} - An object detail of the copied run. - */ - async copyRun(runId, targetExperimentId, runName = null) { - try { - // get original run - const originalRun = await this.RunClient.getRun(runId); - - // create a new run in the target experiment - const newRun = await this.RunClient.createRun( - targetExperimentId, - null, - originalRun.info.start_time - ); - - const newRunId = newRun.info.run_id; - - const endTime = originalRun.info.end_time || undefined; - - // copy run information - await this.RunClient.updateRun( - newRunId, - originalRun.info.status, - endTime - ); - if (originalRun.info.lifecycle_stage !== 'active') { - await this.RunClient.setTag( - newRunId, - 'mlflow.lifecycleStage', - originalRun.info.lifecycle_stage - ); - } - - // copy parameters - if (originalRun.data.params) { - for (const param of originalRun.data.params) { - await this.RunClient.logParam(newRunId, param.key, param.value); - } - } - - // copy metrics - if (originalRun.data.metrics) { - for (const metric of originalRun.data.metrics) { - await this.RunClient.logMetric(newRunId, metric.key, metric.value); - } - } - - // copy tags - if (originalRun.data.tags) { - for (const tag of originalRun.data.tags) { - await this.RunClient.setTag(newRunId, tag.key, tag.value); - } - } - - // copy inputs - if ( - originalRun.inputs && - originalRun.inputs.dataset_inputs && - originalRun.inputs.dataset_inputs.length > 0 - ) { - // Log each dataset input separately - for (const datasetInput of originalRun.inputs.dataset_inputs) { - await this.RunClient.logInputs(newRunId, [datasetInput]); - } - } - - // update the new run name - if (runName) { - await this.RunClient.setTag(newRunId, 'mlflow.runName', runName); - } - - // handle models (reference only) - const modelVersions = - await this.ModelVersionManagement.searchModelVersions( - `run_id = '${runId}'` - ); - if (modelVersions && modelVersions.length > 0) { - for (const model of modelVersions) { - await this.RunClient.setTag( - newRunId, - `original_model_${model.name}`, - JSON.stringify({ - name: model.name, - version: model.version, - current_stage: model.current_stage, - source: model.source, - }) - ); - } - await this.RunClient.setTag( - newRunId, - 'mlflow.note.models', - 'Models not copied -see original run' - ); - } - - // set description for the new run - const description = - `This run was copied from experiment ${originalRun.info.experiment_id}, original run ID: ${runId}. ` + - `Original artifact URI: ${originalRun.info.artifact_uri}.`; - - await this.RunClient.setTag(newRunId, 'mlflow.note.content', description); - - // set additional tags for the new run - await this.RunClient.setTag(newRunId, 'mlflow.source.run_id', runId); - - await this.RunClient.setTag( - newRunId, - 'mlflow.source.experiment_id', - originalRun.info.experiment_id - ); - - await this.RunClient.setTag( - newRunId, - 'mlflow.note.artifacts', - 'Artifacts not copied - reference original run' - ); - - // return copy run details - return { - originalRunId: runId, - newRunId: newRunId, - targetExperimentId: targetExperimentId, - }; - } catch (error) { - console.error('Error copying run: ', error); - throw new Error('Failed to copy run.'); - } - } -} - -export { RunManager }; diff --git a/mlflow/tests/RunClientTestFile.js b/mlflow/tests/RunClientTestFile.js deleted file mode 100644 index 1f6bc5b4..00000000 --- a/mlflow/tests/RunClientTestFile.js +++ /dev/null @@ -1,174 +0,0 @@ -import { RunClient } from '../src/tracking/RunClient.js'; - -const myRunClient = new RunClient('http://127.0.0.1:5000'); - -async function testCreateRun(experiment_id) { - try { - const run = await myRunClient.createRun(experiment_id); - console.log('Created run:', run); - } catch (error) { - console.error('Error:', error.message); - } -} - -// testCreateRun('463611670721534538'); - -async function testDeleteRun(run_id) { - try { - const run = await myRunClient.deleteRun(run_id); - console.log(`Run ID ${run_id} deleted`); - } catch (error) { - console.error('Error:', error.message); - } -} - -// testDeleteRun('1d3829715bda4e4eb257f68363dacfa6'); - -async function testRestoreRun(run_id) { - try { - const run = await myRunClient.restoreRun(run_id); - console.log(`Run ID ${run_id} restored`); - } catch (error) { - console.error('Error:', error.message); - } -} - -// testRestoreRun('1d3829715bda4e4eb257f68363dacfa6'); - -async function testGetRun(run_id) { - try { - const run = await myRunClient.getRun(run_id); - console.log('Fetched run ID: ', run); - } catch (error) { - console.error('Error:', error.message); - } -} - -// testGetRun('0577e22f02e24d24b62949625306c256'); - -async function testUpdateRun(run_id, status, end_time, run_name) { - try { - const updatedRun = await myRunClient.updateRun( - run_id, - status, - end_time, - run_name - ); - console.log('Updated run: ', updatedRun); - } catch (error) { - console.error('Error:', error.message); - } -} - -// await myRunClient.updateRun( -// '9acc6e77bc0c4273ab2105e8e6adc38b', -// 'FINISHED', -// '1631234567890', -// 'hey' -// ); - -async function testLogMetric(run_id, key, value) { - try { - const loggedMetric = await myRunClient.logMetric(run_id, key, value); - console.log('Metric logged successfully'); - } catch (error) { - console.error('Error: ', error.message); - } -} - -// testLogMetric('69c2298a1a374e989806ea89ab2b892a', 'metric-01', 0.9); - -async function testLogBatch(run_id, metrics, params, tags) { - try { - await myRunClient.logBatch(run_id, metrics, params, tags); - } catch (error) { - console.error('Error in testLogBatch: ', error); - } -} - -// testLogBatch('521098fe3c6f42ee81fdb82cc1437fef'); -// testLogBatch( -// '0577e22f02e24d24b62949625306c256', -// [ -// { key: 'mae', value: 2.5, timestamp: 1552550804 }, -// { key: 'rmse', value: 2.7, timestamp: 1552550804 }, -// ], -// [{ key: 'model_class', value: 'LogisticRegression' }] -// ); -// testLogBatch( -// '1d3829715bda4e4eb257f68363dacfa6', -// [ -// { key: 'mae', value: 2.2, timestamp: 1552550804 }, -// { key: 'rmse', value: 2.9, timestamp: 1552550804 }, -// ], -// [{ key: 'model_class', value: 'LogisticRegression' }], -// [{ key: 'tag_name', value: 'testing' }] -// ); - -async function testLogModel(run_id, model_json) { - try { - const modelJson = JSON.stringify(model_json); - - await myRunClient.logModel(run_id, modelJson); - console.log('Model logged successfully.'); - } catch (error) { - console.error('Error: ', error); - } -} - -// testLogModel('69c2298a1a374e989806ea89ab2b892a', { -// artifact_path: 'model', -// flavors: { -// python_function: { -// model_path: 'model.pkl', -// loader_module: 'mlflow.sklearn', -// python_version: '3.8.10', -// }, -// // sklearn: { -// // sklearn_version: '0.19.1', -// // pickled_model: 'model.pkl', -// // }, -// }, -// run_id: '69c2298a1a374e989806ea89ab2b892a', -// utc_time_created: '2024-08-28 12:00:00.000000', -// }); - -async function testLogInputs(run_id, datasets) { - try { - await myRunClient.logInputs(run_id, datasets); - console.log('Datasets logged successfully.'); - } catch (error) { - console.error('Error logging datasets: ', error.message); - } -} - -// testLogInputs('4a6e21f64d9d4201b157e838501b8d9c', [ -// { -// name: 'wine quality - white', -// source: -// 'https://raw.githubusercontent.com/mlflow/mlflow/master/tests/datasets/winequality-white.csv', -// targets: 'quality', -// schema: { -// columns: [ -// { name: 'fixed acidity', type: 'double' }, -// { name: 'volatile acidity', type: 'double' }, -// { name: 'citric acid', type: 'double' }, -// { name: 'residual sugar', type: 'double' }, -// { name: 'chlorides', type: 'double' }, -// { name: 'free sulfur dioxide', type: 'double' }, -// { name: 'total sulfur dioxide', type: 'double' }, -// { name: 'density', type: 'double' }, -// { name: 'pH', type: 'double' }, -// { name: 'sulphates', type: 'double' }, -// { name: 'alcohol', type: 'double' }, -// { name: 'quality', type: 'long' }, -// ], -// }, -// // profile: { -// // num_rows: rawData.length, -// // num_elements: rawData.length * Object.keys(rawData[0]).length, -// // }, -// }, -// ]); - -// https://mlflow.org/docs/latest/python_api/mlflow.data.html#mlflow.data.dataset.Dataset From 42c4c9e5b92f430f67facc9d3d7c485ad73a1c58 Mon Sep 17 00:00:00 2001 From: Kyler-Chiago Date: Mon, 14 Oct 2024 19:34:27 -0700 Subject: [PATCH 149/357] fixed some old code in ModelManagerTest.ts, ModelVersionClientTest.ts --- .../src/model-registry/ModelVersionClient.ts | 2 +- mlflow/tests/ModelManagerTest.ts | 39 ++++--------------- mlflow/tests/ModelVersionClientTest.ts | 33 +++------------- 3 files changed, 14 insertions(+), 60 deletions(-) diff --git a/mlflow/src/model-registry/ModelVersionClient.ts b/mlflow/src/model-registry/ModelVersionClient.ts index 7e22edff..20111850 100644 --- a/mlflow/src/model-registry/ModelVersionClient.ts +++ b/mlflow/src/model-registry/ModelVersionClient.ts @@ -135,7 +135,7 @@ class ModelVersionClient { page_token?: string ): Promise> { // let filter2: string = filter?.toString(); - const body: { [key: string]: any } = {}; + const body: { [key: string]: string } = {}; if (filter) { body.filter = filter; } diff --git a/mlflow/tests/ModelManagerTest.ts b/mlflow/tests/ModelManagerTest.ts index 1eb8d7d0..a6098fdc 100644 --- a/mlflow/tests/ModelManagerTest.ts +++ b/mlflow/tests/ModelManagerTest.ts @@ -1,32 +1,7 @@ -import { apiRequest } from '../src/utils/apiRequest'; import ModelManager from '../src/workflows/ModelManager'; -import ModelRegistryClient from '../src/model-registry/ModelRegistryClient'; import RunClient from '../src/tracking/RunClient'; -async function createRun( - client: ModelRegistryClient, - experimentId: string -): Promise { - const { response, data } = await apiRequest( - (client as any).baseUrl, - 'runs/create', - { - method: 'POST', - body: { experiment_id: experimentId }, - } - ); - - if (!response.ok) { - throw new Error( - `Error creating run: ${data.message || response.statusText}` - ); - } - - return data.run; -} - async function testModelManager() { - const modelRegistryClient = new ModelRegistryClient('http://localhost:5001'); const modelManager = new ModelManager('http://localhost:5001'); const runClient = new RunClient('http://localhost:5001'); const timestamp = Date.now(); @@ -45,7 +20,7 @@ async function testModelManager() { const runMetricValueLow = 1; console.log('\n5. Creating a run...'); - const run = await createRun(modelRegistryClient, '0'); // Using '0' as the default experiment ID + const run = await runClient.createRun('0'); // Using '0' as the default experiment ID console.log('Created run:', run); console.log('1. Creating a new registered model with a version...'); @@ -82,7 +57,7 @@ async function testModelManager() { console.log(`Updated latest version of ${modelName}'s alias, tag, and description: `, updatedLatestModelVersionAll); console.log("4. Updating the latest model version's tag..."); - const updatedModelVersionTag = await modelManager.setLatestModelVersionTag( + await modelManager.setLatestModelVersionTag( modelName, modelVersionTagKey, modelVersionTagValue @@ -90,7 +65,7 @@ async function testModelManager() { console.log(`Updated ${modelName} version tag`); console.log('5. Updating the latest model version\'s alias...'); - const updatedModelVersionAlias = await modelManager.setLatestModelVersionAlias( + await modelManager.setLatestModelVersionAlias( modelName, modelVersionAlias ) @@ -115,13 +90,13 @@ async function testModelManager() { console.log('Updated model version: ', updatedModelVersionAll); console.log(`8. Deleting the latest version of the model...`); - const deletedModelVersion = await modelManager.deleteLatestModelVersion( + await modelManager.deleteLatestModelVersion( modelName ); console.log(`Deleted Latest version of ${modelName}`); console.log('9. Creating model from run with best metric...'); - const run2 = await createRun(modelRegistryClient, '0'); // Using '0' as the default experiment ID + const run2 = await runClient.createRun('0'); // Using '0' as the default experiment ID console.log('Created run:', run2); await runClient.logMetric( @@ -133,14 +108,14 @@ async function testModelManager() { await runClient.logMetric( run2.info.run_id, runMetricKey, - runMetricValueHigh + runMetricValueLow ); const runData = await runClient.getRun( run.info.run_id ); - const bestModel = await modelManager.createModelFromRunWithBestMetric( + await modelManager.createModelFromRunWithBestMetric( [run.info.experiment_id], runData.data.metrics[0].key, 'max', diff --git a/mlflow/tests/ModelVersionClientTest.ts b/mlflow/tests/ModelVersionClientTest.ts index 00b89ddd..76e20c5d 100644 --- a/mlflow/tests/ModelVersionClientTest.ts +++ b/mlflow/tests/ModelVersionClientTest.ts @@ -1,32 +1,11 @@ -import { apiRequest } from '../src/utils/apiRequest'; import ModelVersionClient from '../src/model-registry/ModelVersionClient'; import ModelRegistryClient from '../src/model-registry/ModelRegistryClient'; - -async function createRun( - client: ModelRegistryClient, - experimentId: string -): Promise { - const { response, data } = await apiRequest( - (client as any).baseUrl, - 'runs/create', - { - method: 'POST', - body: { experiment_id: experimentId }, - } - ); - - if (!response.ok) { - throw new Error( - `Error creating run: ${data.message || response.statusText}` - ); - } - - return data.run; -} +import RunClient from '../src/tracking/RunClient'; async function testModelVersionClient() { const client = new ModelVersionClient('http://localhost:5001'); const modelRegistryClient = new ModelRegistryClient('http://localhost:5001'); + const runClient = new RunClient('http://localhost:5001'); const timestamp = Date.now(); const modelName = `test-model-${timestamp}`; const modelVersionDescription1 = 'This is test version 1 description'; @@ -42,7 +21,7 @@ async function testModelVersionClient() { ); console.log('\n5. Creating a run...'); - const run = await createRun(modelRegistryClient, '0'); // Using '0' as the default experiment ID + const run = await runClient.createRun('0'); // Using '0' as the default experiment ID console.log('Created run:', run); // 1. Creating a registered model version @@ -99,7 +78,7 @@ async function testModelVersionClient() { // 7. Setting model version tag console.log('7. Setting model version tag...'); - const modelVersionTag = await client.setModelVersionTag( + await client.setModelVersionTag( modelName, '1', modelVersionKey, @@ -109,7 +88,7 @@ async function testModelVersionClient() { // 8. Deleting model version tag console.log('8. Deleting model version tag...'); - const deletedModelVersionTag = await client.deleteModelVersionTag( + await client.deleteModelVersionTag( modelName, '1', modelVersionKey @@ -118,7 +97,7 @@ async function testModelVersionClient() { // 9. Deleting model version console.log('9. Deleting model version...'); - const deletedModelVersion = await client.deleteModelVersion( + await client.deleteModelVersion( modelName, '1', ) From 2180d105e9de941e1731972c53dfa941375df699 Mon Sep 17 00:00:00 2001 From: Kyler-Chiago Date: Tue, 15 Oct 2024 18:14:26 -0700 Subject: [PATCH 150/357] more fixes from Eslint --- mlflow/src/model-registry/ModelVersionClient.ts | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/mlflow/src/model-registry/ModelVersionClient.ts b/mlflow/src/model-registry/ModelVersionClient.ts index 20111850..66ae85a7 100644 --- a/mlflow/src/model-registry/ModelVersionClient.ts +++ b/mlflow/src/model-registry/ModelVersionClient.ts @@ -134,16 +134,15 @@ class ModelVersionClient { order_by?: Array, page_token?: string ): Promise> { - // let filter2: string = filter?.toString(); const body: { [key: string]: string } = {}; if (filter) { body.filter = filter; } if (maxResults) { - body.maxResults = maxResults; + body.maxResults = maxResults.toString(); } if (order_by) { - body.order_by = order_by; + body.order_by = order_by.toString(); } if (page_token) { body.page_token = page_token; From faaf097e0a2e20383f82ec02cd69d8376e70cd50 Mon Sep 17 00:00:00 2001 From: Yiqun Zheng <16813562+yiqunzheng@users.noreply.github.com> Date: Tue, 15 Oct 2024 21:06:48 -0700 Subject: [PATCH 151/357] create mlflow.js --- mlflow/src/mlflow.ts | 84 ++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 84 insertions(+) create mode 100644 mlflow/src/mlflow.ts diff --git a/mlflow/src/mlflow.ts b/mlflow/src/mlflow.ts new file mode 100644 index 00000000..e1f6db11 --- /dev/null +++ b/mlflow/src/mlflow.ts @@ -0,0 +1,84 @@ +import ExperimentClient from './tracking/ExperimentClient'; +import ExperimentManager from './workflows/ExperimentManager'; +import RunClient from './tracking/RunClient'; +import RunManager from './workflows/RunManager'; +import ModelRegistryClient from './model-registry/ModelRegistryClient'; +import ModelVersionClient from './model-registry/ModelVersionClient'; +import ModelManager from './workflows/ModelManager'; + +type ComponentName = keyof Mlflow['components']; + +class Mlflow { + private components: { + experimentClient: ExperimentClient; + experimentManager: ExperimentManager; + runClient: RunClient; + runManager: RunManager; + modelRegistryClient: ModelRegistryClient; + modelVersionClient: ModelVersionClient; + modelManager: ModelManager; + }; + + constructor(trackingUri: string) { + this.components = { + experimentClient: new ExperimentClient(trackingUri), + experimentManager: new ExperimentManager(trackingUri), + runClient: new RunClient(trackingUri), + runManager: new RunManager(trackingUri), + modelRegistryClient: new ModelRegistryClient(trackingUri), + modelVersionClient: new ModelVersionClient(trackingUri), + modelManager: new ModelManager(trackingUri), + }; + + this.initializeMethods(); + } + + private initializeMethods(): void { + (Object.keys(this.components) as ComponentName[]).forEach( + (componentName) => { + const component = this.components[componentName]; + Object.getOwnPropertyNames(Object.getPrototypeOf(component)) + .filter( + (name) => + typeof (component as any)[name] === 'function' && + name !== 'constructor' + ) + .forEach((methodName) => { + (this as any)[methodName] = (...args: any[]) => + (component as any)[methodName](...args); + }); + } + ); + } + + // Getter methods for direct access to clients and managers + getExperimentClient(): ExperimentClient { + return this.components.experimentClient; + } + + getRunClient(): RunClient { + return this.components.runClient; + } + + getModelRegistryClient(): ModelRegistryClient { + return this.components.modelRegistryClient; + } + + getModelVersionClient(): ModelVersionClient { + return this.components.modelVersionClient; + } + + getExperimentManager(): ExperimentManager { + return this.components.experimentManager; + } + + getRunManager(): RunManager { + return this.components.runManager; + } + + getModelManager(): ModelManager { + return this.components.modelManager; + } +} + +export default Mlflow; From 600d5a09d89070e083beabda39efecf1145f90f5 Mon Sep 17 00:00:00 2001 From: Yiqun Zheng <16813562+yiqunzheng@users.noreply.github.com> Date: Wed, 16 Oct 2024 14:00:40 -0700 Subject: [PATCH 152/357] add index.ts and delete js files --- mlflow/src/index.js | 3 - mlflow/src/index.ts | 3 + mlflow/src/mlflow.js | 68 --------- mlflow/src/workflows/RunManager.js | 224 ----------------------------- 4 files changed, 3 insertions(+), 295 deletions(-) delete mode 100644 mlflow/src/index.js create mode 100644 mlflow/src/index.ts delete mode 100644 mlflow/src/mlflow.js delete mode 100644 mlflow/src/workflows/RunManager.js diff --git a/mlflow/src/index.js b/mlflow/src/index.js deleted file mode 100644 index fdd3ed88..00000000 --- a/mlflow/src/index.js +++ /dev/null @@ -1,3 +0,0 @@ -import Mlflow from './mlflow.js'; - -export default Mlflow; diff --git a/mlflow/src/index.ts b/mlflow/src/index.ts new file mode 100644 index 00000000..3643f61e --- /dev/null +++ b/mlflow/src/index.ts @@ -0,0 +1,3 @@ +import Mlflow from './mlflow'; + +export default Mlflow; diff --git a/mlflow/src/mlflow.js b/mlflow/src/mlflow.js deleted file mode 100644 index 496fde33..00000000 --- a/mlflow/src/mlflow.js +++ /dev/null @@ -1,68 +0,0 @@ -import ExperimentClient from './tracking/ExperimentClient'; -import ExperimentManager from './workflows/ExperimentManager'; -import RunClient from './tracking/RunClient'; -import RunManager from './workflows/RunManager'; -import ModelRegistryClient from './model-registry/ModelRegistryClient'; -import ModelVersionClient from './model-registry/ModelVersionClient'; -import ModelManager from './workflows/ModelManager'; - -class Mlflow { - constructor(trackingUri) { - this.components = { - experimentClient: new ExperimentClient(trackingUri), - experimentManager: new ExperimentManager(trackingUri), - runClient: new RunClient(trackingUri), - runManager: new RunManager(trackingUri), - modelRegistryClient: new ModelRegistryClient(trackingUri), - modelVersionClient: new ModelVersionClient(trackingUri), - modelManager: new ModelManager(trackingUri), - }; - - this.initializeMethods(); - } - - initializeMethods() { - Object.keys(this.components).forEach((componentName) => { - const component = this.components[componentName]; - Object.getOwnPropertyNames(Object.getPrototypeOf(component)) - .filter( - (name) => - typeof component[name] === 'function' && name !== 'constructor' - ) - .forEach((methodName) => { - this[methodName] = (...args) => component[methodName](...args); - }); - }); - } - - // Getter methods for direct access to clients and managers - getExperimentClient() { - return this.components.experimentClient; - } - - getRunClient() { - return this.components.runClient; - } - - getModelRegistryClient() { - return this.components.modelRegistryClient; - } - - getModelVersionClient() { - return this.components.modelVersionClient; - } - - getExperimentManager() { - return this.components.experimentManager; - } - - getRunManager() { - return this.components.runManager; - } - - getModelManager() { - return this.components.modelManager; - } -} - -export default Mlflow; diff --git a/mlflow/src/workflows/RunManager.js b/mlflow/src/workflows/RunManager.js deleted file mode 100644 index c0ee3926..00000000 --- a/mlflow/src/workflows/RunManager.js +++ /dev/null @@ -1,224 +0,0 @@ -import { RunClient } from '../tracking/RunClient.js'; -import { ModelVersionManagement } from '../model-registry/model_version_management.js'; - -class RunManager { - constructor(trackingUri) { - this.trackingUri = trackingUri; - this.RunClient = new RunClient(this.trackingUri); - this.ModelVersionManagement = new ModelVersionManagement(this.trackingUri); - } - - /** - * Delete runs that do not meet certain criteria and return deleted runs. - * Dry run is set to true by default. To delete, set dry run to false. - * - * @param {string[]} experimentIds - The IDs of the associated experiments. (required) - * @param {string} queryString - SQL-like query string to filter runs to keep. (required) - * @param {boolean} [dryRun=true] - If true, only simulate the deletion. Defaults to true. (optional) - * @returns {Promise} - An object of deleted runs. - */ - async cleanupRuns(experimentIds, queryString, metricKey, dryRun = true) { - const deletedRuns = []; - const keepRunIds = new Set(); - let pageToken = null; - const maxResults = 1000; - - try { - do { - // get all runs - const searchResult = await this.RunClient.searchRuns( - experimentIds, - '', - null, // run_view_type - maxResults, - ['start_time DESC'], - pageToken - ); - - // get runs that match the keep crteria - const keepRunsResult = await this.RunClient.searchRuns( - experimentIds, - queryString, - null, // run_view_type - maxResults, - ['start_time DESC'], - pageToken - ); - - // Add runs from keepRunsResult to keepResult - keepRunsResult.runs.forEach((run) => keepRunIds.add(run.info.run_id)); - - // Add runs without the specified metric key to keepRunIds - for (const run of searchResult.runs) { - if (Array.isArray(run.data.metrics)) { - const hasMetricKey = run.data.metrics.some( - (metric) => metric.key === metricKey - ); - if (!hasMetricKey) { - keepRunIds.add(run.info.run_id); - } - } else { - // If run.data.metrics is not an array (e.g., undefined), keep the run - keepRunIds.add(run.info.run_id); - } - } - - // Delete runs that are not in keepRunIds - for (const run of searchResult.runs) { - if (!keepRunIds.has(run.info.run_id)) { - if (!dryRun) { - await this.RunClient.deleteRun(run.info.run_id); - } - deletedRuns.push(run); - } - } - - pageToken = searchResult.page_token; - } while (pageToken); - } catch (error) { - console.error('Error during run cleanup: ', error); - throw new Error('Failed to cleanup runs.'); - } - return { deletedRuns, total: deletedRuns.length, dryRun }; - } - - /********************************************************************************************************** */ - - /** - * Copy run from one experiment to another without artifactss and models. - * Artifacts and models detail tagged in new run as reference. - * - * @param {string} runId - The ID of the run to be copied. (required) - * @param {string} targetExperimentId - The ID of the target experiment. (required) - * @param {string} runName - The name of the new run in target experiment. (optional) - * @returns {Promise} - An object detail of the copied run. - */ - async copyRun(runId, targetExperimentId, runName = null) { - try { - // get original run - const originalRun = await this.RunClient.getRun(runId); - - // create a new run in the target experiment - const newRun = await this.RunClient.createRun( - targetExperimentId, - null, - originalRun.info.start_time - ); - - const newRunId = newRun.info.run_id; - - const endTime = originalRun.info.end_time || undefined; - - // copy run information - await this.RunClient.updateRun( - newRunId, - originalRun.info.status, - endTime - ); - if (originalRun.info.lifecycle_stage !== 'active') { - await this.RunClient.setTag( - newRunId, - 'mlflow.lifecycleStage', - originalRun.info.lifecycle_stage - ); - } - - // copy parameters - if (originalRun.data.params) { - for (const param of originalRun.data.params) { - await this.RunClient.logParam(newRunId, param.key, param.value); - } - } - - // copy metrics - if (originalRun.data.metrics) { - for (const metric of originalRun.data.metrics) { - await this.RunClient.logMetric(newRunId, metric.key, metric.value); - } - } - - // copy tags - if (originalRun.data.tags) { - for (const tag of originalRun.data.tags) { - await this.RunClient.setTag(newRunId, tag.key, tag.value); - } - } - - // copy inputs - if ( - originalRun.inputs && - originalRun.inputs.dataset_inputs && - originalRun.inputs.dataset_inputs.length > 0 - ) { - // Log each dataset input separately - for (const datasetInput of originalRun.inputs.dataset_inputs) { - await this.RunClient.logInputs(newRunId, [datasetInput]); - } - } - - // update the new run name - if (runName) { - await this.RunClient.setTag(newRunId, 'mlflow.runName', runName); - } - - // handle models (reference only) - const modelVersions = - await this.ModelVersionManagement.searchModelVersions( - `run_id = '${runId}'` - ); - if (modelVersions && modelVersions.length > 0) { - for (const model of modelVersions) { - await this.RunClient.setTag( - newRunId, - `original_model_${model.name}`, - JSON.stringify({ - name: model.name, - version: model.version, - current_stage: model.current_stage, - source: model.source, - }) - ); - } - await this.RunClient.setTag( - newRunId, - 'mlflow.note.models', - 'Models not copied -see original run' - ); - } - - // set description for the new run - const description = - `This run was copied from experiment ${originalRun.info.experiment_id}, original run ID: ${runId}. ` + - `Original artifact URI: ${originalRun.info.artifact_uri}.`; - - await this.RunClient.setTag(newRunId, 'mlflow.note.content', description); - - // set additional tags for the new run - await this.RunClient.setTag(newRunId, 'mlflow.source.run_id', runId); - - await this.RunClient.setTag( - newRunId, - 'mlflow.source.experiment_id', - originalRun.info.experiment_id - ); - - await this.RunClient.setTag( - newRunId, - 'mlflow.note.artifacts', - 'Artifacts not copied - reference original run' - ); - - // return copy run details - return { - originalRunId: runId, - newRunId: newRunId, - targetExperimentId: targetExperimentId, - }; - } catch (error) { - console.error('Error copying run: ', error); - throw new Error('Failed to copy run.'); - } - } -} - -export { RunManager }; From 1afd3c42b01cd434bcca54e76785751c88f6610b Mon Sep 17 00:00:00 2001 From: Kyler-Chiago Date: Wed, 16 Oct 2024 17:24:58 -0700 Subject: [PATCH 153/357] yes --- mlflow/docs/.nojekyll | 1 + mlflow/docs/assets/highlight.css | 22 + mlflow/docs/assets/icons.js | 18 + mlflow/docs/assets/icons.svg | 1 + mlflow/docs/assets/main.js | 60 + mlflow/docs/assets/navigation.js | 1 + mlflow/docs/assets/search.js | 1 + mlflow/docs/assets/style.css | 1493 +++++++++++++++++++++ mlflow/docs/classes/default.html | 10 + mlflow/docs/code-standards.md | 88 -- mlflow/docs/index.html | 2 + mlflow/docs/tech-design-doc.md | 122 -- mlflow/package-lock.json | 645 +++++++++ mlflow/package.json | 1 + mlflow/src/index.ts | 3 + mlflow/src/mlflow.ts | 81 ++ mlflow/src/workflows/ExperimentManager.ts | 2 - mlflow/tsconfig.json | 4 + mlflow/typedoc.json | 5 + 19 files changed, 2348 insertions(+), 212 deletions(-) create mode 100644 mlflow/docs/.nojekyll create mode 100644 mlflow/docs/assets/highlight.css create mode 100644 mlflow/docs/assets/icons.js create mode 100644 mlflow/docs/assets/icons.svg create mode 100644 mlflow/docs/assets/main.js create mode 100644 mlflow/docs/assets/navigation.js create mode 100644 mlflow/docs/assets/search.js create mode 100644 mlflow/docs/assets/style.css create mode 100644 mlflow/docs/classes/default.html delete mode 100644 mlflow/docs/code-standards.md create mode 100644 mlflow/docs/index.html delete mode 100644 mlflow/docs/tech-design-doc.md create mode 100644 mlflow/src/index.ts create mode 100644 mlflow/src/mlflow.ts create mode 100644 mlflow/typedoc.json diff --git a/mlflow/docs/.nojekyll b/mlflow/docs/.nojekyll new file mode 100644 index 00000000..e2ac6616 --- /dev/null +++ b/mlflow/docs/.nojekyll @@ -0,0 +1 @@ +TypeDoc added this file to prevent GitHub Pages from using Jekyll. You can turn off this behavior by setting the `githubPages` option to false. \ No newline at end of file diff --git a/mlflow/docs/assets/highlight.css b/mlflow/docs/assets/highlight.css new file mode 100644 index 00000000..5674cf39 --- /dev/null +++ b/mlflow/docs/assets/highlight.css @@ -0,0 +1,22 @@ +:root { + --light-code-background: #FFFFFF; + --dark-code-background: #1E1E1E; +} + +@media (prefers-color-scheme: light) { :root { + --code-background: var(--light-code-background); +} } + +@media (prefers-color-scheme: dark) { :root { + --code-background: var(--dark-code-background); +} } + +:root[data-theme='light'] { + --code-background: var(--light-code-background); +} + +:root[data-theme='dark'] { + --code-background: var(--dark-code-background); +} + +pre, code { background: var(--code-background); } diff --git a/mlflow/docs/assets/icons.js b/mlflow/docs/assets/icons.js new file mode 100644 index 00000000..3dfbd322 --- /dev/null +++ b/mlflow/docs/assets/icons.js @@ -0,0 +1,18 @@ +(function() { + addIcons(); + function addIcons() { + if (document.readyState === "loading") return document.addEventListener("DOMContentLoaded", addIcons); + const svg = document.body.appendChild(document.createElementNS("http://www.w3.org/2000/svg", "svg")); + svg.innerHTML = `MMNEPVFCICPMFPCPTTAAATR`; + svg.style.display = "none"; + if (location.protocol === "file:") updateUseElements(); + } + + function updateUseElements() { + document.querySelectorAll("use").forEach(el => { + if (el.getAttribute("href").includes("#icon-")) { + el.setAttribute("href", el.getAttribute("href").replace(/.*#/, "#")); + } + }); + } +})() \ No newline at end of file diff --git a/mlflow/docs/assets/icons.svg b/mlflow/docs/assets/icons.svg new file mode 100644 index 00000000..a19417dc --- /dev/null +++ b/mlflow/docs/assets/icons.svg @@ -0,0 +1 @@ +MMNEPVFCICPMFPCPTTAAATR \ No newline at end of file diff --git a/mlflow/docs/assets/main.js b/mlflow/docs/assets/main.js new file mode 100644 index 00000000..99097a05 --- /dev/null +++ b/mlflow/docs/assets/main.js @@ -0,0 +1,60 @@ +"use strict"; +window.translations={"copy":"Copy","copied":"Copied!","normally_hidden":"This member is normally hidden due to your filter settings."}; +"use strict";(()=>{var Pe=Object.create;var ie=Object.defineProperty;var Oe=Object.getOwnPropertyDescriptor;var _e=Object.getOwnPropertyNames;var Re=Object.getPrototypeOf,Me=Object.prototype.hasOwnProperty;var Fe=(t,e)=>()=>(e||t((e={exports:{}}).exports,e),e.exports);var De=(t,e,n,r)=>{if(e&&typeof e=="object"||typeof e=="function")for(let i of _e(e))!Me.call(t,i)&&i!==n&&ie(t,i,{get:()=>e[i],enumerable:!(r=Oe(e,i))||r.enumerable});return t};var Ae=(t,e,n)=>(n=t!=null?Pe(Re(t)):{},De(e||!t||!t.__esModule?ie(n,"default",{value:t,enumerable:!0}):n,t));var ue=Fe((ae,le)=>{(function(){var t=function(e){var n=new t.Builder;return n.pipeline.add(t.trimmer,t.stopWordFilter,t.stemmer),n.searchPipeline.add(t.stemmer),e.call(n,n),n.build()};t.version="2.3.9";t.utils={},t.utils.warn=function(e){return function(n){e.console&&console.warn&&console.warn(n)}}(this),t.utils.asString=function(e){return e==null?"":e.toString()},t.utils.clone=function(e){if(e==null)return e;for(var n=Object.create(null),r=Object.keys(e),i=0;i0){var d=t.utils.clone(n)||{};d.position=[a,u],d.index=s.length,s.push(new t.Token(r.slice(a,o),d))}a=o+1}}return s},t.tokenizer.separator=/[\s\-]+/;t.Pipeline=function(){this._stack=[]},t.Pipeline.registeredFunctions=Object.create(null),t.Pipeline.registerFunction=function(e,n){n in this.registeredFunctions&&t.utils.warn("Overwriting existing registered function: "+n),e.label=n,t.Pipeline.registeredFunctions[e.label]=e},t.Pipeline.warnIfFunctionNotRegistered=function(e){var n=e.label&&e.label in this.registeredFunctions;n||t.utils.warn(`Function is not registered with pipeline. This may cause problems when serialising the index. +`,e)},t.Pipeline.load=function(e){var n=new t.Pipeline;return e.forEach(function(r){var i=t.Pipeline.registeredFunctions[r];if(i)n.add(i);else throw new Error("Cannot load unregistered function: "+r)}),n},t.Pipeline.prototype.add=function(){var e=Array.prototype.slice.call(arguments);e.forEach(function(n){t.Pipeline.warnIfFunctionNotRegistered(n),this._stack.push(n)},this)},t.Pipeline.prototype.after=function(e,n){t.Pipeline.warnIfFunctionNotRegistered(n);var r=this._stack.indexOf(e);if(r==-1)throw new Error("Cannot find existingFn");r=r+1,this._stack.splice(r,0,n)},t.Pipeline.prototype.before=function(e,n){t.Pipeline.warnIfFunctionNotRegistered(n);var r=this._stack.indexOf(e);if(r==-1)throw new Error("Cannot find existingFn");this._stack.splice(r,0,n)},t.Pipeline.prototype.remove=function(e){var n=this._stack.indexOf(e);n!=-1&&this._stack.splice(n,1)},t.Pipeline.prototype.run=function(e){for(var n=this._stack.length,r=0;r1&&(oe&&(r=s),o!=e);)i=r-n,s=n+Math.floor(i/2),o=this.elements[s*2];if(o==e||o>e)return s*2;if(ol?d+=2:a==l&&(n+=r[u+1]*i[d+1],u+=2,d+=2);return n},t.Vector.prototype.similarity=function(e){return this.dot(e)/this.magnitude()||0},t.Vector.prototype.toArray=function(){for(var e=new Array(this.elements.length/2),n=1,r=0;n0){var o=s.str.charAt(0),a;o in s.node.edges?a=s.node.edges[o]:(a=new t.TokenSet,s.node.edges[o]=a),s.str.length==1&&(a.final=!0),i.push({node:a,editsRemaining:s.editsRemaining,str:s.str.slice(1)})}if(s.editsRemaining!=0){if("*"in s.node.edges)var l=s.node.edges["*"];else{var l=new t.TokenSet;s.node.edges["*"]=l}if(s.str.length==0&&(l.final=!0),i.push({node:l,editsRemaining:s.editsRemaining-1,str:s.str}),s.str.length>1&&i.push({node:s.node,editsRemaining:s.editsRemaining-1,str:s.str.slice(1)}),s.str.length==1&&(s.node.final=!0),s.str.length>=1){if("*"in s.node.edges)var u=s.node.edges["*"];else{var u=new t.TokenSet;s.node.edges["*"]=u}s.str.length==1&&(u.final=!0),i.push({node:u,editsRemaining:s.editsRemaining-1,str:s.str.slice(1)})}if(s.str.length>1){var d=s.str.charAt(0),m=s.str.charAt(1),p;m in s.node.edges?p=s.node.edges[m]:(p=new t.TokenSet,s.node.edges[m]=p),s.str.length==1&&(p.final=!0),i.push({node:p,editsRemaining:s.editsRemaining-1,str:d+s.str.slice(2)})}}}return r},t.TokenSet.fromString=function(e){for(var n=new t.TokenSet,r=n,i=0,s=e.length;i=e;n--){var r=this.uncheckedNodes[n],i=r.child.toString();i in this.minimizedNodes?r.parent.edges[r.char]=this.minimizedNodes[i]:(r.child._str=i,this.minimizedNodes[i]=r.child),this.uncheckedNodes.pop()}};t.Index=function(e){this.invertedIndex=e.invertedIndex,this.fieldVectors=e.fieldVectors,this.tokenSet=e.tokenSet,this.fields=e.fields,this.pipeline=e.pipeline},t.Index.prototype.search=function(e){return this.query(function(n){var r=new t.QueryParser(e,n);r.parse()})},t.Index.prototype.query=function(e){for(var n=new t.Query(this.fields),r=Object.create(null),i=Object.create(null),s=Object.create(null),o=Object.create(null),a=Object.create(null),l=0;l1?this._b=1:this._b=e},t.Builder.prototype.k1=function(e){this._k1=e},t.Builder.prototype.add=function(e,n){var r=e[this._ref],i=Object.keys(this._fields);this._documents[r]=n||{},this.documentCount+=1;for(var s=0;s=this.length)return t.QueryLexer.EOS;var e=this.str.charAt(this.pos);return this.pos+=1,e},t.QueryLexer.prototype.width=function(){return this.pos-this.start},t.QueryLexer.prototype.ignore=function(){this.start==this.pos&&(this.pos+=1),this.start=this.pos},t.QueryLexer.prototype.backup=function(){this.pos-=1},t.QueryLexer.prototype.acceptDigitRun=function(){var e,n;do e=this.next(),n=e.charCodeAt(0);while(n>47&&n<58);e!=t.QueryLexer.EOS&&this.backup()},t.QueryLexer.prototype.more=function(){return this.pos1&&(e.backup(),e.emit(t.QueryLexer.TERM)),e.ignore(),e.more())return t.QueryLexer.lexText},t.QueryLexer.lexEditDistance=function(e){return e.ignore(),e.acceptDigitRun(),e.emit(t.QueryLexer.EDIT_DISTANCE),t.QueryLexer.lexText},t.QueryLexer.lexBoost=function(e){return e.ignore(),e.acceptDigitRun(),e.emit(t.QueryLexer.BOOST),t.QueryLexer.lexText},t.QueryLexer.lexEOS=function(e){e.width()>0&&e.emit(t.QueryLexer.TERM)},t.QueryLexer.termSeparator=t.tokenizer.separator,t.QueryLexer.lexText=function(e){for(;;){var n=e.next();if(n==t.QueryLexer.EOS)return t.QueryLexer.lexEOS;if(n.charCodeAt(0)==92){e.escapeCharacter();continue}if(n==":")return t.QueryLexer.lexField;if(n=="~")return e.backup(),e.width()>0&&e.emit(t.QueryLexer.TERM),t.QueryLexer.lexEditDistance;if(n=="^")return e.backup(),e.width()>0&&e.emit(t.QueryLexer.TERM),t.QueryLexer.lexBoost;if(n=="+"&&e.width()===1||n=="-"&&e.width()===1)return e.emit(t.QueryLexer.PRESENCE),t.QueryLexer.lexText;if(n.match(t.QueryLexer.termSeparator))return t.QueryLexer.lexTerm}},t.QueryParser=function(e,n){this.lexer=new t.QueryLexer(e),this.query=n,this.currentClause={},this.lexemeIdx=0},t.QueryParser.prototype.parse=function(){this.lexer.run(),this.lexemes=this.lexer.lexemes;for(var e=t.QueryParser.parseClause;e;)e=e(this);return this.query},t.QueryParser.prototype.peekLexeme=function(){return this.lexemes[this.lexemeIdx]},t.QueryParser.prototype.consumeLexeme=function(){var e=this.peekLexeme();return this.lexemeIdx+=1,e},t.QueryParser.prototype.nextClause=function(){var e=this.currentClause;this.query.clause(e),this.currentClause={}},t.QueryParser.parseClause=function(e){var n=e.peekLexeme();if(n!=null)switch(n.type){case t.QueryLexer.PRESENCE:return t.QueryParser.parsePresence;case t.QueryLexer.FIELD:return t.QueryParser.parseField;case t.QueryLexer.TERM:return t.QueryParser.parseTerm;default:var r="expected either a field or a term, found "+n.type;throw n.str.length>=1&&(r+=" with value '"+n.str+"'"),new t.QueryParseError(r,n.start,n.end)}},t.QueryParser.parsePresence=function(e){var n=e.consumeLexeme();if(n!=null){switch(n.str){case"-":e.currentClause.presence=t.Query.presence.PROHIBITED;break;case"+":e.currentClause.presence=t.Query.presence.REQUIRED;break;default:var r="unrecognised presence operator'"+n.str+"'";throw new t.QueryParseError(r,n.start,n.end)}var i=e.peekLexeme();if(i==null){var r="expecting term or field, found nothing";throw new t.QueryParseError(r,n.start,n.end)}switch(i.type){case t.QueryLexer.FIELD:return t.QueryParser.parseField;case t.QueryLexer.TERM:return t.QueryParser.parseTerm;default:var r="expecting term or field, found '"+i.type+"'";throw new t.QueryParseError(r,i.start,i.end)}}},t.QueryParser.parseField=function(e){var n=e.consumeLexeme();if(n!=null){if(e.query.allFields.indexOf(n.str)==-1){var r=e.query.allFields.map(function(o){return"'"+o+"'"}).join(", "),i="unrecognised field '"+n.str+"', possible fields: "+r;throw new t.QueryParseError(i,n.start,n.end)}e.currentClause.fields=[n.str];var s=e.peekLexeme();if(s==null){var i="expecting term, found nothing";throw new t.QueryParseError(i,n.start,n.end)}switch(s.type){case t.QueryLexer.TERM:return t.QueryParser.parseTerm;default:var i="expecting term, found '"+s.type+"'";throw new t.QueryParseError(i,s.start,s.end)}}},t.QueryParser.parseTerm=function(e){var n=e.consumeLexeme();if(n!=null){e.currentClause.term=n.str.toLowerCase(),n.str.indexOf("*")!=-1&&(e.currentClause.usePipeline=!1);var r=e.peekLexeme();if(r==null){e.nextClause();return}switch(r.type){case t.QueryLexer.TERM:return e.nextClause(),t.QueryParser.parseTerm;case t.QueryLexer.FIELD:return e.nextClause(),t.QueryParser.parseField;case t.QueryLexer.EDIT_DISTANCE:return t.QueryParser.parseEditDistance;case t.QueryLexer.BOOST:return t.QueryParser.parseBoost;case t.QueryLexer.PRESENCE:return e.nextClause(),t.QueryParser.parsePresence;default:var i="Unexpected lexeme type '"+r.type+"'";throw new t.QueryParseError(i,r.start,r.end)}}},t.QueryParser.parseEditDistance=function(e){var n=e.consumeLexeme();if(n!=null){var r=parseInt(n.str,10);if(isNaN(r)){var i="edit distance must be numeric";throw new t.QueryParseError(i,n.start,n.end)}e.currentClause.editDistance=r;var s=e.peekLexeme();if(s==null){e.nextClause();return}switch(s.type){case t.QueryLexer.TERM:return e.nextClause(),t.QueryParser.parseTerm;case t.QueryLexer.FIELD:return e.nextClause(),t.QueryParser.parseField;case t.QueryLexer.EDIT_DISTANCE:return t.QueryParser.parseEditDistance;case t.QueryLexer.BOOST:return t.QueryParser.parseBoost;case t.QueryLexer.PRESENCE:return e.nextClause(),t.QueryParser.parsePresence;default:var i="Unexpected lexeme type '"+s.type+"'";throw new t.QueryParseError(i,s.start,s.end)}}},t.QueryParser.parseBoost=function(e){var n=e.consumeLexeme();if(n!=null){var r=parseInt(n.str,10);if(isNaN(r)){var i="boost must be numeric";throw new t.QueryParseError(i,n.start,n.end)}e.currentClause.boost=r;var s=e.peekLexeme();if(s==null){e.nextClause();return}switch(s.type){case t.QueryLexer.TERM:return e.nextClause(),t.QueryParser.parseTerm;case t.QueryLexer.FIELD:return e.nextClause(),t.QueryParser.parseField;case t.QueryLexer.EDIT_DISTANCE:return t.QueryParser.parseEditDistance;case t.QueryLexer.BOOST:return t.QueryParser.parseBoost;case t.QueryLexer.PRESENCE:return e.nextClause(),t.QueryParser.parsePresence;default:var i="Unexpected lexeme type '"+s.type+"'";throw new t.QueryParseError(i,s.start,s.end)}}},function(e,n){typeof define=="function"&&define.amd?define(n):typeof ae=="object"?le.exports=n():e.lunr=n()}(this,function(){return t})})()});var se=[];function G(t,e){se.push({selector:e,constructor:t})}var U=class{constructor(){this.alwaysVisibleMember=null;this.createComponents(document.body),this.ensureFocusedElementVisible(),this.listenForCodeCopies(),window.addEventListener("hashchange",()=>this.ensureFocusedElementVisible()),document.body.style.display||(this.ensureFocusedElementVisible(),this.updateIndexVisibility(),this.scrollToHash())}createComponents(e){se.forEach(n=>{e.querySelectorAll(n.selector).forEach(r=>{r.dataset.hasInstance||(new n.constructor({el:r,app:this}),r.dataset.hasInstance=String(!0))})})}filterChanged(){this.ensureFocusedElementVisible()}showPage(){document.body.style.display&&(document.body.style.removeProperty("display"),this.ensureFocusedElementVisible(),this.updateIndexVisibility(),this.scrollToHash())}scrollToHash(){if(location.hash){let e=document.getElementById(location.hash.substring(1));if(!e)return;e.scrollIntoView({behavior:"instant",block:"start"})}}ensureActivePageVisible(){let e=document.querySelector(".tsd-navigation .current"),n=e?.parentElement;for(;n&&!n.classList.contains(".tsd-navigation");)n instanceof HTMLDetailsElement&&(n.open=!0),n=n.parentElement;if(e&&!Ve(e)){let r=e.getBoundingClientRect().top-document.documentElement.clientHeight/4;document.querySelector(".site-menu").scrollTop=r,document.querySelector(".col-sidebar").scrollTop=r}}updateIndexVisibility(){let e=document.querySelector(".tsd-index-content"),n=e?.open;e&&(e.open=!0),document.querySelectorAll(".tsd-index-section").forEach(r=>{r.style.display="block";let i=Array.from(r.querySelectorAll(".tsd-index-link")).every(s=>s.offsetParent==null);r.style.display=i?"none":"block"}),e&&(e.open=n)}ensureFocusedElementVisible(){if(this.alwaysVisibleMember&&(this.alwaysVisibleMember.classList.remove("always-visible"),this.alwaysVisibleMember.firstElementChild.remove(),this.alwaysVisibleMember=null),!location.hash)return;let e=document.getElementById(location.hash.substring(1));if(!e)return;let n=e.parentElement;for(;n&&n.tagName!=="SECTION";)n=n.parentElement;if(!n)return;let r=n.offsetParent==null,i=n;for(;i!==document.body;)i instanceof HTMLDetailsElement&&(i.open=!0),i=i.parentElement;if(n.offsetParent==null){this.alwaysVisibleMember=n,n.classList.add("always-visible");let s=document.createElement("p");s.classList.add("warning"),s.textContent=window.translations.normally_hidden,n.prepend(s)}r&&e.scrollIntoView()}listenForCodeCopies(){document.querySelectorAll("pre > button").forEach(e=>{let n;e.addEventListener("click",()=>{e.previousElementSibling instanceof HTMLElement&&navigator.clipboard.writeText(e.previousElementSibling.innerText.trim()),e.textContent=window.translations.copied,e.classList.add("visible"),clearTimeout(n),n=setTimeout(()=>{e.classList.remove("visible"),n=setTimeout(()=>{e.textContent=window.translations.copy},100)},1e3)})})}};function Ve(t){let e=t.getBoundingClientRect(),n=Math.max(document.documentElement.clientHeight,window.innerHeight);return!(e.bottom<0||e.top-n>=0)}var oe=(t,e=100)=>{let n;return()=>{clearTimeout(n),n=setTimeout(()=>t(),e)}};var pe=Ae(ue());async function ce(t,e){if(!window.searchData)return;let n=await fetch(window.searchData),r=new Blob([await n.arrayBuffer()]).stream().pipeThrough(new DecompressionStream("gzip")),i=await new Response(r).json();t.data=i,t.index=pe.Index.load(i.index),e.classList.remove("loading"),e.classList.add("ready")}function fe(){let t=document.getElementById("tsd-search");if(!t)return;let e={base:t.dataset.base+"/"},n=document.getElementById("tsd-search-script");t.classList.add("loading"),n&&(n.addEventListener("error",()=>{t.classList.remove("loading"),t.classList.add("failure")}),n.addEventListener("load",()=>{ce(e,t)}),ce(e,t));let r=document.querySelector("#tsd-search input"),i=document.querySelector("#tsd-search .results");if(!r||!i)throw new Error("The input field or the result list wrapper was not found");i.addEventListener("mouseup",()=>{te(t)}),r.addEventListener("focus",()=>t.classList.add("has-focus")),He(t,i,r,e)}function He(t,e,n,r){n.addEventListener("input",oe(()=>{Ne(t,e,n,r)},200)),n.addEventListener("keydown",i=>{i.key=="Enter"?Be(e,t):i.key=="ArrowUp"?(de(e,n,-1),i.preventDefault()):i.key==="ArrowDown"&&(de(e,n,1),i.preventDefault())}),document.body.addEventListener("keypress",i=>{i.altKey||i.ctrlKey||i.metaKey||!n.matches(":focus")&&i.key==="/"&&(i.preventDefault(),n.focus())}),document.body.addEventListener("keyup",i=>{t.classList.contains("has-focus")&&(i.key==="Escape"||!e.matches(":focus-within")&&!n.matches(":focus"))&&(n.blur(),te(t))})}function te(t){t.classList.remove("has-focus")}function Ne(t,e,n,r){if(!r.index||!r.data)return;e.textContent="";let i=n.value.trim(),s;if(i){let o=i.split(" ").map(a=>a.length?`*${a}*`:"").join(" ");s=r.index.search(o)}else s=[];for(let o=0;oa.score-o.score);for(let o=0,a=Math.min(10,s.length);o`,d=he(l.name,i);globalThis.DEBUG_SEARCH_WEIGHTS&&(d+=` (score: ${s[o].score.toFixed(2)})`),l.parent&&(d=` + ${he(l.parent,i)}.${d}`);let m=document.createElement("li");m.classList.value=l.classes??"";let p=document.createElement("a");p.href=r.base+l.url,p.innerHTML=u+d,m.append(p),p.addEventListener("focus",()=>{e.querySelector(".current")?.classList.remove("current"),m.classList.add("current")}),e.appendChild(m)}}function de(t,e,n){let r=t.querySelector(".current");if(!r)r=t.querySelector(n==1?"li:first-child":"li:last-child"),r&&r.classList.add("current");else{let i=r;if(n===1)do i=i.nextElementSibling??void 0;while(i instanceof HTMLElement&&i.offsetParent==null);else do i=i.previousElementSibling??void 0;while(i instanceof HTMLElement&&i.offsetParent==null);i?(r.classList.remove("current"),i.classList.add("current")):n===-1&&(r.classList.remove("current"),e.focus())}}function Be(t,e){let n=t.querySelector(".current");if(n||(n=t.querySelector("li:first-child")),n){let r=n.querySelector("a");r&&(window.location.href=r.href),te(e)}}function he(t,e){if(e==="")return t;let n=t.toLocaleLowerCase(),r=e.toLocaleLowerCase(),i=[],s=0,o=n.indexOf(r);for(;o!=-1;)i.push(ee(t.substring(s,o)),`${ee(t.substring(o,o+r.length))}`),s=o+r.length,o=n.indexOf(r,s);return i.push(ee(t.substring(s))),i.join("")}var je={"&":"&","<":"<",">":">","'":"'",'"':"""};function ee(t){return t.replace(/[&<>"'"]/g,e=>je[e])}var I=class{constructor(e){this.el=e.el,this.app=e.app}};var F="mousedown",ye="mousemove",N="mouseup",J={x:0,y:0},me=!1,ne=!1,qe=!1,D=!1,ve=/Android|webOS|iPhone|iPad|iPod|BlackBerry|IEMobile|Opera Mini/i.test(navigator.userAgent);document.documentElement.classList.add(ve?"is-mobile":"not-mobile");ve&&"ontouchstart"in document.documentElement&&(qe=!0,F="touchstart",ye="touchmove",N="touchend");document.addEventListener(F,t=>{ne=!0,D=!1;let e=F=="touchstart"?t.targetTouches[0]:t;J.y=e.pageY||0,J.x=e.pageX||0});document.addEventListener(ye,t=>{if(ne&&!D){let e=F=="touchstart"?t.targetTouches[0]:t,n=J.x-(e.pageX||0),r=J.y-(e.pageY||0);D=Math.sqrt(n*n+r*r)>10}});document.addEventListener(N,()=>{ne=!1});document.addEventListener("click",t=>{me&&(t.preventDefault(),t.stopImmediatePropagation(),me=!1)});var X=class extends I{constructor(e){super(e),this.className=this.el.dataset.toggle||"",this.el.addEventListener(N,n=>this.onPointerUp(n)),this.el.addEventListener("click",n=>n.preventDefault()),document.addEventListener(F,n=>this.onDocumentPointerDown(n)),document.addEventListener(N,n=>this.onDocumentPointerUp(n))}setActive(e){if(this.active==e)return;this.active=e,document.documentElement.classList.toggle("has-"+this.className,e),this.el.classList.toggle("active",e);let n=(this.active?"to-has-":"from-has-")+this.className;document.documentElement.classList.add(n),setTimeout(()=>document.documentElement.classList.remove(n),500)}onPointerUp(e){D||(this.setActive(!0),e.preventDefault())}onDocumentPointerDown(e){if(this.active){if(e.target.closest(".col-sidebar, .tsd-filter-group"))return;this.setActive(!1)}}onDocumentPointerUp(e){if(!D&&this.active&&e.target.closest(".col-sidebar")){let n=e.target.closest("a");if(n){let r=window.location.href;r.indexOf("#")!=-1&&(r=r.substring(0,r.indexOf("#"))),n.href.substring(0,r.length)==r&&setTimeout(()=>this.setActive(!1),250)}}}};var re;try{re=localStorage}catch{re={getItem(){return null},setItem(){}}}var Q=re;var ge=document.head.appendChild(document.createElement("style"));ge.dataset.for="filters";var Y=class extends I{constructor(e){super(e),this.key=`filter-${this.el.name}`,this.value=this.el.checked,this.el.addEventListener("change",()=>{this.setLocalStorage(this.el.checked)}),this.setLocalStorage(this.fromLocalStorage()),ge.innerHTML+=`html:not(.${this.key}) .tsd-is-${this.el.name} { display: none; } +`,this.app.updateIndexVisibility()}fromLocalStorage(){let e=Q.getItem(this.key);return e?e==="true":this.el.checked}setLocalStorage(e){Q.setItem(this.key,e.toString()),this.value=e,this.handleValueChange()}handleValueChange(){this.el.checked=this.value,document.documentElement.classList.toggle(this.key,this.value),this.app.filterChanged(),this.app.updateIndexVisibility()}};var Z=class extends I{constructor(e){super(e),this.summary=this.el.querySelector(".tsd-accordion-summary"),this.icon=this.summary.querySelector("svg"),this.key=`tsd-accordion-${this.summary.dataset.key??this.summary.textContent.trim().replace(/\s+/g,"-").toLowerCase()}`;let n=Q.getItem(this.key);this.el.open=n?n==="true":this.el.open,this.el.addEventListener("toggle",()=>this.update());let r=this.summary.querySelector("a");r&&r.addEventListener("click",()=>{location.assign(r.href)}),this.update()}update(){this.icon.style.transform=`rotate(${this.el.open?0:-90}deg)`,Q.setItem(this.key,this.el.open.toString())}};function Ee(t){let e=Q.getItem("tsd-theme")||"os";t.value=e,xe(e),t.addEventListener("change",()=>{Q.setItem("tsd-theme",t.value),xe(t.value)})}function xe(t){document.documentElement.dataset.theme=t}var K;function we(){let t=document.getElementById("tsd-nav-script");t&&(t.addEventListener("load",Le),Le())}async function Le(){let t=document.getElementById("tsd-nav-container");if(!t||!window.navigationData)return;let n=await(await fetch(window.navigationData)).arrayBuffer(),r=new Blob([n]).stream().pipeThrough(new DecompressionStream("gzip")),i=await new Response(r).json();K=t.dataset.base,K.endsWith("/")||(K+="/"),t.innerHTML="";for(let s of i)Se(s,t,[]);window.app.createComponents(t),window.app.showPage(),window.app.ensureActivePageVisible()}function Se(t,e,n){let r=e.appendChild(document.createElement("li"));if(t.children){let i=[...n,t.text],s=r.appendChild(document.createElement("details"));s.className=t.class?`${t.class} tsd-accordion`:"tsd-accordion";let o=s.appendChild(document.createElement("summary"));o.className="tsd-accordion-summary",o.dataset.key=i.join("$"),o.innerHTML='',be(t,o);let a=s.appendChild(document.createElement("div"));a.className="tsd-accordion-details";let l=a.appendChild(document.createElement("ul"));l.className="tsd-nested-navigation";for(let u of t.children)Se(u,l,i)}else be(t,r,t.class)}function be(t,e,n){if(t.path){let r=e.appendChild(document.createElement("a"));r.href=K+t.path,n&&(r.className=n),location.pathname===r.pathname&&!r.href.includes("#")&&r.classList.add("current"),t.kind&&(r.innerHTML=``),r.appendChild(document.createElement("span")).textContent=t.text}else{let r=e.appendChild(document.createElement("span"));r.innerHTML='',r.appendChild(document.createElement("span")).textContent=t.text}}G(X,"a[data-toggle]");G(Z,".tsd-accordion");G(Y,".tsd-filter-item input[type=checkbox]");var Te=document.getElementById("tsd-theme");Te&&Ee(Te);var $e=new U;Object.defineProperty(window,"app",{value:$e});fe();we();})(); +/*! Bundled license information: + +lunr/lunr.js: + (** + * lunr - http://lunrjs.com - A bit like Solr, but much smaller and not as bright - 2.3.9 + * Copyright (C) 2020 Oliver Nightingale + * @license MIT + *) + (*! + * lunr.utils + * Copyright (C) 2020 Oliver Nightingale + *) + (*! + * lunr.Set + * Copyright (C) 2020 Oliver Nightingale + *) + (*! + * lunr.tokenizer + * Copyright (C) 2020 Oliver Nightingale + *) + (*! + * lunr.Pipeline + * Copyright (C) 2020 Oliver Nightingale + *) + (*! + * lunr.Vector + * Copyright (C) 2020 Oliver Nightingale + *) + (*! + * lunr.stemmer + * Copyright (C) 2020 Oliver Nightingale + * Includes code from - http://tartarus.org/~martin/PorterStemmer/js.txt + *) + (*! + * lunr.stopWordFilter + * Copyright (C) 2020 Oliver Nightingale + *) + (*! + * lunr.trimmer + * Copyright (C) 2020 Oliver Nightingale + *) + (*! + * lunr.TokenSet + * Copyright (C) 2020 Oliver Nightingale + *) + (*! + * lunr.Index + * Copyright (C) 2020 Oliver Nightingale + *) + (*! + * lunr.Builder + * Copyright (C) 2020 Oliver Nightingale + *) +*/ diff --git a/mlflow/docs/assets/navigation.js b/mlflow/docs/assets/navigation.js new file mode 100644 index 00000000..05fe130c --- /dev/null +++ b/mlflow/docs/assets/navigation.js @@ -0,0 +1 @@ +window.navigationData = "data:application/octet-stream;base64,H4sIAAAAAAAAA4uuVipJrShRslJKSU1LLM0pUdJRKkgsyVCyUkrOSSwuTi3Wh0roZZTk5ijpKGVn5qUoWRkaWdTGAgAM4TeJPQAAAA==" \ No newline at end of file diff --git a/mlflow/docs/assets/search.js b/mlflow/docs/assets/search.js new file mode 100644 index 00000000..4b4f5ef3 --- /dev/null +++ b/mlflow/docs/assets/search.js @@ -0,0 +1 @@ +window.searchData = "data:application/octet-stream;base64,H4sIAAAAAAAAA6WWS4+bMBRG/8vt1soE82ZbddFFNrOYjYUqBHcyVnlExkynRfz3itc4rt2EJDtk7jmfwdeGHkTzq4WE9fCT1wUkDo0I1FmFkECBr1lXSiDQiRISyMusbbF9WsZ3b7IqgazDkAAMZPX4Dv305E3dStHlshEXXV/0wjMvgVMmsJZnk1JRdO+pOfOaS56V/A8eUL41RXs50VZ+V+4R5bePEwpeYS2/lnyELibbgXuzn7t6Y+h55b1ph6bA8hmPvJXi98ZcO/PQDF5QtLzZ+uBW5PG1PmR1dsQrjf0f4oHV3hqrlT70trcm/lN8JTMlwOsCPyDp4X1eHEiA7txdDAReOZbFeDzNkyGQN1U1r1zR5N10mS5lLzieG2PxXP20B8L2xIl3MfXSlLAVnm5MA6tDjUygA4Q5NtAxQEcDKRBGbSA1QKqBLhDm2kDXAF0N9IAwzwZ6BuhpoA+E+TbQN0BfAwMgLLCBgQEGGhgCYaENDA0w1MAICItsYGSAkQbGQFhsA2MDnEemZnxHIbH4PjclY/rXq4cfS7s66wbpwYGkHwbVnEk/nPXneG/KWr+myrFXjv0mxxElfp4j+XKIKZ+rfO7tvmrds0oYKmG4VViN+9/iipUrvskllo+G+by+Uvo3KZeTxjQGyhhsNYrOIvKUyLtBZHlvkTJFm0zqn6Za/2mUjSobvW5LCZz4CUteIyQsHYa/JpQL0TAKAAA="; \ No newline at end of file diff --git a/mlflow/docs/assets/style.css b/mlflow/docs/assets/style.css new file mode 100644 index 00000000..178bfb02 --- /dev/null +++ b/mlflow/docs/assets/style.css @@ -0,0 +1,1493 @@ +:root { + /* Light */ + --light-color-background: #f2f4f8; + --light-color-background-secondary: #eff0f1; + --light-color-warning-text: #222; + --light-color-background-warning: #e6e600; + --light-color-accent: #c5c7c9; + --light-color-active-menu-item: var(--light-color-accent); + --light-color-text: #222; + --light-color-text-aside: #6e6e6e; + + --light-color-icon-background: var(--light-color-background); + --light-color-icon-text: var(--light-color-text); + + --light-color-comment-tag-text: var(--light-color-text); + --light-color-comment-tag: var(--light-color-background); + + --light-color-link: #1f70c2; + --light-color-focus-outline: #3584e4; + + --light-color-ts-keyword: #056bd6; + --light-color-ts-project: #b111c9; + --light-color-ts-module: var(--light-color-ts-project); + --light-color-ts-namespace: var(--light-color-ts-project); + --light-color-ts-enum: #7e6f15; + --light-color-ts-enum-member: var(--light-color-ts-enum); + --light-color-ts-variable: #4760ec; + --light-color-ts-function: #572be7; + --light-color-ts-class: #1f70c2; + --light-color-ts-interface: #108024; + --light-color-ts-constructor: #4d7fff; + --light-color-ts-property: #ff984d; + --light-color-ts-method: #ff4db8; + --light-color-ts-reference: #ff4d82; + --light-color-ts-call-signature: var(--light-color-ts-method); + --light-color-ts-index-signature: var(--light-color-ts-property); + --light-color-ts-constructor-signature: var(--light-color-ts-constructor); + --light-color-ts-parameter: var(--light-color-ts-variable); + /* type literal not included as links will never be generated to it */ + --light-color-ts-type-parameter: #a55c0e; + --light-color-ts-accessor: #ff4d4d; + --light-color-ts-get-signature: var(--light-color-ts-accessor); + --light-color-ts-set-signature: var(--light-color-ts-accessor); + --light-color-ts-type-alias: #d51270; + /* reference not included as links will be colored with the kind that it points to */ + --light-color-document: #000000; + + --light-external-icon: url("data:image/svg+xml;utf8,"); + --light-color-scheme: light; + + /* Dark */ + --dark-color-background: #2b2e33; + --dark-color-background-secondary: #1e2024; + --dark-color-background-warning: #bebe00; + --dark-color-warning-text: #222; + --dark-color-accent: #9096a2; + --dark-color-active-menu-item: #5d5d6a; + --dark-color-text: #f5f5f5; + --dark-color-text-aside: #dddddd; + + --dark-color-icon-background: var(--dark-color-background-secondary); + --dark-color-icon-text: var(--dark-color-text); + + --dark-color-comment-tag-text: var(--dark-color-text); + --dark-color-comment-tag: var(--dark-color-background); + + --dark-color-link: #00aff4; + --dark-color-focus-outline: #4c97f2; + + --dark-color-ts-keyword: #3399ff; + --dark-color-ts-project: #e358ff; + --dark-color-ts-module: var(--dark-color-ts-project); + --dark-color-ts-namespace: var(--dark-color-ts-project); + --dark-color-ts-enum: #f4d93e; + --dark-color-ts-enum-member: var(--dark-color-ts-enum); + --dark-color-ts-variable: #798dff; + --dark-color-ts-function: #a280ff; + --dark-color-ts-class: #8ac4ff; + --dark-color-ts-interface: #6cff87; + --dark-color-ts-constructor: #4d7fff; + --dark-color-ts-property: #ff984d; + --dark-color-ts-method: #ff4db8; + --dark-color-ts-reference: #ff4d82; + --dark-color-ts-call-signature: var(--dark-color-ts-method); + --dark-color-ts-index-signature: var(--dark-color-ts-property); + --dark-color-ts-constructor-signature: var(--dark-color-ts-constructor); + --dark-color-ts-parameter: var(--dark-color-ts-variable); + /* type literal not included as links will never be generated to it */ + --dark-color-ts-type-parameter: #e07d13; + --dark-color-ts-accessor: #ff4d4d; + --dark-color-ts-get-signature: var(--dark-color-ts-accessor); + --dark-color-ts-set-signature: var(--dark-color-ts-accessor); + --dark-color-ts-type-alias: #ff6492; + /* reference not included as links will be colored with the kind that it points to */ + --dark-color-document: #ffffff; + + --dark-external-icon: url("data:image/svg+xml;utf8,"); + --dark-color-scheme: dark; +} + +@media (prefers-color-scheme: light) { + :root { + --color-background: var(--light-color-background); + --color-background-secondary: var(--light-color-background-secondary); + --color-background-warning: var(--light-color-background-warning); + --color-warning-text: var(--light-color-warning-text); + --color-accent: var(--light-color-accent); + --color-active-menu-item: var(--light-color-active-menu-item); + --color-text: var(--light-color-text); + --color-text-aside: var(--light-color-text-aside); + + --color-icon-background: var(--light-color-icon-background); + --color-icon-text: var(--light-color-icon-text); + + --color-comment-tag-text: var(--light-color-text); + --color-comment-tag: var(--light-color-background); + + --color-link: var(--light-color-link); + --color-focus-outline: var(--light-color-focus-outline); + + --color-ts-keyword: var(--light-color-ts-keyword); + --color-ts-project: var(--light-color-ts-project); + --color-ts-module: var(--light-color-ts-module); + --color-ts-namespace: var(--light-color-ts-namespace); + --color-ts-enum: var(--light-color-ts-enum); + --color-ts-enum-member: var(--light-color-ts-enum-member); + --color-ts-variable: var(--light-color-ts-variable); + --color-ts-function: var(--light-color-ts-function); + --color-ts-class: var(--light-color-ts-class); + --color-ts-interface: var(--light-color-ts-interface); + --color-ts-constructor: var(--light-color-ts-constructor); + --color-ts-property: var(--light-color-ts-property); + --color-ts-method: var(--light-color-ts-method); + --color-ts-reference: var(--light-color-ts-reference); + --color-ts-call-signature: var(--light-color-ts-call-signature); + --color-ts-index-signature: var(--light-color-ts-index-signature); + --color-ts-constructor-signature: var( + --light-color-ts-constructor-signature + ); + --color-ts-parameter: var(--light-color-ts-parameter); + --color-ts-type-parameter: var(--light-color-ts-type-parameter); + --color-ts-accessor: var(--light-color-ts-accessor); + --color-ts-get-signature: var(--light-color-ts-get-signature); + --color-ts-set-signature: var(--light-color-ts-set-signature); + --color-ts-type-alias: var(--light-color-ts-type-alias); + --color-document: var(--light-color-document); + + --external-icon: var(--light-external-icon); + --color-scheme: var(--light-color-scheme); + } +} + +@media (prefers-color-scheme: dark) { + :root { + --color-background: var(--dark-color-background); + --color-background-secondary: var(--dark-color-background-secondary); + --color-background-warning: var(--dark-color-background-warning); + --color-warning-text: var(--dark-color-warning-text); + --color-accent: var(--dark-color-accent); + --color-active-menu-item: var(--dark-color-active-menu-item); + --color-text: var(--dark-color-text); + --color-text-aside: var(--dark-color-text-aside); + + --color-icon-background: var(--dark-color-icon-background); + --color-icon-text: var(--dark-color-icon-text); + + --color-comment-tag-text: var(--dark-color-text); + --color-comment-tag: var(--dark-color-background); + + --color-link: var(--dark-color-link); + --color-focus-outline: var(--dark-color-focus-outline); + + --color-ts-keyword: var(--dark-color-ts-keyword); + --color-ts-project: var(--dark-color-ts-project); + --color-ts-module: var(--dark-color-ts-module); + --color-ts-namespace: var(--dark-color-ts-namespace); + --color-ts-enum: var(--dark-color-ts-enum); + --color-ts-enum-member: var(--dark-color-ts-enum-member); + --color-ts-variable: var(--dark-color-ts-variable); + --color-ts-function: var(--dark-color-ts-function); + --color-ts-class: var(--dark-color-ts-class); + --color-ts-interface: var(--dark-color-ts-interface); + --color-ts-constructor: var(--dark-color-ts-constructor); + --color-ts-property: var(--dark-color-ts-property); + --color-ts-method: var(--dark-color-ts-method); + --color-ts-reference: var(--dark-color-ts-reference); + --color-ts-call-signature: var(--dark-color-ts-call-signature); + --color-ts-index-signature: var(--dark-color-ts-index-signature); + --color-ts-constructor-signature: var( + --dark-color-ts-constructor-signature + ); + --color-ts-parameter: var(--dark-color-ts-parameter); + --color-ts-type-parameter: var(--dark-color-ts-type-parameter); + --color-ts-accessor: var(--dark-color-ts-accessor); + --color-ts-get-signature: var(--dark-color-ts-get-signature); + --color-ts-set-signature: var(--dark-color-ts-set-signature); + --color-ts-type-alias: var(--dark-color-ts-type-alias); + --color-document: var(--dark-color-document); + + --external-icon: var(--dark-external-icon); + --color-scheme: var(--dark-color-scheme); + } +} + +html { + color-scheme: var(--color-scheme); +} + +body { + margin: 0; +} + +:root[data-theme="light"] { + --color-background: var(--light-color-background); + --color-background-secondary: var(--light-color-background-secondary); + --color-background-warning: var(--light-color-background-warning); + --color-warning-text: var(--light-color-warning-text); + --color-icon-background: var(--light-color-icon-background); + --color-accent: var(--light-color-accent); + --color-active-menu-item: var(--light-color-active-menu-item); + --color-text: var(--light-color-text); + --color-text-aside: var(--light-color-text-aside); + --color-icon-text: var(--light-color-icon-text); + + --color-comment-tag-text: var(--light-color-text); + --color-comment-tag: var(--light-color-background); + + --color-link: var(--light-color-link); + --color-focus-outline: var(--light-color-focus-outline); + + --color-ts-keyword: var(--light-color-ts-keyword); + --color-ts-project: var(--light-color-ts-project); + --color-ts-module: var(--light-color-ts-module); + --color-ts-namespace: var(--light-color-ts-namespace); + --color-ts-enum: var(--light-color-ts-enum); + --color-ts-enum-member: var(--light-color-ts-enum-member); + --color-ts-variable: var(--light-color-ts-variable); + --color-ts-function: var(--light-color-ts-function); + --color-ts-class: var(--light-color-ts-class); + --color-ts-interface: var(--light-color-ts-interface); + --color-ts-constructor: var(--light-color-ts-constructor); + --color-ts-property: var(--light-color-ts-property); + --color-ts-method: var(--light-color-ts-method); + --color-ts-reference: var(--light-color-ts-reference); + --color-ts-call-signature: var(--light-color-ts-call-signature); + --color-ts-index-signature: var(--light-color-ts-index-signature); + --color-ts-constructor-signature: var( + --light-color-ts-constructor-signature + ); + --color-ts-parameter: var(--light-color-ts-parameter); + --color-ts-type-parameter: var(--light-color-ts-type-parameter); + --color-ts-accessor: var(--light-color-ts-accessor); + --color-ts-get-signature: var(--light-color-ts-get-signature); + --color-ts-set-signature: var(--light-color-ts-set-signature); + --color-ts-type-alias: var(--light-color-ts-type-alias); + --color-document: var(--light-color-document); + + --external-icon: var(--light-external-icon); + --color-scheme: var(--light-color-scheme); +} + +:root[data-theme="dark"] { + --color-background: var(--dark-color-background); + --color-background-secondary: var(--dark-color-background-secondary); + --color-background-warning: var(--dark-color-background-warning); + --color-warning-text: var(--dark-color-warning-text); + --color-icon-background: var(--dark-color-icon-background); + --color-accent: var(--dark-color-accent); + --color-active-menu-item: var(--dark-color-active-menu-item); + --color-text: var(--dark-color-text); + --color-text-aside: var(--dark-color-text-aside); + --color-icon-text: var(--dark-color-icon-text); + + --color-comment-tag-text: var(--dark-color-text); + --color-comment-tag: var(--dark-color-background); + + --color-link: var(--dark-color-link); + --color-focus-outline: var(--dark-color-focus-outline); + + --color-ts-keyword: var(--dark-color-ts-keyword); + --color-ts-project: var(--dark-color-ts-project); + --color-ts-module: var(--dark-color-ts-module); + --color-ts-namespace: var(--dark-color-ts-namespace); + --color-ts-enum: var(--dark-color-ts-enum); + --color-ts-enum-member: var(--dark-color-ts-enum-member); + --color-ts-variable: var(--dark-color-ts-variable); + --color-ts-function: var(--dark-color-ts-function); + --color-ts-class: var(--dark-color-ts-class); + --color-ts-interface: var(--dark-color-ts-interface); + --color-ts-constructor: var(--dark-color-ts-constructor); + --color-ts-property: var(--dark-color-ts-property); + --color-ts-method: var(--dark-color-ts-method); + --color-ts-reference: var(--dark-color-ts-reference); + --color-ts-call-signature: var(--dark-color-ts-call-signature); + --color-ts-index-signature: var(--dark-color-ts-index-signature); + --color-ts-constructor-signature: var( + --dark-color-ts-constructor-signature + ); + --color-ts-parameter: var(--dark-color-ts-parameter); + --color-ts-type-parameter: var(--dark-color-ts-type-parameter); + --color-ts-accessor: var(--dark-color-ts-accessor); + --color-ts-get-signature: var(--dark-color-ts-get-signature); + --color-ts-set-signature: var(--dark-color-ts-set-signature); + --color-ts-type-alias: var(--dark-color-ts-type-alias); + --color-document: var(--dark-color-document); + + --external-icon: var(--dark-external-icon); + --color-scheme: var(--dark-color-scheme); +} + +*:focus-visible, +.tsd-accordion-summary:focus-visible svg { + outline: 2px solid var(--color-focus-outline); +} + +.always-visible, +.always-visible .tsd-signatures { + display: inherit !important; +} + +h1, +h2, +h3, +h4, +h5, +h6 { + line-height: 1.2; +} + +h1 { + font-size: 1.875rem; + margin: 0.67rem 0; +} + +h2 { + font-size: 1.5rem; + margin: 0.83rem 0; +} + +h3 { + font-size: 1.25rem; + margin: 1rem 0; +} + +h4 { + font-size: 1.05rem; + margin: 1.33rem 0; +} + +h5 { + font-size: 1rem; + margin: 1.5rem 0; +} + +h6 { + font-size: 0.875rem; + margin: 2.33rem 0; +} + +dl, +menu, +ol, +ul { + margin: 1em 0; +} + +dd { + margin: 0 0 0 40px; +} + +.container { + max-width: 1700px; + padding: 0 2rem; +} + +/* Footer */ +footer { + border-top: 1px solid var(--color-accent); + padding-top: 1rem; + padding-bottom: 1rem; + max-height: 3.5rem; +} +footer > p { + margin: 0 1em; +} + +.container-main { + margin: 0 auto; + /* toolbar, footer, margin */ + min-height: calc(100vh - 41px - 56px - 4rem); +} + +@keyframes fade-in { + from { + opacity: 0; + } + to { + opacity: 1; + } +} +@keyframes fade-out { + from { + opacity: 1; + visibility: visible; + } + to { + opacity: 0; + } +} +@keyframes fade-in-delayed { + 0% { + opacity: 0; + } + 33% { + opacity: 0; + } + 100% { + opacity: 1; + } +} +@keyframes fade-out-delayed { + 0% { + opacity: 1; + visibility: visible; + } + 66% { + opacity: 0; + } + 100% { + opacity: 0; + } +} +@keyframes pop-in-from-right { + from { + transform: translate(100%, 0); + } + to { + transform: translate(0, 0); + } +} +@keyframes pop-out-to-right { + from { + transform: translate(0, 0); + visibility: visible; + } + to { + transform: translate(100%, 0); + } +} +body { + background: var(--color-background); + font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", "Noto Sans", + Helvetica, Arial, sans-serif, "Apple Color Emoji", "Segoe UI Emoji"; + font-size: 16px; + color: var(--color-text); +} + +a { + color: var(--color-link); + text-decoration: none; +} +a:hover { + text-decoration: underline; +} +a.external[target="_blank"] { + background-image: var(--external-icon); + background-position: top 3px right; + background-repeat: no-repeat; + padding-right: 13px; +} +a.tsd-anchor-link { + color: var(--color-text); +} + +code, +pre { + font-family: Menlo, Monaco, Consolas, "Courier New", monospace; + padding: 0.2em; + margin: 0; + font-size: 0.875rem; + border-radius: 0.8em; +} + +pre { + position: relative; + white-space: pre-wrap; + word-wrap: break-word; + padding: 10px; + border: 1px solid var(--color-accent); +} +pre code { + padding: 0; + font-size: 100%; +} +pre > button { + position: absolute; + top: 10px; + right: 10px; + opacity: 0; + transition: opacity 0.1s; + box-sizing: border-box; +} +pre:hover > button, +pre > button.visible { + opacity: 1; +} + +blockquote { + margin: 1em 0; + padding-left: 1em; + border-left: 4px solid gray; +} + +.tsd-typography { + line-height: 1.333em; +} +.tsd-typography ul { + list-style: square; + padding: 0 0 0 20px; + margin: 0; +} +.tsd-typography .tsd-index-panel h3, +.tsd-index-panel .tsd-typography h3, +.tsd-typography h4, +.tsd-typography h5, +.tsd-typography h6 { + font-size: 1em; +} +.tsd-typography h5, +.tsd-typography h6 { + font-weight: normal; +} +.tsd-typography p, +.tsd-typography ul, +.tsd-typography ol { + margin: 1em 0; +} +.tsd-typography table { + border-collapse: collapse; + border: none; +} +.tsd-typography td, +.tsd-typography th { + padding: 6px 13px; + border: 1px solid var(--color-accent); +} +.tsd-typography thead, +.tsd-typography tr:nth-child(even) { + background-color: var(--color-background-secondary); +} + +.tsd-breadcrumb { + margin: 0; + padding: 0; + color: var(--color-text-aside); +} +.tsd-breadcrumb a { + color: var(--color-text-aside); + text-decoration: none; +} +.tsd-breadcrumb a:hover { + text-decoration: underline; +} +.tsd-breadcrumb li { + display: inline; +} +.tsd-breadcrumb li:after { + content: " / "; +} + +.tsd-comment-tags { + display: flex; + flex-direction: column; +} +dl.tsd-comment-tag-group { + display: flex; + align-items: center; + overflow: hidden; + margin: 0.5em 0; +} +dl.tsd-comment-tag-group dt { + display: flex; + margin-right: 0.5em; + font-size: 0.875em; + font-weight: normal; +} +dl.tsd-comment-tag-group dd { + margin: 0; +} +code.tsd-tag { + padding: 0.25em 0.4em; + border: 0.1em solid var(--color-accent); + margin-right: 0.25em; + font-size: 70%; +} +h1 code.tsd-tag:first-of-type { + margin-left: 0.25em; +} + +dl.tsd-comment-tag-group dd:before, +dl.tsd-comment-tag-group dd:after { + content: " "; +} +dl.tsd-comment-tag-group dd pre, +dl.tsd-comment-tag-group dd:after { + clear: both; +} +dl.tsd-comment-tag-group p { + margin: 0; +} + +.tsd-panel.tsd-comment .lead { + font-size: 1.1em; + line-height: 1.333em; + margin-bottom: 2em; +} +.tsd-panel.tsd-comment .lead:last-child { + margin-bottom: 0; +} + +.tsd-filter-visibility h4 { + font-size: 1rem; + padding-top: 0.75rem; + padding-bottom: 0.5rem; + margin: 0; +} +.tsd-filter-item:not(:last-child) { + margin-bottom: 0.5rem; +} +.tsd-filter-input { + display: flex; + width: -moz-fit-content; + width: fit-content; + align-items: center; + -webkit-user-select: none; + -moz-user-select: none; + -ms-user-select: none; + user-select: none; + cursor: pointer; +} +.tsd-filter-input input[type="checkbox"] { + cursor: pointer; + position: absolute; + width: 1.5em; + height: 1.5em; + opacity: 0; +} +.tsd-filter-input input[type="checkbox"]:disabled { + pointer-events: none; +} +.tsd-filter-input svg { + cursor: pointer; + width: 1.5em; + height: 1.5em; + margin-right: 0.5em; + border-radius: 0.33em; + /* Leaving this at full opacity breaks event listeners on Firefox. + Don't remove unless you know what you're doing. */ + opacity: 0.99; +} +.tsd-filter-input input[type="checkbox"]:focus-visible + svg { + outline: 2px solid var(--color-focus-outline); +} +.tsd-checkbox-background { + fill: var(--color-accent); +} +input[type="checkbox"]:checked ~ svg .tsd-checkbox-checkmark { + stroke: var(--color-text); +} +.tsd-filter-input input:disabled ~ svg > .tsd-checkbox-background { + fill: var(--color-background); + stroke: var(--color-accent); + stroke-width: 0.25rem; +} +.tsd-filter-input input:disabled ~ svg > .tsd-checkbox-checkmark { + stroke: var(--color-accent); +} + +.settings-label { + font-weight: bold; + text-transform: uppercase; + display: inline-block; +} + +.tsd-filter-visibility .settings-label { + margin: 0.75rem 0 0.5rem 0; +} + +.tsd-theme-toggle .settings-label { + margin: 0.75rem 0.75rem 0 0; +} + +.tsd-hierarchy { + list-style: square; + margin: 0; +} +.tsd-hierarchy .target { + font-weight: bold; +} + +.tsd-full-hierarchy:not(:last-child) { + margin-bottom: 1em; + padding-bottom: 1em; + border-bottom: 1px solid var(--color-accent); +} +.tsd-full-hierarchy, +.tsd-full-hierarchy ul { + list-style: none; + margin: 0; + padding: 0; +} +.tsd-full-hierarchy ul { + padding-left: 1.5rem; +} +.tsd-full-hierarchy a { + padding: 0.25rem 0 !important; + font-size: 1rem; + display: inline-flex; + align-items: center; + color: var(--color-text); +} + +.tsd-panel-group.tsd-index-group { + margin-bottom: 0; +} +.tsd-index-panel .tsd-index-list { + list-style: none; + line-height: 1.333em; + margin: 0; + padding: 0.25rem 0 0 0; + overflow: hidden; + display: grid; + grid-template-columns: repeat(3, 1fr); + column-gap: 1rem; + grid-template-rows: auto; +} +@media (max-width: 1024px) { + .tsd-index-panel .tsd-index-list { + grid-template-columns: repeat(2, 1fr); + } +} +@media (max-width: 768px) { + .tsd-index-panel .tsd-index-list { + grid-template-columns: repeat(1, 1fr); + } +} +.tsd-index-panel .tsd-index-list li { + -webkit-page-break-inside: avoid; + -moz-page-break-inside: avoid; + -ms-page-break-inside: avoid; + -o-page-break-inside: avoid; + page-break-inside: avoid; +} + +.tsd-flag { + display: inline-block; + padding: 0.25em 0.4em; + border-radius: 4px; + color: var(--color-comment-tag-text); + background-color: var(--color-comment-tag); + text-indent: 0; + font-size: 75%; + line-height: 1; + font-weight: normal; +} + +.tsd-anchor { + position: relative; + top: -100px; +} + +.tsd-member { + position: relative; +} +.tsd-member .tsd-anchor + h3 { + display: flex; + align-items: center; + margin-top: 0; + margin-bottom: 0; + border-bottom: none; +} + +.tsd-navigation.settings { + margin: 1rem 0; +} +.tsd-navigation > a, +.tsd-navigation .tsd-accordion-summary { + width: calc(100% - 0.25rem); + display: flex; + align-items: center; +} +.tsd-navigation a, +.tsd-navigation summary > span, +.tsd-page-navigation a { + display: flex; + width: calc(100% - 0.25rem); + align-items: center; + padding: 0.25rem; + color: var(--color-text); + text-decoration: none; + box-sizing: border-box; +} +.tsd-navigation a.current, +.tsd-page-navigation a.current { + background: var(--color-active-menu-item); +} +.tsd-navigation a:hover, +.tsd-page-navigation a:hover { + text-decoration: underline; +} +.tsd-navigation ul, +.tsd-page-navigation ul { + margin-top: 0; + margin-bottom: 0; + padding: 0; + list-style: none; +} +.tsd-navigation li, +.tsd-page-navigation li { + padding: 0; + max-width: 100%; +} +.tsd-navigation .tsd-nav-link { + display: none; +} +.tsd-nested-navigation { + margin-left: 3rem; +} +.tsd-nested-navigation > li > details { + margin-left: -1.5rem; +} +.tsd-small-nested-navigation { + margin-left: 1.5rem; +} +.tsd-small-nested-navigation > li > details { + margin-left: -1.5rem; +} + +.tsd-page-navigation-section { + margin-left: 10px; +} +.tsd-page-navigation-section > summary { + padding: 0.25rem; +} +.tsd-page-navigation-section > div { + margin-left: 20px; +} +.tsd-page-navigation ul { + padding-left: 1.75rem; +} + +#tsd-sidebar-links a { + margin-top: 0; + margin-bottom: 0.5rem; + line-height: 1.25rem; +} +#tsd-sidebar-links a:last-of-type { + margin-bottom: 0; +} + +a.tsd-index-link { + padding: 0.25rem 0 !important; + font-size: 1rem; + line-height: 1.25rem; + display: inline-flex; + align-items: center; + color: var(--color-text); +} +.tsd-accordion-summary { + list-style-type: none; /* hide marker on non-safari */ + outline: none; /* broken on safari, so just hide it */ +} +.tsd-accordion-summary::-webkit-details-marker { + display: none; /* hide marker on safari */ +} +.tsd-accordion-summary, +.tsd-accordion-summary a { + -moz-user-select: none; + -webkit-user-select: none; + -ms-user-select: none; + user-select: none; + + cursor: pointer; +} +.tsd-accordion-summary a { + width: calc(100% - 1.5rem); +} +.tsd-accordion-summary > * { + margin-top: 0; + margin-bottom: 0; + padding-top: 0; + padding-bottom: 0; +} +.tsd-accordion .tsd-accordion-summary > svg { + margin-left: 0.25rem; + vertical-align: text-top; +} +.tsd-index-content > :not(:first-child) { + margin-top: 0.75rem; +} +.tsd-index-heading { + margin-top: 1.5rem; + margin-bottom: 0.75rem; +} + +.tsd-no-select { + -webkit-user-select: none; + -moz-user-select: none; + -ms-user-select: none; + user-select: none; +} +.tsd-kind-icon { + margin-right: 0.5rem; + width: 1.25rem; + height: 1.25rem; + min-width: 1.25rem; + min-height: 1.25rem; +} +.tsd-signature > .tsd-kind-icon { + margin-right: 0.8rem; +} + +.tsd-panel { + margin-bottom: 2.5rem; +} +.tsd-panel.tsd-member { + margin-bottom: 4rem; +} +.tsd-panel:empty { + display: none; +} +.tsd-panel > h1, +.tsd-panel > h2, +.tsd-panel > h3 { + margin: 1.5rem -1.5rem 0.75rem -1.5rem; + padding: 0 1.5rem 0.75rem 1.5rem; +} +.tsd-panel > h1.tsd-before-signature, +.tsd-panel > h2.tsd-before-signature, +.tsd-panel > h3.tsd-before-signature { + margin-bottom: 0; + border-bottom: none; +} + +.tsd-panel-group { + margin: 2rem 0; +} +.tsd-panel-group.tsd-index-group { + margin: 2rem 0; +} +.tsd-panel-group.tsd-index-group details { + margin: 2rem 0; +} +.tsd-panel-group > .tsd-accordion-summary { + margin-bottom: 1rem; +} + +#tsd-search { + transition: background-color 0.2s; +} +#tsd-search .title { + position: relative; + z-index: 2; +} +#tsd-search .field { + position: absolute; + left: 0; + top: 0; + right: 2.5rem; + height: 100%; +} +#tsd-search .field input { + box-sizing: border-box; + position: relative; + top: -50px; + z-index: 1; + width: 100%; + padding: 0 10px; + opacity: 0; + outline: 0; + border: 0; + background: transparent; + color: var(--color-text); +} +#tsd-search .field label { + position: absolute; + overflow: hidden; + right: -40px; +} +#tsd-search .field input, +#tsd-search .title, +#tsd-toolbar-links a { + transition: opacity 0.2s; +} +#tsd-search .results { + position: absolute; + visibility: hidden; + top: 40px; + width: 100%; + margin: 0; + padding: 0; + list-style: none; + box-shadow: 0 0 4px rgba(0, 0, 0, 0.25); +} +#tsd-search .results li { + background-color: var(--color-background); + line-height: initial; + padding: 4px; +} +#tsd-search .results li:nth-child(even) { + background-color: var(--color-background-secondary); +} +#tsd-search .results li.state { + display: none; +} +#tsd-search .results li.current:not(.no-results), +#tsd-search .results li:hover:not(.no-results) { + background-color: var(--color-accent); +} +#tsd-search .results a { + display: flex; + align-items: center; + padding: 0.25rem; + box-sizing: border-box; +} +#tsd-search .results a:before { + top: 10px; +} +#tsd-search .results span.parent { + color: var(--color-text-aside); + font-weight: normal; +} +#tsd-search.has-focus { + background-color: var(--color-accent); +} +#tsd-search.has-focus .field input { + top: 0; + opacity: 1; +} +#tsd-search.has-focus .title, +#tsd-search.has-focus #tsd-toolbar-links a { + z-index: 0; + opacity: 0; +} +#tsd-search.has-focus .results { + visibility: visible; +} +#tsd-search.loading .results li.state.loading { + display: block; +} +#tsd-search.failure .results li.state.failure { + display: block; +} + +#tsd-toolbar-links { + position: absolute; + top: 0; + right: 2rem; + height: 100%; + display: flex; + align-items: center; + justify-content: flex-end; +} +#tsd-toolbar-links a { + margin-left: 1.5rem; +} +#tsd-toolbar-links a:hover { + text-decoration: underline; +} + +.tsd-signature { + margin: 0 0 1rem 0; + padding: 1rem 0.5rem; + border: 1px solid var(--color-accent); + font-family: Menlo, Monaco, Consolas, "Courier New", monospace; + font-size: 14px; + overflow-x: auto; +} + +.tsd-signature-keyword { + color: var(--color-ts-keyword); + font-weight: normal; +} + +.tsd-signature-symbol { + color: var(--color-text-aside); + font-weight: normal; +} + +.tsd-signature-type { + font-style: italic; + font-weight: normal; +} + +.tsd-signatures { + padding: 0; + margin: 0 0 1em 0; + list-style-type: none; +} +.tsd-signatures .tsd-signature { + margin: 0; + border-color: var(--color-accent); + border-width: 1px 0; + transition: background-color 0.1s; +} +.tsd-signatures .tsd-index-signature:not(:last-child) { + margin-bottom: 1em; +} +.tsd-signatures .tsd-index-signature .tsd-signature { + border-width: 1px; +} +.tsd-description .tsd-signatures .tsd-signature { + border-width: 1px; +} + +ul.tsd-parameter-list, +ul.tsd-type-parameter-list { + list-style: square; + margin: 0; + padding-left: 20px; +} +ul.tsd-parameter-list > li.tsd-parameter-signature, +ul.tsd-type-parameter-list > li.tsd-parameter-signature { + list-style: none; + margin-left: -20px; +} +ul.tsd-parameter-list h5, +ul.tsd-type-parameter-list h5 { + font-size: 16px; + margin: 1em 0 0.5em 0; +} +.tsd-sources { + margin-top: 1rem; + font-size: 0.875em; +} +.tsd-sources a { + color: var(--color-text-aside); + text-decoration: underline; +} +.tsd-sources ul { + list-style: none; + padding: 0; +} + +.tsd-page-toolbar { + position: sticky; + z-index: 1; + top: 0; + left: 0; + width: 100%; + color: var(--color-text); + background: var(--color-background-secondary); + border-bottom: 1px var(--color-accent) solid; + transition: transform 0.3s ease-in-out; +} +.tsd-page-toolbar a { + color: var(--color-text); + text-decoration: none; +} +.tsd-page-toolbar a.title { + font-weight: bold; +} +.tsd-page-toolbar a.title:hover { + text-decoration: underline; +} +.tsd-page-toolbar .tsd-toolbar-contents { + display: flex; + justify-content: space-between; + height: 2.5rem; + margin: 0 auto; +} +.tsd-page-toolbar .table-cell { + position: relative; + white-space: nowrap; + line-height: 40px; +} +.tsd-page-toolbar .table-cell:first-child { + width: 100%; +} +.tsd-page-toolbar .tsd-toolbar-icon { + box-sizing: border-box; + line-height: 0; + padding: 12px 0; +} + +.tsd-widget { + display: inline-block; + overflow: hidden; + opacity: 0.8; + height: 40px; + transition: + opacity 0.1s, + background-color 0.2s; + vertical-align: bottom; + cursor: pointer; +} +.tsd-widget:hover { + opacity: 0.9; +} +.tsd-widget.active { + opacity: 1; + background-color: var(--color-accent); +} +.tsd-widget.no-caption { + width: 40px; +} +.tsd-widget.no-caption:before { + margin: 0; +} + +.tsd-widget.options, +.tsd-widget.menu { + display: none; +} +input[type="checkbox"] + .tsd-widget:before { + background-position: -120px 0; +} +input[type="checkbox"]:checked + .tsd-widget:before { + background-position: -160px 0; +} + +img { + max-width: 100%; +} + +.tsd-anchor-icon { + display: inline-flex; + align-items: center; + margin-left: 0.5rem; + vertical-align: middle; + color: var(--color-text); +} + +.tsd-anchor-icon svg { + width: 1em; + height: 1em; + visibility: hidden; +} + +.tsd-anchor-link:hover > .tsd-anchor-icon svg { + visibility: visible; +} + +.deprecated { + text-decoration: line-through !important; +} + +.warning { + padding: 1rem; + color: var(--color-warning-text); + background: var(--color-background-warning); +} + +.tsd-kind-project { + color: var(--color-ts-project); +} +.tsd-kind-module { + color: var(--color-ts-module); +} +.tsd-kind-namespace { + color: var(--color-ts-namespace); +} +.tsd-kind-enum { + color: var(--color-ts-enum); +} +.tsd-kind-enum-member { + color: var(--color-ts-enum-member); +} +.tsd-kind-variable { + color: var(--color-ts-variable); +} +.tsd-kind-function { + color: var(--color-ts-function); +} +.tsd-kind-class { + color: var(--color-ts-class); +} +.tsd-kind-interface { + color: var(--color-ts-interface); +} +.tsd-kind-constructor { + color: var(--color-ts-constructor); +} +.tsd-kind-property { + color: var(--color-ts-property); +} +.tsd-kind-method { + color: var(--color-ts-method); +} +.tsd-kind-reference { + color: var(--color-ts-reference); +} +.tsd-kind-call-signature { + color: var(--color-ts-call-signature); +} +.tsd-kind-index-signature { + color: var(--color-ts-index-signature); +} +.tsd-kind-constructor-signature { + color: var(--color-ts-constructor-signature); +} +.tsd-kind-parameter { + color: var(--color-ts-parameter); +} +.tsd-kind-type-parameter { + color: var(--color-ts-type-parameter); +} +.tsd-kind-accessor { + color: var(--color-ts-accessor); +} +.tsd-kind-get-signature { + color: var(--color-ts-get-signature); +} +.tsd-kind-set-signature { + color: var(--color-ts-set-signature); +} +.tsd-kind-type-alias { + color: var(--color-ts-type-alias); +} + +/* if we have a kind icon, don't color the text by kind */ +.tsd-kind-icon ~ span { + color: var(--color-text); +} + +* { + scrollbar-width: thin; + scrollbar-color: var(--color-accent) var(--color-icon-background); +} + +*::-webkit-scrollbar { + width: 0.75rem; +} + +*::-webkit-scrollbar-track { + background: var(--color-icon-background); +} + +*::-webkit-scrollbar-thumb { + background-color: var(--color-accent); + border-radius: 999rem; + border: 0.25rem solid var(--color-icon-background); +} + +/* mobile */ +@media (max-width: 769px) { + .tsd-widget.options, + .tsd-widget.menu { + display: inline-block; + } + + .container-main { + display: flex; + } + html .col-content { + float: none; + max-width: 100%; + width: 100%; + } + html .col-sidebar { + position: fixed !important; + overflow-y: auto; + -webkit-overflow-scrolling: touch; + z-index: 1024; + top: 0 !important; + bottom: 0 !important; + left: auto !important; + right: 0 !important; + padding: 1.5rem 1.5rem 0 0; + width: 75vw; + visibility: hidden; + background-color: var(--color-background); + transform: translate(100%, 0); + } + html .col-sidebar > *:last-child { + padding-bottom: 20px; + } + html .overlay { + content: ""; + display: block; + position: fixed; + z-index: 1023; + top: 0; + left: 0; + right: 0; + bottom: 0; + background-color: rgba(0, 0, 0, 0.75); + visibility: hidden; + } + + .to-has-menu .overlay { + animation: fade-in 0.4s; + } + + .to-has-menu .col-sidebar { + animation: pop-in-from-right 0.4s; + } + + .from-has-menu .overlay { + animation: fade-out 0.4s; + } + + .from-has-menu .col-sidebar { + animation: pop-out-to-right 0.4s; + } + + .has-menu body { + overflow: hidden; + } + .has-menu .overlay { + visibility: visible; + } + .has-menu .col-sidebar { + visibility: visible; + transform: translate(0, 0); + display: flex; + flex-direction: column; + gap: 1.5rem; + max-height: 100vh; + padding: 1rem 2rem; + } + .has-menu .tsd-navigation { + max-height: 100%; + } + #tsd-toolbar-links { + display: none; + } + .tsd-navigation .tsd-nav-link { + display: flex; + } +} + +/* one sidebar */ +@media (min-width: 770px) { + .container-main { + display: grid; + grid-template-columns: minmax(0, 1fr) minmax(0, 2fr); + grid-template-areas: "sidebar content"; + margin: 2rem auto; + } + + .col-sidebar { + grid-area: sidebar; + } + .col-content { + grid-area: content; + padding: 0 1rem; + } +} +@media (min-width: 770px) and (max-width: 1399px) { + .col-sidebar { + max-height: calc(100vh - 2rem - 42px); + overflow: auto; + position: sticky; + top: 42px; + padding-top: 1rem; + } + .site-menu { + margin-top: 1rem; + } +} + +/* two sidebars */ +@media (min-width: 1200px) { + .container-main { + grid-template-columns: minmax(0, 1fr) minmax(0, 2.5fr) minmax(0, 20rem); + grid-template-areas: "sidebar content toc"; + } + + .col-sidebar { + display: contents; + } + + .page-menu { + grid-area: toc; + padding-left: 1rem; + } + .site-menu { + grid-area: sidebar; + } + + .site-menu { + margin-top: 1rem; + } + + .page-menu, + .site-menu { + max-height: calc(100vh - 2rem - 42px); + overflow: auto; + position: sticky; + top: 42px; + } +} diff --git a/mlflow/docs/classes/default.html b/mlflow/docs/classes/default.html new file mode 100644 index 00000000..b47c84f2 --- /dev/null +++ b/mlflow/docs/classes/default.html @@ -0,0 +1,10 @@ +default | mlflow-js

Classdefault

Constructors

  • Parameters

    • trackingUri: string

    Returns default

Methods

  • Returns ExperimentClient

  • Returns ExperimentManager

  • Returns ModelManager

  • Returns ModelRegistryClient

  • Returns ModelVersionClient

  • Returns RunClient

  • Returns RunManager

  • Returns void

diff --git a/mlflow/docs/code-standards.md b/mlflow/docs/code-standards.md deleted file mode 100644 index 2e4a497e..00000000 --- a/mlflow/docs/code-standards.md +++ /dev/null @@ -1,88 +0,0 @@ -# TypeScript Code Standards - -## File Structure and Naming -- Use PascalCase for class files (e.g., `ModelRegistryClient.ts`) -- Use camelCase for utility files (e.g., `apiRequest.ts`) -- Use kebab-case for directory names (e.g., `model-registry`) - -## Imports and Exports -- Use named exports for utilities and interfaces -- Use default exports for main classes -- Group and sort imports: - 1. External libraries - 2. Internal modules - 3. Relative imports -- Within each group, sort alphabetically -- For imports from other modules, use the path aliases defined in tsconfig.json -- For imports within the same directory, use relative imports - -## Naming Conventions -- PascalCase for classes and interfaces -- camelCase for methods, variables, and functions -- UPPER_SNAKE_CASE for constants - -## Documentation -- Use JSDoc comments for classes, methods, and functions -- Include parameter descriptions, return types, and thrown exceptions -- Example: - ```typescript - /** - * Creates a new registered model. - * @param {string} name - The name of the model to register - * @param {RegisteredModelTag[]} [tags] - Optional tags for the model - * @param {string} [description] - Optional description for the model - * @returns {Promise} The created registered model object - * @throws {ApiError} If the API request fails - */ - ``` - -## Error Handling Guide - -- For simple API calls, use the ApiError class: - -```typescript -if (!response.ok) { - throw new ApiError( - `Error: ${data.message || response.statusText}`, - response.status - ); -} -``` - -- For complex functions, use try/catch blocks: - -```typescript -try { - // complex operation -} catch (error) { - if (error instanceof ApiError) { - console.error(`API Error (${error.statusCode}): ${error.message}`); - throw error; - } else { - console.error('An unexpected error occurred:', error); - throw new Error; - } -} -``` - -## Asynchronous Code -- Use async/await for asynchronous operations - -## Type Annotations -- Use TypeScript type annotations consistently -- Create interfaces for complex object structures -- Use generics where appropriate - -## Class and Method Structure -- Utilize TypeScript features like access modifiers (public, private) -- Use method signatures with proper TypeScript types - -## Formatting -- Use 2 spaces for indentation -- Use single quotes for strings -- Add semicolons at the end of statements - -## Consistency -- Maintain consistent style and patterns throughout the codebase -- When in doubt, follow the existing patterns in the project - diff --git a/mlflow/docs/index.html b/mlflow/docs/index.html new file mode 100644 index 00000000..93ab265c --- /dev/null +++ b/mlflow/docs/index.html @@ -0,0 +1,2 @@ +mlflow-js

mlflow-js

Index

Classes

diff --git a/mlflow/docs/tech-design-doc.md b/mlflow/docs/tech-design-doc.md deleted file mode 100644 index 850f2acb..00000000 --- a/mlflow/docs/tech-design-doc.md +++ /dev/null @@ -1,122 +0,0 @@ -# MLflow JavaScript Library Technical Design Document - - -## 1. Overview - - -The MLflow-JS library aims to provide a comprehensive and intuitive interface for interacting with MLflow services in a JavaScript/Typescript environment. It simplifies the integration with MLflow REST APIs by offering high-level methods for tracking, model management, and advanced workflows. - - -## 2. Architecture - - -The library follows a modular architecture with a main `MLflow` class serving as the primary entry point and separate clients for different MLflow components and workflow managers. - - -### 2.1 Core Components - - -1. **MLflow**: Main class providing access to high-level abstractions and other components. -2. **Tracking**: Module for interacting with MLflow's tracking server. -3. **Model Registry**: Module for managing models in MLflow's model registry. -4. **Workflows**: Higher-level abstractions for common workflows. -5. **Utils**: Utility functions and classes used across the library. - - -### 2.2 Folder Structure - - -``` -mlflow-js/ -├── src/ -│ ├── tracking/ -│ │ ├── ExperimentClient.ts -│ │ ├── RunClient.ts -│ ├── model-registry/ -│ │ ├── ModelRegistryClient.ts -│ │ └── ModelVersionClient.ts -│ ├── workflows/ -│ │ ├── ExperimentManager.ts -│ │ ├── RunManager.ts -│ │ └── ModelManager.ts -│ ├── utils/ -│ │ ├── apiRequest.ts -│ │ └── apiError.ts -│ ├── mlflow.ts -│ └── index.ts -├── tests/ -├── lib/ -│ └── index.js -├── examples/ -└── docs/ -``` - - -## 3. Component Details - - -### 3.1 MLflow Class - - -The `MLflow` class serves as the main entry point for the library. It provides: -- Access to High-level abstractions for common workflows -- Access to tracking and model registry components -- Dynamic Method Delegation Approach/Dynamic Method Binding and getter access - - -### 3.2 Tracking Module - - -Includes clients for interacting with MLflow's tracking server: -- `ExperimentClient`: Manage experiments -- `RunClient`: Create and manage runs, log metrics/params/artifacts - - -### 3.3 Model Registry Module - - -Provides functionality for model management: -- `ModelRegistryClient`: Register and manage models -- `ModelVersionClient`: Handle model versioning and stage transitions - - -### 3.4 Workflows - - -Higher-level abstractions for common workflows: -- `ExperimentManager`: Manage experiment lifecycles -- `RunManager`: Simplify run creation and management -- `ModelManager`: Streamline model registration and promotion - - -### 3.5 Utils - - -Utility classes and functions: -- `apiRequest`: Handle HTTP requests to MLflow server -- `ApiError`: Custom error class for API-related errors - - -## 4. Data Flow - - -1. User interacts with `MLflow` instance -2. `MLflow` delegates to appropriate abstraction or client -3. Client/abstraction uses `ApiRequest` to make HTTP requests -4. `ApiRequest` sends request to MLflow server -5. Response is processed and returned to user - - -## 5. Testing Strategy - - -- Integration tests for API interactions -- End-to-end tests with a real MLflow server and ML model - - -## 6. Documentation - - -- Comprehensive API documentation generated from JSDoc comments -- Usage examples for common scenarios -- Tutorials for getting started and advanced usage diff --git a/mlflow/package-lock.json b/mlflow/package-lock.json index 226a9b30..ebe9f22d 100644 --- a/mlflow/package-lock.json +++ b/mlflow/package-lock.json @@ -16,6 +16,7 @@ "rimraf": "^6.0.1", "ts-node": "^10.9.2", "tsx": "^4.19.1", + "typedoc": "^0.26.9", "typescript": "^5.6.2", "typescript-eslint": "^8.8.0" }, @@ -749,6 +750,62 @@ "node": ">= 8" } }, + "node_modules/@shikijs/core": { + "version": "1.22.0", + "resolved": "https://registry.npmjs.org/@shikijs/core/-/core-1.22.0.tgz", + "integrity": "sha512-S8sMe4q71TJAW+qG93s5VaiihujRK6rqDFqBnxqvga/3LvqHEnxqBIOPkt//IdXVtHkQWKu4nOQNk0uBGicU7Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "@shikijs/engine-javascript": "1.22.0", + "@shikijs/engine-oniguruma": "1.22.0", + "@shikijs/types": "1.22.0", + "@shikijs/vscode-textmate": "^9.3.0", + "@types/hast": "^3.0.4", + "hast-util-to-html": "^9.0.3" + } + }, + "node_modules/@shikijs/engine-javascript": { + "version": "1.22.0", + "resolved": "https://registry.npmjs.org/@shikijs/engine-javascript/-/engine-javascript-1.22.0.tgz", + "integrity": "sha512-AeEtF4Gcck2dwBqCFUKYfsCq0s+eEbCEbkUuFou53NZ0sTGnJnJ/05KHQFZxpii5HMXbocV9URYVowOP2wH5kw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@shikijs/types": "1.22.0", + "@shikijs/vscode-textmate": "^9.3.0", + "oniguruma-to-js": "0.4.3" + } + }, + "node_modules/@shikijs/engine-oniguruma": { + "version": "1.22.0", + "resolved": "https://registry.npmjs.org/@shikijs/engine-oniguruma/-/engine-oniguruma-1.22.0.tgz", + "integrity": "sha512-5iBVjhu/DYs1HB0BKsRRFipRrD7rqjxlWTj4F2Pf+nQSPqc3kcyqFFeZXnBMzDf0HdqaFVvhDRAGiYNvyLP+Mw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@shikijs/types": "1.22.0", + "@shikijs/vscode-textmate": "^9.3.0" + } + }, + "node_modules/@shikijs/types": { + "version": "1.22.0", + "resolved": "https://registry.npmjs.org/@shikijs/types/-/types-1.22.0.tgz", + "integrity": "sha512-Fw/Nr7FGFhlQqHfxzZY8Cwtwk5E9nKDUgeLjZgt3UuhcM3yJR9xj3ZGNravZZok8XmEZMiYkSMTPlPkULB8nww==", + "dev": true, + "license": "MIT", + "dependencies": { + "@shikijs/vscode-textmate": "^9.3.0", + "@types/hast": "^3.0.4" + } + }, + "node_modules/@shikijs/vscode-textmate": { + "version": "9.3.0", + "resolved": "https://registry.npmjs.org/@shikijs/vscode-textmate/-/vscode-textmate-9.3.0.tgz", + "integrity": "sha512-jn7/7ky30idSkd/O5yDBfAnVt+JJpepofP/POZ1iMOxK59cOfqIgg/Dj0eFsjOTMw+4ycJN0uhZH/Eb0bs/EUA==", + "dev": true, + "license": "MIT" + }, "node_modules/@tsconfig/node10": { "version": "1.0.11", "resolved": "https://registry.npmjs.org/@tsconfig/node10/-/node10-1.0.11.tgz", @@ -805,6 +862,16 @@ "dev": true, "license": "MIT" }, + "node_modules/@types/hast": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/@types/hast/-/hast-3.0.4.tgz", + "integrity": "sha512-WPs+bbQw5aCj+x6laNGWLH3wviHtoCv/P3+otBhbOhJgG8qtpdAMlTCxLtsTWA7LH1Oh/bFCHsBn0TPS5m30EQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/unist": "*" + } + }, "node_modules/@types/json-schema": { "version": "7.0.15", "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.15.tgz", @@ -812,6 +879,16 @@ "dev": true, "license": "MIT" }, + "node_modules/@types/mdast": { + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/@types/mdast/-/mdast-4.0.4.tgz", + "integrity": "sha512-kGaNbPh1k7AFzgpud/gMdvIm5xuECykRR+JnWKQno9TAXVa6WIVCGTPvYGekIDL4uwCZQSYbUxNBSb1aUo79oA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/unist": "*" + } + }, "node_modules/@types/node": { "version": "22.7.4", "resolved": "https://registry.npmjs.org/@types/node/-/node-22.7.4.tgz", @@ -822,6 +899,13 @@ "undici-types": "~6.19.2" } }, + "node_modules/@types/unist": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/@types/unist/-/unist-3.0.3.tgz", + "integrity": "sha512-ko/gIFJRv177XgZsZcBwnqJN5x/Gien8qNOn0D5bQU/zAzVf9Zt3BlcUiLqhV9y4ARk0GbT3tnUiPNgnTXzc/Q==", + "dev": true, + "license": "MIT" + }, "node_modules/@typescript-eslint/eslint-plugin": { "version": "8.8.0", "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-8.8.0.tgz", @@ -1041,6 +1125,13 @@ "url": "https://opencollective.com/eslint" } }, + "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, + "license": "ISC" + }, "node_modules/acorn": { "version": "8.12.1", "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.12.1.tgz", @@ -1174,6 +1265,17 @@ "node": ">=6" } }, + "node_modules/ccount": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/ccount/-/ccount-2.0.1.tgz", + "integrity": "sha512-eyrF0jiFpY+3drT6383f1qhkbGsLSifNAjA61IUjZjmLCWjItY6LB9ft9YhoDgwfmclB2zhu51Lc7+95b8NRAg==", + "dev": true, + "license": "MIT", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, "node_modules/chalk": { "version": "4.1.2", "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", @@ -1207,6 +1309,28 @@ "url": "https://github.com/chalk/ansi-styles?sponsor=1" } }, + "node_modules/character-entities-html4": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/character-entities-html4/-/character-entities-html4-2.1.0.tgz", + "integrity": "sha512-1v7fgQRj6hnSwFpq1Eu0ynr/CDEw0rXo2B61qXrLNdHZmPKgb7fqS1a2JwF0rISo9q77jDI8VMEHoApn8qDoZA==", + "dev": true, + "license": "MIT", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/character-entities-legacy": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/character-entities-legacy/-/character-entities-legacy-3.0.0.tgz", + "integrity": "sha512-RpPp0asT/6ufRm//AJVwpViZbGM/MkjQFxJccQRHmISF/22NBtsHqAWmL+/pmkPWoIUJdWyeVleTl1wydHATVQ==", + "dev": true, + "license": "MIT", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, "node_modules/color-convert": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", @@ -1227,6 +1351,17 @@ "dev": true, "license": "MIT" }, + "node_modules/comma-separated-tokens": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/comma-separated-tokens/-/comma-separated-tokens-2.0.3.tgz", + "integrity": "sha512-Fu4hJdvzeylCfQPp9SGWidpzrMs7tTrlu6Vb8XGaRGck8QSNZJJp538Wrb60Lax4fPwR64ViY468OIUTbRlGZg==", + "dev": true, + "license": "MIT", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, "node_modules/concat-map": { "version": "0.0.1", "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", @@ -1281,6 +1416,30 @@ "dev": true, "license": "MIT" }, + "node_modules/dequal": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/dequal/-/dequal-2.0.3.tgz", + "integrity": "sha512-0je+qPKHEMohvfRTCEo3CrPG6cAzAYgmzKyxRiYSSDkS6eGJdyVJm7WaYA5ECaAD9wLB2T4EEeymA5aFVcYXCA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/devlop": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/devlop/-/devlop-1.1.0.tgz", + "integrity": "sha512-RWmIqhcFf1lRYBvNmr7qTNuyCt/7/ns2jbpp1+PalgE/rDQcBT0fioSMUpJ93irlUhC5hrg4cYqe6U+0ImW0rA==", + "dev": true, + "license": "MIT", + "dependencies": { + "dequal": "^2.0.0" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, "node_modules/diff": { "version": "4.0.2", "resolved": "https://registry.npmjs.org/diff/-/diff-4.0.2.tgz", @@ -1305,6 +1464,19 @@ "dev": true, "license": "MIT" }, + "node_modules/entities": { + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/entities/-/entities-4.5.0.tgz", + "integrity": "sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw==", + "dev": true, + "license": "BSD-2-Clause", + "engines": { + "node": ">=0.12" + }, + "funding": { + "url": "https://github.com/fb55/entities?sponsor=1" + } + }, "node_modules/esbuild": { "version": "0.23.1", "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.23.1.tgz", @@ -1774,6 +1946,55 @@ "node": ">=8" } }, + "node_modules/hast-util-to-html": { + "version": "9.0.3", + "resolved": "https://registry.npmjs.org/hast-util-to-html/-/hast-util-to-html-9.0.3.tgz", + "integrity": "sha512-M17uBDzMJ9RPCqLMO92gNNUDuBSq10a25SDBI08iCCxmorf4Yy6sYHK57n9WAbRAAaU+DuR4W6GN9K4DFZesYg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/hast": "^3.0.0", + "@types/unist": "^3.0.0", + "ccount": "^2.0.0", + "comma-separated-tokens": "^2.0.0", + "hast-util-whitespace": "^3.0.0", + "html-void-elements": "^3.0.0", + "mdast-util-to-hast": "^13.0.0", + "property-information": "^6.0.0", + "space-separated-tokens": "^2.0.0", + "stringify-entities": "^4.0.0", + "zwitch": "^2.0.4" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/hast-util-whitespace": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/hast-util-whitespace/-/hast-util-whitespace-3.0.0.tgz", + "integrity": "sha512-88JUN06ipLwsnv+dVn+OIYOvAuvBMy/Qoi6O7mQHxdPXpjy+Cd6xRkWwux7DKO+4sYILtLBRIKgsdpS2gQc7qw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/hast": "^3.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/html-void-elements": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/html-void-elements/-/html-void-elements-3.0.0.tgz", + "integrity": "sha512-bEqo66MRXsUGxWHV5IP0PUiAWwoEjba4VCzg0LjFJBpchPaTfyfCKTG6bc5F8ucKec3q5y6qOdGyYTSBEvhCrg==", + "dev": true, + "license": "MIT", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, "node_modules/ignore": { "version": "5.3.2", "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.3.2.tgz", @@ -1935,6 +2156,16 @@ "node": ">= 0.8.0" } }, + "node_modules/linkify-it": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/linkify-it/-/linkify-it-5.0.0.tgz", + "integrity": "sha512-5aHCbzQRADcdP+ATqnDuhhJ/MRIqDkZX5pyjFHRRysS8vZ5AbqGEoFIb6pYHPZ+L/OC2Lc+xT8uHVVR5CAK/wQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "uc.micro": "^2.0.0" + } + }, "node_modules/locate-path": { "version": "6.0.0", "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz", @@ -1968,6 +2199,13 @@ "node": "20 || >=22" } }, + "node_modules/lunr": { + "version": "2.3.9", + "resolved": "https://registry.npmjs.org/lunr/-/lunr-2.3.9.tgz", + "integrity": "sha512-zTU3DaZaF3Rt9rhN3uBMGQD3dD2/vFQqnvZCDv4dl5iOzq2IZQqTxu90r4E5J+nP70J3ilqVCrbho2eWaeW8Ow==", + "dev": true, + "license": "MIT" + }, "node_modules/make-error": { "version": "1.3.6", "resolved": "https://registry.npmjs.org/make-error/-/make-error-1.3.6.tgz", @@ -1975,6 +2213,53 @@ "dev": true, "license": "ISC" }, + "node_modules/markdown-it": { + "version": "14.1.0", + "resolved": "https://registry.npmjs.org/markdown-it/-/markdown-it-14.1.0.tgz", + "integrity": "sha512-a54IwgWPaeBCAAsv13YgmALOF1elABB08FxO9i+r4VFk5Vl4pKokRPeX8u5TCgSsPi6ec1otfLjdOpVcgbpshg==", + "dev": true, + "license": "MIT", + "dependencies": { + "argparse": "^2.0.1", + "entities": "^4.4.0", + "linkify-it": "^5.0.0", + "mdurl": "^2.0.0", + "punycode.js": "^2.3.1", + "uc.micro": "^2.1.0" + }, + "bin": { + "markdown-it": "bin/markdown-it.mjs" + } + }, + "node_modules/mdast-util-to-hast": { + "version": "13.2.0", + "resolved": "https://registry.npmjs.org/mdast-util-to-hast/-/mdast-util-to-hast-13.2.0.tgz", + "integrity": "sha512-QGYKEuUsYT9ykKBCMOEDLsU5JRObWQusAolFMeko/tYPufNkRffBAQjIE+99jbA87xv6FgmjLtwjh9wBWajwAA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/hast": "^3.0.0", + "@types/mdast": "^4.0.0", + "@ungap/structured-clone": "^1.0.0", + "devlop": "^1.0.0", + "micromark-util-sanitize-uri": "^2.0.0", + "trim-lines": "^3.0.0", + "unist-util-position": "^5.0.0", + "unist-util-visit": "^5.0.0", + "vfile": "^6.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/mdurl": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/mdurl/-/mdurl-2.0.0.tgz", + "integrity": "sha512-Lf+9+2r+Tdp5wXDXC4PcIBjTDtq4UKjCPMQhKIuzpJNW0b96kVqSwW0bT7FhRSfmAiFYgP+SCRvdrDozfh0U5w==", + "dev": true, + "license": "MIT" + }, "node_modules/merge2": { "version": "1.4.1", "resolved": "https://registry.npmjs.org/merge2/-/merge2-1.4.1.tgz", @@ -1985,6 +2270,100 @@ "node": ">= 8" } }, + "node_modules/micromark-util-character": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/micromark-util-character/-/micromark-util-character-2.1.0.tgz", + "integrity": "sha512-KvOVV+X1yLBfs9dCBSopq/+G1PcgT3lAK07mC4BzXi5E7ahzMAF8oIupDDJ6mievI6F+lAATkbQQlQixJfT3aQ==", + "dev": true, + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT", + "dependencies": { + "micromark-util-symbol": "^2.0.0", + "micromark-util-types": "^2.0.0" + } + }, + "node_modules/micromark-util-encode": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/micromark-util-encode/-/micromark-util-encode-2.0.0.tgz", + "integrity": "sha512-pS+ROfCXAGLWCOc8egcBvT0kf27GoWMqtdarNfDcjb6YLuV5cM3ioG45Ys2qOVqeqSbjaKg72vU+Wby3eddPsA==", + "dev": true, + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT" + }, + "node_modules/micromark-util-sanitize-uri": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/micromark-util-sanitize-uri/-/micromark-util-sanitize-uri-2.0.0.tgz", + "integrity": "sha512-WhYv5UEcZrbAtlsnPuChHUAsu/iBPOVaEVsntLBIdpibO0ddy8OzavZz3iL2xVvBZOpolujSliP65Kq0/7KIYw==", + "dev": true, + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT", + "dependencies": { + "micromark-util-character": "^2.0.0", + "micromark-util-encode": "^2.0.0", + "micromark-util-symbol": "^2.0.0" + } + }, + "node_modules/micromark-util-symbol": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/micromark-util-symbol/-/micromark-util-symbol-2.0.0.tgz", + "integrity": "sha512-8JZt9ElZ5kyTnO94muPxIGS8oyElRJaiJO8EzV6ZSyGQ1Is8xwl4Q45qU5UOg+bGH4AikWziz0iN4sFLWs8PGw==", + "dev": true, + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT" + }, + "node_modules/micromark-util-types": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/micromark-util-types/-/micromark-util-types-2.0.0.tgz", + "integrity": "sha512-oNh6S2WMHWRZrmutsRmDDfkzKtxF+bc2VxLC9dvtrDIRFln627VsFP6fLMgTryGDljgLPjkrzQSDcPrjPyDJ5w==", + "dev": true, + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT" + }, "node_modules/micromatch": { "version": "4.0.8", "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.8.tgz", @@ -2039,6 +2418,19 @@ "dev": true, "license": "MIT" }, + "node_modules/oniguruma-to-js": { + "version": "0.4.3", + "resolved": "https://registry.npmjs.org/oniguruma-to-js/-/oniguruma-to-js-0.4.3.tgz", + "integrity": "sha512-X0jWUcAlxORhOqqBREgPMgnshB7ZGYszBNspP+tS9hPD3l13CdaXcHbgImoHUHlrvGx/7AvFEkTRhAGYh+jzjQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "regex": "^4.3.2" + }, + "funding": { + "url": "https://github.com/sponsors/antfu" + } + }, "node_modules/optionator": { "version": "0.9.4", "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.9.4.tgz", @@ -2169,6 +2561,17 @@ "node": ">= 0.8.0" } }, + "node_modules/property-information": { + "version": "6.5.0", + "resolved": "https://registry.npmjs.org/property-information/-/property-information-6.5.0.tgz", + "integrity": "sha512-PgTgs/BlvHxOu8QuEN7wi5A0OmXaBcHpmCSTehcs6Uuu9IkDIEo13Hy7n898RHfrQ49vKCoGeWZSaAK01nwVig==", + "dev": true, + "license": "MIT", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, "node_modules/punycode": { "version": "2.3.1", "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.1.tgz", @@ -2179,6 +2582,16 @@ "node": ">=6" } }, + "node_modules/punycode.js": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/punycode.js/-/punycode.js-2.3.1.tgz", + "integrity": "sha512-uxFIHU0YlHYhDQtV4R9J6a52SLx28BCjT+4ieh7IGbgwVJWO+km431c4yRlREUAsAmt/uMjQUyQHNEPf0M39CA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6" + } + }, "node_modules/queue-microtask": { "version": "1.2.3", "resolved": "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.3.tgz", @@ -2200,6 +2613,13 @@ ], "license": "MIT" }, + "node_modules/regex": { + "version": "4.3.3", + "resolved": "https://registry.npmjs.org/regex/-/regex-4.3.3.tgz", + "integrity": "sha512-r/AadFO7owAq1QJVeZ/nq9jNS1vyZt+6t1p/E59B56Rn2GCya+gr1KSyOzNL/er+r+B7phv5jG2xU2Nz1YkmJg==", + "dev": true, + "license": "MIT" + }, "node_modules/resolve-from": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz", @@ -2311,6 +2731,21 @@ "node": ">=8" } }, + "node_modules/shiki": { + "version": "1.22.0", + "resolved": "https://registry.npmjs.org/shiki/-/shiki-1.22.0.tgz", + "integrity": "sha512-/t5LlhNs+UOKQCYBtl5ZsH/Vclz73GIqT2yQsCBygr8L/ppTdmpL4w3kPLoZJbMKVWtoG77Ue1feOjZfDxvMkw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@shikijs/core": "1.22.0", + "@shikijs/engine-javascript": "1.22.0", + "@shikijs/engine-oniguruma": "1.22.0", + "@shikijs/types": "1.22.0", + "@shikijs/vscode-textmate": "^9.3.0", + "@types/hast": "^3.0.4" + } + }, "node_modules/signal-exit": { "version": "4.1.0", "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-4.1.0.tgz", @@ -2324,6 +2759,17 @@ "url": "https://github.com/sponsors/isaacs" } }, + "node_modules/space-separated-tokens": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/space-separated-tokens/-/space-separated-tokens-2.0.2.tgz", + "integrity": "sha512-PEGlAwrG8yXGXRjW32fGbg66JAlOAwbObuqVoJpv/mRgoWDQfgH1wDPvtzWyUSNAXBGSk8h755YDbbcEy3SH2Q==", + "dev": true, + "license": "MIT", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, "node_modules/string-width": { "version": "5.1.2", "resolved": "https://registry.npmjs.org/string-width/-/string-width-5.1.2.tgz", @@ -2388,6 +2834,21 @@ "node": ">=8" } }, + "node_modules/stringify-entities": { + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/stringify-entities/-/stringify-entities-4.0.4.tgz", + "integrity": "sha512-IwfBptatlO+QCJUo19AqvrPNqlVMpW9YEL2LIVY+Rpv2qsjCGxaDLNRgeGsQWJhfItebuJhsGSLjaBbNSQ+ieg==", + "dev": true, + "license": "MIT", + "dependencies": { + "character-entities-html4": "^2.0.0", + "character-entities-legacy": "^3.0.0" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, "node_modules/strip-ansi": { "version": "7.1.0", "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.1.0.tgz", @@ -2474,6 +2935,17 @@ "node": ">=8.0" } }, + "node_modules/trim-lines": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/trim-lines/-/trim-lines-3.0.1.tgz", + "integrity": "sha512-kRj8B+YHZCc9kQYdWfJB2/oUl9rA99qbowYYBtr4ui4mZyAQ2JpvVBd/6U2YloATfqBhBTSMhTpgBHtU0Mf3Rg==", + "dev": true, + "license": "MIT", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, "node_modules/ts-api-utils": { "version": "1.3.0", "resolved": "https://registry.npmjs.org/ts-api-utils/-/ts-api-utils-1.3.0.tgz", @@ -2564,6 +3036,45 @@ "node": ">= 0.8.0" } }, + "node_modules/typedoc": { + "version": "0.26.9", + "resolved": "https://registry.npmjs.org/typedoc/-/typedoc-0.26.9.tgz", + "integrity": "sha512-Rc7QpWL7EtmrT8yxV0GmhOR6xHgFnnhphbD9Suti3fz3um7ZOrou6q/g9d6+zC5PssTLZmjaW4Upmzv8T1rCcQ==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "lunr": "^2.3.9", + "markdown-it": "^14.1.0", + "minimatch": "^9.0.5", + "shiki": "^1.16.2", + "yaml": "^2.5.1" + }, + "bin": { + "typedoc": "bin/typedoc" + }, + "engines": { + "node": ">= 18" + }, + "peerDependencies": { + "typescript": "4.6.x || 4.7.x || 4.8.x || 4.9.x || 5.0.x || 5.1.x || 5.2.x || 5.3.x || 5.4.x || 5.5.x || 5.6.x" + } + }, + "node_modules/typedoc/node_modules/minimatch": { + "version": "9.0.5", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.5.tgz", + "integrity": "sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow==", + "dev": true, + "license": "ISC", + "dependencies": { + "brace-expansion": "^2.0.1" + }, + "engines": { + "node": ">=16 || 14 >=14.17" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, "node_modules/typescript": { "version": "5.6.2", "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.6.2.tgz", @@ -2602,6 +3113,13 @@ } } }, + "node_modules/uc.micro": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/uc.micro/-/uc.micro-2.1.0.tgz", + "integrity": "sha512-ARDJmphmdvUk6Glw7y9DQ2bFkKBHwQHLi2lsaH6PPmz/Ka9sFOBsBluozhDltWmnv9u/cF6Rt87znRTPV+yp/A==", + "dev": true, + "license": "MIT" + }, "node_modules/undici-types": { "version": "6.19.8", "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-6.19.8.tgz", @@ -2609,6 +3127,79 @@ "dev": true, "license": "MIT" }, + "node_modules/unist-util-is": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/unist-util-is/-/unist-util-is-6.0.0.tgz", + "integrity": "sha512-2qCTHimwdxLfz+YzdGfkqNlH0tLi9xjTnHddPmJwtIG9MGsdbutfTc4P+haPD7l7Cjxf/WZj+we5qfVPvvxfYw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/unist": "^3.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/unist-util-position": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/unist-util-position/-/unist-util-position-5.0.0.tgz", + "integrity": "sha512-fucsC7HjXvkB5R3kTCO7kUjRdrS0BJt3M/FPxmHMBOm8JQi2BsHAHFsy27E0EolP8rp0NzXsJ+jNPyDWvOJZPA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/unist": "^3.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/unist-util-stringify-position": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/unist-util-stringify-position/-/unist-util-stringify-position-4.0.0.tgz", + "integrity": "sha512-0ASV06AAoKCDkS2+xw5RXJywruurpbC4JZSm7nr7MOt1ojAzvyyaO+UxZf18j8FCF6kmzCZKcAgN/yu2gm2XgQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/unist": "^3.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/unist-util-visit": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/unist-util-visit/-/unist-util-visit-5.0.0.tgz", + "integrity": "sha512-MR04uvD+07cwl/yhVuVWAtw+3GOR/knlL55Nd/wAdblk27GCVt3lqpTivy/tkJcZoNPzTwS1Y+KMojlLDhoTzg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/unist": "^3.0.0", + "unist-util-is": "^6.0.0", + "unist-util-visit-parents": "^6.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/unist-util-visit-parents": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/unist-util-visit-parents/-/unist-util-visit-parents-6.0.1.tgz", + "integrity": "sha512-L/PqWzfTP9lzzEa6CKs0k2nARxTdZduw3zyh8d2NVBnsyvHjSX4TWse388YrrQKbvI8w20fGjGlhgT96WwKykw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/unist": "^3.0.0", + "unist-util-is": "^6.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, "node_modules/uri-js": { "version": "4.4.1", "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz", @@ -2626,6 +3217,36 @@ "dev": true, "license": "MIT" }, + "node_modules/vfile": { + "version": "6.0.3", + "resolved": "https://registry.npmjs.org/vfile/-/vfile-6.0.3.tgz", + "integrity": "sha512-KzIbH/9tXat2u30jf+smMwFCsno4wHVdNmzFyL+T/L3UGqqk6JKfVqOFOZEpZSHADH1k40ab6NUIXZq422ov3Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/unist": "^3.0.0", + "vfile-message": "^4.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/vfile-message": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/vfile-message/-/vfile-message-4.0.2.tgz", + "integrity": "sha512-jRDZ1IMLttGj41KcZvlrYAaI3CfqpLpfpf+Mfig13viT6NKvRzWZ+lXz0Y5D60w6uJIBAOGq9mSHf0gktF0duw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/unist": "^3.0.0", + "unist-util-stringify-position": "^4.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, "node_modules/which": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", @@ -2750,6 +3371,19 @@ "node": ">=8" } }, + "node_modules/yaml": { + "version": "2.6.0", + "resolved": "https://registry.npmjs.org/yaml/-/yaml-2.6.0.tgz", + "integrity": "sha512-a6ae//JvKDEra2kdi1qzCyrJW/WZCgFi8ydDV+eXExl95t+5R+ijnqHJbz9tmMh8FUjx3iv2fCQ4dclAQlO2UQ==", + "dev": true, + "license": "ISC", + "bin": { + "yaml": "bin.mjs" + }, + "engines": { + "node": ">= 14" + } + }, "node_modules/yn": { "version": "3.1.1", "resolved": "https://registry.npmjs.org/yn/-/yn-3.1.1.tgz", @@ -2772,6 +3406,17 @@ "funding": { "url": "https://github.com/sponsors/sindresorhus" } + }, + "node_modules/zwitch": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/zwitch/-/zwitch-2.0.4.tgz", + "integrity": "sha512-bXE4cR/kVZhKZX/RjPEflHaKVhUVl85noU3v6b8apfQEc1x4A+zBxjZ4lN8LqGd6WZ3dl98pY4o717VFmoPp+A==", + "dev": true, + "license": "MIT", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } } } } diff --git a/mlflow/package.json b/mlflow/package.json index c3dcbf13..ec3af68a 100644 --- a/mlflow/package.json +++ b/mlflow/package.json @@ -29,6 +29,7 @@ "rimraf": "^6.0.1", "ts-node": "^10.9.2", "tsx": "^4.19.1", + "typedoc": "^0.26.9", "typescript": "^5.6.2", "typescript-eslint": "^8.8.0" }, diff --git a/mlflow/src/index.ts b/mlflow/src/index.ts new file mode 100644 index 00000000..7450f2e5 --- /dev/null +++ b/mlflow/src/index.ts @@ -0,0 +1,3 @@ +import Mlflow from "./mlflow"; + +export default Mlflow; \ No newline at end of file diff --git a/mlflow/src/mlflow.ts b/mlflow/src/mlflow.ts new file mode 100644 index 00000000..699ab50f --- /dev/null +++ b/mlflow/src/mlflow.ts @@ -0,0 +1,81 @@ +import ExperimentClient from './tracking/ExperimentClient'; +import ExperimentManager from './workflows/ExperimentManager'; +import RunClient from './tracking/RunClient'; +import RunManager from './workflows/RunManager'; +import ModelRegistryClient from './model-registry/ModelRegistryClient'; +import ModelVersionClient from './model-registry/ModelVersionClient'; +import ModelManager from './workflows/ModelManager'; + +// Define a type for the components +type Components = { + experimentClient: ExperimentClient; + experimentManager: ExperimentManager; + runClient: RunClient; + runManager: RunManager; + modelRegistryClient: ModelRegistryClient; + modelVersionClient: ModelVersionClient; + modelManager: ModelManager; + }; + +class Mlflow { + private components: Components; + + constructor(trackingUri: string) { + this.components = { + experimentClient: new ExperimentClient(trackingUri), + experimentManager: new ExperimentManager(trackingUri), + runClient: new RunClient(trackingUri), + runManager: new RunManager(trackingUri), + modelRegistryClient: new ModelRegistryClient(trackingUri), + modelVersionClient: new ModelVersionClient(trackingUri), + modelManager: new ModelManager(trackingUri), + }; + + this.initializeMethods(); + } + + initializeMethods() { + Object.keys(this.components).forEach((componentName) => { + const component = this.components[componentName as keyof Components]; + Object.getOwnPropertyNames(Object.getPrototypeOf(component)) + .filter( + (name) => + typeof (component as keyof typeof component)[name] === 'function' && name !== 'constructor' + ) + .forEach((methodName) => { + (this as any)[methodName] = (...args: unknown[]) => (component as any)[methodName as any](...args); + }); + }); + } + + // Getter methods for direct access to clients and managers + getExperimentClient() { + return this.components.experimentClient; + } + + getRunClient() { + return this.components.runClient; + } + + getModelRegistryClient() { + return this.components.modelRegistryClient; + } + + getModelVersionClient() { + return this.components.modelVersionClient; + } + + getExperimentManager() { + return this.components.experimentManager; + } + + getRunManager() { + return this.components.runManager; + } + + getModelManager() { + return this.components.modelManager; + } +} + +export default Mlflow; \ No newline at end of file diff --git a/mlflow/src/workflows/ExperimentManager.ts b/mlflow/src/workflows/ExperimentManager.ts index 07345830..7e128e49 100644 --- a/mlflow/src/workflows/ExperimentManager.ts +++ b/mlflow/src/workflows/ExperimentManager.ts @@ -3,11 +3,9 @@ import RunClient from '@tracking/RunClient'; import { ApiError } from '@utils/apiError'; class ExperimentManager { - private trackingUri: string; private experimentClient: ExperimentClient; private runClient: RunClient; constructor(trackingUri: string) { - this.trackingUri = trackingUri; this.experimentClient = new ExperimentClient(trackingUri); this.runClient = new RunClient(trackingUri); } diff --git a/mlflow/tsconfig.json b/mlflow/tsconfig.json index 88e5b25e..37131b51 100644 --- a/mlflow/tsconfig.json +++ b/mlflow/tsconfig.json @@ -53,6 +53,10 @@ "removeComments": false, "allowJs": false }, + "typedocOptions": { + "entryPoints": ["src/index.ts"], + "out": "docs" + }, "include": ["src/**/*"], "exclude": ["node_modules", "**/*.spec.ts"] } diff --git a/mlflow/typedoc.json b/mlflow/typedoc.json new file mode 100644 index 00000000..7c3d5a6d --- /dev/null +++ b/mlflow/typedoc.json @@ -0,0 +1,5 @@ +{ + // Comments are supported, like tsconfig.json + "entryPoints": ["src/index.ts"], + "out": "docs" +} \ No newline at end of file From d021c958158589ffecfc15fece62b7e71153e0e5 Mon Sep 17 00:00:00 2001 From: Stephany Ho Date: Wed, 16 Oct 2024 20:47:21 -0400 Subject: [PATCH 154/357] Test npm pack and update a file --- mlflow/src/workflows/ExperimentManager.ts | 110 ++++++++++++++-------- 1 file changed, 72 insertions(+), 38 deletions(-) diff --git a/mlflow/src/workflows/ExperimentManager.ts b/mlflow/src/workflows/ExperimentManager.ts index 07345830..8411d628 100644 --- a/mlflow/src/workflows/ExperimentManager.ts +++ b/mlflow/src/workflows/ExperimentManager.ts @@ -3,11 +3,10 @@ import RunClient from '@tracking/RunClient'; import { ApiError } from '@utils/apiError'; class ExperimentManager { - private trackingUri: string; private experimentClient: ExperimentClient; private runClient: RunClient; + constructor(trackingUri: string) { - this.trackingUri = trackingUri; this.experimentClient = new ExperimentClient(trackingUri); this.runClient = new RunClient(trackingUri); } @@ -27,20 +26,32 @@ class ExperimentManager { async runExistingExperiment( experiment_id: string, run_name?: string, - metrics?: Array<{key: string, value: number, timestamp: number, step?: number}>, - params?: Array<{key: string, value: string}>, - tags?: Array<{key: string, value: string}>, - model?: {artifact_path: string, flavors: Object, model_url: string, model_uuid: string, utc_time_created: number, mlflow_version: string, run_id?: string} + metrics?: Array<{ + key: string; + value: number; + timestamp: number; + step?: number; + }>, + params?: Array<{ key: string; value: string }>, + tags?: Array<{ key: string; value: string }>, + model?: { + artifact_path: string; + flavors: Object; + model_url: string; + model_uuid: string; + utc_time_created: number; + mlflow_version: string; + run_id?: string; + } ): Promise { - try { // create run const run = await this.runClient.createRun(experiment_id, run_name); const run_id = run.info.run_id; - + // log metric, params, and tags via logBatch await this.runClient.logBatch(run_id, metrics, params, tags); - + // log model // (model gets passed in as a JS object, not JSON - it gets JSON stringified here after adding a run_id property) if (model) { @@ -48,10 +59,10 @@ class ExperimentManager { let model_json = JSON.stringify(model); await this.runClient.logModel(run_id, model_json); } - + // updateRun to finish it const latestRun = await this.runClient.updateRun(run_id, 'FINISHED'); - + return latestRun; } catch (error) { if (error instanceof ApiError) { @@ -59,7 +70,7 @@ class ExperimentManager { throw error; } else { console.error('An unexpected error occurred:', error); - throw new Error; + throw new Error(); } } } @@ -79,22 +90,36 @@ class ExperimentManager { async runNewExperiment( experiment_name: string, run_name: string, - metrics: Array<{key: string, value: number, timestamp: number, step?: number}>, - params?: Array<{key: string, value: string}>, - tags?: Array<{key: string, value: string}>, - model?: {artifact_path: string, flavors: Object, model_url: string, model_uuid: string, utc_time_created: number, mlflow_version: string, run_id?: string} + metrics: Array<{ + key: string; + value: number; + timestamp: number; + step?: number; + }>, + params?: Array<{ key: string; value: string }>, + tags?: Array<{ key: string; value: string }>, + model?: { + artifact_path: string; + flavors: Object; + model_url: string; + model_uuid: string; + utc_time_created: number; + mlflow_version: string; + run_id?: string; + } ): Promise { - try { - let experiment_id = await this.experimentClient.createExperiment(experiment_name); - + let experiment_id = await this.experimentClient.createExperiment( + experiment_name + ); + // create run const run = await this.runClient.createRun(experiment_id, run_name); const run_id = run.info.run_id; - + // log metric, params, and tags via logBatch await this.runClient.logBatch(run_id, metrics, params, tags); - + // log model // (model gets passed in as a JS object, not JSON - it gets JSON stringified here after adding a run_id property) if (model) { @@ -102,19 +127,18 @@ class ExperimentManager { let model_json = JSON.stringify(model); await this.runClient.logModel(run_id, model_json); } - + // updateRun to finish it const latest_run = await this.runClient.updateRun(run_id, 'FINISHED'); - + return latest_run; - } - catch (error) { + } catch (error) { if (error instanceof ApiError) { console.error(`API Error (${error.statusCode}): ${error.message}`); throw error; } else { console.error('An unexpected error occurred:', error); - throw new Error; + throw new Error(); } } } @@ -129,11 +153,10 @@ class ExperimentManager { */ async experimentSummary( - experiment_id: string, - primaryMetric: string, + experiment_id: string, + primaryMetric: string, order?: 'ASC' | 'DESC' | 1 | -1 ): Promise { - try { interface RunInfo { run_id: string; @@ -145,13 +168,18 @@ class ExperimentManager { artifact_uri: string; lifecycle_stage: string; } - + interface RunData { - metrics: Array<{ key: string; value: number; timestamp: number; step?: number }>; + metrics: Array<{ + key: string; + value: number; + timestamp: number; + step?: number; + }>; params: Array<{ key: string; value: string }>; tags: Array<{ key: string; value: string }>; } - + interface Run { info: RunInfo; data: RunData; @@ -186,21 +214,27 @@ class ExperimentManager { data.runs.forEach((el: Run) => { const arr = el.data.metrics; let val: number | undefined; - arr.forEach((obj: {key: string, value: number, timestamp: number, step?: number}) => { - if (obj.key === primaryMetric) val = obj.value; - }) + arr.forEach( + (obj: { + key: string; + value: number; + timestamp: number; + step?: number; + }) => { + if (obj.key === primaryMetric) val = obj.value; + } + ); el[primaryMetric] = val; }); return data.runs; - } - catch (error) { + } catch (error) { if (error instanceof ApiError) { console.error(`API Error (${error.statusCode}): ${error.message}`); throw error; } else { console.error('An unexpected error occurred:', error); - throw new Error; + throw new Error(); } } } From 1bc8bb0880614f0c8d2cdc8e0d88901abf6e4838 Mon Sep 17 00:00:00 2001 From: Kyler-Chiago Date: Wed, 16 Oct 2024 18:09:10 -0700 Subject: [PATCH 155/357] Typescript Eslint and Typedoc added --- mlflow/docs/code-standards.md:Zone.Identifier | 3 --- mlflow/docs/tech-design-doc.md:Zone.Identifier | 3 --- mlflow/eslint.config.mjs | 5 ++++- mlflow/src/workflows/ExperimentManager.ts | 6 +++--- 4 files changed, 7 insertions(+), 10 deletions(-) delete mode 100644 mlflow/docs/code-standards.md:Zone.Identifier delete mode 100644 mlflow/docs/tech-design-doc.md:Zone.Identifier diff --git a/mlflow/docs/code-standards.md:Zone.Identifier b/mlflow/docs/code-standards.md:Zone.Identifier deleted file mode 100644 index 1bf0b28e..00000000 --- a/mlflow/docs/code-standards.md:Zone.Identifier +++ /dev/null @@ -1,3 +0,0 @@ -[ZoneTransfer] -ZoneId=3 -HostUrl=https://github.com/ diff --git a/mlflow/docs/tech-design-doc.md:Zone.Identifier b/mlflow/docs/tech-design-doc.md:Zone.Identifier deleted file mode 100644 index 1bf0b28e..00000000 --- a/mlflow/docs/tech-design-doc.md:Zone.Identifier +++ /dev/null @@ -1,3 +0,0 @@ -[ZoneTransfer] -ZoneId=3 -HostUrl=https://github.com/ diff --git a/mlflow/eslint.config.mjs b/mlflow/eslint.config.mjs index 7d3e80e0..35ea989f 100644 --- a/mlflow/eslint.config.mjs +++ b/mlflow/eslint.config.mjs @@ -6,4 +6,7 @@ import tseslint from 'typescript-eslint'; export default tseslint.config( eslint.configs.recommended, ...tseslint.configs.recommended, -); \ No newline at end of file + { + ignores: ['docs'], + } +); diff --git a/mlflow/src/workflows/ExperimentManager.ts b/mlflow/src/workflows/ExperimentManager.ts index 7e128e49..1a795bd1 100644 --- a/mlflow/src/workflows/ExperimentManager.ts +++ b/mlflow/src/workflows/ExperimentManager.ts @@ -80,11 +80,11 @@ class ExperimentManager { metrics: Array<{key: string, value: number, timestamp: number, step?: number}>, params?: Array<{key: string, value: string}>, tags?: Array<{key: string, value: string}>, - model?: {artifact_path: string, flavors: Object, model_url: string, model_uuid: string, utc_time_created: number, mlflow_version: string, run_id?: string} + model?: {artifact_path: string, flavors: object, model_url: string, model_uuid: string, utc_time_created: number, mlflow_version: string, run_id?: string} ): Promise { try { - let experiment_id = await this.experimentClient.createExperiment(experiment_name); + const experiment_id = await this.experimentClient.createExperiment(experiment_name); // create run const run = await this.runClient.createRun(experiment_id, run_name); @@ -97,7 +97,7 @@ class ExperimentManager { // (model gets passed in as a JS object, not JSON - it gets JSON stringified here after adding a run_id property) if (model) { model.run_id = run_id; - let model_json = JSON.stringify(model); + const model_json = JSON.stringify(model); await this.runClient.logModel(run_id, model_json); } From 39cefd5895dc15d255ddb49c76e5fec4b53c0959 Mon Sep 17 00:00:00 2001 From: Kyler-Chiago Date: Wed, 16 Oct 2024 18:17:04 -0700 Subject: [PATCH 156/357] small script change in package.json to 'docs' --- mlflow/docs/documentation/classes/default.html | 4 ++-- mlflow/package.json | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/mlflow/docs/documentation/classes/default.html b/mlflow/docs/documentation/classes/default.html index dee34144..af2d475f 100644 --- a/mlflow/docs/documentation/classes/default.html +++ b/mlflow/docs/documentation/classes/default.html @@ -1,4 +1,4 @@ -default | mlflow-js

Classdefault

Constructors

constructor +default | mlflow-js

Classdefault

Constructors

Methods

  • Returns ExperimentClient

  • Returns ExperimentManager

  • Returns ModelManager

  • Returns ModelRegistryClient

  • Returns ModelVersionClient

  • Returns RunClient

  • Returns RunManager

+

Constructors

Methods

  • Returns ExperimentClient

  • Returns ExperimentManager

  • Returns ModelManager

  • Returns ModelRegistryClient

  • Returns ModelVersionClient

  • Returns RunClient

  • Returns RunManager

diff --git a/mlflow/package.json b/mlflow/package.json index 52faed9f..8035abd7 100644 --- a/mlflow/package.json +++ b/mlflow/package.json @@ -10,7 +10,7 @@ "build": "npm run clean && tsc", "test": "", "lint": "eslint .", - "docs": "npx typedoc src/index.ts" + "docs": "typedoc src/index.ts" }, "keywords": [ "mlflow", From d95afa0e79c06bb46c78b5ad50d8441e5390c3c8 Mon Sep 17 00:00:00 2001 From: Kyler-Chiago Date: Wed, 16 Oct 2024 18:17:53 -0700 Subject: [PATCH 157/357] removed a comment in typedoc.json --- mlflow/typedoc.json | 1 - 1 file changed, 1 deletion(-) diff --git a/mlflow/typedoc.json b/mlflow/typedoc.json index 25990734..507c52ca 100644 --- a/mlflow/typedoc.json +++ b/mlflow/typedoc.json @@ -1,5 +1,4 @@ { - // Comments are supported, like tsconfig.json "entryPoints": ["src/index.ts"], "out": "docs/documentation" } \ No newline at end of file From 4e54ad398bfb0a3a1f56eeefbb0951415b0cfdfa Mon Sep 17 00:00:00 2001 From: Kyler-Chiago Date: Wed, 16 Oct 2024 18:31:45 -0700 Subject: [PATCH 158/357] removed documentation folder --- mlflow/docs/documentation/.nojekyll | 1 - .../docs/documentation/assets/highlight.css | 22 - mlflow/docs/documentation/assets/icons.js | 18 - mlflow/docs/documentation/assets/icons.svg | 1 - mlflow/docs/documentation/assets/main.js | 60 - .../docs/documentation/assets/navigation.js | 1 - mlflow/docs/documentation/assets/search.js | 1 - mlflow/docs/documentation/assets/style.css | 1493 ----------------- .../docs/documentation/classes/default.html | 9 - mlflow/docs/documentation/index.html | 2 - 10 files changed, 1608 deletions(-) delete mode 100644 mlflow/docs/documentation/.nojekyll delete mode 100644 mlflow/docs/documentation/assets/highlight.css delete mode 100644 mlflow/docs/documentation/assets/icons.js delete mode 100644 mlflow/docs/documentation/assets/icons.svg delete mode 100644 mlflow/docs/documentation/assets/main.js delete mode 100644 mlflow/docs/documentation/assets/navigation.js delete mode 100644 mlflow/docs/documentation/assets/search.js delete mode 100644 mlflow/docs/documentation/assets/style.css delete mode 100644 mlflow/docs/documentation/classes/default.html delete mode 100644 mlflow/docs/documentation/index.html diff --git a/mlflow/docs/documentation/.nojekyll b/mlflow/docs/documentation/.nojekyll deleted file mode 100644 index e2ac6616..00000000 --- a/mlflow/docs/documentation/.nojekyll +++ /dev/null @@ -1 +0,0 @@ -TypeDoc added this file to prevent GitHub Pages from using Jekyll. You can turn off this behavior by setting the `githubPages` option to false. \ No newline at end of file diff --git a/mlflow/docs/documentation/assets/highlight.css b/mlflow/docs/documentation/assets/highlight.css deleted file mode 100644 index 5674cf39..00000000 --- a/mlflow/docs/documentation/assets/highlight.css +++ /dev/null @@ -1,22 +0,0 @@ -:root { - --light-code-background: #FFFFFF; - --dark-code-background: #1E1E1E; -} - -@media (prefers-color-scheme: light) { :root { - --code-background: var(--light-code-background); -} } - -@media (prefers-color-scheme: dark) { :root { - --code-background: var(--dark-code-background); -} } - -:root[data-theme='light'] { - --code-background: var(--light-code-background); -} - -:root[data-theme='dark'] { - --code-background: var(--dark-code-background); -} - -pre, code { background: var(--code-background); } diff --git a/mlflow/docs/documentation/assets/icons.js b/mlflow/docs/documentation/assets/icons.js deleted file mode 100644 index 3dfbd322..00000000 --- a/mlflow/docs/documentation/assets/icons.js +++ /dev/null @@ -1,18 +0,0 @@ -(function() { - addIcons(); - function addIcons() { - if (document.readyState === "loading") return document.addEventListener("DOMContentLoaded", addIcons); - const svg = document.body.appendChild(document.createElementNS("http://www.w3.org/2000/svg", "svg")); - svg.innerHTML = `MMNEPVFCICPMFPCPTTAAATR`; - svg.style.display = "none"; - if (location.protocol === "file:") updateUseElements(); - } - - function updateUseElements() { - document.querySelectorAll("use").forEach(el => { - if (el.getAttribute("href").includes("#icon-")) { - el.setAttribute("href", el.getAttribute("href").replace(/.*#/, "#")); - } - }); - } -})() \ No newline at end of file diff --git a/mlflow/docs/documentation/assets/icons.svg b/mlflow/docs/documentation/assets/icons.svg deleted file mode 100644 index a19417dc..00000000 --- a/mlflow/docs/documentation/assets/icons.svg +++ /dev/null @@ -1 +0,0 @@ -MMNEPVFCICPMFPCPTTAAATR \ No newline at end of file diff --git a/mlflow/docs/documentation/assets/main.js b/mlflow/docs/documentation/assets/main.js deleted file mode 100644 index 99097a05..00000000 --- a/mlflow/docs/documentation/assets/main.js +++ /dev/null @@ -1,60 +0,0 @@ -"use strict"; -window.translations={"copy":"Copy","copied":"Copied!","normally_hidden":"This member is normally hidden due to your filter settings."}; -"use strict";(()=>{var Pe=Object.create;var ie=Object.defineProperty;var Oe=Object.getOwnPropertyDescriptor;var _e=Object.getOwnPropertyNames;var Re=Object.getPrototypeOf,Me=Object.prototype.hasOwnProperty;var Fe=(t,e)=>()=>(e||t((e={exports:{}}).exports,e),e.exports);var De=(t,e,n,r)=>{if(e&&typeof e=="object"||typeof e=="function")for(let i of _e(e))!Me.call(t,i)&&i!==n&&ie(t,i,{get:()=>e[i],enumerable:!(r=Oe(e,i))||r.enumerable});return t};var Ae=(t,e,n)=>(n=t!=null?Pe(Re(t)):{},De(e||!t||!t.__esModule?ie(n,"default",{value:t,enumerable:!0}):n,t));var ue=Fe((ae,le)=>{(function(){var t=function(e){var n=new t.Builder;return n.pipeline.add(t.trimmer,t.stopWordFilter,t.stemmer),n.searchPipeline.add(t.stemmer),e.call(n,n),n.build()};t.version="2.3.9";t.utils={},t.utils.warn=function(e){return function(n){e.console&&console.warn&&console.warn(n)}}(this),t.utils.asString=function(e){return e==null?"":e.toString()},t.utils.clone=function(e){if(e==null)return e;for(var n=Object.create(null),r=Object.keys(e),i=0;i0){var d=t.utils.clone(n)||{};d.position=[a,u],d.index=s.length,s.push(new t.Token(r.slice(a,o),d))}a=o+1}}return s},t.tokenizer.separator=/[\s\-]+/;t.Pipeline=function(){this._stack=[]},t.Pipeline.registeredFunctions=Object.create(null),t.Pipeline.registerFunction=function(e,n){n in this.registeredFunctions&&t.utils.warn("Overwriting existing registered function: "+n),e.label=n,t.Pipeline.registeredFunctions[e.label]=e},t.Pipeline.warnIfFunctionNotRegistered=function(e){var n=e.label&&e.label in this.registeredFunctions;n||t.utils.warn(`Function is not registered with pipeline. This may cause problems when serialising the index. -`,e)},t.Pipeline.load=function(e){var n=new t.Pipeline;return e.forEach(function(r){var i=t.Pipeline.registeredFunctions[r];if(i)n.add(i);else throw new Error("Cannot load unregistered function: "+r)}),n},t.Pipeline.prototype.add=function(){var e=Array.prototype.slice.call(arguments);e.forEach(function(n){t.Pipeline.warnIfFunctionNotRegistered(n),this._stack.push(n)},this)},t.Pipeline.prototype.after=function(e,n){t.Pipeline.warnIfFunctionNotRegistered(n);var r=this._stack.indexOf(e);if(r==-1)throw new Error("Cannot find existingFn");r=r+1,this._stack.splice(r,0,n)},t.Pipeline.prototype.before=function(e,n){t.Pipeline.warnIfFunctionNotRegistered(n);var r=this._stack.indexOf(e);if(r==-1)throw new Error("Cannot find existingFn");this._stack.splice(r,0,n)},t.Pipeline.prototype.remove=function(e){var n=this._stack.indexOf(e);n!=-1&&this._stack.splice(n,1)},t.Pipeline.prototype.run=function(e){for(var n=this._stack.length,r=0;r1&&(oe&&(r=s),o!=e);)i=r-n,s=n+Math.floor(i/2),o=this.elements[s*2];if(o==e||o>e)return s*2;if(ol?d+=2:a==l&&(n+=r[u+1]*i[d+1],u+=2,d+=2);return n},t.Vector.prototype.similarity=function(e){return this.dot(e)/this.magnitude()||0},t.Vector.prototype.toArray=function(){for(var e=new Array(this.elements.length/2),n=1,r=0;n0){var o=s.str.charAt(0),a;o in s.node.edges?a=s.node.edges[o]:(a=new t.TokenSet,s.node.edges[o]=a),s.str.length==1&&(a.final=!0),i.push({node:a,editsRemaining:s.editsRemaining,str:s.str.slice(1)})}if(s.editsRemaining!=0){if("*"in s.node.edges)var l=s.node.edges["*"];else{var l=new t.TokenSet;s.node.edges["*"]=l}if(s.str.length==0&&(l.final=!0),i.push({node:l,editsRemaining:s.editsRemaining-1,str:s.str}),s.str.length>1&&i.push({node:s.node,editsRemaining:s.editsRemaining-1,str:s.str.slice(1)}),s.str.length==1&&(s.node.final=!0),s.str.length>=1){if("*"in s.node.edges)var u=s.node.edges["*"];else{var u=new t.TokenSet;s.node.edges["*"]=u}s.str.length==1&&(u.final=!0),i.push({node:u,editsRemaining:s.editsRemaining-1,str:s.str.slice(1)})}if(s.str.length>1){var d=s.str.charAt(0),m=s.str.charAt(1),p;m in s.node.edges?p=s.node.edges[m]:(p=new t.TokenSet,s.node.edges[m]=p),s.str.length==1&&(p.final=!0),i.push({node:p,editsRemaining:s.editsRemaining-1,str:d+s.str.slice(2)})}}}return r},t.TokenSet.fromString=function(e){for(var n=new t.TokenSet,r=n,i=0,s=e.length;i=e;n--){var r=this.uncheckedNodes[n],i=r.child.toString();i in this.minimizedNodes?r.parent.edges[r.char]=this.minimizedNodes[i]:(r.child._str=i,this.minimizedNodes[i]=r.child),this.uncheckedNodes.pop()}};t.Index=function(e){this.invertedIndex=e.invertedIndex,this.fieldVectors=e.fieldVectors,this.tokenSet=e.tokenSet,this.fields=e.fields,this.pipeline=e.pipeline},t.Index.prototype.search=function(e){return this.query(function(n){var r=new t.QueryParser(e,n);r.parse()})},t.Index.prototype.query=function(e){for(var n=new t.Query(this.fields),r=Object.create(null),i=Object.create(null),s=Object.create(null),o=Object.create(null),a=Object.create(null),l=0;l1?this._b=1:this._b=e},t.Builder.prototype.k1=function(e){this._k1=e},t.Builder.prototype.add=function(e,n){var r=e[this._ref],i=Object.keys(this._fields);this._documents[r]=n||{},this.documentCount+=1;for(var s=0;s=this.length)return t.QueryLexer.EOS;var e=this.str.charAt(this.pos);return this.pos+=1,e},t.QueryLexer.prototype.width=function(){return this.pos-this.start},t.QueryLexer.prototype.ignore=function(){this.start==this.pos&&(this.pos+=1),this.start=this.pos},t.QueryLexer.prototype.backup=function(){this.pos-=1},t.QueryLexer.prototype.acceptDigitRun=function(){var e,n;do e=this.next(),n=e.charCodeAt(0);while(n>47&&n<58);e!=t.QueryLexer.EOS&&this.backup()},t.QueryLexer.prototype.more=function(){return this.pos1&&(e.backup(),e.emit(t.QueryLexer.TERM)),e.ignore(),e.more())return t.QueryLexer.lexText},t.QueryLexer.lexEditDistance=function(e){return e.ignore(),e.acceptDigitRun(),e.emit(t.QueryLexer.EDIT_DISTANCE),t.QueryLexer.lexText},t.QueryLexer.lexBoost=function(e){return e.ignore(),e.acceptDigitRun(),e.emit(t.QueryLexer.BOOST),t.QueryLexer.lexText},t.QueryLexer.lexEOS=function(e){e.width()>0&&e.emit(t.QueryLexer.TERM)},t.QueryLexer.termSeparator=t.tokenizer.separator,t.QueryLexer.lexText=function(e){for(;;){var n=e.next();if(n==t.QueryLexer.EOS)return t.QueryLexer.lexEOS;if(n.charCodeAt(0)==92){e.escapeCharacter();continue}if(n==":")return t.QueryLexer.lexField;if(n=="~")return e.backup(),e.width()>0&&e.emit(t.QueryLexer.TERM),t.QueryLexer.lexEditDistance;if(n=="^")return e.backup(),e.width()>0&&e.emit(t.QueryLexer.TERM),t.QueryLexer.lexBoost;if(n=="+"&&e.width()===1||n=="-"&&e.width()===1)return e.emit(t.QueryLexer.PRESENCE),t.QueryLexer.lexText;if(n.match(t.QueryLexer.termSeparator))return t.QueryLexer.lexTerm}},t.QueryParser=function(e,n){this.lexer=new t.QueryLexer(e),this.query=n,this.currentClause={},this.lexemeIdx=0},t.QueryParser.prototype.parse=function(){this.lexer.run(),this.lexemes=this.lexer.lexemes;for(var e=t.QueryParser.parseClause;e;)e=e(this);return this.query},t.QueryParser.prototype.peekLexeme=function(){return this.lexemes[this.lexemeIdx]},t.QueryParser.prototype.consumeLexeme=function(){var e=this.peekLexeme();return this.lexemeIdx+=1,e},t.QueryParser.prototype.nextClause=function(){var e=this.currentClause;this.query.clause(e),this.currentClause={}},t.QueryParser.parseClause=function(e){var n=e.peekLexeme();if(n!=null)switch(n.type){case t.QueryLexer.PRESENCE:return t.QueryParser.parsePresence;case t.QueryLexer.FIELD:return t.QueryParser.parseField;case t.QueryLexer.TERM:return t.QueryParser.parseTerm;default:var r="expected either a field or a term, found "+n.type;throw n.str.length>=1&&(r+=" with value '"+n.str+"'"),new t.QueryParseError(r,n.start,n.end)}},t.QueryParser.parsePresence=function(e){var n=e.consumeLexeme();if(n!=null){switch(n.str){case"-":e.currentClause.presence=t.Query.presence.PROHIBITED;break;case"+":e.currentClause.presence=t.Query.presence.REQUIRED;break;default:var r="unrecognised presence operator'"+n.str+"'";throw new t.QueryParseError(r,n.start,n.end)}var i=e.peekLexeme();if(i==null){var r="expecting term or field, found nothing";throw new t.QueryParseError(r,n.start,n.end)}switch(i.type){case t.QueryLexer.FIELD:return t.QueryParser.parseField;case t.QueryLexer.TERM:return t.QueryParser.parseTerm;default:var r="expecting term or field, found '"+i.type+"'";throw new t.QueryParseError(r,i.start,i.end)}}},t.QueryParser.parseField=function(e){var n=e.consumeLexeme();if(n!=null){if(e.query.allFields.indexOf(n.str)==-1){var r=e.query.allFields.map(function(o){return"'"+o+"'"}).join(", "),i="unrecognised field '"+n.str+"', possible fields: "+r;throw new t.QueryParseError(i,n.start,n.end)}e.currentClause.fields=[n.str];var s=e.peekLexeme();if(s==null){var i="expecting term, found nothing";throw new t.QueryParseError(i,n.start,n.end)}switch(s.type){case t.QueryLexer.TERM:return t.QueryParser.parseTerm;default:var i="expecting term, found '"+s.type+"'";throw new t.QueryParseError(i,s.start,s.end)}}},t.QueryParser.parseTerm=function(e){var n=e.consumeLexeme();if(n!=null){e.currentClause.term=n.str.toLowerCase(),n.str.indexOf("*")!=-1&&(e.currentClause.usePipeline=!1);var r=e.peekLexeme();if(r==null){e.nextClause();return}switch(r.type){case t.QueryLexer.TERM:return e.nextClause(),t.QueryParser.parseTerm;case t.QueryLexer.FIELD:return e.nextClause(),t.QueryParser.parseField;case t.QueryLexer.EDIT_DISTANCE:return t.QueryParser.parseEditDistance;case t.QueryLexer.BOOST:return t.QueryParser.parseBoost;case t.QueryLexer.PRESENCE:return e.nextClause(),t.QueryParser.parsePresence;default:var i="Unexpected lexeme type '"+r.type+"'";throw new t.QueryParseError(i,r.start,r.end)}}},t.QueryParser.parseEditDistance=function(e){var n=e.consumeLexeme();if(n!=null){var r=parseInt(n.str,10);if(isNaN(r)){var i="edit distance must be numeric";throw new t.QueryParseError(i,n.start,n.end)}e.currentClause.editDistance=r;var s=e.peekLexeme();if(s==null){e.nextClause();return}switch(s.type){case t.QueryLexer.TERM:return e.nextClause(),t.QueryParser.parseTerm;case t.QueryLexer.FIELD:return e.nextClause(),t.QueryParser.parseField;case t.QueryLexer.EDIT_DISTANCE:return t.QueryParser.parseEditDistance;case t.QueryLexer.BOOST:return t.QueryParser.parseBoost;case t.QueryLexer.PRESENCE:return e.nextClause(),t.QueryParser.parsePresence;default:var i="Unexpected lexeme type '"+s.type+"'";throw new t.QueryParseError(i,s.start,s.end)}}},t.QueryParser.parseBoost=function(e){var n=e.consumeLexeme();if(n!=null){var r=parseInt(n.str,10);if(isNaN(r)){var i="boost must be numeric";throw new t.QueryParseError(i,n.start,n.end)}e.currentClause.boost=r;var s=e.peekLexeme();if(s==null){e.nextClause();return}switch(s.type){case t.QueryLexer.TERM:return e.nextClause(),t.QueryParser.parseTerm;case t.QueryLexer.FIELD:return e.nextClause(),t.QueryParser.parseField;case t.QueryLexer.EDIT_DISTANCE:return t.QueryParser.parseEditDistance;case t.QueryLexer.BOOST:return t.QueryParser.parseBoost;case t.QueryLexer.PRESENCE:return e.nextClause(),t.QueryParser.parsePresence;default:var i="Unexpected lexeme type '"+s.type+"'";throw new t.QueryParseError(i,s.start,s.end)}}},function(e,n){typeof define=="function"&&define.amd?define(n):typeof ae=="object"?le.exports=n():e.lunr=n()}(this,function(){return t})})()});var se=[];function G(t,e){se.push({selector:e,constructor:t})}var U=class{constructor(){this.alwaysVisibleMember=null;this.createComponents(document.body),this.ensureFocusedElementVisible(),this.listenForCodeCopies(),window.addEventListener("hashchange",()=>this.ensureFocusedElementVisible()),document.body.style.display||(this.ensureFocusedElementVisible(),this.updateIndexVisibility(),this.scrollToHash())}createComponents(e){se.forEach(n=>{e.querySelectorAll(n.selector).forEach(r=>{r.dataset.hasInstance||(new n.constructor({el:r,app:this}),r.dataset.hasInstance=String(!0))})})}filterChanged(){this.ensureFocusedElementVisible()}showPage(){document.body.style.display&&(document.body.style.removeProperty("display"),this.ensureFocusedElementVisible(),this.updateIndexVisibility(),this.scrollToHash())}scrollToHash(){if(location.hash){let e=document.getElementById(location.hash.substring(1));if(!e)return;e.scrollIntoView({behavior:"instant",block:"start"})}}ensureActivePageVisible(){let e=document.querySelector(".tsd-navigation .current"),n=e?.parentElement;for(;n&&!n.classList.contains(".tsd-navigation");)n instanceof HTMLDetailsElement&&(n.open=!0),n=n.parentElement;if(e&&!Ve(e)){let r=e.getBoundingClientRect().top-document.documentElement.clientHeight/4;document.querySelector(".site-menu").scrollTop=r,document.querySelector(".col-sidebar").scrollTop=r}}updateIndexVisibility(){let e=document.querySelector(".tsd-index-content"),n=e?.open;e&&(e.open=!0),document.querySelectorAll(".tsd-index-section").forEach(r=>{r.style.display="block";let i=Array.from(r.querySelectorAll(".tsd-index-link")).every(s=>s.offsetParent==null);r.style.display=i?"none":"block"}),e&&(e.open=n)}ensureFocusedElementVisible(){if(this.alwaysVisibleMember&&(this.alwaysVisibleMember.classList.remove("always-visible"),this.alwaysVisibleMember.firstElementChild.remove(),this.alwaysVisibleMember=null),!location.hash)return;let e=document.getElementById(location.hash.substring(1));if(!e)return;let n=e.parentElement;for(;n&&n.tagName!=="SECTION";)n=n.parentElement;if(!n)return;let r=n.offsetParent==null,i=n;for(;i!==document.body;)i instanceof HTMLDetailsElement&&(i.open=!0),i=i.parentElement;if(n.offsetParent==null){this.alwaysVisibleMember=n,n.classList.add("always-visible");let s=document.createElement("p");s.classList.add("warning"),s.textContent=window.translations.normally_hidden,n.prepend(s)}r&&e.scrollIntoView()}listenForCodeCopies(){document.querySelectorAll("pre > button").forEach(e=>{let n;e.addEventListener("click",()=>{e.previousElementSibling instanceof HTMLElement&&navigator.clipboard.writeText(e.previousElementSibling.innerText.trim()),e.textContent=window.translations.copied,e.classList.add("visible"),clearTimeout(n),n=setTimeout(()=>{e.classList.remove("visible"),n=setTimeout(()=>{e.textContent=window.translations.copy},100)},1e3)})})}};function Ve(t){let e=t.getBoundingClientRect(),n=Math.max(document.documentElement.clientHeight,window.innerHeight);return!(e.bottom<0||e.top-n>=0)}var oe=(t,e=100)=>{let n;return()=>{clearTimeout(n),n=setTimeout(()=>t(),e)}};var pe=Ae(ue());async function ce(t,e){if(!window.searchData)return;let n=await fetch(window.searchData),r=new Blob([await n.arrayBuffer()]).stream().pipeThrough(new DecompressionStream("gzip")),i=await new Response(r).json();t.data=i,t.index=pe.Index.load(i.index),e.classList.remove("loading"),e.classList.add("ready")}function fe(){let t=document.getElementById("tsd-search");if(!t)return;let e={base:t.dataset.base+"/"},n=document.getElementById("tsd-search-script");t.classList.add("loading"),n&&(n.addEventListener("error",()=>{t.classList.remove("loading"),t.classList.add("failure")}),n.addEventListener("load",()=>{ce(e,t)}),ce(e,t));let r=document.querySelector("#tsd-search input"),i=document.querySelector("#tsd-search .results");if(!r||!i)throw new Error("The input field or the result list wrapper was not found");i.addEventListener("mouseup",()=>{te(t)}),r.addEventListener("focus",()=>t.classList.add("has-focus")),He(t,i,r,e)}function He(t,e,n,r){n.addEventListener("input",oe(()=>{Ne(t,e,n,r)},200)),n.addEventListener("keydown",i=>{i.key=="Enter"?Be(e,t):i.key=="ArrowUp"?(de(e,n,-1),i.preventDefault()):i.key==="ArrowDown"&&(de(e,n,1),i.preventDefault())}),document.body.addEventListener("keypress",i=>{i.altKey||i.ctrlKey||i.metaKey||!n.matches(":focus")&&i.key==="/"&&(i.preventDefault(),n.focus())}),document.body.addEventListener("keyup",i=>{t.classList.contains("has-focus")&&(i.key==="Escape"||!e.matches(":focus-within")&&!n.matches(":focus"))&&(n.blur(),te(t))})}function te(t){t.classList.remove("has-focus")}function Ne(t,e,n,r){if(!r.index||!r.data)return;e.textContent="";let i=n.value.trim(),s;if(i){let o=i.split(" ").map(a=>a.length?`*${a}*`:"").join(" ");s=r.index.search(o)}else s=[];for(let o=0;oa.score-o.score);for(let o=0,a=Math.min(10,s.length);o`,d=he(l.name,i);globalThis.DEBUG_SEARCH_WEIGHTS&&(d+=` (score: ${s[o].score.toFixed(2)})`),l.parent&&(d=` - ${he(l.parent,i)}.${d}`);let m=document.createElement("li");m.classList.value=l.classes??"";let p=document.createElement("a");p.href=r.base+l.url,p.innerHTML=u+d,m.append(p),p.addEventListener("focus",()=>{e.querySelector(".current")?.classList.remove("current"),m.classList.add("current")}),e.appendChild(m)}}function de(t,e,n){let r=t.querySelector(".current");if(!r)r=t.querySelector(n==1?"li:first-child":"li:last-child"),r&&r.classList.add("current");else{let i=r;if(n===1)do i=i.nextElementSibling??void 0;while(i instanceof HTMLElement&&i.offsetParent==null);else do i=i.previousElementSibling??void 0;while(i instanceof HTMLElement&&i.offsetParent==null);i?(r.classList.remove("current"),i.classList.add("current")):n===-1&&(r.classList.remove("current"),e.focus())}}function Be(t,e){let n=t.querySelector(".current");if(n||(n=t.querySelector("li:first-child")),n){let r=n.querySelector("a");r&&(window.location.href=r.href),te(e)}}function he(t,e){if(e==="")return t;let n=t.toLocaleLowerCase(),r=e.toLocaleLowerCase(),i=[],s=0,o=n.indexOf(r);for(;o!=-1;)i.push(ee(t.substring(s,o)),`${ee(t.substring(o,o+r.length))}`),s=o+r.length,o=n.indexOf(r,s);return i.push(ee(t.substring(s))),i.join("")}var je={"&":"&","<":"<",">":">","'":"'",'"':"""};function ee(t){return t.replace(/[&<>"'"]/g,e=>je[e])}var I=class{constructor(e){this.el=e.el,this.app=e.app}};var F="mousedown",ye="mousemove",N="mouseup",J={x:0,y:0},me=!1,ne=!1,qe=!1,D=!1,ve=/Android|webOS|iPhone|iPad|iPod|BlackBerry|IEMobile|Opera Mini/i.test(navigator.userAgent);document.documentElement.classList.add(ve?"is-mobile":"not-mobile");ve&&"ontouchstart"in document.documentElement&&(qe=!0,F="touchstart",ye="touchmove",N="touchend");document.addEventListener(F,t=>{ne=!0,D=!1;let e=F=="touchstart"?t.targetTouches[0]:t;J.y=e.pageY||0,J.x=e.pageX||0});document.addEventListener(ye,t=>{if(ne&&!D){let e=F=="touchstart"?t.targetTouches[0]:t,n=J.x-(e.pageX||0),r=J.y-(e.pageY||0);D=Math.sqrt(n*n+r*r)>10}});document.addEventListener(N,()=>{ne=!1});document.addEventListener("click",t=>{me&&(t.preventDefault(),t.stopImmediatePropagation(),me=!1)});var X=class extends I{constructor(e){super(e),this.className=this.el.dataset.toggle||"",this.el.addEventListener(N,n=>this.onPointerUp(n)),this.el.addEventListener("click",n=>n.preventDefault()),document.addEventListener(F,n=>this.onDocumentPointerDown(n)),document.addEventListener(N,n=>this.onDocumentPointerUp(n))}setActive(e){if(this.active==e)return;this.active=e,document.documentElement.classList.toggle("has-"+this.className,e),this.el.classList.toggle("active",e);let n=(this.active?"to-has-":"from-has-")+this.className;document.documentElement.classList.add(n),setTimeout(()=>document.documentElement.classList.remove(n),500)}onPointerUp(e){D||(this.setActive(!0),e.preventDefault())}onDocumentPointerDown(e){if(this.active){if(e.target.closest(".col-sidebar, .tsd-filter-group"))return;this.setActive(!1)}}onDocumentPointerUp(e){if(!D&&this.active&&e.target.closest(".col-sidebar")){let n=e.target.closest("a");if(n){let r=window.location.href;r.indexOf("#")!=-1&&(r=r.substring(0,r.indexOf("#"))),n.href.substring(0,r.length)==r&&setTimeout(()=>this.setActive(!1),250)}}}};var re;try{re=localStorage}catch{re={getItem(){return null},setItem(){}}}var Q=re;var ge=document.head.appendChild(document.createElement("style"));ge.dataset.for="filters";var Y=class extends I{constructor(e){super(e),this.key=`filter-${this.el.name}`,this.value=this.el.checked,this.el.addEventListener("change",()=>{this.setLocalStorage(this.el.checked)}),this.setLocalStorage(this.fromLocalStorage()),ge.innerHTML+=`html:not(.${this.key}) .tsd-is-${this.el.name} { display: none; } -`,this.app.updateIndexVisibility()}fromLocalStorage(){let e=Q.getItem(this.key);return e?e==="true":this.el.checked}setLocalStorage(e){Q.setItem(this.key,e.toString()),this.value=e,this.handleValueChange()}handleValueChange(){this.el.checked=this.value,document.documentElement.classList.toggle(this.key,this.value),this.app.filterChanged(),this.app.updateIndexVisibility()}};var Z=class extends I{constructor(e){super(e),this.summary=this.el.querySelector(".tsd-accordion-summary"),this.icon=this.summary.querySelector("svg"),this.key=`tsd-accordion-${this.summary.dataset.key??this.summary.textContent.trim().replace(/\s+/g,"-").toLowerCase()}`;let n=Q.getItem(this.key);this.el.open=n?n==="true":this.el.open,this.el.addEventListener("toggle",()=>this.update());let r=this.summary.querySelector("a");r&&r.addEventListener("click",()=>{location.assign(r.href)}),this.update()}update(){this.icon.style.transform=`rotate(${this.el.open?0:-90}deg)`,Q.setItem(this.key,this.el.open.toString())}};function Ee(t){let e=Q.getItem("tsd-theme")||"os";t.value=e,xe(e),t.addEventListener("change",()=>{Q.setItem("tsd-theme",t.value),xe(t.value)})}function xe(t){document.documentElement.dataset.theme=t}var K;function we(){let t=document.getElementById("tsd-nav-script");t&&(t.addEventListener("load",Le),Le())}async function Le(){let t=document.getElementById("tsd-nav-container");if(!t||!window.navigationData)return;let n=await(await fetch(window.navigationData)).arrayBuffer(),r=new Blob([n]).stream().pipeThrough(new DecompressionStream("gzip")),i=await new Response(r).json();K=t.dataset.base,K.endsWith("/")||(K+="/"),t.innerHTML="";for(let s of i)Se(s,t,[]);window.app.createComponents(t),window.app.showPage(),window.app.ensureActivePageVisible()}function Se(t,e,n){let r=e.appendChild(document.createElement("li"));if(t.children){let i=[...n,t.text],s=r.appendChild(document.createElement("details"));s.className=t.class?`${t.class} tsd-accordion`:"tsd-accordion";let o=s.appendChild(document.createElement("summary"));o.className="tsd-accordion-summary",o.dataset.key=i.join("$"),o.innerHTML='',be(t,o);let a=s.appendChild(document.createElement("div"));a.className="tsd-accordion-details";let l=a.appendChild(document.createElement("ul"));l.className="tsd-nested-navigation";for(let u of t.children)Se(u,l,i)}else be(t,r,t.class)}function be(t,e,n){if(t.path){let r=e.appendChild(document.createElement("a"));r.href=K+t.path,n&&(r.className=n),location.pathname===r.pathname&&!r.href.includes("#")&&r.classList.add("current"),t.kind&&(r.innerHTML=``),r.appendChild(document.createElement("span")).textContent=t.text}else{let r=e.appendChild(document.createElement("span"));r.innerHTML='',r.appendChild(document.createElement("span")).textContent=t.text}}G(X,"a[data-toggle]");G(Z,".tsd-accordion");G(Y,".tsd-filter-item input[type=checkbox]");var Te=document.getElementById("tsd-theme");Te&&Ee(Te);var $e=new U;Object.defineProperty(window,"app",{value:$e});fe();we();})(); -/*! Bundled license information: - -lunr/lunr.js: - (** - * lunr - http://lunrjs.com - A bit like Solr, but much smaller and not as bright - 2.3.9 - * Copyright (C) 2020 Oliver Nightingale - * @license MIT - *) - (*! - * lunr.utils - * Copyright (C) 2020 Oliver Nightingale - *) - (*! - * lunr.Set - * Copyright (C) 2020 Oliver Nightingale - *) - (*! - * lunr.tokenizer - * Copyright (C) 2020 Oliver Nightingale - *) - (*! - * lunr.Pipeline - * Copyright (C) 2020 Oliver Nightingale - *) - (*! - * lunr.Vector - * Copyright (C) 2020 Oliver Nightingale - *) - (*! - * lunr.stemmer - * Copyright (C) 2020 Oliver Nightingale - * Includes code from - http://tartarus.org/~martin/PorterStemmer/js.txt - *) - (*! - * lunr.stopWordFilter - * Copyright (C) 2020 Oliver Nightingale - *) - (*! - * lunr.trimmer - * Copyright (C) 2020 Oliver Nightingale - *) - (*! - * lunr.TokenSet - * Copyright (C) 2020 Oliver Nightingale - *) - (*! - * lunr.Index - * Copyright (C) 2020 Oliver Nightingale - *) - (*! - * lunr.Builder - * Copyright (C) 2020 Oliver Nightingale - *) -*/ diff --git a/mlflow/docs/documentation/assets/navigation.js b/mlflow/docs/documentation/assets/navigation.js deleted file mode 100644 index 05fe130c..00000000 --- a/mlflow/docs/documentation/assets/navigation.js +++ /dev/null @@ -1 +0,0 @@ -window.navigationData = "data:application/octet-stream;base64,H4sIAAAAAAAAA4uuVipJrShRslJKSU1LLM0pUdJRKkgsyVCyUkrOSSwuTi3Wh0roZZTk5ijpKGVn5qUoWRkaWdTGAgAM4TeJPQAAAA==" \ No newline at end of file diff --git a/mlflow/docs/documentation/assets/search.js b/mlflow/docs/documentation/assets/search.js deleted file mode 100644 index ce6f921b..00000000 --- a/mlflow/docs/documentation/assets/search.js +++ /dev/null @@ -1 +0,0 @@ -window.searchData = "data:application/octet-stream;base64,H4sIAAAAAAAAA6WVS2+cMBCA/8v0Otpg84yvVQ855JJDLhaqEDhbVB4rY5JUiP9e8YrXtZtlszc0zPeNjcfDALJ964DxAX6XTQGM0AShyWoBDArxkvWVAoReVsAgr7KuE93dGj/8UnUFuIWBAYy4eUJCPzx523RK9rlq5aeub2bimRfhlEnRqLNF6VLUC/Saj0L9eD8JWdaiUd+rcoI+rekGvlr7qW92Fj3P/Gq1x7YQ1ZM4lp2Sf3bWdTM3reBZyK5s927cidx+1o9Zkx3FhQb7D3HDae8ta6Te9LX3Vvwn+ULNFKFsCvEObIDX5XCAAT34h3tAeClFVUxjYlkMQt7W9XJyRZv382O6pj2L6f5OyUv2nQfIPSTJ4T4maYp8g+cXc2Bz6MgMEkBOXCCxQGKAFJBTF0gtkBqgD8h9F+hboG+AASAPXGBggYEBhoA8dIGhBYYGGAHyyAVGFhgZYAzIYxcYW2BsgAkgT1xgYoFLZO6pVyGVKB6W3uLc/BkM8HPtOrL1+QAE2DCOusfYMJ612fRurrX9nLTD0w5vl+MolPgYB/k6i7SPah+93ldvV08LIy2M9grr6Ro7XIl2JVe55Dr77f0GWhlcpVwHhm0MtTHca5S9Q+RrkX+FyPHdYm2KL5tShFN5ElXZCGA8Hce/a8G9NzEJAAA="; \ No newline at end of file diff --git a/mlflow/docs/documentation/assets/style.css b/mlflow/docs/documentation/assets/style.css deleted file mode 100644 index 178bfb02..00000000 --- a/mlflow/docs/documentation/assets/style.css +++ /dev/null @@ -1,1493 +0,0 @@ -:root { - /* Light */ - --light-color-background: #f2f4f8; - --light-color-background-secondary: #eff0f1; - --light-color-warning-text: #222; - --light-color-background-warning: #e6e600; - --light-color-accent: #c5c7c9; - --light-color-active-menu-item: var(--light-color-accent); - --light-color-text: #222; - --light-color-text-aside: #6e6e6e; - - --light-color-icon-background: var(--light-color-background); - --light-color-icon-text: var(--light-color-text); - - --light-color-comment-tag-text: var(--light-color-text); - --light-color-comment-tag: var(--light-color-background); - - --light-color-link: #1f70c2; - --light-color-focus-outline: #3584e4; - - --light-color-ts-keyword: #056bd6; - --light-color-ts-project: #b111c9; - --light-color-ts-module: var(--light-color-ts-project); - --light-color-ts-namespace: var(--light-color-ts-project); - --light-color-ts-enum: #7e6f15; - --light-color-ts-enum-member: var(--light-color-ts-enum); - --light-color-ts-variable: #4760ec; - --light-color-ts-function: #572be7; - --light-color-ts-class: #1f70c2; - --light-color-ts-interface: #108024; - --light-color-ts-constructor: #4d7fff; - --light-color-ts-property: #ff984d; - --light-color-ts-method: #ff4db8; - --light-color-ts-reference: #ff4d82; - --light-color-ts-call-signature: var(--light-color-ts-method); - --light-color-ts-index-signature: var(--light-color-ts-property); - --light-color-ts-constructor-signature: var(--light-color-ts-constructor); - --light-color-ts-parameter: var(--light-color-ts-variable); - /* type literal not included as links will never be generated to it */ - --light-color-ts-type-parameter: #a55c0e; - --light-color-ts-accessor: #ff4d4d; - --light-color-ts-get-signature: var(--light-color-ts-accessor); - --light-color-ts-set-signature: var(--light-color-ts-accessor); - --light-color-ts-type-alias: #d51270; - /* reference not included as links will be colored with the kind that it points to */ - --light-color-document: #000000; - - --light-external-icon: url("data:image/svg+xml;utf8,"); - --light-color-scheme: light; - - /* Dark */ - --dark-color-background: #2b2e33; - --dark-color-background-secondary: #1e2024; - --dark-color-background-warning: #bebe00; - --dark-color-warning-text: #222; - --dark-color-accent: #9096a2; - --dark-color-active-menu-item: #5d5d6a; - --dark-color-text: #f5f5f5; - --dark-color-text-aside: #dddddd; - - --dark-color-icon-background: var(--dark-color-background-secondary); - --dark-color-icon-text: var(--dark-color-text); - - --dark-color-comment-tag-text: var(--dark-color-text); - --dark-color-comment-tag: var(--dark-color-background); - - --dark-color-link: #00aff4; - --dark-color-focus-outline: #4c97f2; - - --dark-color-ts-keyword: #3399ff; - --dark-color-ts-project: #e358ff; - --dark-color-ts-module: var(--dark-color-ts-project); - --dark-color-ts-namespace: var(--dark-color-ts-project); - --dark-color-ts-enum: #f4d93e; - --dark-color-ts-enum-member: var(--dark-color-ts-enum); - --dark-color-ts-variable: #798dff; - --dark-color-ts-function: #a280ff; - --dark-color-ts-class: #8ac4ff; - --dark-color-ts-interface: #6cff87; - --dark-color-ts-constructor: #4d7fff; - --dark-color-ts-property: #ff984d; - --dark-color-ts-method: #ff4db8; - --dark-color-ts-reference: #ff4d82; - --dark-color-ts-call-signature: var(--dark-color-ts-method); - --dark-color-ts-index-signature: var(--dark-color-ts-property); - --dark-color-ts-constructor-signature: var(--dark-color-ts-constructor); - --dark-color-ts-parameter: var(--dark-color-ts-variable); - /* type literal not included as links will never be generated to it */ - --dark-color-ts-type-parameter: #e07d13; - --dark-color-ts-accessor: #ff4d4d; - --dark-color-ts-get-signature: var(--dark-color-ts-accessor); - --dark-color-ts-set-signature: var(--dark-color-ts-accessor); - --dark-color-ts-type-alias: #ff6492; - /* reference not included as links will be colored with the kind that it points to */ - --dark-color-document: #ffffff; - - --dark-external-icon: url("data:image/svg+xml;utf8,"); - --dark-color-scheme: dark; -} - -@media (prefers-color-scheme: light) { - :root { - --color-background: var(--light-color-background); - --color-background-secondary: var(--light-color-background-secondary); - --color-background-warning: var(--light-color-background-warning); - --color-warning-text: var(--light-color-warning-text); - --color-accent: var(--light-color-accent); - --color-active-menu-item: var(--light-color-active-menu-item); - --color-text: var(--light-color-text); - --color-text-aside: var(--light-color-text-aside); - - --color-icon-background: var(--light-color-icon-background); - --color-icon-text: var(--light-color-icon-text); - - --color-comment-tag-text: var(--light-color-text); - --color-comment-tag: var(--light-color-background); - - --color-link: var(--light-color-link); - --color-focus-outline: var(--light-color-focus-outline); - - --color-ts-keyword: var(--light-color-ts-keyword); - --color-ts-project: var(--light-color-ts-project); - --color-ts-module: var(--light-color-ts-module); - --color-ts-namespace: var(--light-color-ts-namespace); - --color-ts-enum: var(--light-color-ts-enum); - --color-ts-enum-member: var(--light-color-ts-enum-member); - --color-ts-variable: var(--light-color-ts-variable); - --color-ts-function: var(--light-color-ts-function); - --color-ts-class: var(--light-color-ts-class); - --color-ts-interface: var(--light-color-ts-interface); - --color-ts-constructor: var(--light-color-ts-constructor); - --color-ts-property: var(--light-color-ts-property); - --color-ts-method: var(--light-color-ts-method); - --color-ts-reference: var(--light-color-ts-reference); - --color-ts-call-signature: var(--light-color-ts-call-signature); - --color-ts-index-signature: var(--light-color-ts-index-signature); - --color-ts-constructor-signature: var( - --light-color-ts-constructor-signature - ); - --color-ts-parameter: var(--light-color-ts-parameter); - --color-ts-type-parameter: var(--light-color-ts-type-parameter); - --color-ts-accessor: var(--light-color-ts-accessor); - --color-ts-get-signature: var(--light-color-ts-get-signature); - --color-ts-set-signature: var(--light-color-ts-set-signature); - --color-ts-type-alias: var(--light-color-ts-type-alias); - --color-document: var(--light-color-document); - - --external-icon: var(--light-external-icon); - --color-scheme: var(--light-color-scheme); - } -} - -@media (prefers-color-scheme: dark) { - :root { - --color-background: var(--dark-color-background); - --color-background-secondary: var(--dark-color-background-secondary); - --color-background-warning: var(--dark-color-background-warning); - --color-warning-text: var(--dark-color-warning-text); - --color-accent: var(--dark-color-accent); - --color-active-menu-item: var(--dark-color-active-menu-item); - --color-text: var(--dark-color-text); - --color-text-aside: var(--dark-color-text-aside); - - --color-icon-background: var(--dark-color-icon-background); - --color-icon-text: var(--dark-color-icon-text); - - --color-comment-tag-text: var(--dark-color-text); - --color-comment-tag: var(--dark-color-background); - - --color-link: var(--dark-color-link); - --color-focus-outline: var(--dark-color-focus-outline); - - --color-ts-keyword: var(--dark-color-ts-keyword); - --color-ts-project: var(--dark-color-ts-project); - --color-ts-module: var(--dark-color-ts-module); - --color-ts-namespace: var(--dark-color-ts-namespace); - --color-ts-enum: var(--dark-color-ts-enum); - --color-ts-enum-member: var(--dark-color-ts-enum-member); - --color-ts-variable: var(--dark-color-ts-variable); - --color-ts-function: var(--dark-color-ts-function); - --color-ts-class: var(--dark-color-ts-class); - --color-ts-interface: var(--dark-color-ts-interface); - --color-ts-constructor: var(--dark-color-ts-constructor); - --color-ts-property: var(--dark-color-ts-property); - --color-ts-method: var(--dark-color-ts-method); - --color-ts-reference: var(--dark-color-ts-reference); - --color-ts-call-signature: var(--dark-color-ts-call-signature); - --color-ts-index-signature: var(--dark-color-ts-index-signature); - --color-ts-constructor-signature: var( - --dark-color-ts-constructor-signature - ); - --color-ts-parameter: var(--dark-color-ts-parameter); - --color-ts-type-parameter: var(--dark-color-ts-type-parameter); - --color-ts-accessor: var(--dark-color-ts-accessor); - --color-ts-get-signature: var(--dark-color-ts-get-signature); - --color-ts-set-signature: var(--dark-color-ts-set-signature); - --color-ts-type-alias: var(--dark-color-ts-type-alias); - --color-document: var(--dark-color-document); - - --external-icon: var(--dark-external-icon); - --color-scheme: var(--dark-color-scheme); - } -} - -html { - color-scheme: var(--color-scheme); -} - -body { - margin: 0; -} - -:root[data-theme="light"] { - --color-background: var(--light-color-background); - --color-background-secondary: var(--light-color-background-secondary); - --color-background-warning: var(--light-color-background-warning); - --color-warning-text: var(--light-color-warning-text); - --color-icon-background: var(--light-color-icon-background); - --color-accent: var(--light-color-accent); - --color-active-menu-item: var(--light-color-active-menu-item); - --color-text: var(--light-color-text); - --color-text-aside: var(--light-color-text-aside); - --color-icon-text: var(--light-color-icon-text); - - --color-comment-tag-text: var(--light-color-text); - --color-comment-tag: var(--light-color-background); - - --color-link: var(--light-color-link); - --color-focus-outline: var(--light-color-focus-outline); - - --color-ts-keyword: var(--light-color-ts-keyword); - --color-ts-project: var(--light-color-ts-project); - --color-ts-module: var(--light-color-ts-module); - --color-ts-namespace: var(--light-color-ts-namespace); - --color-ts-enum: var(--light-color-ts-enum); - --color-ts-enum-member: var(--light-color-ts-enum-member); - --color-ts-variable: var(--light-color-ts-variable); - --color-ts-function: var(--light-color-ts-function); - --color-ts-class: var(--light-color-ts-class); - --color-ts-interface: var(--light-color-ts-interface); - --color-ts-constructor: var(--light-color-ts-constructor); - --color-ts-property: var(--light-color-ts-property); - --color-ts-method: var(--light-color-ts-method); - --color-ts-reference: var(--light-color-ts-reference); - --color-ts-call-signature: var(--light-color-ts-call-signature); - --color-ts-index-signature: var(--light-color-ts-index-signature); - --color-ts-constructor-signature: var( - --light-color-ts-constructor-signature - ); - --color-ts-parameter: var(--light-color-ts-parameter); - --color-ts-type-parameter: var(--light-color-ts-type-parameter); - --color-ts-accessor: var(--light-color-ts-accessor); - --color-ts-get-signature: var(--light-color-ts-get-signature); - --color-ts-set-signature: var(--light-color-ts-set-signature); - --color-ts-type-alias: var(--light-color-ts-type-alias); - --color-document: var(--light-color-document); - - --external-icon: var(--light-external-icon); - --color-scheme: var(--light-color-scheme); -} - -:root[data-theme="dark"] { - --color-background: var(--dark-color-background); - --color-background-secondary: var(--dark-color-background-secondary); - --color-background-warning: var(--dark-color-background-warning); - --color-warning-text: var(--dark-color-warning-text); - --color-icon-background: var(--dark-color-icon-background); - --color-accent: var(--dark-color-accent); - --color-active-menu-item: var(--dark-color-active-menu-item); - --color-text: var(--dark-color-text); - --color-text-aside: var(--dark-color-text-aside); - --color-icon-text: var(--dark-color-icon-text); - - --color-comment-tag-text: var(--dark-color-text); - --color-comment-tag: var(--dark-color-background); - - --color-link: var(--dark-color-link); - --color-focus-outline: var(--dark-color-focus-outline); - - --color-ts-keyword: var(--dark-color-ts-keyword); - --color-ts-project: var(--dark-color-ts-project); - --color-ts-module: var(--dark-color-ts-module); - --color-ts-namespace: var(--dark-color-ts-namespace); - --color-ts-enum: var(--dark-color-ts-enum); - --color-ts-enum-member: var(--dark-color-ts-enum-member); - --color-ts-variable: var(--dark-color-ts-variable); - --color-ts-function: var(--dark-color-ts-function); - --color-ts-class: var(--dark-color-ts-class); - --color-ts-interface: var(--dark-color-ts-interface); - --color-ts-constructor: var(--dark-color-ts-constructor); - --color-ts-property: var(--dark-color-ts-property); - --color-ts-method: var(--dark-color-ts-method); - --color-ts-reference: var(--dark-color-ts-reference); - --color-ts-call-signature: var(--dark-color-ts-call-signature); - --color-ts-index-signature: var(--dark-color-ts-index-signature); - --color-ts-constructor-signature: var( - --dark-color-ts-constructor-signature - ); - --color-ts-parameter: var(--dark-color-ts-parameter); - --color-ts-type-parameter: var(--dark-color-ts-type-parameter); - --color-ts-accessor: var(--dark-color-ts-accessor); - --color-ts-get-signature: var(--dark-color-ts-get-signature); - --color-ts-set-signature: var(--dark-color-ts-set-signature); - --color-ts-type-alias: var(--dark-color-ts-type-alias); - --color-document: var(--dark-color-document); - - --external-icon: var(--dark-external-icon); - --color-scheme: var(--dark-color-scheme); -} - -*:focus-visible, -.tsd-accordion-summary:focus-visible svg { - outline: 2px solid var(--color-focus-outline); -} - -.always-visible, -.always-visible .tsd-signatures { - display: inherit !important; -} - -h1, -h2, -h3, -h4, -h5, -h6 { - line-height: 1.2; -} - -h1 { - font-size: 1.875rem; - margin: 0.67rem 0; -} - -h2 { - font-size: 1.5rem; - margin: 0.83rem 0; -} - -h3 { - font-size: 1.25rem; - margin: 1rem 0; -} - -h4 { - font-size: 1.05rem; - margin: 1.33rem 0; -} - -h5 { - font-size: 1rem; - margin: 1.5rem 0; -} - -h6 { - font-size: 0.875rem; - margin: 2.33rem 0; -} - -dl, -menu, -ol, -ul { - margin: 1em 0; -} - -dd { - margin: 0 0 0 40px; -} - -.container { - max-width: 1700px; - padding: 0 2rem; -} - -/* Footer */ -footer { - border-top: 1px solid var(--color-accent); - padding-top: 1rem; - padding-bottom: 1rem; - max-height: 3.5rem; -} -footer > p { - margin: 0 1em; -} - -.container-main { - margin: 0 auto; - /* toolbar, footer, margin */ - min-height: calc(100vh - 41px - 56px - 4rem); -} - -@keyframes fade-in { - from { - opacity: 0; - } - to { - opacity: 1; - } -} -@keyframes fade-out { - from { - opacity: 1; - visibility: visible; - } - to { - opacity: 0; - } -} -@keyframes fade-in-delayed { - 0% { - opacity: 0; - } - 33% { - opacity: 0; - } - 100% { - opacity: 1; - } -} -@keyframes fade-out-delayed { - 0% { - opacity: 1; - visibility: visible; - } - 66% { - opacity: 0; - } - 100% { - opacity: 0; - } -} -@keyframes pop-in-from-right { - from { - transform: translate(100%, 0); - } - to { - transform: translate(0, 0); - } -} -@keyframes pop-out-to-right { - from { - transform: translate(0, 0); - visibility: visible; - } - to { - transform: translate(100%, 0); - } -} -body { - background: var(--color-background); - font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", "Noto Sans", - Helvetica, Arial, sans-serif, "Apple Color Emoji", "Segoe UI Emoji"; - font-size: 16px; - color: var(--color-text); -} - -a { - color: var(--color-link); - text-decoration: none; -} -a:hover { - text-decoration: underline; -} -a.external[target="_blank"] { - background-image: var(--external-icon); - background-position: top 3px right; - background-repeat: no-repeat; - padding-right: 13px; -} -a.tsd-anchor-link { - color: var(--color-text); -} - -code, -pre { - font-family: Menlo, Monaco, Consolas, "Courier New", monospace; - padding: 0.2em; - margin: 0; - font-size: 0.875rem; - border-radius: 0.8em; -} - -pre { - position: relative; - white-space: pre-wrap; - word-wrap: break-word; - padding: 10px; - border: 1px solid var(--color-accent); -} -pre code { - padding: 0; - font-size: 100%; -} -pre > button { - position: absolute; - top: 10px; - right: 10px; - opacity: 0; - transition: opacity 0.1s; - box-sizing: border-box; -} -pre:hover > button, -pre > button.visible { - opacity: 1; -} - -blockquote { - margin: 1em 0; - padding-left: 1em; - border-left: 4px solid gray; -} - -.tsd-typography { - line-height: 1.333em; -} -.tsd-typography ul { - list-style: square; - padding: 0 0 0 20px; - margin: 0; -} -.tsd-typography .tsd-index-panel h3, -.tsd-index-panel .tsd-typography h3, -.tsd-typography h4, -.tsd-typography h5, -.tsd-typography h6 { - font-size: 1em; -} -.tsd-typography h5, -.tsd-typography h6 { - font-weight: normal; -} -.tsd-typography p, -.tsd-typography ul, -.tsd-typography ol { - margin: 1em 0; -} -.tsd-typography table { - border-collapse: collapse; - border: none; -} -.tsd-typography td, -.tsd-typography th { - padding: 6px 13px; - border: 1px solid var(--color-accent); -} -.tsd-typography thead, -.tsd-typography tr:nth-child(even) { - background-color: var(--color-background-secondary); -} - -.tsd-breadcrumb { - margin: 0; - padding: 0; - color: var(--color-text-aside); -} -.tsd-breadcrumb a { - color: var(--color-text-aside); - text-decoration: none; -} -.tsd-breadcrumb a:hover { - text-decoration: underline; -} -.tsd-breadcrumb li { - display: inline; -} -.tsd-breadcrumb li:after { - content: " / "; -} - -.tsd-comment-tags { - display: flex; - flex-direction: column; -} -dl.tsd-comment-tag-group { - display: flex; - align-items: center; - overflow: hidden; - margin: 0.5em 0; -} -dl.tsd-comment-tag-group dt { - display: flex; - margin-right: 0.5em; - font-size: 0.875em; - font-weight: normal; -} -dl.tsd-comment-tag-group dd { - margin: 0; -} -code.tsd-tag { - padding: 0.25em 0.4em; - border: 0.1em solid var(--color-accent); - margin-right: 0.25em; - font-size: 70%; -} -h1 code.tsd-tag:first-of-type { - margin-left: 0.25em; -} - -dl.tsd-comment-tag-group dd:before, -dl.tsd-comment-tag-group dd:after { - content: " "; -} -dl.tsd-comment-tag-group dd pre, -dl.tsd-comment-tag-group dd:after { - clear: both; -} -dl.tsd-comment-tag-group p { - margin: 0; -} - -.tsd-panel.tsd-comment .lead { - font-size: 1.1em; - line-height: 1.333em; - margin-bottom: 2em; -} -.tsd-panel.tsd-comment .lead:last-child { - margin-bottom: 0; -} - -.tsd-filter-visibility h4 { - font-size: 1rem; - padding-top: 0.75rem; - padding-bottom: 0.5rem; - margin: 0; -} -.tsd-filter-item:not(:last-child) { - margin-bottom: 0.5rem; -} -.tsd-filter-input { - display: flex; - width: -moz-fit-content; - width: fit-content; - align-items: center; - -webkit-user-select: none; - -moz-user-select: none; - -ms-user-select: none; - user-select: none; - cursor: pointer; -} -.tsd-filter-input input[type="checkbox"] { - cursor: pointer; - position: absolute; - width: 1.5em; - height: 1.5em; - opacity: 0; -} -.tsd-filter-input input[type="checkbox"]:disabled { - pointer-events: none; -} -.tsd-filter-input svg { - cursor: pointer; - width: 1.5em; - height: 1.5em; - margin-right: 0.5em; - border-radius: 0.33em; - /* Leaving this at full opacity breaks event listeners on Firefox. - Don't remove unless you know what you're doing. */ - opacity: 0.99; -} -.tsd-filter-input input[type="checkbox"]:focus-visible + svg { - outline: 2px solid var(--color-focus-outline); -} -.tsd-checkbox-background { - fill: var(--color-accent); -} -input[type="checkbox"]:checked ~ svg .tsd-checkbox-checkmark { - stroke: var(--color-text); -} -.tsd-filter-input input:disabled ~ svg > .tsd-checkbox-background { - fill: var(--color-background); - stroke: var(--color-accent); - stroke-width: 0.25rem; -} -.tsd-filter-input input:disabled ~ svg > .tsd-checkbox-checkmark { - stroke: var(--color-accent); -} - -.settings-label { - font-weight: bold; - text-transform: uppercase; - display: inline-block; -} - -.tsd-filter-visibility .settings-label { - margin: 0.75rem 0 0.5rem 0; -} - -.tsd-theme-toggle .settings-label { - margin: 0.75rem 0.75rem 0 0; -} - -.tsd-hierarchy { - list-style: square; - margin: 0; -} -.tsd-hierarchy .target { - font-weight: bold; -} - -.tsd-full-hierarchy:not(:last-child) { - margin-bottom: 1em; - padding-bottom: 1em; - border-bottom: 1px solid var(--color-accent); -} -.tsd-full-hierarchy, -.tsd-full-hierarchy ul { - list-style: none; - margin: 0; - padding: 0; -} -.tsd-full-hierarchy ul { - padding-left: 1.5rem; -} -.tsd-full-hierarchy a { - padding: 0.25rem 0 !important; - font-size: 1rem; - display: inline-flex; - align-items: center; - color: var(--color-text); -} - -.tsd-panel-group.tsd-index-group { - margin-bottom: 0; -} -.tsd-index-panel .tsd-index-list { - list-style: none; - line-height: 1.333em; - margin: 0; - padding: 0.25rem 0 0 0; - overflow: hidden; - display: grid; - grid-template-columns: repeat(3, 1fr); - column-gap: 1rem; - grid-template-rows: auto; -} -@media (max-width: 1024px) { - .tsd-index-panel .tsd-index-list { - grid-template-columns: repeat(2, 1fr); - } -} -@media (max-width: 768px) { - .tsd-index-panel .tsd-index-list { - grid-template-columns: repeat(1, 1fr); - } -} -.tsd-index-panel .tsd-index-list li { - -webkit-page-break-inside: avoid; - -moz-page-break-inside: avoid; - -ms-page-break-inside: avoid; - -o-page-break-inside: avoid; - page-break-inside: avoid; -} - -.tsd-flag { - display: inline-block; - padding: 0.25em 0.4em; - border-radius: 4px; - color: var(--color-comment-tag-text); - background-color: var(--color-comment-tag); - text-indent: 0; - font-size: 75%; - line-height: 1; - font-weight: normal; -} - -.tsd-anchor { - position: relative; - top: -100px; -} - -.tsd-member { - position: relative; -} -.tsd-member .tsd-anchor + h3 { - display: flex; - align-items: center; - margin-top: 0; - margin-bottom: 0; - border-bottom: none; -} - -.tsd-navigation.settings { - margin: 1rem 0; -} -.tsd-navigation > a, -.tsd-navigation .tsd-accordion-summary { - width: calc(100% - 0.25rem); - display: flex; - align-items: center; -} -.tsd-navigation a, -.tsd-navigation summary > span, -.tsd-page-navigation a { - display: flex; - width: calc(100% - 0.25rem); - align-items: center; - padding: 0.25rem; - color: var(--color-text); - text-decoration: none; - box-sizing: border-box; -} -.tsd-navigation a.current, -.tsd-page-navigation a.current { - background: var(--color-active-menu-item); -} -.tsd-navigation a:hover, -.tsd-page-navigation a:hover { - text-decoration: underline; -} -.tsd-navigation ul, -.tsd-page-navigation ul { - margin-top: 0; - margin-bottom: 0; - padding: 0; - list-style: none; -} -.tsd-navigation li, -.tsd-page-navigation li { - padding: 0; - max-width: 100%; -} -.tsd-navigation .tsd-nav-link { - display: none; -} -.tsd-nested-navigation { - margin-left: 3rem; -} -.tsd-nested-navigation > li > details { - margin-left: -1.5rem; -} -.tsd-small-nested-navigation { - margin-left: 1.5rem; -} -.tsd-small-nested-navigation > li > details { - margin-left: -1.5rem; -} - -.tsd-page-navigation-section { - margin-left: 10px; -} -.tsd-page-navigation-section > summary { - padding: 0.25rem; -} -.tsd-page-navigation-section > div { - margin-left: 20px; -} -.tsd-page-navigation ul { - padding-left: 1.75rem; -} - -#tsd-sidebar-links a { - margin-top: 0; - margin-bottom: 0.5rem; - line-height: 1.25rem; -} -#tsd-sidebar-links a:last-of-type { - margin-bottom: 0; -} - -a.tsd-index-link { - padding: 0.25rem 0 !important; - font-size: 1rem; - line-height: 1.25rem; - display: inline-flex; - align-items: center; - color: var(--color-text); -} -.tsd-accordion-summary { - list-style-type: none; /* hide marker on non-safari */ - outline: none; /* broken on safari, so just hide it */ -} -.tsd-accordion-summary::-webkit-details-marker { - display: none; /* hide marker on safari */ -} -.tsd-accordion-summary, -.tsd-accordion-summary a { - -moz-user-select: none; - -webkit-user-select: none; - -ms-user-select: none; - user-select: none; - - cursor: pointer; -} -.tsd-accordion-summary a { - width: calc(100% - 1.5rem); -} -.tsd-accordion-summary > * { - margin-top: 0; - margin-bottom: 0; - padding-top: 0; - padding-bottom: 0; -} -.tsd-accordion .tsd-accordion-summary > svg { - margin-left: 0.25rem; - vertical-align: text-top; -} -.tsd-index-content > :not(:first-child) { - margin-top: 0.75rem; -} -.tsd-index-heading { - margin-top: 1.5rem; - margin-bottom: 0.75rem; -} - -.tsd-no-select { - -webkit-user-select: none; - -moz-user-select: none; - -ms-user-select: none; - user-select: none; -} -.tsd-kind-icon { - margin-right: 0.5rem; - width: 1.25rem; - height: 1.25rem; - min-width: 1.25rem; - min-height: 1.25rem; -} -.tsd-signature > .tsd-kind-icon { - margin-right: 0.8rem; -} - -.tsd-panel { - margin-bottom: 2.5rem; -} -.tsd-panel.tsd-member { - margin-bottom: 4rem; -} -.tsd-panel:empty { - display: none; -} -.tsd-panel > h1, -.tsd-panel > h2, -.tsd-panel > h3 { - margin: 1.5rem -1.5rem 0.75rem -1.5rem; - padding: 0 1.5rem 0.75rem 1.5rem; -} -.tsd-panel > h1.tsd-before-signature, -.tsd-panel > h2.tsd-before-signature, -.tsd-panel > h3.tsd-before-signature { - margin-bottom: 0; - border-bottom: none; -} - -.tsd-panel-group { - margin: 2rem 0; -} -.tsd-panel-group.tsd-index-group { - margin: 2rem 0; -} -.tsd-panel-group.tsd-index-group details { - margin: 2rem 0; -} -.tsd-panel-group > .tsd-accordion-summary { - margin-bottom: 1rem; -} - -#tsd-search { - transition: background-color 0.2s; -} -#tsd-search .title { - position: relative; - z-index: 2; -} -#tsd-search .field { - position: absolute; - left: 0; - top: 0; - right: 2.5rem; - height: 100%; -} -#tsd-search .field input { - box-sizing: border-box; - position: relative; - top: -50px; - z-index: 1; - width: 100%; - padding: 0 10px; - opacity: 0; - outline: 0; - border: 0; - background: transparent; - color: var(--color-text); -} -#tsd-search .field label { - position: absolute; - overflow: hidden; - right: -40px; -} -#tsd-search .field input, -#tsd-search .title, -#tsd-toolbar-links a { - transition: opacity 0.2s; -} -#tsd-search .results { - position: absolute; - visibility: hidden; - top: 40px; - width: 100%; - margin: 0; - padding: 0; - list-style: none; - box-shadow: 0 0 4px rgba(0, 0, 0, 0.25); -} -#tsd-search .results li { - background-color: var(--color-background); - line-height: initial; - padding: 4px; -} -#tsd-search .results li:nth-child(even) { - background-color: var(--color-background-secondary); -} -#tsd-search .results li.state { - display: none; -} -#tsd-search .results li.current:not(.no-results), -#tsd-search .results li:hover:not(.no-results) { - background-color: var(--color-accent); -} -#tsd-search .results a { - display: flex; - align-items: center; - padding: 0.25rem; - box-sizing: border-box; -} -#tsd-search .results a:before { - top: 10px; -} -#tsd-search .results span.parent { - color: var(--color-text-aside); - font-weight: normal; -} -#tsd-search.has-focus { - background-color: var(--color-accent); -} -#tsd-search.has-focus .field input { - top: 0; - opacity: 1; -} -#tsd-search.has-focus .title, -#tsd-search.has-focus #tsd-toolbar-links a { - z-index: 0; - opacity: 0; -} -#tsd-search.has-focus .results { - visibility: visible; -} -#tsd-search.loading .results li.state.loading { - display: block; -} -#tsd-search.failure .results li.state.failure { - display: block; -} - -#tsd-toolbar-links { - position: absolute; - top: 0; - right: 2rem; - height: 100%; - display: flex; - align-items: center; - justify-content: flex-end; -} -#tsd-toolbar-links a { - margin-left: 1.5rem; -} -#tsd-toolbar-links a:hover { - text-decoration: underline; -} - -.tsd-signature { - margin: 0 0 1rem 0; - padding: 1rem 0.5rem; - border: 1px solid var(--color-accent); - font-family: Menlo, Monaco, Consolas, "Courier New", monospace; - font-size: 14px; - overflow-x: auto; -} - -.tsd-signature-keyword { - color: var(--color-ts-keyword); - font-weight: normal; -} - -.tsd-signature-symbol { - color: var(--color-text-aside); - font-weight: normal; -} - -.tsd-signature-type { - font-style: italic; - font-weight: normal; -} - -.tsd-signatures { - padding: 0; - margin: 0 0 1em 0; - list-style-type: none; -} -.tsd-signatures .tsd-signature { - margin: 0; - border-color: var(--color-accent); - border-width: 1px 0; - transition: background-color 0.1s; -} -.tsd-signatures .tsd-index-signature:not(:last-child) { - margin-bottom: 1em; -} -.tsd-signatures .tsd-index-signature .tsd-signature { - border-width: 1px; -} -.tsd-description .tsd-signatures .tsd-signature { - border-width: 1px; -} - -ul.tsd-parameter-list, -ul.tsd-type-parameter-list { - list-style: square; - margin: 0; - padding-left: 20px; -} -ul.tsd-parameter-list > li.tsd-parameter-signature, -ul.tsd-type-parameter-list > li.tsd-parameter-signature { - list-style: none; - margin-left: -20px; -} -ul.tsd-parameter-list h5, -ul.tsd-type-parameter-list h5 { - font-size: 16px; - margin: 1em 0 0.5em 0; -} -.tsd-sources { - margin-top: 1rem; - font-size: 0.875em; -} -.tsd-sources a { - color: var(--color-text-aside); - text-decoration: underline; -} -.tsd-sources ul { - list-style: none; - padding: 0; -} - -.tsd-page-toolbar { - position: sticky; - z-index: 1; - top: 0; - left: 0; - width: 100%; - color: var(--color-text); - background: var(--color-background-secondary); - border-bottom: 1px var(--color-accent) solid; - transition: transform 0.3s ease-in-out; -} -.tsd-page-toolbar a { - color: var(--color-text); - text-decoration: none; -} -.tsd-page-toolbar a.title { - font-weight: bold; -} -.tsd-page-toolbar a.title:hover { - text-decoration: underline; -} -.tsd-page-toolbar .tsd-toolbar-contents { - display: flex; - justify-content: space-between; - height: 2.5rem; - margin: 0 auto; -} -.tsd-page-toolbar .table-cell { - position: relative; - white-space: nowrap; - line-height: 40px; -} -.tsd-page-toolbar .table-cell:first-child { - width: 100%; -} -.tsd-page-toolbar .tsd-toolbar-icon { - box-sizing: border-box; - line-height: 0; - padding: 12px 0; -} - -.tsd-widget { - display: inline-block; - overflow: hidden; - opacity: 0.8; - height: 40px; - transition: - opacity 0.1s, - background-color 0.2s; - vertical-align: bottom; - cursor: pointer; -} -.tsd-widget:hover { - opacity: 0.9; -} -.tsd-widget.active { - opacity: 1; - background-color: var(--color-accent); -} -.tsd-widget.no-caption { - width: 40px; -} -.tsd-widget.no-caption:before { - margin: 0; -} - -.tsd-widget.options, -.tsd-widget.menu { - display: none; -} -input[type="checkbox"] + .tsd-widget:before { - background-position: -120px 0; -} -input[type="checkbox"]:checked + .tsd-widget:before { - background-position: -160px 0; -} - -img { - max-width: 100%; -} - -.tsd-anchor-icon { - display: inline-flex; - align-items: center; - margin-left: 0.5rem; - vertical-align: middle; - color: var(--color-text); -} - -.tsd-anchor-icon svg { - width: 1em; - height: 1em; - visibility: hidden; -} - -.tsd-anchor-link:hover > .tsd-anchor-icon svg { - visibility: visible; -} - -.deprecated { - text-decoration: line-through !important; -} - -.warning { - padding: 1rem; - color: var(--color-warning-text); - background: var(--color-background-warning); -} - -.tsd-kind-project { - color: var(--color-ts-project); -} -.tsd-kind-module { - color: var(--color-ts-module); -} -.tsd-kind-namespace { - color: var(--color-ts-namespace); -} -.tsd-kind-enum { - color: var(--color-ts-enum); -} -.tsd-kind-enum-member { - color: var(--color-ts-enum-member); -} -.tsd-kind-variable { - color: var(--color-ts-variable); -} -.tsd-kind-function { - color: var(--color-ts-function); -} -.tsd-kind-class { - color: var(--color-ts-class); -} -.tsd-kind-interface { - color: var(--color-ts-interface); -} -.tsd-kind-constructor { - color: var(--color-ts-constructor); -} -.tsd-kind-property { - color: var(--color-ts-property); -} -.tsd-kind-method { - color: var(--color-ts-method); -} -.tsd-kind-reference { - color: var(--color-ts-reference); -} -.tsd-kind-call-signature { - color: var(--color-ts-call-signature); -} -.tsd-kind-index-signature { - color: var(--color-ts-index-signature); -} -.tsd-kind-constructor-signature { - color: var(--color-ts-constructor-signature); -} -.tsd-kind-parameter { - color: var(--color-ts-parameter); -} -.tsd-kind-type-parameter { - color: var(--color-ts-type-parameter); -} -.tsd-kind-accessor { - color: var(--color-ts-accessor); -} -.tsd-kind-get-signature { - color: var(--color-ts-get-signature); -} -.tsd-kind-set-signature { - color: var(--color-ts-set-signature); -} -.tsd-kind-type-alias { - color: var(--color-ts-type-alias); -} - -/* if we have a kind icon, don't color the text by kind */ -.tsd-kind-icon ~ span { - color: var(--color-text); -} - -* { - scrollbar-width: thin; - scrollbar-color: var(--color-accent) var(--color-icon-background); -} - -*::-webkit-scrollbar { - width: 0.75rem; -} - -*::-webkit-scrollbar-track { - background: var(--color-icon-background); -} - -*::-webkit-scrollbar-thumb { - background-color: var(--color-accent); - border-radius: 999rem; - border: 0.25rem solid var(--color-icon-background); -} - -/* mobile */ -@media (max-width: 769px) { - .tsd-widget.options, - .tsd-widget.menu { - display: inline-block; - } - - .container-main { - display: flex; - } - html .col-content { - float: none; - max-width: 100%; - width: 100%; - } - html .col-sidebar { - position: fixed !important; - overflow-y: auto; - -webkit-overflow-scrolling: touch; - z-index: 1024; - top: 0 !important; - bottom: 0 !important; - left: auto !important; - right: 0 !important; - padding: 1.5rem 1.5rem 0 0; - width: 75vw; - visibility: hidden; - background-color: var(--color-background); - transform: translate(100%, 0); - } - html .col-sidebar > *:last-child { - padding-bottom: 20px; - } - html .overlay { - content: ""; - display: block; - position: fixed; - z-index: 1023; - top: 0; - left: 0; - right: 0; - bottom: 0; - background-color: rgba(0, 0, 0, 0.75); - visibility: hidden; - } - - .to-has-menu .overlay { - animation: fade-in 0.4s; - } - - .to-has-menu .col-sidebar { - animation: pop-in-from-right 0.4s; - } - - .from-has-menu .overlay { - animation: fade-out 0.4s; - } - - .from-has-menu .col-sidebar { - animation: pop-out-to-right 0.4s; - } - - .has-menu body { - overflow: hidden; - } - .has-menu .overlay { - visibility: visible; - } - .has-menu .col-sidebar { - visibility: visible; - transform: translate(0, 0); - display: flex; - flex-direction: column; - gap: 1.5rem; - max-height: 100vh; - padding: 1rem 2rem; - } - .has-menu .tsd-navigation { - max-height: 100%; - } - #tsd-toolbar-links { - display: none; - } - .tsd-navigation .tsd-nav-link { - display: flex; - } -} - -/* one sidebar */ -@media (min-width: 770px) { - .container-main { - display: grid; - grid-template-columns: minmax(0, 1fr) minmax(0, 2fr); - grid-template-areas: "sidebar content"; - margin: 2rem auto; - } - - .col-sidebar { - grid-area: sidebar; - } - .col-content { - grid-area: content; - padding: 0 1rem; - } -} -@media (min-width: 770px) and (max-width: 1399px) { - .col-sidebar { - max-height: calc(100vh - 2rem - 42px); - overflow: auto; - position: sticky; - top: 42px; - padding-top: 1rem; - } - .site-menu { - margin-top: 1rem; - } -} - -/* two sidebars */ -@media (min-width: 1200px) { - .container-main { - grid-template-columns: minmax(0, 1fr) minmax(0, 2.5fr) minmax(0, 20rem); - grid-template-areas: "sidebar content toc"; - } - - .col-sidebar { - display: contents; - } - - .page-menu { - grid-area: toc; - padding-left: 1rem; - } - .site-menu { - grid-area: sidebar; - } - - .site-menu { - margin-top: 1rem; - } - - .page-menu, - .site-menu { - max-height: calc(100vh - 2rem - 42px); - overflow: auto; - position: sticky; - top: 42px; - } -} diff --git a/mlflow/docs/documentation/classes/default.html b/mlflow/docs/documentation/classes/default.html deleted file mode 100644 index af2d475f..00000000 --- a/mlflow/docs/documentation/classes/default.html +++ /dev/null @@ -1,9 +0,0 @@ -default | mlflow-js

Classdefault

Constructors

Methods

  • Returns ExperimentClient

  • Returns ExperimentManager

  • Returns ModelManager

  • Returns ModelRegistryClient

  • Returns ModelVersionClient

  • Returns RunClient

  • Returns RunManager

diff --git a/mlflow/docs/documentation/index.html b/mlflow/docs/documentation/index.html deleted file mode 100644 index 93ab265c..00000000 --- a/mlflow/docs/documentation/index.html +++ /dev/null @@ -1,2 +0,0 @@ -mlflow-js

mlflow-js

Index

Classes

From adef11e1a14e34aab69cb91aa2250fb684e4e42b Mon Sep 17 00:00:00 2001 From: Austin Fraser Date: Wed, 16 Oct 2024 19:36:21 -0700 Subject: [PATCH 159/357] added new directory for site, ran create-next-app --- mlflow-site/.eslintrc.json | 3 + mlflow-site/.gitignore | 36 + mlflow-site/README.md | 36 + mlflow-site/next.config.mjs | 4 + mlflow-site/package-lock.json | 5317 ++++++++++++++++++++ mlflow-site/package.json | 26 + mlflow-site/postcss.config.mjs | 8 + mlflow-site/src/app/favicon.ico | Bin 0 -> 25931 bytes mlflow-site/src/app/fonts/GeistMonoVF.woff | Bin 0 -> 67864 bytes mlflow-site/src/app/fonts/GeistVF.woff | Bin 0 -> 66268 bytes mlflow-site/src/app/globals.css | 27 + mlflow-site/src/app/layout.tsx | 35 + mlflow-site/src/app/page.tsx | 101 + mlflow-site/tailwind.config.ts | 19 + mlflow-site/tsconfig.json | 26 + 15 files changed, 5638 insertions(+) create mode 100644 mlflow-site/.eslintrc.json create mode 100644 mlflow-site/.gitignore create mode 100644 mlflow-site/README.md create mode 100644 mlflow-site/next.config.mjs create mode 100644 mlflow-site/package-lock.json create mode 100644 mlflow-site/package.json create mode 100644 mlflow-site/postcss.config.mjs create mode 100644 mlflow-site/src/app/favicon.ico create mode 100644 mlflow-site/src/app/fonts/GeistMonoVF.woff create mode 100644 mlflow-site/src/app/fonts/GeistVF.woff create mode 100644 mlflow-site/src/app/globals.css create mode 100644 mlflow-site/src/app/layout.tsx create mode 100644 mlflow-site/src/app/page.tsx create mode 100644 mlflow-site/tailwind.config.ts create mode 100644 mlflow-site/tsconfig.json diff --git a/mlflow-site/.eslintrc.json b/mlflow-site/.eslintrc.json new file mode 100644 index 00000000..37224185 --- /dev/null +++ b/mlflow-site/.eslintrc.json @@ -0,0 +1,3 @@ +{ + "extends": ["next/core-web-vitals", "next/typescript"] +} diff --git a/mlflow-site/.gitignore b/mlflow-site/.gitignore new file mode 100644 index 00000000..fd3dbb57 --- /dev/null +++ b/mlflow-site/.gitignore @@ -0,0 +1,36 @@ +# See https://help.github.com/articles/ignoring-files/ for more about ignoring files. + +# dependencies +/node_modules +/.pnp +.pnp.js +.yarn/install-state.gz + +# testing +/coverage + +# next.js +/.next/ +/out/ + +# production +/build + +# misc +.DS_Store +*.pem + +# debug +npm-debug.log* +yarn-debug.log* +yarn-error.log* + +# local env files +.env*.local + +# vercel +.vercel + +# typescript +*.tsbuildinfo +next-env.d.ts diff --git a/mlflow-site/README.md b/mlflow-site/README.md new file mode 100644 index 00000000..e215bc4c --- /dev/null +++ b/mlflow-site/README.md @@ -0,0 +1,36 @@ +This is a [Next.js](https://nextjs.org) project bootstrapped with [`create-next-app`](https://nextjs.org/docs/app/api-reference/cli/create-next-app). + +## Getting Started + +First, run the development server: + +```bash +npm run dev +# or +yarn dev +# or +pnpm dev +# or +bun dev +``` + +Open [http://localhost:3000](http://localhost:3000) with your browser to see the result. + +You can start editing the page by modifying `app/page.tsx`. The page auto-updates as you edit the file. + +This project uses [`next/font`](https://nextjs.org/docs/app/building-your-application/optimizing/fonts) to automatically optimize and load [Geist](https://vercel.com/font), a new font family for Vercel. + +## Learn More + +To learn more about Next.js, take a look at the following resources: + +- [Next.js Documentation](https://nextjs.org/docs) - learn about Next.js features and API. +- [Learn Next.js](https://nextjs.org/learn) - an interactive Next.js tutorial. + +You can check out [the Next.js GitHub repository](https://github.com/vercel/next.js) - your feedback and contributions are welcome! + +## Deploy on Vercel + +The easiest way to deploy your Next.js app is to use the [Vercel Platform](https://vercel.com/new?utm_medium=default-template&filter=next.js&utm_source=create-next-app&utm_campaign=create-next-app-readme) from the creators of Next.js. + +Check out our [Next.js deployment documentation](https://nextjs.org/docs/app/building-your-application/deploying) for more details. diff --git a/mlflow-site/next.config.mjs b/mlflow-site/next.config.mjs new file mode 100644 index 00000000..4678774e --- /dev/null +++ b/mlflow-site/next.config.mjs @@ -0,0 +1,4 @@ +/** @type {import('next').NextConfig} */ +const nextConfig = {}; + +export default nextConfig; diff --git a/mlflow-site/package-lock.json b/mlflow-site/package-lock.json new file mode 100644 index 00000000..bdd6ac5e --- /dev/null +++ b/mlflow-site/package-lock.json @@ -0,0 +1,5317 @@ +{ + "name": "mlflow-site", + "version": "0.1.0", + "lockfileVersion": 3, + "requires": true, + "packages": { + "": { + "name": "mlflow-site", + "version": "0.1.0", + "dependencies": { + "next": "14.2.15", + "react": "^18", + "react-dom": "^18" + }, + "devDependencies": { + "@types/node": "^20", + "@types/react": "^18", + "@types/react-dom": "^18", + "eslint": "^8", + "eslint-config-next": "14.2.15", + "postcss": "^8", + "tailwindcss": "^3.4.1", + "typescript": "^5" + } + }, + "node_modules/@alloc/quick-lru": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/@alloc/quick-lru/-/quick-lru-5.2.0.tgz", + "integrity": "sha512-UrcABB+4bUrFABwbluTIBErXwvbsU/V7TZWfmbgJfbkwiBuziS9gxdODUyuiecfdGQ85jglMW6juS3+z5TsKLw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "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, + "license": "MIT", + "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.11.1", + "resolved": "https://registry.npmjs.org/@eslint-community/regexpp/-/regexpp-4.11.1.tgz", + "integrity": "sha512-m4DVN9ZqskZoLU5GlWZadwDnYo3vAEydiUayB9widCl9ffWx2IvPnp6n3on5rJmziJSw9Bv+Z3ChDVdMwXCY8Q==", + "dev": true, + "license": "MIT", + "engines": { + "node": "^12.0.0 || ^14.0.0 || >=16.0.0" + } + }, + "node_modules/@eslint/eslintrc": { + "version": "2.1.4", + "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-2.1.4.tgz", + "integrity": "sha512-269Z39MS6wVJtsoUl10L60WdkhJVdPG24Q4eZTH3nnF6lpvSShEK3wQjDX9JRWAUPvPh7COouPpU9IrqaZFvtQ==", + "dev": true, + "license": "MIT", + "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/js": { + "version": "8.57.1", + "resolved": "https://registry.npmjs.org/@eslint/js/-/js-8.57.1.tgz", + "integrity": "sha512-d9zaMRSTIKDLhctzH12MtXvJKSSUhaHcjV+2Z+GK+EEY7XKpP5yR4x+N3TAcHTcu963nIr+TMcCb4DBCYX1z6Q==", + "dev": true, + "license": "MIT", + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + } + }, + "node_modules/@humanwhocodes/config-array": { + "version": "0.13.0", + "resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.13.0.tgz", + "integrity": "sha512-DZLEEqFWQFiyK6h5YIeynKx7JlvCYWL0cImfSRXZ9l4Sg2efkFGTuFf6vzXjK1cq6IYkU+Eg/JizXw+TD2vRNw==", + "deprecated": "Use @eslint/config-array instead", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "@humanwhocodes/object-schema": "^2.0.3", + "debug": "^4.3.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, + "license": "Apache-2.0", + "engines": { + "node": ">=12.22" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/nzakas" + } + }, + "node_modules/@humanwhocodes/object-schema": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/@humanwhocodes/object-schema/-/object-schema-2.0.3.tgz", + "integrity": "sha512-93zYdMES/c1D69yZiKDBj0V24vqNzB/koF26KPaagAfd3P/4gUlh3Dys5ogAK+Exi9QyzlD8x/08Zt7wIKcDcA==", + "deprecated": "Use @eslint/object-schema instead", + "dev": true, + "license": "BSD-3-Clause" + }, + "node_modules/@isaacs/cliui": { + "version": "8.0.2", + "resolved": "https://registry.npmjs.org/@isaacs/cliui/-/cliui-8.0.2.tgz", + "integrity": "sha512-O8jcjabXaleOG9DQ0+ARXWZBTfnP4WNAqzuiJK7ll44AmxGKv/J2M4TPjxjY3znBCfvBXFzucm1twdyFybFqEA==", + "dev": true, + "license": "ISC", + "dependencies": { + "string-width": "^5.1.2", + "string-width-cjs": "npm:string-width@^4.2.0", + "strip-ansi": "^7.0.1", + "strip-ansi-cjs": "npm:strip-ansi@^6.0.1", + "wrap-ansi": "^8.1.0", + "wrap-ansi-cjs": "npm:wrap-ansi@^7.0.0" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/@isaacs/cliui/node_modules/ansi-regex": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.1.0.tgz", + "integrity": "sha512-7HSX4QQb4CspciLpVFwyRe79O3xsIZDDLER21kERQ71oaPodF8jL725AgJMFAYbooIqolJoRLuM81SpeUkpkvA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/ansi-regex?sponsor=1" + } + }, + "node_modules/@isaacs/cliui/node_modules/strip-ansi": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.1.0.tgz", + "integrity": "sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-regex": "^6.0.1" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/strip-ansi?sponsor=1" + } + }, + "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, + "license": "MIT", + "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, + "license": "MIT", + "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, + "license": "MIT", + "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, + "license": "MIT" + }, + "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, + "license": "MIT", + "dependencies": { + "@jridgewell/resolve-uri": "^3.1.0", + "@jridgewell/sourcemap-codec": "^1.4.14" + } + }, + "node_modules/@next/env": { + "version": "14.2.15", + "resolved": "https://registry.npmjs.org/@next/env/-/env-14.2.15.tgz", + "integrity": "sha512-S1qaj25Wru2dUpcIZMjxeMVSwkt8BK4dmWHHiBuRstcIyOsMapqT4A4jSB6onvqeygkSSmOkyny9VVx8JIGamQ==", + "license": "MIT" + }, + "node_modules/@next/eslint-plugin-next": { + "version": "14.2.15", + "resolved": "https://registry.npmjs.org/@next/eslint-plugin-next/-/eslint-plugin-next-14.2.15.tgz", + "integrity": "sha512-pKU0iqKRBlFB/ocOI1Ip2CkKePZpYpnw5bEItEkuZ/Nr9FQP1+p7VDWr4VfOdff4i9bFmrOaeaU1bFEyAcxiMQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "glob": "10.3.10" + } + }, + "node_modules/@next/swc-darwin-arm64": { + "version": "14.2.15", + "resolved": "https://registry.npmjs.org/@next/swc-darwin-arm64/-/swc-darwin-arm64-14.2.15.tgz", + "integrity": "sha512-Rvh7KU9hOUBnZ9TJ28n2Oa7dD9cvDBKua9IKx7cfQQ0GoYUwg9ig31O2oMwH3wm+pE3IkAQ67ZobPfEgurPZIA==", + "cpu": [ + "arm64" + ], + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@next/swc-darwin-x64": { + "version": "14.2.15", + "resolved": "https://registry.npmjs.org/@next/swc-darwin-x64/-/swc-darwin-x64-14.2.15.tgz", + "integrity": "sha512-5TGyjFcf8ampZP3e+FyCax5zFVHi+Oe7sZyaKOngsqyaNEpOgkKB3sqmymkZfowy3ufGA/tUgDPPxpQx931lHg==", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@next/swc-linux-arm64-gnu": { + "version": "14.2.15", + "resolved": "https://registry.npmjs.org/@next/swc-linux-arm64-gnu/-/swc-linux-arm64-gnu-14.2.15.tgz", + "integrity": "sha512-3Bwv4oc08ONiQ3FiOLKT72Q+ndEMyLNsc/D3qnLMbtUYTQAmkx9E/JRu0DBpHxNddBmNT5hxz1mYBphJ3mfrrw==", + "cpu": [ + "arm64" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@next/swc-linux-arm64-musl": { + "version": "14.2.15", + "resolved": "https://registry.npmjs.org/@next/swc-linux-arm64-musl/-/swc-linux-arm64-musl-14.2.15.tgz", + "integrity": "sha512-k5xf/tg1FBv/M4CMd8S+JL3uV9BnnRmoe7F+GWC3DxkTCD9aewFRH1s5rJ1zkzDa+Do4zyN8qD0N8c84Hu96FQ==", + "cpu": [ + "arm64" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@next/swc-linux-x64-gnu": { + "version": "14.2.15", + "resolved": "https://registry.npmjs.org/@next/swc-linux-x64-gnu/-/swc-linux-x64-gnu-14.2.15.tgz", + "integrity": "sha512-kE6q38hbrRbKEkkVn62reLXhThLRh6/TvgSP56GkFNhU22TbIrQDEMrO7j0IcQHcew2wfykq8lZyHFabz0oBrA==", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@next/swc-linux-x64-musl": { + "version": "14.2.15", + "resolved": "https://registry.npmjs.org/@next/swc-linux-x64-musl/-/swc-linux-x64-musl-14.2.15.tgz", + "integrity": "sha512-PZ5YE9ouy/IdO7QVJeIcyLn/Rc4ml9M2G4y3kCM9MNf1YKvFY4heg3pVa/jQbMro+tP6yc4G2o9LjAz1zxD7tQ==", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@next/swc-win32-arm64-msvc": { + "version": "14.2.15", + "resolved": "https://registry.npmjs.org/@next/swc-win32-arm64-msvc/-/swc-win32-arm64-msvc-14.2.15.tgz", + "integrity": "sha512-2raR16703kBvYEQD9HNLyb0/394yfqzmIeyp2nDzcPV4yPjqNUG3ohX6jX00WryXz6s1FXpVhsCo3i+g4RUX+g==", + "cpu": [ + "arm64" + ], + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@next/swc-win32-ia32-msvc": { + "version": "14.2.15", + "resolved": "https://registry.npmjs.org/@next/swc-win32-ia32-msvc/-/swc-win32-ia32-msvc-14.2.15.tgz", + "integrity": "sha512-fyTE8cklgkyR1p03kJa5zXEaZ9El+kDNM5A+66+8evQS5e/6v0Gk28LqA0Jet8gKSOyP+OTm/tJHzMlGdQerdQ==", + "cpu": [ + "ia32" + ], + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@next/swc-win32-x64-msvc": { + "version": "14.2.15", + "resolved": "https://registry.npmjs.org/@next/swc-win32-x64-msvc/-/swc-win32-x64-msvc-14.2.15.tgz", + "integrity": "sha512-SzqGbsLsP9OwKNUG9nekShTwhj6JSB9ZLMWQ8g1gG6hdE5gQLncbnbymrwy2yVmH9nikSLYRYxYMFu78Ggp7/g==", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">= 10" + } + }, + "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, + "license": "MIT", + "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, + "license": "MIT", + "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, + "license": "MIT", + "dependencies": { + "@nodelib/fs.scandir": "2.1.5", + "fastq": "^1.6.0" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/@nolyfill/is-core-module": { + "version": "1.0.39", + "resolved": "https://registry.npmjs.org/@nolyfill/is-core-module/-/is-core-module-1.0.39.tgz", + "integrity": "sha512-nn5ozdjYQpUCZlWGuxcJY/KpxkWQs4DcbMCmKojjyrYDEAGy4Ce19NN4v5MduafTwJlbKc99UA8YhSVqq9yPZA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12.4.0" + } + }, + "node_modules/@pkgjs/parseargs": { + "version": "0.11.0", + "resolved": "https://registry.npmjs.org/@pkgjs/parseargs/-/parseargs-0.11.0.tgz", + "integrity": "sha512-+1VkjdD0QBLPodGrJUeqarH8VAIvQODIbwh9XpP5Syisf7YoQgsJKPNFoqqLQlu+VQ/tVSshMR6loPMn8U+dPg==", + "dev": true, + "license": "MIT", + "optional": true, + "engines": { + "node": ">=14" + } + }, + "node_modules/@rtsao/scc": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@rtsao/scc/-/scc-1.1.0.tgz", + "integrity": "sha512-zt6OdqaDoOnJ1ZYsCYGt9YmWzDXl4vQdKTyJev62gFhRGKdx7mcT54V9KIjg+d2wi9EXsPvAPKe7i7WjfVWB8g==", + "dev": true, + "license": "MIT" + }, + "node_modules/@rushstack/eslint-patch": { + "version": "1.10.4", + "resolved": "https://registry.npmjs.org/@rushstack/eslint-patch/-/eslint-patch-1.10.4.tgz", + "integrity": "sha512-WJgX9nzTqknM393q1QJDJmoW28kUfEnybeTfVNcNAPnIx210RXm2DiXiHzfNPJNIUUb1tJnz/l4QGtJ30PgWmA==", + "dev": true, + "license": "MIT" + }, + "node_modules/@swc/counter": { + "version": "0.1.3", + "resolved": "https://registry.npmjs.org/@swc/counter/-/counter-0.1.3.tgz", + "integrity": "sha512-e2BR4lsJkkRlKZ/qCHPw9ZaSxc0MVUd7gtbtaB7aMvHeJVYe8sOB8DBZkP2DtISHGSku9sCK6T6cnY0CtXrOCQ==", + "license": "Apache-2.0" + }, + "node_modules/@swc/helpers": { + "version": "0.5.5", + "resolved": "https://registry.npmjs.org/@swc/helpers/-/helpers-0.5.5.tgz", + "integrity": "sha512-KGYxvIOXcceOAbEk4bi/dVLEK9z8sZ0uBB3Il5b1rhfClSpcX0yfRO0KmTkqR2cnQDymwLB+25ZyMzICg/cm/A==", + "license": "Apache-2.0", + "dependencies": { + "@swc/counter": "^0.1.3", + "tslib": "^2.4.0" + } + }, + "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, + "license": "MIT" + }, + "node_modules/@types/node": { + "version": "20.16.12", + "resolved": "https://registry.npmjs.org/@types/node/-/node-20.16.12.tgz", + "integrity": "sha512-LfPFB0zOeCeCNQV3i+67rcoVvoN5n0NVuR2vLG0O5ySQMgchuZlC4lgz546ZOJyDtj5KIgOxy+lacOimfqZAIA==", + "dev": true, + "license": "MIT", + "dependencies": { + "undici-types": "~6.19.2" + } + }, + "node_modules/@types/prop-types": { + "version": "15.7.13", + "resolved": "https://registry.npmjs.org/@types/prop-types/-/prop-types-15.7.13.tgz", + "integrity": "sha512-hCZTSvwbzWGvhqxp/RqVqwU999pBf2vp7hzIjiYOsl8wqOmUxkQ6ddw1cV3l8811+kdUFus/q4d1Y3E3SyEifA==", + "dev": true, + "license": "MIT" + }, + "node_modules/@types/react": { + "version": "18.3.11", + "resolved": "https://registry.npmjs.org/@types/react/-/react-18.3.11.tgz", + "integrity": "sha512-r6QZ069rFTjrEYgFdOck1gK7FLVsgJE7tTz0pQBczlBNUhBNk0MQH4UbnFSwjpQLMkLzgqvBBa+qGpLje16eTQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/prop-types": "*", + "csstype": "^3.0.2" + } + }, + "node_modules/@types/react-dom": { + "version": "18.3.1", + "resolved": "https://registry.npmjs.org/@types/react-dom/-/react-dom-18.3.1.tgz", + "integrity": "sha512-qW1Mfv8taImTthu4KoXgDfLuk4bydU6Q/TkADnDWWHwi4NX4BR+LWfTp2sVmTqRrsHvyDDTelgelxJ+SsejKKQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/react": "*" + } + }, + "node_modules/@typescript-eslint/eslint-plugin": { + "version": "8.9.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-8.9.0.tgz", + "integrity": "sha512-Y1n621OCy4m7/vTXNlCbMVp87zSd7NH0L9cXD8aIpOaNlzeWxIK4+Q19A68gSmTNRZn92UjocVUWDthGxtqHFg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@eslint-community/regexpp": "^4.10.0", + "@typescript-eslint/scope-manager": "8.9.0", + "@typescript-eslint/type-utils": "8.9.0", + "@typescript-eslint/utils": "8.9.0", + "@typescript-eslint/visitor-keys": "8.9.0", + "graphemer": "^1.4.0", + "ignore": "^5.3.1", + "natural-compare": "^1.4.0", + "ts-api-utils": "^1.3.0" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "@typescript-eslint/parser": "^8.0.0 || ^8.0.0-alpha.0", + "eslint": "^8.57.0 || ^9.0.0" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, + "node_modules/@typescript-eslint/parser": { + "version": "8.9.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-8.9.0.tgz", + "integrity": "sha512-U+BLn2rqTTHnc4FL3FJjxaXptTxmf9sNftJK62XLz4+GxG3hLHm/SUNaaXP5Y4uTiuYoL5YLy4JBCJe3+t8awQ==", + "dev": true, + "license": "BSD-2-Clause", + "dependencies": { + "@typescript-eslint/scope-manager": "8.9.0", + "@typescript-eslint/types": "8.9.0", + "@typescript-eslint/typescript-estree": "8.9.0", + "@typescript-eslint/visitor-keys": "8.9.0", + "debug": "^4.3.4" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "eslint": "^8.57.0 || ^9.0.0" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, + "node_modules/@typescript-eslint/scope-manager": { + "version": "8.9.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-8.9.0.tgz", + "integrity": "sha512-bZu9bUud9ym1cabmOYH9S6TnbWRzpklVmwqICeOulTCZ9ue2/pczWzQvt/cGj2r2o1RdKoZbuEMalJJSYw3pHQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@typescript-eslint/types": "8.9.0", + "@typescript-eslint/visitor-keys": "8.9.0" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + } + }, + "node_modules/@typescript-eslint/type-utils": { + "version": "8.9.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-8.9.0.tgz", + "integrity": "sha512-JD+/pCqlKqAk5961vxCluK+clkppHY07IbV3vett97KOV+8C6l+CPEPwpUuiMwgbOz/qrN3Ke4zzjqbT+ls+1Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "@typescript-eslint/typescript-estree": "8.9.0", + "@typescript-eslint/utils": "8.9.0", + "debug": "^4.3.4", + "ts-api-utils": "^1.3.0" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, + "node_modules/@typescript-eslint/types": { + "version": "8.9.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-8.9.0.tgz", + "integrity": "sha512-SjgkvdYyt1FAPhU9c6FiYCXrldwYYlIQLkuc+LfAhCna6ggp96ACncdtlbn8FmnG72tUkXclrDExOpEYf1nfJQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + } + }, + "node_modules/@typescript-eslint/typescript-estree": { + "version": "8.9.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-8.9.0.tgz", + "integrity": "sha512-9iJYTgKLDG6+iqegehc5+EqE6sqaee7kb8vWpmHZ86EqwDjmlqNNHeqDVqb9duh+BY6WCNHfIGvuVU3Tf9Db0g==", + "dev": true, + "license": "BSD-2-Clause", + "dependencies": { + "@typescript-eslint/types": "8.9.0", + "@typescript-eslint/visitor-keys": "8.9.0", + "debug": "^4.3.4", + "fast-glob": "^3.3.2", + "is-glob": "^4.0.3", + "minimatch": "^9.0.4", + "semver": "^7.6.0", + "ts-api-utils": "^1.3.0" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, + "node_modules/@typescript-eslint/typescript-estree/node_modules/brace-expansion": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", + "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", + "dev": true, + "license": "MIT", + "dependencies": { + "balanced-match": "^1.0.0" + } + }, + "node_modules/@typescript-eslint/typescript-estree/node_modules/minimatch": { + "version": "9.0.5", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.5.tgz", + "integrity": "sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow==", + "dev": true, + "license": "ISC", + "dependencies": { + "brace-expansion": "^2.0.1" + }, + "engines": { + "node": ">=16 || 14 >=14.17" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/@typescript-eslint/utils": { + "version": "8.9.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-8.9.0.tgz", + "integrity": "sha512-PKgMmaSo/Yg/F7kIZvrgrWa1+Vwn036CdNUvYFEkYbPwOH4i8xvkaRlu148W3vtheWK9ckKRIz7PBP5oUlkrvQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@eslint-community/eslint-utils": "^4.4.0", + "@typescript-eslint/scope-manager": "8.9.0", + "@typescript-eslint/types": "8.9.0", + "@typescript-eslint/typescript-estree": "8.9.0" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "eslint": "^8.57.0 || ^9.0.0" + } + }, + "node_modules/@typescript-eslint/visitor-keys": { + "version": "8.9.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-8.9.0.tgz", + "integrity": "sha512-Ht4y38ubk4L5/U8xKUBfKNYGmvKvA1CANoxiTRMM+tOLk3lbF3DvzZCxJCRSE+2GdCMSh6zq9VZJc3asc1XuAA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@typescript-eslint/types": "8.9.0", + "eslint-visitor-keys": "^3.4.3" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + } + }, + "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, + "license": "ISC" + }, + "node_modules/acorn": { + "version": "8.13.0", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.13.0.tgz", + "integrity": "sha512-8zSiw54Oxrdym50NlZ9sUusyO1Z1ZchgRLWRaK6c86XJFClyCgFKetdowBg5bKxyp/u+CDBJG4Mpp0m3HLZl9w==", + "dev": true, + "license": "MIT", + "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, + "license": "MIT", + "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, + "license": "MIT", + "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-regex": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", + "dev": true, + "license": "MIT", + "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, + "license": "MIT", + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/any-promise": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/any-promise/-/any-promise-1.3.0.tgz", + "integrity": "sha512-7UvmKalWRt1wgjL1RrGxoSJW/0QZFIegpeGvZG9kjp8vrRu55XTHbwnqq2GpXm9uLbcuhxm3IqX9OB4MZR1b2A==", + "dev": true, + "license": "MIT" + }, + "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, + "license": "ISC", + "dependencies": { + "normalize-path": "^3.0.0", + "picomatch": "^2.0.4" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/arg": { + "version": "5.0.2", + "resolved": "https://registry.npmjs.org/arg/-/arg-5.0.2.tgz", + "integrity": "sha512-PYjyFOLKQ9y57JvQ6QLo8dAgNqswh8M1RMJYdQduT6xbWSgK36P/Z/v+p888pM69jMMfS8Xd8F6I1kQ/I9HUGg==", + "dev": true, + "license": "MIT" + }, + "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, + "license": "Python-2.0" + }, + "node_modules/aria-query": { + "version": "5.1.3", + "resolved": "https://registry.npmjs.org/aria-query/-/aria-query-5.1.3.tgz", + "integrity": "sha512-R5iJ5lkuHybztUfuOAznmboyjWq8O6sqNqtK7CLOqdydi54VNbORp49mb14KbWgG1QD3JFO9hJdZ+y4KutfdOQ==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "deep-equal": "^2.0.5" + } + }, + "node_modules/array-buffer-byte-length": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/array-buffer-byte-length/-/array-buffer-byte-length-1.0.1.tgz", + "integrity": "sha512-ahC5W1xgou+KTXix4sAO8Ki12Q+jf4i0+tmk3sC+zgcynshkHxzpXdImBehiUYKKKDwvfFiJl1tZt6ewscS1Mg==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.5", + "is-array-buffer": "^3.0.4" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/array-includes": { + "version": "3.1.8", + "resolved": "https://registry.npmjs.org/array-includes/-/array-includes-3.1.8.tgz", + "integrity": "sha512-itaWrbYbqpGXkGhZPGUulwnhVf5Hpy1xiCFsGqyIGglbBxmG5vSjxQen3/WGOjPpNEv1RtBLKxbmVXm8HpJStQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.7", + "define-properties": "^1.2.1", + "es-abstract": "^1.23.2", + "es-object-atoms": "^1.0.0", + "get-intrinsic": "^1.2.4", + "is-string": "^1.0.7" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/array.prototype.findlast": { + "version": "1.2.5", + "resolved": "https://registry.npmjs.org/array.prototype.findlast/-/array.prototype.findlast-1.2.5.tgz", + "integrity": "sha512-CVvd6FHg1Z3POpBLxO6E6zr+rSKEQ9L6rZHAaY7lLfhKsWYUBBOuMs0e9o24oopj6H+geRCX0YJ+TJLBK2eHyQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.7", + "define-properties": "^1.2.1", + "es-abstract": "^1.23.2", + "es-errors": "^1.3.0", + "es-object-atoms": "^1.0.0", + "es-shim-unscopables": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/array.prototype.findlastindex": { + "version": "1.2.5", + "resolved": "https://registry.npmjs.org/array.prototype.findlastindex/-/array.prototype.findlastindex-1.2.5.tgz", + "integrity": "sha512-zfETvRFA8o7EiNn++N5f/kaCw221hrpGsDmcpndVupkPzEc1Wuf3VgC0qby1BbHs7f5DVYjgtEU2LLh5bqeGfQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.7", + "define-properties": "^1.2.1", + "es-abstract": "^1.23.2", + "es-errors": "^1.3.0", + "es-object-atoms": "^1.0.0", + "es-shim-unscopables": "^1.0.2" + }, + "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, + "license": "MIT", + "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, + "license": "MIT", + "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.4", + "resolved": "https://registry.npmjs.org/array.prototype.tosorted/-/array.prototype.tosorted-1.1.4.tgz", + "integrity": "sha512-p6Fx8B7b7ZhL/gmUsAy0D15WhvDccw3mnGNbZpi3pmeJdxtWsj2jEaI4Y6oo3XiHfzuSgPwKc04MYt6KgvC/wA==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.7", + "define-properties": "^1.2.1", + "es-abstract": "^1.23.3", + "es-errors": "^1.3.0", + "es-shim-unscopables": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/arraybuffer.prototype.slice": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/arraybuffer.prototype.slice/-/arraybuffer.prototype.slice-1.0.3.tgz", + "integrity": "sha512-bMxMKAjg13EBSVscxTaYA4mRc5t1UAXa2kXiGTNfZ079HIWXEkKmkgFrh/nJqamaLSrXO5H4WFFkPEaLJWbs3A==", + "dev": true, + "license": "MIT", + "dependencies": { + "array-buffer-byte-length": "^1.0.1", + "call-bind": "^1.0.5", + "define-properties": "^1.2.1", + "es-abstract": "^1.22.3", + "es-errors": "^1.2.1", + "get-intrinsic": "^1.2.3", + "is-array-buffer": "^3.0.4", + "is-shared-array-buffer": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/ast-types-flow": { + "version": "0.0.8", + "resolved": "https://registry.npmjs.org/ast-types-flow/-/ast-types-flow-0.0.8.tgz", + "integrity": "sha512-OH/2E5Fg20h2aPrbe+QL8JZQFko0YZaF+j4mnQ7BGhfavO7OpSLa8a0y9sBwomHdSbkhTS8TQNayBfnW5DwbvQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/available-typed-arrays": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/available-typed-arrays/-/available-typed-arrays-1.0.7.tgz", + "integrity": "sha512-wvUjBtSGN7+7SjNpq/9M2Tg350UZD3q62IFZLbRAR1bSMlCo1ZaeW+BJ+D090e4hIIZLBcTDWe4Mh4jvUDajzQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "possible-typed-array-names": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/axe-core": { + "version": "4.10.1", + "resolved": "https://registry.npmjs.org/axe-core/-/axe-core-4.10.1.tgz", + "integrity": "sha512-qPC9o+kD8Tir0lzNGLeghbOrWMr3ZJpaRlCIb6Uobt/7N4FiEDvqUMnxzCHRHmg8vOg14kr5gVNyScRmbMaJ9g==", + "dev": true, + "license": "MPL-2.0", + "engines": { + "node": ">=4" + } + }, + "node_modules/axobject-query": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/axobject-query/-/axobject-query-4.1.0.tgz", + "integrity": "sha512-qIj0G9wZbMGNLjLmg1PT6v2mE9AH2zlnADJD/2tC6E00hgmhUOfEB6greHPAfLRSufHqROIUTkw6E+M3lH0PTQ==", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": ">= 0.4" + } + }, + "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, + "license": "MIT" + }, + "node_modules/binary-extensions": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.3.0.tgz", + "integrity": "sha512-Ceh+7ox5qe7LJuLHoY0feh3pHuUDHAcRUeyL2VYghZwfpkNIy/+8Ocg0a3UuSoYzavmylwuLWQOf3hl0jjMMIw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "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, + "license": "MIT", + "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, + "license": "MIT", + "dependencies": { + "fill-range": "^7.1.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/busboy": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/busboy/-/busboy-1.6.0.tgz", + "integrity": "sha512-8SFQbg/0hQ9xy3UNTB0YEnsNBbWfhf7RtnzpL7TkBiTBRfrQ9Fxcnz7VJsleJpyp6rVLvXiuORqjlHi5q+PYuA==", + "dependencies": { + "streamsearch": "^1.1.0" + }, + "engines": { + "node": ">=10.16.0" + } + }, + "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==", + "dev": true, + "license": "MIT", + "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, + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/camelcase-css": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/camelcase-css/-/camelcase-css-2.0.1.tgz", + "integrity": "sha512-QOSvevhslijgYwRx6Rv7zKdMF8lbRmx+uQGx2+vDc+KI/eBnsy9kit5aj23AgGu3pa4t9AgwbnXWqS+iOY+2aA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 6" + } + }, + "node_modules/caniuse-lite": { + "version": "1.0.30001669", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001669.tgz", + "integrity": "sha512-DlWzFDJqstqtIVx1zeSpIMLjunf5SmwOw0N2Ck/QSQdS8PLS4+9HrLaYei4w8BIAL7IB/UEDu889d8vhCTPA0w==", + "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" + } + ], + "license": "CC-BY-4.0" + }, + "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, + "license": "MIT", + "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/chokidar": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.6.0.tgz", + "integrity": "sha512-7VT13fmjotKpGipCW9JEQAusEPE+Ei8nl6/g4FBAmIm0GOOLMua9NDDo/DWp0ZAxCr3cPq5ZpBqmPAQgDda2Pw==", + "dev": true, + "license": "MIT", + "dependencies": { + "anymatch": "~3.1.2", + "braces": "~3.0.2", + "glob-parent": "~5.1.2", + "is-binary-path": "~2.1.0", + "is-glob": "~4.0.1", + "normalize-path": "~3.0.0", + "readdirp": "~3.6.0" + }, + "engines": { + "node": ">= 8.10.0" + }, + "funding": { + "url": "https://paulmillr.com/funding/" + }, + "optionalDependencies": { + "fsevents": "~2.3.2" + } + }, + "node_modules/chokidar/node_modules/glob-parent": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", + "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", + "dev": true, + "license": "ISC", + "dependencies": { + "is-glob": "^4.0.1" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/client-only": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/client-only/-/client-only-0.0.1.tgz", + "integrity": "sha512-IV3Ou0jSMzZrd3pZ48nLkT9DA7Ag1pnPzaiQhpW7c3RbcqqzvzzVu+L8gfqMp/8IM2MQtSiqaCxrrcfu8I8rMA==", + "license": "MIT" + }, + "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, + "license": "MIT", + "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, + "license": "MIT" + }, + "node_modules/commander": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/commander/-/commander-4.1.1.tgz", + "integrity": "sha512-NOKm8xhkzAjzFx8B2v5OAHT+u5pRQc2UCa2Vq9jYL/31o2wi9mxBA7LIFs3sV5VSC49z6pEhfbMULvShKj26WA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 6" + } + }, + "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, + "license": "MIT" + }, + "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, + "license": "MIT", + "dependencies": { + "path-key": "^3.1.0", + "shebang-command": "^2.0.0", + "which": "^2.0.1" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/cssesc": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/cssesc/-/cssesc-3.0.0.tgz", + "integrity": "sha512-/Tb/JcjK111nNScGob5MNtsntNM1aCNUDipB/TkwZFhyDrrE47SOx/18wF2bbjgc3ZzCSKW1T5nt5EbFoAz/Vg==", + "dev": true, + "license": "MIT", + "bin": { + "cssesc": "bin/cssesc" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/csstype": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/csstype/-/csstype-3.1.3.tgz", + "integrity": "sha512-M1uQkMl8rQK/szD0LNhtqxIPLpimGm8sOBwU7lLnCpSbTyY3yeU1Vc7l4KT5zT4s/yOxHH5O7tIuuLOCnLADRw==", + "dev": true, + "license": "MIT" + }, + "node_modules/damerau-levenshtein": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/damerau-levenshtein/-/damerau-levenshtein-1.0.8.tgz", + "integrity": "sha512-sdQSFB7+llfUcQHUQO3+B8ERRj0Oa4w9POWMI/puGtuf7gFywGmkaLCElnudfTiKZV+NvHqL0ifzdrI8Ro7ESA==", + "dev": true, + "license": "BSD-2-Clause" + }, + "node_modules/data-view-buffer": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/data-view-buffer/-/data-view-buffer-1.0.1.tgz", + "integrity": "sha512-0lht7OugA5x3iJLOWFhWK/5ehONdprk0ISXqVFn/NFrDu+cuc8iADFrGQz5BnRK7LLU3JmkbXSxaqX+/mXYtUA==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.6", + "es-errors": "^1.3.0", + "is-data-view": "^1.0.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/data-view-byte-length": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/data-view-byte-length/-/data-view-byte-length-1.0.1.tgz", + "integrity": "sha512-4J7wRJD3ABAzr8wP+OcIcqq2dlUKp4DVflx++hs5h5ZKydWMI6/D/fAot+yh6g2tHh8fLFTvNOaVN357NvSrOQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.7", + "es-errors": "^1.3.0", + "is-data-view": "^1.0.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/data-view-byte-offset": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/data-view-byte-offset/-/data-view-byte-offset-1.0.0.tgz", + "integrity": "sha512-t/Ygsytq+R995EJ5PZlD4Cu56sWa8InXySaViRzw9apusqsOO2bQP+SbYzAhR0pFKoB+43lYy8rWban9JSuXnA==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.6", + "es-errors": "^1.3.0", + "is-data-view": "^1.0.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/debug": { + "version": "4.3.7", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.7.tgz", + "integrity": "sha512-Er2nc/H7RrMXZBFCEim6TCmMk02Z8vLC2Rbi1KEBggpo0fS6l0S1nnapwmIi3yW/+GOJap1Krg4w0Hg80oCqgQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "ms": "^2.1.3" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/deep-equal": { + "version": "2.2.3", + "resolved": "https://registry.npmjs.org/deep-equal/-/deep-equal-2.2.3.tgz", + "integrity": "sha512-ZIwpnevOurS8bpT4192sqAowWM76JDKSHYzMLty3BZGSswgq6pBaH3DhCSW5xVAZICZyKdOBPjwww5wfgT/6PA==", + "dev": true, + "license": "MIT", + "dependencies": { + "array-buffer-byte-length": "^1.0.0", + "call-bind": "^1.0.5", + "es-get-iterator": "^1.1.3", + "get-intrinsic": "^1.2.2", + "is-arguments": "^1.1.1", + "is-array-buffer": "^3.0.2", + "is-date-object": "^1.0.5", + "is-regex": "^1.1.4", + "is-shared-array-buffer": "^1.0.2", + "isarray": "^2.0.5", + "object-is": "^1.1.5", + "object-keys": "^1.1.1", + "object.assign": "^4.1.4", + "regexp.prototype.flags": "^1.5.1", + "side-channel": "^1.0.4", + "which-boxed-primitive": "^1.0.2", + "which-collection": "^1.0.1", + "which-typed-array": "^1.1.13" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "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, + "license": "MIT" + }, + "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==", + "dev": true, + "license": "MIT", + "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, + "license": "MIT", + "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/didyoumean": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/didyoumean/-/didyoumean-1.2.2.tgz", + "integrity": "sha512-gxtyfqMg7GKyhQmb056K7M3xszy/myH8w+B4RT+QXBQsvAOdc3XymqDDPHx1BgPgsdAA5SIifona89YtRATDzw==", + "dev": true, + "license": "Apache-2.0" + }, + "node_modules/dlv": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/dlv/-/dlv-1.1.3.tgz", + "integrity": "sha512-+HlytyjlPKnIG8XuRG8WvmBP8xs8P71y+SKKS6ZXWoEgLuePxtDoUEiH7WkdePWrQ5JBpE6aoVqfZfJUQkjXwA==", + "dev": true, + "license": "MIT" + }, + "node_modules/doctrine": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-3.0.0.tgz", + "integrity": "sha512-yS+Q5i3hBf7GBkd4KG8a7eBNNWNGLTaEwwYWUijIYM7zrlYDM0BFXHjjPWlWZ1Rg7UaddZeIDmi9jF3HmqiQ2w==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "esutils": "^2.0.2" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/eastasianwidth": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/eastasianwidth/-/eastasianwidth-0.2.0.tgz", + "integrity": "sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA==", + "dev": true, + "license": "MIT" + }, + "node_modules/emoji-regex": { + "version": "9.2.2", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-9.2.2.tgz", + "integrity": "sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==", + "dev": true, + "license": "MIT" + }, + "node_modules/enhanced-resolve": { + "version": "5.17.1", + "resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-5.17.1.tgz", + "integrity": "sha512-LMHl3dXhTcfv8gM4kEzIUeTQ+7fpdA0l2tUf34BddXPkz2A5xJ5L/Pchd5BL6rdccM9QGvu0sWZzK1Z1t4wwyg==", + "dev": true, + "license": "MIT", + "dependencies": { + "graceful-fs": "^4.2.4", + "tapable": "^2.2.0" + }, + "engines": { + "node": ">=10.13.0" + } + }, + "node_modules/es-abstract": { + "version": "1.23.3", + "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.23.3.tgz", + "integrity": "sha512-e+HfNH61Bj1X9/jLc5v1owaLYuHdeHHSQlkhCBiTK8rBvKaULl/beGMxwrMXjpYrv4pz22BlY570vVePA2ho4A==", + "dev": true, + "license": "MIT", + "dependencies": { + "array-buffer-byte-length": "^1.0.1", + "arraybuffer.prototype.slice": "^1.0.3", + "available-typed-arrays": "^1.0.7", + "call-bind": "^1.0.7", + "data-view-buffer": "^1.0.1", + "data-view-byte-length": "^1.0.1", + "data-view-byte-offset": "^1.0.0", + "es-define-property": "^1.0.0", + "es-errors": "^1.3.0", + "es-object-atoms": "^1.0.0", + "es-set-tostringtag": "^2.0.3", + "es-to-primitive": "^1.2.1", + "function.prototype.name": "^1.1.6", + "get-intrinsic": "^1.2.4", + "get-symbol-description": "^1.0.2", + "globalthis": "^1.0.3", + "gopd": "^1.0.1", + "has-property-descriptors": "^1.0.2", + "has-proto": "^1.0.3", + "has-symbols": "^1.0.3", + "hasown": "^2.0.2", + "internal-slot": "^1.0.7", + "is-array-buffer": "^3.0.4", + "is-callable": "^1.2.7", + "is-data-view": "^1.0.1", + "is-negative-zero": "^2.0.3", + "is-regex": "^1.1.4", + "is-shared-array-buffer": "^1.0.3", + "is-string": "^1.0.7", + "is-typed-array": "^1.1.13", + "is-weakref": "^1.0.2", + "object-inspect": "^1.13.1", + "object-keys": "^1.1.1", + "object.assign": "^4.1.5", + "regexp.prototype.flags": "^1.5.2", + "safe-array-concat": "^1.1.2", + "safe-regex-test": "^1.0.3", + "string.prototype.trim": "^1.2.9", + "string.prototype.trimend": "^1.0.8", + "string.prototype.trimstart": "^1.0.8", + "typed-array-buffer": "^1.0.2", + "typed-array-byte-length": "^1.0.1", + "typed-array-byte-offset": "^1.0.2", + "typed-array-length": "^1.0.6", + "unbox-primitive": "^1.0.2", + "which-typed-array": "^1.1.15" + }, + "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==", + "dev": true, + "license": "MIT", + "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==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/es-get-iterator": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/es-get-iterator/-/es-get-iterator-1.1.3.tgz", + "integrity": "sha512-sPZmqHBe6JIiTfN5q2pEi//TwxmAFHwj/XEuYjTuse78i8KxaqMTTzxPoFKuzRpDpTJ+0NAbpfenkmH2rePtuw==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.2", + "get-intrinsic": "^1.1.3", + "has-symbols": "^1.0.3", + "is-arguments": "^1.1.1", + "is-map": "^2.0.2", + "is-set": "^2.0.2", + "is-string": "^1.0.7", + "isarray": "^2.0.5", + "stop-iteration-iterator": "^1.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/es-iterator-helpers": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/es-iterator-helpers/-/es-iterator-helpers-1.1.0.tgz", + "integrity": "sha512-/SurEfycdyssORP/E+bj4sEu1CWw4EmLDsHynHwSXQ7utgbrMRWW195pTrCjFgFCddf/UkYm3oqKPRq5i8bJbw==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.7", + "define-properties": "^1.2.1", + "es-abstract": "^1.23.3", + "es-errors": "^1.3.0", + "es-set-tostringtag": "^2.0.3", + "function-bind": "^1.1.2", + "get-intrinsic": "^1.2.4", + "globalthis": "^1.0.4", + "has-property-descriptors": "^1.0.2", + "has-proto": "^1.0.3", + "has-symbols": "^1.0.3", + "internal-slot": "^1.0.7", + "iterator.prototype": "^1.1.3", + "safe-array-concat": "^1.1.2" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/es-object-atoms": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/es-object-atoms/-/es-object-atoms-1.0.0.tgz", + "integrity": "sha512-MZ4iQ6JwHOBQjahnjwaC1ZtIBH+2ohjamzAO3oaHcXYup7qxjF2fixyH+Q71voWHeOkI2q/TnJao/KfXYIZWbw==", + "dev": true, + "license": "MIT", + "dependencies": { + "es-errors": "^1.3.0" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/es-set-tostringtag": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/es-set-tostringtag/-/es-set-tostringtag-2.0.3.tgz", + "integrity": "sha512-3T8uNMC3OQTHkFUsFq8r/BwAXLHvU/9O9mE0fBc/MY5iq/8H7ncvO947LmYA6ldWw9Uh8Yhf25zu6n7nML5QWQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "get-intrinsic": "^1.2.4", + "has-tostringtag": "^1.0.2", + "hasown": "^2.0.1" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/es-shim-unscopables": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/es-shim-unscopables/-/es-shim-unscopables-1.0.2.tgz", + "integrity": "sha512-J3yBRXCzDu4ULnQwxyToo/OjdMx6akgVC7K6few0a7F/0wLtmKKN7I73AH5T2836UuXRqN7Qg+IIUw/+YJksRw==", + "dev": true, + "license": "MIT", + "dependencies": { + "hasown": "^2.0.0" + } + }, + "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, + "license": "MIT", + "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/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, + "license": "MIT", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/eslint": { + "version": "8.57.1", + "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.57.1.tgz", + "integrity": "sha512-ypowyDxpVSYpkXr9WPv2PAZCtNip1Mv5KTW0SCurXv/9iOpcrH9PaqUElksqEB6pChqHGDRCFTyrZlGhnLNGiA==", + "deprecated": "This version is no longer supported. Please see https://eslint.org/version-support for other options.", + "dev": true, + "license": "MIT", + "dependencies": { + "@eslint-community/eslint-utils": "^4.2.0", + "@eslint-community/regexpp": "^4.6.1", + "@eslint/eslintrc": "^2.1.4", + "@eslint/js": "8.57.1", + "@humanwhocodes/config-array": "^0.13.0", + "@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-next": { + "version": "14.2.15", + "resolved": "https://registry.npmjs.org/eslint-config-next/-/eslint-config-next-14.2.15.tgz", + "integrity": "sha512-mKg+NC/8a4JKLZRIOBplxXNdStgxy7lzWuedUaCc8tev+Al9mwDUTujQH6W6qXDH9kycWiVo28tADWGvpBsZcQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@next/eslint-plugin-next": "14.2.15", + "@rushstack/eslint-patch": "^1.3.3", + "@typescript-eslint/eslint-plugin": "^5.4.2 || ^6.0.0 || ^7.0.0 || ^8.0.0", + "@typescript-eslint/parser": "^5.4.2 || ^6.0.0 || ^7.0.0 || ^8.0.0", + "eslint-import-resolver-node": "^0.3.6", + "eslint-import-resolver-typescript": "^3.5.2", + "eslint-plugin-import": "^2.28.1", + "eslint-plugin-jsx-a11y": "^6.7.1", + "eslint-plugin-react": "^7.33.2", + "eslint-plugin-react-hooks": "^4.5.0 || 5.0.0-canary-7118f5dd7-20230705" + }, + "peerDependencies": { + "eslint": "^7.23.0 || ^8.0.0", + "typescript": ">=3.3.1" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, + "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, + "license": "MIT", + "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, + "license": "MIT", + "dependencies": { + "ms": "^2.1.1" + } + }, + "node_modules/eslint-import-resolver-typescript": { + "version": "3.6.3", + "resolved": "https://registry.npmjs.org/eslint-import-resolver-typescript/-/eslint-import-resolver-typescript-3.6.3.tgz", + "integrity": "sha512-ud9aw4szY9cCT1EWWdGv1L1XR6hh2PaRWif0j2QjQ0pgTY/69iw+W0Z4qZv5wHahOl8isEr+k/JnyAqNQkLkIA==", + "dev": true, + "license": "ISC", + "dependencies": { + "@nolyfill/is-core-module": "1.0.39", + "debug": "^4.3.5", + "enhanced-resolve": "^5.15.0", + "eslint-module-utils": "^2.8.1", + "fast-glob": "^3.3.2", + "get-tsconfig": "^4.7.5", + "is-bun-module": "^1.0.2", + "is-glob": "^4.0.3" + }, + "engines": { + "node": "^14.18.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/unts/projects/eslint-import-resolver-ts" + }, + "peerDependencies": { + "eslint": "*", + "eslint-plugin-import": "*", + "eslint-plugin-import-x": "*" + }, + "peerDependenciesMeta": { + "eslint-plugin-import": { + "optional": true + }, + "eslint-plugin-import-x": { + "optional": true + } + } + }, + "node_modules/eslint-module-utils": { + "version": "2.12.0", + "resolved": "https://registry.npmjs.org/eslint-module-utils/-/eslint-module-utils-2.12.0.tgz", + "integrity": "sha512-wALZ0HFoytlyh/1+4wuZ9FJCD/leWHQzzrxJ8+rebyReSLk7LApMyd3WJaLVoN+D5+WIdJyDK1c6JnE65V4Zyg==", + "dev": true, + "license": "MIT", + "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, + "license": "MIT", + "dependencies": { + "ms": "^2.1.1" + } + }, + "node_modules/eslint-plugin-import": { + "version": "2.31.0", + "resolved": "https://registry.npmjs.org/eslint-plugin-import/-/eslint-plugin-import-2.31.0.tgz", + "integrity": "sha512-ixmkI62Rbc2/w8Vfxyh1jQRTdRTF52VxwRVHl/ykPAmqG+Nb7/kNn+byLP0LxPgI7zWA16Jt82SybJInmMia3A==", + "dev": true, + "license": "MIT", + "dependencies": { + "@rtsao/scc": "^1.1.0", + "array-includes": "^3.1.8", + "array.prototype.findlastindex": "^1.2.5", + "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.12.0", + "hasown": "^2.0.2", + "is-core-module": "^2.15.1", + "is-glob": "^4.0.3", + "minimatch": "^3.1.2", + "object.fromentries": "^2.0.8", + "object.groupby": "^1.0.3", + "object.values": "^1.2.0", + "semver": "^6.3.1", + "string.prototype.trimend": "^1.0.8", + "tsconfig-paths": "^3.15.0" + }, + "engines": { + "node": ">=4" + }, + "peerDependencies": { + "eslint": "^2 || ^3 || ^4 || ^5 || ^6 || ^7.2.0 || ^8 || ^9" + } + }, + "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, + "license": "MIT", + "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, + "license": "Apache-2.0", + "dependencies": { + "esutils": "^2.0.2" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/eslint-plugin-import/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, + "license": "ISC", + "bin": { + "semver": "bin/semver.js" + } + }, + "node_modules/eslint-plugin-jsx-a11y": { + "version": "6.10.0", + "resolved": "https://registry.npmjs.org/eslint-plugin-jsx-a11y/-/eslint-plugin-jsx-a11y-6.10.0.tgz", + "integrity": "sha512-ySOHvXX8eSN6zz8Bywacm7CvGNhUtdjvqfQDVe6020TUK34Cywkw7m0KsCCk1Qtm9G1FayfTN1/7mMYnYO2Bhg==", + "dev": true, + "license": "MIT", + "dependencies": { + "aria-query": "~5.1.3", + "array-includes": "^3.1.8", + "array.prototype.flatmap": "^1.3.2", + "ast-types-flow": "^0.0.8", + "axe-core": "^4.10.0", + "axobject-query": "^4.1.0", + "damerau-levenshtein": "^1.0.8", + "emoji-regex": "^9.2.2", + "es-iterator-helpers": "^1.0.19", + "hasown": "^2.0.2", + "jsx-ast-utils": "^3.3.5", + "language-tags": "^1.0.9", + "minimatch": "^3.1.2", + "object.fromentries": "^2.0.8", + "safe-regex-test": "^1.0.3", + "string.prototype.includes": "^2.0.0" + }, + "engines": { + "node": ">=4.0" + }, + "peerDependencies": { + "eslint": "^3 || ^4 || ^5 || ^6 || ^7 || ^8 || ^9" + } + }, + "node_modules/eslint-plugin-react": { + "version": "7.37.1", + "resolved": "https://registry.npmjs.org/eslint-plugin-react/-/eslint-plugin-react-7.37.1.tgz", + "integrity": "sha512-xwTnwDqzbDRA8uJ7BMxPs/EXRB3i8ZfnOIp8BsxEQkT0nHPp+WWceqGgo6rKb9ctNi8GJLDT4Go5HAWELa/WMg==", + "dev": true, + "license": "MIT", + "dependencies": { + "array-includes": "^3.1.8", + "array.prototype.findlast": "^1.2.5", + "array.prototype.flatmap": "^1.3.2", + "array.prototype.tosorted": "^1.1.4", + "doctrine": "^2.1.0", + "es-iterator-helpers": "^1.0.19", + "estraverse": "^5.3.0", + "hasown": "^2.0.2", + "jsx-ast-utils": "^2.4.1 || ^3.0.0", + "minimatch": "^3.1.2", + "object.entries": "^1.1.8", + "object.fromentries": "^2.0.8", + "object.values": "^1.2.0", + "prop-types": "^15.8.1", + "resolve": "^2.0.0-next.5", + "semver": "^6.3.1", + "string.prototype.matchall": "^4.0.11", + "string.prototype.repeat": "^1.0.0" + }, + "engines": { + "node": ">=4" + }, + "peerDependencies": { + "eslint": "^3 || ^4 || ^5 || ^6 || ^7 || ^8 || ^9.7" + } + }, + "node_modules/eslint-plugin-react-hooks": { + "version": "5.0.0-canary-7118f5dd7-20230705", + "resolved": "https://registry.npmjs.org/eslint-plugin-react-hooks/-/eslint-plugin-react-hooks-5.0.0-canary-7118f5dd7-20230705.tgz", + "integrity": "sha512-AZYbMo/NW9chdL7vk6HQzQhT+PvTAEVqWk9ziruUoW2kAOcN5qNyelv70e0F1VNQAbvutOC9oc+xfWycI9FxDw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=10" + }, + "peerDependencies": { + "eslint": "^3.0.0 || ^4.0.0 || ^5.0.0 || ^6.0.0 || ^7.0.0 || ^8.0.0-0" + } + }, + "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, + "license": "Apache-2.0", + "dependencies": { + "esutils": "^2.0.2" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/eslint-plugin-react/node_modules/resolve": { + "version": "2.0.0-next.5", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-2.0.0-next.5.tgz", + "integrity": "sha512-U7WjGVG9sH8tvjW5SmGbQuui75FiyjAX72HX15DwBBwF9dNiQZRQAg9nnPhYy+TUnE0+VcrttuvNI8oSxZcocA==", + "dev": true, + "license": "MIT", + "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/eslint-plugin-react/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, + "license": "ISC", + "bin": { + "semver": "bin/semver.js" + } + }, + "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, + "license": "BSD-2-Clause", + "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-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, + "license": "Apache-2.0", + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "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, + "license": "BSD-2-Clause", + "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/esquery": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.6.0.tgz", + "integrity": "sha512-ca9pw9fomFcKPvFLXhBKUK90ZvGibiGOvRJNbjljY7s7uq/5YO4BOzcYtJqExdx99rF6aAcnRxHmcUHcz6sQsg==", + "dev": true, + "license": "BSD-3-Clause", + "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, + "license": "BSD-2-Clause", + "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, + "license": "BSD-2-Clause", + "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, + "license": "BSD-2-Clause", + "engines": { + "node": ">=0.10.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, + "license": "MIT" + }, + "node_modules/fast-glob": { + "version": "3.3.2", + "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.3.2.tgz", + "integrity": "sha512-oX2ruAFQwf/Orj8m737Y5adxDQO0LAB7/S5MnxCdTNDd4p6BsyIVsv9JQsATbTSq8KHRpLwIHbVlUNatxd+1Ow==", + "dev": true, + "license": "MIT", + "dependencies": { + "@nodelib/fs.stat": "^2.0.2", + "@nodelib/fs.walk": "^1.2.3", + "glob-parent": "^5.1.2", + "merge2": "^1.3.0", + "micromatch": "^4.0.4" + }, + "engines": { + "node": ">=8.6.0" + } + }, + "node_modules/fast-glob/node_modules/glob-parent": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", + "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", + "dev": true, + "license": "ISC", + "dependencies": { + "is-glob": "^4.0.1" + }, + "engines": { + "node": ">= 6" + } + }, + "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, + "license": "MIT" + }, + "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, + "license": "MIT" + }, + "node_modules/fastq": { + "version": "1.17.1", + "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.17.1.tgz", + "integrity": "sha512-sRVD3lWVIXWg6By68ZN7vho9a1pQcN/WBFaAAsDDFzlJjvoGx0P8z7V1t72grFJfJhu3YPZBuu25f7Kaw2jN1w==", + "dev": true, + "license": "ISC", + "dependencies": { + "reusify": "^1.0.4" + } + }, + "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, + "license": "MIT", + "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, + "license": "MIT", + "dependencies": { + "to-regex-range": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "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, + "license": "MIT", + "dependencies": { + "locate-path": "^6.0.0", + "path-exists": "^4.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/flat-cache": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-3.2.0.tgz", + "integrity": "sha512-CYcENa+FtcUKLmhhqyctpclsq7QF38pKjZHsGNiSQF5r4FtoKDWabFDl3hzaEQMvT1LHEysw5twgLvpYYb4vbw==", + "dev": true, + "license": "MIT", + "dependencies": { + "flatted": "^3.2.9", + "keyv": "^4.5.3", + "rimraf": "^3.0.2" + }, + "engines": { + "node": "^10.12.0 || >=12.0.0" + } + }, + "node_modules/flatted": { + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.3.1.tgz", + "integrity": "sha512-X8cqMLLie7KsNUDSdzeN8FYK9rEt4Dt67OsG/DNGnYTSDBG4uFAJFBnUeiV+zCVAvwFy56IjM9sH51jVaEhNxw==", + "dev": true, + "license": "ISC" + }, + "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, + "license": "MIT", + "dependencies": { + "is-callable": "^1.1.3" + } + }, + "node_modules/foreground-child": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/foreground-child/-/foreground-child-3.3.0.tgz", + "integrity": "sha512-Ld2g8rrAyMYFXBhEqMz8ZAHBi4J4uS1i/CxGMDnjyFWddMXLVcDp051DZfu+t7+ab7Wv6SMqpWmyFIj5UbfFvg==", + "dev": true, + "license": "ISC", + "dependencies": { + "cross-spawn": "^7.0.0", + "signal-exit": "^4.0.1" + }, + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "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, + "license": "ISC" + }, + "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, + "license": "MIT", + "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==", + "dev": true, + "license": "MIT", + "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, + "license": "MIT", + "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, + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "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==", + "dev": true, + "license": "MIT", + "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-symbol-description": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/get-symbol-description/-/get-symbol-description-1.0.2.tgz", + "integrity": "sha512-g0QYk1dZBxGwk+Ngc+ltRH2IBp2f7zBkBMBJZCDerh6EhlhSR6+9irMCuT/09zD6qkarHUSn529sK/yL4S27mg==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.5", + "es-errors": "^1.3.0", + "get-intrinsic": "^1.2.4" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/get-tsconfig": { + "version": "4.8.1", + "resolved": "https://registry.npmjs.org/get-tsconfig/-/get-tsconfig-4.8.1.tgz", + "integrity": "sha512-k9PN+cFBmaLWtVz29SkUoqU5O0slLuHJXt/2P+tMVFT+phsSGXGkp9t3rQIqdz0e+06EHNGs3oM6ZX1s2zHxRg==", + "dev": true, + "license": "MIT", + "dependencies": { + "resolve-pkg-maps": "^1.0.0" + }, + "funding": { + "url": "https://github.com/privatenumber/get-tsconfig?sponsor=1" + } + }, + "node_modules/glob": { + "version": "10.3.10", + "resolved": "https://registry.npmjs.org/glob/-/glob-10.3.10.tgz", + "integrity": "sha512-fa46+tv1Ak0UPK1TOy/pZrIybNNt4HCv7SDzwyfiOZkvZLEbjsZkJBPtDHVshZjbecAoAGSC20MjLDG/qr679g==", + "dev": true, + "license": "ISC", + "dependencies": { + "foreground-child": "^3.1.0", + "jackspeak": "^2.3.5", + "minimatch": "^9.0.1", + "minipass": "^5.0.0 || ^6.0.2 || ^7.0.0", + "path-scurry": "^1.10.1" + }, + "bin": { + "glob": "dist/esm/bin.mjs" + }, + "engines": { + "node": ">=16 || 14 >=14.17" + }, + "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, + "license": "ISC", + "dependencies": { + "is-glob": "^4.0.3" + }, + "engines": { + "node": ">=10.13.0" + } + }, + "node_modules/glob/node_modules/brace-expansion": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", + "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", + "dev": true, + "license": "MIT", + "dependencies": { + "balanced-match": "^1.0.0" + } + }, + "node_modules/glob/node_modules/minimatch": { + "version": "9.0.5", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.5.tgz", + "integrity": "sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow==", + "dev": true, + "license": "ISC", + "dependencies": { + "brace-expansion": "^2.0.1" + }, + "engines": { + "node": ">=16 || 14 >=14.17" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/globals": { + "version": "13.24.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-13.24.0.tgz", + "integrity": "sha512-AhO5QUcj8llrbG09iWhPU2B204J1xnPeL8kQmVorSsy+Sjj1sk8gIyh6cUocGmH4L0UuhAJy+hJMRA4mgA4mFQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "type-fest": "^0.20.2" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/globalthis": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/globalthis/-/globalthis-1.0.4.tgz", + "integrity": "sha512-DpLKbNU4WylpxJykQujfCcwYWiV/Jhm50Goo0wrVILAv5jOr9d+H+UR3PhSCD2rCCEIg0uc+G+muBTwD54JhDQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "define-properties": "^1.2.1", + "gopd": "^1.0.1" + }, + "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==", + "dev": true, + "license": "MIT", + "dependencies": { + "get-intrinsic": "^1.1.3" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/graceful-fs": { + "version": "4.2.11", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.11.tgz", + "integrity": "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==", + "license": "ISC" + }, + "node_modules/graphemer": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/graphemer/-/graphemer-1.4.0.tgz", + "integrity": "sha512-EtKwoO6kxCL9WO5xipiHTZlSzBm7WLT627TqC/uVRd0HKmq8NXyebnNYxDoBi7wt8eTWrUrKXCOVaFq9x1kgag==", + "dev": true, + "license": "MIT" + }, + "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, + "license": "MIT", + "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, + "license": "MIT", + "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==", + "dev": true, + "license": "MIT", + "dependencies": { + "es-define-property": "^1.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/has-proto": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/has-proto/-/has-proto-1.0.3.tgz", + "integrity": "sha512-SJ1amZAJUiZS+PhsVLf5tGydlaVB8EdFpaSO4gmiUKUOxk8qzn5AIy4ZeJUmh22znIdk/uMAUT2pl3FxzVUH+Q==", + "dev": true, + "license": "MIT", + "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==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/has-tostringtag": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/has-tostringtag/-/has-tostringtag-1.0.2.tgz", + "integrity": "sha512-NqADB8VjPFLM2V0VvHUewwwsw0ZWBaIdgo+ieHtK3hasLz4qeCRjYcqfB6AQrBggRKppKF8L52/VqdVsO47Dlw==", + "dev": true, + "license": "MIT", + "dependencies": { + "has-symbols": "^1.0.3" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/hasown": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.2.tgz", + "integrity": "sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "function-bind": "^1.1.2" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/ignore": { + "version": "5.3.2", + "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.3.2.tgz", + "integrity": "sha512-hsBTNUqQTDwkWtcdYI2i06Y/nUBEsNEDJKjWdigLvegy8kDuJAS8uRlpkkcQpyEXL0Z/pjDy5HBmMjRCJ2gq+g==", + "dev": true, + "license": "MIT", + "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, + "license": "MIT", + "dependencies": { + "parent-module": "^1.0.0", + "resolve-from": "^4.0.0" + }, + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/imurmurhash": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz", + "integrity": "sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==", + "dev": true, + "license": "MIT", + "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==", + "deprecated": "This module is not supported, and leaks memory. Do not use it. Check out lru-cache if you want a good and tested way to coalesce async requests by a key value, which is much more comprehensive and powerful.", + "dev": true, + "license": "ISC", + "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, + "license": "ISC" + }, + "node_modules/internal-slot": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/internal-slot/-/internal-slot-1.0.7.tgz", + "integrity": "sha512-NGnrKwXzSms2qUUih/ILZ5JBqNTSa1+ZmP6flaIp6KmSElgE9qdndzS3cqjrDovwFdmwsGsLdeFgB6suw+1e9g==", + "dev": true, + "license": "MIT", + "dependencies": { + "es-errors": "^1.3.0", + "hasown": "^2.0.0", + "side-channel": "^1.0.4" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/is-arguments": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/is-arguments/-/is-arguments-1.1.1.tgz", + "integrity": "sha512-8Q7EARjzEnKpt/PCD7e1cgUS0a6X8u5tdSiMqXhojOdoV9TsMsiO+9VLC5vAmO8N7/GmXn7yjR8qnA6bVAEzfA==", + "dev": true, + "license": "MIT", + "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-array-buffer": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/is-array-buffer/-/is-array-buffer-3.0.4.tgz", + "integrity": "sha512-wcjaerHw0ydZwfhiKbXJWLDY8A7yV7KhjQOpb83hGgGfId/aQa4TOvwyzn2PuswW2gPCYEL/nEAiSVpdOj1lXw==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.2", + "get-intrinsic": "^1.2.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "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, + "license": "MIT", + "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, + "license": "MIT", + "dependencies": { + "has-bigints": "^1.0.1" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-binary-path": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz", + "integrity": "sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==", + "dev": true, + "license": "MIT", + "dependencies": { + "binary-extensions": "^2.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/is-boolean-object": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/is-boolean-object/-/is-boolean-object-1.1.2.tgz", + "integrity": "sha512-gDYaKHJmnj4aWxyj6YHyXVpdQawtVLHU5cb+eztPGczf6cjuTdwve5ZIEfgXqH4e57An1D1AKf8CZ3kYrQRqYA==", + "dev": true, + "license": "MIT", + "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-bun-module": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/is-bun-module/-/is-bun-module-1.2.1.tgz", + "integrity": "sha512-AmidtEM6D6NmUiLOvvU7+IePxjEjOzra2h0pSrsfSAcXwl/83zLLXDByafUJy9k/rKK0pvXMLdwKwGHlX2Ke6Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "semver": "^7.6.3" + } + }, + "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, + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-core-module": { + "version": "2.15.1", + "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.15.1.tgz", + "integrity": "sha512-z0vtXSwucUJtANQWldhbtbt7BnL0vxiFjIdDLAatwhDYty2bad6s+rijD6Ri4YuYJubLzIJLUidCh09e1djEVQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "hasown": "^2.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-data-view": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-data-view/-/is-data-view-1.0.1.tgz", + "integrity": "sha512-AHkaJrsUVW6wq6JS8y3JnM/GJF/9cf+k20+iDzlSaJrinEo5+7vRiteOSwBhHRiAyQATN1AmY4hwzxJKPmYf+w==", + "dev": true, + "license": "MIT", + "dependencies": { + "is-typed-array": "^1.1.13" + }, + "engines": { + "node": ">= 0.4" + }, + "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, + "license": "MIT", + "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, + "license": "MIT", + "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, + "license": "MIT", + "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, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/is-generator-function": { + "version": "1.0.10", + "resolved": "https://registry.npmjs.org/is-generator-function/-/is-generator-function-1.0.10.tgz", + "integrity": "sha512-jsEjy9l3yiXEQ+PsXdmBwEPcOxaXWLspKdplFUVI9vq1iZgIekeC0L167qeu86czQaxed3q/Uzuw0swL0irL8A==", + "dev": true, + "license": "MIT", + "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, + "license": "MIT", + "dependencies": { + "is-extglob": "^2.1.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-map": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/is-map/-/is-map-2.0.3.tgz", + "integrity": "sha512-1Qed0/Hr2m+YqxnM09CjA2d/i6YZNfF6R2oRAOj36eUdS6qIV/huPJNSEpKbupewFs+ZsJlxsjjPbc0/afW6Lw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-negative-zero": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/is-negative-zero/-/is-negative-zero-2.0.3.tgz", + "integrity": "sha512-5KoIu2Ngpyek75jXodFvnafB6DJgr3u8uuK0LEZJjrU19DrMD3EVERaR8sjz8CCGgpZvxPl9SuE1GMVPFHx1mw==", + "dev": true, + "license": "MIT", + "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, + "license": "MIT", + "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, + "license": "MIT", + "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, + "license": "MIT", + "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, + "license": "MIT", + "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.3", + "resolved": "https://registry.npmjs.org/is-set/-/is-set-2.0.3.tgz", + "integrity": "sha512-iPAjerrse27/ygGLxw+EBR9agv9Y6uLeYVJMu+QNCoouJ1/1ri0mGrcWpfCqFZuzzx3WjtwxG098X+n4OuRkPg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-shared-array-buffer": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/is-shared-array-buffer/-/is-shared-array-buffer-1.0.3.tgz", + "integrity": "sha512-nA2hv5XIhLR3uVzDDfCIknerhx8XUKnstuOERPNNIinXG7v9u+ohXF67vxm4TPTEPU6lm61ZkwP3c9PCB97rhg==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.7" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "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, + "license": "MIT", + "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, + "license": "MIT", + "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.13", + "resolved": "https://registry.npmjs.org/is-typed-array/-/is-typed-array-1.1.13.tgz", + "integrity": "sha512-uZ25/bUAlUY5fR4OKT4rZQEBrzQWYV9ZJYGGsUmEJ6thodVJ1HX64ePQ6Z0qPWP+m+Uq6e9UugrE38jeYsDSMw==", + "dev": true, + "license": "MIT", + "dependencies": { + "which-typed-array": "^1.1.14" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-weakmap": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/is-weakmap/-/is-weakmap-2.0.2.tgz", + "integrity": "sha512-K5pXYOm9wqY1RgjpL3YTkF39tni1XajUIkawTLUo9EZEVUFga5gSQJF8nNS7ZwJQ02y+1YCNYcMh+HIf1ZqE+w==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, + "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, + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.2" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-weakset": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/is-weakset/-/is-weakset-2.0.3.tgz", + "integrity": "sha512-LvIm3/KWzS9oRFHugab7d+M/GcBXuXX5xZkzPmN+NxihdQlZUQ4dWuSV1xR/sq6upL1TJEDrfBgRepHFdBtSNQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.7", + "get-intrinsic": "^1.2.4" + }, + "engines": { + "node": ">= 0.4" + }, + "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, + "license": "MIT" + }, + "node_modules/isexe": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", + "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==", + "dev": true, + "license": "ISC" + }, + "node_modules/iterator.prototype": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/iterator.prototype/-/iterator.prototype-1.1.3.tgz", + "integrity": "sha512-FW5iMbeQ6rBGm/oKgzq2aW4KvAGpxPzYES8N4g4xNXUKpL1mclMvOe+76AcLDTvD+Ze+sOpVhgdAQEKF4L9iGQ==", + "dev": true, + "license": "MIT", + "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" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/jackspeak": { + "version": "2.3.6", + "resolved": "https://registry.npmjs.org/jackspeak/-/jackspeak-2.3.6.tgz", + "integrity": "sha512-N3yCS/NegsOBokc8GAdM8UcmfsKiSS8cipheD/nivzr700H+nsMOxJjQnvwOcRYVuFkdH0wGUvW2WbXGmrZGbQ==", + "dev": true, + "license": "BlueOak-1.0.0", + "dependencies": { + "@isaacs/cliui": "^8.0.2" + }, + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + }, + "optionalDependencies": { + "@pkgjs/parseargs": "^0.11.0" + } + }, + "node_modules/jiti": { + "version": "1.21.6", + "resolved": "https://registry.npmjs.org/jiti/-/jiti-1.21.6.tgz", + "integrity": "sha512-2yTgeWTWzMWkHu6Jp9NKgePDaYHbntiwvYuuJLbbN9vl7DC9DvXKOB2BC3ZZ92D3cvV/aflH0osDfwpHepQ53w==", + "dev": true, + "license": "MIT", + "bin": { + "jiti": "bin/jiti.js" + } + }, + "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==", + "license": "MIT" + }, + "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, + "license": "MIT", + "dependencies": { + "argparse": "^2.0.1" + }, + "bin": { + "js-yaml": "bin/js-yaml.js" + } + }, + "node_modules/json-buffer": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/json-buffer/-/json-buffer-3.0.1.tgz", + "integrity": "sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ==", + "dev": true, + "license": "MIT" + }, + "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, + "license": "MIT" + }, + "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, + "license": "MIT" + }, + "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, + "license": "MIT", + "dependencies": { + "minimist": "^1.2.0" + }, + "bin": { + "json5": "lib/cli.js" + } + }, + "node_modules/jsx-ast-utils": { + "version": "3.3.5", + "resolved": "https://registry.npmjs.org/jsx-ast-utils/-/jsx-ast-utils-3.3.5.tgz", + "integrity": "sha512-ZZow9HBI5O6EPgSJLUb8n2NKgmVWTwCvHGwFuJlMjvLFqlGG6pjirPhtdsseaLZjSibD8eegzmYpUZwoIlj2cQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "array-includes": "^3.1.6", + "array.prototype.flat": "^1.3.1", + "object.assign": "^4.1.4", + "object.values": "^1.1.6" + }, + "engines": { + "node": ">=4.0" + } + }, + "node_modules/keyv": { + "version": "4.5.4", + "resolved": "https://registry.npmjs.org/keyv/-/keyv-4.5.4.tgz", + "integrity": "sha512-oxVHkHR/EJf2CNXnWxRLW6mg7JyCCUcG0DtEGmL2ctUo1PNTin1PUil+r/+4r5MpVgC/fn1kjsx7mjSujKqIpw==", + "dev": true, + "license": "MIT", + "dependencies": { + "json-buffer": "3.0.1" + } + }, + "node_modules/language-subtag-registry": { + "version": "0.3.23", + "resolved": "https://registry.npmjs.org/language-subtag-registry/-/language-subtag-registry-0.3.23.tgz", + "integrity": "sha512-0K65Lea881pHotoGEa5gDlMxt3pctLi2RplBb7Ezh4rRdLEOtgi7n4EwK9lamnUCkKBqaeKRVebTq6BAxSkpXQ==", + "dev": true, + "license": "CC0-1.0" + }, + "node_modules/language-tags": { + "version": "1.0.9", + "resolved": "https://registry.npmjs.org/language-tags/-/language-tags-1.0.9.tgz", + "integrity": "sha512-MbjN408fEndfiQXbFQ1vnd+1NoLDsnQW41410oQBXiyXDMYH5z505juWa4KUE1LqxRC7DgOgZDbKLxHIwm27hA==", + "dev": true, + "license": "MIT", + "dependencies": { + "language-subtag-registry": "^0.3.20" + }, + "engines": { + "node": ">=0.10" + } + }, + "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, + "license": "MIT", + "dependencies": { + "prelude-ls": "^1.2.1", + "type-check": "~0.4.0" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/lilconfig": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/lilconfig/-/lilconfig-2.1.0.tgz", + "integrity": "sha512-utWOt/GHzuUxnLKxB6dk81RoOeoNeHgbrXiuGk4yyF5qlRz+iIVWu56E2fqGHFrXz0QNUhLB/8nKqvRH66JKGQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=10" + } + }, + "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, + "license": "MIT" + }, + "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, + "license": "MIT", + "dependencies": { + "p-locate": "^5.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "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, + "license": "MIT" + }, + "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==", + "license": "MIT", + "dependencies": { + "js-tokens": "^3.0.0 || ^4.0.0" + }, + "bin": { + "loose-envify": "cli.js" + } + }, + "node_modules/lru-cache": { + "version": "10.4.3", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-10.4.3.tgz", + "integrity": "sha512-JNAzZcXrCt42VGLuYz0zfAzDfAvJWW6AfYlDBQyDV5DClI2m5sAmK+OIO7s59XfsRsWHp02jAJrRadPRGTt6SQ==", + "dev": true, + "license": "ISC" + }, + "node_modules/merge2": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/merge2/-/merge2-1.4.1.tgz", + "integrity": "sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 8" + } + }, + "node_modules/micromatch": { + "version": "4.0.8", + "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.8.tgz", + "integrity": "sha512-PXwfBhYu0hBCPw8Dn0E+WDYb7af3dSLVWKi3HGv84IdF4TyFoC0ysxFd0Goxw7nSv4T/PzEJQxsYsEiFCKo2BA==", + "dev": true, + "license": "MIT", + "dependencies": { + "braces": "^3.0.3", + "picomatch": "^2.3.1" + }, + "engines": { + "node": ">=8.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, + "license": "ISC", + "dependencies": { + "brace-expansion": "^1.1.7" + }, + "engines": { + "node": "*" + } + }, + "node_modules/minimist": { + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.8.tgz", + "integrity": "sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==", + "dev": true, + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/minipass": { + "version": "7.1.2", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-7.1.2.tgz", + "integrity": "sha512-qOOzS1cBTWYF4BH8fVePDBOO9iptMnGUEZwNc/cMWnTV2nVLZ7VoNWEPHkYczZA0pdoA7dl6e7FL659nX9S2aw==", + "dev": true, + "license": "ISC", + "engines": { + "node": ">=16 || 14 >=14.17" + } + }, + "node_modules/ms": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", + "dev": true, + "license": "MIT" + }, + "node_modules/mz": { + "version": "2.7.0", + "resolved": "https://registry.npmjs.org/mz/-/mz-2.7.0.tgz", + "integrity": "sha512-z81GNO7nnYMEhrGh9LeymoE4+Yr0Wn5McHIZMK5cfQCl+NDX08sCZgUc9/6MHni9IWuFLm1Z3HTCXu2z9fN62Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "any-promise": "^1.0.0", + "object-assign": "^4.0.1", + "thenify-all": "^1.0.0" + } + }, + "node_modules/nanoid": { + "version": "3.3.7", + "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.7.tgz", + "integrity": "sha512-eSRppjcPIatRIMC1U6UngP8XFcz8MQWGQdt1MTBQ7NaAmvXDfvNxbvWV3x2y6CdEUciCSsDHDQZbhYaB8QEo2g==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "license": "MIT", + "bin": { + "nanoid": "bin/nanoid.cjs" + }, + "engines": { + "node": "^10 || ^12 || ^13.7 || ^14 || >=15.0.1" + } + }, + "node_modules/natural-compare": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz", + "integrity": "sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==", + "dev": true, + "license": "MIT" + }, + "node_modules/next": { + "version": "14.2.15", + "resolved": "https://registry.npmjs.org/next/-/next-14.2.15.tgz", + "integrity": "sha512-h9ctmOokpoDphRvMGnwOJAedT6zKhwqyZML9mDtspgf4Rh3Pn7UTYKqePNoDvhsWBAO5GoPNYshnAUGIazVGmw==", + "license": "MIT", + "dependencies": { + "@next/env": "14.2.15", + "@swc/helpers": "0.5.5", + "busboy": "1.6.0", + "caniuse-lite": "^1.0.30001579", + "graceful-fs": "^4.2.11", + "postcss": "8.4.31", + "styled-jsx": "5.1.1" + }, + "bin": { + "next": "dist/bin/next" + }, + "engines": { + "node": ">=18.17.0" + }, + "optionalDependencies": { + "@next/swc-darwin-arm64": "14.2.15", + "@next/swc-darwin-x64": "14.2.15", + "@next/swc-linux-arm64-gnu": "14.2.15", + "@next/swc-linux-arm64-musl": "14.2.15", + "@next/swc-linux-x64-gnu": "14.2.15", + "@next/swc-linux-x64-musl": "14.2.15", + "@next/swc-win32-arm64-msvc": "14.2.15", + "@next/swc-win32-ia32-msvc": "14.2.15", + "@next/swc-win32-x64-msvc": "14.2.15" + }, + "peerDependencies": { + "@opentelemetry/api": "^1.1.0", + "@playwright/test": "^1.41.2", + "react": "^18.2.0", + "react-dom": "^18.2.0", + "sass": "^1.3.0" + }, + "peerDependenciesMeta": { + "@opentelemetry/api": { + "optional": true + }, + "@playwright/test": { + "optional": true + }, + "sass": { + "optional": true + } + } + }, + "node_modules/next/node_modules/postcss": { + "version": "8.4.31", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.31.tgz", + "integrity": "sha512-PS08Iboia9mts/2ygV3eLpY5ghnUcfLV/EXTOW1E2qYxJKGGBUtNjN76FYHnMs36RmARn41bC0AZmn+rR0OVpQ==", + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/postcss/" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/postcss" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "license": "MIT", + "dependencies": { + "nanoid": "^3.3.6", + "picocolors": "^1.0.0", + "source-map-js": "^1.0.2" + }, + "engines": { + "node": "^10 || ^12 || >=14" + } + }, + "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, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "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, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/object-hash": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/object-hash/-/object-hash-3.0.0.tgz", + "integrity": "sha512-RSn9F68PjH9HqtltsSnqYC1XXoWe9Bju5+213R98cNGttag9q9yAOTzdbsqvIa7aNm5WffBZFpWYr2aWrklWAw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 6" + } + }, + "node_modules/object-inspect": { + "version": "1.13.2", + "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.13.2.tgz", + "integrity": "sha512-IRZSRuzJiynemAXPYtPe5BoI/RESNYR7TYm50MC5Mqbd3Jmw5y790sErYw3V6SryFJD64b74qQQs9wn5Bg/k3g==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/object-is": { + "version": "1.1.6", + "resolved": "https://registry.npmjs.org/object-is/-/object-is-1.1.6.tgz", + "integrity": "sha512-F8cZ+KfGlSGi09lJT7/Nd6KJZ9ygtvYC0/UYYLI9nmQKLMnydpB9yvbv9K1uSkEu7FU9vYPmVwLg328tX+ot3Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.7", + "define-properties": "^1.2.1" + }, + "engines": { + "node": ">= 0.4" + }, + "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, + "license": "MIT", + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/object.assign": { + "version": "4.1.5", + "resolved": "https://registry.npmjs.org/object.assign/-/object.assign-4.1.5.tgz", + "integrity": "sha512-byy+U7gp+FVwmyzKPYhW2h5l3crpmGsxl7X2s8y43IgxvG4g3QZ6CffDtsNQy1WsmZpQbO+ybo0AlW7TY6DcBQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.5", + "define-properties": "^1.2.1", + "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.8", + "resolved": "https://registry.npmjs.org/object.entries/-/object.entries-1.1.8.tgz", + "integrity": "sha512-cmopxi8VwRIAw/fkijJohSfpef5PdN0pMQJN6VC/ZKvn0LIknWD8KtgY6KlQdEc4tIjcQ3HxSMmnvtzIscdaYQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.7", + "define-properties": "^1.2.1", + "es-object-atoms": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/object.fromentries": { + "version": "2.0.8", + "resolved": "https://registry.npmjs.org/object.fromentries/-/object.fromentries-2.0.8.tgz", + "integrity": "sha512-k6E21FzySsSK5a21KRADBd/NGneRegFO5pLHfdQLpRDETUNJueLXs3WCzyQ3tFRDYgbq3KHGXfTbi2bs8WQ6rQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.7", + "define-properties": "^1.2.1", + "es-abstract": "^1.23.2", + "es-object-atoms": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/object.groupby": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/object.groupby/-/object.groupby-1.0.3.tgz", + "integrity": "sha512-+Lhy3TQTuzXI5hevh8sBGqbmurHbbIjAi0Z4S63nthVLmLxfbj4T54a4CfZrXIrt9iP4mVAPYMo/v99taj3wjQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.7", + "define-properties": "^1.2.1", + "es-abstract": "^1.23.2" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/object.values": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/object.values/-/object.values-1.2.0.tgz", + "integrity": "sha512-yBYjY9QX2hnRmZHAjG/f13MzmBzxzYgQhFrke06TTyKY5zSTEqkOeukBzIdVA3j3ulu8Qa3MbVFShV7T2RmGtQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.7", + "define-properties": "^1.2.1", + "es-object-atoms": "^1.0.0" + }, + "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, + "license": "ISC", + "dependencies": { + "wrappy": "1" + } + }, + "node_modules/optionator": { + "version": "0.9.4", + "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.9.4.tgz", + "integrity": "sha512-6IpQ7mKUxRcZNLIObR0hz7lxsapSSIYNZJwXPGeF0mTVqGKFIXj1DQcMoT22S3ROcLyY/rz0PWaWZ9ayWmad9g==", + "dev": true, + "license": "MIT", + "dependencies": { + "deep-is": "^0.1.3", + "fast-levenshtein": "^2.0.6", + "levn": "^0.4.1", + "prelude-ls": "^1.2.1", + "type-check": "^0.4.0", + "word-wrap": "^1.2.5" + }, + "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, + "license": "MIT", + "dependencies": { + "yocto-queue": "^0.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "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, + "license": "MIT", + "dependencies": { + "p-limit": "^3.0.2" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "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, + "license": "MIT", + "dependencies": { + "callsites": "^3.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "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, + "license": "MIT", + "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, + "license": "MIT", + "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, + "license": "MIT", + "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, + "license": "MIT" + }, + "node_modules/path-scurry": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/path-scurry/-/path-scurry-1.11.1.tgz", + "integrity": "sha512-Xa4Nw17FS9ApQFJ9umLiJS4orGjm7ZzwUrwamcGQuHSzDyth9boKDaycYdDcZDuqYATXw4HFXgaqWTctW/v1HA==", + "dev": true, + "license": "BlueOak-1.0.0", + "dependencies": { + "lru-cache": "^10.2.0", + "minipass": "^5.0.0 || ^6.0.2 || ^7.0.0" + }, + "engines": { + "node": ">=16 || 14 >=14.18" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/picocolors": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.1.1.tgz", + "integrity": "sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==", + "license": "ISC" + }, + "node_modules/picomatch": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", + "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8.6" + }, + "funding": { + "url": "https://github.com/sponsors/jonschlinkert" + } + }, + "node_modules/pify": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz", + "integrity": "sha512-udgsAY+fTnvv7kI7aaxbqwWNb0AHiB0qBO89PZKPkoTmGOgdbrHDKD+0B2X4uTfJ/FT1R09r9gTsjUjNJotuog==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "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, + "license": "MIT", + "engines": { + "node": ">= 6" + } + }, + "node_modules/possible-typed-array-names": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/possible-typed-array-names/-/possible-typed-array-names-1.0.0.tgz", + "integrity": "sha512-d7Uw+eZoloe0EHDIYoe+bQ5WXnGMOpmiZFTuMWCwpjzzkL2nTjcKiAk4hh8TjnGye2TwWOk3UXucZ+3rbmBa8Q==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/postcss": { + "version": "8.4.47", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.47.tgz", + "integrity": "sha512-56rxCq7G/XfB4EkXq9Egn5GCqugWvDFjafDOThIdMBsI15iqPqR5r15TfSr1YPYeEI19YeaXMCbY6u88Y76GLQ==", + "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/postcss/" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/postcss" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "license": "MIT", + "dependencies": { + "nanoid": "^3.3.7", + "picocolors": "^1.1.0", + "source-map-js": "^1.2.1" + }, + "engines": { + "node": "^10 || ^12 || >=14" + } + }, + "node_modules/postcss-import": { + "version": "15.1.0", + "resolved": "https://registry.npmjs.org/postcss-import/-/postcss-import-15.1.0.tgz", + "integrity": "sha512-hpr+J05B2FVYUAXHeK1YyI267J/dDDhMU6B6civm8hSY1jYJnBXxzKDKDswzJmtLHryrjhnDjqqp/49t8FALew==", + "dev": true, + "license": "MIT", + "dependencies": { + "postcss-value-parser": "^4.0.0", + "read-cache": "^1.0.0", + "resolve": "^1.1.7" + }, + "engines": { + "node": ">=14.0.0" + }, + "peerDependencies": { + "postcss": "^8.0.0" + } + }, + "node_modules/postcss-js": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/postcss-js/-/postcss-js-4.0.1.tgz", + "integrity": "sha512-dDLF8pEO191hJMtlHFPRa8xsizHaM82MLfNkUHdUtVEV3tgTp5oj+8qbEqYM57SLfc74KSbw//4SeJma2LRVIw==", + "dev": true, + "license": "MIT", + "dependencies": { + "camelcase-css": "^2.0.1" + }, + "engines": { + "node": "^12 || ^14 || >= 16" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/postcss/" + }, + "peerDependencies": { + "postcss": "^8.4.21" + } + }, + "node_modules/postcss-load-config": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/postcss-load-config/-/postcss-load-config-4.0.2.tgz", + "integrity": "sha512-bSVhyJGL00wMVoPUzAVAnbEoWyqRxkjv64tUl427SKnPrENtq6hJwUojroMz2VB+Q1edmi4IfrAPpami5VVgMQ==", + "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/postcss/" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "license": "MIT", + "dependencies": { + "lilconfig": "^3.0.0", + "yaml": "^2.3.4" + }, + "engines": { + "node": ">= 14" + }, + "peerDependencies": { + "postcss": ">=8.0.9", + "ts-node": ">=9.0.0" + }, + "peerDependenciesMeta": { + "postcss": { + "optional": true + }, + "ts-node": { + "optional": true + } + } + }, + "node_modules/postcss-load-config/node_modules/lilconfig": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/lilconfig/-/lilconfig-3.1.2.tgz", + "integrity": "sha512-eop+wDAvpItUys0FWkHIKeC9ybYrTGbU41U5K7+bttZZeohvnY7M9dZ5kB21GNWiFT2q1OoPTvncPCgSOVO5ow==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/sponsors/antonk52" + } + }, + "node_modules/postcss-nested": { + "version": "6.2.0", + "resolved": "https://registry.npmjs.org/postcss-nested/-/postcss-nested-6.2.0.tgz", + "integrity": "sha512-HQbt28KulC5AJzG+cZtj9kvKB93CFCdLvog1WFLf1D+xmMvPGlBstkpTEZfK5+AN9hfJocyBFCNiqyS48bpgzQ==", + "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/postcss/" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "license": "MIT", + "dependencies": { + "postcss-selector-parser": "^6.1.1" + }, + "engines": { + "node": ">=12.0" + }, + "peerDependencies": { + "postcss": "^8.2.14" + } + }, + "node_modules/postcss-selector-parser": { + "version": "6.1.2", + "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-6.1.2.tgz", + "integrity": "sha512-Q8qQfPiZ+THO/3ZrOrO0cJJKfpYCagtMUkXbnEfmgUjwXg6z/WBeOyS9APBBPCTSiDV+s4SwQGu8yFsiMRIudg==", + "dev": true, + "license": "MIT", + "dependencies": { + "cssesc": "^3.0.0", + "util-deprecate": "^1.0.2" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/postcss-value-parser": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-4.2.0.tgz", + "integrity": "sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ==", + "dev": true, + "license": "MIT" + }, + "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, + "license": "MIT", + "engines": { + "node": ">= 0.8.0" + } + }, + "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, + "license": "MIT", + "dependencies": { + "loose-envify": "^1.4.0", + "object-assign": "^4.1.1", + "react-is": "^16.13.1" + } + }, + "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, + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "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" + } + ], + "license": "MIT" + }, + "node_modules/react": { + "version": "18.3.1", + "resolved": "https://registry.npmjs.org/react/-/react-18.3.1.tgz", + "integrity": "sha512-wS+hAgJShR0KhEvPJArfuPVN1+Hz1t0Y6n5jLrGQbkb4urgPE/0Rve+1kMB1v/oWgHgm4WIcV+i7F2pTVj+2iQ==", + "license": "MIT", + "dependencies": { + "loose-envify": "^1.1.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/react-dom": { + "version": "18.3.1", + "resolved": "https://registry.npmjs.org/react-dom/-/react-dom-18.3.1.tgz", + "integrity": "sha512-5m4nQKp+rZRb09LNH59GM4BxTh9251/ylbKIbpe7TpGxfJ+9kv6BLkLBXIjjspbgbnIBNqlI23tRnTWT0snUIw==", + "license": "MIT", + "dependencies": { + "loose-envify": "^1.1.0", + "scheduler": "^0.23.2" + }, + "peerDependencies": { + "react": "^18.3.1" + } + }, + "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, + "license": "MIT" + }, + "node_modules/read-cache": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/read-cache/-/read-cache-1.0.0.tgz", + "integrity": "sha512-Owdv/Ft7IjOgm/i0xvNDZ1LrRANRfew4b2prF3OWMQLxLfu3bS8FVhCsrSCMK4lR56Y9ya+AThoTpDCTxCmpRA==", + "dev": true, + "license": "MIT", + "dependencies": { + "pify": "^2.3.0" + } + }, + "node_modules/readdirp": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz", + "integrity": "sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==", + "dev": true, + "license": "MIT", + "dependencies": { + "picomatch": "^2.2.1" + }, + "engines": { + "node": ">=8.10.0" + } + }, + "node_modules/reflect.getprototypeof": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/reflect.getprototypeof/-/reflect.getprototypeof-1.0.6.tgz", + "integrity": "sha512-fmfw4XgoDke3kdI6h4xcUz1dG8uaiv5q9gcEwLS4Pnth2kxT+GZ7YehS1JTMGBQmtV7Y4GFGbs2re2NqhdozUg==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.7", + "define-properties": "^1.2.1", + "es-abstract": "^1.23.1", + "es-errors": "^1.3.0", + "get-intrinsic": "^1.2.4", + "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.3", + "resolved": "https://registry.npmjs.org/regexp.prototype.flags/-/regexp.prototype.flags-1.5.3.tgz", + "integrity": "sha512-vqlC04+RQoFalODCbCumG2xIOvapzVMHwsyIGM/SIE8fRhFFsXeH8/QQ+s0T0kDAhKc4k30s73/0ydkHQz6HlQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.7", + "define-properties": "^1.2.1", + "es-errors": "^1.3.0", + "set-function-name": "^2.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "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, + "license": "MIT", + "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-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, + "license": "MIT", + "engines": { + "node": ">=4" + } + }, + "node_modules/resolve-pkg-maps": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/resolve-pkg-maps/-/resolve-pkg-maps-1.0.0.tgz", + "integrity": "sha512-seS2Tj26TBVOC2NIc2rOe2y2ZO7efxITtLZcGSOnHHNOQ7CkiUBfw0Iw2ck6xkIhPwLhKNLS8BO+hEpngQlqzw==", + "dev": true, + "license": "MIT", + "funding": { + "url": "https://github.com/privatenumber/resolve-pkg-maps?sponsor=1" + } + }, + "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, + "license": "MIT", + "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==", + "deprecated": "Rimraf versions prior to v4 are no longer supported", + "dev": true, + "license": "ISC", + "dependencies": { + "glob": "^7.1.3" + }, + "bin": { + "rimraf": "bin.js" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/rimraf/node_modules/glob": { + "version": "7.2.3", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", + "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", + "deprecated": "Glob versions prior to v9 are no longer supported", + "dev": true, + "license": "ISC", + "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/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" + } + ], + "license": "MIT", + "dependencies": { + "queue-microtask": "^1.2.2" + } + }, + "node_modules/safe-array-concat": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/safe-array-concat/-/safe-array-concat-1.1.2.tgz", + "integrity": "sha512-vj6RsCsWBCf19jIeHEfkRMw8DPiBb+DMXklQ/1SGDHOMlHdPUkZXFQ2YdplS23zESTijAcurb1aSgJA3AgMu1Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.7", + "get-intrinsic": "^1.2.4", + "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.3", + "resolved": "https://registry.npmjs.org/safe-regex-test/-/safe-regex-test-1.0.3.tgz", + "integrity": "sha512-CdASjNJPvRa7roO6Ra/gLYBTzYzzPyyBXxIMdGW3USQLyjWEls2RgW5UBTXaQVp+OrpeCK3bLem8smtmheoRuw==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.6", + "es-errors": "^1.3.0", + "is-regex": "^1.1.4" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/scheduler": { + "version": "0.23.2", + "resolved": "https://registry.npmjs.org/scheduler/-/scheduler-0.23.2.tgz", + "integrity": "sha512-UOShsPwz7NrMUqhR6t0hWjFduvOzbtv7toDH1/hIrfRNIDBnnBWd0CwJTGvTpngVlmwGCdP9/Zl/tVrDqcuYzQ==", + "license": "MIT", + "dependencies": { + "loose-envify": "^1.1.0" + } + }, + "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, + "license": "ISC", + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "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==", + "dev": true, + "license": "MIT", + "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.2", + "resolved": "https://registry.npmjs.org/set-function-name/-/set-function-name-2.0.2.tgz", + "integrity": "sha512-7PGFlmtwsEADb0WYyvCMa1t+yke6daIG4Wirafur5kcf+MhUnPms1UeR0CKQdTZD81yESwMHbtn+TR+dMviakQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "define-data-property": "^1.1.4", + "es-errors": "^1.3.0", + "functions-have-names": "^1.2.3", + "has-property-descriptors": "^1.0.2" + }, + "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, + "license": "MIT", + "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, + "license": "MIT", + "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==", + "dev": true, + "license": "MIT", + "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": "4.1.0", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-4.1.0.tgz", + "integrity": "sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==", + "dev": true, + "license": "ISC", + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/source-map-js": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.2.1.tgz", + "integrity": "sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA==", + "license": "BSD-3-Clause", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/stop-iteration-iterator": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/stop-iteration-iterator/-/stop-iteration-iterator-1.0.0.tgz", + "integrity": "sha512-iCGQj+0l0HOdZ2AEeBADlsRC+vsnDsZsbdSiH1yNSjcfKM7fdpCMfqAL/dwF5BLiw/XhRft/Wax6zQbhq2BcjQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "internal-slot": "^1.0.4" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/streamsearch": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/streamsearch/-/streamsearch-1.1.0.tgz", + "integrity": "sha512-Mcc5wHehp9aXz1ax6bZUyY5afg9u2rv5cqQI3mRrYkGC8rW2hM02jWuwjtL++LS5qinSyhj2QfLyNsuc+VsExg==", + "engines": { + "node": ">=10.0.0" + } + }, + "node_modules/string-width": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-5.1.2.tgz", + "integrity": "sha512-HnLOCR3vjcY8beoNLtcjZ5/nxn2afmME6lhrDrebokqMap+XbeW8n9TXpPDOqdGK5qcI3oT0GKTW6wC7EMiVqA==", + "dev": true, + "license": "MIT", + "dependencies": { + "eastasianwidth": "^0.2.0", + "emoji-regex": "^9.2.2", + "strip-ansi": "^7.0.1" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/string-width-cjs": { + "name": "string-width", + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "dev": true, + "license": "MIT", + "dependencies": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/string-width-cjs/node_modules/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, + "license": "MIT" + }, + "node_modules/string-width/node_modules/ansi-regex": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.1.0.tgz", + "integrity": "sha512-7HSX4QQb4CspciLpVFwyRe79O3xsIZDDLER21kERQ71oaPodF8jL725AgJMFAYbooIqolJoRLuM81SpeUkpkvA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/ansi-regex?sponsor=1" + } + }, + "node_modules/string-width/node_modules/strip-ansi": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.1.0.tgz", + "integrity": "sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-regex": "^6.0.1" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/strip-ansi?sponsor=1" + } + }, + "node_modules/string.prototype.includes": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/string.prototype.includes/-/string.prototype.includes-2.0.1.tgz", + "integrity": "sha512-o7+c9bW6zpAdJHTtujeePODAhkuicdAryFsfVKwA+wGw89wJ4GTY484WTucM9hLtDEOpOvI+aHnzqnC5lHp4Rg==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.7", + "define-properties": "^1.2.1", + "es-abstract": "^1.23.3" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/string.prototype.matchall": { + "version": "4.0.11", + "resolved": "https://registry.npmjs.org/string.prototype.matchall/-/string.prototype.matchall-4.0.11.tgz", + "integrity": "sha512-NUdh0aDavY2og7IbBPenWqR9exH+E26Sv8e0/eTe1tltDGZL+GtBkDAnnyBtmekfK6/Dq3MkcGtzXFEd1LQrtg==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.7", + "define-properties": "^1.2.1", + "es-abstract": "^1.23.2", + "es-errors": "^1.3.0", + "es-object-atoms": "^1.0.0", + "get-intrinsic": "^1.2.4", + "gopd": "^1.0.1", + "has-symbols": "^1.0.3", + "internal-slot": "^1.0.7", + "regexp.prototype.flags": "^1.5.2", + "set-function-name": "^2.0.2", + "side-channel": "^1.0.6" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/string.prototype.repeat": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/string.prototype.repeat/-/string.prototype.repeat-1.0.0.tgz", + "integrity": "sha512-0u/TldDbKD8bFCQ/4f5+mNRrXwZ8hg2w7ZR8wa16e8z9XpePWl3eGEcUD0OXpEH/VJH/2G3gjUtR3ZOiBe2S/w==", + "dev": true, + "license": "MIT", + "dependencies": { + "define-properties": "^1.1.3", + "es-abstract": "^1.17.5" + } + }, + "node_modules/string.prototype.trim": { + "version": "1.2.9", + "resolved": "https://registry.npmjs.org/string.prototype.trim/-/string.prototype.trim-1.2.9.tgz", + "integrity": "sha512-klHuCNxiMZ8MlsOihJhJEBJAiMVqU3Z2nEXWfWnIqjN0gEFS9J9+IxKozWWtQGcgoa1WUZzLjKPTr4ZHNFTFxw==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.7", + "define-properties": "^1.2.1", + "es-abstract": "^1.23.0", + "es-object-atoms": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/string.prototype.trimend": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/string.prototype.trimend/-/string.prototype.trimend-1.0.8.tgz", + "integrity": "sha512-p73uL5VCHCO2BZZ6krwwQE3kCzM7NKmis8S//xEC6fQonchbum4eP6kR4DLEjQFO3Wnj3Fuo8NM0kOSjVdHjZQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.7", + "define-properties": "^1.2.1", + "es-object-atoms": "^1.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/string.prototype.trimstart": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/string.prototype.trimstart/-/string.prototype.trimstart-1.0.8.tgz", + "integrity": "sha512-UXSH262CSZY1tfu3G3Secr6uGLCFVPMhIqHjlgCUtCCcgihYc/xKs9djMTMUOb2j1mVSeU8EU6NWc/iQKU6Gfg==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.7", + "define-properties": "^1.2.1", + "es-object-atoms": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "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, + "license": "MIT", + "dependencies": { + "ansi-regex": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/strip-ansi-cjs": { + "name": "strip-ansi", + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-regex": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/strip-bom": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-3.0.0.tgz", + "integrity": "sha512-vavAMRXOgBVNF6nyEEmL3DBK19iRpDcoIwW+swQ+CbGiu7lju6t+JklA1MHweoWtadgt4ISVUsXLyDq34ddcwA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=4" + } + }, + "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, + "license": "MIT", + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/styled-jsx": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/styled-jsx/-/styled-jsx-5.1.1.tgz", + "integrity": "sha512-pW7uC1l4mBZ8ugbiZrcIsiIvVx1UmTfw7UkC3Um2tmfUq9Bhk8IiyEIPl6F8agHgjzku6j0xQEZbfA5uSgSaCw==", + "license": "MIT", + "dependencies": { + "client-only": "0.0.1" + }, + "engines": { + "node": ">= 12.0.0" + }, + "peerDependencies": { + "react": ">= 16.8.0 || 17.x.x || ^18.0.0-0" + }, + "peerDependenciesMeta": { + "@babel/core": { + "optional": true + }, + "babel-plugin-macros": { + "optional": true + } + } + }, + "node_modules/sucrase": { + "version": "3.35.0", + "resolved": "https://registry.npmjs.org/sucrase/-/sucrase-3.35.0.tgz", + "integrity": "sha512-8EbVDiu9iN/nESwxeSxDKe0dunta1GOlHufmSSXxMD2z2/tMZpDMpvXQGsc+ajGo8y2uYUmixaSRUc/QPoQ0GA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jridgewell/gen-mapping": "^0.3.2", + "commander": "^4.0.0", + "glob": "^10.3.10", + "lines-and-columns": "^1.1.6", + "mz": "^2.7.0", + "pirates": "^4.0.1", + "ts-interface-checker": "^0.1.9" + }, + "bin": { + "sucrase": "bin/sucrase", + "sucrase-node": "bin/sucrase-node" + }, + "engines": { + "node": ">=16 || 14 >=14.17" + } + }, + "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, + "license": "MIT", + "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, + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/tailwindcss": { + "version": "3.4.14", + "resolved": "https://registry.npmjs.org/tailwindcss/-/tailwindcss-3.4.14.tgz", + "integrity": "sha512-IcSvOcTRcUtQQ7ILQL5quRDg7Xs93PdJEk1ZLbhhvJc7uj/OAhYOnruEiwnGgBvUtaUAJ8/mhSw1o8L2jCiENA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@alloc/quick-lru": "^5.2.0", + "arg": "^5.0.2", + "chokidar": "^3.5.3", + "didyoumean": "^1.2.2", + "dlv": "^1.1.3", + "fast-glob": "^3.3.0", + "glob-parent": "^6.0.2", + "is-glob": "^4.0.3", + "jiti": "^1.21.0", + "lilconfig": "^2.1.0", + "micromatch": "^4.0.5", + "normalize-path": "^3.0.0", + "object-hash": "^3.0.0", + "picocolors": "^1.0.0", + "postcss": "^8.4.23", + "postcss-import": "^15.1.0", + "postcss-js": "^4.0.1", + "postcss-load-config": "^4.0.1", + "postcss-nested": "^6.0.1", + "postcss-selector-parser": "^6.0.11", + "resolve": "^1.22.2", + "sucrase": "^3.32.0" + }, + "bin": { + "tailwind": "lib/cli.js", + "tailwindcss": "lib/cli.js" + }, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/tapable": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/tapable/-/tapable-2.2.1.tgz", + "integrity": "sha512-GNzQvQTOIP6RyTfE2Qxb8ZVlNmw0n88vp1szwWRimP02mnTsx3Wtn5qRdqY9w2XduFNUgvOwhNnQsjwCp+kqaQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/text-table": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz", + "integrity": "sha512-N+8UisAXDGk8PFXP4HAzVR9nbfmVJ3zYLAWiTIoqC5v5isinhr+r5uaO8+7r3BMfuNIufIsA7RdpVgacC2cSpw==", + "dev": true, + "license": "MIT" + }, + "node_modules/thenify": { + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/thenify/-/thenify-3.3.1.tgz", + "integrity": "sha512-RVZSIV5IG10Hk3enotrhvz0T9em6cyHBLkH/YAZuKqd8hRkKhSfCGIcP2KUY0EPxndzANBmNllzWPwak+bheSw==", + "dev": true, + "license": "MIT", + "dependencies": { + "any-promise": "^1.0.0" + } + }, + "node_modules/thenify-all": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/thenify-all/-/thenify-all-1.6.0.tgz", + "integrity": "sha512-RNxQH/qI8/t3thXJDwcstUO4zeqo64+Uy/+sNVRBx4Xn2OX+OZ9oP+iJnNFqplFra2ZUVeKCSa2oVWi3T4uVmA==", + "dev": true, + "license": "MIT", + "dependencies": { + "thenify": ">= 3.1.0 < 4" + }, + "engines": { + "node": ">=0.8" + } + }, + "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, + "license": "MIT", + "dependencies": { + "is-number": "^7.0.0" + }, + "engines": { + "node": ">=8.0" + } + }, + "node_modules/ts-api-utils": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/ts-api-utils/-/ts-api-utils-1.3.0.tgz", + "integrity": "sha512-UQMIo7pb8WRomKR1/+MFVLTroIvDVtMX3K6OUir8ynLyzB8Jeriont2bTAtmNPa1ekAgN7YPDyf6V+ygrdU+eQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=16" + }, + "peerDependencies": { + "typescript": ">=4.2.0" + } + }, + "node_modules/ts-interface-checker": { + "version": "0.1.13", + "resolved": "https://registry.npmjs.org/ts-interface-checker/-/ts-interface-checker-0.1.13.tgz", + "integrity": "sha512-Y/arvbn+rrz3JCKl9C4kVNfTfSm2/mEp5FSz5EsZSANGPSlQrpRI5M4PKF+mJnE52jOO90PnPSc3Ur3bTQw0gA==", + "dev": true, + "license": "Apache-2.0" + }, + "node_modules/tsconfig-paths": { + "version": "3.15.0", + "resolved": "https://registry.npmjs.org/tsconfig-paths/-/tsconfig-paths-3.15.0.tgz", + "integrity": "sha512-2Ac2RgzDe/cn48GvOe3M+o82pEFewD3UPbyoUHHdKasHwJKjds4fLXWf/Ux5kATBKN20oaFGu+jbElp1pos0mg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/json5": "^0.0.29", + "json5": "^1.0.2", + "minimist": "^1.2.6", + "strip-bom": "^3.0.0" + } + }, + "node_modules/tslib": { + "version": "2.8.0", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.0.tgz", + "integrity": "sha512-jWVzBLplnCmoaTr13V9dYbiQ99wvZRd0vNWaDRg+aVYRcjDF3nDksxFDE/+fkXnKhpnUUkmx5pK/v8mCtLVqZA==", + "license": "0BSD" + }, + "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, + "license": "MIT", + "dependencies": { + "prelude-ls": "^1.2.1" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "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, + "license": "(MIT OR CC0-1.0)", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/typed-array-buffer": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/typed-array-buffer/-/typed-array-buffer-1.0.2.tgz", + "integrity": "sha512-gEymJYKZtKXzzBzM4jqa9w6Q1Jjm7x2d+sh19AdsD4wqnMPDYyvwpsIc2Q/835kHuo3BEQ7CjelGhfTsoBb2MQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.7", + "es-errors": "^1.3.0", + "is-typed-array": "^1.1.13" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/typed-array-byte-length": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/typed-array-byte-length/-/typed-array-byte-length-1.0.1.tgz", + "integrity": "sha512-3iMJ9q0ao7WE9tWcaYKIptkNBuOIcZCCT0d4MRvuuH88fEoEH62IuQe0OtraD3ebQEoTRk8XCBoknUNc1Y67pw==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.7", + "for-each": "^0.3.3", + "gopd": "^1.0.1", + "has-proto": "^1.0.3", + "is-typed-array": "^1.1.13" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/typed-array-byte-offset": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/typed-array-byte-offset/-/typed-array-byte-offset-1.0.2.tgz", + "integrity": "sha512-Ous0vodHa56FviZucS2E63zkgtgrACj7omjwd/8lTEMEPFFyjfixMZ1ZXenpgCFBBt4EC1J2XsyVS2gkG0eTFA==", + "dev": true, + "license": "MIT", + "dependencies": { + "available-typed-arrays": "^1.0.7", + "call-bind": "^1.0.7", + "for-each": "^0.3.3", + "gopd": "^1.0.1", + "has-proto": "^1.0.3", + "is-typed-array": "^1.1.13" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/typed-array-length": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/typed-array-length/-/typed-array-length-1.0.6.tgz", + "integrity": "sha512-/OxDN6OtAk5KBpGb28T+HZc2M+ADtvRxXrKKbUwtsLgdoxgX13hyy7ek6bFRl5+aBs2yZzB0c4CnQfAtVypW/g==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.7", + "for-each": "^0.3.3", + "gopd": "^1.0.1", + "has-proto": "^1.0.3", + "is-typed-array": "^1.1.13", + "possible-typed-array-names": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/typescript": { + "version": "5.6.3", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.6.3.tgz", + "integrity": "sha512-hjcS1mhfuyi4WW8IWtjP7brDrG2cuDZukyrYrSauoXGNgx0S7zceP07adYkJycEr56BOUTNPzbInooiN3fn1qw==", + "dev": true, + "license": "Apache-2.0", + "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, + "license": "MIT", + "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.19.8", + "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-6.19.8.tgz", + "integrity": "sha512-ve2KP6f/JnbPBFyobGHuerC9g1FYGn/F8n1LWTwNxCEzd6IfqTwUQcNXgEtmmQ6DlRrC1hrSrBnCZPokRrDHjw==", + "dev": true, + "license": "MIT" + }, + "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, + "license": "BSD-2-Clause", + "dependencies": { + "punycode": "^2.1.0" + } + }, + "node_modules/util-deprecate": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", + "integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==", + "dev": true, + "license": "MIT" + }, + "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, + "license": "ISC", + "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, + "license": "MIT", + "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.4", + "resolved": "https://registry.npmjs.org/which-builtin-type/-/which-builtin-type-1.1.4.tgz", + "integrity": "sha512-bppkmBSsHFmIMSl8BO9TbsyzsvGjVoppt8xUiGzwiu/bhDCGxnpOKCxgqj6GuyHE0mINMDecBFPlOm2hzY084w==", + "dev": true, + "license": "MIT", + "dependencies": { + "function.prototype.name": "^1.1.6", + "has-tostringtag": "^1.0.2", + "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.2", + "which-typed-array": "^1.1.15" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/which-collection": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/which-collection/-/which-collection-1.0.2.tgz", + "integrity": "sha512-K4jVyjnBdgvc86Y6BkaLZEN933SwYOuBFkdmBu9ZfkcAbdVbpITnDmjvZ/aQjRXQrv5EPkTnD1s39GiiqbngCw==", + "dev": true, + "license": "MIT", + "dependencies": { + "is-map": "^2.0.3", + "is-set": "^2.0.3", + "is-weakmap": "^2.0.2", + "is-weakset": "^2.0.3" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/which-typed-array": { + "version": "1.1.15", + "resolved": "https://registry.npmjs.org/which-typed-array/-/which-typed-array-1.1.15.tgz", + "integrity": "sha512-oV0jmFtUky6CXfkqehVvBP/LSWJ2sy4vWMioiENyJLePrBO/yKyV9OyJySfAKosh+RYkIl5zJCNZ8/4JncrpdA==", + "dev": true, + "license": "MIT", + "dependencies": { + "available-typed-arrays": "^1.0.7", + "call-bind": "^1.0.7", + "for-each": "^0.3.3", + "gopd": "^1.0.1", + "has-tostringtag": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/word-wrap": { + "version": "1.2.5", + "resolved": "https://registry.npmjs.org/word-wrap/-/word-wrap-1.2.5.tgz", + "integrity": "sha512-BN22B5eaMMI9UMtjrGd5g5eCYPpCPDUy0FJXbYsaT5zYxjFOckS53SQDE3pWkVoWpHXVb3BrYcEN4Twa55B5cA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/wrap-ansi": { + "version": "8.1.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-8.1.0.tgz", + "integrity": "sha512-si7QWI6zUMq56bESFvagtmzMdGOtoxfR+Sez11Mobfc7tm+VkUckk9bW2UeffTGVUbOksxmSw0AA2gs8g71NCQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-styles": "^6.1.0", + "string-width": "^5.0.1", + "strip-ansi": "^7.0.1" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/wrap-ansi?sponsor=1" + } + }, + "node_modules/wrap-ansi-cjs": { + "name": "wrap-ansi", + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", + "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-styles": "^4.0.0", + "string-width": "^4.1.0", + "strip-ansi": "^6.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/wrap-ansi?sponsor=1" + } + }, + "node_modules/wrap-ansi-cjs/node_modules/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, + "license": "MIT" + }, + "node_modules/wrap-ansi-cjs/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, + "license": "MIT", + "dependencies": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/wrap-ansi/node_modules/ansi-regex": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.1.0.tgz", + "integrity": "sha512-7HSX4QQb4CspciLpVFwyRe79O3xsIZDDLER21kERQ71oaPodF8jL725AgJMFAYbooIqolJoRLuM81SpeUkpkvA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/ansi-regex?sponsor=1" + } + }, + "node_modules/wrap-ansi/node_modules/ansi-styles": { + "version": "6.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-6.2.1.tgz", + "integrity": "sha512-bN798gFfQX+viw3R7yrGWRqnrN2oRkEkUjjl4JNn4E8GxxbjtG3FbrEIIY3l8/hrwUwIeCZvi4QuOTP4MErVug==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/wrap-ansi/node_modules/strip-ansi": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.1.0.tgz", + "integrity": "sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-regex": "^6.0.1" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/strip-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, + "license": "ISC" + }, + "node_modules/yaml": { + "version": "2.6.0", + "resolved": "https://registry.npmjs.org/yaml/-/yaml-2.6.0.tgz", + "integrity": "sha512-a6ae//JvKDEra2kdi1qzCyrJW/WZCgFi8ydDV+eXExl95t+5R+ijnqHJbz9tmMh8FUjx3iv2fCQ4dclAQlO2UQ==", + "dev": true, + "license": "ISC", + "bin": { + "yaml": "bin.mjs" + }, + "engines": { + "node": ">= 14" + } + }, + "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, + "license": "MIT", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + } + } +} diff --git a/mlflow-site/package.json b/mlflow-site/package.json new file mode 100644 index 00000000..ae9b78d7 --- /dev/null +++ b/mlflow-site/package.json @@ -0,0 +1,26 @@ +{ + "name": "mlflow-site", + "version": "0.1.0", + "private": true, + "scripts": { + "dev": "next dev", + "build": "next build", + "start": "next start", + "lint": "next lint" + }, + "dependencies": { + "react": "^18", + "react-dom": "^18", + "next": "14.2.15" + }, + "devDependencies": { + "typescript": "^5", + "@types/node": "^20", + "@types/react": "^18", + "@types/react-dom": "^18", + "postcss": "^8", + "tailwindcss": "^3.4.1", + "eslint": "^8", + "eslint-config-next": "14.2.15" + } +} diff --git a/mlflow-site/postcss.config.mjs b/mlflow-site/postcss.config.mjs new file mode 100644 index 00000000..1a69fd2a --- /dev/null +++ b/mlflow-site/postcss.config.mjs @@ -0,0 +1,8 @@ +/** @type {import('postcss-load-config').Config} */ +const config = { + plugins: { + tailwindcss: {}, + }, +}; + +export default config; diff --git a/mlflow-site/src/app/favicon.ico b/mlflow-site/src/app/favicon.ico new file mode 100644 index 0000000000000000000000000000000000000000..718d6fea4835ec2d246af9800eddb7ffb276240c GIT binary patch literal 25931 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 LrJugUA?W`A8`#=m literal 0 HcmV?d00001 diff --git a/mlflow-site/src/app/fonts/GeistMonoVF.woff b/mlflow-site/src/app/fonts/GeistMonoVF.woff new file mode 100644 index 0000000000000000000000000000000000000000..f2ae185cbfd16946a534d819e9eb03924abbcc49 GIT binary patch literal 67864 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ϣ%UY8`RWp~V-U_7 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 CLkb=M literal 0 HcmV?d00001 diff --git a/mlflow-site/src/app/fonts/GeistVF.woff b/mlflow-site/src/app/fonts/GeistVF.woff new file mode 100644 index 0000000000000000000000000000000000000000..1b62daacff96dad6584e71cd962051b82957c313 GIT binary patch literal 66268 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 >-Aun5A4Gp>4U0IQJ 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 G)cz05(PHWV literal 0 HcmV?d00001 diff --git a/mlflow-site/src/app/globals.css b/mlflow-site/src/app/globals.css new file mode 100644 index 00000000..13d40b89 --- /dev/null +++ b/mlflow-site/src/app/globals.css @@ -0,0 +1,27 @@ +@tailwind base; +@tailwind components; +@tailwind utilities; + +:root { + --background: #ffffff; + --foreground: #171717; +} + +@media (prefers-color-scheme: dark) { + :root { + --background: #0a0a0a; + --foreground: #ededed; + } +} + +body { + color: var(--foreground); + background: var(--background); + font-family: Arial, Helvetica, sans-serif; +} + +@layer utilities { + .text-balance { + text-wrap: balance; + } +} diff --git a/mlflow-site/src/app/layout.tsx b/mlflow-site/src/app/layout.tsx new file mode 100644 index 00000000..a36cde01 --- /dev/null +++ b/mlflow-site/src/app/layout.tsx @@ -0,0 +1,35 @@ +import type { Metadata } from "next"; +import localFont from "next/font/local"; +import "./globals.css"; + +const geistSans = localFont({ + src: "./fonts/GeistVF.woff", + variable: "--font-geist-sans", + weight: "100 900", +}); +const geistMono = localFont({ + src: "./fonts/GeistMonoVF.woff", + variable: "--font-geist-mono", + weight: "100 900", +}); + +export const metadata: Metadata = { + title: "Create Next App", + description: "Generated by create next app", +}; + +export default function RootLayout({ + children, +}: Readonly<{ + children: React.ReactNode; +}>) { + return ( + + + {children} + + + ); +} diff --git a/mlflow-site/src/app/page.tsx b/mlflow-site/src/app/page.tsx new file mode 100644 index 00000000..f0832dd2 --- /dev/null +++ b/mlflow-site/src/app/page.tsx @@ -0,0 +1,101 @@ +import Image from 'next/image'; + +export default function Home() { + return ( + + ); +} diff --git a/mlflow-site/tailwind.config.ts b/mlflow-site/tailwind.config.ts new file mode 100644 index 00000000..021c3937 --- /dev/null +++ b/mlflow-site/tailwind.config.ts @@ -0,0 +1,19 @@ +import type { Config } from "tailwindcss"; + +const config: Config = { + content: [ + "./src/pages/**/*.{js,ts,jsx,tsx,mdx}", + "./src/components/**/*.{js,ts,jsx,tsx,mdx}", + "./src/app/**/*.{js,ts,jsx,tsx,mdx}", + ], + theme: { + extend: { + colors: { + background: "var(--background)", + foreground: "var(--foreground)", + }, + }, + }, + plugins: [], +}; +export default config; diff --git a/mlflow-site/tsconfig.json b/mlflow-site/tsconfig.json new file mode 100644 index 00000000..7b285893 --- /dev/null +++ b/mlflow-site/tsconfig.json @@ -0,0 +1,26 @@ +{ + "compilerOptions": { + "lib": ["dom", "dom.iterable", "esnext"], + "allowJs": true, + "skipLibCheck": true, + "strict": true, + "noEmit": true, + "esModuleInterop": true, + "module": "esnext", + "moduleResolution": "bundler", + "resolveJsonModule": true, + "isolatedModules": true, + "jsx": "preserve", + "incremental": true, + "plugins": [ + { + "name": "next" + } + ], + "paths": { + "@/*": ["./src/*"] + } + }, + "include": ["next-env.d.ts", "**/*.ts", "**/*.tsx", ".next/types/**/*.ts"], + "exclude": ["node_modules"] +} From 44ddc9edd0503638c812d71573de7c0d70acf470 Mon Sep 17 00:00:00 2001 From: Kyler-Chiago Date: Wed, 16 Oct 2024 19:39:24 -0700 Subject: [PATCH 160/357] new site branch --- mlflow-site/Home.jsx | 0 mlflow-site/NavBar.jsx | 33 +++++++++++++++++++++++++++++++++ 2 files changed, 33 insertions(+) create mode 100644 mlflow-site/Home.jsx create mode 100644 mlflow-site/NavBar.jsx diff --git a/mlflow-site/Home.jsx b/mlflow-site/Home.jsx new file mode 100644 index 00000000..e69de29b diff --git a/mlflow-site/NavBar.jsx b/mlflow-site/NavBar.jsx new file mode 100644 index 00000000..dda47ea2 --- /dev/null +++ b/mlflow-site/NavBar.jsx @@ -0,0 +1,33 @@ +import { useRef } from "react" + + +const NavBar = () => { + const myRef = useRef(null); + return ( +
+
+ MLflow.js +
+
+ + + + + + + + + + +
+
+ ) +} \ No newline at end of file From 49cdae715eb238c1094699ae715638059b806222 Mon Sep 17 00:00:00 2001 From: Kyler-Chiago Date: Thu, 17 Oct 2024 02:17:46 -0700 Subject: [PATCH 161/357] oops worked in dev --- mlflow-site/src/app/components/Button.tsx | 7 ++ mlflow-site/src/app/components/Demo.tsx | 20 +++ mlflow-site/src/app/components/DemoCard.tsx | 0 .../src/app/components/FeatureCard.tsx | 12 ++ mlflow-site/src/app/components/Features.tsx | 13 ++ mlflow-site/src/app/components/Headline.tsx | 13 ++ mlflow-site/src/app/components/NavBar.tsx | 7 ++ mlflow-site/src/app/components/Team.tsx | 56 +++++++++ mlflow-site/src/app/components/TeamCard.tsx | 30 +++++ mlflow-site/src/app/globals.css | 117 ++++++++++++++++++ mlflow-site/src/app/layout.tsx | 2 +- mlflow-site/src/app/page.tsx | 108 +++------------- mlflow-site/src/assets/imageNotFound.jpg | Bin 0 -> 10853 bytes .../assets/imageNotFound.jpg:Zone.Identifier | 4 + 14 files changed, 294 insertions(+), 95 deletions(-) create mode 100644 mlflow-site/src/app/components/Button.tsx create mode 100644 mlflow-site/src/app/components/Demo.tsx create mode 100644 mlflow-site/src/app/components/DemoCard.tsx create mode 100644 mlflow-site/src/app/components/FeatureCard.tsx create mode 100644 mlflow-site/src/app/components/Features.tsx create mode 100644 mlflow-site/src/app/components/Headline.tsx create mode 100644 mlflow-site/src/app/components/NavBar.tsx create mode 100644 mlflow-site/src/app/components/Team.tsx create mode 100644 mlflow-site/src/app/components/TeamCard.tsx create mode 100644 mlflow-site/src/assets/imageNotFound.jpg create mode 100644 mlflow-site/src/assets/imageNotFound.jpg:Zone.Identifier diff --git a/mlflow-site/src/app/components/Button.tsx b/mlflow-site/src/app/components/Button.tsx new file mode 100644 index 00000000..d8422c5a --- /dev/null +++ b/mlflow-site/src/app/components/Button.tsx @@ -0,0 +1,7 @@ +const Button = () => { + return ( +
Button
+ ) + } + + export default Button \ No newline at end of file diff --git a/mlflow-site/src/app/components/Demo.tsx b/mlflow-site/src/app/components/Demo.tsx new file mode 100644 index 00000000..4faf4d86 --- /dev/null +++ b/mlflow-site/src/app/components/Demo.tsx @@ -0,0 +1,20 @@ +const Demo = () => { + return ( +
+
+
Img 1
+
Demo 1
+
+
+
Demo 2
+
Img 2
+
+
+
Img 3
+
Demo 3
+
+
+ ); +}; + +export default Demo; diff --git a/mlflow-site/src/app/components/DemoCard.tsx b/mlflow-site/src/app/components/DemoCard.tsx new file mode 100644 index 00000000..e69de29b diff --git a/mlflow-site/src/app/components/FeatureCard.tsx b/mlflow-site/src/app/components/FeatureCard.tsx new file mode 100644 index 00000000..a12b733d --- /dev/null +++ b/mlflow-site/src/app/components/FeatureCard.tsx @@ -0,0 +1,12 @@ +const FeatureCard = () => { + return ( +
+
FeatureCard1
+
FeatureCard2
+
FeatureCard3
+
FeatureCard4
+
+ ); +}; + +export default FeatureCard; diff --git a/mlflow-site/src/app/components/Features.tsx b/mlflow-site/src/app/components/Features.tsx new file mode 100644 index 00000000..55a9c6af --- /dev/null +++ b/mlflow-site/src/app/components/Features.tsx @@ -0,0 +1,13 @@ +import FeatureCard from "./FeatureCard"; + +const Features = () => { + return ( +
+
MLOps in Javascript, made simple.
+
Long blurb
+ +
+ ); +}; + +export default Features; diff --git a/mlflow-site/src/app/components/Headline.tsx b/mlflow-site/src/app/components/Headline.tsx new file mode 100644 index 00000000..79cbbdfe --- /dev/null +++ b/mlflow-site/src/app/components/Headline.tsx @@ -0,0 +1,13 @@ +import Button from './Button'; + +const Headline = () => { + return ( +
+
MLOps workflow for Javascript
+
Harness MLflow's MLOps functionality for your Javascript application with MLflow.js
+
+ ); +}; + +export default Headline; diff --git a/mlflow-site/src/app/components/NavBar.tsx b/mlflow-site/src/app/components/NavBar.tsx new file mode 100644 index 00000000..64955b63 --- /dev/null +++ b/mlflow-site/src/app/components/NavBar.tsx @@ -0,0 +1,7 @@ +const NavBar = () => { + return ( +
NavBar
+ ) +} + +export default NavBar \ No newline at end of file diff --git a/mlflow-site/src/app/components/Team.tsx b/mlflow-site/src/app/components/Team.tsx new file mode 100644 index 00000000..b740a7d6 --- /dev/null +++ b/mlflow-site/src/app/components/Team.tsx @@ -0,0 +1,56 @@ +import TeamCard from './TeamCard'; + +const Team = () => { + const teamArray = [ + { + name: 'Yiqun Zheng', + github: 'https://github.com/yiqunzheng', + email: 'yiqun.zhengfamily@gmail.com', + linkedIn: 'https://www.linkedin.com/in/yiqunzheng/', + }, + { + name: 'Kyler Chiago', + github: 'https://github.com/Kyler-Chiago', + email: 'kchiago50@gmail.com', + linkedIn: 'https://www.linkedin.com/in/kyler-chiago/', + }, + { + name: 'Austin Fraser', + github: 'https://github.com/austinbfraser', + email: 'austinbfraser@gmail.com', + linkedIn: 'http://www.linkedin.com/in/austin-fraser', + }, + { + name: 'Stephany Ho', + github: 'https://github.com/seneyu/', + email: 'shohk39@gmail.com', + linkedIn: 'https://www.linkedin.com/in/stephanyho/', + }, + { + name: 'Winston Ludlam', + github: 'https://github.com/winjolu/', + email: 'winjolu@gmail.com', + linkedIn: 'https://www.linkedin.com/in/wjludlam/', + }, + ]; + + return ( +
+
Meet the team
+
+ {teamArray.map((member, index) => ( + + ))} +
+
+ ); +}; + +export default Team; + diff --git a/mlflow-site/src/app/components/TeamCard.tsx b/mlflow-site/src/app/components/TeamCard.tsx new file mode 100644 index 00000000..87585f8d --- /dev/null +++ b/mlflow-site/src/app/components/TeamCard.tsx @@ -0,0 +1,30 @@ +// import React from 'react'; +import imageNotFound from '../../assets/imageNotFound.jpg' + +interface TeamCardProps { + name: string; + github: string; + email: string; + linkedIn: string; +} + +const TeamCard: React.FC = ({ + name, + github, + email, + linkedIn, +}) => { + return ( +
+ Img not found +
{name}
+
+ G + E + L +
+
+ ); +}; + +export default TeamCard; diff --git a/mlflow-site/src/app/globals.css b/mlflow-site/src/app/globals.css index 13d40b89..a604c7aa 100644 --- a/mlflow-site/src/app/globals.css +++ b/mlflow-site/src/app/globals.css @@ -25,3 +25,120 @@ body { text-wrap: balance; } } + +.fullScreen { + position: fixed; + width: 100%; + height: 100%; + left: 0; + top: 0; +} + +.wrapper { + position:absolute; + background: rgb(51, 51, 58); + width: 100%; + height: 100%; + display: grid; + grid-template-columns: 10px 1fr 360px 1fr 10px; + grid-template-rows: 10px 1fr 10px; +} + +.mobileWrapper { + background: rgb(255, 255, 255); + width: 100%; + height: 100%; + grid-column: 3; + grid-row: 2; + display: grid; + grid-template-columns: 10px 20px 1fr 20px 10px; + grid-template-rows: 20px 50px 1fr 250px 20px; +} + +.navBar { + grid-column: 2/5; + grid-row: 2; + width: 100%; + height: 100%; + background-color: #0a0a0a; +} + +.mobileInnerWrapper { + grid-column: 3; + grid-row: 3; + width: 100%; + height: 100%; + background-color: aqua; +} + +.team { + grid-column: 2/5; + grid-row: 4; + width: 100%; + height: fit-content; + background-color: yellow; + display: flex; + justify-content: center; + align-items: center; + flex-direction: column; +} + +.home { + grid-column: 2/5; + grid-row: 3; + width: 100%; + background-color: rgb(102, 102, 54); +} + +.button { + width: 100%; + background-color: rgb(14, 69, 129); +} + +.features { + grid-column: 2/5; + grid-row: 3; + width: 100%; + background-color: rgb(176, 47, 107); +} + +.featureCard { + width: 100%; + background-color: rgb(122, 144, 167); + display: grid; + grid-template-columns: 50% 50%; + grid-template-rows: 50% 50%; +} + +.demo { + grid-column: 2/5; + grid-row: 3; + width: 100%; + background-color: rgb(47, 176, 101); + display: grid; + grid-template-columns: 100%; + grid-template-rows: calc(100%/3) calc(100%/3) calc(100%/3); +} + +.demoSplit { + width: 100%; + display: grid; + grid-template-columns: 50% 50%; + grid-template-rows: 100%; +} + +.teamCards { + width: 100%; + display: grid; + grid-template-columns: 50% 50%; + grid-template-rows: repeat(calc(100%/3), 3); + /* border: #0a0a0a; */ + background-color: red; +} + +.teamcard { + display: flex; + flex-direction: column; + justify-content: center; + align-items: center; +} \ No newline at end of file diff --git a/mlflow-site/src/app/layout.tsx b/mlflow-site/src/app/layout.tsx index a36cde01..3f975de8 100644 --- a/mlflow-site/src/app/layout.tsx +++ b/mlflow-site/src/app/layout.tsx @@ -26,7 +26,7 @@ export default function RootLayout({ return ( {children} diff --git a/mlflow-site/src/app/page.tsx b/mlflow-site/src/app/page.tsx index f0832dd2..e6b7eb2a 100644 --- a/mlflow-site/src/app/page.tsx +++ b/mlflow-site/src/app/page.tsx @@ -1,101 +1,21 @@ -import Image from 'next/image'; +import NavBar from './components/NavBar'; +import Team from './components/Team'; +import Headline from './components/Headline'; +import Features from './components/Features'; +import Demo from './components/Demo'; export default function Home() { return ( -
-
- Next.js logo -
    -
  1. - Get started by editing{' '} - - src/app/page.tsx - - . -
  2. -
  3. Save and see your changes instantly.
  4. -
- -
- + +
); } diff --git a/mlflow-site/src/assets/imageNotFound.jpg b/mlflow-site/src/assets/imageNotFound.jpg new file mode 100644 index 0000000000000000000000000000000000000000..e00f52074b9844ccc9b752beb0d120ad1aea883f GIT binary patch literal 10853 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 literal 0 HcmV?d00001 diff --git a/mlflow-site/src/assets/imageNotFound.jpg:Zone.Identifier b/mlflow-site/src/assets/imageNotFound.jpg:Zone.Identifier new file mode 100644 index 00000000..bf78e7a7 --- /dev/null +++ b/mlflow-site/src/assets/imageNotFound.jpg:Zone.Identifier @@ -0,0 +1,4 @@ +[ZoneTransfer] +ZoneId=3 +ReferrerUrl=https://media.istockphoto.com/id/1409329028/vector/no-picture-available-placeholder-thumbnail-icon-illustration-design.jpg?s=612x612&w=0&k=20&c=_zOuJu755g2eEUioiOUdz_mHKJQJn-tDgIAhQzyeKUQ= +HostUrl=https://media.istockphoto.com/id/1409329028/vector/no-picture-available-placeholder-thumbnail-icon-illustration-design.jpg?s=612x612&w=0&k=20&c=_zOuJu755g2eEUioiOUdz_mHKJQJn-tDgIAhQzyeKUQ= From 003b2525472096eedc46f81d3a651fc3d9e4ab90 Mon Sep 17 00:00:00 2001 From: Kyler-Chiago Date: Thu, 17 Oct 2024 02:31:26 -0700 Subject: [PATCH 162/357] basic website --- mlflow-site/src/app/components/NavBar.tsx | 18 +++++++++--- mlflow-site/src/app/globals.css | 34 +++++++++++++++++++++++ 2 files changed, 48 insertions(+), 4 deletions(-) diff --git a/mlflow-site/src/app/components/NavBar.tsx b/mlflow-site/src/app/components/NavBar.tsx index 64955b63..448cb56f 100644 --- a/mlflow-site/src/app/components/NavBar.tsx +++ b/mlflow-site/src/app/components/NavBar.tsx @@ -1,7 +1,17 @@ const NavBar = () => { return ( -
NavBar
- ) -} +
+
MLflow.js
+
+
Home
+
Features
+
Demo
+
Team
+
G
+
L
+
+
+ ); +}; -export default NavBar \ No newline at end of file +export default NavBar; diff --git a/mlflow-site/src/app/globals.css b/mlflow-site/src/app/globals.css index a604c7aa..23d327d6 100644 --- a/mlflow-site/src/app/globals.css +++ b/mlflow-site/src/app/globals.css @@ -18,6 +18,7 @@ body { color: var(--foreground); background: var(--background); font-family: Arial, Helvetica, sans-serif; + font-size: 14px; } @layer utilities { @@ -61,6 +62,39 @@ body { width: 100%; height: 100%; background-color: #0a0a0a; + display: grid; + grid-template-columns: auto auto; + grid-template-rows: 100%; +} + +.navBarLinks { + grid-column: 2; + grid-row: 1; + width: 100%; + height: 100%; + display: grid; + grid-template-columns: repeat(calc(100%/6), 6); + grid-template-rows: 100%; +} + +.navBarLinksFeatures { + grid-column: 2; +} + +.navBarLinksDemo { + grid-column: 3; +} + +.navBarLinksTeam { + grid-column: 4; +} + +.navBarLinksGithub { + grid-column: 5; +} + +.navBarLinksLinkedIn { + grid-column: 6; } .mobileInnerWrapper { From 264f63785a38b52b84435d335b8cc6bdd4c858c2 Mon Sep 17 00:00:00 2001 From: Kyler-Chiago Date: Thu, 17 Oct 2024 02:36:01 -0700 Subject: [PATCH 163/357] basic site --- mlflow-site/src/app/globals.css | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/mlflow-site/src/app/globals.css b/mlflow-site/src/app/globals.css index 23d327d6..d255c8be 100644 --- a/mlflow-site/src/app/globals.css +++ b/mlflow-site/src/app/globals.css @@ -41,16 +41,16 @@ body { width: 100%; height: 100%; display: grid; - grid-template-columns: 10px 1fr 360px 1fr 10px; - grid-template-rows: 10px 1fr 10px; + grid-template-columns: 1fr 360px 1fr; + grid-template-rows: 1fr; } .mobileWrapper { background: rgb(255, 255, 255); width: 100%; height: 100%; - grid-column: 3; - grid-row: 2; + grid-column: 2; + grid-row: 1; display: grid; grid-template-columns: 10px 20px 1fr 20px 10px; grid-template-rows: 20px 50px 1fr 250px 20px; From 594fbb7b8060d7cbb40ca19dabe75da14ea23fbc Mon Sep 17 00:00:00 2001 From: Kyler-Chiago Date: Thu, 17 Oct 2024 02:38:24 -0700 Subject: [PATCH 164/357] basic site --- mlflow-site/src/app/globals.css | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mlflow-site/src/app/globals.css b/mlflow-site/src/app/globals.css index d255c8be..6fd7c1bb 100644 --- a/mlflow-site/src/app/globals.css +++ b/mlflow-site/src/app/globals.css @@ -53,7 +53,7 @@ body { grid-row: 1; display: grid; grid-template-columns: 10px 20px 1fr 20px 10px; - grid-template-rows: 20px 50px 1fr 250px 20px; + grid-template-rows: 20px 50px 1fr min-content 20px; } .navBar { From cefec1bafab3bb2aeec45b7bc7beba77868565f7 Mon Sep 17 00:00:00 2001 From: Kyler-Chiago Date: Thu, 17 Oct 2024 02:44:04 -0700 Subject: [PATCH 165/357] basic site --- mlflow-site/src/app/globals.css | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/mlflow-site/src/app/globals.css b/mlflow-site/src/app/globals.css index 6fd7c1bb..a762b785 100644 --- a/mlflow-site/src/app/globals.css +++ b/mlflow-site/src/app/globals.css @@ -18,7 +18,7 @@ body { color: var(--foreground); background: var(--background); font-family: Arial, Helvetica, sans-serif; - font-size: 14px; + font-size: 1rem; } @layer utilities { @@ -52,8 +52,8 @@ body { grid-column: 2; grid-row: 1; display: grid; - grid-template-columns: 10px 20px 1fr 20px 10px; - grid-template-rows: 20px 50px 1fr min-content 20px; + grid-template-columns: 0.7rem 1.3rem 1fr 1.3rem 0.7rem; + grid-template-rows: 1.3rem 2.8rem 1fr min-content 1.3rem; } .navBar { From 861f017dcbf62efecb05aee6806acb2cc3b8b757 Mon Sep 17 00:00:00 2001 From: Kyler-Chiago Date: Thu, 17 Oct 2024 18:01:08 -0700 Subject: [PATCH 166/357] made some things single row --- mlflow-site/src/app/components/FeatureCard.tsx | 2 +- mlflow-site/src/app/components/TeamCard.tsx | 3 ++- mlflow-site/src/app/globals.css | 17 +++++++++++++---- 3 files changed, 16 insertions(+), 6 deletions(-) diff --git a/mlflow-site/src/app/components/FeatureCard.tsx b/mlflow-site/src/app/components/FeatureCard.tsx index a12b733d..01ee70f8 100644 --- a/mlflow-site/src/app/components/FeatureCard.tsx +++ b/mlflow-site/src/app/components/FeatureCard.tsx @@ -1,7 +1,7 @@ const FeatureCard = () => { return (
-
FeatureCard1
+
FeatureCard1 hello how are you doing?
FeatureCard2
FeatureCard3
FeatureCard4
diff --git a/mlflow-site/src/app/components/TeamCard.tsx b/mlflow-site/src/app/components/TeamCard.tsx index 87585f8d..72785b72 100644 --- a/mlflow-site/src/app/components/TeamCard.tsx +++ b/mlflow-site/src/app/components/TeamCard.tsx @@ -16,7 +16,8 @@ const TeamCard: React.FC = ({ }) => { return (
- Img not found + {/*
*/} + Miss
{name}
G diff --git a/mlflow-site/src/app/globals.css b/mlflow-site/src/app/globals.css index a762b785..8d4de289 100644 --- a/mlflow-site/src/app/globals.css +++ b/mlflow-site/src/app/globals.css @@ -43,6 +43,7 @@ body { display: grid; grid-template-columns: 1fr 360px 1fr; grid-template-rows: 1fr; + overflow-y: auto; } .mobileWrapper { @@ -134,14 +135,17 @@ body { grid-row: 3; width: 100%; background-color: rgb(176, 47, 107); + display: grid; + place-items: center; } .featureCard { width: 100%; background-color: rgb(122, 144, 167); display: grid; - grid-template-columns: 50% 50%; - grid-template-rows: 50% 50%; + grid-template-columns: 100%; + grid-template-rows: min-content; + text-align: center; } .demo { @@ -157,8 +161,8 @@ body { .demoSplit { width: 100%; display: grid; - grid-template-columns: 50% 50%; - grid-template-rows: 100%; + grid-template-columns: 100%; + grid-template-rows: min-content; } .teamCards { @@ -175,4 +179,9 @@ body { flex-direction: column; justify-content: center; align-items: center; +} + +.teamCardImg { + width: 50px; + height: 50px; } \ No newline at end of file From b3eb3523224d6dcc8e45494f957ab9aed99ff6d6 Mon Sep 17 00:00:00 2001 From: Kyler-Chiago Date: Thu, 17 Oct 2024 18:07:17 -0700 Subject: [PATCH 167/357] added scroll and custom scrollbar --- mlflow-site/src/app/globals.css | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/mlflow-site/src/app/globals.css b/mlflow-site/src/app/globals.css index 8d4de289..a3599074 100644 --- a/mlflow-site/src/app/globals.css +++ b/mlflow-site/src/app/globals.css @@ -46,6 +46,26 @@ body { overflow-y: auto; } +::-webkit-scrollbar { + height: 10px; + width: 10px; +} + +/* Track */ +::-webkit-scrollbar-track { + background: #262626; +} + +/* Handle */ +::-webkit-scrollbar-thumb { + background: #3c3c3c; +} + +/* Handle on hover */ +::-webkit-scrollbar-thumb:hover { + background: #1b1b1b; +} + .mobileWrapper { background: rgb(255, 255, 255); width: 100%; From 6d064de8cc6151e44a8eabcf5c6acb5529667f53 Mon Sep 17 00:00:00 2001 From: Kyler-Chiago Date: Thu, 17 Oct 2024 18:20:34 -0700 Subject: [PATCH 168/357] deleted jsx --- mlflow-site/Home.jsx | 0 mlflow-site/NavBar.jsx | 33 --------------------- mlflow-site/src/app/components/TeamCard.tsx | 3 ++ 3 files changed, 3 insertions(+), 33 deletions(-) delete mode 100644 mlflow-site/Home.jsx delete mode 100644 mlflow-site/NavBar.jsx diff --git a/mlflow-site/Home.jsx b/mlflow-site/Home.jsx deleted file mode 100644 index e69de29b..00000000 diff --git a/mlflow-site/NavBar.jsx b/mlflow-site/NavBar.jsx deleted file mode 100644 index dda47ea2..00000000 --- a/mlflow-site/NavBar.jsx +++ /dev/null @@ -1,33 +0,0 @@ -import { useRef } from "react" - - -const NavBar = () => { - const myRef = useRef(null); - return ( -
-
- MLflow.js -
-
- - - - - - - - - - -
-
- ) -} \ No newline at end of file diff --git a/mlflow-site/src/app/components/TeamCard.tsx b/mlflow-site/src/app/components/TeamCard.tsx index 72785b72..84f4c2f7 100644 --- a/mlflow-site/src/app/components/TeamCard.tsx +++ b/mlflow-site/src/app/components/TeamCard.tsx @@ -7,6 +7,8 @@ interface TeamCardProps { email: string; linkedIn: string; } +// declare function require(path: string); +// const kittenHeader = require('../images/kitten-header.jpg'); const TeamCard: React.FC = ({ name, @@ -18,6 +20,7 @@ const TeamCard: React.FC = ({
{/*
*/} Miss + {/* Test */}
{name}
G From fa391fd3be834b0a50265f9e5349ff90e8251f6d Mon Sep 17 00:00:00 2001 From: Kyler-Chiago Date: Thu, 17 Oct 2024 18:21:54 -0700 Subject: [PATCH 169/357] removed data --- mlflow-site/src/app/components/Team.tsx | 6 ------ mlflow-site/src/app/components/TeamCard.tsx | 3 --- 2 files changed, 9 deletions(-) diff --git a/mlflow-site/src/app/components/Team.tsx b/mlflow-site/src/app/components/Team.tsx index b740a7d6..e8687aba 100644 --- a/mlflow-site/src/app/components/Team.tsx +++ b/mlflow-site/src/app/components/Team.tsx @@ -5,31 +5,26 @@ const Team = () => { { name: 'Yiqun Zheng', github: 'https://github.com/yiqunzheng', - email: 'yiqun.zhengfamily@gmail.com', linkedIn: 'https://www.linkedin.com/in/yiqunzheng/', }, { name: 'Kyler Chiago', github: 'https://github.com/Kyler-Chiago', - email: 'kchiago50@gmail.com', linkedIn: 'https://www.linkedin.com/in/kyler-chiago/', }, { name: 'Austin Fraser', github: 'https://github.com/austinbfraser', - email: 'austinbfraser@gmail.com', linkedIn: 'http://www.linkedin.com/in/austin-fraser', }, { name: 'Stephany Ho', github: 'https://github.com/seneyu/', - email: 'shohk39@gmail.com', linkedIn: 'https://www.linkedin.com/in/stephanyho/', }, { name: 'Winston Ludlam', github: 'https://github.com/winjolu/', - email: 'winjolu@gmail.com', linkedIn: 'https://www.linkedin.com/in/wjludlam/', }, ]; @@ -43,7 +38,6 @@ const Team = () => { key={index} name={member.name} github={member.github} - email={member.email} linkedIn={member.linkedIn} /> ))} diff --git a/mlflow-site/src/app/components/TeamCard.tsx b/mlflow-site/src/app/components/TeamCard.tsx index 84f4c2f7..ba83dbf0 100644 --- a/mlflow-site/src/app/components/TeamCard.tsx +++ b/mlflow-site/src/app/components/TeamCard.tsx @@ -4,7 +4,6 @@ import imageNotFound from '../../assets/imageNotFound.jpg' interface TeamCardProps { name: string; github: string; - email: string; linkedIn: string; } // declare function require(path: string); @@ -13,7 +12,6 @@ interface TeamCardProps { const TeamCard: React.FC = ({ name, github, - email, linkedIn, }) => { return ( @@ -24,7 +22,6 @@ const TeamCard: React.FC = ({
{name}
From 83a9e9d0c6c9fa58fcf01347d36d78c8734799f2 Mon Sep 17 00:00:00 2001 From: Kyler-Chiago Date: Thu, 17 Oct 2024 18:22:50 -0700 Subject: [PATCH 170/357] removed comments --- mlflow-site/src/app/components/TeamCard.tsx | 3 --- 1 file changed, 3 deletions(-) diff --git a/mlflow-site/src/app/components/TeamCard.tsx b/mlflow-site/src/app/components/TeamCard.tsx index ba83dbf0..51916286 100644 --- a/mlflow-site/src/app/components/TeamCard.tsx +++ b/mlflow-site/src/app/components/TeamCard.tsx @@ -1,4 +1,3 @@ -// import React from 'react'; import imageNotFound from '../../assets/imageNotFound.jpg' interface TeamCardProps { @@ -6,8 +5,6 @@ interface TeamCardProps { github: string; linkedIn: string; } -// declare function require(path: string); -// const kittenHeader = require('../images/kitten-header.jpg'); const TeamCard: React.FC = ({ name, From 5ac4b3ff3e40b83e13f35f4069ba3508383f9c46 Mon Sep 17 00:00:00 2001 From: Kyler-Chiago Date: Thu, 17 Oct 2024 18:23:27 -0700 Subject: [PATCH 171/357] removed identifier --- mlflow-site/src/assets/imageNotFound.jpg:Zone.Identifier | 4 ---- 1 file changed, 4 deletions(-) delete mode 100644 mlflow-site/src/assets/imageNotFound.jpg:Zone.Identifier diff --git a/mlflow-site/src/assets/imageNotFound.jpg:Zone.Identifier b/mlflow-site/src/assets/imageNotFound.jpg:Zone.Identifier deleted file mode 100644 index bf78e7a7..00000000 --- a/mlflow-site/src/assets/imageNotFound.jpg:Zone.Identifier +++ /dev/null @@ -1,4 +0,0 @@ -[ZoneTransfer] -ZoneId=3 -ReferrerUrl=https://media.istockphoto.com/id/1409329028/vector/no-picture-available-placeholder-thumbnail-icon-illustration-design.jpg?s=612x612&w=0&k=20&c=_zOuJu755g2eEUioiOUdz_mHKJQJn-tDgIAhQzyeKUQ= -HostUrl=https://media.istockphoto.com/id/1409329028/vector/no-picture-available-placeholder-thumbnail-icon-illustration-design.jpg?s=612x612&w=0&k=20&c=_zOuJu755g2eEUioiOUdz_mHKJQJn-tDgIAhQzyeKUQ= From 0ea22d68ea568623f0a7c1ab6bff7cdf65ff0543 Mon Sep 17 00:00:00 2001 From: Austin Fraser Date: Thu, 17 Oct 2024 18:40:27 -0700 Subject: [PATCH 172/357] updated gitignore --- mlflow-site/.gitignore | 1 + 1 file changed, 1 insertion(+) diff --git a/mlflow-site/.gitignore b/mlflow-site/.gitignore index fd3dbb57..10c81238 100644 --- a/mlflow-site/.gitignore +++ b/mlflow-site/.gitignore @@ -18,6 +18,7 @@ # misc .DS_Store +../.DS_Store *.pem # debug From e60babc18166590c85e5a8297355f0f88e8f49f0 Mon Sep 17 00:00:00 2001 From: Austin Fraser Date: Thu, 17 Oct 2024 18:42:16 -0700 Subject: [PATCH 173/357] updated gitignore --- mlflow/.gitignore | 1 + 1 file changed, 1 insertion(+) diff --git a/mlflow/.gitignore b/mlflow/.gitignore index 845fa117..cc86d1b2 100644 --- a/mlflow/.gitignore +++ b/mlflow/.gitignore @@ -3,6 +3,7 @@ node_modules/ # Misc .DS_Store +../.DS_Store # Python / MLflow specific .venv/ From d3c4995e3823dfd36cffe3f36a1e1b6ada4a4ce3 Mon Sep 17 00:00:00 2001 From: Kyler-Chiago Date: Thu, 17 Oct 2024 19:37:06 -0700 Subject: [PATCH 174/357] before changing assets location --- mlflow-site/src/app/components/Headline.tsx | 2 +- mlflow-site/src/app/components/NavBar.tsx | 21 ++++++++++++++--- mlflow-site/src/app/globals.css | 24 ++++++++++++++++---- mlflow-site/src/assets/Github_logo.png | Bin 0 -> 4701 bytes mlflow-site/src/assets/LinkedIn_logo.png | Bin 0 -> 13517 bytes 5 files changed, 38 insertions(+), 9 deletions(-) create mode 100644 mlflow-site/src/assets/Github_logo.png create mode 100644 mlflow-site/src/assets/LinkedIn_logo.png diff --git a/mlflow-site/src/app/components/Headline.tsx b/mlflow-site/src/app/components/Headline.tsx index 79cbbdfe..fadef0c5 100644 --- a/mlflow-site/src/app/components/Headline.tsx +++ b/mlflow-site/src/app/components/Headline.tsx @@ -3,7 +3,7 @@ import Button from './Button'; const Headline = () => { return (
-
MLOps workflow for Javascript
+
MLOps workflow for Javascript
Harness MLflow's MLOps functionality for your Javascript application with MLflow.js
diff --git a/mlflow-site/src/app/components/NavBar.tsx b/mlflow-site/src/app/components/NavBar.tsx index 448cb56f..83525df2 100644 --- a/mlflow-site/src/app/components/NavBar.tsx +++ b/mlflow-site/src/app/components/NavBar.tsx @@ -1,14 +1,29 @@ +import Image from 'next/image' + const NavBar = () => { return (
-
MLflow.js
+
MLflow.js
Home
Features
Demo
Team
-
G
-
L
+ + {/* G */} + M + + + L +
); diff --git a/mlflow-site/src/app/globals.css b/mlflow-site/src/app/globals.css index a3599074..4aae4b9f 100644 --- a/mlflow-site/src/app/globals.css +++ b/mlflow-site/src/app/globals.css @@ -2,7 +2,7 @@ @tailwind components; @tailwind utilities; -:root { +/* :root { --background: #ffffff; --foreground: #171717; } @@ -12,13 +12,14 @@ --background: #0a0a0a; --foreground: #ededed; } -} +} */ body { color: var(--foreground); background: var(--background); - font-family: Arial, Helvetica, sans-serif; + font-family: Inter; font-size: 1rem; + color: rgb(0, 0, 0); } @layer utilities { @@ -74,7 +75,7 @@ body { grid-row: 1; display: grid; grid-template-columns: 0.7rem 1.3rem 1fr 1.3rem 0.7rem; - grid-template-rows: 1.3rem 2.8rem 1fr min-content 1.3rem; + grid-template-rows: 1.3rem min-content 1fr min-content 1.3rem; } .navBar { @@ -82,10 +83,11 @@ body { grid-row: 2; width: 100%; height: 100%; - background-color: #0a0a0a; + background-color: #7e7e7e; display: grid; grid-template-columns: auto auto; grid-template-rows: 100%; + /* text-align: center; */ } .navBarLinks { @@ -96,6 +98,7 @@ body { display: grid; grid-template-columns: repeat(calc(100%/6), 6); grid-template-rows: 100%; + align-items: center; } .navBarLinksFeatures { @@ -118,6 +121,17 @@ body { grid-column: 6; } +.navBarMlflow { + color: rgb(66, 107, 31); + font-size: 1.2rem; + font-family: Newsreader; +} + +.bigHeadline { + font-size: 1.7rem; + font-family: Newsreader; +} + .mobileInnerWrapper { grid-column: 3; grid-row: 3; diff --git a/mlflow-site/src/assets/Github_logo.png b/mlflow-site/src/assets/Github_logo.png new file mode 100644 index 0000000000000000000000000000000000000000..e7605b02fcf0bb4f1e34aa9effb7faa82bcc1696 GIT binary patch literal 4701 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 literal 0 HcmV?d00001 From bdad7a2c23be01052b6e8cd7003c96bc8f1b62b1 Mon Sep 17 00:00:00 2001 From: Kyler-Chiago Date: Thu, 17 Oct 2024 20:24:00 -0700 Subject: [PATCH 175/357] navbar set up and some of home --- mlflow-site/src/app/assets/GithubLogo.png | Bin 0 -> 7876 bytes mlflow-site/src/app/assets/LinkedInLogo.png | Bin 0 -> 14584 bytes .../src/{ => app}/assets/imageNotFound.jpg | Bin mlflow-site/src/app/components/Demo.tsx | 2 +- mlflow-site/src/app/components/Features.tsx | 2 +- mlflow-site/src/app/components/Headline.tsx | 2 +- mlflow-site/src/app/components/NavBar.tsx | 54 +++++++++++++----- mlflow-site/src/app/components/Team.tsx | 2 +- mlflow-site/src/app/components/TeamCard.tsx | 4 +- mlflow-site/src/app/globals.css | 8 ++- mlflow-site/src/assets/Github_logo.png | Bin 4701 -> 0 bytes mlflow-site/src/assets/LinkedIn_logo.png | Bin 13517 -> 0 bytes 12 files changed, 52 insertions(+), 22 deletions(-) create mode 100644 mlflow-site/src/app/assets/GithubLogo.png create mode 100644 mlflow-site/src/app/assets/LinkedInLogo.png rename mlflow-site/src/{ => app}/assets/imageNotFound.jpg (100%) delete mode 100644 mlflow-site/src/assets/Github_logo.png delete mode 100644 mlflow-site/src/assets/LinkedIn_logo.png diff --git a/mlflow-site/src/app/assets/GithubLogo.png b/mlflow-site/src/app/assets/GithubLogo.png new file mode 100644 index 0000000000000000000000000000000000000000..157ec02ec5a9970c412b78f7342b4179b90538c8 GIT binary patch literal 7876 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 literal 0 HcmV?d00001 diff --git a/mlflow-site/src/assets/imageNotFound.jpg b/mlflow-site/src/app/assets/imageNotFound.jpg similarity index 100% rename from mlflow-site/src/assets/imageNotFound.jpg rename to mlflow-site/src/app/assets/imageNotFound.jpg diff --git a/mlflow-site/src/app/components/Demo.tsx b/mlflow-site/src/app/components/Demo.tsx index 4faf4d86..026f3518 100644 --- a/mlflow-site/src/app/components/Demo.tsx +++ b/mlflow-site/src/app/components/Demo.tsx @@ -1,6 +1,6 @@ const Demo = () => { return ( -
+
Img 1
Demo 1
diff --git a/mlflow-site/src/app/components/Features.tsx b/mlflow-site/src/app/components/Features.tsx index 55a9c6af..608c386f 100644 --- a/mlflow-site/src/app/components/Features.tsx +++ b/mlflow-site/src/app/components/Features.tsx @@ -2,7 +2,7 @@ import FeatureCard from "./FeatureCard"; const Features = () => { return ( -
+
MLOps in Javascript, made simple.
Long blurb
diff --git a/mlflow-site/src/app/components/Headline.tsx b/mlflow-site/src/app/components/Headline.tsx index fadef0c5..85968a2a 100644 --- a/mlflow-site/src/app/components/Headline.tsx +++ b/mlflow-site/src/app/components/Headline.tsx @@ -2,7 +2,7 @@ import Button from './Button'; const Headline = () => { return ( -
+
diff --git a/mlflow-site/src/app/components/Team.tsx b/mlflow-site/src/app/components/Team.tsx index e8687aba..ef18d083 100644 --- a/mlflow-site/src/app/components/Team.tsx +++ b/mlflow-site/src/app/components/Team.tsx @@ -30,7 +30,7 @@ const Team = () => { ]; return ( -
+
Meet the team
{teamArray.map((member, index) => ( diff --git a/mlflow-site/src/app/components/TeamCard.tsx b/mlflow-site/src/app/components/TeamCard.tsx index 51916286..26bf83e8 100644 --- a/mlflow-site/src/app/components/TeamCard.tsx +++ b/mlflow-site/src/app/components/TeamCard.tsx @@ -1,4 +1,4 @@ -import imageNotFound from '../../assets/imageNotFound.jpg' +// import imageNotFound from '/../..//assets/imageNotFound.jpg' interface TeamCardProps { name: string; @@ -14,7 +14,7 @@ const TeamCard: React.FC = ({ return (
{/*
*/} - Miss + {/* Miss */} {/* Test */}
{name}
diff --git a/mlflow-site/src/app/globals.css b/mlflow-site/src/app/globals.css index 4aae4b9f..ae52d554 100644 --- a/mlflow-site/src/app/globals.css +++ b/mlflow-site/src/app/globals.css @@ -83,11 +83,10 @@ body { grid-row: 2; width: 100%; height: 100%; - background-color: #7e7e7e; + /* background-color: #7e7e7e; */ display: grid; grid-template-columns: auto auto; grid-template-rows: 100%; - /* text-align: center; */ } .navBarLinks { @@ -125,6 +124,8 @@ body { color: rgb(66, 107, 31); font-size: 1.2rem; font-family: Newsreader; + display: flex; + align-items: center; } .bigHeadline { @@ -153,10 +154,11 @@ body { } .home { + margin-top: 0.3rem; grid-column: 2/5; grid-row: 3; width: 100%; - background-color: rgb(102, 102, 54); + /* background-color: rgb(102, 102, 54); */ } .button { diff --git a/mlflow-site/src/assets/Github_logo.png b/mlflow-site/src/assets/Github_logo.png deleted file mode 100644 index e7605b02fcf0bb4f1e34aa9effb7faa82bcc1696..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 4701 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 From b704b6ac6af8e808c4a40a8fd7a846a692949306 Mon Sep 17 00:00:00 2001 From: Kyler-Chiago Date: Thu, 17 Oct 2024 20:52:37 -0700 Subject: [PATCH 176/357] navBar and Home basics done --- mlflow-site/src/app/components/Button.tsx | 31 ++++++++++++++++++----- mlflow-site/src/app/globals.css | 21 +++++++++++++-- 2 files changed, 44 insertions(+), 8 deletions(-) diff --git a/mlflow-site/src/app/components/Button.tsx b/mlflow-site/src/app/components/Button.tsx index d8422c5a..db00ce41 100644 --- a/mlflow-site/src/app/components/Button.tsx +++ b/mlflow-site/src/app/components/Button.tsx @@ -1,7 +1,26 @@ +'use client'; + const Button = () => { - return ( -
Button
- ) - } - - export default Button \ No newline at end of file + return ( +
+ + +
+ ); +}; + +export default Button; diff --git a/mlflow-site/src/app/globals.css b/mlflow-site/src/app/globals.css index ae52d554..0cbb3915 100644 --- a/mlflow-site/src/app/globals.css +++ b/mlflow-site/src/app/globals.css @@ -138,7 +138,7 @@ body { grid-row: 3; width: 100%; height: 100%; - background-color: aqua; + /* background-color: aqua; */ } .team { @@ -161,9 +161,26 @@ body { /* background-color: rgb(102, 102, 54); */ } +.homeButton { + padding: 3px; + padding-left: 6px; + padding-right: 6px; + border-radius: 5px; + font-size: 0.8rem; + margin-right: 8px; +} + +.homeButtonDownload { + background-color: rgb(66, 107, 31); +} + +.homeButtonRead { + background-color: rgb(204, 204, 204); +} + .button { width: 100%; - background-color: rgb(14, 69, 129); + /* background-color: rgb(14, 69, 129); */ } .features { From 35524d82c55dde559406abb0bc7763c1e456572b Mon Sep 17 00:00:00 2001 From: Kyler-Chiago Date: Sat, 19 Oct 2024 09:29:01 -0700 Subject: [PATCH 177/357] updated read the docs link --- mlflow-site/src/app/components/Button.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mlflow-site/src/app/components/Button.tsx b/mlflow-site/src/app/components/Button.tsx index db00ce41..f5fac613 100644 --- a/mlflow-site/src/app/components/Button.tsx +++ b/mlflow-site/src/app/components/Button.tsx @@ -13,7 +13,7 @@ const Button = () => {
); diff --git a/mlflow-site/src/app/globals.css b/mlflow-site/src/app/globals.css index 0cbb3915..3b393519 100644 --- a/mlflow-site/src/app/globals.css +++ b/mlflow-site/src/app/globals.css @@ -95,7 +95,7 @@ body { width: 100%; height: 100%; display: grid; - grid-template-columns: repeat(calc(100%/6), 6); + grid-template-columns: repeat(calc(100%/5), 5); grid-template-rows: 100%; align-items: center; } @@ -116,10 +116,6 @@ body { grid-column: 5; } -.navBarLinksLinkedIn { - grid-column: 6; -} - .navBarMlflow { color: rgb(66, 107, 31); font-size: 1.2rem; From 4373d64948cf124273c2c15a0218f87fdeac87b8 Mon Sep 17 00:00:00 2001 From: Kyler-Chiago Date: Sat, 19 Oct 2024 11:03:37 -0700 Subject: [PATCH 179/357] kyler/siteHomeNavBar --- .../{src/app => public}/assets/GithubLogo.png | Bin .../app => public}/assets/LinkedInLogo.png | Bin .../app => public}/assets/imageNotFound.jpg | Bin mlflow-site/public/assets/kylerpfp.png | Bin 0 -> 818501 bytes mlflow-site/src/app/components/NavBar.tsx | 3 +- mlflow-site/src/app/components/Team.tsx | 25 +++++++++---- mlflow-site/src/app/components/TeamCard.tsx | 33 +++++++++++------- mlflow-site/src/app/globals.css | 24 +++++++++++-- 8 files changed, 62 insertions(+), 23 deletions(-) rename mlflow-site/{src/app => public}/assets/GithubLogo.png (100%) rename mlflow-site/{src/app => public}/assets/LinkedInLogo.png (100%) rename mlflow-site/{src/app => public}/assets/imageNotFound.jpg (100%) create mode 100644 mlflow-site/public/assets/kylerpfp.png diff --git a/mlflow-site/src/app/assets/GithubLogo.png b/mlflow-site/public/assets/GithubLogo.png similarity index 100% rename from mlflow-site/src/app/assets/GithubLogo.png rename to mlflow-site/public/assets/GithubLogo.png diff --git a/mlflow-site/src/app/assets/LinkedInLogo.png b/mlflow-site/public/assets/LinkedInLogo.png similarity index 100% rename from mlflow-site/src/app/assets/LinkedInLogo.png rename to mlflow-site/public/assets/LinkedInLogo.png diff --git a/mlflow-site/src/app/assets/imageNotFound.jpg b/mlflow-site/public/assets/imageNotFound.jpg similarity index 100% rename from mlflow-site/src/app/assets/imageNotFound.jpg rename to mlflow-site/public/assets/imageNotFound.jpg diff --git a/mlflow-site/public/assets/kylerpfp.png b/mlflow-site/public/assets/kylerpfp.png new file mode 100644 index 0000000000000000000000000000000000000000..154bd474f5814aa3b604b44d36615877ae85c17f GIT binary patch literal 818501 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ÐZn6oD1MAHg9_nl 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%0D5%P1XQcA^EY*c!j-$bBM8dNoty^cv&|%OJ@N-mY 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�lj4}<#uW~5WMt`qW(GL)-k2p%cu|w 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%0D%~=T5esSh6j`C6HHXt=ST(X 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%0Ahnch>x>zPiU~P) z92ap4{v_l(=Oy0)kW#`Q4(=#zAac)!ABKF+p&D4u`{R`Igh?hU>Rk zD0Ws0G2H^2g0$zi$WK|wl(&Oh;myrc3Kdi~4h{=fb5?qA;h{C>Mx zCk;c4F+Rt~SvlFNz3|S!!O^6v;kukwZ|y{OqoiIm9u5Z<czEd+xafmUhyq7t->L~Iq zVOzq?-i299W!!||eL}AUJJrRa==u3MP`*0J6nN?sfxD{eo-B`Pbu-0@!8^8Et&Wc$ zJ=h!9DSAU5G+ysCCOgjZmmi<0$EC7@X~BdMV??`}Z#m_db|(Xr$1scfhx7!x;t%fB z!?=LYKD=wO(ro>bZ61!1#(Z(Ofx|IORz#5b9VI%2BgV{p9zh|VN(N`;YCRru8bY5| zG~KcmTJoo5H*RIVJe+++#DtOC1t+IM2p+jp5<_;@Tn?*lUamIvP8YC83b_|Tn9Y&2 z0EKwOhn8K@f?(w`!@q{=xC-i@wG&!)udPPf4zZJDmV%jz^?&;B|NXDOefYP({^f7K zefY3@{P6Jn>)-$Dzdk=4x*iPW^y4Jg8kb8{n|cT2rA59?!Rzt#)qbKDQl&MIIKAQp za+aj7Ww*D$BP_rpA%|w554`*_v-Nt7s4nM6@AFST{S@<6%}{wEgwLNpqi>S^0x?F` zvpmJy?RF%Li~;8wr%y;}q{;Az52;wGW#_l>13!h}y7c3b=N+y1*M;@h0=9JuLJ6L| z&#TqS1@hnj{&xwRJ%cap-wQfa>G%IBWk% zTMsVKLoLTz>)EcKIB@yHZ2fC_Ipc~^D4)+ut!IT4rDj7bgz)o!{~zo1`dtS1)PxZ3 z@9)nXx-fpD==5Unvprs@YPNFBF4w>`Dzx>{st2>q)V$D{YZvXPif4ME{@I_FyYvqU zt?=n@6?t?mgz93iON2!Y*UtO3$K{Ge1@r7p`tz;eTKsvbZKmne-@7Ypz-4d*tp$aVS?j4Qb8)~Bj;m5E}SnAf`Mw|Da{hquQGP37jKFX941{3TN z71I>ylor~B1!vIkf5l zPIy~er^o8y!qYjcti|cC>(4@YBN@d{erQktmMM-++y+Ya+qDXF05aS7I;=!$OZBx>kEkDFg+-$mEJ@F%a)3J)E>%LK_1CQyc^5Q3#rEEgm6Ne84FFalr#VOphJG1RP>%U!p&()bTFDN?BznC8=R$DI(gw&4)(>D2%p3 z<5~{zww$Insfc*zO~n(@h=?SyplV`%J}a4-N;11&Z&OOq;&3_*rkkX)mQK6WX*3-y z_0bd5NHQ_e!)bDx1A4XHZY_yKHI*c1BQmD>`Ep~c-U%GYQ8LbpUn~)VsETSL??Xx{ zc8WEB3u$4R4BLN#g7CH=$8_pW@|+a~&H?p&nUy(lBs(B5YNe~YjTZb&195sx>^!ts z?lhd6h?dl%j_CLDF*cntv-9E+VeHTHZWIZL;XB()6dI}v)(y7P1z;J6^_^dhLE?gf$b}htwdYX4T zVvLYu@WOi!kwwd<`W@;C)%suGe2SFEO$Z4gr-pU#&w;{cJWdlvAiH(2@xvA30~?J> zF6kg$2wez1%TYvAGS%inAOt@ptyxEp5^NaG&YJvCm2O4k**CMk4(eX z-dI994w(p<_FhQ=mqClQ7o-jA6m*p*1@UVIKwAZhl`Cpy&T2Ykv8GvRwWjKs_(REPgO$I<>H0r(eGbKo_!&D{WzMD`(TS1j9~A zcI_|I^Ov{#)^IKU-x>7ws@|9AmXGSV-QZ6g82QY1Y(z@e zYqfIVsb_^AW3+r*VzHJkoM`8{)_JE)O7r8AsZ*wyU;G3#@-fLU&7eG6f0!o7dAG6|~jC4YgUrN_16=C*(TRCM~ zz>6X!DdDS{ZVF5=H9l_wt$B2lQ>Ry7y|r-u3ZQd#-9mZXJaRl9J>9RL4IIo0v@GMN zP#G*AuIfJ|7hDbevX`xql#g@T)Z8+XHJ zXfbE^jdIF-D`*`jxprruRlY?(kjQxQ3QOV-coD1t*Vd!tujHA!Rsdd0C)dJ4f7m#f zHLbpc%~_H#hHLRVS_$cxQZoPNu6a{c4SIehbduD9N=jzhII*jKyOWCLzqBz7doCqQ zNzBAIqxf!uaZY{XNJPxWE{KSX*EYG^z`vSU5<8hivt$xYEJ+L!lMF$EX%vyDCy}l* zUlEI_1(WgU+<8aK%mz!EY_Jqk?9zE>=4A6{twR?~OuFESZIVh93u33?gc(%TAl9h_ z&0D5oK?Hc5e@{?GjwEq?Ul12glIb9@vQf4#j1 z#Ij8S17VjG5{WK8e^8aNQbXn)bvyCi!+CIFCeCLeP{@cyilv;e4O=YK#cZ z4F!C4U|GuSFGNvYBX`?duVPyDpW=MZO(7H1Xj7!niOjGvrG!!bP)Zut+BkZj@~N?< z<4d3<$yX{Ygafn&xg4>=9P57(HVi7a#m(eIJBQ3at$tp+XkmpU)!Lv{UZ%u%Rf|6s z%;LuZ5(FH$JT>1H6!aO|v04r-)_7gQzb|=Z8Oi^s_->9FND8lKL&&I+lzvhTanv+F)Za3x}3)SB;KP!5}~@(W1^7J&5iG8tcqBjPOJk zpw_qzbb6oN9H0lwfy!}u_C8Re!J?mI%~wXsSel98P;$7SdyK#|jY(Oke-*k!7e2~V zG6>~L^aEMeIPg*PujOM(mUnk+T0(CD9-)AQpqfp?)oR6yfg%AR&zfeZm5;G-$^<%k zc8R1~{`Fc=%IS;99hoyT>K)hH_M|0mQ|6SA(@Z%0D95y0pi}Wq_?*XsCwhmB%Ir`k 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%0A)hPOB=7y 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 QIRF3v07*qoM6N<$f=46h!~g&Q literal 0 HcmV?d00001 diff --git a/mlflow-site/src/app/components/NavBar.tsx b/mlflow-site/src/app/components/NavBar.tsx index 504f77c7..54c7223e 100644 --- a/mlflow-site/src/app/components/NavBar.tsx +++ b/mlflow-site/src/app/components/NavBar.tsx @@ -1,7 +1,6 @@ 'use client'; import Image from 'next/image'; -import githubLogo from '../assets/GithubLogo.png'; const NavBar = () => { return ( @@ -46,7 +45,7 @@ const NavBar = () => { href='https://github.com/oslabs-beta/mlflow-js' className='navBarLinksGithub' > - G + G

diff --git a/mlflow-site/src/app/components/Team.tsx b/mlflow-site/src/app/components/Team.tsx index ef18d083..efafbc79 100644 --- a/mlflow-site/src/app/components/Team.tsx +++ b/mlflow-site/src/app/components/Team.tsx @@ -6,32 +6,37 @@ const Team = () => { name: 'Yiqun Zheng', github: 'https://github.com/yiqunzheng', linkedIn: 'https://www.linkedin.com/in/yiqunzheng/', + pfp: '', }, { name: 'Kyler Chiago', github: 'https://github.com/Kyler-Chiago', linkedIn: 'https://www.linkedin.com/in/kyler-chiago/', + pfp: '/assets/kylerpfp.png', }, { name: 'Austin Fraser', github: 'https://github.com/austinbfraser', linkedIn: 'http://www.linkedin.com/in/austin-fraser', + pfp: '', }, { name: 'Stephany Ho', github: 'https://github.com/seneyu/', linkedIn: 'https://www.linkedin.com/in/stephanyho/', + pfp: '', }, - { - name: 'Winston Ludlam', - github: 'https://github.com/winjolu/', - linkedIn: 'https://www.linkedin.com/in/wjludlam/', - }, + // { + // name: 'Winston Ludlam', + // github: 'https://github.com/winjolu/', + // linkedIn: 'https://www.linkedin.com/in/wjludlam/', + // pfp: '', + // }, ]; return (
-
Meet the team
+
Meet the team
{teamArray.map((member, index) => ( { name={member.name} github={member.github} linkedIn={member.linkedIn} + pfp={member.pfp} /> ))}
+
); }; diff --git a/mlflow-site/src/app/components/TeamCard.tsx b/mlflow-site/src/app/components/TeamCard.tsx index 26bf83e8..f9d87436 100644 --- a/mlflow-site/src/app/components/TeamCard.tsx +++ b/mlflow-site/src/app/components/TeamCard.tsx @@ -1,25 +1,34 @@ -// import imageNotFound from '/../..//assets/imageNotFound.jpg' +import Image from 'next/image'; interface TeamCardProps { name: string; github: string; linkedIn: string; + pfp: string; } -const TeamCard: React.FC = ({ - name, - github, - linkedIn, -}) => { +const TeamCard: React.FC = ({ name, github, linkedIn, pfp }) => { return (
- {/*
*/} - {/* Miss */} - {/* Test */} + No Image
{name}
- ); diff --git a/mlflow-site/src/app/globals.css b/mlflow-site/src/app/globals.css index 3b393519..c410700c 100644 --- a/mlflow-site/src/app/globals.css +++ b/mlflow-site/src/app/globals.css @@ -142,7 +142,7 @@ body { grid-row: 4; width: 100%; height: fit-content; - background-color: yellow; + /* background-color: yellow; */ display: flex; justify-content: center; align-items: center; @@ -214,16 +214,20 @@ body { grid-template-rows: min-content; } +.teamHead { + font-size: 1.35rem; +} + .teamCards { width: 100%; display: grid; grid-template-columns: 50% 50%; grid-template-rows: repeat(calc(100%/3), 3); - /* border: #0a0a0a; */ - background-color: red; + /* background-color: red; */ } .teamcard { + margin-top: 0.5rem; display: flex; flex-direction: column; justify-content: center; @@ -233,4 +237,18 @@ body { .teamCardImg { width: 50px; height: 50px; +} + +.teamcardLinks { + display: grid; + grid-template-columns: 45% 10% 45%; + grid-template-rows: 100%; +} + +.teamCardLink1 { + grid-column: 1; +} + +.teamCardLink2 { + grid-column: 3; } \ No newline at end of file From c0aeb5ee32cef48788a8f133dab913ffa013341d Mon Sep 17 00:00:00 2001 From: Kyler-Chiago Date: Sat, 19 Oct 2024 11:08:18 -0700 Subject: [PATCH 180/357] cleaned up commented out code --- mlflow-site/src/app/components/Team.tsx | 6 ------ mlflow-site/src/app/globals.css | 18 ------------------ 2 files changed, 24 deletions(-) diff --git a/mlflow-site/src/app/components/Team.tsx b/mlflow-site/src/app/components/Team.tsx index efafbc79..1de66cb3 100644 --- a/mlflow-site/src/app/components/Team.tsx +++ b/mlflow-site/src/app/components/Team.tsx @@ -26,12 +26,6 @@ const Team = () => { linkedIn: 'https://www.linkedin.com/in/stephanyho/', pfp: '', }, - // { - // name: 'Winston Ludlam', - // github: 'https://github.com/winjolu/', - // linkedIn: 'https://www.linkedin.com/in/wjludlam/', - // pfp: '', - // }, ]; return ( diff --git a/mlflow-site/src/app/globals.css b/mlflow-site/src/app/globals.css index c410700c..d84e884c 100644 --- a/mlflow-site/src/app/globals.css +++ b/mlflow-site/src/app/globals.css @@ -2,18 +2,6 @@ @tailwind components; @tailwind utilities; -/* :root { - --background: #ffffff; - --foreground: #171717; -} - -@media (prefers-color-scheme: dark) { - :root { - --background: #0a0a0a; - --foreground: #ededed; - } -} */ - body { color: var(--foreground); background: var(--background); @@ -83,7 +71,6 @@ body { grid-row: 2; width: 100%; height: 100%; - /* background-color: #7e7e7e; */ display: grid; grid-template-columns: auto auto; grid-template-rows: 100%; @@ -134,7 +121,6 @@ body { grid-row: 3; width: 100%; height: 100%; - /* background-color: aqua; */ } .team { @@ -142,7 +128,6 @@ body { grid-row: 4; width: 100%; height: fit-content; - /* background-color: yellow; */ display: flex; justify-content: center; align-items: center; @@ -154,7 +139,6 @@ body { grid-column: 2/5; grid-row: 3; width: 100%; - /* background-color: rgb(102, 102, 54); */ } .homeButton { @@ -176,7 +160,6 @@ body { .button { width: 100%; - /* background-color: rgb(14, 69, 129); */ } .features { @@ -223,7 +206,6 @@ body { display: grid; grid-template-columns: 50% 50%; grid-template-rows: repeat(calc(100%/3), 3); - /* background-color: red; */ } .teamcard { From e30138e7ecd932ded6b436fb4c6c11679e839f22 Mon Sep 17 00:00:00 2001 From: Austin Fraser Date: Sat, 19 Oct 2024 11:54:31 -0700 Subject: [PATCH 181/357] finished Features.tsx and FeatureCard.tsx --- .../src/app/components/FeatureCard.tsx | 14 ++++---- mlflow-site/src/app/components/Features.tsx | 35 ++++++++++++++++--- mlflow-site/src/app/globals.css | 5 +-- mlflow-site/src/app/layout.tsx | 4 +-- 4 files changed, 44 insertions(+), 14 deletions(-) diff --git a/mlflow-site/src/app/components/FeatureCard.tsx b/mlflow-site/src/app/components/FeatureCard.tsx index 01ee70f8..8c479375 100644 --- a/mlflow-site/src/app/components/FeatureCard.tsx +++ b/mlflow-site/src/app/components/FeatureCard.tsx @@ -1,10 +1,12 @@ -const FeatureCard = () => { +const FeatureCard = ({ header, blurb }: { + key: string, + blurb: string, + header: string +}) => { return ( -
-
FeatureCard1 hello how are you doing?
-
FeatureCard2
-
FeatureCard3
-
FeatureCard4
+
+
{header}
+ {blurb}
); }; diff --git a/mlflow-site/src/app/components/Features.tsx b/mlflow-site/src/app/components/Features.tsx index 55a9c6af..3164f111 100644 --- a/mlflow-site/src/app/components/Features.tsx +++ b/mlflow-site/src/app/components/Features.tsx @@ -1,11 +1,38 @@ import FeatureCard from "./FeatureCard"; const Features = () => { + const featureHeader = 'MLOps in Javascript, made simple.'; + const featureLongBlurb = ` + Longer blurb about MLFlow.js\'s feature set. Longer blurb about MLFlow.js\'s feature set. Longer blurb about MLFlow.js\'s feature set. Longer blurb about MLFlow.js\'s feature set. Longer blurb about MLFlow.js\'s feature set. Longer blurb about MLFlow.js\'s feature set. + `; + const cards = []; + const featureCardHeaders = [ + 'Feature 1', + 'Feature 2', + 'Feature 3', + 'Feature 4', + ]; + const featureCardBlurbs = [ + 'Feature Card Blurb 1. Feature Card Blurb 1. Feature Card Blurb 1. Feature Card Blurb 1. ', + 'Feature Card Blurb 2. Feature Card Blurb 2. Feature Card Blurb 2. Feature Card Blurb 2. ', + 'Feature Card Blurb 3. Feature Card Blurb 3. Feature Card Blurb 3. Feature Card Blurb 3. ', + 'Feature Card Blurb 4. Feature Card Blurb 4. Feature Card Blurb 4. Feature Card Blurb 4. ' + + ]; + for (let i = 0; i < 4; i++) { + cards.push( + + ); + } return ( -
-
MLOps in Javascript, made simple.
-
Long blurb
- +
+
{featureHeader}
+
{featureLongBlurb}
+
{cards}
); }; diff --git a/mlflow-site/src/app/globals.css b/mlflow-site/src/app/globals.css index a3599074..bf74bf00 100644 --- a/mlflow-site/src/app/globals.css +++ b/mlflow-site/src/app/globals.css @@ -160,12 +160,13 @@ body { } .featureCard { + color: black; width: 100%; - background-color: rgb(122, 144, 167); + background-color: rgb(217, 225, 210); display: grid; grid-template-columns: 100%; grid-template-rows: min-content; - text-align: center; + text-align: left; } .demo { diff --git a/mlflow-site/src/app/layout.tsx b/mlflow-site/src/app/layout.tsx index 3f975de8..5864fb61 100644 --- a/mlflow-site/src/app/layout.tsx +++ b/mlflow-site/src/app/layout.tsx @@ -14,8 +14,8 @@ const geistMono = localFont({ }); export const metadata: Metadata = { - title: "Create Next App", - description: "Generated by create next app", + title: "MLflow.js", + description: "MLflow.js", }; export default function RootLayout({ From 9566fa6a2d09d6dca179db65cbd973e25d294055 Mon Sep 17 00:00:00 2001 From: Kyler-Chiago Date: Sat, 19 Oct 2024 13:09:19 -0700 Subject: [PATCH 182/357] reactive to screen size --- mlflow-site/src/app/components/Headline.tsx | 2 +- mlflow-site/src/app/components/NavBar.tsx | 2 +- mlflow-site/src/app/components/Team.tsx | 13 ++--- mlflow-site/src/app/components/TeamCard.tsx | 6 +- mlflow-site/src/app/globals.css | 61 +++++++++++++++++---- mlflow-site/src/app/layout.tsx | 8 +++ 6 files changed, 69 insertions(+), 23 deletions(-) diff --git a/mlflow-site/src/app/components/Headline.tsx b/mlflow-site/src/app/components/Headline.tsx index 85968a2a..287ad894 100644 --- a/mlflow-site/src/app/components/Headline.tsx +++ b/mlflow-site/src/app/components/Headline.tsx @@ -4,7 +4,7 @@ const Headline = () => { return (
MLOps workflow for Javascript
-
Harness MLflow's MLOps functionality for your Javascript application with MLflow.js
+
Harness MLflow's MLOps functionality for your Javascript application with MLflow.js
); diff --git a/mlflow-site/src/app/components/NavBar.tsx b/mlflow-site/src/app/components/NavBar.tsx index 54c7223e..03dedb1a 100644 --- a/mlflow-site/src/app/components/NavBar.tsx +++ b/mlflow-site/src/app/components/NavBar.tsx @@ -45,7 +45,7 @@ const NavBar = () => { href='https://github.com/oslabs-beta/mlflow-js' className='navBarLinksGithub' > - G + G
diff --git a/mlflow-site/src/app/components/Team.tsx b/mlflow-site/src/app/components/Team.tsx index 1de66cb3..5aee85c6 100644 --- a/mlflow-site/src/app/components/Team.tsx +++ b/mlflow-site/src/app/components/Team.tsx @@ -26,6 +26,12 @@ const Team = () => { linkedIn: 'https://www.linkedin.com/in/stephanyho/', pfp: '', }, + { + name: 'Winston Ludlam', + github: 'https://github.com/winjolu/', + linkedIn: 'https://www.linkedin.com/in/wjludlam/', + pfp: '', + }, ]; return ( @@ -42,13 +48,6 @@ const Team = () => { /> ))}
-
); }; diff --git a/mlflow-site/src/app/components/TeamCard.tsx b/mlflow-site/src/app/components/TeamCard.tsx index f9d87436..e84ee737 100644 --- a/mlflow-site/src/app/components/TeamCard.tsx +++ b/mlflow-site/src/app/components/TeamCard.tsx @@ -10,11 +10,11 @@ interface TeamCardProps { const TeamCard: React.FC = ({ name, github, linkedIn, pfp }) => { return (
- No Image + No Image
{name}
- = ({ name, github, linkedIn, pfp }) => { /> - Date: Sat, 19 Oct 2024 13:16:19 -0700 Subject: [PATCH 183/357] small change to button font size --- mlflow-site/src/app/globals.css | 28 +--------------------------- 1 file changed, 1 insertion(+), 27 deletions(-) diff --git a/mlflow-site/src/app/globals.css b/mlflow-site/src/app/globals.css index ba21cfc3..bd1e1930 100644 --- a/mlflow-site/src/app/globals.css +++ b/mlflow-site/src/app/globals.css @@ -157,7 +157,7 @@ body { padding-left: clamp(0.375rem, 1.66125vw, .65625rem); padding-right: clamp(0.375rem, 1.66125vw, .65625rem); border-radius: clamp(0.3125rem, 1.384375vw, 0.546875rem); - font-size: clamp(0.8rem, 3.544vw, 1rem); + font-size: clamp(0.8rem, 3.544vw, 1.05rem); margin-right: 8px; } @@ -219,32 +219,6 @@ body { flex-wrap: wrap; } -/* .teamCards { - width: 100%; - display: grid; - grid-template-columns: 50% 50%; - grid-template-rows: repeat(calc(100%/3), 3); -} - -@media (min-width: 600px) { - .teamCards { - width: 100%; - display: grid; - grid-template-columns: calc(100%/3) calc(100%/3) calc(100%/3); - grid-template-rows: 50% 50%; - } -} - -@media (min-width: 900px) { - .teamCards { - width: 100%; - display: grid; - grid-template-columns: 25% 25% 25% 25%; - grid-template-rows: 100%; - background-color: red; - } -} */ - .teamcard { margin-top: 0.5rem; display: flex; From 99a33bf1a95fc9a4d32a142ba1736ee540e683c5 Mon Sep 17 00:00:00 2001 From: Kyler-Chiago Date: Sat, 19 Oct 2024 13:35:20 -0700 Subject: [PATCH 184/357] more styling on the teams section --- mlflow-site/src/app/globals.css | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/mlflow-site/src/app/globals.css b/mlflow-site/src/app/globals.css index bd1e1930..d5c6a610 100644 --- a/mlflow-site/src/app/globals.css +++ b/mlflow-site/src/app/globals.css @@ -226,12 +226,15 @@ body { justify-content: center; align-items: center; font-size: clamp(1rem, 4.43vw, 1.3rem); + padding: clamp(.22rem, 1.1927vw,0.35rem); margin-left: 0.2rem; margin-right: 0.2rem; + background-color: rgb(217, 225, 210); } .teamCardImg { - width: clamp(80px, 22.155vw, 100px) + width: clamp(80px, 22.155vw, 100px); + border: 1px solid black; } .teamcardLinks { From 4312059076f3a47f87e71aaee69332aa1f8c018a Mon Sep 17 00:00:00 2001 From: Kyler-Chiago Date: Sat, 19 Oct 2024 13:36:09 -0700 Subject: [PATCH 185/357] removed commented out code from css --- mlflow-site/src/app/globals.css | 2 -- 1 file changed, 2 deletions(-) diff --git a/mlflow-site/src/app/globals.css b/mlflow-site/src/app/globals.css index d5c6a610..cdfb50a7 100644 --- a/mlflow-site/src/app/globals.css +++ b/mlflow-site/src/app/globals.css @@ -7,7 +7,6 @@ body { background: var(--background); font-family: Inter; font-size: 1rem; - /* font-size: 4.43vw; */ color: rgb(0, 0, 0); } @@ -31,7 +30,6 @@ body { width: 100%; height: 100%; display: grid; - /* grid-template-columns: 1fr 360px 1fr; */ grid-template-columns: 1fr 100vw 1fr; grid-template-rows: 1fr; overflow-y: auto; From 72e6aebbb213917b1f7235c01233b6cba94f2633 Mon Sep 17 00:00:00 2001 From: Austin Fraser Date: Sat, 19 Oct 2024 13:40:29 -0700 Subject: [PATCH 186/357] finished Demo and DemoCard --- mlflow-site/next.config.mjs | 11 +++++- mlflow-site/src/app/components/Demo.tsx | 37 ++++++++++++------- mlflow-site/src/app/components/DemoCard.tsx | 28 ++++++++++++++ .../src/app/components/FeatureCard.tsx | 2 +- mlflow-site/src/app/components/Features.tsx | 4 +- mlflow-site/src/app/globals.css | 3 -- 6 files changed, 64 insertions(+), 21 deletions(-) diff --git a/mlflow-site/next.config.mjs b/mlflow-site/next.config.mjs index 4678774e..cb29b8e9 100644 --- a/mlflow-site/next.config.mjs +++ b/mlflow-site/next.config.mjs @@ -1,4 +1,13 @@ /** @type {import('next').NextConfig} */ -const nextConfig = {}; +const nextConfig = { + images: { + remotePatterns: [ + { + protocol: 'https', + hostname: 'i.giphy.com' + }, + ], + }, +}; export default nextConfig; diff --git a/mlflow-site/src/app/components/Demo.tsx b/mlflow-site/src/app/components/Demo.tsx index 4faf4d86..b541c27a 100644 --- a/mlflow-site/src/app/components/Demo.tsx +++ b/mlflow-site/src/app/components/Demo.tsx @@ -1,19 +1,28 @@ +import DemoCard from "./DemoCard"; + const Demo = () => { + const demos = []; + const demoCardHeaders = [ + 'Demo 1', + 'Demo 2', + 'Demo 3' + ]; + const demoCardBlurbs = [ + 'Description for what\'s happening in Demo 1. This block of text will contain all the info needed to understand the demo.', + 'Description for what\'s happening in Demo 2. This block of text will contain all the info needed to understand the demo.', + 'Description for what\'s happening in Demo 3. This block of text will contain all the info needed to understand the demo.' + ]; + for (let i = 0; i < 3; i++) { + demos.push( + + ); + } return ( -
-
-
Img 1
-
Demo 1
-
-
-
Demo 2
-
Img 2
-
-
-
Img 3
-
Demo 3
-
-
+
{demos}
); }; diff --git a/mlflow-site/src/app/components/DemoCard.tsx b/mlflow-site/src/app/components/DemoCard.tsx index e69de29b..8d5aeb7c 100644 --- a/mlflow-site/src/app/components/DemoCard.tsx +++ b/mlflow-site/src/app/components/DemoCard.tsx @@ -0,0 +1,28 @@ +import Image from "next/image"; + +const DemoCard = ({ header, blurb }: { + key: string, + blurb: string, + header: string + }) => { + return ( +
+ +
{header}
+ {blurb} +
+ ); + }; + + export default DemoCard; + \ No newline at end of file diff --git a/mlflow-site/src/app/components/FeatureCard.tsx b/mlflow-site/src/app/components/FeatureCard.tsx index 8c479375..79ef32ee 100644 --- a/mlflow-site/src/app/components/FeatureCard.tsx +++ b/mlflow-site/src/app/components/FeatureCard.tsx @@ -4,7 +4,7 @@ const FeatureCard = ({ header, blurb }: { header: string }) => { return ( -
+
{header}
{blurb}
diff --git a/mlflow-site/src/app/components/Features.tsx b/mlflow-site/src/app/components/Features.tsx index 3164f111..f1b61f20 100644 --- a/mlflow-site/src/app/components/Features.tsx +++ b/mlflow-site/src/app/components/Features.tsx @@ -29,8 +29,8 @@ const Features = () => { ); } return ( -
-
{featureHeader}
+
+
{featureHeader}
{featureLongBlurb}
{cards}
diff --git a/mlflow-site/src/app/globals.css b/mlflow-site/src/app/globals.css index bf74bf00..5e7d5c9e 100644 --- a/mlflow-site/src/app/globals.css +++ b/mlflow-site/src/app/globals.css @@ -154,7 +154,6 @@ body { grid-column: 2/5; grid-row: 3; width: 100%; - background-color: rgb(176, 47, 107); display: grid; place-items: center; } @@ -166,14 +165,12 @@ body { display: grid; grid-template-columns: 100%; grid-template-rows: min-content; - text-align: left; } .demo { grid-column: 2/5; grid-row: 3; width: 100%; - background-color: rgb(47, 176, 101); display: grid; grid-template-columns: 100%; grid-template-rows: calc(100%/3) calc(100%/3) calc(100%/3); From 7c049c10c9ddaded80b67a7b0358df0bea5e477e Mon Sep 17 00:00:00 2001 From: Austin Fraser Date: Sat, 19 Oct 2024 15:07:28 -0700 Subject: [PATCH 187/357] refactored Features and Demo to CSS from Tailwind --- mlflow-site/src/app/components/Demo.tsx | 2 +- mlflow-site/src/app/components/DemoCard.tsx | 4 +-- .../src/app/components/FeatureCard.tsx | 4 +-- mlflow-site/src/app/components/Features.tsx | 6 ++-- mlflow-site/src/app/globals.css | 34 +++++++++++++++++++ 5 files changed, 42 insertions(+), 8 deletions(-) diff --git a/mlflow-site/src/app/components/Demo.tsx b/mlflow-site/src/app/components/Demo.tsx index b541c27a..ab85039a 100644 --- a/mlflow-site/src/app/components/Demo.tsx +++ b/mlflow-site/src/app/components/Demo.tsx @@ -22,7 +22,7 @@ const Demo = () => { ); } return ( -
{demos}
+
{demos}
); }; diff --git a/mlflow-site/src/app/components/DemoCard.tsx b/mlflow-site/src/app/components/DemoCard.tsx index 8d5aeb7c..909fed47 100644 --- a/mlflow-site/src/app/components/DemoCard.tsx +++ b/mlflow-site/src/app/components/DemoCard.tsx @@ -6,7 +6,7 @@ const DemoCard = ({ header, blurb }: { header: string }) => { return ( -
+
-
{header}
+
{header}
{blurb}
); diff --git a/mlflow-site/src/app/components/FeatureCard.tsx b/mlflow-site/src/app/components/FeatureCard.tsx index 79ef32ee..4047d0c5 100644 --- a/mlflow-site/src/app/components/FeatureCard.tsx +++ b/mlflow-site/src/app/components/FeatureCard.tsx @@ -4,8 +4,8 @@ const FeatureCard = ({ header, blurb }: { header: string }) => { return ( -
-
{header}
+
+
{header}
{blurb}
); diff --git a/mlflow-site/src/app/components/Features.tsx b/mlflow-site/src/app/components/Features.tsx index f1b61f20..6517c965 100644 --- a/mlflow-site/src/app/components/Features.tsx +++ b/mlflow-site/src/app/components/Features.tsx @@ -29,9 +29,9 @@ const Features = () => { ); } return ( -
-
{featureHeader}
-
{featureLongBlurb}
+
+
{featureHeader}
+
{featureLongBlurb}
{cards}
); diff --git a/mlflow-site/src/app/globals.css b/mlflow-site/src/app/globals.css index fbab937d..0dd2ef23 100644 --- a/mlflow-site/src/app/globals.css +++ b/mlflow-site/src/app/globals.css @@ -168,6 +168,20 @@ body { width: 100%; display: grid; place-items: center; + padding: 0.5rem; + margin-bottom: 5rem; + text-align: center; + color: black; + background-color: white; +} + +.featureHeader { + font-size: 1.875rem; + margin-bottom: 0.5rem; +} + +.featureLongBlurb { + margin-bottom: 0.5rem; } .featureCard { @@ -177,6 +191,12 @@ body { display: grid; grid-template-columns: 100%; grid-template-rows: min-content; + padding: 0.5rem; + margin-bottom: 0.5rem; +} + +.featureCardHeader { + font-size: 1.5rem; } .demo { @@ -186,6 +206,20 @@ body { display: grid; grid-template-columns: 100%; grid-template-rows: calc(100%/3) calc(100%/3) calc(100%/3); + color: black; + background-color: white; + margin-bottom: 5rem; +} + +.demoCard { + gap: 1.25rem; + padding: 0.25rem; + margin-bottom: 5rem; + text-align: center; +} + +.demoCardHeader { + font-size: 1.5rem; } .demoSplit { From 35a05cbef79a3cdee558c15e0587509bc89d0555 Mon Sep 17 00:00:00 2001 From: Austin Fraser Date: Mon, 21 Oct 2024 17:41:22 -0700 Subject: [PATCH 188/357] deleted package lock --- mlflow/package-lock.json | 3766 -------------------------------------- 1 file changed, 3766 deletions(-) delete mode 100644 mlflow/package-lock.json diff --git a/mlflow/package-lock.json b/mlflow/package-lock.json deleted file mode 100644 index a21f38fe..00000000 --- a/mlflow/package-lock.json +++ /dev/null @@ -1,3766 +0,0 @@ -{ - "name": "mlflow-js", - "version": "1.0.0", - "lockfileVersion": 3, - "requires": true, - "packages": { - "": { - "name": "mlflow-js", - "version": "1.0.0", - "license": "MIT", - "devDependencies": { - "@eslint/js": "^9.12.0", - "@types/eslint__js": "^8.42.3", - "@types/node": "^22.5.4", - "eslint": "^9.12.0", - "rimraf": "^6.0.1", - "ts-node": "^10.9.2", - "tsc-alias": "^1.8.10", - "tsx": "^4.19.1", - "typedoc": "^0.26.9", - "typescript": "^5.6.2", - "typescript-eslint": "^8.8.0" - }, - "engines": { - "node": ">=22.7.0" - } - }, - "node_modules/@cspotcode/source-map-support": { - "version": "0.8.1", - "resolved": "https://registry.npmjs.org/@cspotcode/source-map-support/-/source-map-support-0.8.1.tgz", - "integrity": "sha512-IchNf6dN4tHoMFIn/7OE8LWZ19Y6q/67Bmf6vnGREv8RSbBVb9LPJxEcnwrcwX6ixSvaiGoomAUvu4YSxXrVgw==", - "dev": true, - "license": "MIT", - "dependencies": { - "@jridgewell/trace-mapping": "0.3.9" - }, - "engines": { - "node": ">=12" - } - }, - "node_modules/@esbuild/aix-ppc64": { - "version": "0.23.1", - "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.23.1.tgz", - "integrity": "sha512-6VhYk1diRqrhBAqpJEdjASR/+WVRtfjpqKuNw11cLiaWpAT/Uu+nokB+UJnevzy/P9C/ty6AOe0dwueMrGh/iQ==", - "cpu": [ - "ppc64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "aix" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/android-arm": { - "version": "0.23.1", - "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.23.1.tgz", - "integrity": "sha512-uz6/tEy2IFm9RYOyvKl88zdzZfwEfKZmnX9Cj1BHjeSGNuGLuMD1kR8y5bteYmwqKm1tj8m4cb/aKEorr6fHWQ==", - "cpu": [ - "arm" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "android" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/android-arm64": { - "version": "0.23.1", - "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.23.1.tgz", - "integrity": "sha512-xw50ipykXcLstLeWH7WRdQuysJqejuAGPd30vd1i5zSyKK3WE+ijzHmLKxdiCMtH1pHz78rOg0BKSYOSB/2Khw==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "android" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/android-x64": { - "version": "0.23.1", - "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.23.1.tgz", - "integrity": "sha512-nlN9B69St9BwUoB+jkyU090bru8L0NA3yFvAd7k8dNsVH8bi9a8cUAUSEcEEgTp2z3dbEDGJGfP6VUnkQnlReg==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "android" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/darwin-arm64": { - "version": "0.23.1", - "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.23.1.tgz", - "integrity": "sha512-YsS2e3Wtgnw7Wq53XXBLcV6JhRsEq8hkfg91ESVadIrzr9wO6jJDMZnCQbHm1Guc5t/CdDiFSSfWP58FNuvT3Q==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "darwin" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/darwin-x64": { - "version": "0.23.1", - "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.23.1.tgz", - "integrity": "sha512-aClqdgTDVPSEGgoCS8QDG37Gu8yc9lTHNAQlsztQ6ENetKEO//b8y31MMu2ZaPbn4kVsIABzVLXYLhCGekGDqw==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "darwin" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/freebsd-arm64": { - "version": "0.23.1", - "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.23.1.tgz", - "integrity": "sha512-h1k6yS8/pN/NHlMl5+v4XPfikhJulk4G+tKGFIOwURBSFzE8bixw1ebjluLOjfwtLqY0kewfjLSrO6tN2MgIhA==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "freebsd" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/freebsd-x64": { - "version": "0.23.1", - "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.23.1.tgz", - "integrity": "sha512-lK1eJeyk1ZX8UklqFd/3A60UuZ/6UVfGT2LuGo3Wp4/z7eRTRYY+0xOu2kpClP+vMTi9wKOfXi2vjUpO1Ro76g==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "freebsd" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/linux-arm": { - "version": "0.23.1", - "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.23.1.tgz", - "integrity": "sha512-CXXkzgn+dXAPs3WBwE+Kvnrf4WECwBdfjfeYHpMeVxWE0EceB6vhWGShs6wi0IYEqMSIzdOF1XjQ/Mkm5d7ZdQ==", - "cpu": [ - "arm" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/linux-arm64": { - "version": "0.23.1", - "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.23.1.tgz", - "integrity": "sha512-/93bf2yxencYDnItMYV/v116zff6UyTjo4EtEQjUBeGiVpMmffDNUyD9UN2zV+V3LRV3/on4xdZ26NKzn6754g==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/linux-ia32": { - "version": "0.23.1", - "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.23.1.tgz", - "integrity": "sha512-VTN4EuOHwXEkXzX5nTvVY4s7E/Krz7COC8xkftbbKRYAl96vPiUssGkeMELQMOnLOJ8k3BY1+ZY52tttZnHcXQ==", - "cpu": [ - "ia32" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/linux-loong64": { - "version": "0.23.1", - "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.23.1.tgz", - "integrity": "sha512-Vx09LzEoBa5zDnieH8LSMRToj7ir/Jeq0Gu6qJ/1GcBq9GkfoEAoXvLiW1U9J1qE/Y/Oyaq33w5p2ZWrNNHNEw==", - "cpu": [ - "loong64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/linux-mips64el": { - "version": "0.23.1", - "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.23.1.tgz", - "integrity": "sha512-nrFzzMQ7W4WRLNUOU5dlWAqa6yVeI0P78WKGUo7lg2HShq/yx+UYkeNSE0SSfSure0SqgnsxPvmAUu/vu0E+3Q==", - "cpu": [ - "mips64el" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/linux-ppc64": { - "version": "0.23.1", - "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.23.1.tgz", - "integrity": "sha512-dKN8fgVqd0vUIjxuJI6P/9SSSe/mB9rvA98CSH2sJnlZ/OCZWO1DJvxj8jvKTfYUdGfcq2dDxoKaC6bHuTlgcw==", - "cpu": [ - "ppc64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/linux-riscv64": { - "version": "0.23.1", - "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.23.1.tgz", - "integrity": "sha512-5AV4Pzp80fhHL83JM6LoA6pTQVWgB1HovMBsLQ9OZWLDqVY8MVobBXNSmAJi//Csh6tcY7e7Lny2Hg1tElMjIA==", - "cpu": [ - "riscv64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/linux-s390x": { - "version": "0.23.1", - "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.23.1.tgz", - "integrity": "sha512-9ygs73tuFCe6f6m/Tb+9LtYxWR4c9yg7zjt2cYkjDbDpV/xVn+68cQxMXCjUpYwEkze2RcU/rMnfIXNRFmSoDw==", - "cpu": [ - "s390x" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/linux-x64": { - "version": "0.23.1", - "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.23.1.tgz", - "integrity": "sha512-EV6+ovTsEXCPAp58g2dD68LxoP/wK5pRvgy0J/HxPGB009omFPv3Yet0HiaqvrIrgPTBuC6wCH1LTOY91EO5hQ==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/netbsd-x64": { - "version": "0.23.1", - "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.23.1.tgz", - "integrity": "sha512-aevEkCNu7KlPRpYLjwmdcuNz6bDFiE7Z8XC4CPqExjTvrHugh28QzUXVOZtiYghciKUacNktqxdpymplil1beA==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "netbsd" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/openbsd-arm64": { - "version": "0.23.1", - "resolved": "https://registry.npmjs.org/@esbuild/openbsd-arm64/-/openbsd-arm64-0.23.1.tgz", - "integrity": "sha512-3x37szhLexNA4bXhLrCC/LImN/YtWis6WXr1VESlfVtVeoFJBRINPJ3f0a/6LV8zpikqoUg4hyXw0sFBt5Cr+Q==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "openbsd" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/openbsd-x64": { - "version": "0.23.1", - "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.23.1.tgz", - "integrity": "sha512-aY2gMmKmPhxfU+0EdnN+XNtGbjfQgwZj43k8G3fyrDM/UdZww6xrWxmDkuz2eCZchqVeABjV5BpildOrUbBTqA==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "openbsd" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/sunos-x64": { - "version": "0.23.1", - "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.23.1.tgz", - "integrity": "sha512-RBRT2gqEl0IKQABT4XTj78tpk9v7ehp+mazn2HbUeZl1YMdaGAQqhapjGTCe7uw7y0frDi4gS0uHzhvpFuI1sA==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "sunos" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/win32-arm64": { - "version": "0.23.1", - "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.23.1.tgz", - "integrity": "sha512-4O+gPR5rEBe2FpKOVyiJ7wNDPA8nGzDuJ6gN4okSA1gEOYZ67N8JPk58tkWtdtPeLz7lBnY6I5L3jdsr3S+A6A==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "win32" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/win32-ia32": { - "version": "0.23.1", - "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.23.1.tgz", - "integrity": "sha512-BcaL0Vn6QwCwre3Y717nVHZbAa4UBEigzFm6VdsVdT/MbZ38xoj1X9HPkZhbmaBGUD1W8vxAfffbDe8bA6AKnQ==", - "cpu": [ - "ia32" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "win32" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/win32-x64": { - "version": "0.23.1", - "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.23.1.tgz", - "integrity": "sha512-BHpFFeslkWrXWyUPnbKm+xYYVYruCinGcftSBaa8zoF9hZO4BcSCFUvHVTtzpIY6YzUnYtuEhZ+C9iEXjxnasg==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "win32" - ], - "engines": { - "node": ">=18" - } - }, - "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, - "license": "MIT", - "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/eslint-utils/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, - "license": "Apache-2.0", - "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" - }, - "funding": { - "url": "https://opencollective.com/eslint" - } - }, - "node_modules/@eslint-community/regexpp": { - "version": "4.11.1", - "resolved": "https://registry.npmjs.org/@eslint-community/regexpp/-/regexpp-4.11.1.tgz", - "integrity": "sha512-m4DVN9ZqskZoLU5GlWZadwDnYo3vAEydiUayB9widCl9ffWx2IvPnp6n3on5rJmziJSw9Bv+Z3ChDVdMwXCY8Q==", - "dev": true, - "license": "MIT", - "engines": { - "node": "^12.0.0 || ^14.0.0 || >=16.0.0" - } - }, - "node_modules/@eslint/config-array": { - "version": "0.18.0", - "resolved": "https://registry.npmjs.org/@eslint/config-array/-/config-array-0.18.0.tgz", - "integrity": "sha512-fTxvnS1sRMu3+JjXwJG0j/i4RT9u4qJ+lqS/yCGap4lH4zZGzQ7tu+xZqQmcMZq5OBZDL4QRxQzRjkWcGt8IVw==", - "dev": true, - "license": "Apache-2.0", - "dependencies": { - "@eslint/object-schema": "^2.1.4", - "debug": "^4.3.1", - "minimatch": "^3.1.2" - }, - "engines": { - "node": "^18.18.0 || ^20.9.0 || >=21.1.0" - } - }, - "node_modules/@eslint/config-array/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, - "license": "MIT", - "dependencies": { - "balanced-match": "^1.0.0", - "concat-map": "0.0.1" - } - }, - "node_modules/@eslint/config-array/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, - "license": "ISC", - "dependencies": { - "brace-expansion": "^1.1.7" - }, - "engines": { - "node": "*" - } - }, - "node_modules/@eslint/core": { - "version": "0.6.0", - "resolved": "https://registry.npmjs.org/@eslint/core/-/core-0.6.0.tgz", - "integrity": "sha512-8I2Q8ykA4J0x0o7cg67FPVnehcqWTBehu/lmY+bolPFHGjh49YzGBMXTvpqVgEbBdvNCSxj6iFgiIyHzf03lzg==", - "dev": true, - "license": "Apache-2.0", - "engines": { - "node": "^18.18.0 || ^20.9.0 || >=21.1.0" - } - }, - "node_modules/@eslint/eslintrc": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-3.1.0.tgz", - "integrity": "sha512-4Bfj15dVJdoy3RfZmmo86RK1Fwzn6SstsvK9JS+BaVKqC6QQQQyXekNaC+g+LKNgkQ+2VhGAzm6hO40AhMR3zQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "ajv": "^6.12.4", - "debug": "^4.3.2", - "espree": "^10.0.1", - "globals": "^14.0.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": "^18.18.0 || ^20.9.0 || >=21.1.0" - }, - "funding": { - "url": "https://opencollective.com/eslint" - } - }, - "node_modules/@eslint/eslintrc/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, - "license": "MIT", - "dependencies": { - "balanced-match": "^1.0.0", - "concat-map": "0.0.1" - } - }, - "node_modules/@eslint/eslintrc/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, - "license": "ISC", - "dependencies": { - "brace-expansion": "^1.1.7" - }, - "engines": { - "node": "*" - } - }, - "node_modules/@eslint/js": { - "version": "9.12.0", - "resolved": "https://registry.npmjs.org/@eslint/js/-/js-9.12.0.tgz", - "integrity": "sha512-eohesHH8WFRUprDNyEREgqP6beG6htMeUYeCpkEgBCieCMme5r9zFWjzAJp//9S+Kub4rqE+jXe9Cp1a7IYIIA==", - "dev": true, - "license": "MIT", - "engines": { - "node": "^18.18.0 || ^20.9.0 || >=21.1.0" - } - }, - "node_modules/@eslint/object-schema": { - "version": "2.1.4", - "resolved": "https://registry.npmjs.org/@eslint/object-schema/-/object-schema-2.1.4.tgz", - "integrity": "sha512-BsWiH1yFGjXXS2yvrf5LyuoSIIbPrGUWob917o+BTKuZ7qJdxX8aJLRxs1fS9n6r7vESrq1OUqb68dANcFXuQQ==", - "dev": true, - "license": "Apache-2.0", - "engines": { - "node": "^18.18.0 || ^20.9.0 || >=21.1.0" - } - }, - "node_modules/@eslint/plugin-kit": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/@eslint/plugin-kit/-/plugin-kit-0.2.0.tgz", - "integrity": "sha512-vH9PiIMMwvhCx31Af3HiGzsVNULDbyVkHXwlemn/B0TFj/00ho3y55efXrUZTfQipxoHC5u4xq6zblww1zm1Ig==", - "dev": true, - "license": "Apache-2.0", - "dependencies": { - "levn": "^0.4.1" - }, - "engines": { - "node": "^18.18.0 || ^20.9.0 || >=21.1.0" - } - }, - "node_modules/@humanfs/core": { - "version": "0.19.0", - "resolved": "https://registry.npmjs.org/@humanfs/core/-/core-0.19.0.tgz", - "integrity": "sha512-2cbWIHbZVEweE853g8jymffCA+NCMiuqeECeBBLm8dg2oFdjuGJhgN4UAbI+6v0CKbbhvtXA4qV8YR5Ji86nmw==", - "dev": true, - "license": "Apache-2.0", - "engines": { - "node": ">=18.18.0" - } - }, - "node_modules/@humanfs/node": { - "version": "0.16.5", - "resolved": "https://registry.npmjs.org/@humanfs/node/-/node-0.16.5.tgz", - "integrity": "sha512-KSPA4umqSG4LHYRodq31VDwKAvaTF4xmVlzM8Aeh4PlU1JQ3IG0wiA8C25d3RQ9nJyM3mBHyI53K06VVL/oFFg==", - "dev": true, - "license": "Apache-2.0", - "dependencies": { - "@humanfs/core": "^0.19.0", - "@humanwhocodes/retry": "^0.3.0" - }, - "engines": { - "node": ">=18.18.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, - "license": "Apache-2.0", - "engines": { - "node": ">=12.22" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/nzakas" - } - }, - "node_modules/@humanwhocodes/retry": { - "version": "0.3.1", - "resolved": "https://registry.npmjs.org/@humanwhocodes/retry/-/retry-0.3.1.tgz", - "integrity": "sha512-JBxkERygn7Bv/GbN5Rv8Ul6LVknS+5Bp6RgDC/O8gEBU/yeH5Ui5C/OlWrTb6qct7LjjfT6Re2NxB0ln0yYybA==", - "dev": true, - "license": "Apache-2.0", - "engines": { - "node": ">=18.18" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/nzakas" - } - }, - "node_modules/@isaacs/cliui": { - "version": "8.0.2", - "resolved": "https://registry.npmjs.org/@isaacs/cliui/-/cliui-8.0.2.tgz", - "integrity": "sha512-O8jcjabXaleOG9DQ0+ARXWZBTfnP4WNAqzuiJK7ll44AmxGKv/J2M4TPjxjY3znBCfvBXFzucm1twdyFybFqEA==", - "dev": true, - "license": "ISC", - "dependencies": { - "string-width": "^5.1.2", - "string-width-cjs": "npm:string-width@^4.2.0", - "strip-ansi": "^7.0.1", - "strip-ansi-cjs": "npm:strip-ansi@^6.0.1", - "wrap-ansi": "^8.1.0", - "wrap-ansi-cjs": "npm:wrap-ansi@^7.0.0" - }, - "engines": { - "node": ">=12" - } - }, - "node_modules/@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, - "license": "MIT", - "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, - "license": "MIT" - }, - "node_modules/@jridgewell/trace-mapping": { - "version": "0.3.9", - "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.9.tgz", - "integrity": "sha512-3Belt6tdc8bPgAtbcmdtNJlirVoTmEb5e2gC94PnkwEW9jI6CAHUeoG85tjWP5WquqfavoMtMwiG4P926ZKKuQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "@jridgewell/resolve-uri": "^3.0.3", - "@jridgewell/sourcemap-codec": "^1.4.10" - } - }, - "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, -<<<<<<< HEAD -======= - "license": "MIT", ->>>>>>> dev - "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, -<<<<<<< HEAD -======= - "license": "MIT", ->>>>>>> dev - "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, -<<<<<<< HEAD -======= - "license": "MIT", ->>>>>>> dev - "dependencies": { - "@nodelib/fs.scandir": "2.1.5", - "fastq": "^1.6.0" - }, - "engines": { - "node": ">= 8" - } - }, -<<<<<<< HEAD -======= - "node_modules/@shikijs/core": { - "version": "1.22.0", - "resolved": "https://registry.npmjs.org/@shikijs/core/-/core-1.22.0.tgz", - "integrity": "sha512-S8sMe4q71TJAW+qG93s5VaiihujRK6rqDFqBnxqvga/3LvqHEnxqBIOPkt//IdXVtHkQWKu4nOQNk0uBGicU7Q==", - "dev": true, - "license": "MIT", - "dependencies": { - "@shikijs/engine-javascript": "1.22.0", - "@shikijs/engine-oniguruma": "1.22.0", - "@shikijs/types": "1.22.0", - "@shikijs/vscode-textmate": "^9.3.0", - "@types/hast": "^3.0.4", - "hast-util-to-html": "^9.0.3" - } - }, - "node_modules/@shikijs/engine-javascript": { - "version": "1.22.0", - "resolved": "https://registry.npmjs.org/@shikijs/engine-javascript/-/engine-javascript-1.22.0.tgz", - "integrity": "sha512-AeEtF4Gcck2dwBqCFUKYfsCq0s+eEbCEbkUuFou53NZ0sTGnJnJ/05KHQFZxpii5HMXbocV9URYVowOP2wH5kw==", - "dev": true, - "license": "MIT", - "dependencies": { - "@shikijs/types": "1.22.0", - "@shikijs/vscode-textmate": "^9.3.0", - "oniguruma-to-js": "0.4.3" - } - }, - "node_modules/@shikijs/engine-oniguruma": { - "version": "1.22.0", - "resolved": "https://registry.npmjs.org/@shikijs/engine-oniguruma/-/engine-oniguruma-1.22.0.tgz", - "integrity": "sha512-5iBVjhu/DYs1HB0BKsRRFipRrD7rqjxlWTj4F2Pf+nQSPqc3kcyqFFeZXnBMzDf0HdqaFVvhDRAGiYNvyLP+Mw==", - "dev": true, - "license": "MIT", - "dependencies": { - "@shikijs/types": "1.22.0", - "@shikijs/vscode-textmate": "^9.3.0" - } - }, - "node_modules/@shikijs/types": { - "version": "1.22.0", - "resolved": "https://registry.npmjs.org/@shikijs/types/-/types-1.22.0.tgz", - "integrity": "sha512-Fw/Nr7FGFhlQqHfxzZY8Cwtwk5E9nKDUgeLjZgt3UuhcM3yJR9xj3ZGNravZZok8XmEZMiYkSMTPlPkULB8nww==", - "dev": true, - "license": "MIT", - "dependencies": { - "@shikijs/vscode-textmate": "^9.3.0", - "@types/hast": "^3.0.4" - } - }, - "node_modules/@shikijs/vscode-textmate": { - "version": "9.3.0", - "resolved": "https://registry.npmjs.org/@shikijs/vscode-textmate/-/vscode-textmate-9.3.0.tgz", - "integrity": "sha512-jn7/7ky30idSkd/O5yDBfAnVt+JJpepofP/POZ1iMOxK59cOfqIgg/Dj0eFsjOTMw+4ycJN0uhZH/Eb0bs/EUA==", - "dev": true, - "license": "MIT" - }, ->>>>>>> dev - "node_modules/@tsconfig/node10": { - "version": "1.0.11", - "resolved": "https://registry.npmjs.org/@tsconfig/node10/-/node10-1.0.11.tgz", - "integrity": "sha512-DcRjDCujK/kCk/cUe8Xz8ZSpm8mS3mNNpta+jGCA6USEDfktlNvm1+IuZ9eTcDbNk41BHwpHHeW+N1lKCz4zOw==", - "dev": true, - "license": "MIT" - }, - "node_modules/@tsconfig/node12": { - "version": "1.0.11", - "resolved": "https://registry.npmjs.org/@tsconfig/node12/-/node12-1.0.11.tgz", - "integrity": "sha512-cqefuRsh12pWyGsIoBKJA9luFu3mRxCA+ORZvA4ktLSzIuCUtWVxGIuXigEwO5/ywWFMZ2QEGKWvkZG1zDMTag==", - "dev": true, - "license": "MIT" - }, - "node_modules/@tsconfig/node14": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/@tsconfig/node14/-/node14-1.0.3.tgz", - "integrity": "sha512-ysT8mhdixWK6Hw3i1V2AeRqZ5WfXg1G43mqoYlM2nc6388Fq5jcXyr5mRsqViLx/GJYdoL0bfXD8nmF+Zn/Iow==", - "dev": true, - "license": "MIT" - }, - "node_modules/@tsconfig/node16": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/@tsconfig/node16/-/node16-1.0.4.tgz", - "integrity": "sha512-vxhUy4J8lyeyinH7Azl1pdd43GJhZH/tP2weN8TntQblOY+A0XbT8DJk1/oCPuOOyg/Ja757rG0CgHcWC8OfMA==", - "dev": true, - "license": "MIT" - }, - "node_modules/@types/eslint": { - "version": "9.6.1", - "resolved": "https://registry.npmjs.org/@types/eslint/-/eslint-9.6.1.tgz", - "integrity": "sha512-FXx2pKgId/WyYo2jXw63kk7/+TY7u7AziEJxJAnSFzHlqTAS3Ync6SvgYAN/k4/PQpnnVuzoMuVnByKK2qp0ag==", - "dev": true, - "license": "MIT", - "dependencies": { - "@types/estree": "*", - "@types/json-schema": "*" - } - }, - "node_modules/@types/eslint__js": { - "version": "8.42.3", - "resolved": "https://registry.npmjs.org/@types/eslint__js/-/eslint__js-8.42.3.tgz", - "integrity": "sha512-alfG737uhmPdnvkrLdZLcEKJ/B8s9Y4hrZ+YAdzUeoArBlSUERA2E87ROfOaS4jd/C45fzOoZzidLc1IPwLqOw==", - "dev": true, - "license": "MIT", - "dependencies": { - "@types/eslint": "*" - } - }, - "node_modules/@types/estree": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.6.tgz", - "integrity": "sha512-AYnb1nQyY49te+VRAVgmzfcgjYS91mY5P0TKUDCLEM+gNnA+3T6rWITXRLYCpahpqSQbN5cE+gHpnPyXjHWxcw==", - "dev": true, - "license": "MIT" - }, - "node_modules/@types/hast": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/@types/hast/-/hast-3.0.4.tgz", - "integrity": "sha512-WPs+bbQw5aCj+x6laNGWLH3wviHtoCv/P3+otBhbOhJgG8qtpdAMlTCxLtsTWA7LH1Oh/bFCHsBn0TPS5m30EQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "@types/unist": "*" - } - }, - "node_modules/@types/json-schema": { - "version": "7.0.15", - "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.15.tgz", - "integrity": "sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA==", - "dev": true, - "license": "MIT" - }, - "node_modules/@types/mdast": { - "version": "4.0.4", - "resolved": "https://registry.npmjs.org/@types/mdast/-/mdast-4.0.4.tgz", - "integrity": "sha512-kGaNbPh1k7AFzgpud/gMdvIm5xuECykRR+JnWKQno9TAXVa6WIVCGTPvYGekIDL4uwCZQSYbUxNBSb1aUo79oA==", - "dev": true, - "license": "MIT", - "dependencies": { - "@types/unist": "*" - } - }, - "node_modules/@types/node": { - "version": "22.7.4", - "resolved": "https://registry.npmjs.org/@types/node/-/node-22.7.4.tgz", - "integrity": "sha512-y+NPi1rFzDs1NdQHHToqeiX2TIS79SWEAw9GYhkkx8bD0ChpfqC+n2j5OXOCpzfojBEBt6DnEnnG9MY0zk1XLg==", - "dev": true, - "license": "MIT", - "dependencies": { - "undici-types": "~6.19.2" - } - }, - "node_modules/@types/unist": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/@types/unist/-/unist-3.0.3.tgz", - "integrity": "sha512-ko/gIFJRv177XgZsZcBwnqJN5x/Gien8qNOn0D5bQU/zAzVf9Zt3BlcUiLqhV9y4ARk0GbT3tnUiPNgnTXzc/Q==", - "dev": true, - "license": "MIT" - }, - "node_modules/@typescript-eslint/eslint-plugin": { - "version": "8.8.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-8.8.0.tgz", - "integrity": "sha512-wORFWjU30B2WJ/aXBfOm1LX9v9nyt9D3jsSOxC3cCaTQGCW5k4jNpmjFv3U7p/7s4yvdjHzwtv2Sd2dOyhjS0A==", - "dev": true, - "license": "MIT", - "dependencies": { - "@eslint-community/regexpp": "^4.10.0", - "@typescript-eslint/scope-manager": "8.8.0", - "@typescript-eslint/type-utils": "8.8.0", - "@typescript-eslint/utils": "8.8.0", - "@typescript-eslint/visitor-keys": "8.8.0", - "graphemer": "^1.4.0", - "ignore": "^5.3.1", - "natural-compare": "^1.4.0", - "ts-api-utils": "^1.3.0" - }, - "engines": { - "node": "^18.18.0 || ^20.9.0 || >=21.1.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - }, - "peerDependencies": { - "@typescript-eslint/parser": "^8.0.0 || ^8.0.0-alpha.0", - "eslint": "^8.57.0 || ^9.0.0" - }, - "peerDependenciesMeta": { - "typescript": { - "optional": true - } - } - }, - "node_modules/@typescript-eslint/parser": { - "version": "8.8.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-8.8.0.tgz", - "integrity": "sha512-uEFUsgR+tl8GmzmLjRqz+VrDv4eoaMqMXW7ruXfgThaAShO9JTciKpEsB+TvnfFfbg5IpujgMXVV36gOJRLtZg==", - "dev": true, - "license": "BSD-2-Clause", - "dependencies": { - "@typescript-eslint/scope-manager": "8.8.0", - "@typescript-eslint/types": "8.8.0", - "@typescript-eslint/typescript-estree": "8.8.0", - "@typescript-eslint/visitor-keys": "8.8.0", - "debug": "^4.3.4" - }, - "engines": { - "node": "^18.18.0 || ^20.9.0 || >=21.1.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - }, - "peerDependencies": { - "eslint": "^8.57.0 || ^9.0.0" - }, - "peerDependenciesMeta": { - "typescript": { - "optional": true - } - } - }, - "node_modules/@typescript-eslint/scope-manager": { - "version": "8.8.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-8.8.0.tgz", - "integrity": "sha512-EL8eaGC6gx3jDd8GwEFEV091210U97J0jeEHrAYvIYosmEGet4wJ+g0SYmLu+oRiAwbSA5AVrt6DxLHfdd+bUg==", - "dev": true, - "license": "MIT", - "dependencies": { - "@typescript-eslint/types": "8.8.0", - "@typescript-eslint/visitor-keys": "8.8.0" - }, - "engines": { - "node": "^18.18.0 || ^20.9.0 || >=21.1.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - } - }, - "node_modules/@typescript-eslint/type-utils": { - "version": "8.8.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-8.8.0.tgz", - "integrity": "sha512-IKwJSS7bCqyCeG4NVGxnOP6lLT9Okc3Zj8hLO96bpMkJab+10HIfJbMouLrlpyOr3yrQ1cA413YPFiGd1mW9/Q==", - "dev": true, - "license": "MIT", - "dependencies": { - "@typescript-eslint/typescript-estree": "8.8.0", - "@typescript-eslint/utils": "8.8.0", - "debug": "^4.3.4", - "ts-api-utils": "^1.3.0" - }, - "engines": { - "node": "^18.18.0 || ^20.9.0 || >=21.1.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - }, - "peerDependenciesMeta": { - "typescript": { - "optional": true - } - } - }, - "node_modules/@typescript-eslint/types": { - "version": "8.8.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-8.8.0.tgz", - "integrity": "sha512-QJwc50hRCgBd/k12sTykOJbESe1RrzmX6COk8Y525C9l7oweZ+1lw9JiU56im7Amm8swlz00DRIlxMYLizr2Vw==", - "dev": true, - "license": "MIT", - "engines": { - "node": "^18.18.0 || ^20.9.0 || >=21.1.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - } - }, - "node_modules/@typescript-eslint/typescript-estree": { - "version": "8.8.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-8.8.0.tgz", - "integrity": "sha512-ZaMJwc/0ckLz5DaAZ+pNLmHv8AMVGtfWxZe/x2JVEkD5LnmhWiQMMcYT7IY7gkdJuzJ9P14fRy28lUrlDSWYdw==", - "dev": true, - "license": "BSD-2-Clause", - "dependencies": { - "@typescript-eslint/types": "8.8.0", - "@typescript-eslint/visitor-keys": "8.8.0", - "debug": "^4.3.4", - "fast-glob": "^3.3.2", - "is-glob": "^4.0.3", - "minimatch": "^9.0.4", - "semver": "^7.6.0", - "ts-api-utils": "^1.3.0" - }, - "engines": { - "node": "^18.18.0 || ^20.9.0 || >=21.1.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - }, - "peerDependenciesMeta": { - "typescript": { - "optional": true - } - } - }, - "node_modules/@typescript-eslint/typescript-estree/node_modules/minimatch": { - "version": "9.0.5", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.5.tgz", - "integrity": "sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow==", - "dev": true, - "license": "ISC", - "dependencies": { - "brace-expansion": "^2.0.1" - }, - "engines": { - "node": ">=16 || 14 >=14.17" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, - "node_modules/@typescript-eslint/utils": { - "version": "8.8.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-8.8.0.tgz", - "integrity": "sha512-QE2MgfOTem00qrlPgyByaCHay9yb1+9BjnMFnSFkUKQfu7adBXDTnCAivURnuPPAG/qiB+kzKkZKmKfaMT0zVg==", - "dev": true, - "license": "MIT", - "dependencies": { - "@eslint-community/eslint-utils": "^4.4.0", - "@typescript-eslint/scope-manager": "8.8.0", - "@typescript-eslint/types": "8.8.0", - "@typescript-eslint/typescript-estree": "8.8.0" - }, - "engines": { - "node": "^18.18.0 || ^20.9.0 || >=21.1.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - }, - "peerDependencies": { - "eslint": "^8.57.0 || ^9.0.0" - } - }, - "node_modules/@typescript-eslint/visitor-keys": { - "version": "8.8.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-8.8.0.tgz", - "integrity": "sha512-8mq51Lx6Hpmd7HnA2fcHQo3YgfX1qbccxQOgZcb4tvasu//zXRaA1j5ZRFeCw/VRAdFi4mRM9DnZw0Nu0Q2d1g==", - "dev": true, - "license": "MIT", - "dependencies": { - "@typescript-eslint/types": "8.8.0", - "eslint-visitor-keys": "^3.4.3" - }, - "engines": { - "node": "^18.18.0 || ^20.9.0 || >=21.1.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - } - }, - "node_modules/@typescript-eslint/visitor-keys/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, - "license": "Apache-2.0", - "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" - }, - "funding": { - "url": "https://opencollective.com/eslint" - } - }, - "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, - "license": "ISC" - }, - "node_modules/acorn": { - "version": "8.12.1", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.12.1.tgz", - "integrity": "sha512-tcpGyI9zbizT9JbV6oYE477V6mTlXvvi0T0G3SNIYE2apm/G5huBa1+K89VGeovbg+jycCrfhl3ADxErOuO6Jg==", - "dev": true, - "license": "MIT", - "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, - "license": "MIT", - "peerDependencies": { - "acorn": "^6.0.0 || ^7.0.0 || ^8.0.0" - } - }, - "node_modules/acorn-walk": { - "version": "8.3.4", - "resolved": "https://registry.npmjs.org/acorn-walk/-/acorn-walk-8.3.4.tgz", - "integrity": "sha512-ueEepnujpqee2o5aIYnvHU6C0A42MNdsIDeqy5BydrkuC5R1ZuUFnm27EeFJGoEHJQgn3uleRvmTXaJgfXbt4g==", - "dev": true, - "license": "MIT", - "dependencies": { - "acorn": "^8.11.0" - }, - "engines": { - "node": ">=0.4.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, - "license": "MIT", - "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-regex": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.1.0.tgz", - "integrity": "sha512-7HSX4QQb4CspciLpVFwyRe79O3xsIZDDLER21kERQ71oaPodF8jL725AgJMFAYbooIqolJoRLuM81SpeUkpkvA==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/chalk/ansi-regex?sponsor=1" - } - }, - "node_modules/ansi-styles": { - "version": "6.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-6.2.1.tgz", - "integrity": "sha512-bN798gFfQX+viw3R7yrGWRqnrN2oRkEkUjjl4JNn4E8GxxbjtG3FbrEIIY3l8/hrwUwIeCZvi4QuOTP4MErVug==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=12" - }, - "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/anymatch/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/arg": { - "version": "4.1.3", - "resolved": "https://registry.npmjs.org/arg/-/arg-4.1.3.tgz", - "integrity": "sha512-58S9QDqG0Xx27YwPSt9fJxivjYl432YCwfDMfZ+71RAqUrZef7LrKQZ3LHLOwCS4FLNBplP533Zx895SeOCHvA==", - "dev": true, - "license": "MIT" - }, -<<<<<<< HEAD - "node_modules/array-union": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/array-union/-/array-union-2.1.0.tgz", - "integrity": "sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw==", - "dev": true, - "engines": { - "node": ">=8" - } -======= - "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, - "license": "Python-2.0" ->>>>>>> dev - }, - "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, - "license": "MIT" - }, - "node_modules/binary-extensions": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.3.0.tgz", - "integrity": "sha512-Ceh+7ox5qe7LJuLHoY0feh3pHuUDHAcRUeyL2VYghZwfpkNIy/+8Ocg0a3UuSoYzavmylwuLWQOf3hl0jjMMIw==", - "dev": true, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/brace-expansion": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", - "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", - "dev": true, - "license": "MIT", - "dependencies": { - "balanced-match": "^1.0.0" - } - }, - "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, -<<<<<<< HEAD -======= - "license": "MIT", ->>>>>>> dev - "dependencies": { - "fill-range": "^7.1.1" - }, - "engines": { - "node": ">=8" - } - }, -<<<<<<< HEAD - "node_modules/chokidar": { - "version": "3.6.0", - "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.6.0.tgz", - "integrity": "sha512-7VT13fmjotKpGipCW9JEQAusEPE+Ei8nl6/g4FBAmIm0GOOLMua9NDDo/DWp0ZAxCr3cPq5ZpBqmPAQgDda2Pw==", - "dev": true, - "dependencies": { - "anymatch": "~3.1.2", - "braces": "~3.0.2", - "glob-parent": "~5.1.2", - "is-binary-path": "~2.1.0", - "is-glob": "~4.0.1", - "normalize-path": "~3.0.0", - "readdirp": "~3.6.0" - }, - "engines": { - "node": ">= 8.10.0" - }, - "funding": { - "url": "https://paulmillr.com/funding/" - }, - "optionalDependencies": { - "fsevents": "~2.3.2" -======= - "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, - "license": "MIT", - "engines": { - "node": ">=6" - } - }, - "node_modules/ccount": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/ccount/-/ccount-2.0.1.tgz", - "integrity": "sha512-eyrF0jiFpY+3drT6383f1qhkbGsLSifNAjA61IUjZjmLCWjItY6LB9ft9YhoDgwfmclB2zhu51Lc7+95b8NRAg==", - "dev": true, - "license": "MIT", - "funding": { - "type": "github", - "url": "https://github.com/sponsors/wooorm" - } - }, - "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, - "license": "MIT", - "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/chalk/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, - "license": "MIT", - "dependencies": { - "color-convert": "^2.0.1" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" - } - }, - "node_modules/character-entities-html4": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/character-entities-html4/-/character-entities-html4-2.1.0.tgz", - "integrity": "sha512-1v7fgQRj6hnSwFpq1Eu0ynr/CDEw0rXo2B61qXrLNdHZmPKgb7fqS1a2JwF0rISo9q77jDI8VMEHoApn8qDoZA==", - "dev": true, - "license": "MIT", - "funding": { - "type": "github", - "url": "https://github.com/sponsors/wooorm" - } - }, - "node_modules/character-entities-legacy": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/character-entities-legacy/-/character-entities-legacy-3.0.0.tgz", - "integrity": "sha512-RpPp0asT/6ufRm//AJVwpViZbGM/MkjQFxJccQRHmISF/22NBtsHqAWmL+/pmkPWoIUJdWyeVleTl1wydHATVQ==", - "dev": true, - "license": "MIT", - "funding": { - "type": "github", - "url": "https://github.com/sponsors/wooorm" ->>>>>>> dev - } - }, - "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, - "license": "MIT", - "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, - "license": "MIT" - }, -<<<<<<< HEAD - "node_modules/commander": { - "version": "9.5.0", - "resolved": "https://registry.npmjs.org/commander/-/commander-9.5.0.tgz", - "integrity": "sha512-KRs7WVDKg86PWiuAqhDrAQnTXZKraVcCc6vFdL14qrZ/DcWwuRo7VoiYXalXO7S5GKpqYiVEwCbgFDfxNHKJBQ==", - "dev": true, - "engines": { - "node": "^12.20.0 || >=14" - } - }, -======= - "node_modules/comma-separated-tokens": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/comma-separated-tokens/-/comma-separated-tokens-2.0.3.tgz", - "integrity": "sha512-Fu4hJdvzeylCfQPp9SGWidpzrMs7tTrlu6Vb8XGaRGck8QSNZJJp538Wrb60Lax4fPwR64ViY468OIUTbRlGZg==", - "dev": true, - "license": "MIT", - "funding": { - "type": "github", - "url": "https://github.com/sponsors/wooorm" - } - }, - "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, - "license": "MIT" - }, ->>>>>>> dev - "node_modules/create-require": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/create-require/-/create-require-1.1.1.tgz", - "integrity": "sha512-dcKFX3jn0MpIaXjisoRvexIJVEKzaq7z2rZKxf+MSr9TkdmHmsU4m2lcLojrj/FHl8mk5VxMmYA+ftRkP/3oKQ==", - "dev": true, - "license": "MIT" - }, - "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, - "license": "MIT", - "dependencies": { - "path-key": "^3.1.0", - "shebang-command": "^2.0.0", - "which": "^2.0.1" - }, - "engines": { - "node": ">= 8" - } - }, - "node_modules/debug": { - "version": "4.3.7", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.7.tgz", - "integrity": "sha512-Er2nc/H7RrMXZBFCEim6TCmMk02Z8vLC2Rbi1KEBggpo0fS6l0S1nnapwmIi3yW/+GOJap1Krg4w0Hg80oCqgQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "ms": "^2.1.3" - }, - "engines": { - "node": ">=6.0" - }, - "peerDependenciesMeta": { - "supports-color": { - "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, - "license": "MIT" - }, - "node_modules/dequal": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/dequal/-/dequal-2.0.3.tgz", - "integrity": "sha512-0je+qPKHEMohvfRTCEo3CrPG6cAzAYgmzKyxRiYSSDkS6eGJdyVJm7WaYA5ECaAD9wLB2T4EEeymA5aFVcYXCA==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=6" - } - }, - "node_modules/devlop": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/devlop/-/devlop-1.1.0.tgz", - "integrity": "sha512-RWmIqhcFf1lRYBvNmr7qTNuyCt/7/ns2jbpp1+PalgE/rDQcBT0fioSMUpJ93irlUhC5hrg4cYqe6U+0ImW0rA==", - "dev": true, - "license": "MIT", - "dependencies": { - "dequal": "^2.0.0" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/wooorm" - } - }, - "node_modules/diff": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/diff/-/diff-4.0.2.tgz", - "integrity": "sha512-58lmxKSA4BNyLz+HHMUzlOEpg09FV+ev6ZMe3vJihgdxzgcwZ8VoEEPmALCZG9LmqfVoNMMKpttIYTVG6uDY7A==", - "dev": true, - "license": "BSD-3-Clause", - "engines": { - "node": ">=0.3.1" - } - }, - "node_modules/dir-glob": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/dir-glob/-/dir-glob-3.0.1.tgz", - "integrity": "sha512-WkrWp9GR4KXfKGYzOLmTuGVi1UWFfws377n9cc55/tb6DuqyF6pcQ5AbiHEshaDpY9v6oaSr2XCDidGmMwdzIA==", - "dev": true, - "dependencies": { - "path-type": "^4.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/eastasianwidth": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/eastasianwidth/-/eastasianwidth-0.2.0.tgz", - "integrity": "sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA==", - "dev": true, - "license": "MIT" - }, - "node_modules/emoji-regex": { - "version": "9.2.2", - "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-9.2.2.tgz", - "integrity": "sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==", - "dev": true, - "license": "MIT" - }, - "node_modules/entities": { - "version": "4.5.0", - "resolved": "https://registry.npmjs.org/entities/-/entities-4.5.0.tgz", - "integrity": "sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw==", - "dev": true, - "license": "BSD-2-Clause", - "engines": { - "node": ">=0.12" - }, - "funding": { - "url": "https://github.com/fb55/entities?sponsor=1" - } - }, - "node_modules/esbuild": { - "version": "0.23.1", - "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.23.1.tgz", - "integrity": "sha512-VVNz/9Sa0bs5SELtn3f7qhJCDPCF5oMEl5cO9/SSinpE9hbPVvxbd572HH5AKiP7WD8INO53GgfDDhRjkylHEg==", - "dev": true, - "hasInstallScript": true, - "license": "MIT", - "bin": { - "esbuild": "bin/esbuild" - }, - "engines": { - "node": ">=18" - }, - "optionalDependencies": { - "@esbuild/aix-ppc64": "0.23.1", - "@esbuild/android-arm": "0.23.1", - "@esbuild/android-arm64": "0.23.1", - "@esbuild/android-x64": "0.23.1", - "@esbuild/darwin-arm64": "0.23.1", - "@esbuild/darwin-x64": "0.23.1", - "@esbuild/freebsd-arm64": "0.23.1", - "@esbuild/freebsd-x64": "0.23.1", - "@esbuild/linux-arm": "0.23.1", - "@esbuild/linux-arm64": "0.23.1", - "@esbuild/linux-ia32": "0.23.1", - "@esbuild/linux-loong64": "0.23.1", - "@esbuild/linux-mips64el": "0.23.1", - "@esbuild/linux-ppc64": "0.23.1", - "@esbuild/linux-riscv64": "0.23.1", - "@esbuild/linux-s390x": "0.23.1", - "@esbuild/linux-x64": "0.23.1", - "@esbuild/netbsd-x64": "0.23.1", - "@esbuild/openbsd-arm64": "0.23.1", - "@esbuild/openbsd-x64": "0.23.1", - "@esbuild/sunos-x64": "0.23.1", - "@esbuild/win32-arm64": "0.23.1", - "@esbuild/win32-ia32": "0.23.1", - "@esbuild/win32-x64": "0.23.1" - } - }, -<<<<<<< HEAD -======= - "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, - "license": "MIT", - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/eslint": { - "version": "9.12.0", - "resolved": "https://registry.npmjs.org/eslint/-/eslint-9.12.0.tgz", - "integrity": "sha512-UVIOlTEWxwIopRL1wgSQYdnVDcEvs2wyaO6DGo5mXqe3r16IoCNWkR29iHhyaP4cICWjbgbmFUGAhh0GJRuGZw==", - "dev": true, - "license": "MIT", - "dependencies": { - "@eslint-community/eslint-utils": "^4.2.0", - "@eslint-community/regexpp": "^4.11.0", - "@eslint/config-array": "^0.18.0", - "@eslint/core": "^0.6.0", - "@eslint/eslintrc": "^3.1.0", - "@eslint/js": "9.12.0", - "@eslint/plugin-kit": "^0.2.0", - "@humanfs/node": "^0.16.5", - "@humanwhocodes/module-importer": "^1.0.1", - "@humanwhocodes/retry": "^0.3.1", - "@types/estree": "^1.0.6", - "@types/json-schema": "^7.0.15", - "ajv": "^6.12.4", - "chalk": "^4.0.0", - "cross-spawn": "^7.0.2", - "debug": "^4.3.2", - "escape-string-regexp": "^4.0.0", - "eslint-scope": "^8.1.0", - "eslint-visitor-keys": "^4.1.0", - "espree": "^10.2.0", - "esquery": "^1.5.0", - "esutils": "^2.0.2", - "fast-deep-equal": "^3.1.3", - "file-entry-cache": "^8.0.0", - "find-up": "^5.0.0", - "glob-parent": "^6.0.2", - "ignore": "^5.2.0", - "imurmurhash": "^0.1.4", - "is-glob": "^4.0.0", - "json-stable-stringify-without-jsonify": "^1.0.1", - "lodash.merge": "^4.6.2", - "minimatch": "^3.1.2", - "natural-compare": "^1.4.0", - "optionator": "^0.9.3", - "text-table": "^0.2.0" - }, - "bin": { - "eslint": "bin/eslint.js" - }, - "engines": { - "node": "^18.18.0 || ^20.9.0 || >=21.1.0" - }, - "funding": { - "url": "https://eslint.org/donate" - }, - "peerDependencies": { - "jiti": "*" - }, - "peerDependenciesMeta": { - "jiti": { - "optional": true - } - } - }, - "node_modules/eslint-scope": { - "version": "8.1.0", - "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-8.1.0.tgz", - "integrity": "sha512-14dSvlhaVhKKsa9Fx1l8A17s7ah7Ef7wCakJ10LYk6+GYmP9yDti2oq2SEwcyndt6knfcZyhyxwY3i9yL78EQw==", - "dev": true, - "license": "BSD-2-Clause", - "dependencies": { - "esrecurse": "^4.3.0", - "estraverse": "^5.2.0" - }, - "engines": { - "node": "^18.18.0 || ^20.9.0 || >=21.1.0" - }, - "funding": { - "url": "https://opencollective.com/eslint" - } - }, - "node_modules/eslint-visitor-keys": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-4.1.0.tgz", - "integrity": "sha512-Q7lok0mqMUSf5a/AdAZkA5a/gHcO6snwQClVNNvFKCAVlxXucdU8pKydU5ZVZjBx5xr37vGbFFWtLQYreLzrZg==", - "dev": true, - "license": "Apache-2.0", - "engines": { - "node": "^18.18.0 || ^20.9.0 || >=21.1.0" - }, - "funding": { - "url": "https://opencollective.com/eslint" - } - }, - "node_modules/eslint/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, - "license": "MIT", - "dependencies": { - "balanced-match": "^1.0.0", - "concat-map": "0.0.1" - } - }, - "node_modules/eslint/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, - "license": "ISC", - "dependencies": { - "brace-expansion": "^1.1.7" - }, - "engines": { - "node": "*" - } - }, - "node_modules/espree": { - "version": "10.2.0", - "resolved": "https://registry.npmjs.org/espree/-/espree-10.2.0.tgz", - "integrity": "sha512-upbkBJbckcCNBDBDXEbuhjbP68n+scUd3k/U2EkyM9nw+I/jPiL4cLF/Al06CF96wRltFda16sxDFrxsI1v0/g==", - "dev": true, - "license": "BSD-2-Clause", - "dependencies": { - "acorn": "^8.12.0", - "acorn-jsx": "^5.3.2", - "eslint-visitor-keys": "^4.1.0" - }, - "engines": { - "node": "^18.18.0 || ^20.9.0 || >=21.1.0" - }, - "funding": { - "url": "https://opencollective.com/eslint" - } - }, - "node_modules/esquery": { - "version": "1.6.0", - "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.6.0.tgz", - "integrity": "sha512-ca9pw9fomFcKPvFLXhBKUK90ZvGibiGOvRJNbjljY7s7uq/5YO4BOzcYtJqExdx99rF6aAcnRxHmcUHcz6sQsg==", - "dev": true, - "license": "BSD-3-Clause", - "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, - "license": "BSD-2-Clause", - "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, - "license": "BSD-2-Clause", - "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, - "license": "BSD-2-Clause", - "engines": { - "node": ">=0.10.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, - "license": "MIT" - }, ->>>>>>> dev - "node_modules/fast-glob": { - "version": "3.3.2", - "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.3.2.tgz", - "integrity": "sha512-oX2ruAFQwf/Orj8m737Y5adxDQO0LAB7/S5MnxCdTNDd4p6BsyIVsv9JQsATbTSq8KHRpLwIHbVlUNatxd+1Ow==", - "dev": true, -<<<<<<< HEAD -======= - "license": "MIT", ->>>>>>> dev - "dependencies": { - "@nodelib/fs.stat": "^2.0.2", - "@nodelib/fs.walk": "^1.2.3", - "glob-parent": "^5.1.2", - "merge2": "^1.3.0", - "micromatch": "^4.0.4" - }, - "engines": { - "node": ">=8.6.0" - } - }, -<<<<<<< HEAD -======= - "node_modules/fast-glob/node_modules/glob-parent": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", - "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", - "dev": true, - "license": "ISC", - "dependencies": { - "is-glob": "^4.0.1" - }, - "engines": { - "node": ">= 6" - } - }, - "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, - "license": "MIT" - }, - "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, - "license": "MIT" - }, ->>>>>>> dev - "node_modules/fastq": { - "version": "1.17.1", - "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.17.1.tgz", - "integrity": "sha512-sRVD3lWVIXWg6By68ZN7vho9a1pQcN/WBFaAAsDDFzlJjvoGx0P8z7V1t72grFJfJhu3YPZBuu25f7Kaw2jN1w==", - "dev": true, -<<<<<<< HEAD -======= - "license": "ISC", ->>>>>>> dev - "dependencies": { - "reusify": "^1.0.4" - } - }, -<<<<<<< HEAD -======= - "node_modules/file-entry-cache": { - "version": "8.0.0", - "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-8.0.0.tgz", - "integrity": "sha512-XXTUwCvisa5oacNGRP9SfNtYBNAMi+RPwBFmblZEF7N7swHYQS6/Zfk7SRwx4D5j3CH211YNRco1DEMNVfZCnQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "flat-cache": "^4.0.0" - }, - "engines": { - "node": ">=16.0.0" - } - }, ->>>>>>> dev - "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, -<<<<<<< HEAD -======= - "license": "MIT", ->>>>>>> dev - "dependencies": { - "to-regex-range": "^5.0.1" - }, - "engines": { - "node": ">=8" - } - }, -<<<<<<< HEAD -======= - "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, - "license": "MIT", - "dependencies": { - "locate-path": "^6.0.0", - "path-exists": "^4.0.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/flat-cache": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-4.0.1.tgz", - "integrity": "sha512-f7ccFPK3SXFHpx15UIGyRJ/FJQctuKZ0zVuN3frBo4HnK3cay9VEW0R6yPYFHC0AgqhukPzKjq22t5DmAyqGyw==", - "dev": true, - "license": "MIT", - "dependencies": { - "flatted": "^3.2.9", - "keyv": "^4.5.4" - }, - "engines": { - "node": ">=16" - } - }, - "node_modules/flatted": { - "version": "3.3.1", - "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.3.1.tgz", - "integrity": "sha512-X8cqMLLie7KsNUDSdzeN8FYK9rEt4Dt67OsG/DNGnYTSDBG4uFAJFBnUeiV+zCVAvwFy56IjM9sH51jVaEhNxw==", - "dev": true, - "license": "ISC" - }, ->>>>>>> dev - "node_modules/foreground-child": { - "version": "3.3.0", - "resolved": "https://registry.npmjs.org/foreground-child/-/foreground-child-3.3.0.tgz", - "integrity": "sha512-Ld2g8rrAyMYFXBhEqMz8ZAHBi4J4uS1i/CxGMDnjyFWddMXLVcDp051DZfu+t7+ab7Wv6SMqpWmyFIj5UbfFvg==", - "dev": true, - "license": "ISC", - "dependencies": { - "cross-spawn": "^7.0.0", - "signal-exit": "^4.0.1" - }, - "engines": { - "node": ">=14" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, - "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, - "license": "MIT", - "optional": true, - "os": [ - "darwin" - ], - "engines": { - "node": "^8.16.0 || ^10.6.0 || >=11.0.0" - } - }, - "node_modules/get-tsconfig": { - "version": "4.8.1", - "resolved": "https://registry.npmjs.org/get-tsconfig/-/get-tsconfig-4.8.1.tgz", - "integrity": "sha512-k9PN+cFBmaLWtVz29SkUoqU5O0slLuHJXt/2P+tMVFT+phsSGXGkp9t3rQIqdz0e+06EHNGs3oM6ZX1s2zHxRg==", - "dev": true, - "license": "MIT", - "dependencies": { - "resolve-pkg-maps": "^1.0.0" - }, - "funding": { - "url": "https://github.com/privatenumber/get-tsconfig?sponsor=1" - } - }, - "node_modules/glob": { - "version": "11.0.0", - "resolved": "https://registry.npmjs.org/glob/-/glob-11.0.0.tgz", - "integrity": "sha512-9UiX/Bl6J2yaBbxKoEBRm4Cipxgok8kQYcOPEhScPwebu2I0HoQOuYdIO6S3hLuWoZgpDpwQZMzTFxgpkyT76g==", - "dev": true, - "license": "ISC", - "dependencies": { - "foreground-child": "^3.1.0", - "jackspeak": "^4.0.1", - "minimatch": "^10.0.0", - "minipass": "^7.1.2", - "package-json-from-dist": "^1.0.0", - "path-scurry": "^2.0.0" - }, - "bin": { - "glob": "dist/esm/bin.mjs" - }, - "engines": { - "node": "20 || >=22" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, - "node_modules/glob-parent": { -<<<<<<< HEAD - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", - "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", - "dev": true, - "dependencies": { - "is-glob": "^4.0.1" - }, - "engines": { - "node": ">= 6" - } - }, - "node_modules/globby": { - "version": "11.1.0", - "resolved": "https://registry.npmjs.org/globby/-/globby-11.1.0.tgz", - "integrity": "sha512-jhIXaOzy1sb8IyocaruWSn1TjmnBVs8Ayhcy83rmxNJ8q2uWKCAj3CnJY+KpGSXCueAPc0i05kVvVKtP1t9S3g==", - "dev": true, - "dependencies": { - "array-union": "^2.1.0", - "dir-glob": "^3.0.1", - "fast-glob": "^3.2.9", - "ignore": "^5.2.0", - "merge2": "^1.4.1", - "slash": "^3.0.0" - }, - "engines": { - "node": ">=10" -======= - "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, - "license": "ISC", - "dependencies": { - "is-glob": "^4.0.3" - }, - "engines": { - "node": ">=10.13.0" - } - }, - "node_modules/globals": { - "version": "14.0.0", - "resolved": "https://registry.npmjs.org/globals/-/globals-14.0.0.tgz", - "integrity": "sha512-oahGvuMGQlPw/ivIYBjVSrWAfWLBeku5tpPE2fOPLi+WHffIWbuh2tCjhyQhTBPMf5E9jDEH4FOmTYgYwbKwtQ==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=18" ->>>>>>> dev - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, -<<<<<<< HEAD -======= - "node_modules/graphemer": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/graphemer/-/graphemer-1.4.0.tgz", - "integrity": "sha512-EtKwoO6kxCL9WO5xipiHTZlSzBm7WLT627TqC/uVRd0HKmq8NXyebnNYxDoBi7wt8eTWrUrKXCOVaFq9x1kgag==", - "dev": true, - "license": "MIT" - }, - "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, - "license": "MIT", - "engines": { - "node": ">=8" - } - }, - "node_modules/hast-util-to-html": { - "version": "9.0.3", - "resolved": "https://registry.npmjs.org/hast-util-to-html/-/hast-util-to-html-9.0.3.tgz", - "integrity": "sha512-M17uBDzMJ9RPCqLMO92gNNUDuBSq10a25SDBI08iCCxmorf4Yy6sYHK57n9WAbRAAaU+DuR4W6GN9K4DFZesYg==", - "dev": true, - "license": "MIT", - "dependencies": { - "@types/hast": "^3.0.0", - "@types/unist": "^3.0.0", - "ccount": "^2.0.0", - "comma-separated-tokens": "^2.0.0", - "hast-util-whitespace": "^3.0.0", - "html-void-elements": "^3.0.0", - "mdast-util-to-hast": "^13.0.0", - "property-information": "^6.0.0", - "space-separated-tokens": "^2.0.0", - "stringify-entities": "^4.0.0", - "zwitch": "^2.0.4" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, - "node_modules/hast-util-whitespace": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/hast-util-whitespace/-/hast-util-whitespace-3.0.0.tgz", - "integrity": "sha512-88JUN06ipLwsnv+dVn+OIYOvAuvBMy/Qoi6O7mQHxdPXpjy+Cd6xRkWwux7DKO+4sYILtLBRIKgsdpS2gQc7qw==", - "dev": true, - "license": "MIT", - "dependencies": { - "@types/hast": "^3.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, - "node_modules/html-void-elements": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/html-void-elements/-/html-void-elements-3.0.0.tgz", - "integrity": "sha512-bEqo66MRXsUGxWHV5IP0PUiAWwoEjba4VCzg0LjFJBpchPaTfyfCKTG6bc5F8ucKec3q5y6qOdGyYTSBEvhCrg==", - "dev": true, - "license": "MIT", - "funding": { - "type": "github", - "url": "https://github.com/sponsors/wooorm" - } - }, ->>>>>>> dev - "node_modules/ignore": { - "version": "5.3.2", - "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.3.2.tgz", - "integrity": "sha512-hsBTNUqQTDwkWtcdYI2i06Y/nUBEsNEDJKjWdigLvegy8kDuJAS8uRlpkkcQpyEXL0Z/pjDy5HBmMjRCJ2gq+g==", - "dev": true, -<<<<<<< HEAD -======= - "license": "MIT", ->>>>>>> dev - "engines": { - "node": ">= 4" - } - }, -<<<<<<< HEAD - "node_modules/is-binary-path": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz", - "integrity": "sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==", - "dev": true, - "dependencies": { - "binary-extensions": "^2.0.0" - }, - "engines": { - "node": ">=8" -======= - "node_modules/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, - "license": "MIT", - "dependencies": { - "parent-module": "^1.0.0", - "resolve-from": "^4.0.0" - }, - "engines": { - "node": ">=6" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/imurmurhash": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz", - "integrity": "sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=0.8.19" ->>>>>>> dev - } - }, - "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, -<<<<<<< HEAD -======= - "license": "MIT", ->>>>>>> dev - "engines": { - "node": ">=0.10.0" - } - }, - "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, - "license": "MIT", - "engines": { - "node": ">=8" - } - }, - "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, -<<<<<<< HEAD -======= - "license": "MIT", ->>>>>>> dev - "dependencies": { - "is-extglob": "^2.1.1" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "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, -<<<<<<< HEAD -======= - "license": "MIT", ->>>>>>> dev - "engines": { - "node": ">=0.12.0" - } - }, - "node_modules/isexe": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", - "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==", - "dev": true, - "license": "ISC" - }, - "node_modules/jackspeak": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/jackspeak/-/jackspeak-4.0.2.tgz", - "integrity": "sha512-bZsjR/iRjl1Nk1UkjGpAzLNfQtzuijhn2g+pbZb98HQ1Gk8vM9hfbxeMBP+M2/UUdwj0RqGG3mlvk2MsAqwvEw==", - "dev": true, - "license": "BlueOak-1.0.0", - "dependencies": { - "@isaacs/cliui": "^8.0.2" - }, - "engines": { - "node": "20 || >=22" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, - "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, - "license": "MIT", - "dependencies": { - "argparse": "^2.0.1" - }, - "bin": { - "js-yaml": "bin/js-yaml.js" - } - }, - "node_modules/json-buffer": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/json-buffer/-/json-buffer-3.0.1.tgz", - "integrity": "sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ==", - "dev": true, - "license": "MIT" - }, - "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, - "license": "MIT" - }, - "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, - "license": "MIT" - }, - "node_modules/keyv": { - "version": "4.5.4", - "resolved": "https://registry.npmjs.org/keyv/-/keyv-4.5.4.tgz", - "integrity": "sha512-oxVHkHR/EJf2CNXnWxRLW6mg7JyCCUcG0DtEGmL2ctUo1PNTin1PUil+r/+4r5MpVgC/fn1kjsx7mjSujKqIpw==", - "dev": true, - "license": "MIT", - "dependencies": { - "json-buffer": "3.0.1" - } - }, - "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, - "license": "MIT", - "dependencies": { - "prelude-ls": "^1.2.1", - "type-check": "~0.4.0" - }, - "engines": { - "node": ">= 0.8.0" - } - }, - "node_modules/linkify-it": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/linkify-it/-/linkify-it-5.0.0.tgz", - "integrity": "sha512-5aHCbzQRADcdP+ATqnDuhhJ/MRIqDkZX5pyjFHRRysS8vZ5AbqGEoFIb6pYHPZ+L/OC2Lc+xT8uHVVR5CAK/wQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "uc.micro": "^2.0.0" - } - }, - "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, - "license": "MIT", - "dependencies": { - "p-locate": "^5.0.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "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, - "license": "MIT" - }, - "node_modules/lru-cache": { - "version": "11.0.1", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-11.0.1.tgz", - "integrity": "sha512-CgeuL5uom6j/ZVrg7G/+1IXqRY8JXX4Hghfy5YE0EhoYQWvndP1kufu58cmZLNIDKnRhZrXfdS9urVWx98AipQ==", - "dev": true, - "license": "ISC", - "engines": { - "node": "20 || >=22" - } - }, - "node_modules/lunr": { - "version": "2.3.9", - "resolved": "https://registry.npmjs.org/lunr/-/lunr-2.3.9.tgz", - "integrity": "sha512-zTU3DaZaF3Rt9rhN3uBMGQD3dD2/vFQqnvZCDv4dl5iOzq2IZQqTxu90r4E5J+nP70J3ilqVCrbho2eWaeW8Ow==", - "dev": true, - "license": "MIT" - }, - "node_modules/make-error": { - "version": "1.3.6", - "resolved": "https://registry.npmjs.org/make-error/-/make-error-1.3.6.tgz", - "integrity": "sha512-s8UhlNe7vPKomQhC1qFelMokr/Sc3AgNbso3n74mVPA5LTZwkB9NlXf4XPamLxJE8h0gh73rM94xvwRT2CVInw==", - "dev": true, - "license": "ISC" - }, -<<<<<<< HEAD -======= - "node_modules/markdown-it": { - "version": "14.1.0", - "resolved": "https://registry.npmjs.org/markdown-it/-/markdown-it-14.1.0.tgz", - "integrity": "sha512-a54IwgWPaeBCAAsv13YgmALOF1elABB08FxO9i+r4VFk5Vl4pKokRPeX8u5TCgSsPi6ec1otfLjdOpVcgbpshg==", - "dev": true, - "license": "MIT", - "dependencies": { - "argparse": "^2.0.1", - "entities": "^4.4.0", - "linkify-it": "^5.0.0", - "mdurl": "^2.0.0", - "punycode.js": "^2.3.1", - "uc.micro": "^2.1.0" - }, - "bin": { - "markdown-it": "bin/markdown-it.mjs" - } - }, - "node_modules/mdast-util-to-hast": { - "version": "13.2.0", - "resolved": "https://registry.npmjs.org/mdast-util-to-hast/-/mdast-util-to-hast-13.2.0.tgz", - "integrity": "sha512-QGYKEuUsYT9ykKBCMOEDLsU5JRObWQusAolFMeko/tYPufNkRffBAQjIE+99jbA87xv6FgmjLtwjh9wBWajwAA==", - "dev": true, - "license": "MIT", - "dependencies": { - "@types/hast": "^3.0.0", - "@types/mdast": "^4.0.0", - "@ungap/structured-clone": "^1.0.0", - "devlop": "^1.0.0", - "micromark-util-sanitize-uri": "^2.0.0", - "trim-lines": "^3.0.0", - "unist-util-position": "^5.0.0", - "unist-util-visit": "^5.0.0", - "vfile": "^6.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, - "node_modules/mdurl": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/mdurl/-/mdurl-2.0.0.tgz", - "integrity": "sha512-Lf+9+2r+Tdp5wXDXC4PcIBjTDtq4UKjCPMQhKIuzpJNW0b96kVqSwW0bT7FhRSfmAiFYgP+SCRvdrDozfh0U5w==", - "dev": true, - "license": "MIT" - }, ->>>>>>> dev - "node_modules/merge2": { - "version": "1.4.1", - "resolved": "https://registry.npmjs.org/merge2/-/merge2-1.4.1.tgz", - "integrity": "sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==", - "dev": true, -<<<<<<< HEAD -======= - "license": "MIT", ->>>>>>> dev - "engines": { - "node": ">= 8" - } - }, -<<<<<<< HEAD -======= - "node_modules/micromark-util-character": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/micromark-util-character/-/micromark-util-character-2.1.0.tgz", - "integrity": "sha512-KvOVV+X1yLBfs9dCBSopq/+G1PcgT3lAK07mC4BzXi5E7ahzMAF8oIupDDJ6mievI6F+lAATkbQQlQixJfT3aQ==", - "dev": true, - "funding": [ - { - "type": "GitHub Sponsors", - "url": "https://github.com/sponsors/unifiedjs" - }, - { - "type": "OpenCollective", - "url": "https://opencollective.com/unified" - } - ], - "license": "MIT", - "dependencies": { - "micromark-util-symbol": "^2.0.0", - "micromark-util-types": "^2.0.0" - } - }, - "node_modules/micromark-util-encode": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/micromark-util-encode/-/micromark-util-encode-2.0.0.tgz", - "integrity": "sha512-pS+ROfCXAGLWCOc8egcBvT0kf27GoWMqtdarNfDcjb6YLuV5cM3ioG45Ys2qOVqeqSbjaKg72vU+Wby3eddPsA==", - "dev": true, - "funding": [ - { - "type": "GitHub Sponsors", - "url": "https://github.com/sponsors/unifiedjs" - }, - { - "type": "OpenCollective", - "url": "https://opencollective.com/unified" - } - ], - "license": "MIT" - }, - "node_modules/micromark-util-sanitize-uri": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/micromark-util-sanitize-uri/-/micromark-util-sanitize-uri-2.0.0.tgz", - "integrity": "sha512-WhYv5UEcZrbAtlsnPuChHUAsu/iBPOVaEVsntLBIdpibO0ddy8OzavZz3iL2xVvBZOpolujSliP65Kq0/7KIYw==", - "dev": true, - "funding": [ - { - "type": "GitHub Sponsors", - "url": "https://github.com/sponsors/unifiedjs" - }, - { - "type": "OpenCollective", - "url": "https://opencollective.com/unified" - } - ], - "license": "MIT", - "dependencies": { - "micromark-util-character": "^2.0.0", - "micromark-util-encode": "^2.0.0", - "micromark-util-symbol": "^2.0.0" - } - }, - "node_modules/micromark-util-symbol": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/micromark-util-symbol/-/micromark-util-symbol-2.0.0.tgz", - "integrity": "sha512-8JZt9ElZ5kyTnO94muPxIGS8oyElRJaiJO8EzV6ZSyGQ1Is8xwl4Q45qU5UOg+bGH4AikWziz0iN4sFLWs8PGw==", - "dev": true, - "funding": [ - { - "type": "GitHub Sponsors", - "url": "https://github.com/sponsors/unifiedjs" - }, - { - "type": "OpenCollective", - "url": "https://opencollective.com/unified" - } - ], - "license": "MIT" - }, - "node_modules/micromark-util-types": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/micromark-util-types/-/micromark-util-types-2.0.0.tgz", - "integrity": "sha512-oNh6S2WMHWRZrmutsRmDDfkzKtxF+bc2VxLC9dvtrDIRFln627VsFP6fLMgTryGDljgLPjkrzQSDcPrjPyDJ5w==", - "dev": true, - "funding": [ - { - "type": "GitHub Sponsors", - "url": "https://github.com/sponsors/unifiedjs" - }, - { - "type": "OpenCollective", - "url": "https://opencollective.com/unified" - } - ], - "license": "MIT" - }, ->>>>>>> dev - "node_modules/micromatch": { - "version": "4.0.8", - "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.8.tgz", - "integrity": "sha512-PXwfBhYu0hBCPw8Dn0E+WDYb7af3dSLVWKi3HGv84IdF4TyFoC0ysxFd0Goxw7nSv4T/PzEJQxsYsEiFCKo2BA==", - "dev": true, -<<<<<<< HEAD -======= - "license": "MIT", ->>>>>>> dev - "dependencies": { - "braces": "^3.0.3", - "picomatch": "^2.3.1" - }, - "engines": { - "node": ">=8.6" - } - }, -<<<<<<< HEAD - "node_modules/micromatch/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" - } - }, -======= ->>>>>>> dev - "node_modules/minimatch": { - "version": "10.0.1", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-10.0.1.tgz", - "integrity": "sha512-ethXTt3SGGR+95gudmqJ1eNhRO7eGEGIgYA9vnPatK4/etz2MEVDno5GMCibdMTuBMyElzIlgxMna3K94XDIDQ==", - "dev": true, - "license": "ISC", - "dependencies": { - "brace-expansion": "^2.0.1" - }, - "engines": { - "node": "20 || >=22" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, - "node_modules/minipass": { - "version": "7.1.2", - "resolved": "https://registry.npmjs.org/minipass/-/minipass-7.1.2.tgz", - "integrity": "sha512-qOOzS1cBTWYF4BH8fVePDBOO9iptMnGUEZwNc/cMWnTV2nVLZ7VoNWEPHkYczZA0pdoA7dl6e7FL659nX9S2aw==", - "dev": true, - "license": "ISC", - "engines": { - "node": ">=16 || 14 >=14.17" - } - }, -<<<<<<< HEAD - "node_modules/mylas": { - "version": "2.1.13", - "resolved": "https://registry.npmjs.org/mylas/-/mylas-2.1.13.tgz", - "integrity": "sha512-+MrqnJRtxdF+xngFfUUkIMQrUUL0KsxbADUkn23Z/4ibGg192Q+z+CQyiYwvWTsYjJygmMR8+w3ZDa98Zh6ESg==", - "dev": true, - "engines": { - "node": ">=12.0.0" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/raouldeheer" - } - }, - "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/ms": { - "version": "2.1.3", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", - "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", - "dev": true, - "license": "MIT" - }, - "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, - "license": "MIT" - }, - "node_modules/oniguruma-to-js": { - "version": "0.4.3", - "resolved": "https://registry.npmjs.org/oniguruma-to-js/-/oniguruma-to-js-0.4.3.tgz", - "integrity": "sha512-X0jWUcAlxORhOqqBREgPMgnshB7ZGYszBNspP+tS9hPD3l13CdaXcHbgImoHUHlrvGx/7AvFEkTRhAGYh+jzjQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "regex": "^4.3.2" - }, - "funding": { - "url": "https://github.com/sponsors/antfu" - } - }, - "node_modules/optionator": { - "version": "0.9.4", - "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.9.4.tgz", - "integrity": "sha512-6IpQ7mKUxRcZNLIObR0hz7lxsapSSIYNZJwXPGeF0mTVqGKFIXj1DQcMoT22S3ROcLyY/rz0PWaWZ9ayWmad9g==", - "dev": true, - "license": "MIT", - "dependencies": { - "deep-is": "^0.1.3", - "fast-levenshtein": "^2.0.6", - "levn": "^0.4.1", - "prelude-ls": "^1.2.1", - "type-check": "^0.4.0", - "word-wrap": "^1.2.5" - }, - "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, - "license": "MIT", - "dependencies": { - "yocto-queue": "^0.1.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "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, - "license": "MIT", - "dependencies": { - "p-limit": "^3.0.2" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" ->>>>>>> dev - } - }, - "node_modules/package-json-from-dist": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/package-json-from-dist/-/package-json-from-dist-1.0.1.tgz", - "integrity": "sha512-UEZIS3/by4OC8vL3P2dTXRETpebLI2NiI5vIrjaD/5UtrkFX/tNbwjTSRAGC/+7CAo2pIcBaRgWmcBBHcsaCIw==", - "dev": true, - "license": "BlueOak-1.0.0" - }, - "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, - "license": "MIT", - "dependencies": { - "callsites": "^3.0.0" - }, - "engines": { - "node": ">=6" - } - }, - "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, - "license": "MIT", - "engines": { - "node": ">=8" - } - }, - "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, - "license": "MIT", - "engines": { - "node": ">=8" - } - }, - "node_modules/path-scurry": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/path-scurry/-/path-scurry-2.0.0.tgz", - "integrity": "sha512-ypGJsmGtdXUOeM5u93TyeIEfEhM6s+ljAhrk5vAvSx8uyY/02OvrZnA0YNGUrPXfpJMgI1ODd3nwz8Npx4O4cg==", - "dev": true, - "license": "BlueOak-1.0.0", - "dependencies": { - "lru-cache": "^11.0.0", - "minipass": "^7.1.2" - }, - "engines": { - "node": "20 || >=22" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, -<<<<<<< HEAD - "node_modules/path-type": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/path-type/-/path-type-4.0.0.tgz", - "integrity": "sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/plimit-lit": { - "version": "1.6.1", - "resolved": "https://registry.npmjs.org/plimit-lit/-/plimit-lit-1.6.1.tgz", - "integrity": "sha512-B7+VDyb8Tl6oMJT9oSO2CW8XC/T4UcJGrwOVoNGwOQsQYhlpfajmrMj5xeejqaASq3V/EqThyOeATEOMuSEXiA==", - "dev": true, - "dependencies": { - "queue-lit": "^1.5.1" - }, - "engines": { - "node": ">=12" - } - }, - "node_modules/queue-lit": { - "version": "1.5.2", - "resolved": "https://registry.npmjs.org/queue-lit/-/queue-lit-1.5.2.tgz", - "integrity": "sha512-tLc36IOPeMAubu8BkW8YDBV+WyIgKlYU7zUNs0J5Vk9skSZ4JfGlPOqplP0aHdfv7HL0B2Pg6nwiq60Qc6M2Hw==", - "dev": true, - "engines": { - "node": ">=12" -======= - "node_modules/picomatch": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", - "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=8.6" - }, - "funding": { - "url": "https://github.com/sponsors/jonschlinkert" - } - }, - "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, - "license": "MIT", - "engines": { - "node": ">= 0.8.0" - } - }, - "node_modules/property-information": { - "version": "6.5.0", - "resolved": "https://registry.npmjs.org/property-information/-/property-information-6.5.0.tgz", - "integrity": "sha512-PgTgs/BlvHxOu8QuEN7wi5A0OmXaBcHpmCSTehcs6Uuu9IkDIEo13Hy7n898RHfrQ49vKCoGeWZSaAK01nwVig==", - "dev": true, - "license": "MIT", - "funding": { - "type": "github", - "url": "https://github.com/sponsors/wooorm" - } - }, - "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, - "license": "MIT", - "engines": { - "node": ">=6" - } - }, - "node_modules/punycode.js": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/punycode.js/-/punycode.js-2.3.1.tgz", - "integrity": "sha512-uxFIHU0YlHYhDQtV4R9J6a52SLx28BCjT+4ieh7IGbgwVJWO+km431c4yRlREUAsAmt/uMjQUyQHNEPf0M39CA==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=6" ->>>>>>> dev - } - }, - "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" - } -<<<<<<< HEAD - ] - }, - "node_modules/readdirp": { - "version": "3.6.0", - "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz", - "integrity": "sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==", - "dev": true, - "dependencies": { - "picomatch": "^2.2.1" - }, - "engines": { - "node": ">=8.10.0" - } - }, - "node_modules/readdirp/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" -======= - ], - "license": "MIT" - }, - "node_modules/regex": { - "version": "4.3.3", - "resolved": "https://registry.npmjs.org/regex/-/regex-4.3.3.tgz", - "integrity": "sha512-r/AadFO7owAq1QJVeZ/nq9jNS1vyZt+6t1p/E59B56Rn2GCya+gr1KSyOzNL/er+r+B7phv5jG2xU2Nz1YkmJg==", - "dev": true, - "license": "MIT" - }, - "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, - "license": "MIT", - "engines": { - "node": ">=4" ->>>>>>> dev - } - }, - "node_modules/resolve-pkg-maps": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/resolve-pkg-maps/-/resolve-pkg-maps-1.0.0.tgz", - "integrity": "sha512-seS2Tj26TBVOC2NIc2rOe2y2ZO7efxITtLZcGSOnHHNOQ7CkiUBfw0Iw2ck6xkIhPwLhKNLS8BO+hEpngQlqzw==", - "dev": true, - "license": "MIT", - "funding": { - "url": "https://github.com/privatenumber/resolve-pkg-maps?sponsor=1" - } - }, - "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, -<<<<<<< HEAD -======= - "license": "MIT", ->>>>>>> dev - "engines": { - "iojs": ">=1.0.0", - "node": ">=0.10.0" - } - }, - "node_modules/rimraf": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-6.0.1.tgz", - "integrity": "sha512-9dkvaxAsk/xNXSJzMgFqqMCuFgt2+KsOFek3TMLfo8NCPfWpBmqwyNn5Y+NX56QUYfCtsyhF3ayiboEoUmJk/A==", - "dev": true, - "license": "ISC", - "dependencies": { - "glob": "^11.0.0", - "package-json-from-dist": "^1.0.0" - }, - "bin": { - "rimraf": "dist/esm/bin.mjs" - }, - "engines": { - "node": "20 || >=22" - }, - "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" - } - ], -<<<<<<< HEAD -======= - "license": "MIT", ->>>>>>> dev - "dependencies": { - "queue-microtask": "^1.2.2" - } - }, -<<<<<<< HEAD -======= - "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, - "license": "ISC", - "bin": { - "semver": "bin/semver.js" - }, - "engines": { - "node": ">=10" - } - }, ->>>>>>> dev - "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, - "license": "MIT", - "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, - "license": "MIT", - "engines": { - "node": ">=8" - } - }, - "node_modules/shiki": { - "version": "1.22.0", - "resolved": "https://registry.npmjs.org/shiki/-/shiki-1.22.0.tgz", - "integrity": "sha512-/t5LlhNs+UOKQCYBtl5ZsH/Vclz73GIqT2yQsCBygr8L/ppTdmpL4w3kPLoZJbMKVWtoG77Ue1feOjZfDxvMkw==", - "dev": true, - "license": "MIT", - "dependencies": { - "@shikijs/core": "1.22.0", - "@shikijs/engine-javascript": "1.22.0", - "@shikijs/engine-oniguruma": "1.22.0", - "@shikijs/types": "1.22.0", - "@shikijs/vscode-textmate": "^9.3.0", - "@types/hast": "^3.0.4" - } - }, - "node_modules/signal-exit": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-4.1.0.tgz", - "integrity": "sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==", - "dev": true, - "license": "ISC", - "engines": { - "node": ">=14" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, -<<<<<<< HEAD - "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/space-separated-tokens": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/space-separated-tokens/-/space-separated-tokens-2.0.2.tgz", - "integrity": "sha512-PEGlAwrG8yXGXRjW32fGbg66JAlOAwbObuqVoJpv/mRgoWDQfgH1wDPvtzWyUSNAXBGSk8h755YDbbcEy3SH2Q==", - "dev": true, - "license": "MIT", - "funding": { - "type": "github", - "url": "https://github.com/sponsors/wooorm" ->>>>>>> dev - } - }, - "node_modules/string-width": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-5.1.2.tgz", - "integrity": "sha512-HnLOCR3vjcY8beoNLtcjZ5/nxn2afmME6lhrDrebokqMap+XbeW8n9TXpPDOqdGK5qcI3oT0GKTW6wC7EMiVqA==", - "dev": true, - "license": "MIT", - "dependencies": { - "eastasianwidth": "^0.2.0", - "emoji-regex": "^9.2.2", - "strip-ansi": "^7.0.1" - }, - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/string-width-cjs": { - "name": "string-width", - "version": "4.2.3", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", - "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", - "dev": true, - "license": "MIT", - "dependencies": { - "emoji-regex": "^8.0.0", - "is-fullwidth-code-point": "^3.0.0", - "strip-ansi": "^6.0.1" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/string-width-cjs/node_modules/ansi-regex": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", - "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=8" - } - }, - "node_modules/string-width-cjs/node_modules/emoji-regex": { - "version": "8.0.0", - "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", - "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", - "dev": true, - "license": "MIT" - }, - "node_modules/string-width-cjs/node_modules/strip-ansi": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", - "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", - "dev": true, - "license": "MIT", - "dependencies": { - "ansi-regex": "^5.0.1" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/stringify-entities": { - "version": "4.0.4", - "resolved": "https://registry.npmjs.org/stringify-entities/-/stringify-entities-4.0.4.tgz", - "integrity": "sha512-IwfBptatlO+QCJUo19AqvrPNqlVMpW9YEL2LIVY+Rpv2qsjCGxaDLNRgeGsQWJhfItebuJhsGSLjaBbNSQ+ieg==", - "dev": true, - "license": "MIT", - "dependencies": { - "character-entities-html4": "^2.0.0", - "character-entities-legacy": "^3.0.0" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/wooorm" - } - }, - "node_modules/strip-ansi": { - "version": "7.1.0", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.1.0.tgz", - "integrity": "sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "ansi-regex": "^6.0.1" - }, - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/chalk/strip-ansi?sponsor=1" - } - }, - "node_modules/strip-ansi-cjs": { - "name": "strip-ansi", - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", - "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", - "dev": true, - "license": "MIT", - "dependencies": { - "ansi-regex": "^5.0.1" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/strip-ansi-cjs/node_modules/ansi-regex": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", - "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=8" - } - }, -<<<<<<< HEAD -======= - "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, - "license": "MIT", - "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, - "license": "MIT", - "dependencies": { - "has-flag": "^4.0.0" - }, - "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, - "license": "MIT" - }, ->>>>>>> dev - "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, -<<<<<<< HEAD -======= - "license": "MIT", ->>>>>>> dev - "dependencies": { - "is-number": "^7.0.0" - }, - "engines": { - "node": ">=8.0" - } - }, -<<<<<<< HEAD -======= - "node_modules/trim-lines": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/trim-lines/-/trim-lines-3.0.1.tgz", - "integrity": "sha512-kRj8B+YHZCc9kQYdWfJB2/oUl9rA99qbowYYBtr4ui4mZyAQ2JpvVBd/6U2YloATfqBhBTSMhTpgBHtU0Mf3Rg==", - "dev": true, - "license": "MIT", - "funding": { - "type": "github", - "url": "https://github.com/sponsors/wooorm" - } - }, - "node_modules/ts-api-utils": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/ts-api-utils/-/ts-api-utils-1.3.0.tgz", - "integrity": "sha512-UQMIo7pb8WRomKR1/+MFVLTroIvDVtMX3K6OUir8ynLyzB8Jeriont2bTAtmNPa1ekAgN7YPDyf6V+ygrdU+eQ==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=16" - }, - "peerDependencies": { - "typescript": ">=4.2.0" - } - }, ->>>>>>> dev - "node_modules/ts-node": { - "version": "10.9.2", - "resolved": "https://registry.npmjs.org/ts-node/-/ts-node-10.9.2.tgz", - "integrity": "sha512-f0FFpIdcHgn8zcPSbf1dRevwt047YMnaiJM3u2w2RewrB+fob/zePZcrOyQoLMMO7aBIddLcQIEK5dYjkLnGrQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "@cspotcode/source-map-support": "^0.8.0", - "@tsconfig/node10": "^1.0.7", - "@tsconfig/node12": "^1.0.7", - "@tsconfig/node14": "^1.0.0", - "@tsconfig/node16": "^1.0.2", - "acorn": "^8.4.1", - "acorn-walk": "^8.1.1", - "arg": "^4.1.0", - "create-require": "^1.1.0", - "diff": "^4.0.1", - "make-error": "^1.1.1", - "v8-compile-cache-lib": "^3.0.1", - "yn": "3.1.1" - }, - "bin": { - "ts-node": "dist/bin.js", - "ts-node-cwd": "dist/bin-cwd.js", - "ts-node-esm": "dist/bin-esm.js", - "ts-node-script": "dist/bin-script.js", - "ts-node-transpile-only": "dist/bin-transpile.js", - "ts-script": "dist/bin-script-deprecated.js" - }, - "peerDependencies": { - "@swc/core": ">=1.2.50", - "@swc/wasm": ">=1.2.50", - "@types/node": "*", - "typescript": ">=2.7" - }, - "peerDependenciesMeta": { - "@swc/core": { - "optional": true - }, - "@swc/wasm": { - "optional": true - } - } - }, - "node_modules/tsc-alias": { - "version": "1.8.10", - "resolved": "https://registry.npmjs.org/tsc-alias/-/tsc-alias-1.8.10.tgz", - "integrity": "sha512-Ibv4KAWfFkFdKJxnWfVtdOmB0Zi1RJVxcbPGiCDsFpCQSsmpWyuzHG3rQyI5YkobWwxFPEyQfu1hdo4qLG2zPw==", - "dev": true, - "license": "MIT", - "dependencies": { - "chokidar": "^3.5.3", - "commander": "^9.0.0", - "globby": "^11.0.4", - "mylas": "^2.1.9", - "normalize-path": "^3.0.0", - "plimit-lit": "^1.2.6" - }, - "bin": { - "tsc-alias": "dist/bin/index.js" - } - }, - "node_modules/tsx": { - "version": "4.19.1", - "resolved": "https://registry.npmjs.org/tsx/-/tsx-4.19.1.tgz", - "integrity": "sha512-0flMz1lh74BR4wOvBjuh9olbnwqCPc35OOlfyzHba0Dc+QNUeWX/Gq2YTbnwcWPO3BMd8fkzRVrHcsR+a7z7rA==", - "dev": true, - "license": "MIT", - "dependencies": { - "esbuild": "~0.23.0", - "get-tsconfig": "^4.7.5" - }, - "bin": { - "tsx": "dist/cli.mjs" - }, - "engines": { - "node": ">=18.0.0" - }, - "optionalDependencies": { - "fsevents": "~2.3.3" - } - }, - "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, - "license": "MIT", - "dependencies": { - "prelude-ls": "^1.2.1" - }, - "engines": { - "node": ">= 0.8.0" - } - }, - "node_modules/typedoc": { - "version": "0.26.9", - "resolved": "https://registry.npmjs.org/typedoc/-/typedoc-0.26.9.tgz", - "integrity": "sha512-Rc7QpWL7EtmrT8yxV0GmhOR6xHgFnnhphbD9Suti3fz3um7ZOrou6q/g9d6+zC5PssTLZmjaW4Upmzv8T1rCcQ==", - "dev": true, - "license": "Apache-2.0", - "dependencies": { - "lunr": "^2.3.9", - "markdown-it": "^14.1.0", - "minimatch": "^9.0.5", - "shiki": "^1.16.2", - "yaml": "^2.5.1" - }, - "bin": { - "typedoc": "bin/typedoc" - }, - "engines": { - "node": ">= 18" - }, - "peerDependencies": { - "typescript": "4.6.x || 4.7.x || 4.8.x || 4.9.x || 5.0.x || 5.1.x || 5.2.x || 5.3.x || 5.4.x || 5.5.x || 5.6.x" - } - }, - "node_modules/typedoc/node_modules/minimatch": { - "version": "9.0.5", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.5.tgz", - "integrity": "sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow==", - "dev": true, - "license": "ISC", - "dependencies": { - "brace-expansion": "^2.0.1" - }, - "engines": { - "node": ">=16 || 14 >=14.17" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, - "node_modules/typescript": { - "version": "5.6.2", - "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.6.2.tgz", - "integrity": "sha512-NW8ByodCSNCwZeghjN3o+JX5OFH0Ojg6sadjEKY4huZ52TqbJTJnDo5+Tw98lSy63NZvi4n+ez5m2u5d4PkZyw==", - "dev": true, - "bin": { - "tsc": "bin/tsc", - "tsserver": "bin/tsserver" - }, - "engines": { - "node": ">=14.17" - } - }, - "node_modules/typescript-eslint": { - "version": "8.8.0", - "resolved": "https://registry.npmjs.org/typescript-eslint/-/typescript-eslint-8.8.0.tgz", - "integrity": "sha512-BjIT/VwJ8+0rVO01ZQ2ZVnjE1svFBiRczcpr1t1Yxt7sT25VSbPfrJtDsQ8uQTy2pilX5nI9gwxhUyLULNentw==", - "dev": true, - "license": "MIT", - "dependencies": { - "@typescript-eslint/eslint-plugin": "8.8.0", - "@typescript-eslint/parser": "8.8.0", - "@typescript-eslint/utils": "8.8.0" - }, - "engines": { - "node": "^18.18.0 || ^20.9.0 || >=21.1.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - }, - "peerDependenciesMeta": { - "typescript": { - "optional": true - } - } - }, - "node_modules/uc.micro": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/uc.micro/-/uc.micro-2.1.0.tgz", - "integrity": "sha512-ARDJmphmdvUk6Glw7y9DQ2bFkKBHwQHLi2lsaH6PPmz/Ka9sFOBsBluozhDltWmnv9u/cF6Rt87znRTPV+yp/A==", - "dev": true, - "license": "MIT" - }, - "node_modules/undici-types": { - "version": "6.19.8", - "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-6.19.8.tgz", - "integrity": "sha512-ve2KP6f/JnbPBFyobGHuerC9g1FYGn/F8n1LWTwNxCEzd6IfqTwUQcNXgEtmmQ6DlRrC1hrSrBnCZPokRrDHjw==", - "dev": true, - "license": "MIT" - }, - "node_modules/unist-util-is": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/unist-util-is/-/unist-util-is-6.0.0.tgz", - "integrity": "sha512-2qCTHimwdxLfz+YzdGfkqNlH0tLi9xjTnHddPmJwtIG9MGsdbutfTc4P+haPD7l7Cjxf/WZj+we5qfVPvvxfYw==", - "dev": true, - "license": "MIT", - "dependencies": { - "@types/unist": "^3.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, - "node_modules/unist-util-position": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/unist-util-position/-/unist-util-position-5.0.0.tgz", - "integrity": "sha512-fucsC7HjXvkB5R3kTCO7kUjRdrS0BJt3M/FPxmHMBOm8JQi2BsHAHFsy27E0EolP8rp0NzXsJ+jNPyDWvOJZPA==", - "dev": true, - "license": "MIT", - "dependencies": { - "@types/unist": "^3.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, - "node_modules/unist-util-stringify-position": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/unist-util-stringify-position/-/unist-util-stringify-position-4.0.0.tgz", - "integrity": "sha512-0ASV06AAoKCDkS2+xw5RXJywruurpbC4JZSm7nr7MOt1ojAzvyyaO+UxZf18j8FCF6kmzCZKcAgN/yu2gm2XgQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "@types/unist": "^3.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, - "node_modules/unist-util-visit": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/unist-util-visit/-/unist-util-visit-5.0.0.tgz", - "integrity": "sha512-MR04uvD+07cwl/yhVuVWAtw+3GOR/knlL55Nd/wAdblk27GCVt3lqpTivy/tkJcZoNPzTwS1Y+KMojlLDhoTzg==", - "dev": true, - "license": "MIT", - "dependencies": { - "@types/unist": "^3.0.0", - "unist-util-is": "^6.0.0", - "unist-util-visit-parents": "^6.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, - "node_modules/unist-util-visit-parents": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/unist-util-visit-parents/-/unist-util-visit-parents-6.0.1.tgz", - "integrity": "sha512-L/PqWzfTP9lzzEa6CKs0k2nARxTdZduw3zyh8d2NVBnsyvHjSX4TWse388YrrQKbvI8w20fGjGlhgT96WwKykw==", - "dev": true, - "license": "MIT", - "dependencies": { - "@types/unist": "^3.0.0", - "unist-util-is": "^6.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, - "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, - "license": "BSD-2-Clause", - "dependencies": { - "punycode": "^2.1.0" - } - }, - "node_modules/v8-compile-cache-lib": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/v8-compile-cache-lib/-/v8-compile-cache-lib-3.0.1.tgz", - "integrity": "sha512-wa7YjyUGfNZngI/vtK0UHAN+lgDCxBPCylVXGp0zu59Fz5aiGtNXaq3DhIov063MorB+VfufLh3JlF2KdTK3xg==", - "dev": true, - "license": "MIT" - }, - "node_modules/vfile": { - "version": "6.0.3", - "resolved": "https://registry.npmjs.org/vfile/-/vfile-6.0.3.tgz", - "integrity": "sha512-KzIbH/9tXat2u30jf+smMwFCsno4wHVdNmzFyL+T/L3UGqqk6JKfVqOFOZEpZSHADH1k40ab6NUIXZq422ov3Q==", - "dev": true, - "license": "MIT", - "dependencies": { - "@types/unist": "^3.0.0", - "vfile-message": "^4.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, - "node_modules/vfile-message": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/vfile-message/-/vfile-message-4.0.2.tgz", - "integrity": "sha512-jRDZ1IMLttGj41KcZvlrYAaI3CfqpLpfpf+Mfig13viT6NKvRzWZ+lXz0Y5D60w6uJIBAOGq9mSHf0gktF0duw==", - "dev": true, - "license": "MIT", - "dependencies": { - "@types/unist": "^3.0.0", - "unist-util-stringify-position": "^4.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, - "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, - "license": "ISC", - "dependencies": { - "isexe": "^2.0.0" - }, - "bin": { - "node-which": "bin/node-which" - }, - "engines": { - "node": ">= 8" - } - }, - "node_modules/word-wrap": { - "version": "1.2.5", - "resolved": "https://registry.npmjs.org/word-wrap/-/word-wrap-1.2.5.tgz", - "integrity": "sha512-BN22B5eaMMI9UMtjrGd5g5eCYPpCPDUy0FJXbYsaT5zYxjFOckS53SQDE3pWkVoWpHXVb3BrYcEN4Twa55B5cA==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/wrap-ansi": { - "version": "8.1.0", - "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-8.1.0.tgz", - "integrity": "sha512-si7QWI6zUMq56bESFvagtmzMdGOtoxfR+Sez11Mobfc7tm+VkUckk9bW2UeffTGVUbOksxmSw0AA2gs8g71NCQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "ansi-styles": "^6.1.0", - "string-width": "^5.0.1", - "strip-ansi": "^7.0.1" - }, - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/chalk/wrap-ansi?sponsor=1" - } - }, - "node_modules/wrap-ansi-cjs": { - "name": "wrap-ansi", - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", - "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", - "dev": true, - "license": "MIT", - "dependencies": { - "ansi-styles": "^4.0.0", - "string-width": "^4.1.0", - "strip-ansi": "^6.0.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/chalk/wrap-ansi?sponsor=1" - } - }, - "node_modules/wrap-ansi-cjs/node_modules/ansi-regex": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", - "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=8" - } - }, - "node_modules/wrap-ansi-cjs/node_modules/ansi-styles": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", - "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", - "dev": true, - "license": "MIT", - "dependencies": { - "color-convert": "^2.0.1" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" - } - }, - "node_modules/wrap-ansi-cjs/node_modules/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, - "license": "MIT" - }, - "node_modules/wrap-ansi-cjs/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, - "license": "MIT", - "dependencies": { - "emoji-regex": "^8.0.0", - "is-fullwidth-code-point": "^3.0.0", - "strip-ansi": "^6.0.1" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/wrap-ansi-cjs/node_modules/strip-ansi": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", - "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", - "dev": true, - "license": "MIT", - "dependencies": { - "ansi-regex": "^5.0.1" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/yaml": { - "version": "2.6.0", - "resolved": "https://registry.npmjs.org/yaml/-/yaml-2.6.0.tgz", - "integrity": "sha512-a6ae//JvKDEra2kdi1qzCyrJW/WZCgFi8ydDV+eXExl95t+5R+ijnqHJbz9tmMh8FUjx3iv2fCQ4dclAQlO2UQ==", - "dev": true, - "license": "ISC", - "bin": { - "yaml": "bin.mjs" - }, - "engines": { - "node": ">= 14" - } - }, - "node_modules/yn": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/yn/-/yn-3.1.1.tgz", - "integrity": "sha512-Ux4ygGWsu2c7isFWe8Yu1YluJmqVhxqK2cLXNQA5AcC3QfbGNpM7fu0Y8b/z16pXLnFxZYvWhd3fhBY9DLmC6Q==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=6" - } - }, - "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, - "license": "MIT", - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/zwitch": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/zwitch/-/zwitch-2.0.4.tgz", - "integrity": "sha512-bXE4cR/kVZhKZX/RjPEflHaKVhUVl85noU3v6b8apfQEc1x4A+zBxjZ4lN8LqGd6WZ3dl98pY4o717VFmoPp+A==", - "dev": true, - "license": "MIT", - "funding": { - "type": "github", - "url": "https://github.com/sponsors/wooorm" - } - } - } -} From 8f21ba6303a29a2134670a854d6cc4f0b195773f Mon Sep 17 00:00:00 2001 From: Austin Fraser Date: Mon, 21 Oct 2024 17:49:18 -0700 Subject: [PATCH 189/357] deleted node_modules and package-lock.json, ran npm install again to generate fresh instances of them --- mlflow/package-lock.json | 733 +++++++++++++++------------------------ 1 file changed, 288 insertions(+), 445 deletions(-) diff --git a/mlflow/package-lock.json b/mlflow/package-lock.json index a21f38fe..bcb2d62a 100644 --- a/mlflow/package-lock.json +++ b/mlflow/package-lock.json @@ -500,34 +500,10 @@ "node": "^18.18.0 || ^20.9.0 || >=21.1.0" } }, - "node_modules/@eslint/config-array/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, - "license": "MIT", - "dependencies": { - "balanced-match": "^1.0.0", - "concat-map": "0.0.1" - } - }, - "node_modules/@eslint/config-array/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, - "license": "ISC", - "dependencies": { - "brace-expansion": "^1.1.7" - }, - "engines": { - "node": "*" - } - }, "node_modules/@eslint/core": { - "version": "0.6.0", - "resolved": "https://registry.npmjs.org/@eslint/core/-/core-0.6.0.tgz", - "integrity": "sha512-8I2Q8ykA4J0x0o7cg67FPVnehcqWTBehu/lmY+bolPFHGjh49YzGBMXTvpqVgEbBdvNCSxj6iFgiIyHzf03lzg==", + "version": "0.7.0", + "resolved": "https://registry.npmjs.org/@eslint/core/-/core-0.7.0.tgz", + "integrity": "sha512-xp5Jirz5DyPYlPiKat8jaq0EmYvDXKKpzTbxXMpT9eqlRJkRKIz9AGMdlvYjih+im+QlhWrpvVjl8IPC/lHlUw==", "dev": true, "license": "Apache-2.0", "engines": { @@ -558,34 +534,10 @@ "url": "https://opencollective.com/eslint" } }, - "node_modules/@eslint/eslintrc/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, - "license": "MIT", - "dependencies": { - "balanced-match": "^1.0.0", - "concat-map": "0.0.1" - } - }, - "node_modules/@eslint/eslintrc/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, - "license": "ISC", - "dependencies": { - "brace-expansion": "^1.1.7" - }, - "engines": { - "node": "*" - } - }, "node_modules/@eslint/js": { - "version": "9.12.0", - "resolved": "https://registry.npmjs.org/@eslint/js/-/js-9.12.0.tgz", - "integrity": "sha512-eohesHH8WFRUprDNyEREgqP6beG6htMeUYeCpkEgBCieCMme5r9zFWjzAJp//9S+Kub4rqE+jXe9Cp1a7IYIIA==", + "version": "9.13.0", + "resolved": "https://registry.npmjs.org/@eslint/js/-/js-9.13.0.tgz", + "integrity": "sha512-IFLyoY4d72Z5y/6o/BazFBezupzI/taV8sGumxTAVw3lXG9A6md1Dc34T9s1FoD/an9pJH8RHbAxsaEbBed9lA==", "dev": true, "license": "MIT", "engines": { @@ -603,9 +555,9 @@ } }, "node_modules/@eslint/plugin-kit": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/@eslint/plugin-kit/-/plugin-kit-0.2.0.tgz", - "integrity": "sha512-vH9PiIMMwvhCx31Af3HiGzsVNULDbyVkHXwlemn/B0TFj/00ho3y55efXrUZTfQipxoHC5u4xq6zblww1zm1Ig==", + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/@eslint/plugin-kit/-/plugin-kit-0.2.1.tgz", + "integrity": "sha512-HFZ4Mp26nbWk9d/BpvP0YNL6W4UoZF0VFcTw/aPPA8RpOxeFQgK+ClABGgAUXs9Y/RGX/l1vOmrqz1MQt9MNuw==", "dev": true, "license": "Apache-2.0", "dependencies": { @@ -718,10 +670,7 @@ "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz", "integrity": "sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==", "dev": true, -<<<<<<< HEAD -======= "license": "MIT", ->>>>>>> dev "dependencies": { "@nodelib/fs.stat": "2.0.5", "run-parallel": "^1.1.9" @@ -735,10 +684,7 @@ "resolved": "https://registry.npmjs.org/@nodelib/fs.stat/-/fs.stat-2.0.5.tgz", "integrity": "sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==", "dev": true, -<<<<<<< HEAD -======= "license": "MIT", ->>>>>>> dev "engines": { "node": ">= 8" } @@ -748,10 +694,7 @@ "resolved": "https://registry.npmjs.org/@nodelib/fs.walk/-/fs.walk-1.2.8.tgz", "integrity": "sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==", "dev": true, -<<<<<<< HEAD -======= "license": "MIT", ->>>>>>> dev "dependencies": { "@nodelib/fs.scandir": "2.1.5", "fastq": "^1.6.0" @@ -760,8 +703,6 @@ "node": ">= 8" } }, -<<<<<<< HEAD -======= "node_modules/@shikijs/core": { "version": "1.22.0", "resolved": "https://registry.npmjs.org/@shikijs/core/-/core-1.22.0.tgz", @@ -818,7 +759,6 @@ "dev": true, "license": "MIT" }, ->>>>>>> dev "node_modules/@tsconfig/node10": { "version": "1.0.11", "resolved": "https://registry.npmjs.org/@tsconfig/node10/-/node10-1.0.11.tgz", @@ -903,9 +843,9 @@ } }, "node_modules/@types/node": { - "version": "22.7.4", - "resolved": "https://registry.npmjs.org/@types/node/-/node-22.7.4.tgz", - "integrity": "sha512-y+NPi1rFzDs1NdQHHToqeiX2TIS79SWEAw9GYhkkx8bD0ChpfqC+n2j5OXOCpzfojBEBt6DnEnnG9MY0zk1XLg==", + "version": "22.7.7", + "resolved": "https://registry.npmjs.org/@types/node/-/node-22.7.7.tgz", + "integrity": "sha512-SRxCrrg9CL/y54aiMCG3edPKdprgMVGDXjA3gB8UmmBW5TcXzRUYAh8EWzTnSJFAd1rgImPELza+A3bJ+qxz8Q==", "dev": true, "license": "MIT", "dependencies": { @@ -920,17 +860,17 @@ "license": "MIT" }, "node_modules/@typescript-eslint/eslint-plugin": { - "version": "8.8.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-8.8.0.tgz", - "integrity": "sha512-wORFWjU30B2WJ/aXBfOm1LX9v9nyt9D3jsSOxC3cCaTQGCW5k4jNpmjFv3U7p/7s4yvdjHzwtv2Sd2dOyhjS0A==", + "version": "8.11.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-8.11.0.tgz", + "integrity": "sha512-KhGn2LjW1PJT2A/GfDpiyOfS4a8xHQv2myUagTM5+zsormOmBlYsnQ6pobJ8XxJmh6hnHwa2Mbe3fPrDJoDhbA==", "dev": true, "license": "MIT", "dependencies": { "@eslint-community/regexpp": "^4.10.0", - "@typescript-eslint/scope-manager": "8.8.0", - "@typescript-eslint/type-utils": "8.8.0", - "@typescript-eslint/utils": "8.8.0", - "@typescript-eslint/visitor-keys": "8.8.0", + "@typescript-eslint/scope-manager": "8.11.0", + "@typescript-eslint/type-utils": "8.11.0", + "@typescript-eslint/utils": "8.11.0", + "@typescript-eslint/visitor-keys": "8.11.0", "graphemer": "^1.4.0", "ignore": "^5.3.1", "natural-compare": "^1.4.0", @@ -954,16 +894,16 @@ } }, "node_modules/@typescript-eslint/parser": { - "version": "8.8.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-8.8.0.tgz", - "integrity": "sha512-uEFUsgR+tl8GmzmLjRqz+VrDv4eoaMqMXW7ruXfgThaAShO9JTciKpEsB+TvnfFfbg5IpujgMXVV36gOJRLtZg==", + "version": "8.11.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-8.11.0.tgz", + "integrity": "sha512-lmt73NeHdy1Q/2ul295Qy3uninSqi6wQI18XwSpm8w0ZbQXUpjCAWP1Vlv/obudoBiIjJVjlztjQ+d/Md98Yxg==", "dev": true, "license": "BSD-2-Clause", "dependencies": { - "@typescript-eslint/scope-manager": "8.8.0", - "@typescript-eslint/types": "8.8.0", - "@typescript-eslint/typescript-estree": "8.8.0", - "@typescript-eslint/visitor-keys": "8.8.0", + "@typescript-eslint/scope-manager": "8.11.0", + "@typescript-eslint/types": "8.11.0", + "@typescript-eslint/typescript-estree": "8.11.0", + "@typescript-eslint/visitor-keys": "8.11.0", "debug": "^4.3.4" }, "engines": { @@ -983,14 +923,14 @@ } }, "node_modules/@typescript-eslint/scope-manager": { - "version": "8.8.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-8.8.0.tgz", - "integrity": "sha512-EL8eaGC6gx3jDd8GwEFEV091210U97J0jeEHrAYvIYosmEGet4wJ+g0SYmLu+oRiAwbSA5AVrt6DxLHfdd+bUg==", + "version": "8.11.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-8.11.0.tgz", + "integrity": "sha512-Uholz7tWhXmA4r6epo+vaeV7yjdKy5QFCERMjs1kMVsLRKIrSdM6o21W2He9ftp5PP6aWOVpD5zvrvuHZC0bMQ==", "dev": true, "license": "MIT", "dependencies": { - "@typescript-eslint/types": "8.8.0", - "@typescript-eslint/visitor-keys": "8.8.0" + "@typescript-eslint/types": "8.11.0", + "@typescript-eslint/visitor-keys": "8.11.0" }, "engines": { "node": "^18.18.0 || ^20.9.0 || >=21.1.0" @@ -1001,14 +941,14 @@ } }, "node_modules/@typescript-eslint/type-utils": { - "version": "8.8.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-8.8.0.tgz", - "integrity": "sha512-IKwJSS7bCqyCeG4NVGxnOP6lLT9Okc3Zj8hLO96bpMkJab+10HIfJbMouLrlpyOr3yrQ1cA413YPFiGd1mW9/Q==", + "version": "8.11.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-8.11.0.tgz", + "integrity": "sha512-ItiMfJS6pQU0NIKAaybBKkuVzo6IdnAhPFZA/2Mba/uBjuPQPet/8+zh5GtLHwmuFRShZx+8lhIs7/QeDHflOg==", "dev": true, "license": "MIT", "dependencies": { - "@typescript-eslint/typescript-estree": "8.8.0", - "@typescript-eslint/utils": "8.8.0", + "@typescript-eslint/typescript-estree": "8.11.0", + "@typescript-eslint/utils": "8.11.0", "debug": "^4.3.4", "ts-api-utils": "^1.3.0" }, @@ -1026,9 +966,9 @@ } }, "node_modules/@typescript-eslint/types": { - "version": "8.8.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-8.8.0.tgz", - "integrity": "sha512-QJwc50hRCgBd/k12sTykOJbESe1RrzmX6COk8Y525C9l7oweZ+1lw9JiU56im7Amm8swlz00DRIlxMYLizr2Vw==", + "version": "8.11.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-8.11.0.tgz", + "integrity": "sha512-tn6sNMHf6EBAYMvmPUaKaVeYvhUsrE6x+bXQTxjQRp360h1giATU0WvgeEys1spbvb5R+VpNOZ+XJmjD8wOUHw==", "dev": true, "license": "MIT", "engines": { @@ -1040,14 +980,14 @@ } }, "node_modules/@typescript-eslint/typescript-estree": { - "version": "8.8.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-8.8.0.tgz", - "integrity": "sha512-ZaMJwc/0ckLz5DaAZ+pNLmHv8AMVGtfWxZe/x2JVEkD5LnmhWiQMMcYT7IY7gkdJuzJ9P14fRy28lUrlDSWYdw==", + "version": "8.11.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-8.11.0.tgz", + "integrity": "sha512-yHC3s1z1RCHoCz5t06gf7jH24rr3vns08XXhfEqzYpd6Hll3z/3g23JRi0jM8A47UFKNc3u/y5KIMx8Ynbjohg==", "dev": true, "license": "BSD-2-Clause", "dependencies": { - "@typescript-eslint/types": "8.8.0", - "@typescript-eslint/visitor-keys": "8.8.0", + "@typescript-eslint/types": "8.11.0", + "@typescript-eslint/visitor-keys": "8.11.0", "debug": "^4.3.4", "fast-glob": "^3.3.2", "is-glob": "^4.0.3", @@ -1068,6 +1008,16 @@ } } }, + "node_modules/@typescript-eslint/typescript-estree/node_modules/brace-expansion": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", + "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", + "dev": true, + "license": "MIT", + "dependencies": { + "balanced-match": "^1.0.0" + } + }, "node_modules/@typescript-eslint/typescript-estree/node_modules/minimatch": { "version": "9.0.5", "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.5.tgz", @@ -1085,16 +1035,16 @@ } }, "node_modules/@typescript-eslint/utils": { - "version": "8.8.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-8.8.0.tgz", - "integrity": "sha512-QE2MgfOTem00qrlPgyByaCHay9yb1+9BjnMFnSFkUKQfu7adBXDTnCAivURnuPPAG/qiB+kzKkZKmKfaMT0zVg==", + "version": "8.11.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-8.11.0.tgz", + "integrity": "sha512-CYiX6WZcbXNJV7UNB4PLDIBtSdRmRI/nb0FMyqHPTQD1rMjA0foPLaPUV39C/MxkTd/QKSeX+Gb34PPsDVC35g==", "dev": true, "license": "MIT", "dependencies": { "@eslint-community/eslint-utils": "^4.4.0", - "@typescript-eslint/scope-manager": "8.8.0", - "@typescript-eslint/types": "8.8.0", - "@typescript-eslint/typescript-estree": "8.8.0" + "@typescript-eslint/scope-manager": "8.11.0", + "@typescript-eslint/types": "8.11.0", + "@typescript-eslint/typescript-estree": "8.11.0" }, "engines": { "node": "^18.18.0 || ^20.9.0 || >=21.1.0" @@ -1108,13 +1058,13 @@ } }, "node_modules/@typescript-eslint/visitor-keys": { - "version": "8.8.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-8.8.0.tgz", - "integrity": "sha512-8mq51Lx6Hpmd7HnA2fcHQo3YgfX1qbccxQOgZcb4tvasu//zXRaA1j5ZRFeCw/VRAdFi4mRM9DnZw0Nu0Q2d1g==", + "version": "8.11.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-8.11.0.tgz", + "integrity": "sha512-EaewX6lxSjRJnc+99+dqzTeoDZUfyrA52d2/HRrkI830kgovWsmIiTfmr0NZorzqic7ga+1bS60lRBUgR3n/Bw==", "dev": true, "license": "MIT", "dependencies": { - "@typescript-eslint/types": "8.8.0", + "@typescript-eslint/types": "8.11.0", "eslint-visitor-keys": "^3.4.3" }, "engines": { @@ -1146,9 +1096,9 @@ "license": "ISC" }, "node_modules/acorn": { - "version": "8.12.1", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.12.1.tgz", - "integrity": "sha512-tcpGyI9zbizT9JbV6oYE477V6mTlXvvi0T0G3SNIYE2apm/G5huBa1+K89VGeovbg+jycCrfhl3ADxErOuO6Jg==", + "version": "8.13.0", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.13.0.tgz", + "integrity": "sha512-8zSiw54Oxrdym50NlZ9sUusyO1Z1ZchgRLWRaK6c86XJFClyCgFKetdowBg5bKxyp/u+CDBJG4Mpp0m3HLZl9w==", "dev": true, "license": "MIT", "bin": { @@ -1212,13 +1162,16 @@ } }, "node_modules/ansi-styles": { - "version": "6.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-6.2.1.tgz", - "integrity": "sha512-bN798gFfQX+viw3R7yrGWRqnrN2oRkEkUjjl4JNn4E8GxxbjtG3FbrEIIY3l8/hrwUwIeCZvi4QuOTP4MErVug==", + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", "dev": true, "license": "MIT", + "dependencies": { + "color-convert": "^2.0.1" + }, "engines": { - "node": ">=12" + "node": ">=8" }, "funding": { "url": "https://github.com/chalk/ansi-styles?sponsor=1" @@ -1229,6 +1182,7 @@ "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.3.tgz", "integrity": "sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw==", "dev": true, + "license": "ISC", "dependencies": { "normalize-path": "^3.0.0", "picomatch": "^2.0.4" @@ -1237,18 +1191,6 @@ "node": ">= 8" } }, - "node_modules/anymatch/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/arg": { "version": "4.1.3", "resolved": "https://registry.npmjs.org/arg/-/arg-4.1.3.tgz", @@ -1256,23 +1198,22 @@ "dev": true, "license": "MIT" }, -<<<<<<< HEAD + "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, + "license": "Python-2.0" + }, "node_modules/array-union": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/array-union/-/array-union-2.1.0.tgz", "integrity": "sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw==", "dev": true, + "license": "MIT", "engines": { "node": ">=8" } -======= - "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, - "license": "Python-2.0" ->>>>>>> dev }, "node_modules/balanced-match": { "version": "1.0.2", @@ -1286,6 +1227,7 @@ "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.3.0.tgz", "integrity": "sha512-Ceh+7ox5qe7LJuLHoY0feh3pHuUDHAcRUeyL2VYghZwfpkNIy/+8Ocg0a3UuSoYzavmylwuLWQOf3hl0jjMMIw==", "dev": true, + "license": "MIT", "engines": { "node": ">=8" }, @@ -1294,13 +1236,14 @@ } }, "node_modules/brace-expansion": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", - "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", "dev": true, "license": "MIT", "dependencies": { - "balanced-match": "^1.0.0" + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" } }, "node_modules/braces": { @@ -1308,10 +1251,7 @@ "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.3.tgz", "integrity": "sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==", "dev": true, -<<<<<<< HEAD -======= "license": "MIT", ->>>>>>> dev "dependencies": { "fill-range": "^7.1.1" }, @@ -1319,30 +1259,6 @@ "node": ">=8" } }, -<<<<<<< HEAD - "node_modules/chokidar": { - "version": "3.6.0", - "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.6.0.tgz", - "integrity": "sha512-7VT13fmjotKpGipCW9JEQAusEPE+Ei8nl6/g4FBAmIm0GOOLMua9NDDo/DWp0ZAxCr3cPq5ZpBqmPAQgDda2Pw==", - "dev": true, - "dependencies": { - "anymatch": "~3.1.2", - "braces": "~3.0.2", - "glob-parent": "~5.1.2", - "is-binary-path": "~2.1.0", - "is-glob": "~4.0.1", - "normalize-path": "~3.0.0", - "readdirp": "~3.6.0" - }, - "engines": { - "node": ">= 8.10.0" - }, - "funding": { - "url": "https://paulmillr.com/funding/" - }, - "optionalDependencies": { - "fsevents": "~2.3.2" -======= "node_modules/callsites": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz", @@ -1381,22 +1297,6 @@ "url": "https://github.com/chalk/chalk?sponsor=1" } }, - "node_modules/chalk/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, - "license": "MIT", - "dependencies": { - "color-convert": "^2.0.1" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" - } - }, "node_modules/character-entities-html4": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/character-entities-html4/-/character-entities-html4-2.1.0.tgz", @@ -1417,7 +1317,44 @@ "funding": { "type": "github", "url": "https://github.com/sponsors/wooorm" ->>>>>>> dev + } + }, + "node_modules/chokidar": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.6.0.tgz", + "integrity": "sha512-7VT13fmjotKpGipCW9JEQAusEPE+Ei8nl6/g4FBAmIm0GOOLMua9NDDo/DWp0ZAxCr3cPq5ZpBqmPAQgDda2Pw==", + "dev": true, + "license": "MIT", + "dependencies": { + "anymatch": "~3.1.2", + "braces": "~3.0.2", + "glob-parent": "~5.1.2", + "is-binary-path": "~2.1.0", + "is-glob": "~4.0.1", + "normalize-path": "~3.0.0", + "readdirp": "~3.6.0" + }, + "engines": { + "node": ">= 8.10.0" + }, + "funding": { + "url": "https://paulmillr.com/funding/" + }, + "optionalDependencies": { + "fsevents": "~2.3.2" + } + }, + "node_modules/chokidar/node_modules/glob-parent": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", + "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", + "dev": true, + "license": "ISC", + "dependencies": { + "is-glob": "^4.0.1" + }, + "engines": { + "node": ">= 6" } }, "node_modules/color-convert": { @@ -1440,17 +1377,6 @@ "dev": true, "license": "MIT" }, -<<<<<<< HEAD - "node_modules/commander": { - "version": "9.5.0", - "resolved": "https://registry.npmjs.org/commander/-/commander-9.5.0.tgz", - "integrity": "sha512-KRs7WVDKg86PWiuAqhDrAQnTXZKraVcCc6vFdL14qrZ/DcWwuRo7VoiYXalXO7S5GKpqYiVEwCbgFDfxNHKJBQ==", - "dev": true, - "engines": { - "node": "^12.20.0 || >=14" - } - }, -======= "node_modules/comma-separated-tokens": { "version": "2.0.3", "resolved": "https://registry.npmjs.org/comma-separated-tokens/-/comma-separated-tokens-2.0.3.tgz", @@ -1462,6 +1388,16 @@ "url": "https://github.com/sponsors/wooorm" } }, + "node_modules/commander": { + "version": "9.5.0", + "resolved": "https://registry.npmjs.org/commander/-/commander-9.5.0.tgz", + "integrity": "sha512-KRs7WVDKg86PWiuAqhDrAQnTXZKraVcCc6vFdL14qrZ/DcWwuRo7VoiYXalXO7S5GKpqYiVEwCbgFDfxNHKJBQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": "^12.20.0 || >=14" + } + }, "node_modules/concat-map": { "version": "0.0.1", "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", @@ -1469,7 +1405,6 @@ "dev": true, "license": "MIT" }, ->>>>>>> dev "node_modules/create-require": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/create-require/-/create-require-1.1.1.tgz", @@ -1556,6 +1491,7 @@ "resolved": "https://registry.npmjs.org/dir-glob/-/dir-glob-3.0.1.tgz", "integrity": "sha512-WkrWp9GR4KXfKGYzOLmTuGVi1UWFfws377n9cc55/tb6DuqyF6pcQ5AbiHEshaDpY9v6oaSr2XCDidGmMwdzIA==", "dev": true, + "license": "MIT", "dependencies": { "path-type": "^4.0.0" }, @@ -1630,8 +1566,6 @@ "@esbuild/win32-x64": "0.23.1" } }, -<<<<<<< HEAD -======= "node_modules/escape-string-regexp": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz", @@ -1646,18 +1580,18 @@ } }, "node_modules/eslint": { - "version": "9.12.0", - "resolved": "https://registry.npmjs.org/eslint/-/eslint-9.12.0.tgz", - "integrity": "sha512-UVIOlTEWxwIopRL1wgSQYdnVDcEvs2wyaO6DGo5mXqe3r16IoCNWkR29iHhyaP4cICWjbgbmFUGAhh0GJRuGZw==", + "version": "9.13.0", + "resolved": "https://registry.npmjs.org/eslint/-/eslint-9.13.0.tgz", + "integrity": "sha512-EYZK6SX6zjFHST/HRytOdA/zE72Cq/bfw45LSyuwrdvcclb/gqV8RRQxywOBEWO2+WDpva6UZa4CcDeJKzUCFA==", "dev": true, "license": "MIT", "dependencies": { "@eslint-community/eslint-utils": "^4.2.0", "@eslint-community/regexpp": "^4.11.0", "@eslint/config-array": "^0.18.0", - "@eslint/core": "^0.6.0", + "@eslint/core": "^0.7.0", "@eslint/eslintrc": "^3.1.0", - "@eslint/js": "9.12.0", + "@eslint/js": "9.13.0", "@eslint/plugin-kit": "^0.2.0", "@humanfs/node": "^0.16.5", "@humanwhocodes/module-importer": "^1.0.1", @@ -1736,30 +1670,6 @@ "url": "https://opencollective.com/eslint" } }, - "node_modules/eslint/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, - "license": "MIT", - "dependencies": { - "balanced-match": "^1.0.0", - "concat-map": "0.0.1" - } - }, - "node_modules/eslint/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, - "license": "ISC", - "dependencies": { - "brace-expansion": "^1.1.7" - }, - "engines": { - "node": "*" - } - }, "node_modules/espree": { "version": "10.2.0", "resolved": "https://registry.npmjs.org/espree/-/espree-10.2.0.tgz", @@ -1831,16 +1741,12 @@ "dev": true, "license": "MIT" }, ->>>>>>> dev "node_modules/fast-glob": { "version": "3.3.2", "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.3.2.tgz", "integrity": "sha512-oX2ruAFQwf/Orj8m737Y5adxDQO0LAB7/S5MnxCdTNDd4p6BsyIVsv9JQsATbTSq8KHRpLwIHbVlUNatxd+1Ow==", "dev": true, -<<<<<<< HEAD -======= "license": "MIT", ->>>>>>> dev "dependencies": { "@nodelib/fs.stat": "^2.0.2", "@nodelib/fs.walk": "^1.2.3", @@ -1852,8 +1758,6 @@ "node": ">=8.6.0" } }, -<<<<<<< HEAD -======= "node_modules/fast-glob/node_modules/glob-parent": { "version": "5.1.2", "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", @@ -1881,22 +1785,16 @@ "dev": true, "license": "MIT" }, ->>>>>>> dev "node_modules/fastq": { "version": "1.17.1", "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.17.1.tgz", "integrity": "sha512-sRVD3lWVIXWg6By68ZN7vho9a1pQcN/WBFaAAsDDFzlJjvoGx0P8z7V1t72grFJfJhu3YPZBuu25f7Kaw2jN1w==", "dev": true, -<<<<<<< HEAD -======= "license": "ISC", ->>>>>>> dev "dependencies": { "reusify": "^1.0.4" } }, -<<<<<<< HEAD -======= "node_modules/file-entry-cache": { "version": "8.0.0", "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-8.0.0.tgz", @@ -1910,16 +1808,12 @@ "node": ">=16.0.0" } }, ->>>>>>> dev "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, -<<<<<<< HEAD -======= "license": "MIT", ->>>>>>> dev "dependencies": { "to-regex-range": "^5.0.1" }, @@ -1927,8 +1821,6 @@ "node": ">=8" } }, -<<<<<<< HEAD -======= "node_modules/find-up": { "version": "5.0.0", "resolved": "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz", @@ -1967,7 +1859,6 @@ "dev": true, "license": "ISC" }, ->>>>>>> dev "node_modules/foreground-child": { "version": "3.3.0", "resolved": "https://registry.npmjs.org/foreground-child/-/foreground-child-3.3.0.tgz", @@ -2038,44 +1929,42 @@ } }, "node_modules/glob-parent": { -<<<<<<< HEAD - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", - "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", + "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, + "license": "ISC", "dependencies": { - "is-glob": "^4.0.1" + "is-glob": "^4.0.3" }, "engines": { - "node": ">= 6" + "node": ">=10.13.0" } }, - "node_modules/globby": { - "version": "11.1.0", - "resolved": "https://registry.npmjs.org/globby/-/globby-11.1.0.tgz", - "integrity": "sha512-jhIXaOzy1sb8IyocaruWSn1TjmnBVs8Ayhcy83rmxNJ8q2uWKCAj3CnJY+KpGSXCueAPc0i05kVvVKtP1t9S3g==", + "node_modules/glob/node_modules/brace-expansion": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", + "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", "dev": true, + "license": "MIT", "dependencies": { - "array-union": "^2.1.0", - "dir-glob": "^3.0.1", - "fast-glob": "^3.2.9", - "ignore": "^5.2.0", - "merge2": "^1.4.1", - "slash": "^3.0.0" - }, - "engines": { - "node": ">=10" -======= - "version": "6.0.2", - "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-6.0.2.tgz", - "integrity": "sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==", + "balanced-match": "^1.0.0" + } + }, + "node_modules/glob/node_modules/minimatch": { + "version": "10.0.1", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-10.0.1.tgz", + "integrity": "sha512-ethXTt3SGGR+95gudmqJ1eNhRO7eGEGIgYA9vnPatK4/etz2MEVDno5GMCibdMTuBMyElzIlgxMna3K94XDIDQ==", "dev": true, "license": "ISC", "dependencies": { - "is-glob": "^4.0.3" + "brace-expansion": "^2.0.1" }, "engines": { - "node": ">=10.13.0" + "node": "20 || >=22" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" } }, "node_modules/globals": { @@ -2086,14 +1975,32 @@ "license": "MIT", "engines": { "node": ">=18" ->>>>>>> dev }, "funding": { "url": "https://github.com/sponsors/sindresorhus" } }, -<<<<<<< HEAD -======= + "node_modules/globby": { + "version": "11.1.0", + "resolved": "https://registry.npmjs.org/globby/-/globby-11.1.0.tgz", + "integrity": "sha512-jhIXaOzy1sb8IyocaruWSn1TjmnBVs8Ayhcy83rmxNJ8q2uWKCAj3CnJY+KpGSXCueAPc0i05kVvVKtP1t9S3g==", + "dev": true, + "license": "MIT", + "dependencies": { + "array-union": "^2.1.0", + "dir-glob": "^3.0.1", + "fast-glob": "^3.2.9", + "ignore": "^5.2.0", + "merge2": "^1.4.1", + "slash": "^3.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/graphemer": { "version": "1.4.0", "resolved": "https://registry.npmjs.org/graphemer/-/graphemer-1.4.0.tgz", @@ -2160,32 +2067,16 @@ "url": "https://github.com/sponsors/wooorm" } }, ->>>>>>> dev "node_modules/ignore": { "version": "5.3.2", "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.3.2.tgz", "integrity": "sha512-hsBTNUqQTDwkWtcdYI2i06Y/nUBEsNEDJKjWdigLvegy8kDuJAS8uRlpkkcQpyEXL0Z/pjDy5HBmMjRCJ2gq+g==", "dev": true, -<<<<<<< HEAD -======= "license": "MIT", ->>>>>>> dev "engines": { "node": ">= 4" } }, -<<<<<<< HEAD - "node_modules/is-binary-path": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz", - "integrity": "sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==", - "dev": true, - "dependencies": { - "binary-extensions": "^2.0.0" - }, - "engines": { - "node": ">=8" -======= "node_modules/import-fresh": { "version": "3.3.0", "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.0.tgz", @@ -2211,7 +2102,19 @@ "license": "MIT", "engines": { "node": ">=0.8.19" ->>>>>>> dev + } + }, + "node_modules/is-binary-path": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz", + "integrity": "sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==", + "dev": true, + "license": "MIT", + "dependencies": { + "binary-extensions": "^2.0.0" + }, + "engines": { + "node": ">=8" } }, "node_modules/is-extglob": { @@ -2219,10 +2122,7 @@ "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", "integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==", "dev": true, -<<<<<<< HEAD -======= "license": "MIT", ->>>>>>> dev "engines": { "node": ">=0.10.0" } @@ -2242,10 +2142,7 @@ "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz", "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==", "dev": true, -<<<<<<< HEAD -======= "license": "MIT", ->>>>>>> dev "dependencies": { "is-extglob": "^2.1.1" }, @@ -2258,10 +2155,7 @@ "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", "dev": true, -<<<<<<< HEAD -======= "license": "MIT", ->>>>>>> dev "engines": { "node": ">=0.12.0" } @@ -2404,8 +2298,6 @@ "dev": true, "license": "ISC" }, -<<<<<<< HEAD -======= "node_modules/markdown-it": { "version": "14.1.0", "resolved": "https://registry.npmjs.org/markdown-it/-/markdown-it-14.1.0.tgz", @@ -2453,22 +2345,16 @@ "dev": true, "license": "MIT" }, ->>>>>>> dev "node_modules/merge2": { "version": "1.4.1", "resolved": "https://registry.npmjs.org/merge2/-/merge2-1.4.1.tgz", "integrity": "sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==", "dev": true, -<<<<<<< HEAD -======= "license": "MIT", ->>>>>>> dev "engines": { "node": ">= 8" } }, -<<<<<<< HEAD -======= "node_modules/micromark-util-character": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/micromark-util-character/-/micromark-util-character-2.1.0.tgz", @@ -2563,16 +2449,12 @@ ], "license": "MIT" }, ->>>>>>> dev "node_modules/micromatch": { "version": "4.0.8", "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.8.tgz", "integrity": "sha512-PXwfBhYu0hBCPw8Dn0E+WDYb7af3dSLVWKi3HGv84IdF4TyFoC0ysxFd0Goxw7nSv4T/PzEJQxsYsEiFCKo2BA==", "dev": true, -<<<<<<< HEAD -======= "license": "MIT", ->>>>>>> dev "dependencies": { "braces": "^3.0.3", "picomatch": "^2.3.1" @@ -2581,35 +2463,17 @@ "node": ">=8.6" } }, -<<<<<<< HEAD - "node_modules/micromatch/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" - } - }, -======= ->>>>>>> dev "node_modules/minimatch": { - "version": "10.0.1", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-10.0.1.tgz", - "integrity": "sha512-ethXTt3SGGR+95gudmqJ1eNhRO7eGEGIgYA9vnPatK4/etz2MEVDno5GMCibdMTuBMyElzIlgxMna3K94XDIDQ==", + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", "dev": true, "license": "ISC", "dependencies": { - "brace-expansion": "^2.0.1" + "brace-expansion": "^1.1.7" }, "engines": { - "node": "20 || >=22" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" + "node": "*" } }, "node_modules/minipass": { @@ -2622,12 +2486,19 @@ "node": ">=16 || 14 >=14.17" } }, -<<<<<<< HEAD + "node_modules/ms": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", + "dev": true, + "license": "MIT" + }, "node_modules/mylas": { "version": "2.1.13", "resolved": "https://registry.npmjs.org/mylas/-/mylas-2.1.13.tgz", "integrity": "sha512-+MrqnJRtxdF+xngFfUUkIMQrUUL0KsxbADUkn23Z/4ibGg192Q+z+CQyiYwvWTsYjJygmMR8+w3ZDa98Zh6ESg==", "dev": true, + "license": "MIT", "engines": { "node": ">=12.0.0" }, @@ -2636,27 +2507,22 @@ "url": "https://github.com/sponsors/raouldeheer" } }, + "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, + "license": "MIT" + }, "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, + "license": "MIT", "engines": { "node": ">=0.10.0" -======= - "node_modules/ms": { - "version": "2.1.3", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", - "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", - "dev": true, - "license": "MIT" - }, - "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, - "license": "MIT" + } }, "node_modules/oniguruma-to-js": { "version": "0.4.3", @@ -2719,7 +2585,6 @@ }, "funding": { "url": "https://github.com/sponsors/sindresorhus" ->>>>>>> dev } }, "node_modules/package-json-from-dist": { @@ -2779,36 +2644,16 @@ "url": "https://github.com/sponsors/isaacs" } }, -<<<<<<< HEAD "node_modules/path-type": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/path-type/-/path-type-4.0.0.tgz", "integrity": "sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==", "dev": true, + "license": "MIT", "engines": { "node": ">=8" } }, - "node_modules/plimit-lit": { - "version": "1.6.1", - "resolved": "https://registry.npmjs.org/plimit-lit/-/plimit-lit-1.6.1.tgz", - "integrity": "sha512-B7+VDyb8Tl6oMJT9oSO2CW8XC/T4UcJGrwOVoNGwOQsQYhlpfajmrMj5xeejqaASq3V/EqThyOeATEOMuSEXiA==", - "dev": true, - "dependencies": { - "queue-lit": "^1.5.1" - }, - "engines": { - "node": ">=12" - } - }, - "node_modules/queue-lit": { - "version": "1.5.2", - "resolved": "https://registry.npmjs.org/queue-lit/-/queue-lit-1.5.2.tgz", - "integrity": "sha512-tLc36IOPeMAubu8BkW8YDBV+WyIgKlYU7zUNs0J5Vk9skSZ4JfGlPOqplP0aHdfv7HL0B2Pg6nwiq60Qc6M2Hw==", - "dev": true, - "engines": { - "node": ">=12" -======= "node_modules/picomatch": { "version": "2.3.1", "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", @@ -2822,6 +2667,19 @@ "url": "https://github.com/sponsors/jonschlinkert" } }, + "node_modules/plimit-lit": { + "version": "1.6.1", + "resolved": "https://registry.npmjs.org/plimit-lit/-/plimit-lit-1.6.1.tgz", + "integrity": "sha512-B7+VDyb8Tl6oMJT9oSO2CW8XC/T4UcJGrwOVoNGwOQsQYhlpfajmrMj5xeejqaASq3V/EqThyOeATEOMuSEXiA==", + "dev": true, + "license": "MIT", + "dependencies": { + "queue-lit": "^1.5.1" + }, + "engines": { + "node": ">=12" + } + }, "node_modules/prelude-ls": { "version": "1.2.1", "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.2.1.tgz", @@ -2861,7 +2719,16 @@ "license": "MIT", "engines": { "node": ">=6" ->>>>>>> dev + } + }, + "node_modules/queue-lit": { + "version": "1.5.2", + "resolved": "https://registry.npmjs.org/queue-lit/-/queue-lit-1.5.2.tgz", + "integrity": "sha512-tLc36IOPeMAubu8BkW8YDBV+WyIgKlYU7zUNs0J5Vk9skSZ4JfGlPOqplP0aHdfv7HL0B2Pg6nwiq60Qc6M2Hw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12" } }, "node_modules/queue-microtask": { @@ -2882,14 +2749,15 @@ "type": "consulting", "url": "https://feross.org/support" } -<<<<<<< HEAD - ] + ], + "license": "MIT" }, "node_modules/readdirp": { "version": "3.6.0", "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz", "integrity": "sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==", "dev": true, + "license": "MIT", "dependencies": { "picomatch": "^2.2.1" }, @@ -2897,20 +2765,6 @@ "node": ">=8.10.0" } }, - "node_modules/readdirp/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" -======= - ], - "license": "MIT" - }, "node_modules/regex": { "version": "4.3.3", "resolved": "https://registry.npmjs.org/regex/-/regex-4.3.3.tgz", @@ -2926,7 +2780,6 @@ "license": "MIT", "engines": { "node": ">=4" ->>>>>>> dev } }, "node_modules/resolve-pkg-maps": { @@ -2944,10 +2797,7 @@ "resolved": "https://registry.npmjs.org/reusify/-/reusify-1.0.4.tgz", "integrity": "sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw==", "dev": true, -<<<<<<< HEAD -======= "license": "MIT", ->>>>>>> dev "engines": { "iojs": ">=1.0.0", "node": ">=0.10.0" @@ -2992,16 +2842,11 @@ "url": "https://feross.org/support" } ], -<<<<<<< HEAD -======= "license": "MIT", ->>>>>>> dev "dependencies": { "queue-microtask": "^1.2.2" } }, -<<<<<<< HEAD -======= "node_modules/semver": { "version": "7.6.3", "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.3.tgz", @@ -3015,7 +2860,6 @@ "node": ">=10" } }, ->>>>>>> dev "node_modules/shebang-command": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", @@ -3067,15 +2911,16 @@ "url": "https://github.com/sponsors/isaacs" } }, -<<<<<<< HEAD "node_modules/slash": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/slash/-/slash-3.0.0.tgz", "integrity": "sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==", "dev": true, + "license": "MIT", "engines": { "node": ">=8" -======= + } + }, "node_modules/space-separated-tokens": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/space-separated-tokens/-/space-separated-tokens-2.0.2.tgz", @@ -3085,7 +2930,6 @@ "funding": { "type": "github", "url": "https://github.com/sponsors/wooorm" ->>>>>>> dev } }, "node_modules/string-width": { @@ -3207,8 +3051,6 @@ "node": ">=8" } }, -<<<<<<< HEAD -======= "node_modules/strip-json-comments": { "version": "3.1.1", "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz", @@ -3242,16 +3084,12 @@ "dev": true, "license": "MIT" }, ->>>>>>> dev "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, -<<<<<<< HEAD -======= "license": "MIT", ->>>>>>> dev "dependencies": { "is-number": "^7.0.0" }, @@ -3259,8 +3097,6 @@ "node": ">=8.0" } }, -<<<<<<< HEAD -======= "node_modules/trim-lines": { "version": "3.0.1", "resolved": "https://registry.npmjs.org/trim-lines/-/trim-lines-3.0.1.tgz", @@ -3285,7 +3121,6 @@ "typescript": ">=4.2.0" } }, ->>>>>>> dev "node_modules/ts-node": { "version": "10.9.2", "resolved": "https://registry.npmjs.org/ts-node/-/ts-node-10.9.2.tgz", @@ -3382,9 +3217,9 @@ } }, "node_modules/typedoc": { - "version": "0.26.9", - "resolved": "https://registry.npmjs.org/typedoc/-/typedoc-0.26.9.tgz", - "integrity": "sha512-Rc7QpWL7EtmrT8yxV0GmhOR6xHgFnnhphbD9Suti3fz3um7ZOrou6q/g9d6+zC5PssTLZmjaW4Upmzv8T1rCcQ==", + "version": "0.26.10", + "resolved": "https://registry.npmjs.org/typedoc/-/typedoc-0.26.10.tgz", + "integrity": "sha512-xLmVKJ8S21t+JeuQLNueebEuTVphx6IrP06CdV7+0WVflUSW3SPmR+h1fnWVdAR/FQePEgsSWCUHXqKKjzuUAw==", "dev": true, "license": "Apache-2.0", "dependencies": { @@ -3404,6 +3239,16 @@ "typescript": "4.6.x || 4.7.x || 4.8.x || 4.9.x || 5.0.x || 5.1.x || 5.2.x || 5.3.x || 5.4.x || 5.5.x || 5.6.x" } }, + "node_modules/typedoc/node_modules/brace-expansion": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", + "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", + "dev": true, + "license": "MIT", + "dependencies": { + "balanced-match": "^1.0.0" + } + }, "node_modules/typedoc/node_modules/minimatch": { "version": "9.0.5", "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.5.tgz", @@ -3421,10 +3266,11 @@ } }, "node_modules/typescript": { - "version": "5.6.2", - "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.6.2.tgz", - "integrity": "sha512-NW8ByodCSNCwZeghjN3o+JX5OFH0Ojg6sadjEKY4huZ52TqbJTJnDo5+Tw98lSy63NZvi4n+ez5m2u5d4PkZyw==", + "version": "5.6.3", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.6.3.tgz", + "integrity": "sha512-hjcS1mhfuyi4WW8IWtjP7brDrG2cuDZukyrYrSauoXGNgx0S7zceP07adYkJycEr56BOUTNPzbInooiN3fn1qw==", "dev": true, + "license": "Apache-2.0", "bin": { "tsc": "bin/tsc", "tsserver": "bin/tsserver" @@ -3434,15 +3280,15 @@ } }, "node_modules/typescript-eslint": { - "version": "8.8.0", - "resolved": "https://registry.npmjs.org/typescript-eslint/-/typescript-eslint-8.8.0.tgz", - "integrity": "sha512-BjIT/VwJ8+0rVO01ZQ2ZVnjE1svFBiRczcpr1t1Yxt7sT25VSbPfrJtDsQ8uQTy2pilX5nI9gwxhUyLULNentw==", + "version": "8.11.0", + "resolved": "https://registry.npmjs.org/typescript-eslint/-/typescript-eslint-8.11.0.tgz", + "integrity": "sha512-cBRGnW3FSlxaYwU8KfAewxFK5uzeOAp0l2KebIlPDOT5olVi65KDG/yjBooPBG0kGW/HLkoz1c/iuBFehcS3IA==", "dev": true, "license": "MIT", "dependencies": { - "@typescript-eslint/eslint-plugin": "8.8.0", - "@typescript-eslint/parser": "8.8.0", - "@typescript-eslint/utils": "8.8.0" + "@typescript-eslint/eslint-plugin": "8.11.0", + "@typescript-eslint/parser": "8.11.0", + "@typescript-eslint/utils": "8.11.0" }, "engines": { "node": "^18.18.0 || ^20.9.0 || >=21.1.0" @@ -3664,22 +3510,6 @@ "node": ">=8" } }, - "node_modules/wrap-ansi-cjs/node_modules/ansi-styles": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", - "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", - "dev": true, - "license": "MIT", - "dependencies": { - "color-convert": "^2.0.1" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" - } - }, "node_modules/wrap-ansi-cjs/node_modules/emoji-regex": { "version": "8.0.0", "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", @@ -3715,6 +3545,19 @@ "node": ">=8" } }, + "node_modules/wrap-ansi/node_modules/ansi-styles": { + "version": "6.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-6.2.1.tgz", + "integrity": "sha512-bN798gFfQX+viw3R7yrGWRqnrN2oRkEkUjjl4JNn4E8GxxbjtG3FbrEIIY3l8/hrwUwIeCZvi4QuOTP4MErVug==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, "node_modules/yaml": { "version": "2.6.0", "resolved": "https://registry.npmjs.org/yaml/-/yaml-2.6.0.tgz", From 28a416391e1c7518c749c0aee4c611e10a63459a Mon Sep 17 00:00:00 2001 From: Austin Fraser Date: Mon, 21 Oct 2024 18:14:56 -0700 Subject: [PATCH 190/357] added id attribute back to TSX elements for Demo and Features --- mlflow-site/src/app/components/Demo.tsx | 2 +- mlflow-site/src/app/components/Features.tsx | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/mlflow-site/src/app/components/Demo.tsx b/mlflow-site/src/app/components/Demo.tsx index ab85039a..0f273f81 100644 --- a/mlflow-site/src/app/components/Demo.tsx +++ b/mlflow-site/src/app/components/Demo.tsx @@ -22,7 +22,7 @@ const Demo = () => { ); } return ( -
{demos}
+
{demos}
); }; diff --git a/mlflow-site/src/app/components/Features.tsx b/mlflow-site/src/app/components/Features.tsx index 6517c965..9a9c95ea 100644 --- a/mlflow-site/src/app/components/Features.tsx +++ b/mlflow-site/src/app/components/Features.tsx @@ -29,7 +29,7 @@ const Features = () => { ); } return ( -
+
{featureHeader}
{featureLongBlurb}
{cards}
From 8f7844124fd9290c5599a65aea3cbad9eb126bd9 Mon Sep 17 00:00:00 2001 From: Austin Fraser Date: Mon, 21 Oct 2024 18:16:00 -0700 Subject: [PATCH 191/357] committing package-lock.json added pack into mlflow directory --- mlflow/package-lock.json | 3203 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 3203 insertions(+) create mode 100644 mlflow/package-lock.json diff --git a/mlflow/package-lock.json b/mlflow/package-lock.json new file mode 100644 index 00000000..1227129e --- /dev/null +++ b/mlflow/package-lock.json @@ -0,0 +1,3203 @@ +{ + "name": "mlflow-js", + "version": "1.0.0", + "lockfileVersion": 3, + "requires": true, + "packages": { + "": { + "name": "mlflow-js", + "version": "1.0.0", + "license": "MIT", + "devDependencies": { + "@eslint/js": "^9.12.0", + "@types/eslint__js": "^8.42.3", + "@types/node": "^22.5.4", + "eslint": "^9.12.0", + "rimraf": "^6.0.1", + "ts-node": "^10.9.2", + "tsc-alias": "^1.8.10", + "tsx": "^4.19.1", + "typedoc": "^0.26.9", + "typescript": "^5.6.2", + "typescript-eslint": "^8.8.0" + }, + "engines": { + "node": ">=22.7.0" + } + }, + "node_modules/@cspotcode/source-map-support": { + "version": "0.8.1", + "resolved": "https://registry.npmjs.org/@cspotcode/source-map-support/-/source-map-support-0.8.1.tgz", + "integrity": "sha512-IchNf6dN4tHoMFIn/7OE8LWZ19Y6q/67Bmf6vnGREv8RSbBVb9LPJxEcnwrcwX6ixSvaiGoomAUvu4YSxXrVgw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jridgewell/trace-mapping": "0.3.9" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/darwin-x64": { + "version": "0.23.1", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.23.1.tgz", + "integrity": "sha512-aClqdgTDVPSEGgoCS8QDG37Gu8yc9lTHNAQlsztQ6ENetKEO//b8y31MMu2ZaPbn4kVsIABzVLXYLhCGekGDqw==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=18" + } + }, + "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, + "license": "MIT", + "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/eslint-utils/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, + "license": "Apache-2.0", + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/@eslint-community/regexpp": { + "version": "4.11.1", + "resolved": "https://registry.npmjs.org/@eslint-community/regexpp/-/regexpp-4.11.1.tgz", + "integrity": "sha512-m4DVN9ZqskZoLU5GlWZadwDnYo3vAEydiUayB9widCl9ffWx2IvPnp6n3on5rJmziJSw9Bv+Z3ChDVdMwXCY8Q==", + "dev": true, + "license": "MIT", + "engines": { + "node": "^12.0.0 || ^14.0.0 || >=16.0.0" + } + }, + "node_modules/@eslint/config-array": { + "version": "0.18.0", + "resolved": "https://registry.npmjs.org/@eslint/config-array/-/config-array-0.18.0.tgz", + "integrity": "sha512-fTxvnS1sRMu3+JjXwJG0j/i4RT9u4qJ+lqS/yCGap4lH4zZGzQ7tu+xZqQmcMZq5OBZDL4QRxQzRjkWcGt8IVw==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "@eslint/object-schema": "^2.1.4", + "debug": "^4.3.1", + "minimatch": "^3.1.2" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + } + }, + "node_modules/@eslint/core": { + "version": "0.7.0", + "resolved": "https://registry.npmjs.org/@eslint/core/-/core-0.7.0.tgz", + "integrity": "sha512-xp5Jirz5DyPYlPiKat8jaq0EmYvDXKKpzTbxXMpT9eqlRJkRKIz9AGMdlvYjih+im+QlhWrpvVjl8IPC/lHlUw==", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + } + }, + "node_modules/@eslint/eslintrc": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-3.1.0.tgz", + "integrity": "sha512-4Bfj15dVJdoy3RfZmmo86RK1Fwzn6SstsvK9JS+BaVKqC6QQQQyXekNaC+g+LKNgkQ+2VhGAzm6hO40AhMR3zQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "ajv": "^6.12.4", + "debug": "^4.3.2", + "espree": "^10.0.1", + "globals": "^14.0.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": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/@eslint/js": { + "version": "9.13.0", + "resolved": "https://registry.npmjs.org/@eslint/js/-/js-9.13.0.tgz", + "integrity": "sha512-IFLyoY4d72Z5y/6o/BazFBezupzI/taV8sGumxTAVw3lXG9A6md1Dc34T9s1FoD/an9pJH8RHbAxsaEbBed9lA==", + "dev": true, + "license": "MIT", + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + } + }, + "node_modules/@eslint/object-schema": { + "version": "2.1.4", + "resolved": "https://registry.npmjs.org/@eslint/object-schema/-/object-schema-2.1.4.tgz", + "integrity": "sha512-BsWiH1yFGjXXS2yvrf5LyuoSIIbPrGUWob917o+BTKuZ7qJdxX8aJLRxs1fS9n6r7vESrq1OUqb68dANcFXuQQ==", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + } + }, + "node_modules/@eslint/plugin-kit": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/@eslint/plugin-kit/-/plugin-kit-0.2.1.tgz", + "integrity": "sha512-HFZ4Mp26nbWk9d/BpvP0YNL6W4UoZF0VFcTw/aPPA8RpOxeFQgK+ClABGgAUXs9Y/RGX/l1vOmrqz1MQt9MNuw==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "levn": "^0.4.1" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + } + }, + "node_modules/@humanfs/core": { + "version": "0.19.0", + "resolved": "https://registry.npmjs.org/@humanfs/core/-/core-0.19.0.tgz", + "integrity": "sha512-2cbWIHbZVEweE853g8jymffCA+NCMiuqeECeBBLm8dg2oFdjuGJhgN4UAbI+6v0CKbbhvtXA4qV8YR5Ji86nmw==", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": ">=18.18.0" + } + }, + "node_modules/@humanfs/node": { + "version": "0.16.5", + "resolved": "https://registry.npmjs.org/@humanfs/node/-/node-0.16.5.tgz", + "integrity": "sha512-KSPA4umqSG4LHYRodq31VDwKAvaTF4xmVlzM8Aeh4PlU1JQ3IG0wiA8C25d3RQ9nJyM3mBHyI53K06VVL/oFFg==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "@humanfs/core": "^0.19.0", + "@humanwhocodes/retry": "^0.3.0" + }, + "engines": { + "node": ">=18.18.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, + "license": "Apache-2.0", + "engines": { + "node": ">=12.22" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/nzakas" + } + }, + "node_modules/@humanwhocodes/retry": { + "version": "0.3.1", + "resolved": "https://registry.npmjs.org/@humanwhocodes/retry/-/retry-0.3.1.tgz", + "integrity": "sha512-JBxkERygn7Bv/GbN5Rv8Ul6LVknS+5Bp6RgDC/O8gEBU/yeH5Ui5C/OlWrTb6qct7LjjfT6Re2NxB0ln0yYybA==", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": ">=18.18" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/nzakas" + } + }, + "node_modules/@isaacs/cliui": { + "version": "8.0.2", + "resolved": "https://registry.npmjs.org/@isaacs/cliui/-/cliui-8.0.2.tgz", + "integrity": "sha512-O8jcjabXaleOG9DQ0+ARXWZBTfnP4WNAqzuiJK7ll44AmxGKv/J2M4TPjxjY3znBCfvBXFzucm1twdyFybFqEA==", + "dev": true, + "license": "ISC", + "dependencies": { + "string-width": "^5.1.2", + "string-width-cjs": "npm:string-width@^4.2.0", + "strip-ansi": "^7.0.1", + "strip-ansi-cjs": "npm:strip-ansi@^6.0.1", + "wrap-ansi": "^8.1.0", + "wrap-ansi-cjs": "npm:wrap-ansi@^7.0.0" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/@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, + "license": "MIT", + "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, + "license": "MIT" + }, + "node_modules/@jridgewell/trace-mapping": { + "version": "0.3.9", + "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.9.tgz", + "integrity": "sha512-3Belt6tdc8bPgAtbcmdtNJlirVoTmEb5e2gC94PnkwEW9jI6CAHUeoG85tjWP5WquqfavoMtMwiG4P926ZKKuQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jridgewell/resolve-uri": "^3.0.3", + "@jridgewell/sourcemap-codec": "^1.4.10" + } + }, + "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, + "license": "MIT", + "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, + "license": "MIT", + "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, + "license": "MIT", + "dependencies": { + "@nodelib/fs.scandir": "2.1.5", + "fastq": "^1.6.0" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/@shikijs/core": { + "version": "1.22.0", + "resolved": "https://registry.npmjs.org/@shikijs/core/-/core-1.22.0.tgz", + "integrity": "sha512-S8sMe4q71TJAW+qG93s5VaiihujRK6rqDFqBnxqvga/3LvqHEnxqBIOPkt//IdXVtHkQWKu4nOQNk0uBGicU7Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "@shikijs/engine-javascript": "1.22.0", + "@shikijs/engine-oniguruma": "1.22.0", + "@shikijs/types": "1.22.0", + "@shikijs/vscode-textmate": "^9.3.0", + "@types/hast": "^3.0.4", + "hast-util-to-html": "^9.0.3" + } + }, + "node_modules/@shikijs/engine-javascript": { + "version": "1.22.0", + "resolved": "https://registry.npmjs.org/@shikijs/engine-javascript/-/engine-javascript-1.22.0.tgz", + "integrity": "sha512-AeEtF4Gcck2dwBqCFUKYfsCq0s+eEbCEbkUuFou53NZ0sTGnJnJ/05KHQFZxpii5HMXbocV9URYVowOP2wH5kw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@shikijs/types": "1.22.0", + "@shikijs/vscode-textmate": "^9.3.0", + "oniguruma-to-js": "0.4.3" + } + }, + "node_modules/@shikijs/engine-oniguruma": { + "version": "1.22.0", + "resolved": "https://registry.npmjs.org/@shikijs/engine-oniguruma/-/engine-oniguruma-1.22.0.tgz", + "integrity": "sha512-5iBVjhu/DYs1HB0BKsRRFipRrD7rqjxlWTj4F2Pf+nQSPqc3kcyqFFeZXnBMzDf0HdqaFVvhDRAGiYNvyLP+Mw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@shikijs/types": "1.22.0", + "@shikijs/vscode-textmate": "^9.3.0" + } + }, + "node_modules/@shikijs/types": { + "version": "1.22.0", + "resolved": "https://registry.npmjs.org/@shikijs/types/-/types-1.22.0.tgz", + "integrity": "sha512-Fw/Nr7FGFhlQqHfxzZY8Cwtwk5E9nKDUgeLjZgt3UuhcM3yJR9xj3ZGNravZZok8XmEZMiYkSMTPlPkULB8nww==", + "dev": true, + "license": "MIT", + "dependencies": { + "@shikijs/vscode-textmate": "^9.3.0", + "@types/hast": "^3.0.4" + } + }, + "node_modules/@shikijs/vscode-textmate": { + "version": "9.3.0", + "resolved": "https://registry.npmjs.org/@shikijs/vscode-textmate/-/vscode-textmate-9.3.0.tgz", + "integrity": "sha512-jn7/7ky30idSkd/O5yDBfAnVt+JJpepofP/POZ1iMOxK59cOfqIgg/Dj0eFsjOTMw+4ycJN0uhZH/Eb0bs/EUA==", + "dev": true, + "license": "MIT" + }, + "node_modules/@tsconfig/node10": { + "version": "1.0.11", + "resolved": "https://registry.npmjs.org/@tsconfig/node10/-/node10-1.0.11.tgz", + "integrity": "sha512-DcRjDCujK/kCk/cUe8Xz8ZSpm8mS3mNNpta+jGCA6USEDfktlNvm1+IuZ9eTcDbNk41BHwpHHeW+N1lKCz4zOw==", + "dev": true, + "license": "MIT" + }, + "node_modules/@tsconfig/node12": { + "version": "1.0.11", + "resolved": "https://registry.npmjs.org/@tsconfig/node12/-/node12-1.0.11.tgz", + "integrity": "sha512-cqefuRsh12pWyGsIoBKJA9luFu3mRxCA+ORZvA4ktLSzIuCUtWVxGIuXigEwO5/ywWFMZ2QEGKWvkZG1zDMTag==", + "dev": true, + "license": "MIT" + }, + "node_modules/@tsconfig/node14": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/@tsconfig/node14/-/node14-1.0.3.tgz", + "integrity": "sha512-ysT8mhdixWK6Hw3i1V2AeRqZ5WfXg1G43mqoYlM2nc6388Fq5jcXyr5mRsqViLx/GJYdoL0bfXD8nmF+Zn/Iow==", + "dev": true, + "license": "MIT" + }, + "node_modules/@tsconfig/node16": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/@tsconfig/node16/-/node16-1.0.4.tgz", + "integrity": "sha512-vxhUy4J8lyeyinH7Azl1pdd43GJhZH/tP2weN8TntQblOY+A0XbT8DJk1/oCPuOOyg/Ja757rG0CgHcWC8OfMA==", + "dev": true, + "license": "MIT" + }, + "node_modules/@types/eslint": { + "version": "9.6.1", + "resolved": "https://registry.npmjs.org/@types/eslint/-/eslint-9.6.1.tgz", + "integrity": "sha512-FXx2pKgId/WyYo2jXw63kk7/+TY7u7AziEJxJAnSFzHlqTAS3Ync6SvgYAN/k4/PQpnnVuzoMuVnByKK2qp0ag==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/estree": "*", + "@types/json-schema": "*" + } + }, + "node_modules/@types/eslint__js": { + "version": "8.42.3", + "resolved": "https://registry.npmjs.org/@types/eslint__js/-/eslint__js-8.42.3.tgz", + "integrity": "sha512-alfG737uhmPdnvkrLdZLcEKJ/B8s9Y4hrZ+YAdzUeoArBlSUERA2E87ROfOaS4jd/C45fzOoZzidLc1IPwLqOw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/eslint": "*" + } + }, + "node_modules/@types/estree": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.6.tgz", + "integrity": "sha512-AYnb1nQyY49te+VRAVgmzfcgjYS91mY5P0TKUDCLEM+gNnA+3T6rWITXRLYCpahpqSQbN5cE+gHpnPyXjHWxcw==", + "dev": true, + "license": "MIT" + }, + "node_modules/@types/hast": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/@types/hast/-/hast-3.0.4.tgz", + "integrity": "sha512-WPs+bbQw5aCj+x6laNGWLH3wviHtoCv/P3+otBhbOhJgG8qtpdAMlTCxLtsTWA7LH1Oh/bFCHsBn0TPS5m30EQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/unist": "*" + } + }, + "node_modules/@types/json-schema": { + "version": "7.0.15", + "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.15.tgz", + "integrity": "sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA==", + "dev": true, + "license": "MIT" + }, + "node_modules/@types/mdast": { + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/@types/mdast/-/mdast-4.0.4.tgz", + "integrity": "sha512-kGaNbPh1k7AFzgpud/gMdvIm5xuECykRR+JnWKQno9TAXVa6WIVCGTPvYGekIDL4uwCZQSYbUxNBSb1aUo79oA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/unist": "*" + } + }, + "node_modules/@types/node": { + "version": "22.7.7", + "resolved": "https://registry.npmjs.org/@types/node/-/node-22.7.7.tgz", + "integrity": "sha512-SRxCrrg9CL/y54aiMCG3edPKdprgMVGDXjA3gB8UmmBW5TcXzRUYAh8EWzTnSJFAd1rgImPELza+A3bJ+qxz8Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "undici-types": "~6.19.2" + } + }, + "node_modules/@types/unist": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/@types/unist/-/unist-3.0.3.tgz", + "integrity": "sha512-ko/gIFJRv177XgZsZcBwnqJN5x/Gien8qNOn0D5bQU/zAzVf9Zt3BlcUiLqhV9y4ARk0GbT3tnUiPNgnTXzc/Q==", + "dev": true, + "license": "MIT" + }, + "node_modules/@typescript-eslint/eslint-plugin": { + "version": "8.11.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-8.11.0.tgz", + "integrity": "sha512-KhGn2LjW1PJT2A/GfDpiyOfS4a8xHQv2myUagTM5+zsormOmBlYsnQ6pobJ8XxJmh6hnHwa2Mbe3fPrDJoDhbA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@eslint-community/regexpp": "^4.10.0", + "@typescript-eslint/scope-manager": "8.11.0", + "@typescript-eslint/type-utils": "8.11.0", + "@typescript-eslint/utils": "8.11.0", + "@typescript-eslint/visitor-keys": "8.11.0", + "graphemer": "^1.4.0", + "ignore": "^5.3.1", + "natural-compare": "^1.4.0", + "ts-api-utils": "^1.3.0" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "@typescript-eslint/parser": "^8.0.0 || ^8.0.0-alpha.0", + "eslint": "^8.57.0 || ^9.0.0" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, + "node_modules/@typescript-eslint/parser": { + "version": "8.11.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-8.11.0.tgz", + "integrity": "sha512-lmt73NeHdy1Q/2ul295Qy3uninSqi6wQI18XwSpm8w0ZbQXUpjCAWP1Vlv/obudoBiIjJVjlztjQ+d/Md98Yxg==", + "dev": true, + "license": "BSD-2-Clause", + "dependencies": { + "@typescript-eslint/scope-manager": "8.11.0", + "@typescript-eslint/types": "8.11.0", + "@typescript-eslint/typescript-estree": "8.11.0", + "@typescript-eslint/visitor-keys": "8.11.0", + "debug": "^4.3.4" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "eslint": "^8.57.0 || ^9.0.0" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, + "node_modules/@typescript-eslint/scope-manager": { + "version": "8.11.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-8.11.0.tgz", + "integrity": "sha512-Uholz7tWhXmA4r6epo+vaeV7yjdKy5QFCERMjs1kMVsLRKIrSdM6o21W2He9ftp5PP6aWOVpD5zvrvuHZC0bMQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@typescript-eslint/types": "8.11.0", + "@typescript-eslint/visitor-keys": "8.11.0" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + } + }, + "node_modules/@typescript-eslint/type-utils": { + "version": "8.11.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-8.11.0.tgz", + "integrity": "sha512-ItiMfJS6pQU0NIKAaybBKkuVzo6IdnAhPFZA/2Mba/uBjuPQPet/8+zh5GtLHwmuFRShZx+8lhIs7/QeDHflOg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@typescript-eslint/typescript-estree": "8.11.0", + "@typescript-eslint/utils": "8.11.0", + "debug": "^4.3.4", + "ts-api-utils": "^1.3.0" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, + "node_modules/@typescript-eslint/types": { + "version": "8.11.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-8.11.0.tgz", + "integrity": "sha512-tn6sNMHf6EBAYMvmPUaKaVeYvhUsrE6x+bXQTxjQRp360h1giATU0WvgeEys1spbvb5R+VpNOZ+XJmjD8wOUHw==", + "dev": true, + "license": "MIT", + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + } + }, + "node_modules/@typescript-eslint/typescript-estree": { + "version": "8.11.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-8.11.0.tgz", + "integrity": "sha512-yHC3s1z1RCHoCz5t06gf7jH24rr3vns08XXhfEqzYpd6Hll3z/3g23JRi0jM8A47UFKNc3u/y5KIMx8Ynbjohg==", + "dev": true, + "license": "BSD-2-Clause", + "dependencies": { + "@typescript-eslint/types": "8.11.0", + "@typescript-eslint/visitor-keys": "8.11.0", + "debug": "^4.3.4", + "fast-glob": "^3.3.2", + "is-glob": "^4.0.3", + "minimatch": "^9.0.4", + "semver": "^7.6.0", + "ts-api-utils": "^1.3.0" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, + "node_modules/@typescript-eslint/typescript-estree/node_modules/brace-expansion": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", + "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", + "dev": true, + "license": "MIT", + "dependencies": { + "balanced-match": "^1.0.0" + } + }, + "node_modules/@typescript-eslint/typescript-estree/node_modules/minimatch": { + "version": "9.0.5", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.5.tgz", + "integrity": "sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow==", + "dev": true, + "license": "ISC", + "dependencies": { + "brace-expansion": "^2.0.1" + }, + "engines": { + "node": ">=16 || 14 >=14.17" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/@typescript-eslint/utils": { + "version": "8.11.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-8.11.0.tgz", + "integrity": "sha512-CYiX6WZcbXNJV7UNB4PLDIBtSdRmRI/nb0FMyqHPTQD1rMjA0foPLaPUV39C/MxkTd/QKSeX+Gb34PPsDVC35g==", + "dev": true, + "license": "MIT", + "dependencies": { + "@eslint-community/eslint-utils": "^4.4.0", + "@typescript-eslint/scope-manager": "8.11.0", + "@typescript-eslint/types": "8.11.0", + "@typescript-eslint/typescript-estree": "8.11.0" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "eslint": "^8.57.0 || ^9.0.0" + } + }, + "node_modules/@typescript-eslint/visitor-keys": { + "version": "8.11.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-8.11.0.tgz", + "integrity": "sha512-EaewX6lxSjRJnc+99+dqzTeoDZUfyrA52d2/HRrkI830kgovWsmIiTfmr0NZorzqic7ga+1bS60lRBUgR3n/Bw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@typescript-eslint/types": "8.11.0", + "eslint-visitor-keys": "^3.4.3" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + } + }, + "node_modules/@typescript-eslint/visitor-keys/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, + "license": "Apache-2.0", + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "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, + "license": "ISC" + }, + "node_modules/acorn": { + "version": "8.13.0", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.13.0.tgz", + "integrity": "sha512-8zSiw54Oxrdym50NlZ9sUusyO1Z1ZchgRLWRaK6c86XJFClyCgFKetdowBg5bKxyp/u+CDBJG4Mpp0m3HLZl9w==", + "dev": true, + "license": "MIT", + "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, + "license": "MIT", + "peerDependencies": { + "acorn": "^6.0.0 || ^7.0.0 || ^8.0.0" + } + }, + "node_modules/acorn-walk": { + "version": "8.3.4", + "resolved": "https://registry.npmjs.org/acorn-walk/-/acorn-walk-8.3.4.tgz", + "integrity": "sha512-ueEepnujpqee2o5aIYnvHU6C0A42MNdsIDeqy5BydrkuC5R1ZuUFnm27EeFJGoEHJQgn3uleRvmTXaJgfXbt4g==", + "dev": true, + "license": "MIT", + "dependencies": { + "acorn": "^8.11.0" + }, + "engines": { + "node": ">=0.4.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, + "license": "MIT", + "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-regex": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.1.0.tgz", + "integrity": "sha512-7HSX4QQb4CspciLpVFwyRe79O3xsIZDDLER21kERQ71oaPodF8jL725AgJMFAYbooIqolJoRLuM81SpeUkpkvA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/ansi-regex?sponsor=1" + } + }, + "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, + "license": "MIT", + "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, + "license": "ISC", + "dependencies": { + "normalize-path": "^3.0.0", + "picomatch": "^2.0.4" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/arg": { + "version": "4.1.3", + "resolved": "https://registry.npmjs.org/arg/-/arg-4.1.3.tgz", + "integrity": "sha512-58S9QDqG0Xx27YwPSt9fJxivjYl432YCwfDMfZ+71RAqUrZef7LrKQZ3LHLOwCS4FLNBplP533Zx895SeOCHvA==", + "dev": true, + "license": "MIT" + }, + "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, + "license": "Python-2.0" + }, + "node_modules/array-union": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/array-union/-/array-union-2.1.0.tgz", + "integrity": "sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "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, + "license": "MIT" + }, + "node_modules/binary-extensions": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.3.0.tgz", + "integrity": "sha512-Ceh+7ox5qe7LJuLHoY0feh3pHuUDHAcRUeyL2VYghZwfpkNIy/+8Ocg0a3UuSoYzavmylwuLWQOf3hl0jjMMIw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "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, + "license": "MIT", + "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, + "license": "MIT", + "dependencies": { + "fill-range": "^7.1.1" + }, + "engines": { + "node": ">=8" + } + }, + "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, + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/ccount": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/ccount/-/ccount-2.0.1.tgz", + "integrity": "sha512-eyrF0jiFpY+3drT6383f1qhkbGsLSifNAjA61IUjZjmLCWjItY6LB9ft9YhoDgwfmclB2zhu51Lc7+95b8NRAg==", + "dev": true, + "license": "MIT", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "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, + "license": "MIT", + "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/character-entities-html4": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/character-entities-html4/-/character-entities-html4-2.1.0.tgz", + "integrity": "sha512-1v7fgQRj6hnSwFpq1Eu0ynr/CDEw0rXo2B61qXrLNdHZmPKgb7fqS1a2JwF0rISo9q77jDI8VMEHoApn8qDoZA==", + "dev": true, + "license": "MIT", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/character-entities-legacy": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/character-entities-legacy/-/character-entities-legacy-3.0.0.tgz", + "integrity": "sha512-RpPp0asT/6ufRm//AJVwpViZbGM/MkjQFxJccQRHmISF/22NBtsHqAWmL+/pmkPWoIUJdWyeVleTl1wydHATVQ==", + "dev": true, + "license": "MIT", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/chokidar": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.6.0.tgz", + "integrity": "sha512-7VT13fmjotKpGipCW9JEQAusEPE+Ei8nl6/g4FBAmIm0GOOLMua9NDDo/DWp0ZAxCr3cPq5ZpBqmPAQgDda2Pw==", + "dev": true, + "license": "MIT", + "dependencies": { + "anymatch": "~3.1.2", + "braces": "~3.0.2", + "glob-parent": "~5.1.2", + "is-binary-path": "~2.1.0", + "is-glob": "~4.0.1", + "normalize-path": "~3.0.0", + "readdirp": "~3.6.0" + }, + "engines": { + "node": ">= 8.10.0" + }, + "funding": { + "url": "https://paulmillr.com/funding/" + }, + "optionalDependencies": { + "fsevents": "~2.3.2" + } + }, + "node_modules/chokidar/node_modules/glob-parent": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", + "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", + "dev": true, + "license": "ISC", + "dependencies": { + "is-glob": "^4.0.1" + }, + "engines": { + "node": ">= 6" + } + }, + "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, + "license": "MIT", + "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, + "license": "MIT" + }, + "node_modules/comma-separated-tokens": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/comma-separated-tokens/-/comma-separated-tokens-2.0.3.tgz", + "integrity": "sha512-Fu4hJdvzeylCfQPp9SGWidpzrMs7tTrlu6Vb8XGaRGck8QSNZJJp538Wrb60Lax4fPwR64ViY468OIUTbRlGZg==", + "dev": true, + "license": "MIT", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/commander": { + "version": "9.5.0", + "resolved": "https://registry.npmjs.org/commander/-/commander-9.5.0.tgz", + "integrity": "sha512-KRs7WVDKg86PWiuAqhDrAQnTXZKraVcCc6vFdL14qrZ/DcWwuRo7VoiYXalXO7S5GKpqYiVEwCbgFDfxNHKJBQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": "^12.20.0 || >=14" + } + }, + "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, + "license": "MIT" + }, + "node_modules/create-require": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/create-require/-/create-require-1.1.1.tgz", + "integrity": "sha512-dcKFX3jn0MpIaXjisoRvexIJVEKzaq7z2rZKxf+MSr9TkdmHmsU4m2lcLojrj/FHl8mk5VxMmYA+ftRkP/3oKQ==", + "dev": true, + "license": "MIT" + }, + "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, + "license": "MIT", + "dependencies": { + "path-key": "^3.1.0", + "shebang-command": "^2.0.0", + "which": "^2.0.1" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/debug": { + "version": "4.3.7", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.7.tgz", + "integrity": "sha512-Er2nc/H7RrMXZBFCEim6TCmMk02Z8vLC2Rbi1KEBggpo0fS6l0S1nnapwmIi3yW/+GOJap1Krg4w0Hg80oCqgQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "ms": "^2.1.3" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "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, + "license": "MIT" + }, + "node_modules/dequal": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/dequal/-/dequal-2.0.3.tgz", + "integrity": "sha512-0je+qPKHEMohvfRTCEo3CrPG6cAzAYgmzKyxRiYSSDkS6eGJdyVJm7WaYA5ECaAD9wLB2T4EEeymA5aFVcYXCA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/devlop": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/devlop/-/devlop-1.1.0.tgz", + "integrity": "sha512-RWmIqhcFf1lRYBvNmr7qTNuyCt/7/ns2jbpp1+PalgE/rDQcBT0fioSMUpJ93irlUhC5hrg4cYqe6U+0ImW0rA==", + "dev": true, + "license": "MIT", + "dependencies": { + "dequal": "^2.0.0" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/diff": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/diff/-/diff-4.0.2.tgz", + "integrity": "sha512-58lmxKSA4BNyLz+HHMUzlOEpg09FV+ev6ZMe3vJihgdxzgcwZ8VoEEPmALCZG9LmqfVoNMMKpttIYTVG6uDY7A==", + "dev": true, + "license": "BSD-3-Clause", + "engines": { + "node": ">=0.3.1" + } + }, + "node_modules/dir-glob": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/dir-glob/-/dir-glob-3.0.1.tgz", + "integrity": "sha512-WkrWp9GR4KXfKGYzOLmTuGVi1UWFfws377n9cc55/tb6DuqyF6pcQ5AbiHEshaDpY9v6oaSr2XCDidGmMwdzIA==", + "dev": true, + "license": "MIT", + "dependencies": { + "path-type": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/eastasianwidth": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/eastasianwidth/-/eastasianwidth-0.2.0.tgz", + "integrity": "sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA==", + "dev": true, + "license": "MIT" + }, + "node_modules/emoji-regex": { + "version": "9.2.2", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-9.2.2.tgz", + "integrity": "sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==", + "dev": true, + "license": "MIT" + }, + "node_modules/entities": { + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/entities/-/entities-4.5.0.tgz", + "integrity": "sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw==", + "dev": true, + "license": "BSD-2-Clause", + "engines": { + "node": ">=0.12" + }, + "funding": { + "url": "https://github.com/fb55/entities?sponsor=1" + } + }, + "node_modules/esbuild": { + "version": "0.23.1", + "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.23.1.tgz", + "integrity": "sha512-VVNz/9Sa0bs5SELtn3f7qhJCDPCF5oMEl5cO9/SSinpE9hbPVvxbd572HH5AKiP7WD8INO53GgfDDhRjkylHEg==", + "dev": true, + "hasInstallScript": true, + "license": "MIT", + "bin": { + "esbuild": "bin/esbuild" + }, + "engines": { + "node": ">=18" + }, + "optionalDependencies": { + "@esbuild/aix-ppc64": "0.23.1", + "@esbuild/android-arm": "0.23.1", + "@esbuild/android-arm64": "0.23.1", + "@esbuild/android-x64": "0.23.1", + "@esbuild/darwin-arm64": "0.23.1", + "@esbuild/darwin-x64": "0.23.1", + "@esbuild/freebsd-arm64": "0.23.1", + "@esbuild/freebsd-x64": "0.23.1", + "@esbuild/linux-arm": "0.23.1", + "@esbuild/linux-arm64": "0.23.1", + "@esbuild/linux-ia32": "0.23.1", + "@esbuild/linux-loong64": "0.23.1", + "@esbuild/linux-mips64el": "0.23.1", + "@esbuild/linux-ppc64": "0.23.1", + "@esbuild/linux-riscv64": "0.23.1", + "@esbuild/linux-s390x": "0.23.1", + "@esbuild/linux-x64": "0.23.1", + "@esbuild/netbsd-x64": "0.23.1", + "@esbuild/openbsd-arm64": "0.23.1", + "@esbuild/openbsd-x64": "0.23.1", + "@esbuild/sunos-x64": "0.23.1", + "@esbuild/win32-arm64": "0.23.1", + "@esbuild/win32-ia32": "0.23.1", + "@esbuild/win32-x64": "0.23.1" + } + }, + "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, + "license": "MIT", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/eslint": { + "version": "9.13.0", + "resolved": "https://registry.npmjs.org/eslint/-/eslint-9.13.0.tgz", + "integrity": "sha512-EYZK6SX6zjFHST/HRytOdA/zE72Cq/bfw45LSyuwrdvcclb/gqV8RRQxywOBEWO2+WDpva6UZa4CcDeJKzUCFA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@eslint-community/eslint-utils": "^4.2.0", + "@eslint-community/regexpp": "^4.11.0", + "@eslint/config-array": "^0.18.0", + "@eslint/core": "^0.7.0", + "@eslint/eslintrc": "^3.1.0", + "@eslint/js": "9.13.0", + "@eslint/plugin-kit": "^0.2.0", + "@humanfs/node": "^0.16.5", + "@humanwhocodes/module-importer": "^1.0.1", + "@humanwhocodes/retry": "^0.3.1", + "@types/estree": "^1.0.6", + "@types/json-schema": "^7.0.15", + "ajv": "^6.12.4", + "chalk": "^4.0.0", + "cross-spawn": "^7.0.2", + "debug": "^4.3.2", + "escape-string-regexp": "^4.0.0", + "eslint-scope": "^8.1.0", + "eslint-visitor-keys": "^4.1.0", + "espree": "^10.2.0", + "esquery": "^1.5.0", + "esutils": "^2.0.2", + "fast-deep-equal": "^3.1.3", + "file-entry-cache": "^8.0.0", + "find-up": "^5.0.0", + "glob-parent": "^6.0.2", + "ignore": "^5.2.0", + "imurmurhash": "^0.1.4", + "is-glob": "^4.0.0", + "json-stable-stringify-without-jsonify": "^1.0.1", + "lodash.merge": "^4.6.2", + "minimatch": "^3.1.2", + "natural-compare": "^1.4.0", + "optionator": "^0.9.3", + "text-table": "^0.2.0" + }, + "bin": { + "eslint": "bin/eslint.js" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "url": "https://eslint.org/donate" + }, + "peerDependencies": { + "jiti": "*" + }, + "peerDependenciesMeta": { + "jiti": { + "optional": true + } + } + }, + "node_modules/eslint-scope": { + "version": "8.1.0", + "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-8.1.0.tgz", + "integrity": "sha512-14dSvlhaVhKKsa9Fx1l8A17s7ah7Ef7wCakJ10LYk6+GYmP9yDti2oq2SEwcyndt6knfcZyhyxwY3i9yL78EQw==", + "dev": true, + "license": "BSD-2-Clause", + "dependencies": { + "esrecurse": "^4.3.0", + "estraverse": "^5.2.0" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/eslint-visitor-keys": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-4.1.0.tgz", + "integrity": "sha512-Q7lok0mqMUSf5a/AdAZkA5a/gHcO6snwQClVNNvFKCAVlxXucdU8pKydU5ZVZjBx5xr37vGbFFWtLQYreLzrZg==", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/espree": { + "version": "10.2.0", + "resolved": "https://registry.npmjs.org/espree/-/espree-10.2.0.tgz", + "integrity": "sha512-upbkBJbckcCNBDBDXEbuhjbP68n+scUd3k/U2EkyM9nw+I/jPiL4cLF/Al06CF96wRltFda16sxDFrxsI1v0/g==", + "dev": true, + "license": "BSD-2-Clause", + "dependencies": { + "acorn": "^8.12.0", + "acorn-jsx": "^5.3.2", + "eslint-visitor-keys": "^4.1.0" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/esquery": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.6.0.tgz", + "integrity": "sha512-ca9pw9fomFcKPvFLXhBKUK90ZvGibiGOvRJNbjljY7s7uq/5YO4BOzcYtJqExdx99rF6aAcnRxHmcUHcz6sQsg==", + "dev": true, + "license": "BSD-3-Clause", + "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, + "license": "BSD-2-Clause", + "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, + "license": "BSD-2-Clause", + "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, + "license": "BSD-2-Clause", + "engines": { + "node": ">=0.10.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, + "license": "MIT" + }, + "node_modules/fast-glob": { + "version": "3.3.2", + "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.3.2.tgz", + "integrity": "sha512-oX2ruAFQwf/Orj8m737Y5adxDQO0LAB7/S5MnxCdTNDd4p6BsyIVsv9JQsATbTSq8KHRpLwIHbVlUNatxd+1Ow==", + "dev": true, + "license": "MIT", + "dependencies": { + "@nodelib/fs.stat": "^2.0.2", + "@nodelib/fs.walk": "^1.2.3", + "glob-parent": "^5.1.2", + "merge2": "^1.3.0", + "micromatch": "^4.0.4" + }, + "engines": { + "node": ">=8.6.0" + } + }, + "node_modules/fast-glob/node_modules/glob-parent": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", + "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", + "dev": true, + "license": "ISC", + "dependencies": { + "is-glob": "^4.0.1" + }, + "engines": { + "node": ">= 6" + } + }, + "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, + "license": "MIT" + }, + "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, + "license": "MIT" + }, + "node_modules/fastq": { + "version": "1.17.1", + "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.17.1.tgz", + "integrity": "sha512-sRVD3lWVIXWg6By68ZN7vho9a1pQcN/WBFaAAsDDFzlJjvoGx0P8z7V1t72grFJfJhu3YPZBuu25f7Kaw2jN1w==", + "dev": true, + "license": "ISC", + "dependencies": { + "reusify": "^1.0.4" + } + }, + "node_modules/file-entry-cache": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-8.0.0.tgz", + "integrity": "sha512-XXTUwCvisa5oacNGRP9SfNtYBNAMi+RPwBFmblZEF7N7swHYQS6/Zfk7SRwx4D5j3CH211YNRco1DEMNVfZCnQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "flat-cache": "^4.0.0" + }, + "engines": { + "node": ">=16.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, + "license": "MIT", + "dependencies": { + "to-regex-range": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "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, + "license": "MIT", + "dependencies": { + "locate-path": "^6.0.0", + "path-exists": "^4.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/flat-cache": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-4.0.1.tgz", + "integrity": "sha512-f7ccFPK3SXFHpx15UIGyRJ/FJQctuKZ0zVuN3frBo4HnK3cay9VEW0R6yPYFHC0AgqhukPzKjq22t5DmAyqGyw==", + "dev": true, + "license": "MIT", + "dependencies": { + "flatted": "^3.2.9", + "keyv": "^4.5.4" + }, + "engines": { + "node": ">=16" + } + }, + "node_modules/flatted": { + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.3.1.tgz", + "integrity": "sha512-X8cqMLLie7KsNUDSdzeN8FYK9rEt4Dt67OsG/DNGnYTSDBG4uFAJFBnUeiV+zCVAvwFy56IjM9sH51jVaEhNxw==", + "dev": true, + "license": "ISC" + }, + "node_modules/foreground-child": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/foreground-child/-/foreground-child-3.3.0.tgz", + "integrity": "sha512-Ld2g8rrAyMYFXBhEqMz8ZAHBi4J4uS1i/CxGMDnjyFWddMXLVcDp051DZfu+t7+ab7Wv6SMqpWmyFIj5UbfFvg==", + "dev": true, + "license": "ISC", + "dependencies": { + "cross-spawn": "^7.0.0", + "signal-exit": "^4.0.1" + }, + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/get-tsconfig": { + "version": "4.8.1", + "resolved": "https://registry.npmjs.org/get-tsconfig/-/get-tsconfig-4.8.1.tgz", + "integrity": "sha512-k9PN+cFBmaLWtVz29SkUoqU5O0slLuHJXt/2P+tMVFT+phsSGXGkp9t3rQIqdz0e+06EHNGs3oM6ZX1s2zHxRg==", + "dev": true, + "license": "MIT", + "dependencies": { + "resolve-pkg-maps": "^1.0.0" + }, + "funding": { + "url": "https://github.com/privatenumber/get-tsconfig?sponsor=1" + } + }, + "node_modules/glob": { + "version": "11.0.0", + "resolved": "https://registry.npmjs.org/glob/-/glob-11.0.0.tgz", + "integrity": "sha512-9UiX/Bl6J2yaBbxKoEBRm4Cipxgok8kQYcOPEhScPwebu2I0HoQOuYdIO6S3hLuWoZgpDpwQZMzTFxgpkyT76g==", + "dev": true, + "license": "ISC", + "dependencies": { + "foreground-child": "^3.1.0", + "jackspeak": "^4.0.1", + "minimatch": "^10.0.0", + "minipass": "^7.1.2", + "package-json-from-dist": "^1.0.0", + "path-scurry": "^2.0.0" + }, + "bin": { + "glob": "dist/esm/bin.mjs" + }, + "engines": { + "node": "20 || >=22" + }, + "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, + "license": "ISC", + "dependencies": { + "is-glob": "^4.0.3" + }, + "engines": { + "node": ">=10.13.0" + } + }, + "node_modules/glob/node_modules/brace-expansion": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", + "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", + "dev": true, + "license": "MIT", + "dependencies": { + "balanced-match": "^1.0.0" + } + }, + "node_modules/glob/node_modules/minimatch": { + "version": "10.0.1", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-10.0.1.tgz", + "integrity": "sha512-ethXTt3SGGR+95gudmqJ1eNhRO7eGEGIgYA9vnPatK4/etz2MEVDno5GMCibdMTuBMyElzIlgxMna3K94XDIDQ==", + "dev": true, + "license": "ISC", + "dependencies": { + "brace-expansion": "^2.0.1" + }, + "engines": { + "node": "20 || >=22" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/globals": { + "version": "14.0.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-14.0.0.tgz", + "integrity": "sha512-oahGvuMGQlPw/ivIYBjVSrWAfWLBeku5tpPE2fOPLi+WHffIWbuh2tCjhyQhTBPMf5E9jDEH4FOmTYgYwbKwtQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/globby": { + "version": "11.1.0", + "resolved": "https://registry.npmjs.org/globby/-/globby-11.1.0.tgz", + "integrity": "sha512-jhIXaOzy1sb8IyocaruWSn1TjmnBVs8Ayhcy83rmxNJ8q2uWKCAj3CnJY+KpGSXCueAPc0i05kVvVKtP1t9S3g==", + "dev": true, + "license": "MIT", + "dependencies": { + "array-union": "^2.1.0", + "dir-glob": "^3.0.1", + "fast-glob": "^3.2.9", + "ignore": "^5.2.0", + "merge2": "^1.4.1", + "slash": "^3.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/graphemer": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/graphemer/-/graphemer-1.4.0.tgz", + "integrity": "sha512-EtKwoO6kxCL9WO5xipiHTZlSzBm7WLT627TqC/uVRd0HKmq8NXyebnNYxDoBi7wt8eTWrUrKXCOVaFq9x1kgag==", + "dev": true, + "license": "MIT" + }, + "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, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/hast-util-to-html": { + "version": "9.0.3", + "resolved": "https://registry.npmjs.org/hast-util-to-html/-/hast-util-to-html-9.0.3.tgz", + "integrity": "sha512-M17uBDzMJ9RPCqLMO92gNNUDuBSq10a25SDBI08iCCxmorf4Yy6sYHK57n9WAbRAAaU+DuR4W6GN9K4DFZesYg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/hast": "^3.0.0", + "@types/unist": "^3.0.0", + "ccount": "^2.0.0", + "comma-separated-tokens": "^2.0.0", + "hast-util-whitespace": "^3.0.0", + "html-void-elements": "^3.0.0", + "mdast-util-to-hast": "^13.0.0", + "property-information": "^6.0.0", + "space-separated-tokens": "^2.0.0", + "stringify-entities": "^4.0.0", + "zwitch": "^2.0.4" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/hast-util-whitespace": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/hast-util-whitespace/-/hast-util-whitespace-3.0.0.tgz", + "integrity": "sha512-88JUN06ipLwsnv+dVn+OIYOvAuvBMy/Qoi6O7mQHxdPXpjy+Cd6xRkWwux7DKO+4sYILtLBRIKgsdpS2gQc7qw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/hast": "^3.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/html-void-elements": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/html-void-elements/-/html-void-elements-3.0.0.tgz", + "integrity": "sha512-bEqo66MRXsUGxWHV5IP0PUiAWwoEjba4VCzg0LjFJBpchPaTfyfCKTG6bc5F8ucKec3q5y6qOdGyYTSBEvhCrg==", + "dev": true, + "license": "MIT", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/ignore": { + "version": "5.3.2", + "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.3.2.tgz", + "integrity": "sha512-hsBTNUqQTDwkWtcdYI2i06Y/nUBEsNEDJKjWdigLvegy8kDuJAS8uRlpkkcQpyEXL0Z/pjDy5HBmMjRCJ2gq+g==", + "dev": true, + "license": "MIT", + "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, + "license": "MIT", + "dependencies": { + "parent-module": "^1.0.0", + "resolve-from": "^4.0.0" + }, + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/imurmurhash": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz", + "integrity": "sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.8.19" + } + }, + "node_modules/is-binary-path": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz", + "integrity": "sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==", + "dev": true, + "license": "MIT", + "dependencies": { + "binary-extensions": "^2.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "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, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "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, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "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, + "license": "MIT", + "dependencies": { + "is-extglob": "^2.1.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "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, + "license": "MIT", + "engines": { + "node": ">=0.12.0" + } + }, + "node_modules/isexe": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", + "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==", + "dev": true, + "license": "ISC" + }, + "node_modules/jackspeak": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/jackspeak/-/jackspeak-4.0.2.tgz", + "integrity": "sha512-bZsjR/iRjl1Nk1UkjGpAzLNfQtzuijhn2g+pbZb98HQ1Gk8vM9hfbxeMBP+M2/UUdwj0RqGG3mlvk2MsAqwvEw==", + "dev": true, + "license": "BlueOak-1.0.0", + "dependencies": { + "@isaacs/cliui": "^8.0.2" + }, + "engines": { + "node": "20 || >=22" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "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, + "license": "MIT", + "dependencies": { + "argparse": "^2.0.1" + }, + "bin": { + "js-yaml": "bin/js-yaml.js" + } + }, + "node_modules/json-buffer": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/json-buffer/-/json-buffer-3.0.1.tgz", + "integrity": "sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ==", + "dev": true, + "license": "MIT" + }, + "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, + "license": "MIT" + }, + "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, + "license": "MIT" + }, + "node_modules/keyv": { + "version": "4.5.4", + "resolved": "https://registry.npmjs.org/keyv/-/keyv-4.5.4.tgz", + "integrity": "sha512-oxVHkHR/EJf2CNXnWxRLW6mg7JyCCUcG0DtEGmL2ctUo1PNTin1PUil+r/+4r5MpVgC/fn1kjsx7mjSujKqIpw==", + "dev": true, + "license": "MIT", + "dependencies": { + "json-buffer": "3.0.1" + } + }, + "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, + "license": "MIT", + "dependencies": { + "prelude-ls": "^1.2.1", + "type-check": "~0.4.0" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/linkify-it": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/linkify-it/-/linkify-it-5.0.0.tgz", + "integrity": "sha512-5aHCbzQRADcdP+ATqnDuhhJ/MRIqDkZX5pyjFHRRysS8vZ5AbqGEoFIb6pYHPZ+L/OC2Lc+xT8uHVVR5CAK/wQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "uc.micro": "^2.0.0" + } + }, + "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, + "license": "MIT", + "dependencies": { + "p-locate": "^5.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "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, + "license": "MIT" + }, + "node_modules/lru-cache": { + "version": "11.0.1", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-11.0.1.tgz", + "integrity": "sha512-CgeuL5uom6j/ZVrg7G/+1IXqRY8JXX4Hghfy5YE0EhoYQWvndP1kufu58cmZLNIDKnRhZrXfdS9urVWx98AipQ==", + "dev": true, + "license": "ISC", + "engines": { + "node": "20 || >=22" + } + }, + "node_modules/lunr": { + "version": "2.3.9", + "resolved": "https://registry.npmjs.org/lunr/-/lunr-2.3.9.tgz", + "integrity": "sha512-zTU3DaZaF3Rt9rhN3uBMGQD3dD2/vFQqnvZCDv4dl5iOzq2IZQqTxu90r4E5J+nP70J3ilqVCrbho2eWaeW8Ow==", + "dev": true, + "license": "MIT" + }, + "node_modules/make-error": { + "version": "1.3.6", + "resolved": "https://registry.npmjs.org/make-error/-/make-error-1.3.6.tgz", + "integrity": "sha512-s8UhlNe7vPKomQhC1qFelMokr/Sc3AgNbso3n74mVPA5LTZwkB9NlXf4XPamLxJE8h0gh73rM94xvwRT2CVInw==", + "dev": true, + "license": "ISC" + }, + "node_modules/markdown-it": { + "version": "14.1.0", + "resolved": "https://registry.npmjs.org/markdown-it/-/markdown-it-14.1.0.tgz", + "integrity": "sha512-a54IwgWPaeBCAAsv13YgmALOF1elABB08FxO9i+r4VFk5Vl4pKokRPeX8u5TCgSsPi6ec1otfLjdOpVcgbpshg==", + "dev": true, + "license": "MIT", + "dependencies": { + "argparse": "^2.0.1", + "entities": "^4.4.0", + "linkify-it": "^5.0.0", + "mdurl": "^2.0.0", + "punycode.js": "^2.3.1", + "uc.micro": "^2.1.0" + }, + "bin": { + "markdown-it": "bin/markdown-it.mjs" + } + }, + "node_modules/mdast-util-to-hast": { + "version": "13.2.0", + "resolved": "https://registry.npmjs.org/mdast-util-to-hast/-/mdast-util-to-hast-13.2.0.tgz", + "integrity": "sha512-QGYKEuUsYT9ykKBCMOEDLsU5JRObWQusAolFMeko/tYPufNkRffBAQjIE+99jbA87xv6FgmjLtwjh9wBWajwAA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/hast": "^3.0.0", + "@types/mdast": "^4.0.0", + "@ungap/structured-clone": "^1.0.0", + "devlop": "^1.0.0", + "micromark-util-sanitize-uri": "^2.0.0", + "trim-lines": "^3.0.0", + "unist-util-position": "^5.0.0", + "unist-util-visit": "^5.0.0", + "vfile": "^6.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/mdurl": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/mdurl/-/mdurl-2.0.0.tgz", + "integrity": "sha512-Lf+9+2r+Tdp5wXDXC4PcIBjTDtq4UKjCPMQhKIuzpJNW0b96kVqSwW0bT7FhRSfmAiFYgP+SCRvdrDozfh0U5w==", + "dev": true, + "license": "MIT" + }, + "node_modules/merge2": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/merge2/-/merge2-1.4.1.tgz", + "integrity": "sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 8" + } + }, + "node_modules/micromark-util-character": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/micromark-util-character/-/micromark-util-character-2.1.0.tgz", + "integrity": "sha512-KvOVV+X1yLBfs9dCBSopq/+G1PcgT3lAK07mC4BzXi5E7ahzMAF8oIupDDJ6mievI6F+lAATkbQQlQixJfT3aQ==", + "dev": true, + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT", + "dependencies": { + "micromark-util-symbol": "^2.0.0", + "micromark-util-types": "^2.0.0" + } + }, + "node_modules/micromark-util-encode": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/micromark-util-encode/-/micromark-util-encode-2.0.0.tgz", + "integrity": "sha512-pS+ROfCXAGLWCOc8egcBvT0kf27GoWMqtdarNfDcjb6YLuV5cM3ioG45Ys2qOVqeqSbjaKg72vU+Wby3eddPsA==", + "dev": true, + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT" + }, + "node_modules/micromark-util-sanitize-uri": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/micromark-util-sanitize-uri/-/micromark-util-sanitize-uri-2.0.0.tgz", + "integrity": "sha512-WhYv5UEcZrbAtlsnPuChHUAsu/iBPOVaEVsntLBIdpibO0ddy8OzavZz3iL2xVvBZOpolujSliP65Kq0/7KIYw==", + "dev": true, + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT", + "dependencies": { + "micromark-util-character": "^2.0.0", + "micromark-util-encode": "^2.0.0", + "micromark-util-symbol": "^2.0.0" + } + }, + "node_modules/micromark-util-symbol": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/micromark-util-symbol/-/micromark-util-symbol-2.0.0.tgz", + "integrity": "sha512-8JZt9ElZ5kyTnO94muPxIGS8oyElRJaiJO8EzV6ZSyGQ1Is8xwl4Q45qU5UOg+bGH4AikWziz0iN4sFLWs8PGw==", + "dev": true, + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT" + }, + "node_modules/micromark-util-types": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/micromark-util-types/-/micromark-util-types-2.0.0.tgz", + "integrity": "sha512-oNh6S2WMHWRZrmutsRmDDfkzKtxF+bc2VxLC9dvtrDIRFln627VsFP6fLMgTryGDljgLPjkrzQSDcPrjPyDJ5w==", + "dev": true, + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT" + }, + "node_modules/micromatch": { + "version": "4.0.8", + "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.8.tgz", + "integrity": "sha512-PXwfBhYu0hBCPw8Dn0E+WDYb7af3dSLVWKi3HGv84IdF4TyFoC0ysxFd0Goxw7nSv4T/PzEJQxsYsEiFCKo2BA==", + "dev": true, + "license": "MIT", + "dependencies": { + "braces": "^3.0.3", + "picomatch": "^2.3.1" + }, + "engines": { + "node": ">=8.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, + "license": "ISC", + "dependencies": { + "brace-expansion": "^1.1.7" + }, + "engines": { + "node": "*" + } + }, + "node_modules/minipass": { + "version": "7.1.2", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-7.1.2.tgz", + "integrity": "sha512-qOOzS1cBTWYF4BH8fVePDBOO9iptMnGUEZwNc/cMWnTV2nVLZ7VoNWEPHkYczZA0pdoA7dl6e7FL659nX9S2aw==", + "dev": true, + "license": "ISC", + "engines": { + "node": ">=16 || 14 >=14.17" + } + }, + "node_modules/ms": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", + "dev": true, + "license": "MIT" + }, + "node_modules/mylas": { + "version": "2.1.13", + "resolved": "https://registry.npmjs.org/mylas/-/mylas-2.1.13.tgz", + "integrity": "sha512-+MrqnJRtxdF+xngFfUUkIMQrUUL0KsxbADUkn23Z/4ibGg192Q+z+CQyiYwvWTsYjJygmMR8+w3ZDa98Zh6ESg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12.0.0" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/raouldeheer" + } + }, + "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, + "license": "MIT" + }, + "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, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/oniguruma-to-js": { + "version": "0.4.3", + "resolved": "https://registry.npmjs.org/oniguruma-to-js/-/oniguruma-to-js-0.4.3.tgz", + "integrity": "sha512-X0jWUcAlxORhOqqBREgPMgnshB7ZGYszBNspP+tS9hPD3l13CdaXcHbgImoHUHlrvGx/7AvFEkTRhAGYh+jzjQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "regex": "^4.3.2" + }, + "funding": { + "url": "https://github.com/sponsors/antfu" + } + }, + "node_modules/optionator": { + "version": "0.9.4", + "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.9.4.tgz", + "integrity": "sha512-6IpQ7mKUxRcZNLIObR0hz7lxsapSSIYNZJwXPGeF0mTVqGKFIXj1DQcMoT22S3ROcLyY/rz0PWaWZ9ayWmad9g==", + "dev": true, + "license": "MIT", + "dependencies": { + "deep-is": "^0.1.3", + "fast-levenshtein": "^2.0.6", + "levn": "^0.4.1", + "prelude-ls": "^1.2.1", + "type-check": "^0.4.0", + "word-wrap": "^1.2.5" + }, + "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, + "license": "MIT", + "dependencies": { + "yocto-queue": "^0.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "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, + "license": "MIT", + "dependencies": { + "p-limit": "^3.0.2" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/package-json-from-dist": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/package-json-from-dist/-/package-json-from-dist-1.0.1.tgz", + "integrity": "sha512-UEZIS3/by4OC8vL3P2dTXRETpebLI2NiI5vIrjaD/5UtrkFX/tNbwjTSRAGC/+7CAo2pIcBaRgWmcBBHcsaCIw==", + "dev": true, + "license": "BlueOak-1.0.0" + }, + "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, + "license": "MIT", + "dependencies": { + "callsites": "^3.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "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, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "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, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/path-scurry": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/path-scurry/-/path-scurry-2.0.0.tgz", + "integrity": "sha512-ypGJsmGtdXUOeM5u93TyeIEfEhM6s+ljAhrk5vAvSx8uyY/02OvrZnA0YNGUrPXfpJMgI1ODd3nwz8Npx4O4cg==", + "dev": true, + "license": "BlueOak-1.0.0", + "dependencies": { + "lru-cache": "^11.0.0", + "minipass": "^7.1.2" + }, + "engines": { + "node": "20 || >=22" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/path-type": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/path-type/-/path-type-4.0.0.tgz", + "integrity": "sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/picomatch": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", + "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8.6" + }, + "funding": { + "url": "https://github.com/sponsors/jonschlinkert" + } + }, + "node_modules/plimit-lit": { + "version": "1.6.1", + "resolved": "https://registry.npmjs.org/plimit-lit/-/plimit-lit-1.6.1.tgz", + "integrity": "sha512-B7+VDyb8Tl6oMJT9oSO2CW8XC/T4UcJGrwOVoNGwOQsQYhlpfajmrMj5xeejqaASq3V/EqThyOeATEOMuSEXiA==", + "dev": true, + "license": "MIT", + "dependencies": { + "queue-lit": "^1.5.1" + }, + "engines": { + "node": ">=12" + } + }, + "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, + "license": "MIT", + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/property-information": { + "version": "6.5.0", + "resolved": "https://registry.npmjs.org/property-information/-/property-information-6.5.0.tgz", + "integrity": "sha512-PgTgs/BlvHxOu8QuEN7wi5A0OmXaBcHpmCSTehcs6Uuu9IkDIEo13Hy7n898RHfrQ49vKCoGeWZSaAK01nwVig==", + "dev": true, + "license": "MIT", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "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, + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/punycode.js": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/punycode.js/-/punycode.js-2.3.1.tgz", + "integrity": "sha512-uxFIHU0YlHYhDQtV4R9J6a52SLx28BCjT+4ieh7IGbgwVJWO+km431c4yRlREUAsAmt/uMjQUyQHNEPf0M39CA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/queue-lit": { + "version": "1.5.2", + "resolved": "https://registry.npmjs.org/queue-lit/-/queue-lit-1.5.2.tgz", + "integrity": "sha512-tLc36IOPeMAubu8BkW8YDBV+WyIgKlYU7zUNs0J5Vk9skSZ4JfGlPOqplP0aHdfv7HL0B2Pg6nwiq60Qc6M2Hw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12" + } + }, + "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" + } + ], + "license": "MIT" + }, + "node_modules/readdirp": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz", + "integrity": "sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==", + "dev": true, + "license": "MIT", + "dependencies": { + "picomatch": "^2.2.1" + }, + "engines": { + "node": ">=8.10.0" + } + }, + "node_modules/regex": { + "version": "4.3.3", + "resolved": "https://registry.npmjs.org/regex/-/regex-4.3.3.tgz", + "integrity": "sha512-r/AadFO7owAq1QJVeZ/nq9jNS1vyZt+6t1p/E59B56Rn2GCya+gr1KSyOzNL/er+r+B7phv5jG2xU2Nz1YkmJg==", + "dev": true, + "license": "MIT" + }, + "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, + "license": "MIT", + "engines": { + "node": ">=4" + } + }, + "node_modules/resolve-pkg-maps": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/resolve-pkg-maps/-/resolve-pkg-maps-1.0.0.tgz", + "integrity": "sha512-seS2Tj26TBVOC2NIc2rOe2y2ZO7efxITtLZcGSOnHHNOQ7CkiUBfw0Iw2ck6xkIhPwLhKNLS8BO+hEpngQlqzw==", + "dev": true, + "license": "MIT", + "funding": { + "url": "https://github.com/privatenumber/resolve-pkg-maps?sponsor=1" + } + }, + "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, + "license": "MIT", + "engines": { + "iojs": ">=1.0.0", + "node": ">=0.10.0" + } + }, + "node_modules/rimraf": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-6.0.1.tgz", + "integrity": "sha512-9dkvaxAsk/xNXSJzMgFqqMCuFgt2+KsOFek3TMLfo8NCPfWpBmqwyNn5Y+NX56QUYfCtsyhF3ayiboEoUmJk/A==", + "dev": true, + "license": "ISC", + "dependencies": { + "glob": "^11.0.0", + "package-json-from-dist": "^1.0.0" + }, + "bin": { + "rimraf": "dist/esm/bin.mjs" + }, + "engines": { + "node": "20 || >=22" + }, + "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" + } + ], + "license": "MIT", + "dependencies": { + "queue-microtask": "^1.2.2" + } + }, + "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, + "license": "ISC", + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "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, + "license": "MIT", + "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, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/shiki": { + "version": "1.22.0", + "resolved": "https://registry.npmjs.org/shiki/-/shiki-1.22.0.tgz", + "integrity": "sha512-/t5LlhNs+UOKQCYBtl5ZsH/Vclz73GIqT2yQsCBygr8L/ppTdmpL4w3kPLoZJbMKVWtoG77Ue1feOjZfDxvMkw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@shikijs/core": "1.22.0", + "@shikijs/engine-javascript": "1.22.0", + "@shikijs/engine-oniguruma": "1.22.0", + "@shikijs/types": "1.22.0", + "@shikijs/vscode-textmate": "^9.3.0", + "@types/hast": "^3.0.4" + } + }, + "node_modules/signal-exit": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-4.1.0.tgz", + "integrity": "sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==", + "dev": true, + "license": "ISC", + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/slash": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/slash/-/slash-3.0.0.tgz", + "integrity": "sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/space-separated-tokens": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/space-separated-tokens/-/space-separated-tokens-2.0.2.tgz", + "integrity": "sha512-PEGlAwrG8yXGXRjW32fGbg66JAlOAwbObuqVoJpv/mRgoWDQfgH1wDPvtzWyUSNAXBGSk8h755YDbbcEy3SH2Q==", + "dev": true, + "license": "MIT", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/string-width": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-5.1.2.tgz", + "integrity": "sha512-HnLOCR3vjcY8beoNLtcjZ5/nxn2afmME6lhrDrebokqMap+XbeW8n9TXpPDOqdGK5qcI3oT0GKTW6wC7EMiVqA==", + "dev": true, + "license": "MIT", + "dependencies": { + "eastasianwidth": "^0.2.0", + "emoji-regex": "^9.2.2", + "strip-ansi": "^7.0.1" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/string-width-cjs": { + "name": "string-width", + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "dev": true, + "license": "MIT", + "dependencies": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/string-width-cjs/node_modules/ansi-regex": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/string-width-cjs/node_modules/emoji-regex": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", + "dev": true, + "license": "MIT" + }, + "node_modules/string-width-cjs/node_modules/strip-ansi": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-regex": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/stringify-entities": { + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/stringify-entities/-/stringify-entities-4.0.4.tgz", + "integrity": "sha512-IwfBptatlO+QCJUo19AqvrPNqlVMpW9YEL2LIVY+Rpv2qsjCGxaDLNRgeGsQWJhfItebuJhsGSLjaBbNSQ+ieg==", + "dev": true, + "license": "MIT", + "dependencies": { + "character-entities-html4": "^2.0.0", + "character-entities-legacy": "^3.0.0" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/strip-ansi": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.1.0.tgz", + "integrity": "sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-regex": "^6.0.1" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/strip-ansi?sponsor=1" + } + }, + "node_modules/strip-ansi-cjs": { + "name": "strip-ansi", + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-regex": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/strip-ansi-cjs/node_modules/ansi-regex": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "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, + "license": "MIT", + "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, + "license": "MIT", + "dependencies": { + "has-flag": "^4.0.0" + }, + "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, + "license": "MIT" + }, + "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, + "license": "MIT", + "dependencies": { + "is-number": "^7.0.0" + }, + "engines": { + "node": ">=8.0" + } + }, + "node_modules/trim-lines": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/trim-lines/-/trim-lines-3.0.1.tgz", + "integrity": "sha512-kRj8B+YHZCc9kQYdWfJB2/oUl9rA99qbowYYBtr4ui4mZyAQ2JpvVBd/6U2YloATfqBhBTSMhTpgBHtU0Mf3Rg==", + "dev": true, + "license": "MIT", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/ts-api-utils": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/ts-api-utils/-/ts-api-utils-1.3.0.tgz", + "integrity": "sha512-UQMIo7pb8WRomKR1/+MFVLTroIvDVtMX3K6OUir8ynLyzB8Jeriont2bTAtmNPa1ekAgN7YPDyf6V+ygrdU+eQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=16" + }, + "peerDependencies": { + "typescript": ">=4.2.0" + } + }, + "node_modules/ts-node": { + "version": "10.9.2", + "resolved": "https://registry.npmjs.org/ts-node/-/ts-node-10.9.2.tgz", + "integrity": "sha512-f0FFpIdcHgn8zcPSbf1dRevwt047YMnaiJM3u2w2RewrB+fob/zePZcrOyQoLMMO7aBIddLcQIEK5dYjkLnGrQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@cspotcode/source-map-support": "^0.8.0", + "@tsconfig/node10": "^1.0.7", + "@tsconfig/node12": "^1.0.7", + "@tsconfig/node14": "^1.0.0", + "@tsconfig/node16": "^1.0.2", + "acorn": "^8.4.1", + "acorn-walk": "^8.1.1", + "arg": "^4.1.0", + "create-require": "^1.1.0", + "diff": "^4.0.1", + "make-error": "^1.1.1", + "v8-compile-cache-lib": "^3.0.1", + "yn": "3.1.1" + }, + "bin": { + "ts-node": "dist/bin.js", + "ts-node-cwd": "dist/bin-cwd.js", + "ts-node-esm": "dist/bin-esm.js", + "ts-node-script": "dist/bin-script.js", + "ts-node-transpile-only": "dist/bin-transpile.js", + "ts-script": "dist/bin-script-deprecated.js" + }, + "peerDependencies": { + "@swc/core": ">=1.2.50", + "@swc/wasm": ">=1.2.50", + "@types/node": "*", + "typescript": ">=2.7" + }, + "peerDependenciesMeta": { + "@swc/core": { + "optional": true + }, + "@swc/wasm": { + "optional": true + } + } + }, + "node_modules/tsc-alias": { + "version": "1.8.10", + "resolved": "https://registry.npmjs.org/tsc-alias/-/tsc-alias-1.8.10.tgz", + "integrity": "sha512-Ibv4KAWfFkFdKJxnWfVtdOmB0Zi1RJVxcbPGiCDsFpCQSsmpWyuzHG3rQyI5YkobWwxFPEyQfu1hdo4qLG2zPw==", + "dev": true, + "license": "MIT", + "dependencies": { + "chokidar": "^3.5.3", + "commander": "^9.0.0", + "globby": "^11.0.4", + "mylas": "^2.1.9", + "normalize-path": "^3.0.0", + "plimit-lit": "^1.2.6" + }, + "bin": { + "tsc-alias": "dist/bin/index.js" + } + }, + "node_modules/tsx": { + "version": "4.19.1", + "resolved": "https://registry.npmjs.org/tsx/-/tsx-4.19.1.tgz", + "integrity": "sha512-0flMz1lh74BR4wOvBjuh9olbnwqCPc35OOlfyzHba0Dc+QNUeWX/Gq2YTbnwcWPO3BMd8fkzRVrHcsR+a7z7rA==", + "dev": true, + "license": "MIT", + "dependencies": { + "esbuild": "~0.23.0", + "get-tsconfig": "^4.7.5" + }, + "bin": { + "tsx": "dist/cli.mjs" + }, + "engines": { + "node": ">=18.0.0" + }, + "optionalDependencies": { + "fsevents": "~2.3.3" + } + }, + "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, + "license": "MIT", + "dependencies": { + "prelude-ls": "^1.2.1" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/typedoc": { + "version": "0.26.10", + "resolved": "https://registry.npmjs.org/typedoc/-/typedoc-0.26.10.tgz", + "integrity": "sha512-xLmVKJ8S21t+JeuQLNueebEuTVphx6IrP06CdV7+0WVflUSW3SPmR+h1fnWVdAR/FQePEgsSWCUHXqKKjzuUAw==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "lunr": "^2.3.9", + "markdown-it": "^14.1.0", + "minimatch": "^9.0.5", + "shiki": "^1.16.2", + "yaml": "^2.5.1" + }, + "bin": { + "typedoc": "bin/typedoc" + }, + "engines": { + "node": ">= 18" + }, + "peerDependencies": { + "typescript": "4.6.x || 4.7.x || 4.8.x || 4.9.x || 5.0.x || 5.1.x || 5.2.x || 5.3.x || 5.4.x || 5.5.x || 5.6.x" + } + }, + "node_modules/typedoc/node_modules/brace-expansion": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", + "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", + "dev": true, + "license": "MIT", + "dependencies": { + "balanced-match": "^1.0.0" + } + }, + "node_modules/typedoc/node_modules/minimatch": { + "version": "9.0.5", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.5.tgz", + "integrity": "sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow==", + "dev": true, + "license": "ISC", + "dependencies": { + "brace-expansion": "^2.0.1" + }, + "engines": { + "node": ">=16 || 14 >=14.17" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/typescript": { + "version": "5.6.3", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.6.3.tgz", + "integrity": "sha512-hjcS1mhfuyi4WW8IWtjP7brDrG2cuDZukyrYrSauoXGNgx0S7zceP07adYkJycEr56BOUTNPzbInooiN3fn1qw==", + "dev": true, + "license": "Apache-2.0", + "bin": { + "tsc": "bin/tsc", + "tsserver": "bin/tsserver" + }, + "engines": { + "node": ">=14.17" + } + }, + "node_modules/typescript-eslint": { + "version": "8.11.0", + "resolved": "https://registry.npmjs.org/typescript-eslint/-/typescript-eslint-8.11.0.tgz", + "integrity": "sha512-cBRGnW3FSlxaYwU8KfAewxFK5uzeOAp0l2KebIlPDOT5olVi65KDG/yjBooPBG0kGW/HLkoz1c/iuBFehcS3IA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@typescript-eslint/eslint-plugin": "8.11.0", + "@typescript-eslint/parser": "8.11.0", + "@typescript-eslint/utils": "8.11.0" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, + "node_modules/uc.micro": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/uc.micro/-/uc.micro-2.1.0.tgz", + "integrity": "sha512-ARDJmphmdvUk6Glw7y9DQ2bFkKBHwQHLi2lsaH6PPmz/Ka9sFOBsBluozhDltWmnv9u/cF6Rt87znRTPV+yp/A==", + "dev": true, + "license": "MIT" + }, + "node_modules/undici-types": { + "version": "6.19.8", + "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-6.19.8.tgz", + "integrity": "sha512-ve2KP6f/JnbPBFyobGHuerC9g1FYGn/F8n1LWTwNxCEzd6IfqTwUQcNXgEtmmQ6DlRrC1hrSrBnCZPokRrDHjw==", + "dev": true, + "license": "MIT" + }, + "node_modules/unist-util-is": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/unist-util-is/-/unist-util-is-6.0.0.tgz", + "integrity": "sha512-2qCTHimwdxLfz+YzdGfkqNlH0tLi9xjTnHddPmJwtIG9MGsdbutfTc4P+haPD7l7Cjxf/WZj+we5qfVPvvxfYw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/unist": "^3.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/unist-util-position": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/unist-util-position/-/unist-util-position-5.0.0.tgz", + "integrity": "sha512-fucsC7HjXvkB5R3kTCO7kUjRdrS0BJt3M/FPxmHMBOm8JQi2BsHAHFsy27E0EolP8rp0NzXsJ+jNPyDWvOJZPA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/unist": "^3.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/unist-util-stringify-position": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/unist-util-stringify-position/-/unist-util-stringify-position-4.0.0.tgz", + "integrity": "sha512-0ASV06AAoKCDkS2+xw5RXJywruurpbC4JZSm7nr7MOt1ojAzvyyaO+UxZf18j8FCF6kmzCZKcAgN/yu2gm2XgQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/unist": "^3.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/unist-util-visit": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/unist-util-visit/-/unist-util-visit-5.0.0.tgz", + "integrity": "sha512-MR04uvD+07cwl/yhVuVWAtw+3GOR/knlL55Nd/wAdblk27GCVt3lqpTivy/tkJcZoNPzTwS1Y+KMojlLDhoTzg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/unist": "^3.0.0", + "unist-util-is": "^6.0.0", + "unist-util-visit-parents": "^6.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/unist-util-visit-parents": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/unist-util-visit-parents/-/unist-util-visit-parents-6.0.1.tgz", + "integrity": "sha512-L/PqWzfTP9lzzEa6CKs0k2nARxTdZduw3zyh8d2NVBnsyvHjSX4TWse388YrrQKbvI8w20fGjGlhgT96WwKykw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/unist": "^3.0.0", + "unist-util-is": "^6.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "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, + "license": "BSD-2-Clause", + "dependencies": { + "punycode": "^2.1.0" + } + }, + "node_modules/v8-compile-cache-lib": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/v8-compile-cache-lib/-/v8-compile-cache-lib-3.0.1.tgz", + "integrity": "sha512-wa7YjyUGfNZngI/vtK0UHAN+lgDCxBPCylVXGp0zu59Fz5aiGtNXaq3DhIov063MorB+VfufLh3JlF2KdTK3xg==", + "dev": true, + "license": "MIT" + }, + "node_modules/vfile": { + "version": "6.0.3", + "resolved": "https://registry.npmjs.org/vfile/-/vfile-6.0.3.tgz", + "integrity": "sha512-KzIbH/9tXat2u30jf+smMwFCsno4wHVdNmzFyL+T/L3UGqqk6JKfVqOFOZEpZSHADH1k40ab6NUIXZq422ov3Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/unist": "^3.0.0", + "vfile-message": "^4.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/vfile-message": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/vfile-message/-/vfile-message-4.0.2.tgz", + "integrity": "sha512-jRDZ1IMLttGj41KcZvlrYAaI3CfqpLpfpf+Mfig13viT6NKvRzWZ+lXz0Y5D60w6uJIBAOGq9mSHf0gktF0duw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/unist": "^3.0.0", + "unist-util-stringify-position": "^4.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "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, + "license": "ISC", + "dependencies": { + "isexe": "^2.0.0" + }, + "bin": { + "node-which": "bin/node-which" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/word-wrap": { + "version": "1.2.5", + "resolved": "https://registry.npmjs.org/word-wrap/-/word-wrap-1.2.5.tgz", + "integrity": "sha512-BN22B5eaMMI9UMtjrGd5g5eCYPpCPDUy0FJXbYsaT5zYxjFOckS53SQDE3pWkVoWpHXVb3BrYcEN4Twa55B5cA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/wrap-ansi": { + "version": "8.1.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-8.1.0.tgz", + "integrity": "sha512-si7QWI6zUMq56bESFvagtmzMdGOtoxfR+Sez11Mobfc7tm+VkUckk9bW2UeffTGVUbOksxmSw0AA2gs8g71NCQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-styles": "^6.1.0", + "string-width": "^5.0.1", + "strip-ansi": "^7.0.1" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/wrap-ansi?sponsor=1" + } + }, + "node_modules/wrap-ansi-cjs": { + "name": "wrap-ansi", + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", + "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-styles": "^4.0.0", + "string-width": "^4.1.0", + "strip-ansi": "^6.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/wrap-ansi?sponsor=1" + } + }, + "node_modules/wrap-ansi-cjs/node_modules/ansi-regex": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/wrap-ansi-cjs/node_modules/emoji-regex": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", + "dev": true, + "license": "MIT" + }, + "node_modules/wrap-ansi-cjs/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, + "license": "MIT", + "dependencies": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/wrap-ansi-cjs/node_modules/strip-ansi": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-regex": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/wrap-ansi/node_modules/ansi-styles": { + "version": "6.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-6.2.1.tgz", + "integrity": "sha512-bN798gFfQX+viw3R7yrGWRqnrN2oRkEkUjjl4JNn4E8GxxbjtG3FbrEIIY3l8/hrwUwIeCZvi4QuOTP4MErVug==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/yaml": { + "version": "2.6.0", + "resolved": "https://registry.npmjs.org/yaml/-/yaml-2.6.0.tgz", + "integrity": "sha512-a6ae//JvKDEra2kdi1qzCyrJW/WZCgFi8ydDV+eXExl95t+5R+ijnqHJbz9tmMh8FUjx3iv2fCQ4dclAQlO2UQ==", + "dev": true, + "license": "ISC", + "bin": { + "yaml": "bin.mjs" + }, + "engines": { + "node": ">= 14" + } + }, + "node_modules/yn": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/yn/-/yn-3.1.1.tgz", + "integrity": "sha512-Ux4ygGWsu2c7isFWe8Yu1YluJmqVhxqK2cLXNQA5AcC3QfbGNpM7fu0Y8b/z16pXLnFxZYvWhd3fhBY9DLmC6Q==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "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, + "license": "MIT", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/zwitch": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/zwitch/-/zwitch-2.0.4.tgz", + "integrity": "sha512-bXE4cR/kVZhKZX/RjPEflHaKVhUVl85noU3v6b8apfQEc1x4A+zBxjZ4lN8LqGd6WZ3dl98pY4o717VFmoPp+A==", + "dev": true, + "license": "MIT", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + } + } +} From 786f3a894eba6ac62c76f232c95488330366217c Mon Sep 17 00:00:00 2001 From: Austin Fraser Date: Mon, 21 Oct 2024 18:25:50 -0700 Subject: [PATCH 192/357] changed double quote to single --- mlflow-site/src/app/components/Demo.tsx | 2 +- mlflow-site/src/app/components/Features.tsx | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/mlflow-site/src/app/components/Demo.tsx b/mlflow-site/src/app/components/Demo.tsx index 0f273f81..83b4d0a2 100644 --- a/mlflow-site/src/app/components/Demo.tsx +++ b/mlflow-site/src/app/components/Demo.tsx @@ -22,7 +22,7 @@ const Demo = () => { ); } return ( -
{demos}
+
{demos}
); }; diff --git a/mlflow-site/src/app/components/Features.tsx b/mlflow-site/src/app/components/Features.tsx index 9a9c95ea..6ab94b09 100644 --- a/mlflow-site/src/app/components/Features.tsx +++ b/mlflow-site/src/app/components/Features.tsx @@ -29,7 +29,7 @@ const Features = () => { ); } return ( -
+
{featureHeader}
{featureLongBlurb}
{cards}
From 941ebfbde9cfdb2160e7099554be4892f2eba7e0 Mon Sep 17 00:00:00 2001 From: Kyler-Chiago Date: Mon, 21 Oct 2024 18:32:41 -0700 Subject: [PATCH 193/357] back to old --- mlflow-site/src/app/page.tsx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/mlflow-site/src/app/page.tsx b/mlflow-site/src/app/page.tsx index e6b7eb2a..ef501aa3 100644 --- a/mlflow-site/src/app/page.tsx +++ b/mlflow-site/src/app/page.tsx @@ -11,8 +11,8 @@ export default function Home() {
- - + +
From e6e2c7061d7ad91562114c00d2dd7abee52fe928 Mon Sep 17 00:00:00 2001 From: Kyler-Chiago Date: Mon, 21 Oct 2024 18:45:36 -0700 Subject: [PATCH 194/357] started fixing eslint errors in mlflow --- mlflow/src/workflows/ExperimentManager.ts | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/mlflow/src/workflows/ExperimentManager.ts b/mlflow/src/workflows/ExperimentManager.ts index 533956bb..3952b5a8 100644 --- a/mlflow/src/workflows/ExperimentManager.ts +++ b/mlflow/src/workflows/ExperimentManager.ts @@ -36,14 +36,14 @@ class ExperimentManager { tags?: Array<{ key: string; value: string }>, model?: { artifact_path: string; - flavors: Object; + flavors: object; model_url: string; model_uuid: string; utc_time_created: number; mlflow_version: string; run_id?: string; } - ): Promise { + ): Promise { try { // create run const run = await this.runClient.createRun(experiment_id, run_name); @@ -56,7 +56,7 @@ class ExperimentManager { // (model gets passed in as a JS object, not JSON - it gets JSON stringified here after adding a run_id property) if (model) { model.run_id = run_id; - let model_json = JSON.stringify(model); + const model_json = JSON.stringify(model); await this.runClient.logModel(run_id, model_json); } @@ -100,14 +100,14 @@ class ExperimentManager { tags?: Array<{ key: string; value: string }>, model?: { artifact_path: string; - flavors: Object; + flavors: object; model_url: string; model_uuid: string; utc_time_created: number; mlflow_version: string; run_id?: string; } - ): Promise { + ): Promise { try { const experiment_id = await this.experimentClient.createExperiment( experiment_name @@ -156,7 +156,7 @@ class ExperimentManager { experiment_id: string, primaryMetric: string, order?: 'ASC' | 'DESC' | 1 | -1 - ): Promise { + ): Promise> { try { interface RunInfo { run_id: string; From 4ba380ed0c3e318c51f1066265db63c1c0d11c72 Mon Sep 17 00:00:00 2001 From: Kyler-Chiago Date: Mon, 21 Oct 2024 19:15:43 -0700 Subject: [PATCH 195/357] some eslint errors fixed --- mlflow/package-lock.json | 790 ++++------------------- mlflow/src/tracking/ExperimentClient.ts | 12 +- mlflow/src/tracking/RunClient.ts | 12 +- mlflow/tests/ExperimentClientTestFile.ts | 2 +- 4 files changed, 156 insertions(+), 660 deletions(-) diff --git a/mlflow/package-lock.json b/mlflow/package-lock.json index a21f38fe..8d215a64 100644 --- a/mlflow/package-lock.json +++ b/mlflow/package-lock.json @@ -38,278 +38,6 @@ "node": ">=12" } }, - "node_modules/@esbuild/aix-ppc64": { - "version": "0.23.1", - "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.23.1.tgz", - "integrity": "sha512-6VhYk1diRqrhBAqpJEdjASR/+WVRtfjpqKuNw11cLiaWpAT/Uu+nokB+UJnevzy/P9C/ty6AOe0dwueMrGh/iQ==", - "cpu": [ - "ppc64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "aix" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/android-arm": { - "version": "0.23.1", - "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.23.1.tgz", - "integrity": "sha512-uz6/tEy2IFm9RYOyvKl88zdzZfwEfKZmnX9Cj1BHjeSGNuGLuMD1kR8y5bteYmwqKm1tj8m4cb/aKEorr6fHWQ==", - "cpu": [ - "arm" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "android" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/android-arm64": { - "version": "0.23.1", - "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.23.1.tgz", - "integrity": "sha512-xw50ipykXcLstLeWH7WRdQuysJqejuAGPd30vd1i5zSyKK3WE+ijzHmLKxdiCMtH1pHz78rOg0BKSYOSB/2Khw==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "android" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/android-x64": { - "version": "0.23.1", - "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.23.1.tgz", - "integrity": "sha512-nlN9B69St9BwUoB+jkyU090bru8L0NA3yFvAd7k8dNsVH8bi9a8cUAUSEcEEgTp2z3dbEDGJGfP6VUnkQnlReg==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "android" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/darwin-arm64": { - "version": "0.23.1", - "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.23.1.tgz", - "integrity": "sha512-YsS2e3Wtgnw7Wq53XXBLcV6JhRsEq8hkfg91ESVadIrzr9wO6jJDMZnCQbHm1Guc5t/CdDiFSSfWP58FNuvT3Q==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "darwin" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/darwin-x64": { - "version": "0.23.1", - "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.23.1.tgz", - "integrity": "sha512-aClqdgTDVPSEGgoCS8QDG37Gu8yc9lTHNAQlsztQ6ENetKEO//b8y31MMu2ZaPbn4kVsIABzVLXYLhCGekGDqw==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "darwin" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/freebsd-arm64": { - "version": "0.23.1", - "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.23.1.tgz", - "integrity": "sha512-h1k6yS8/pN/NHlMl5+v4XPfikhJulk4G+tKGFIOwURBSFzE8bixw1ebjluLOjfwtLqY0kewfjLSrO6tN2MgIhA==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "freebsd" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/freebsd-x64": { - "version": "0.23.1", - "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.23.1.tgz", - "integrity": "sha512-lK1eJeyk1ZX8UklqFd/3A60UuZ/6UVfGT2LuGo3Wp4/z7eRTRYY+0xOu2kpClP+vMTi9wKOfXi2vjUpO1Ro76g==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "freebsd" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/linux-arm": { - "version": "0.23.1", - "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.23.1.tgz", - "integrity": "sha512-CXXkzgn+dXAPs3WBwE+Kvnrf4WECwBdfjfeYHpMeVxWE0EceB6vhWGShs6wi0IYEqMSIzdOF1XjQ/Mkm5d7ZdQ==", - "cpu": [ - "arm" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/linux-arm64": { - "version": "0.23.1", - "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.23.1.tgz", - "integrity": "sha512-/93bf2yxencYDnItMYV/v116zff6UyTjo4EtEQjUBeGiVpMmffDNUyD9UN2zV+V3LRV3/on4xdZ26NKzn6754g==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/linux-ia32": { - "version": "0.23.1", - "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.23.1.tgz", - "integrity": "sha512-VTN4EuOHwXEkXzX5nTvVY4s7E/Krz7COC8xkftbbKRYAl96vPiUssGkeMELQMOnLOJ8k3BY1+ZY52tttZnHcXQ==", - "cpu": [ - "ia32" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/linux-loong64": { - "version": "0.23.1", - "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.23.1.tgz", - "integrity": "sha512-Vx09LzEoBa5zDnieH8LSMRToj7ir/Jeq0Gu6qJ/1GcBq9GkfoEAoXvLiW1U9J1qE/Y/Oyaq33w5p2ZWrNNHNEw==", - "cpu": [ - "loong64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/linux-mips64el": { - "version": "0.23.1", - "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.23.1.tgz", - "integrity": "sha512-nrFzzMQ7W4WRLNUOU5dlWAqa6yVeI0P78WKGUo7lg2HShq/yx+UYkeNSE0SSfSure0SqgnsxPvmAUu/vu0E+3Q==", - "cpu": [ - "mips64el" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/linux-ppc64": { - "version": "0.23.1", - "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.23.1.tgz", - "integrity": "sha512-dKN8fgVqd0vUIjxuJI6P/9SSSe/mB9rvA98CSH2sJnlZ/OCZWO1DJvxj8jvKTfYUdGfcq2dDxoKaC6bHuTlgcw==", - "cpu": [ - "ppc64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/linux-riscv64": { - "version": "0.23.1", - "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.23.1.tgz", - "integrity": "sha512-5AV4Pzp80fhHL83JM6LoA6pTQVWgB1HovMBsLQ9OZWLDqVY8MVobBXNSmAJi//Csh6tcY7e7Lny2Hg1tElMjIA==", - "cpu": [ - "riscv64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/linux-s390x": { - "version": "0.23.1", - "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.23.1.tgz", - "integrity": "sha512-9ygs73tuFCe6f6m/Tb+9LtYxWR4c9yg7zjt2cYkjDbDpV/xVn+68cQxMXCjUpYwEkze2RcU/rMnfIXNRFmSoDw==", - "cpu": [ - "s390x" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=18" - } - }, "node_modules/@esbuild/linux-x64": { "version": "0.23.1", "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.23.1.tgz", @@ -327,125 +55,6 @@ "node": ">=18" } }, - "node_modules/@esbuild/netbsd-x64": { - "version": "0.23.1", - "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.23.1.tgz", - "integrity": "sha512-aevEkCNu7KlPRpYLjwmdcuNz6bDFiE7Z8XC4CPqExjTvrHugh28QzUXVOZtiYghciKUacNktqxdpymplil1beA==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "netbsd" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/openbsd-arm64": { - "version": "0.23.1", - "resolved": "https://registry.npmjs.org/@esbuild/openbsd-arm64/-/openbsd-arm64-0.23.1.tgz", - "integrity": "sha512-3x37szhLexNA4bXhLrCC/LImN/YtWis6WXr1VESlfVtVeoFJBRINPJ3f0a/6LV8zpikqoUg4hyXw0sFBt5Cr+Q==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "openbsd" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/openbsd-x64": { - "version": "0.23.1", - "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.23.1.tgz", - "integrity": "sha512-aY2gMmKmPhxfU+0EdnN+XNtGbjfQgwZj43k8G3fyrDM/UdZww6xrWxmDkuz2eCZchqVeABjV5BpildOrUbBTqA==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "openbsd" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/sunos-x64": { - "version": "0.23.1", - "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.23.1.tgz", - "integrity": "sha512-RBRT2gqEl0IKQABT4XTj78tpk9v7ehp+mazn2HbUeZl1YMdaGAQqhapjGTCe7uw7y0frDi4gS0uHzhvpFuI1sA==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "sunos" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/win32-arm64": { - "version": "0.23.1", - "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.23.1.tgz", - "integrity": "sha512-4O+gPR5rEBe2FpKOVyiJ7wNDPA8nGzDuJ6gN4okSA1gEOYZ67N8JPk58tkWtdtPeLz7lBnY6I5L3jdsr3S+A6A==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "win32" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/win32-ia32": { - "version": "0.23.1", - "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.23.1.tgz", - "integrity": "sha512-BcaL0Vn6QwCwre3Y717nVHZbAa4UBEigzFm6VdsVdT/MbZ38xoj1X9HPkZhbmaBGUD1W8vxAfffbDe8bA6AKnQ==", - "cpu": [ - "ia32" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "win32" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/win32-x64": { - "version": "0.23.1", - "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.23.1.tgz", - "integrity": "sha512-BHpFFeslkWrXWyUPnbKm+xYYVYruCinGcftSBaa8zoF9hZO4BcSCFUvHVTtzpIY6YzUnYtuEhZ+C9iEXjxnasg==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "win32" - ], - "engines": { - "node": ">=18" - } - }, "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", @@ -718,10 +327,7 @@ "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz", "integrity": "sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==", "dev": true, -<<<<<<< HEAD -======= "license": "MIT", ->>>>>>> dev "dependencies": { "@nodelib/fs.stat": "2.0.5", "run-parallel": "^1.1.9" @@ -735,10 +341,7 @@ "resolved": "https://registry.npmjs.org/@nodelib/fs.stat/-/fs.stat-2.0.5.tgz", "integrity": "sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==", "dev": true, -<<<<<<< HEAD -======= "license": "MIT", ->>>>>>> dev "engines": { "node": ">= 8" } @@ -748,10 +351,7 @@ "resolved": "https://registry.npmjs.org/@nodelib/fs.walk/-/fs.walk-1.2.8.tgz", "integrity": "sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==", "dev": true, -<<<<<<< HEAD -======= "license": "MIT", ->>>>>>> dev "dependencies": { "@nodelib/fs.scandir": "2.1.5", "fastq": "^1.6.0" @@ -760,8 +360,6 @@ "node": ">= 8" } }, -<<<<<<< HEAD -======= "node_modules/@shikijs/core": { "version": "1.22.0", "resolved": "https://registry.npmjs.org/@shikijs/core/-/core-1.22.0.tgz", @@ -818,7 +416,6 @@ "dev": true, "license": "MIT" }, ->>>>>>> dev "node_modules/@tsconfig/node10": { "version": "1.0.11", "resolved": "https://registry.npmjs.org/@tsconfig/node10/-/node10-1.0.11.tgz", @@ -1229,6 +826,7 @@ "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.3.tgz", "integrity": "sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw==", "dev": true, + "license": "ISC", "dependencies": { "normalize-path": "^3.0.0", "picomatch": "^2.0.4" @@ -1237,18 +835,6 @@ "node": ">= 8" } }, - "node_modules/anymatch/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/arg": { "version": "4.1.3", "resolved": "https://registry.npmjs.org/arg/-/arg-4.1.3.tgz", @@ -1256,23 +842,22 @@ "dev": true, "license": "MIT" }, -<<<<<<< HEAD - "node_modules/array-union": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/array-union/-/array-union-2.1.0.tgz", - "integrity": "sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw==", - "dev": true, - "engines": { - "node": ">=8" - } -======= "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, - "license": "Python-2.0" ->>>>>>> dev + "license": "Python-2.0" + }, + "node_modules/array-union": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/array-union/-/array-union-2.1.0.tgz", + "integrity": "sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } }, "node_modules/balanced-match": { "version": "1.0.2", @@ -1286,6 +871,7 @@ "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.3.0.tgz", "integrity": "sha512-Ceh+7ox5qe7LJuLHoY0feh3pHuUDHAcRUeyL2VYghZwfpkNIy/+8Ocg0a3UuSoYzavmylwuLWQOf3hl0jjMMIw==", "dev": true, + "license": "MIT", "engines": { "node": ">=8" }, @@ -1308,10 +894,7 @@ "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.3.tgz", "integrity": "sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==", "dev": true, -<<<<<<< HEAD -======= "license": "MIT", ->>>>>>> dev "dependencies": { "fill-range": "^7.1.1" }, @@ -1319,30 +902,6 @@ "node": ">=8" } }, -<<<<<<< HEAD - "node_modules/chokidar": { - "version": "3.6.0", - "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.6.0.tgz", - "integrity": "sha512-7VT13fmjotKpGipCW9JEQAusEPE+Ei8nl6/g4FBAmIm0GOOLMua9NDDo/DWp0ZAxCr3cPq5ZpBqmPAQgDda2Pw==", - "dev": true, - "dependencies": { - "anymatch": "~3.1.2", - "braces": "~3.0.2", - "glob-parent": "~5.1.2", - "is-binary-path": "~2.1.0", - "is-glob": "~4.0.1", - "normalize-path": "~3.0.0", - "readdirp": "~3.6.0" - }, - "engines": { - "node": ">= 8.10.0" - }, - "funding": { - "url": "https://paulmillr.com/funding/" - }, - "optionalDependencies": { - "fsevents": "~2.3.2" -======= "node_modules/callsites": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz", @@ -1417,7 +976,44 @@ "funding": { "type": "github", "url": "https://github.com/sponsors/wooorm" ->>>>>>> dev + } + }, + "node_modules/chokidar": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.6.0.tgz", + "integrity": "sha512-7VT13fmjotKpGipCW9JEQAusEPE+Ei8nl6/g4FBAmIm0GOOLMua9NDDo/DWp0ZAxCr3cPq5ZpBqmPAQgDda2Pw==", + "dev": true, + "license": "MIT", + "dependencies": { + "anymatch": "~3.1.2", + "braces": "~3.0.2", + "glob-parent": "~5.1.2", + "is-binary-path": "~2.1.0", + "is-glob": "~4.0.1", + "normalize-path": "~3.0.0", + "readdirp": "~3.6.0" + }, + "engines": { + "node": ">= 8.10.0" + }, + "funding": { + "url": "https://paulmillr.com/funding/" + }, + "optionalDependencies": { + "fsevents": "~2.3.2" + } + }, + "node_modules/chokidar/node_modules/glob-parent": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", + "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", + "dev": true, + "license": "ISC", + "dependencies": { + "is-glob": "^4.0.1" + }, + "engines": { + "node": ">= 6" } }, "node_modules/color-convert": { @@ -1440,17 +1036,6 @@ "dev": true, "license": "MIT" }, -<<<<<<< HEAD - "node_modules/commander": { - "version": "9.5.0", - "resolved": "https://registry.npmjs.org/commander/-/commander-9.5.0.tgz", - "integrity": "sha512-KRs7WVDKg86PWiuAqhDrAQnTXZKraVcCc6vFdL14qrZ/DcWwuRo7VoiYXalXO7S5GKpqYiVEwCbgFDfxNHKJBQ==", - "dev": true, - "engines": { - "node": "^12.20.0 || >=14" - } - }, -======= "node_modules/comma-separated-tokens": { "version": "2.0.3", "resolved": "https://registry.npmjs.org/comma-separated-tokens/-/comma-separated-tokens-2.0.3.tgz", @@ -1462,6 +1047,16 @@ "url": "https://github.com/sponsors/wooorm" } }, + "node_modules/commander": { + "version": "9.5.0", + "resolved": "https://registry.npmjs.org/commander/-/commander-9.5.0.tgz", + "integrity": "sha512-KRs7WVDKg86PWiuAqhDrAQnTXZKraVcCc6vFdL14qrZ/DcWwuRo7VoiYXalXO7S5GKpqYiVEwCbgFDfxNHKJBQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": "^12.20.0 || >=14" + } + }, "node_modules/concat-map": { "version": "0.0.1", "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", @@ -1469,7 +1064,6 @@ "dev": true, "license": "MIT" }, ->>>>>>> dev "node_modules/create-require": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/create-require/-/create-require-1.1.1.tgz", @@ -1556,6 +1150,7 @@ "resolved": "https://registry.npmjs.org/dir-glob/-/dir-glob-3.0.1.tgz", "integrity": "sha512-WkrWp9GR4KXfKGYzOLmTuGVi1UWFfws377n9cc55/tb6DuqyF6pcQ5AbiHEshaDpY9v6oaSr2XCDidGmMwdzIA==", "dev": true, + "license": "MIT", "dependencies": { "path-type": "^4.0.0" }, @@ -1630,8 +1225,6 @@ "@esbuild/win32-x64": "0.23.1" } }, -<<<<<<< HEAD -======= "node_modules/escape-string-regexp": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz", @@ -1831,16 +1424,12 @@ "dev": true, "license": "MIT" }, ->>>>>>> dev "node_modules/fast-glob": { "version": "3.3.2", "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.3.2.tgz", "integrity": "sha512-oX2ruAFQwf/Orj8m737Y5adxDQO0LAB7/S5MnxCdTNDd4p6BsyIVsv9JQsATbTSq8KHRpLwIHbVlUNatxd+1Ow==", "dev": true, -<<<<<<< HEAD -======= "license": "MIT", ->>>>>>> dev "dependencies": { "@nodelib/fs.stat": "^2.0.2", "@nodelib/fs.walk": "^1.2.3", @@ -1852,8 +1441,6 @@ "node": ">=8.6.0" } }, -<<<<<<< HEAD -======= "node_modules/fast-glob/node_modules/glob-parent": { "version": "5.1.2", "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", @@ -1881,22 +1468,16 @@ "dev": true, "license": "MIT" }, ->>>>>>> dev "node_modules/fastq": { "version": "1.17.1", "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.17.1.tgz", "integrity": "sha512-sRVD3lWVIXWg6By68ZN7vho9a1pQcN/WBFaAAsDDFzlJjvoGx0P8z7V1t72grFJfJhu3YPZBuu25f7Kaw2jN1w==", "dev": true, -<<<<<<< HEAD -======= "license": "ISC", ->>>>>>> dev "dependencies": { "reusify": "^1.0.4" } }, -<<<<<<< HEAD -======= "node_modules/file-entry-cache": { "version": "8.0.0", "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-8.0.0.tgz", @@ -1910,16 +1491,12 @@ "node": ">=16.0.0" } }, ->>>>>>> dev "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, -<<<<<<< HEAD -======= "license": "MIT", ->>>>>>> dev "dependencies": { "to-regex-range": "^5.0.1" }, @@ -1927,8 +1504,6 @@ "node": ">=8" } }, -<<<<<<< HEAD -======= "node_modules/find-up": { "version": "5.0.0", "resolved": "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz", @@ -1967,7 +1542,6 @@ "dev": true, "license": "ISC" }, ->>>>>>> dev "node_modules/foreground-child": { "version": "3.3.0", "resolved": "https://registry.npmjs.org/foreground-child/-/foreground-child-3.3.0.tgz", @@ -2038,16 +1612,29 @@ } }, "node_modules/glob-parent": { -<<<<<<< HEAD - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", - "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", + "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, + "license": "ISC", "dependencies": { - "is-glob": "^4.0.1" + "is-glob": "^4.0.3" }, "engines": { - "node": ">= 6" + "node": ">=10.13.0" + } + }, + "node_modules/globals": { + "version": "14.0.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-14.0.0.tgz", + "integrity": "sha512-oahGvuMGQlPw/ivIYBjVSrWAfWLBeku5tpPE2fOPLi+WHffIWbuh2tCjhyQhTBPMf5E9jDEH4FOmTYgYwbKwtQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, "node_modules/globby": { @@ -2055,6 +1642,7 @@ "resolved": "https://registry.npmjs.org/globby/-/globby-11.1.0.tgz", "integrity": "sha512-jhIXaOzy1sb8IyocaruWSn1TjmnBVs8Ayhcy83rmxNJ8q2uWKCAj3CnJY+KpGSXCueAPc0i05kVvVKtP1t9S3g==", "dev": true, + "license": "MIT", "dependencies": { "array-union": "^2.1.0", "dir-glob": "^3.0.1", @@ -2065,35 +1653,11 @@ }, "engines": { "node": ">=10" -======= - "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, - "license": "ISC", - "dependencies": { - "is-glob": "^4.0.3" - }, - "engines": { - "node": ">=10.13.0" - } - }, - "node_modules/globals": { - "version": "14.0.0", - "resolved": "https://registry.npmjs.org/globals/-/globals-14.0.0.tgz", - "integrity": "sha512-oahGvuMGQlPw/ivIYBjVSrWAfWLBeku5tpPE2fOPLi+WHffIWbuh2tCjhyQhTBPMf5E9jDEH4FOmTYgYwbKwtQ==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=18" ->>>>>>> dev }, "funding": { "url": "https://github.com/sponsors/sindresorhus" } }, -<<<<<<< HEAD -======= "node_modules/graphemer": { "version": "1.4.0", "resolved": "https://registry.npmjs.org/graphemer/-/graphemer-1.4.0.tgz", @@ -2160,32 +1724,16 @@ "url": "https://github.com/sponsors/wooorm" } }, ->>>>>>> dev "node_modules/ignore": { "version": "5.3.2", "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.3.2.tgz", "integrity": "sha512-hsBTNUqQTDwkWtcdYI2i06Y/nUBEsNEDJKjWdigLvegy8kDuJAS8uRlpkkcQpyEXL0Z/pjDy5HBmMjRCJ2gq+g==", "dev": true, -<<<<<<< HEAD -======= "license": "MIT", ->>>>>>> dev "engines": { "node": ">= 4" } }, -<<<<<<< HEAD - "node_modules/is-binary-path": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz", - "integrity": "sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==", - "dev": true, - "dependencies": { - "binary-extensions": "^2.0.0" - }, - "engines": { - "node": ">=8" -======= "node_modules/import-fresh": { "version": "3.3.0", "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.0.tgz", @@ -2211,7 +1759,19 @@ "license": "MIT", "engines": { "node": ">=0.8.19" ->>>>>>> dev + } + }, + "node_modules/is-binary-path": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz", + "integrity": "sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==", + "dev": true, + "license": "MIT", + "dependencies": { + "binary-extensions": "^2.0.0" + }, + "engines": { + "node": ">=8" } }, "node_modules/is-extglob": { @@ -2219,10 +1779,7 @@ "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", "integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==", "dev": true, -<<<<<<< HEAD -======= "license": "MIT", ->>>>>>> dev "engines": { "node": ">=0.10.0" } @@ -2242,10 +1799,7 @@ "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz", "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==", "dev": true, -<<<<<<< HEAD -======= "license": "MIT", ->>>>>>> dev "dependencies": { "is-extglob": "^2.1.1" }, @@ -2258,10 +1812,7 @@ "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", "dev": true, -<<<<<<< HEAD -======= "license": "MIT", ->>>>>>> dev "engines": { "node": ">=0.12.0" } @@ -2404,8 +1955,6 @@ "dev": true, "license": "ISC" }, -<<<<<<< HEAD -======= "node_modules/markdown-it": { "version": "14.1.0", "resolved": "https://registry.npmjs.org/markdown-it/-/markdown-it-14.1.0.tgz", @@ -2453,22 +2002,16 @@ "dev": true, "license": "MIT" }, ->>>>>>> dev "node_modules/merge2": { "version": "1.4.1", "resolved": "https://registry.npmjs.org/merge2/-/merge2-1.4.1.tgz", "integrity": "sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==", "dev": true, -<<<<<<< HEAD -======= "license": "MIT", ->>>>>>> dev "engines": { "node": ">= 8" } }, -<<<<<<< HEAD -======= "node_modules/micromark-util-character": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/micromark-util-character/-/micromark-util-character-2.1.0.tgz", @@ -2563,16 +2106,12 @@ ], "license": "MIT" }, ->>>>>>> dev "node_modules/micromatch": { "version": "4.0.8", "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.8.tgz", "integrity": "sha512-PXwfBhYu0hBCPw8Dn0E+WDYb7af3dSLVWKi3HGv84IdF4TyFoC0ysxFd0Goxw7nSv4T/PzEJQxsYsEiFCKo2BA==", "dev": true, -<<<<<<< HEAD -======= "license": "MIT", ->>>>>>> dev "dependencies": { "braces": "^3.0.3", "picomatch": "^2.3.1" @@ -2581,21 +2120,6 @@ "node": ">=8.6" } }, -<<<<<<< HEAD - "node_modules/micromatch/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" - } - }, -======= ->>>>>>> dev "node_modules/minimatch": { "version": "10.0.1", "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-10.0.1.tgz", @@ -2622,12 +2146,19 @@ "node": ">=16 || 14 >=14.17" } }, -<<<<<<< HEAD + "node_modules/ms": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", + "dev": true, + "license": "MIT" + }, "node_modules/mylas": { "version": "2.1.13", "resolved": "https://registry.npmjs.org/mylas/-/mylas-2.1.13.tgz", "integrity": "sha512-+MrqnJRtxdF+xngFfUUkIMQrUUL0KsxbADUkn23Z/4ibGg192Q+z+CQyiYwvWTsYjJygmMR8+w3ZDa98Zh6ESg==", "dev": true, + "license": "MIT", "engines": { "node": ">=12.0.0" }, @@ -2636,27 +2167,22 @@ "url": "https://github.com/sponsors/raouldeheer" } }, + "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, + "license": "MIT" + }, "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, + "license": "MIT", "engines": { "node": ">=0.10.0" -======= - "node_modules/ms": { - "version": "2.1.3", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", - "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", - "dev": true, - "license": "MIT" - }, - "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, - "license": "MIT" + } }, "node_modules/oniguruma-to-js": { "version": "0.4.3", @@ -2719,7 +2245,6 @@ }, "funding": { "url": "https://github.com/sponsors/sindresorhus" ->>>>>>> dev } }, "node_modules/package-json-from-dist": { @@ -2779,36 +2304,16 @@ "url": "https://github.com/sponsors/isaacs" } }, -<<<<<<< HEAD "node_modules/path-type": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/path-type/-/path-type-4.0.0.tgz", "integrity": "sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==", "dev": true, + "license": "MIT", "engines": { "node": ">=8" } }, - "node_modules/plimit-lit": { - "version": "1.6.1", - "resolved": "https://registry.npmjs.org/plimit-lit/-/plimit-lit-1.6.1.tgz", - "integrity": "sha512-B7+VDyb8Tl6oMJT9oSO2CW8XC/T4UcJGrwOVoNGwOQsQYhlpfajmrMj5xeejqaASq3V/EqThyOeATEOMuSEXiA==", - "dev": true, - "dependencies": { - "queue-lit": "^1.5.1" - }, - "engines": { - "node": ">=12" - } - }, - "node_modules/queue-lit": { - "version": "1.5.2", - "resolved": "https://registry.npmjs.org/queue-lit/-/queue-lit-1.5.2.tgz", - "integrity": "sha512-tLc36IOPeMAubu8BkW8YDBV+WyIgKlYU7zUNs0J5Vk9skSZ4JfGlPOqplP0aHdfv7HL0B2Pg6nwiq60Qc6M2Hw==", - "dev": true, - "engines": { - "node": ">=12" -======= "node_modules/picomatch": { "version": "2.3.1", "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", @@ -2822,6 +2327,19 @@ "url": "https://github.com/sponsors/jonschlinkert" } }, + "node_modules/plimit-lit": { + "version": "1.6.1", + "resolved": "https://registry.npmjs.org/plimit-lit/-/plimit-lit-1.6.1.tgz", + "integrity": "sha512-B7+VDyb8Tl6oMJT9oSO2CW8XC/T4UcJGrwOVoNGwOQsQYhlpfajmrMj5xeejqaASq3V/EqThyOeATEOMuSEXiA==", + "dev": true, + "license": "MIT", + "dependencies": { + "queue-lit": "^1.5.1" + }, + "engines": { + "node": ">=12" + } + }, "node_modules/prelude-ls": { "version": "1.2.1", "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.2.1.tgz", @@ -2861,7 +2379,16 @@ "license": "MIT", "engines": { "node": ">=6" ->>>>>>> dev + } + }, + "node_modules/queue-lit": { + "version": "1.5.2", + "resolved": "https://registry.npmjs.org/queue-lit/-/queue-lit-1.5.2.tgz", + "integrity": "sha512-tLc36IOPeMAubu8BkW8YDBV+WyIgKlYU7zUNs0J5Vk9skSZ4JfGlPOqplP0aHdfv7HL0B2Pg6nwiq60Qc6M2Hw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12" } }, "node_modules/queue-microtask": { @@ -2882,14 +2409,15 @@ "type": "consulting", "url": "https://feross.org/support" } -<<<<<<< HEAD - ] + ], + "license": "MIT" }, "node_modules/readdirp": { "version": "3.6.0", "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz", "integrity": "sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==", "dev": true, + "license": "MIT", "dependencies": { "picomatch": "^2.2.1" }, @@ -2897,20 +2425,6 @@ "node": ">=8.10.0" } }, - "node_modules/readdirp/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" -======= - ], - "license": "MIT" - }, "node_modules/regex": { "version": "4.3.3", "resolved": "https://registry.npmjs.org/regex/-/regex-4.3.3.tgz", @@ -2926,7 +2440,6 @@ "license": "MIT", "engines": { "node": ">=4" ->>>>>>> dev } }, "node_modules/resolve-pkg-maps": { @@ -2944,10 +2457,7 @@ "resolved": "https://registry.npmjs.org/reusify/-/reusify-1.0.4.tgz", "integrity": "sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw==", "dev": true, -<<<<<<< HEAD -======= "license": "MIT", ->>>>>>> dev "engines": { "iojs": ">=1.0.0", "node": ">=0.10.0" @@ -2992,16 +2502,11 @@ "url": "https://feross.org/support" } ], -<<<<<<< HEAD -======= "license": "MIT", ->>>>>>> dev "dependencies": { "queue-microtask": "^1.2.2" } }, -<<<<<<< HEAD -======= "node_modules/semver": { "version": "7.6.3", "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.3.tgz", @@ -3015,7 +2520,6 @@ "node": ">=10" } }, ->>>>>>> dev "node_modules/shebang-command": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", @@ -3067,15 +2571,16 @@ "url": "https://github.com/sponsors/isaacs" } }, -<<<<<<< HEAD "node_modules/slash": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/slash/-/slash-3.0.0.tgz", "integrity": "sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==", "dev": true, + "license": "MIT", "engines": { "node": ">=8" -======= + } + }, "node_modules/space-separated-tokens": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/space-separated-tokens/-/space-separated-tokens-2.0.2.tgz", @@ -3085,7 +2590,6 @@ "funding": { "type": "github", "url": "https://github.com/sponsors/wooorm" ->>>>>>> dev } }, "node_modules/string-width": { @@ -3207,8 +2711,6 @@ "node": ">=8" } }, -<<<<<<< HEAD -======= "node_modules/strip-json-comments": { "version": "3.1.1", "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz", @@ -3242,16 +2744,12 @@ "dev": true, "license": "MIT" }, ->>>>>>> dev "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, -<<<<<<< HEAD -======= "license": "MIT", ->>>>>>> dev "dependencies": { "is-number": "^7.0.0" }, @@ -3259,8 +2757,6 @@ "node": ">=8.0" } }, -<<<<<<< HEAD -======= "node_modules/trim-lines": { "version": "3.0.1", "resolved": "https://registry.npmjs.org/trim-lines/-/trim-lines-3.0.1.tgz", @@ -3285,7 +2781,6 @@ "typescript": ">=4.2.0" } }, ->>>>>>> dev "node_modules/ts-node": { "version": "10.9.2", "resolved": "https://registry.npmjs.org/ts-node/-/ts-node-10.9.2.tgz", @@ -3425,6 +2920,7 @@ "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.6.2.tgz", "integrity": "sha512-NW8ByodCSNCwZeghjN3o+JX5OFH0Ojg6sadjEKY4huZ52TqbJTJnDo5+Tw98lSy63NZvi4n+ez5m2u5d4PkZyw==", "dev": true, + "license": "Apache-2.0", "bin": { "tsc": "bin/tsc", "tsserver": "bin/tsserver" diff --git a/mlflow/src/tracking/ExperimentClient.ts b/mlflow/src/tracking/ExperimentClient.ts index 080e68da..876d2a2c 100644 --- a/mlflow/src/tracking/ExperimentClient.ts +++ b/mlflow/src/tracking/ExperimentClient.ts @@ -14,14 +14,14 @@ class ExperimentClient { * @param {string} name Experiment name. (required) * @param {string} artifact_location Optional location where all artifacts for the experiment are stored. If not provided, the remote server will select an appropriate default. * @param {Array<{key: string, value: string}>} tags Optional collection of tags to set on the experiment. - * @returns {Promise} Returns the ID of the newly created experiment in an object. + * @returns {Promise} Returns the ID of the newly created experiment in an object. * @throws {ApiError} If the API request fails */ async createExperiment( name: string, artifact_location?: string, tags?: Array<{key: string, value: string}> - ): Promise { + ): Promise { const { response, data } = await apiRequest( this.trackingUri, @@ -62,7 +62,7 @@ class ExperimentClient { page_token?: string, order_by?: string[], view_type?: string - ): Promise { + ): Promise { const { response, data } = await apiRequest( this.trackingUri, @@ -94,7 +94,7 @@ class ExperimentClient { */ async getExperiment( experiment_id: string - ): Promise { + ): Promise { const { response, data } = await apiRequest( this.trackingUri, @@ -129,7 +129,7 @@ class ExperimentClient { */ async getExperimentByName( experiment_name: string - ): Promise { + ): Promise { const { response, data } = await apiRequest( this.trackingUri, @@ -193,7 +193,7 @@ class ExperimentClient { */ async restoreExperiment( experiment_id: string - ): Promise { + ): Promise { const { response, data } = await apiRequest( this.trackingUri, diff --git a/mlflow/src/tracking/RunClient.ts b/mlflow/src/tracking/RunClient.ts index ef26e139..38139ad6 100644 --- a/mlflow/src/tracking/RunClient.ts +++ b/mlflow/src/tracking/RunClient.ts @@ -24,7 +24,7 @@ class RunClient { run_name?: string, start_time: number = Date.now(), tags?: Array<{ key: string; value: string }> - ): Promise { + ): Promise { const { response, data } = await apiRequest(this.baseUrl, 'runs/create', { method: 'POST', body: { experiment_id, run_name, start_time, tags }, @@ -95,7 +95,7 @@ class RunClient { * @returns {Promise} A promise that resolves with the fetched run object. * @throws {ApiError} If the API request fails */ - async getRun(run_id: string): Promise { + async getRun(run_id: string): Promise { const { response, data } = await apiRequest(this.baseUrl, 'runs/get', { method: 'GET', params: { run_id }, @@ -126,7 +126,7 @@ class RunClient { status?: 'RUNNING' | 'SCHEDULED' | 'FINISHED' | 'FAILED' | 'KILLED', end_time?: number, run_name?: string - ): Promise { + ): Promise { const { response, data } = await apiRequest(this.baseUrl, 'runs/update', { method: 'POST', body: { run_id, status, end_time, run_name }, @@ -402,7 +402,7 @@ class RunClient { metric_key: string, page_token?: string, max_results?: number - ): Promise { + ): Promise { const params: Record = { run_id, metric_key }; if (page_token !== undefined) params.page_token = page_token; @@ -458,7 +458,7 @@ class RunClient { max_results?: number, order_by?: Array, page_token?: string - ): Promise { + ): Promise { const { response, data } = await apiRequest(this.baseUrl, 'runs/search', { method: 'POST', body: { @@ -498,7 +498,7 @@ class RunClient { run_id: string, path?: string, page_token?: string - ): Promise { + ): Promise { const params: Record = { run_id }; if (path !== undefined) params.path = path; if (page_token !== undefined) params.page_token = page_token; diff --git a/mlflow/tests/ExperimentClientTestFile.ts b/mlflow/tests/ExperimentClientTestFile.ts index 98449681..c0857c37 100644 --- a/mlflow/tests/ExperimentClientTestFile.ts +++ b/mlflow/tests/ExperimentClientTestFile.ts @@ -1,6 +1,6 @@ import ExperimentClient from '../src/tracking/ExperimentClient.ts'; const MLFLOW_TRACKING_URI = 'http://localhost:5001'; -let experimentClient = new ExperimentClient(MLFLOW_TRACKING_URI); +const experimentClient = new ExperimentClient(MLFLOW_TRACKING_URI); const testCreateExperiment = async () => { const num = Math.random().toString().slice(2, 11); From ab32c19bd0a47da22e3804c33e318e60fbe9648c Mon Sep 17 00:00:00 2001 From: Stephany Ho Date: Mon, 21 Oct 2024 22:31:51 -0400 Subject: [PATCH 196/357] Setup github actions --- .github/workflows/mlflow-js.yaml | 19 +++++++++++++++++++ mlflow/.gitignore | 2 ++ 2 files changed, 21 insertions(+) create mode 100644 .github/workflows/mlflow-js.yaml diff --git a/.github/workflows/mlflow-js.yaml b/.github/workflows/mlflow-js.yaml new file mode 100644 index 00000000..c7759b08 --- /dev/null +++ b/.github/workflows/mlflow-js.yaml @@ -0,0 +1,19 @@ +name: mlflow +on: + push: + branches: [stephany/github-actions-3] +jobs: + build: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + - name: Use Node.js + uses: actions/setup-node@v4 + with: + node-version: '22.7' + - name: Install and build + working-directory: ./mlflow + run: npm ci + - name: Build + working-directory: ./mlflow + run: npm run build diff --git a/mlflow/.gitignore b/mlflow/.gitignore index 845fa117..2198aa0f 100644 --- a/mlflow/.gitignore +++ b/mlflow/.gitignore @@ -13,3 +13,5 @@ lib/ # Temporary files temp/ + +package-lock.json \ No newline at end of file From efffe67985745da3aa59b0406cf01a224ef64441 Mon Sep 17 00:00:00 2001 From: Stephany Ho Date: Mon, 21 Oct 2024 22:32:20 -0400 Subject: [PATCH 197/357] Add rules to eslint.config.mjs --- mlflow/eslint.config.mjs | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/mlflow/eslint.config.mjs b/mlflow/eslint.config.mjs index 35ea989f..f3e6c8b9 100644 --- a/mlflow/eslint.config.mjs +++ b/mlflow/eslint.config.mjs @@ -7,6 +7,12 @@ export default tseslint.config( eslint.configs.recommended, ...tseslint.configs.recommended, { - ignores: ['docs'], + ignores: ['docs', 'lib/**'], + }, + { + rules: { + '@typescript-eslint/no-explicit-any': 'off', + 'no-console': 'off', + }, } ); From e35613ffdb6342f3864c635d92a9a8138effdfbf Mon Sep 17 00:00:00 2001 From: Kyler-Chiago Date: Mon, 21 Oct 2024 19:32:54 -0700 Subject: [PATCH 198/357] more eslint fixes --- .../src/model-registry/ModelRegistryClient.ts | 14 +++---- mlflow/tests/RunClientTest.ts | 27 ++----------- mlflow/tests/RunManagerTestFile.ts | 39 ++++--------------- 3 files changed, 17 insertions(+), 63 deletions(-) diff --git a/mlflow/src/model-registry/ModelRegistryClient.ts b/mlflow/src/model-registry/ModelRegistryClient.ts index 26c58809..cc1b0c38 100644 --- a/mlflow/src/model-registry/ModelRegistryClient.ts +++ b/mlflow/src/model-registry/ModelRegistryClient.ts @@ -21,7 +21,7 @@ class ModelRegistryClient { name: string, tags?: Array<{ key: string; value: string }>, description?: string - ): Promise { + ): Promise { const { response, data } = await apiRequest( this.baseUrl, 'registered-models/create', @@ -50,7 +50,7 @@ class ModelRegistryClient { * @returns {Promise} The registered model object * @throws {ApiError} If the API request fails */ - async getRegisteredModel(name: string): Promise { + async getRegisteredModel(name: string): Promise { const { response, data } = await apiRequest( this.baseUrl, 'registered-models/get', @@ -80,7 +80,7 @@ class ModelRegistryClient { * @returns {Promise} The updated registered model object * @throws {ApiError} If the API request fails */ - async renameRegisteredModel(name: string, newName: string): Promise { + async renameRegisteredModel(name: string, newName: string): Promise { const { response, data } = await apiRequest( this.baseUrl, 'registered-models/rename', @@ -113,7 +113,7 @@ class ModelRegistryClient { async updateRegisteredModel( name: string, description?: string - ): Promise { + ): Promise { const { response, data } = await apiRequest( this.baseUrl, 'registered-models/update', @@ -172,7 +172,7 @@ class ModelRegistryClient { * @returns {Promise} An array of the latest model versions * @throws {ApiError} If the API request fails */ - async getLatestModelVersions(name: string, stages?: string[]): Promise { + async getLatestModelVersions(name: string, stages?: string[]): Promise> { const { response, data } = await apiRequest( this.baseUrl, 'registered-models/get-latest-versions', @@ -207,7 +207,7 @@ class ModelRegistryClient { maxResults?: number, orderBy?: string[], pageToken?: string - ): Promise { + ): Promise { const params: Record = {}; if (filter) params.filter = filter; if (maxResults) params.max_results = maxResults.toString(); @@ -373,7 +373,7 @@ class ModelRegistryClient { * @returns {Promise} The model version object * @throws {ApiError} If the API request fails */ - async getModelVersionByAlias(name: string, alias: string): Promise { + async getModelVersionByAlias(name: string, alias: string): Promise { const { response, data } = await apiRequest( this.baseUrl, 'registered-models/alias', diff --git a/mlflow/tests/RunClientTest.ts b/mlflow/tests/RunClientTest.ts index 40e93d33..30c6be73 100644 --- a/mlflow/tests/RunClientTest.ts +++ b/mlflow/tests/RunClientTest.ts @@ -1,35 +1,14 @@ -import { apiRequest } from '../src/utils/apiRequest'; import RunClient from '../src/tracking/RunClient'; - -async function createExperiment( - client: RunClient, - name: string -): Promise { - const { response, data } = await apiRequest( - (client as any).baseUrl, - 'experiments/create', - { - method: 'POST', - body: { name }, - } - ); - - if (!response.ok) { - throw new Error( - `Error creating experiment: ${data.message || response.statusText}` - ); - } - - return data.experiment_id; -} +import ExperimentClient from '../src/tracking/ExperimentClient'; async function testRunClient(): Promise { const client = new RunClient('http://127.0.0.1:5000'); + const experimentClient = new ExperimentClient('http://127.0.0.1:5000'); try { // createRun console.log('Creating experiment...'); - const experiment_id = await createExperiment(client, 'Experiment 9'); + const experiment_id = await experimentClient.createExperiment('Experiment 9'); console.log('Created experiment ID: ', experiment_id); console.log('1. Creating run...'); diff --git a/mlflow/tests/RunManagerTestFile.ts b/mlflow/tests/RunManagerTestFile.ts index 85527923..42787c02 100644 --- a/mlflow/tests/RunManagerTestFile.ts +++ b/mlflow/tests/RunManagerTestFile.ts @@ -1,46 +1,22 @@ -import { apiRequest } from '../src/utils/apiRequest'; import RunClient from '../src/tracking/RunClient'; import RunManager from '../src/workflows/RunManager'; - -// helper functions -async function createExperiment( - myRunClient: RunClient, - name: string -): Promise { - const { response, data } = await apiRequest( - (myRunClient as any).baseUrl, - 'experiments/create', - { - method: 'POST', - body: { name }, - } - ); - - if (!response.ok) { - throw new Error( - `Error creating experiment: ${data.message || response.statusText}` - ); - } - - return data.experiment_id; -} +import ExperimentClient from '../src/tracking/ExperimentClient'; // test code for cleanupRuns async function testCleanupRuns(): Promise { const myRunClient = new RunClient('http://127.0.0.1:5000'); const myRunManager = new RunManager('http://127.0.0.1:5000'); + const myExperimentClient = new ExperimentClient('http://127.0.0.1:5000'); try { // create 2 experiments console.log('Creating experiment Test Cleanup Run 1...'); - const experiment_id1 = await createExperiment( - myRunClient, + const experiment_id1 = await myExperimentClient.createExperiment( 'Test Cleanup Run 1' ); console.log('Creating experiment Test Cleanup Run 2...'); - const experiment_id2 = await createExperiment( - myRunClient, + const experiment_id2 = await myExperimentClient.createExperiment( 'Test Cleanup Run 2' ); @@ -86,14 +62,14 @@ async function testCleanupRuns(): Promise { async function testCopyRun(): Promise { const myRunClient = new RunClient('http://127.0.0.1:5000'); const myRunManager = new RunManager('http://127.0.0.1:5000'); + const myExperimentClient = new ExperimentClient('http://127.0.0.1:5000'); try { console.log('Testing copy run...'); // create a new experiment console.log('Creating a new experiment and log batch for the new run...'); - const experiment_id1 = await createExperiment( - myRunClient, + const experiment_id1 = await myExperimentClient.createExperiment( 'Test Copy Run 1' ); @@ -173,8 +149,7 @@ async function testCopyRun(): Promise { // create another experiment console.log('Create a target experiment...'); - const experiment_id2 = await createExperiment( - myRunClient, + const experiment_id2 = await myExperimentClient.createExperiment( 'Test Copy Run 2' ); From 6abf6c3a8c2c94a4e3455dce47bb3532bf9a7817 Mon Sep 17 00:00:00 2001 From: Kyler-Chiago Date: Tue, 22 Oct 2024 17:41:55 -0700 Subject: [PATCH 199/357] yes --- mlflow/tests/ModelRegistryClientTest.ts | 80 +++---------------------- mlflow/tests/RunManagerTestFile.ts | 4 +- 2 files changed, 9 insertions(+), 75 deletions(-) diff --git a/mlflow/tests/ModelRegistryClientTest.ts b/mlflow/tests/ModelRegistryClientTest.ts index 57732fa2..709fef58 100644 --- a/mlflow/tests/ModelRegistryClientTest.ts +++ b/mlflow/tests/ModelRegistryClientTest.ts @@ -1,76 +1,11 @@ -import { apiRequest } from '../src/utils/apiRequest'; import ModelRegistryClient from '../src/model-registry/ModelRegistryClient'; - -async function createRun( - client: ModelRegistryClient, - experimentId: string -): Promise { - const { response, data } = await apiRequest( - (client as any).baseUrl, - 'runs/create', - { - method: 'POST', - body: { experiment_id: experimentId }, - } - ); - - if (!response.ok) { - throw new Error( - `Error creating run: ${data.message || response.statusText}` - ); - } - - return data.run; -} - -async function getRun( - client: ModelRegistryClient, - runId: string -): Promise { - const { response, data } = await apiRequest( - (client as any).baseUrl, - 'runs/get', - { - method: 'GET', - params: { run_id: runId }, - } - ); - - if (!response.ok) { - throw new Error( - `Error getting run: ${data.message || response.statusText}` - ); - } - - return data.run; -} - -async function createModelVersion( - client: ModelRegistryClient, - name: string, - source: string, - runId: string -): Promise { - const { response, data } = await apiRequest( - (client as any).baseUrl, - 'model-versions/create', - { - method: 'POST', - body: { name, source, run_id: runId }, - } - ); - - if (!response.ok) { - throw new Error( - `Error creating model version: ${data.message || response.statusText}` - ); - } - - return data.model_version; -} +import RunClient from '../src/tracking/RunClient'; +import ModelVersionClient from '../src/model-registry/ModelVersionClient'; async function testModelRegistryClient() { const client = new ModelRegistryClient('http://localhost:5001'); + const runClient = new RunClient('http://localhost:5001'); + const modelVersionClient = new ModelVersionClient('http://localhost:5001'); const timestamp = Date.now(); const baseName = `test-model-${timestamp}`; const renamedBaseName = `renamed-test-model-${timestamp}`; @@ -109,18 +44,17 @@ async function testModelRegistryClient() { // 5. Create a run console.log('\n5. Creating a run...'); - const run = await createRun(client, '0'); // Using '0' as the default experiment ID + const run = await runClient.createRun('0'); // Using '0' as the default experiment ID console.log('Created run:', run); // 6. Get the run to retrieve the artifact URI console.log('\n6. Getting run details...'); - const runDetails = await getRun(client, run.info.run_id); + const runDetails = await runClient.getRun(run.info.run_id); console.log('Run artifact URI:', runDetails.info.artifact_uri); // 7. Test creating a model version console.log('\n7. Creating a model version...'); - const modelVersion = await createModelVersion( - client, + const modelVersion = await modelVersionClient.createModelVersion( renamedBaseName, runDetails.info.artifact_uri + '/model', // Assuming 'model' as the artifact path run.info.run_id diff --git a/mlflow/tests/RunManagerTestFile.ts b/mlflow/tests/RunManagerTestFile.ts index 42787c02..6609beeb 100644 --- a/mlflow/tests/RunManagerTestFile.ts +++ b/mlflow/tests/RunManagerTestFile.ts @@ -3,7 +3,7 @@ import RunManager from '../src/workflows/RunManager'; import ExperimentClient from '../src/tracking/ExperimentClient'; // test code for cleanupRuns -async function testCleanupRuns(): Promise { +async function testCleanupRuns(): Promise { const myRunClient = new RunClient('http://127.0.0.1:5000'); const myRunManager = new RunManager('http://127.0.0.1:5000'); const myExperimentClient = new ExperimentClient('http://127.0.0.1:5000'); @@ -59,7 +59,7 @@ async function testCleanupRuns(): Promise { // test code for copyRun -async function testCopyRun(): Promise { +async function testCopyRun(): Promise { const myRunClient = new RunClient('http://127.0.0.1:5000'); const myRunManager = new RunManager('http://127.0.0.1:5000'); const myExperimentClient = new ExperimentClient('http://127.0.0.1:5000'); From 8a92ec3e756f3f930060a5763d311791e79a8c90 Mon Sep 17 00:00:00 2001 From: Kyler-Chiago Date: Tue, 22 Oct 2024 18:05:21 -0700 Subject: [PATCH 200/357] yes --- mlflow/package-lock.json | 452 +++++++++++++++++---------------------- 1 file changed, 198 insertions(+), 254 deletions(-) diff --git a/mlflow/package-lock.json b/mlflow/package-lock.json index 2f7e19a1..d01d536f 100644 --- a/mlflow/package-lock.json +++ b/mlflow/package-lock.json @@ -109,10 +109,34 @@ "node": "^18.18.0 || ^20.9.0 || >=21.1.0" } }, + "node_modules/@eslint/config-array/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, + "license": "MIT", + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "node_modules/@eslint/config-array/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, + "license": "ISC", + "dependencies": { + "brace-expansion": "^1.1.7" + }, + "engines": { + "node": "*" + } + }, "node_modules/@eslint/core": { - "version": "0.7.0", - "resolved": "https://registry.npmjs.org/@eslint/core/-/core-0.7.0.tgz", - "integrity": "sha512-xp5Jirz5DyPYlPiKat8jaq0EmYvDXKKpzTbxXMpT9eqlRJkRKIz9AGMdlvYjih+im+QlhWrpvVjl8IPC/lHlUw==", + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/@eslint/core/-/core-0.6.0.tgz", + "integrity": "sha512-8I2Q8ykA4J0x0o7cg67FPVnehcqWTBehu/lmY+bolPFHGjh49YzGBMXTvpqVgEbBdvNCSxj6iFgiIyHzf03lzg==", "dev": true, "license": "Apache-2.0", "engines": { @@ -143,10 +167,34 @@ "url": "https://opencollective.com/eslint" } }, + "node_modules/@eslint/eslintrc/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, + "license": "MIT", + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "node_modules/@eslint/eslintrc/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, + "license": "ISC", + "dependencies": { + "brace-expansion": "^1.1.7" + }, + "engines": { + "node": "*" + } + }, "node_modules/@eslint/js": { - "version": "9.13.0", - "resolved": "https://registry.npmjs.org/@eslint/js/-/js-9.13.0.tgz", - "integrity": "sha512-IFLyoY4d72Z5y/6o/BazFBezupzI/taV8sGumxTAVw3lXG9A6md1Dc34T9s1FoD/an9pJH8RHbAxsaEbBed9lA==", + "version": "9.12.0", + "resolved": "https://registry.npmjs.org/@eslint/js/-/js-9.12.0.tgz", + "integrity": "sha512-eohesHH8WFRUprDNyEREgqP6beG6htMeUYeCpkEgBCieCMme5r9zFWjzAJp//9S+Kub4rqE+jXe9Cp1a7IYIIA==", "dev": true, "license": "MIT", "engines": { @@ -164,9 +212,9 @@ } }, "node_modules/@eslint/plugin-kit": { - "version": "0.2.1", - "resolved": "https://registry.npmjs.org/@eslint/plugin-kit/-/plugin-kit-0.2.1.tgz", - "integrity": "sha512-HFZ4Mp26nbWk9d/BpvP0YNL6W4UoZF0VFcTw/aPPA8RpOxeFQgK+ClABGgAUXs9Y/RGX/l1vOmrqz1MQt9MNuw==", + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/@eslint/plugin-kit/-/plugin-kit-0.2.0.tgz", + "integrity": "sha512-vH9PiIMMwvhCx31Af3HiGzsVNULDbyVkHXwlemn/B0TFj/00ho3y55efXrUZTfQipxoHC5u4xq6zblww1zm1Ig==", "dev": true, "license": "Apache-2.0", "dependencies": { @@ -452,9 +500,9 @@ } }, "node_modules/@types/node": { - "version": "22.7.7", - "resolved": "https://registry.npmjs.org/@types/node/-/node-22.7.7.tgz", - "integrity": "sha512-SRxCrrg9CL/y54aiMCG3edPKdprgMVGDXjA3gB8UmmBW5TcXzRUYAh8EWzTnSJFAd1rgImPELza+A3bJ+qxz8Q==", + "version": "22.7.4", + "resolved": "https://registry.npmjs.org/@types/node/-/node-22.7.4.tgz", + "integrity": "sha512-y+NPi1rFzDs1NdQHHToqeiX2TIS79SWEAw9GYhkkx8bD0ChpfqC+n2j5OXOCpzfojBEBt6DnEnnG9MY0zk1XLg==", "dev": true, "license": "MIT", "dependencies": { @@ -469,17 +517,17 @@ "license": "MIT" }, "node_modules/@typescript-eslint/eslint-plugin": { - "version": "8.11.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-8.11.0.tgz", - "integrity": "sha512-KhGn2LjW1PJT2A/GfDpiyOfS4a8xHQv2myUagTM5+zsormOmBlYsnQ6pobJ8XxJmh6hnHwa2Mbe3fPrDJoDhbA==", + "version": "8.8.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-8.8.0.tgz", + "integrity": "sha512-wORFWjU30B2WJ/aXBfOm1LX9v9nyt9D3jsSOxC3cCaTQGCW5k4jNpmjFv3U7p/7s4yvdjHzwtv2Sd2dOyhjS0A==", "dev": true, "license": "MIT", "dependencies": { "@eslint-community/regexpp": "^4.10.0", - "@typescript-eslint/scope-manager": "8.11.0", - "@typescript-eslint/type-utils": "8.11.0", - "@typescript-eslint/utils": "8.11.0", - "@typescript-eslint/visitor-keys": "8.11.0", + "@typescript-eslint/scope-manager": "8.8.0", + "@typescript-eslint/type-utils": "8.8.0", + "@typescript-eslint/utils": "8.8.0", + "@typescript-eslint/visitor-keys": "8.8.0", "graphemer": "^1.4.0", "ignore": "^5.3.1", "natural-compare": "^1.4.0", @@ -503,16 +551,16 @@ } }, "node_modules/@typescript-eslint/parser": { - "version": "8.11.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-8.11.0.tgz", - "integrity": "sha512-lmt73NeHdy1Q/2ul295Qy3uninSqi6wQI18XwSpm8w0ZbQXUpjCAWP1Vlv/obudoBiIjJVjlztjQ+d/Md98Yxg==", + "version": "8.8.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-8.8.0.tgz", + "integrity": "sha512-uEFUsgR+tl8GmzmLjRqz+VrDv4eoaMqMXW7ruXfgThaAShO9JTciKpEsB+TvnfFfbg5IpujgMXVV36gOJRLtZg==", "dev": true, "license": "BSD-2-Clause", "dependencies": { - "@typescript-eslint/scope-manager": "8.11.0", - "@typescript-eslint/types": "8.11.0", - "@typescript-eslint/typescript-estree": "8.11.0", - "@typescript-eslint/visitor-keys": "8.11.0", + "@typescript-eslint/scope-manager": "8.8.0", + "@typescript-eslint/types": "8.8.0", + "@typescript-eslint/typescript-estree": "8.8.0", + "@typescript-eslint/visitor-keys": "8.8.0", "debug": "^4.3.4" }, "engines": { @@ -532,14 +580,14 @@ } }, "node_modules/@typescript-eslint/scope-manager": { - "version": "8.11.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-8.11.0.tgz", - "integrity": "sha512-Uholz7tWhXmA4r6epo+vaeV7yjdKy5QFCERMjs1kMVsLRKIrSdM6o21W2He9ftp5PP6aWOVpD5zvrvuHZC0bMQ==", + "version": "8.8.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-8.8.0.tgz", + "integrity": "sha512-EL8eaGC6gx3jDd8GwEFEV091210U97J0jeEHrAYvIYosmEGet4wJ+g0SYmLu+oRiAwbSA5AVrt6DxLHfdd+bUg==", "dev": true, "license": "MIT", "dependencies": { - "@typescript-eslint/types": "8.11.0", - "@typescript-eslint/visitor-keys": "8.11.0" + "@typescript-eslint/types": "8.8.0", + "@typescript-eslint/visitor-keys": "8.8.0" }, "engines": { "node": "^18.18.0 || ^20.9.0 || >=21.1.0" @@ -550,14 +598,14 @@ } }, "node_modules/@typescript-eslint/type-utils": { - "version": "8.11.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-8.11.0.tgz", - "integrity": "sha512-ItiMfJS6pQU0NIKAaybBKkuVzo6IdnAhPFZA/2Mba/uBjuPQPet/8+zh5GtLHwmuFRShZx+8lhIs7/QeDHflOg==", + "version": "8.8.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-8.8.0.tgz", + "integrity": "sha512-IKwJSS7bCqyCeG4NVGxnOP6lLT9Okc3Zj8hLO96bpMkJab+10HIfJbMouLrlpyOr3yrQ1cA413YPFiGd1mW9/Q==", "dev": true, "license": "MIT", "dependencies": { - "@typescript-eslint/typescript-estree": "8.11.0", - "@typescript-eslint/utils": "8.11.0", + "@typescript-eslint/typescript-estree": "8.8.0", + "@typescript-eslint/utils": "8.8.0", "debug": "^4.3.4", "ts-api-utils": "^1.3.0" }, @@ -575,9 +623,9 @@ } }, "node_modules/@typescript-eslint/types": { - "version": "8.11.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-8.11.0.tgz", - "integrity": "sha512-tn6sNMHf6EBAYMvmPUaKaVeYvhUsrE6x+bXQTxjQRp360h1giATU0WvgeEys1spbvb5R+VpNOZ+XJmjD8wOUHw==", + "version": "8.8.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-8.8.0.tgz", + "integrity": "sha512-QJwc50hRCgBd/k12sTykOJbESe1RrzmX6COk8Y525C9l7oweZ+1lw9JiU56im7Amm8swlz00DRIlxMYLizr2Vw==", "dev": true, "license": "MIT", "engines": { @@ -589,14 +637,14 @@ } }, "node_modules/@typescript-eslint/typescript-estree": { - "version": "8.11.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-8.11.0.tgz", - "integrity": "sha512-yHC3s1z1RCHoCz5t06gf7jH24rr3vns08XXhfEqzYpd6Hll3z/3g23JRi0jM8A47UFKNc3u/y5KIMx8Ynbjohg==", + "version": "8.8.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-8.8.0.tgz", + "integrity": "sha512-ZaMJwc/0ckLz5DaAZ+pNLmHv8AMVGtfWxZe/x2JVEkD5LnmhWiQMMcYT7IY7gkdJuzJ9P14fRy28lUrlDSWYdw==", "dev": true, "license": "BSD-2-Clause", "dependencies": { - "@typescript-eslint/types": "8.11.0", - "@typescript-eslint/visitor-keys": "8.11.0", + "@typescript-eslint/types": "8.8.0", + "@typescript-eslint/visitor-keys": "8.8.0", "debug": "^4.3.4", "fast-glob": "^3.3.2", "is-glob": "^4.0.3", @@ -617,16 +665,6 @@ } } }, - "node_modules/@typescript-eslint/typescript-estree/node_modules/brace-expansion": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", - "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", - "dev": true, - "license": "MIT", - "dependencies": { - "balanced-match": "^1.0.0" - } - }, "node_modules/@typescript-eslint/typescript-estree/node_modules/minimatch": { "version": "9.0.5", "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.5.tgz", @@ -644,16 +682,16 @@ } }, "node_modules/@typescript-eslint/utils": { - "version": "8.11.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-8.11.0.tgz", - "integrity": "sha512-CYiX6WZcbXNJV7UNB4PLDIBtSdRmRI/nb0FMyqHPTQD1rMjA0foPLaPUV39C/MxkTd/QKSeX+Gb34PPsDVC35g==", + "version": "8.8.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-8.8.0.tgz", + "integrity": "sha512-QE2MgfOTem00qrlPgyByaCHay9yb1+9BjnMFnSFkUKQfu7adBXDTnCAivURnuPPAG/qiB+kzKkZKmKfaMT0zVg==", "dev": true, "license": "MIT", "dependencies": { "@eslint-community/eslint-utils": "^4.4.0", - "@typescript-eslint/scope-manager": "8.11.0", - "@typescript-eslint/types": "8.11.0", - "@typescript-eslint/typescript-estree": "8.11.0" + "@typescript-eslint/scope-manager": "8.8.0", + "@typescript-eslint/types": "8.8.0", + "@typescript-eslint/typescript-estree": "8.8.0" }, "engines": { "node": "^18.18.0 || ^20.9.0 || >=21.1.0" @@ -667,13 +705,13 @@ } }, "node_modules/@typescript-eslint/visitor-keys": { - "version": "8.11.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-8.11.0.tgz", - "integrity": "sha512-EaewX6lxSjRJnc+99+dqzTeoDZUfyrA52d2/HRrkI830kgovWsmIiTfmr0NZorzqic7ga+1bS60lRBUgR3n/Bw==", + "version": "8.8.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-8.8.0.tgz", + "integrity": "sha512-8mq51Lx6Hpmd7HnA2fcHQo3YgfX1qbccxQOgZcb4tvasu//zXRaA1j5ZRFeCw/VRAdFi4mRM9DnZw0Nu0Q2d1g==", "dev": true, "license": "MIT", "dependencies": { - "@typescript-eslint/types": "8.11.0", + "@typescript-eslint/types": "8.8.0", "eslint-visitor-keys": "^3.4.3" }, "engines": { @@ -705,9 +743,9 @@ "license": "ISC" }, "node_modules/acorn": { - "version": "8.13.0", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.13.0.tgz", - "integrity": "sha512-8zSiw54Oxrdym50NlZ9sUusyO1Z1ZchgRLWRaK6c86XJFClyCgFKetdowBg5bKxyp/u+CDBJG4Mpp0m3HLZl9w==", + "version": "8.12.1", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.12.1.tgz", + "integrity": "sha512-tcpGyI9zbizT9JbV6oYE477V6mTlXvvi0T0G3SNIYE2apm/G5huBa1+K89VGeovbg+jycCrfhl3ADxErOuO6Jg==", "dev": true, "license": "MIT", "bin": { @@ -771,16 +809,13 @@ } }, "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==", + "version": "6.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-6.2.1.tgz", + "integrity": "sha512-bN798gFfQX+viw3R7yrGWRqnrN2oRkEkUjjl4JNn4E8GxxbjtG3FbrEIIY3l8/hrwUwIeCZvi4QuOTP4MErVug==", "dev": true, "license": "MIT", - "dependencies": { - "color-convert": "^2.0.1" - }, "engines": { - "node": ">=8" + "node": ">=12" }, "funding": { "url": "https://github.com/chalk/ansi-styles?sponsor=1" @@ -792,7 +827,6 @@ "integrity": "sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw==", "dev": true, "license": "ISC", - "license": "ISC", "dependencies": { "normalize-path": "^3.0.0", "picomatch": "^2.0.4" @@ -815,20 +849,12 @@ "dev": true, "license": "Python-2.0" }, - "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, - "license": "Python-2.0" - }, "node_modules/array-union": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/array-union/-/array-union-2.1.0.tgz", "integrity": "sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw==", "dev": true, "license": "MIT", - "license": "MIT", "engines": { "node": ">=8" } @@ -846,7 +872,6 @@ "integrity": "sha512-Ceh+7ox5qe7LJuLHoY0feh3pHuUDHAcRUeyL2VYghZwfpkNIy/+8Ocg0a3UuSoYzavmylwuLWQOf3hl0jjMMIw==", "dev": true, "license": "MIT", - "license": "MIT", "engines": { "node": ">=8" }, @@ -855,14 +880,13 @@ } }, "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==", + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", + "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", "dev": true, "license": "MIT", "dependencies": { - "balanced-match": "^1.0.0", - "concat-map": "0.0.1" + "balanced-match": "^1.0.0" } }, "node_modules/braces": { @@ -916,6 +940,22 @@ "url": "https://github.com/chalk/chalk?sponsor=1" } }, + "node_modules/chalk/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, + "license": "MIT", + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, "node_modules/character-entities-html4": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/character-entities-html4/-/character-entities-html4-2.1.0.tgz", @@ -976,44 +1016,6 @@ "node": ">= 6" } }, - "node_modules/chokidar": { - "version": "3.6.0", - "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.6.0.tgz", - "integrity": "sha512-7VT13fmjotKpGipCW9JEQAusEPE+Ei8nl6/g4FBAmIm0GOOLMua9NDDo/DWp0ZAxCr3cPq5ZpBqmPAQgDda2Pw==", - "dev": true, - "license": "MIT", - "dependencies": { - "anymatch": "~3.1.2", - "braces": "~3.0.2", - "glob-parent": "~5.1.2", - "is-binary-path": "~2.1.0", - "is-glob": "~4.0.1", - "normalize-path": "~3.0.0", - "readdirp": "~3.6.0" - }, - "engines": { - "node": ">= 8.10.0" - }, - "funding": { - "url": "https://paulmillr.com/funding/" - }, - "optionalDependencies": { - "fsevents": "~2.3.2" - } - }, - "node_modules/chokidar/node_modules/glob-parent": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", - "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", - "dev": true, - "license": "ISC", - "dependencies": { - "is-glob": "^4.0.1" - }, - "engines": { - "node": ">= 6" - } - }, "node_modules/color-convert": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", @@ -1055,16 +1057,6 @@ "node": "^12.20.0 || >=14" } }, - "node_modules/commander": { - "version": "9.5.0", - "resolved": "https://registry.npmjs.org/commander/-/commander-9.5.0.tgz", - "integrity": "sha512-KRs7WVDKg86PWiuAqhDrAQnTXZKraVcCc6vFdL14qrZ/DcWwuRo7VoiYXalXO7S5GKpqYiVEwCbgFDfxNHKJBQ==", - "dev": true, - "license": "MIT", - "engines": { - "node": "^12.20.0 || >=14" - } - }, "node_modules/concat-map": { "version": "0.0.1", "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", @@ -1159,7 +1151,6 @@ "integrity": "sha512-WkrWp9GR4KXfKGYzOLmTuGVi1UWFfws377n9cc55/tb6DuqyF6pcQ5AbiHEshaDpY9v6oaSr2XCDidGmMwdzIA==", "dev": true, "license": "MIT", - "license": "MIT", "dependencies": { "path-type": "^4.0.0" }, @@ -1248,18 +1239,18 @@ } }, "node_modules/eslint": { - "version": "9.13.0", - "resolved": "https://registry.npmjs.org/eslint/-/eslint-9.13.0.tgz", - "integrity": "sha512-EYZK6SX6zjFHST/HRytOdA/zE72Cq/bfw45LSyuwrdvcclb/gqV8RRQxywOBEWO2+WDpva6UZa4CcDeJKzUCFA==", + "version": "9.12.0", + "resolved": "https://registry.npmjs.org/eslint/-/eslint-9.12.0.tgz", + "integrity": "sha512-UVIOlTEWxwIopRL1wgSQYdnVDcEvs2wyaO6DGo5mXqe3r16IoCNWkR29iHhyaP4cICWjbgbmFUGAhh0GJRuGZw==", "dev": true, "license": "MIT", "dependencies": { "@eslint-community/eslint-utils": "^4.2.0", "@eslint-community/regexpp": "^4.11.0", "@eslint/config-array": "^0.18.0", - "@eslint/core": "^0.7.0", + "@eslint/core": "^0.6.0", "@eslint/eslintrc": "^3.1.0", - "@eslint/js": "9.13.0", + "@eslint/js": "9.12.0", "@eslint/plugin-kit": "^0.2.0", "@humanfs/node": "^0.16.5", "@humanwhocodes/module-importer": "^1.0.1", @@ -1338,6 +1329,30 @@ "url": "https://opencollective.com/eslint" } }, + "node_modules/eslint/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, + "license": "MIT", + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "node_modules/eslint/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, + "license": "ISC", + "dependencies": { + "brace-expansion": "^1.1.7" + }, + "engines": { + "node": "*" + } + }, "node_modules/espree": { "version": "10.2.0", "resolved": "https://registry.npmjs.org/espree/-/espree-10.2.0.tgz", @@ -1582,18 +1597,13 @@ } }, "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==", "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, "license": "ISC", - "license": "ISC", "dependencies": { "is-glob": "^4.0.3" - "is-glob": "^4.0.3" }, "engines": { "node": ">=10.13.0" @@ -1612,13 +1622,12 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/glob/node_modules/brace-expansion": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", - "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", + "node_modules/globby": { + "version": "11.1.0", + "resolved": "https://registry.npmjs.org/globby/-/globby-11.1.0.tgz", + "integrity": "sha512-jhIXaOzy1sb8IyocaruWSn1TjmnBVs8Ayhcy83rmxNJ8q2uWKCAj3CnJY+KpGSXCueAPc0i05kVvVKtP1t9S3g==", "dev": true, "license": "MIT", - "license": "MIT", "dependencies": { "array-union": "^2.1.0", "dir-glob": "^3.0.1", @@ -1750,19 +1759,6 @@ "node": ">=8" } }, - "node_modules/is-binary-path": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz", - "integrity": "sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==", - "dev": true, - "license": "MIT", - "dependencies": { - "binary-extensions": "^2.0.0" - }, - "engines": { - "node": ">=8" - } - }, "node_modules/is-extglob": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", @@ -2110,16 +2106,19 @@ } }, "node_modules/minimatch": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", - "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "version": "10.0.1", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-10.0.1.tgz", + "integrity": "sha512-ethXTt3SGGR+95gudmqJ1eNhRO7eGEGIgYA9vnPatK4/etz2MEVDno5GMCibdMTuBMyElzIlgxMna3K94XDIDQ==", "dev": true, "license": "ISC", "dependencies": { - "brace-expansion": "^1.1.7" + "brace-expansion": "^2.0.1" }, "engines": { - "node": "*" + "node": "20 || >=22" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" } }, "node_modules/minipass": { @@ -2139,20 +2138,12 @@ "dev": true, "license": "MIT" }, - "node_modules/ms": { - "version": "2.1.3", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", - "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", - "dev": true, - "license": "MIT" - }, "node_modules/mylas": { "version": "2.1.13", "resolved": "https://registry.npmjs.org/mylas/-/mylas-2.1.13.tgz", "integrity": "sha512-+MrqnJRtxdF+xngFfUUkIMQrUUL0KsxbADUkn23Z/4ibGg192Q+z+CQyiYwvWTsYjJygmMR8+w3ZDa98Zh6ESg==", "dev": true, "license": "MIT", - "license": "MIT", "engines": { "node": ">=12.0.0" }, @@ -2168,24 +2159,15 @@ "dev": true, "license": "MIT" }, - "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, - "license": "MIT" - }, "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, "license": "MIT", - "license": "MIT", "engines": { "node": ">=0.10.0" } - } }, "node_modules/oniguruma-to-js": { "version": "0.4.3", @@ -2313,7 +2295,6 @@ "integrity": "sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==", "dev": true, "license": "MIT", - "license": "MIT", "engines": { "node": ">=8" } @@ -2344,19 +2325,6 @@ "node": ">=12" } }, - "node_modules/plimit-lit": { - "version": "1.6.1", - "resolved": "https://registry.npmjs.org/plimit-lit/-/plimit-lit-1.6.1.tgz", - "integrity": "sha512-B7+VDyb8Tl6oMJT9oSO2CW8XC/T4UcJGrwOVoNGwOQsQYhlpfajmrMj5xeejqaASq3V/EqThyOeATEOMuSEXiA==", - "dev": true, - "license": "MIT", - "dependencies": { - "queue-lit": "^1.5.1" - }, - "engines": { - "node": ">=12" - } - }, "node_modules/prelude-ls": { "version": "1.2.1", "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.2.1.tgz", @@ -2408,16 +2376,6 @@ "node": ">=12" } }, - "node_modules/queue-lit": { - "version": "1.5.2", - "resolved": "https://registry.npmjs.org/queue-lit/-/queue-lit-1.5.2.tgz", - "integrity": "sha512-tLc36IOPeMAubu8BkW8YDBV+WyIgKlYU7zUNs0J5Vk9skSZ4JfGlPOqplP0aHdfv7HL0B2Pg6nwiq60Qc6M2Hw==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=12" - } - }, "node_modules/queue-microtask": { "version": "1.2.3", "resolved": "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.3.tgz", @@ -2438,8 +2396,6 @@ } ], "license": "MIT" - ], - "license": "MIT" }, "node_modules/readdirp": { "version": "3.6.0", @@ -2447,7 +2403,6 @@ "integrity": "sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==", "dev": true, "license": "MIT", - "license": "MIT", "dependencies": { "picomatch": "^2.2.1" }, @@ -2607,12 +2562,9 @@ "integrity": "sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==", "dev": true, "license": "MIT", - "license": "MIT", "engines": { "node": ">=8" } - }, - } }, "node_modules/space-separated-tokens": { "version": "2.0.2", @@ -2910,9 +2862,9 @@ } }, "node_modules/typedoc": { - "version": "0.26.10", - "resolved": "https://registry.npmjs.org/typedoc/-/typedoc-0.26.10.tgz", - "integrity": "sha512-xLmVKJ8S21t+JeuQLNueebEuTVphx6IrP06CdV7+0WVflUSW3SPmR+h1fnWVdAR/FQePEgsSWCUHXqKKjzuUAw==", + "version": "0.26.9", + "resolved": "https://registry.npmjs.org/typedoc/-/typedoc-0.26.9.tgz", + "integrity": "sha512-Rc7QpWL7EtmrT8yxV0GmhOR6xHgFnnhphbD9Suti3fz3um7ZOrou6q/g9d6+zC5PssTLZmjaW4Upmzv8T1rCcQ==", "dev": true, "license": "Apache-2.0", "dependencies": { @@ -2932,16 +2884,6 @@ "typescript": "4.6.x || 4.7.x || 4.8.x || 4.9.x || 5.0.x || 5.1.x || 5.2.x || 5.3.x || 5.4.x || 5.5.x || 5.6.x" } }, - "node_modules/typedoc/node_modules/brace-expansion": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", - "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", - "dev": true, - "license": "MIT", - "dependencies": { - "balanced-match": "^1.0.0" - } - }, "node_modules/typedoc/node_modules/minimatch": { "version": "9.0.5", "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.5.tgz", @@ -2959,12 +2901,11 @@ } }, "node_modules/typescript": { - "version": "5.6.3", - "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.6.3.tgz", - "integrity": "sha512-hjcS1mhfuyi4WW8IWtjP7brDrG2cuDZukyrYrSauoXGNgx0S7zceP07adYkJycEr56BOUTNPzbInooiN3fn1qw==", + "version": "5.6.2", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.6.2.tgz", + "integrity": "sha512-NW8ByodCSNCwZeghjN3o+JX5OFH0Ojg6sadjEKY4huZ52TqbJTJnDo5+Tw98lSy63NZvi4n+ez5m2u5d4PkZyw==", "dev": true, "license": "Apache-2.0", - "license": "Apache-2.0", "bin": { "tsc": "bin/tsc", "tsserver": "bin/tsserver" @@ -2974,15 +2915,15 @@ } }, "node_modules/typescript-eslint": { - "version": "8.11.0", - "resolved": "https://registry.npmjs.org/typescript-eslint/-/typescript-eslint-8.11.0.tgz", - "integrity": "sha512-cBRGnW3FSlxaYwU8KfAewxFK5uzeOAp0l2KebIlPDOT5olVi65KDG/yjBooPBG0kGW/HLkoz1c/iuBFehcS3IA==", + "version": "8.8.0", + "resolved": "https://registry.npmjs.org/typescript-eslint/-/typescript-eslint-8.8.0.tgz", + "integrity": "sha512-BjIT/VwJ8+0rVO01ZQ2ZVnjE1svFBiRczcpr1t1Yxt7sT25VSbPfrJtDsQ8uQTy2pilX5nI9gwxhUyLULNentw==", "dev": true, "license": "MIT", "dependencies": { - "@typescript-eslint/eslint-plugin": "8.11.0", - "@typescript-eslint/parser": "8.11.0", - "@typescript-eslint/utils": "8.11.0" + "@typescript-eslint/eslint-plugin": "8.8.0", + "@typescript-eslint/parser": "8.8.0", + "@typescript-eslint/utils": "8.8.0" }, "engines": { "node": "^18.18.0 || ^20.9.0 || >=21.1.0" @@ -3204,6 +3145,22 @@ "node": ">=8" } }, + "node_modules/wrap-ansi-cjs/node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "license": "MIT", + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, "node_modules/wrap-ansi-cjs/node_modules/emoji-regex": { "version": "8.0.0", "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", @@ -3239,19 +3196,6 @@ "node": ">=8" } }, - "node_modules/wrap-ansi/node_modules/ansi-styles": { - "version": "6.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-6.2.1.tgz", - "integrity": "sha512-bN798gFfQX+viw3R7yrGWRqnrN2oRkEkUjjl4JNn4E8GxxbjtG3FbrEIIY3l8/hrwUwIeCZvi4QuOTP4MErVug==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" - } - }, "node_modules/yaml": { "version": "2.6.0", "resolved": "https://registry.npmjs.org/yaml/-/yaml-2.6.0.tgz", From a18123afbb22c3584df5db8d5d785af1f1f8ce71 Mon Sep 17 00:00:00 2001 From: Kyler-Chiago Date: Tue, 22 Oct 2024 19:44:26 -0700 Subject: [PATCH 201/357] more styling on the website, setting up the desktop view --- mlflow-site/src/app/components/DemoCard.tsx | 54 +++++++------ mlflow-site/src/app/components/Features.tsx | 4 +- mlflow-site/src/app/globals.css | 84 ++++++++++++++++----- 3 files changed, 96 insertions(+), 46 deletions(-) diff --git a/mlflow-site/src/app/components/DemoCard.tsx b/mlflow-site/src/app/components/DemoCard.tsx index 909fed47..b2a34307 100644 --- a/mlflow-site/src/app/components/DemoCard.tsx +++ b/mlflow-site/src/app/components/DemoCard.tsx @@ -1,28 +1,32 @@ -import Image from "next/image"; +import Image from 'next/image'; -const DemoCard = ({ header, blurb }: { - key: string, - blurb: string, - header: string - }) => { - return ( -
- +const DemoCard = ({ + header, + blurb, +}: { + key: string; + blurb: string; + header: string; +}) => { + return ( +
+ +
{header}
- {blurb} +
{blurb}
- ); - }; - - export default DemoCard; - \ No newline at end of file +
+ ); +}; + +export default DemoCard; diff --git a/mlflow-site/src/app/components/Features.tsx b/mlflow-site/src/app/components/Features.tsx index 6ab94b09..5d544de9 100644 --- a/mlflow-site/src/app/components/Features.tsx +++ b/mlflow-site/src/app/components/Features.tsx @@ -13,7 +13,7 @@ const Features = () => { 'Feature 4', ]; const featureCardBlurbs = [ - 'Feature Card Blurb 1. Feature Card Blurb 1. Feature Card Blurb 1. Feature Card Blurb 1. ', + 'Feature Card Blurb 1. Feature Card Blurb 1. Feature Card Blurb 1. Feature Card Blurb 1. Feature Card Blurb 1. Feature Card Blurb 1. Feature Card Blurb 1. Feature Card Blurb 1. ', 'Feature Card Blurb 2. Feature Card Blurb 2. Feature Card Blurb 2. Feature Card Blurb 2. ', 'Feature Card Blurb 3. Feature Card Blurb 3. Feature Card Blurb 3. Feature Card Blurb 3. ', 'Feature Card Blurb 4. Feature Card Blurb 4. Feature Card Blurb 4. Feature Card Blurb 4. ' @@ -32,7 +32,7 @@ const Features = () => {
{featureHeader}
{featureLongBlurb}
-
{cards}
+
{cards}
); }; diff --git a/mlflow-site/src/app/globals.css b/mlflow-site/src/app/globals.css index 18c2374c..4995ea21 100644 --- a/mlflow-site/src/app/globals.css +++ b/mlflow-site/src/app/globals.css @@ -25,7 +25,7 @@ body { } .wrapper { - position:absolute; + position: absolute; background: rgb(51, 51, 58); width: 100%; height: 100%; @@ -33,11 +33,11 @@ body { grid-template-columns: 1fr 100vw 1fr; grid-template-rows: 1fr; overflow-y: auto; + overflow-x: hidden; } ::-webkit-scrollbar { - height: 10px; - width: 10px; + width: 0px; } /* Track */ @@ -47,12 +47,12 @@ body { /* Handle */ ::-webkit-scrollbar-thumb { - background: #3c3c3c; + background: #5c5c5c; } /* Handle on hover */ ::-webkit-scrollbar-thumb:hover { - background: #1b1b1b; + background: #515151; } .mobileWrapper { @@ -62,10 +62,22 @@ body { grid-column: 2; grid-row: 1; display: grid; - grid-template-columns: 0.7rem 1.3rem 1fr 1.3rem 0.7rem; + grid-template-columns: + 1vw clamp(1.3rem, 6vw, 8vw) 1fr clamp(1.3rem, 6vw, 8vw) + 1vw; grid-template-rows: 1.3rem min-content 1fr min-content 1.3rem; } +@media (min-width: 1000px) { + ::-webkit-scrollbar { + width: 10px; + } + + .mobileWrapper { + grid-template-columns: 1vw 8vw 1fr calc(8vw + 10px) calc(1vw + 10px); + } +} + .navBar { grid-column: 2/5; grid-row: 2; @@ -83,9 +95,11 @@ body { width: 100%; height: 100%; display: grid; - grid-template-columns: repeat(calc(100%/5), 5); + grid-template-columns: repeat(calc(100% / 5), 5); grid-template-rows: 100%; align-items: center; + justify-content: right; + column-gap: 2.8vw; } .navBarLinksFeatures { @@ -117,12 +131,12 @@ body { } .bigHeadline { - font-size: clamp(1.7rem, 6.531vw, 3rem); + font-size: clamp(1.7rem, 6.531vw, 6.25rem); font-family: Newsreader; } .headLineText { - font-size: clamp(1rem, 4.43vw, 1.76rem); + font-size: clamp(1.1rem, 4.873vw, 2.25rem); } .mobileInnerWrapper { @@ -152,8 +166,8 @@ body { .homeButton { padding: clamp(0.1875rem, 0.830625vw, 0.328125rem); - padding-left: clamp(0.375rem, 1.66125vw, .65625rem); - padding-right: clamp(0.375rem, 1.66125vw, .65625rem); + padding-left: clamp(0.375rem, 1.66125vw, 0.65625rem); + padding-right: clamp(0.375rem, 1.66125vw, 0.65625rem); border-radius: clamp(0.3125rem, 1.384375vw, 0.546875rem); font-size: clamp(0.8rem, 3.544vw, 1.05rem); margin-right: 8px; @@ -178,18 +192,19 @@ body { display: grid; place-items: center; padding: 0.5rem; - margin-bottom: 5rem; + margin-bottom: 4rem; text-align: center; color: black; background-color: white; } .featureHeader { - font-size: 1.875rem; + font-size: clamp(1.3rem, 5.759vw, 3rem); margin-bottom: 0.5rem; } .featureLongBlurb { + font-size: clamp(1rem, 4.43vw, 1.7rem); margin-bottom: 0.5rem; } @@ -205,7 +220,19 @@ body { } .featureCardHeader { - font-size: 1.5rem; + font-size: clamp(1.3rem, 5.316vw, 1.5rem); +} + +@media (min-width: 1000px) { + .featureCardsSection { + display: grid; + grid-template-columns: 50% 50%; + column-gap: 10px; + } + + .featureCard { + text-align: left; + } } .demo { @@ -214,10 +241,10 @@ body { width: 100%; display: grid; grid-template-columns: 100%; - grid-template-rows: calc(100%/3) calc(100%/3) calc(100%/3); + grid-template-rows: calc(100% / 3) calc(100% / 3) calc(100% / 3); color: black; background-color: white; - margin-bottom: 5rem; + margin-bottom: 3rem; } .demoCard { @@ -227,8 +254,27 @@ body { text-align: center; } +@media (min-width: 1000px) { + .demoCard { + display: grid; + grid-template-columns: 50% 50%; + column-gap: 10px; + text-align: left; + } +} + +@media (max-width: 1000px) { + .demoCardText { + margin-top: 0.8rem; + } +} + .demoCardHeader { - font-size: 1.5rem; + font-size: clamp(1.3rem, 5.759vw, 2rem); +} + +.demoCardInfo { + font-size: clamp(1rem, 4vw, 1.25rem); } .demoSplit { @@ -256,7 +302,7 @@ body { justify-content: center; align-items: center; font-size: clamp(1rem, 4.43vw, 1.3rem); - padding: clamp(.22rem, 1.1927vw,0.35rem); + padding: clamp(0.22rem, 1.1927vw, 0.35rem); margin-left: 0.2rem; margin-right: 0.2rem; background-color: rgb(217, 225, 210); @@ -279,4 +325,4 @@ body { .teamCardLink2 { grid-column: 3; -} \ No newline at end of file +} From 929ae34585859788fe6f250a6b516404e56e3aa1 Mon Sep 17 00:00:00 2001 From: Kyler-Chiago Date: Wed, 23 Oct 2024 17:22:49 -0700 Subject: [PATCH 202/357] more styling done --- mlflow-site/src/app/globals.css | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/mlflow-site/src/app/globals.css b/mlflow-site/src/app/globals.css index 4995ea21..ec912ba7 100644 --- a/mlflow-site/src/app/globals.css +++ b/mlflow-site/src/app/globals.css @@ -196,6 +196,7 @@ body { text-align: center; color: black; background-color: white; + margin-top: clamp(1rem, 4.43vw, 3rem); } .featureHeader { @@ -204,7 +205,7 @@ body { } .featureLongBlurb { - font-size: clamp(1rem, 4.43vw, 1.7rem); + font-size: clamp(1rem, 4.43vw, 1.5rem); margin-bottom: 0.5rem; } @@ -223,6 +224,10 @@ body { font-size: clamp(1.3rem, 5.316vw, 1.5rem); } +.featureCardsSection { + margin-top: 1rem; +} + @media (min-width: 1000px) { .featureCardsSection { display: grid; @@ -244,13 +249,13 @@ body { grid-template-rows: calc(100% / 3) calc(100% / 3) calc(100% / 3); color: black; background-color: white; - margin-bottom: 3rem; + margin-bottom: clamp(1rem, 4.43vw, 3rem); } .demoCard { gap: 1.25rem; padding: 0.25rem; - margin-bottom: 5rem; + margin-bottom: 4rem; text-align: center; } From d1fc8b6980bc6e5aca2ce08e7d6d2db05547cfb7 Mon Sep 17 00:00:00 2001 From: Kyler-Chiago Date: Wed, 23 Oct 2024 18:11:55 -0700 Subject: [PATCH 203/357] removed typedoc --- mlflow/package-lock.json | 645 --------------------------------------- mlflow/package.json | 3 +- mlflow/tsconfig.json | 4 - mlflow/typedoc.json | 4 - 4 files changed, 1 insertion(+), 655 deletions(-) delete mode 100644 mlflow/typedoc.json diff --git a/mlflow/package-lock.json b/mlflow/package-lock.json index d01d536f..9127385a 100644 --- a/mlflow/package-lock.json +++ b/mlflow/package-lock.json @@ -17,7 +17,6 @@ "ts-node": "^10.9.2", "tsc-alias": "^1.8.10", "tsx": "^4.19.1", - "typedoc": "^0.26.9", "typescript": "^5.6.2", "typescript-eslint": "^8.8.0" }, @@ -360,62 +359,6 @@ "node": ">= 8" } }, - "node_modules/@shikijs/core": { - "version": "1.22.0", - "resolved": "https://registry.npmjs.org/@shikijs/core/-/core-1.22.0.tgz", - "integrity": "sha512-S8sMe4q71TJAW+qG93s5VaiihujRK6rqDFqBnxqvga/3LvqHEnxqBIOPkt//IdXVtHkQWKu4nOQNk0uBGicU7Q==", - "dev": true, - "license": "MIT", - "dependencies": { - "@shikijs/engine-javascript": "1.22.0", - "@shikijs/engine-oniguruma": "1.22.0", - "@shikijs/types": "1.22.0", - "@shikijs/vscode-textmate": "^9.3.0", - "@types/hast": "^3.0.4", - "hast-util-to-html": "^9.0.3" - } - }, - "node_modules/@shikijs/engine-javascript": { - "version": "1.22.0", - "resolved": "https://registry.npmjs.org/@shikijs/engine-javascript/-/engine-javascript-1.22.0.tgz", - "integrity": "sha512-AeEtF4Gcck2dwBqCFUKYfsCq0s+eEbCEbkUuFou53NZ0sTGnJnJ/05KHQFZxpii5HMXbocV9URYVowOP2wH5kw==", - "dev": true, - "license": "MIT", - "dependencies": { - "@shikijs/types": "1.22.0", - "@shikijs/vscode-textmate": "^9.3.0", - "oniguruma-to-js": "0.4.3" - } - }, - "node_modules/@shikijs/engine-oniguruma": { - "version": "1.22.0", - "resolved": "https://registry.npmjs.org/@shikijs/engine-oniguruma/-/engine-oniguruma-1.22.0.tgz", - "integrity": "sha512-5iBVjhu/DYs1HB0BKsRRFipRrD7rqjxlWTj4F2Pf+nQSPqc3kcyqFFeZXnBMzDf0HdqaFVvhDRAGiYNvyLP+Mw==", - "dev": true, - "license": "MIT", - "dependencies": { - "@shikijs/types": "1.22.0", - "@shikijs/vscode-textmate": "^9.3.0" - } - }, - "node_modules/@shikijs/types": { - "version": "1.22.0", - "resolved": "https://registry.npmjs.org/@shikijs/types/-/types-1.22.0.tgz", - "integrity": "sha512-Fw/Nr7FGFhlQqHfxzZY8Cwtwk5E9nKDUgeLjZgt3UuhcM3yJR9xj3ZGNravZZok8XmEZMiYkSMTPlPkULB8nww==", - "dev": true, - "license": "MIT", - "dependencies": { - "@shikijs/vscode-textmate": "^9.3.0", - "@types/hast": "^3.0.4" - } - }, - "node_modules/@shikijs/vscode-textmate": { - "version": "9.3.0", - "resolved": "https://registry.npmjs.org/@shikijs/vscode-textmate/-/vscode-textmate-9.3.0.tgz", - "integrity": "sha512-jn7/7ky30idSkd/O5yDBfAnVt+JJpepofP/POZ1iMOxK59cOfqIgg/Dj0eFsjOTMw+4ycJN0uhZH/Eb0bs/EUA==", - "dev": true, - "license": "MIT" - }, "node_modules/@tsconfig/node10": { "version": "1.0.11", "resolved": "https://registry.npmjs.org/@tsconfig/node10/-/node10-1.0.11.tgz", @@ -472,16 +415,6 @@ "dev": true, "license": "MIT" }, - "node_modules/@types/hast": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/@types/hast/-/hast-3.0.4.tgz", - "integrity": "sha512-WPs+bbQw5aCj+x6laNGWLH3wviHtoCv/P3+otBhbOhJgG8qtpdAMlTCxLtsTWA7LH1Oh/bFCHsBn0TPS5m30EQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "@types/unist": "*" - } - }, "node_modules/@types/json-schema": { "version": "7.0.15", "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.15.tgz", @@ -489,16 +422,6 @@ "dev": true, "license": "MIT" }, - "node_modules/@types/mdast": { - "version": "4.0.4", - "resolved": "https://registry.npmjs.org/@types/mdast/-/mdast-4.0.4.tgz", - "integrity": "sha512-kGaNbPh1k7AFzgpud/gMdvIm5xuECykRR+JnWKQno9TAXVa6WIVCGTPvYGekIDL4uwCZQSYbUxNBSb1aUo79oA==", - "dev": true, - "license": "MIT", - "dependencies": { - "@types/unist": "*" - } - }, "node_modules/@types/node": { "version": "22.7.4", "resolved": "https://registry.npmjs.org/@types/node/-/node-22.7.4.tgz", @@ -509,13 +432,6 @@ "undici-types": "~6.19.2" } }, - "node_modules/@types/unist": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/@types/unist/-/unist-3.0.3.tgz", - "integrity": "sha512-ko/gIFJRv177XgZsZcBwnqJN5x/Gien8qNOn0D5bQU/zAzVf9Zt3BlcUiLqhV9y4ARk0GbT3tnUiPNgnTXzc/Q==", - "dev": true, - "license": "MIT" - }, "node_modules/@typescript-eslint/eslint-plugin": { "version": "8.8.0", "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-8.8.0.tgz", @@ -735,13 +651,6 @@ "url": "https://opencollective.com/eslint" } }, - "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, - "license": "ISC" - }, "node_modules/acorn": { "version": "8.12.1", "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.12.1.tgz", @@ -912,17 +821,6 @@ "node": ">=6" } }, - "node_modules/ccount": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/ccount/-/ccount-2.0.1.tgz", - "integrity": "sha512-eyrF0jiFpY+3drT6383f1qhkbGsLSifNAjA61IUjZjmLCWjItY6LB9ft9YhoDgwfmclB2zhu51Lc7+95b8NRAg==", - "dev": true, - "license": "MIT", - "funding": { - "type": "github", - "url": "https://github.com/sponsors/wooorm" - } - }, "node_modules/chalk": { "version": "4.1.2", "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", @@ -956,28 +854,6 @@ "url": "https://github.com/chalk/ansi-styles?sponsor=1" } }, - "node_modules/character-entities-html4": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/character-entities-html4/-/character-entities-html4-2.1.0.tgz", - "integrity": "sha512-1v7fgQRj6hnSwFpq1Eu0ynr/CDEw0rXo2B61qXrLNdHZmPKgb7fqS1a2JwF0rISo9q77jDI8VMEHoApn8qDoZA==", - "dev": true, - "license": "MIT", - "funding": { - "type": "github", - "url": "https://github.com/sponsors/wooorm" - } - }, - "node_modules/character-entities-legacy": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/character-entities-legacy/-/character-entities-legacy-3.0.0.tgz", - "integrity": "sha512-RpPp0asT/6ufRm//AJVwpViZbGM/MkjQFxJccQRHmISF/22NBtsHqAWmL+/pmkPWoIUJdWyeVleTl1wydHATVQ==", - "dev": true, - "license": "MIT", - "funding": { - "type": "github", - "url": "https://github.com/sponsors/wooorm" - } - }, "node_modules/chokidar": { "version": "3.6.0", "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.6.0.tgz", @@ -1036,17 +912,6 @@ "dev": true, "license": "MIT" }, - "node_modules/comma-separated-tokens": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/comma-separated-tokens/-/comma-separated-tokens-2.0.3.tgz", - "integrity": "sha512-Fu4hJdvzeylCfQPp9SGWidpzrMs7tTrlu6Vb8XGaRGck8QSNZJJp538Wrb60Lax4fPwR64ViY468OIUTbRlGZg==", - "dev": true, - "license": "MIT", - "funding": { - "type": "github", - "url": "https://github.com/sponsors/wooorm" - } - }, "node_modules/commander": { "version": "9.5.0", "resolved": "https://registry.npmjs.org/commander/-/commander-9.5.0.tgz", @@ -1111,30 +976,6 @@ "dev": true, "license": "MIT" }, - "node_modules/dequal": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/dequal/-/dequal-2.0.3.tgz", - "integrity": "sha512-0je+qPKHEMohvfRTCEo3CrPG6cAzAYgmzKyxRiYSSDkS6eGJdyVJm7WaYA5ECaAD9wLB2T4EEeymA5aFVcYXCA==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=6" - } - }, - "node_modules/devlop": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/devlop/-/devlop-1.1.0.tgz", - "integrity": "sha512-RWmIqhcFf1lRYBvNmr7qTNuyCt/7/ns2jbpp1+PalgE/rDQcBT0fioSMUpJ93irlUhC5hrg4cYqe6U+0ImW0rA==", - "dev": true, - "license": "MIT", - "dependencies": { - "dequal": "^2.0.0" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/wooorm" - } - }, "node_modules/diff": { "version": "4.0.2", "resolved": "https://registry.npmjs.org/diff/-/diff-4.0.2.tgz", @@ -1172,19 +1013,6 @@ "dev": true, "license": "MIT" }, - "node_modules/entities": { - "version": "4.5.0", - "resolved": "https://registry.npmjs.org/entities/-/entities-4.5.0.tgz", - "integrity": "sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw==", - "dev": true, - "license": "BSD-2-Clause", - "engines": { - "node": ">=0.12" - }, - "funding": { - "url": "https://github.com/fb55/entities?sponsor=1" - } - }, "node_modules/esbuild": { "version": "0.23.1", "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.23.1.tgz", @@ -1660,55 +1488,6 @@ "node": ">=8" } }, - "node_modules/hast-util-to-html": { - "version": "9.0.3", - "resolved": "https://registry.npmjs.org/hast-util-to-html/-/hast-util-to-html-9.0.3.tgz", - "integrity": "sha512-M17uBDzMJ9RPCqLMO92gNNUDuBSq10a25SDBI08iCCxmorf4Yy6sYHK57n9WAbRAAaU+DuR4W6GN9K4DFZesYg==", - "dev": true, - "license": "MIT", - "dependencies": { - "@types/hast": "^3.0.0", - "@types/unist": "^3.0.0", - "ccount": "^2.0.0", - "comma-separated-tokens": "^2.0.0", - "hast-util-whitespace": "^3.0.0", - "html-void-elements": "^3.0.0", - "mdast-util-to-hast": "^13.0.0", - "property-information": "^6.0.0", - "space-separated-tokens": "^2.0.0", - "stringify-entities": "^4.0.0", - "zwitch": "^2.0.4" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, - "node_modules/hast-util-whitespace": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/hast-util-whitespace/-/hast-util-whitespace-3.0.0.tgz", - "integrity": "sha512-88JUN06ipLwsnv+dVn+OIYOvAuvBMy/Qoi6O7mQHxdPXpjy+Cd6xRkWwux7DKO+4sYILtLBRIKgsdpS2gQc7qw==", - "dev": true, - "license": "MIT", - "dependencies": { - "@types/hast": "^3.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, - "node_modules/html-void-elements": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/html-void-elements/-/html-void-elements-3.0.0.tgz", - "integrity": "sha512-bEqo66MRXsUGxWHV5IP0PUiAWwoEjba4VCzg0LjFJBpchPaTfyfCKTG6bc5F8ucKec3q5y6qOdGyYTSBEvhCrg==", - "dev": true, - "license": "MIT", - "funding": { - "type": "github", - "url": "https://github.com/sponsors/wooorm" - } - }, "node_modules/ignore": { "version": "5.3.2", "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.3.2.tgz", @@ -1883,16 +1662,6 @@ "node": ">= 0.8.0" } }, - "node_modules/linkify-it": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/linkify-it/-/linkify-it-5.0.0.tgz", - "integrity": "sha512-5aHCbzQRADcdP+ATqnDuhhJ/MRIqDkZX5pyjFHRRysS8vZ5AbqGEoFIb6pYHPZ+L/OC2Lc+xT8uHVVR5CAK/wQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "uc.micro": "^2.0.0" - } - }, "node_modules/locate-path": { "version": "6.0.0", "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz", @@ -1926,13 +1695,6 @@ "node": "20 || >=22" } }, - "node_modules/lunr": { - "version": "2.3.9", - "resolved": "https://registry.npmjs.org/lunr/-/lunr-2.3.9.tgz", - "integrity": "sha512-zTU3DaZaF3Rt9rhN3uBMGQD3dD2/vFQqnvZCDv4dl5iOzq2IZQqTxu90r4E5J+nP70J3ilqVCrbho2eWaeW8Ow==", - "dev": true, - "license": "MIT" - }, "node_modules/make-error": { "version": "1.3.6", "resolved": "https://registry.npmjs.org/make-error/-/make-error-1.3.6.tgz", @@ -1940,53 +1702,6 @@ "dev": true, "license": "ISC" }, - "node_modules/markdown-it": { - "version": "14.1.0", - "resolved": "https://registry.npmjs.org/markdown-it/-/markdown-it-14.1.0.tgz", - "integrity": "sha512-a54IwgWPaeBCAAsv13YgmALOF1elABB08FxO9i+r4VFk5Vl4pKokRPeX8u5TCgSsPi6ec1otfLjdOpVcgbpshg==", - "dev": true, - "license": "MIT", - "dependencies": { - "argparse": "^2.0.1", - "entities": "^4.4.0", - "linkify-it": "^5.0.0", - "mdurl": "^2.0.0", - "punycode.js": "^2.3.1", - "uc.micro": "^2.1.0" - }, - "bin": { - "markdown-it": "bin/markdown-it.mjs" - } - }, - "node_modules/mdast-util-to-hast": { - "version": "13.2.0", - "resolved": "https://registry.npmjs.org/mdast-util-to-hast/-/mdast-util-to-hast-13.2.0.tgz", - "integrity": "sha512-QGYKEuUsYT9ykKBCMOEDLsU5JRObWQusAolFMeko/tYPufNkRffBAQjIE+99jbA87xv6FgmjLtwjh9wBWajwAA==", - "dev": true, - "license": "MIT", - "dependencies": { - "@types/hast": "^3.0.0", - "@types/mdast": "^4.0.0", - "@ungap/structured-clone": "^1.0.0", - "devlop": "^1.0.0", - "micromark-util-sanitize-uri": "^2.0.0", - "trim-lines": "^3.0.0", - "unist-util-position": "^5.0.0", - "unist-util-visit": "^5.0.0", - "vfile": "^6.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, - "node_modules/mdurl": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/mdurl/-/mdurl-2.0.0.tgz", - "integrity": "sha512-Lf+9+2r+Tdp5wXDXC4PcIBjTDtq4UKjCPMQhKIuzpJNW0b96kVqSwW0bT7FhRSfmAiFYgP+SCRvdrDozfh0U5w==", - "dev": true, - "license": "MIT" - }, "node_modules/merge2": { "version": "1.4.1", "resolved": "https://registry.npmjs.org/merge2/-/merge2-1.4.1.tgz", @@ -1997,100 +1712,6 @@ "node": ">= 8" } }, - "node_modules/micromark-util-character": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/micromark-util-character/-/micromark-util-character-2.1.0.tgz", - "integrity": "sha512-KvOVV+X1yLBfs9dCBSopq/+G1PcgT3lAK07mC4BzXi5E7ahzMAF8oIupDDJ6mievI6F+lAATkbQQlQixJfT3aQ==", - "dev": true, - "funding": [ - { - "type": "GitHub Sponsors", - "url": "https://github.com/sponsors/unifiedjs" - }, - { - "type": "OpenCollective", - "url": "https://opencollective.com/unified" - } - ], - "license": "MIT", - "dependencies": { - "micromark-util-symbol": "^2.0.0", - "micromark-util-types": "^2.0.0" - } - }, - "node_modules/micromark-util-encode": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/micromark-util-encode/-/micromark-util-encode-2.0.0.tgz", - "integrity": "sha512-pS+ROfCXAGLWCOc8egcBvT0kf27GoWMqtdarNfDcjb6YLuV5cM3ioG45Ys2qOVqeqSbjaKg72vU+Wby3eddPsA==", - "dev": true, - "funding": [ - { - "type": "GitHub Sponsors", - "url": "https://github.com/sponsors/unifiedjs" - }, - { - "type": "OpenCollective", - "url": "https://opencollective.com/unified" - } - ], - "license": "MIT" - }, - "node_modules/micromark-util-sanitize-uri": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/micromark-util-sanitize-uri/-/micromark-util-sanitize-uri-2.0.0.tgz", - "integrity": "sha512-WhYv5UEcZrbAtlsnPuChHUAsu/iBPOVaEVsntLBIdpibO0ddy8OzavZz3iL2xVvBZOpolujSliP65Kq0/7KIYw==", - "dev": true, - "funding": [ - { - "type": "GitHub Sponsors", - "url": "https://github.com/sponsors/unifiedjs" - }, - { - "type": "OpenCollective", - "url": "https://opencollective.com/unified" - } - ], - "license": "MIT", - "dependencies": { - "micromark-util-character": "^2.0.0", - "micromark-util-encode": "^2.0.0", - "micromark-util-symbol": "^2.0.0" - } - }, - "node_modules/micromark-util-symbol": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/micromark-util-symbol/-/micromark-util-symbol-2.0.0.tgz", - "integrity": "sha512-8JZt9ElZ5kyTnO94muPxIGS8oyElRJaiJO8EzV6ZSyGQ1Is8xwl4Q45qU5UOg+bGH4AikWziz0iN4sFLWs8PGw==", - "dev": true, - "funding": [ - { - "type": "GitHub Sponsors", - "url": "https://github.com/sponsors/unifiedjs" - }, - { - "type": "OpenCollective", - "url": "https://opencollective.com/unified" - } - ], - "license": "MIT" - }, - "node_modules/micromark-util-types": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/micromark-util-types/-/micromark-util-types-2.0.0.tgz", - "integrity": "sha512-oNh6S2WMHWRZrmutsRmDDfkzKtxF+bc2VxLC9dvtrDIRFln627VsFP6fLMgTryGDljgLPjkrzQSDcPrjPyDJ5w==", - "dev": true, - "funding": [ - { - "type": "GitHub Sponsors", - "url": "https://github.com/sponsors/unifiedjs" - }, - { - "type": "OpenCollective", - "url": "https://opencollective.com/unified" - } - ], - "license": "MIT" - }, "node_modules/micromatch": { "version": "4.0.8", "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.8.tgz", @@ -2169,19 +1790,6 @@ "node": ">=0.10.0" } }, - "node_modules/oniguruma-to-js": { - "version": "0.4.3", - "resolved": "https://registry.npmjs.org/oniguruma-to-js/-/oniguruma-to-js-0.4.3.tgz", - "integrity": "sha512-X0jWUcAlxORhOqqBREgPMgnshB7ZGYszBNspP+tS9hPD3l13CdaXcHbgImoHUHlrvGx/7AvFEkTRhAGYh+jzjQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "regex": "^4.3.2" - }, - "funding": { - "url": "https://github.com/sponsors/antfu" - } - }, "node_modules/optionator": { "version": "0.9.4", "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.9.4.tgz", @@ -2335,17 +1943,6 @@ "node": ">= 0.8.0" } }, - "node_modules/property-information": { - "version": "6.5.0", - "resolved": "https://registry.npmjs.org/property-information/-/property-information-6.5.0.tgz", - "integrity": "sha512-PgTgs/BlvHxOu8QuEN7wi5A0OmXaBcHpmCSTehcs6Uuu9IkDIEo13Hy7n898RHfrQ49vKCoGeWZSaAK01nwVig==", - "dev": true, - "license": "MIT", - "funding": { - "type": "github", - "url": "https://github.com/sponsors/wooorm" - } - }, "node_modules/punycode": { "version": "2.3.1", "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.1.tgz", @@ -2356,16 +1953,6 @@ "node": ">=6" } }, - "node_modules/punycode.js": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/punycode.js/-/punycode.js-2.3.1.tgz", - "integrity": "sha512-uxFIHU0YlHYhDQtV4R9J6a52SLx28BCjT+4ieh7IGbgwVJWO+km431c4yRlREUAsAmt/uMjQUyQHNEPf0M39CA==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=6" - } - }, "node_modules/queue-lit": { "version": "1.5.2", "resolved": "https://registry.npmjs.org/queue-lit/-/queue-lit-1.5.2.tgz", @@ -2410,13 +1997,6 @@ "node": ">=8.10.0" } }, - "node_modules/regex": { - "version": "4.3.3", - "resolved": "https://registry.npmjs.org/regex/-/regex-4.3.3.tgz", - "integrity": "sha512-r/AadFO7owAq1QJVeZ/nq9jNS1vyZt+6t1p/E59B56Rn2GCya+gr1KSyOzNL/er+r+B7phv5jG2xU2Nz1YkmJg==", - "dev": true, - "license": "MIT" - }, "node_modules/resolve-from": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz", @@ -2528,21 +2108,6 @@ "node": ">=8" } }, - "node_modules/shiki": { - "version": "1.22.0", - "resolved": "https://registry.npmjs.org/shiki/-/shiki-1.22.0.tgz", - "integrity": "sha512-/t5LlhNs+UOKQCYBtl5ZsH/Vclz73GIqT2yQsCBygr8L/ppTdmpL4w3kPLoZJbMKVWtoG77Ue1feOjZfDxvMkw==", - "dev": true, - "license": "MIT", - "dependencies": { - "@shikijs/core": "1.22.0", - "@shikijs/engine-javascript": "1.22.0", - "@shikijs/engine-oniguruma": "1.22.0", - "@shikijs/types": "1.22.0", - "@shikijs/vscode-textmate": "^9.3.0", - "@types/hast": "^3.0.4" - } - }, "node_modules/signal-exit": { "version": "4.1.0", "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-4.1.0.tgz", @@ -2566,17 +2131,6 @@ "node": ">=8" } }, - "node_modules/space-separated-tokens": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/space-separated-tokens/-/space-separated-tokens-2.0.2.tgz", - "integrity": "sha512-PEGlAwrG8yXGXRjW32fGbg66JAlOAwbObuqVoJpv/mRgoWDQfgH1wDPvtzWyUSNAXBGSk8h755YDbbcEy3SH2Q==", - "dev": true, - "license": "MIT", - "funding": { - "type": "github", - "url": "https://github.com/sponsors/wooorm" - } - }, "node_modules/string-width": { "version": "5.1.2", "resolved": "https://registry.npmjs.org/string-width/-/string-width-5.1.2.tgz", @@ -2641,21 +2195,6 @@ "node": ">=8" } }, - "node_modules/stringify-entities": { - "version": "4.0.4", - "resolved": "https://registry.npmjs.org/stringify-entities/-/stringify-entities-4.0.4.tgz", - "integrity": "sha512-IwfBptatlO+QCJUo19AqvrPNqlVMpW9YEL2LIVY+Rpv2qsjCGxaDLNRgeGsQWJhfItebuJhsGSLjaBbNSQ+ieg==", - "dev": true, - "license": "MIT", - "dependencies": { - "character-entities-html4": "^2.0.0", - "character-entities-legacy": "^3.0.0" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/wooorm" - } - }, "node_modules/strip-ansi": { "version": "7.1.0", "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.1.0.tgz", @@ -2742,17 +2281,6 @@ "node": ">=8.0" } }, - "node_modules/trim-lines": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/trim-lines/-/trim-lines-3.0.1.tgz", - "integrity": "sha512-kRj8B+YHZCc9kQYdWfJB2/oUl9rA99qbowYYBtr4ui4mZyAQ2JpvVBd/6U2YloATfqBhBTSMhTpgBHtU0Mf3Rg==", - "dev": true, - "license": "MIT", - "funding": { - "type": "github", - "url": "https://github.com/sponsors/wooorm" - } - }, "node_modules/ts-api-utils": { "version": "1.3.0", "resolved": "https://registry.npmjs.org/ts-api-utils/-/ts-api-utils-1.3.0.tgz", @@ -2861,45 +2389,6 @@ "node": ">= 0.8.0" } }, - "node_modules/typedoc": { - "version": "0.26.9", - "resolved": "https://registry.npmjs.org/typedoc/-/typedoc-0.26.9.tgz", - "integrity": "sha512-Rc7QpWL7EtmrT8yxV0GmhOR6xHgFnnhphbD9Suti3fz3um7ZOrou6q/g9d6+zC5PssTLZmjaW4Upmzv8T1rCcQ==", - "dev": true, - "license": "Apache-2.0", - "dependencies": { - "lunr": "^2.3.9", - "markdown-it": "^14.1.0", - "minimatch": "^9.0.5", - "shiki": "^1.16.2", - "yaml": "^2.5.1" - }, - "bin": { - "typedoc": "bin/typedoc" - }, - "engines": { - "node": ">= 18" - }, - "peerDependencies": { - "typescript": "4.6.x || 4.7.x || 4.8.x || 4.9.x || 5.0.x || 5.1.x || 5.2.x || 5.3.x || 5.4.x || 5.5.x || 5.6.x" - } - }, - "node_modules/typedoc/node_modules/minimatch": { - "version": "9.0.5", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.5.tgz", - "integrity": "sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow==", - "dev": true, - "license": "ISC", - "dependencies": { - "brace-expansion": "^2.0.1" - }, - "engines": { - "node": ">=16 || 14 >=14.17" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, "node_modules/typescript": { "version": "5.6.2", "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.6.2.tgz", @@ -2938,13 +2427,6 @@ } } }, - "node_modules/uc.micro": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/uc.micro/-/uc.micro-2.1.0.tgz", - "integrity": "sha512-ARDJmphmdvUk6Glw7y9DQ2bFkKBHwQHLi2lsaH6PPmz/Ka9sFOBsBluozhDltWmnv9u/cF6Rt87znRTPV+yp/A==", - "dev": true, - "license": "MIT" - }, "node_modules/undici-types": { "version": "6.19.8", "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-6.19.8.tgz", @@ -2952,79 +2434,6 @@ "dev": true, "license": "MIT" }, - "node_modules/unist-util-is": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/unist-util-is/-/unist-util-is-6.0.0.tgz", - "integrity": "sha512-2qCTHimwdxLfz+YzdGfkqNlH0tLi9xjTnHddPmJwtIG9MGsdbutfTc4P+haPD7l7Cjxf/WZj+we5qfVPvvxfYw==", - "dev": true, - "license": "MIT", - "dependencies": { - "@types/unist": "^3.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, - "node_modules/unist-util-position": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/unist-util-position/-/unist-util-position-5.0.0.tgz", - "integrity": "sha512-fucsC7HjXvkB5R3kTCO7kUjRdrS0BJt3M/FPxmHMBOm8JQi2BsHAHFsy27E0EolP8rp0NzXsJ+jNPyDWvOJZPA==", - "dev": true, - "license": "MIT", - "dependencies": { - "@types/unist": "^3.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, - "node_modules/unist-util-stringify-position": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/unist-util-stringify-position/-/unist-util-stringify-position-4.0.0.tgz", - "integrity": "sha512-0ASV06AAoKCDkS2+xw5RXJywruurpbC4JZSm7nr7MOt1ojAzvyyaO+UxZf18j8FCF6kmzCZKcAgN/yu2gm2XgQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "@types/unist": "^3.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, - "node_modules/unist-util-visit": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/unist-util-visit/-/unist-util-visit-5.0.0.tgz", - "integrity": "sha512-MR04uvD+07cwl/yhVuVWAtw+3GOR/knlL55Nd/wAdblk27GCVt3lqpTivy/tkJcZoNPzTwS1Y+KMojlLDhoTzg==", - "dev": true, - "license": "MIT", - "dependencies": { - "@types/unist": "^3.0.0", - "unist-util-is": "^6.0.0", - "unist-util-visit-parents": "^6.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, - "node_modules/unist-util-visit-parents": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/unist-util-visit-parents/-/unist-util-visit-parents-6.0.1.tgz", - "integrity": "sha512-L/PqWzfTP9lzzEa6CKs0k2nARxTdZduw3zyh8d2NVBnsyvHjSX4TWse388YrrQKbvI8w20fGjGlhgT96WwKykw==", - "dev": true, - "license": "MIT", - "dependencies": { - "@types/unist": "^3.0.0", - "unist-util-is": "^6.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, "node_modules/uri-js": { "version": "4.4.1", "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz", @@ -3042,36 +2451,6 @@ "dev": true, "license": "MIT" }, - "node_modules/vfile": { - "version": "6.0.3", - "resolved": "https://registry.npmjs.org/vfile/-/vfile-6.0.3.tgz", - "integrity": "sha512-KzIbH/9tXat2u30jf+smMwFCsno4wHVdNmzFyL+T/L3UGqqk6JKfVqOFOZEpZSHADH1k40ab6NUIXZq422ov3Q==", - "dev": true, - "license": "MIT", - "dependencies": { - "@types/unist": "^3.0.0", - "vfile-message": "^4.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, - "node_modules/vfile-message": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/vfile-message/-/vfile-message-4.0.2.tgz", - "integrity": "sha512-jRDZ1IMLttGj41KcZvlrYAaI3CfqpLpfpf+Mfig13viT6NKvRzWZ+lXz0Y5D60w6uJIBAOGq9mSHf0gktF0duw==", - "dev": true, - "license": "MIT", - "dependencies": { - "@types/unist": "^3.0.0", - "unist-util-stringify-position": "^4.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, "node_modules/which": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", @@ -3196,19 +2575,6 @@ "node": ">=8" } }, - "node_modules/yaml": { - "version": "2.6.0", - "resolved": "https://registry.npmjs.org/yaml/-/yaml-2.6.0.tgz", - "integrity": "sha512-a6ae//JvKDEra2kdi1qzCyrJW/WZCgFi8ydDV+eXExl95t+5R+ijnqHJbz9tmMh8FUjx3iv2fCQ4dclAQlO2UQ==", - "dev": true, - "license": "ISC", - "bin": { - "yaml": "bin.mjs" - }, - "engines": { - "node": ">= 14" - } - }, "node_modules/yn": { "version": "3.1.1", "resolved": "https://registry.npmjs.org/yn/-/yn-3.1.1.tgz", @@ -3231,17 +2597,6 @@ "funding": { "url": "https://github.com/sponsors/sindresorhus" } - }, - "node_modules/zwitch": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/zwitch/-/zwitch-2.0.4.tgz", - "integrity": "sha512-bXE4cR/kVZhKZX/RjPEflHaKVhUVl85noU3v6b8apfQEc1x4A+zBxjZ4lN8LqGd6WZ3dl98pY4o717VFmoPp+A==", - "dev": true, - "license": "MIT", - "funding": { - "type": "github", - "url": "https://github.com/sponsors/wooorm" - } } } } diff --git a/mlflow/package.json b/mlflow/package.json index ab0cdce2..1da1d00a 100644 --- a/mlflow/package.json +++ b/mlflow/package.json @@ -16,7 +16,7 @@ "build": "npm run clean && tsc -p tsconfig.json && tsc-alias -p tsconfig.json", "test": "", "lint": "eslint .", - "docs": "typedoc src/index.ts" + "docs": "" }, "keywords": [ "mlflow", @@ -36,7 +36,6 @@ "ts-node": "^10.9.2", "tsc-alias": "^1.8.10", "tsx": "^4.19.1", - "typedoc": "^0.26.9", "typescript": "^5.6.2", "typescript-eslint": "^8.8.0" }, diff --git a/mlflow/tsconfig.json b/mlflow/tsconfig.json index 44c5e84b..39b8395c 100644 --- a/mlflow/tsconfig.json +++ b/mlflow/tsconfig.json @@ -52,10 +52,6 @@ "removeComments": false, "allowJs": false }, - "typedocOptions": { - "entryPoints": ["src/index.ts"], - "out": "docs/documentation" - }, "include": ["src/**/*"], "exclude": ["node_modules", "**/*.spec.ts"], "tsc-alias": { diff --git a/mlflow/typedoc.json b/mlflow/typedoc.json deleted file mode 100644 index 507c52ca..00000000 --- a/mlflow/typedoc.json +++ /dev/null @@ -1,4 +0,0 @@ -{ - "entryPoints": ["src/index.ts"], - "out": "docs/documentation" -} \ No newline at end of file From 8fa0589adaec008e77f7455805b7e311568e12a2 Mon Sep 17 00:00:00 2001 From: Kyler-Chiago Date: Wed, 23 Oct 2024 18:27:43 -0700 Subject: [PATCH 204/357] Eslint fully passing now --- mlflow/tests/ExperimentClientTestFile.ts | 47 +++++++++++++---------- mlflow/tests/ExperimentManagerTestFile.ts | 4 +- 2 files changed, 28 insertions(+), 23 deletions(-) diff --git a/mlflow/tests/ExperimentClientTestFile.ts b/mlflow/tests/ExperimentClientTestFile.ts index c0857c37..8589e22f 100644 --- a/mlflow/tests/ExperimentClientTestFile.ts +++ b/mlflow/tests/ExperimentClientTestFile.ts @@ -8,28 +8,33 @@ const testCreateExperiment = async () => { const log = await experimentClient.createExperiment(name); return console.log(log); }; -// testCreateExperiment(); +testCreateExperiment(); const testSearchExperiment = async () => { const num1 = Math.random().toString().slice(2, 11); const name1 = `Search test ${num1}`; - const exp1 = await experimentClient.createExperiment(name1); + // Experiment 1 + await experimentClient.createExperiment(name1); const num2 = Math.random().toString().slice(2, 11); const name2 = `Search test ${num2}`; - const exp2 = await experimentClient.createExperiment(name2); + // Experiment 2 + await experimentClient.createExperiment(name2); const num3 = Math.random().toString().slice(2, 11); const name3 = `Search test ${num3}`; - const exp3 = await experimentClient.createExperiment(name3); + // Experiment 3 + await experimentClient.createExperiment(name3); const num4 = Math.random().toString().slice(2, 11); const name4 = `Search test ${num4}`; - const exp4 = await experimentClient.createExperiment(name4); + // Experiment 4 + await experimentClient.createExperiment(name4); const num5 = Math.random().toString().slice(2, 11); const name5 = `Search test ${num5}`; - const exp5 = await experimentClient.createExperiment(name5); + // Experiment 5 + await experimentClient.createExperiment(name5); const log = await experimentClient.searchExperiment( "name LIKE 'Search test%'", @@ -37,7 +42,7 @@ const testSearchExperiment = async () => { ); console.log(log); }; -// testSearchExperiment(); +testSearchExperiment(); const testGetExperiment = async () => { const num = Math.random().toString().slice(2, 11); @@ -46,28 +51,27 @@ const testGetExperiment = async () => { const log = await experimentClient.getExperiment(exp); console.log(log); }; -// testGetExperiment(); +testGetExperiment(); const testGetExperimentByName = async () => { const num = Math.random().toString().slice(2, 11); const name = `Test experiment ${num}`; - const exp = await experimentClient.createExperiment(name); + await experimentClient.createExperiment(name); const log = await experimentClient.getExperimentByName(name); console.log(log); }; -// testGetExperimentByName(); +testGetExperimentByName(); const testDeleteExperiment = async () => { const num = Math.random().toString().slice(2, 11); const name = `Test experiment ${num}`; const exp = await experimentClient.createExperiment(name); - const log = await experimentClient.deleteExperiment(exp); - // console.log(log); + await experimentClient.deleteExperiment(exp); const log2 = await experimentClient.getExperiment(exp); console.log(log2); experimentClient.restoreExperiment(exp); }; -// testDeleteExperiment(); +testDeleteExperiment(); const testRestoreExperiment = async () => { const num = Math.random().toString().slice(2, 11); @@ -75,14 +79,14 @@ const testRestoreExperiment = async () => { const exp = await experimentClient.createExperiment(name); const log = await experimentClient.getExperiment(exp); console.log(log); - const deleted = await experimentClient.deleteExperiment(exp); + await experimentClient.deleteExperiment(exp); const log2 = await experimentClient.getExperiment(exp); console.log(log2); - const log3 = await experimentClient.restoreExperiment(exp); + await experimentClient.restoreExperiment(exp); const log4 = await experimentClient.getExperiment(exp); console.log(log4); }; -// testRestoreExperiment(); +testRestoreExperiment(); const testUpdateExperiment = async () => { const num = Math.random().toString().slice(2, 11); @@ -90,15 +94,16 @@ const testUpdateExperiment = async () => { const exp = await experimentClient.createExperiment(name); const log = await experimentClient.getExperiment(exp); console.log(log); - const log2 = await experimentClient.updateExperiment( + await experimentClient.updateExperiment( exp, `${name}_UPDATED_NAME` ); const log3 = await experimentClient.getExperiment(exp); console.log(log3); - const revert = await experimentClient.updateExperiment(exp, name); + // Reverting to old name + await experimentClient.updateExperiment(exp, name); }; -// testUpdateExperiment(); +testUpdateExperiment(); const testSetExperimentTag = async () => { const num = Math.random().toString().slice(2, 11); @@ -107,7 +112,7 @@ const testSetExperimentTag = async () => { const log = await experimentClient.getExperiment(exp); console.log(log); const num2 = Math.random().toString().slice(2, 11); - const log2 = await experimentClient.setExperimentTag( + await experimentClient.setExperimentTag( exp, 'test_tag', `test_value_${num2}` @@ -115,4 +120,4 @@ const testSetExperimentTag = async () => { const log3 = await experimentClient.getExperiment(exp); console.log(log3); }; -// testSetExperimentTag(); +testSetExperimentTag(); diff --git a/mlflow/tests/ExperimentManagerTestFile.ts b/mlflow/tests/ExperimentManagerTestFile.ts index 5d60a80f..4851947b 100644 --- a/mlflow/tests/ExperimentManagerTestFile.ts +++ b/mlflow/tests/ExperimentManagerTestFile.ts @@ -51,7 +51,7 @@ const testRunExistingExperiment = async () => { ); return console.log(log); }; -// testRunExistingExperiment(); +testRunExistingExperiment(); const testRunNewExperiment = async () => { // define fake data for metrics, params, tags, and model @@ -97,7 +97,7 @@ const testRunNewExperiment = async () => { ); return console.log(log); }; -// testRunNewExperiment(); +testRunNewExperiment(); const testExperimentSummary = async () => { const log = await experimentManager.experimentSummary( From da6c4285cb7ca07abe98f2f246ab611b42760570 Mon Sep 17 00:00:00 2001 From: Yiqun Zheng <16813562+yiqunzheng@users.noreply.github.com> Date: Wed, 23 Oct 2024 19:03:08 -0700 Subject: [PATCH 205/357] Reset package-lock.json --- mlflow/examples/LinearRegressionExample.js | 315 ++++ mlflow/package-lock.json | 1937 ++++++++++++++------ mlflow/package.json | 3 + 3 files changed, 1709 insertions(+), 546 deletions(-) create mode 100644 mlflow/examples/LinearRegressionExample.js diff --git a/mlflow/examples/LinearRegressionExample.js b/mlflow/examples/LinearRegressionExample.js new file mode 100644 index 00000000..e2443b31 --- /dev/null +++ b/mlflow/examples/LinearRegressionExample.js @@ -0,0 +1,315 @@ +/** + * @fileoverview Example of using MLflow.js for machine learning experiment tracking + * This example demonstrates a simple linear regression model using TensorFlow.js + * with MLflow tracking. It showcases: + * - Experiment and run management + * - Hyperparameter logging + * - Metric tracking + * - Model versioning + * - Artifact storage + * + * The example creates a synthetic dataset and trains a linear regression model, + * tracking various metrics and parameters throughout the training process. + * + * @requires @tensorflow/tfjs-node + * @requires mlflow-js + * + * @note Ensure MLflow server is running at http://localhost:5001 before executing + */ + +import * as tf from '@tensorflow/tfjs-node'; +import MLflow from 'mlflow-js'; +import { fileURLToPath } from 'url'; +import { dirname } from 'path'; + +const mlflow = new MLflow('http://localhost:5001'); + +const HYPERPARAMETERS = { + learningRate: 0.1, + epochs: 10, + batchSize: 32, + validationSplit: 0.2, +}; + +const DATA_CONFIG = { + numSamples: 1000, + trainTestSplit: 0.7, + trueSlope: 2, + noiseStd: 0.1, +}; + +function generateData() { + // Generate synthetic data: y = 2x + noise + const x = tf.randomUniform([DATA_CONFIG.numSamples, 1]); + const y = tf.tidy(() => { + const trueValues = x.mul(DATA_CONFIG.trueSlope); + const noise = tf.randomNormal( + [DATA_CONFIG.numSamples, 1], + 0, + DATA_CONFIG.noiseStd + ); + return trueValues.add(noise); + }); + + // Split into train and test sets + const splitIdx = Math.floor( + DATA_CONFIG.numSamples * DATA_CONFIG.trainTestSplit + ); + const xTrain = x.slice([0, 0], [splitIdx, 1]); + const xTest = x.slice([splitIdx, 0], [-1, 1]); + const yTrain = y.slice([0, 0], [splitIdx, 1]); + const yTest = y.slice([splitIdx, 0], [-1, 1]); + + return { xTrain, yTrain, xTest, yTest }; +} + +function createModel() { + const model = tf.sequential({ + layers: [tf.layers.dense({ units: 1, inputShape: [1] })], + }); + + model.compile({ + optimizer: tf.train.sgd(HYPERPARAMETERS.learningRate), + loss: 'meanSquaredError', + metrics: ['mse', 'mae'], + }); + + return model; +} + +async function trainModel(model, xTrain, yTrain, runId) { + const history = await model.fit(xTrain, yTrain, { + epochs: HYPERPARAMETERS.epochs, + batchSize: HYPERPARAMETERS.batchSize, + validationSplit: HYPERPARAMETERS.validationSplit, + verbose: 1, + callbacks: { + onEpochEnd: async (epoch, logs) => { + // Log metrics for both training and validation + const metrics = [ + { + key: 'train_loss', + value: logs.loss, + timestamp: Date.now(), + step: epoch, + }, + { + key: 'train_mse', + value: logs.mse, + timestamp: Date.now(), + step: epoch, + }, + { + key: 'train_mae', + value: logs.mae, + timestamp: Date.now(), + step: epoch, + }, + { + key: 'val_loss', + value: logs.val_loss, + timestamp: Date.now(), + step: epoch, + }, + { + key: 'val_mse', + value: logs.val_mse, + timestamp: Date.now(), + step: epoch, + }, + { + key: 'val_mae', + value: logs.val_mae, + timestamp: Date.now(), + step: epoch, + }, + ]; + + await mlflow.logBatch(runId, metrics); + }, + }, + }); + + return history; +} + +function evaluateModel(model, xTest, yTest) { + return tf.tidy(() => { + const yPred = model.predict(xTest); + + // Evaluation Metrics + const mse = tf.metrics.meanSquaredError(yTest, yPred).dataSync()[0]; + const rmse = Math.sqrt(mse); + const mae = tf.metrics.meanAbsoluteError(yTest, yPred).dataSync()[0]; + + // R-squared + const yMean = tf.mean(yTest); + const totalSS = yTest.sub(yMean).square().sum().dataSync()[0]; + const residualSS = yTest.sub(yPred).square().sum().dataSync()[0]; + const r2 = 1 - residualSS / totalSS; + + // Model Parameters + const weight = model.layers[0].getWeights()[0].dataSync()[0]; + const bias = model.layers[0].getWeights()[1].dataSync()[0]; + + return { + metrics: { + mse, + rmse, + mae, + r2, + }, + parameters: { + weight, + bias, + }, + }; + }); +} + +async function main() { + try { + // Initialize experiment + const experimentName = 'Linear_Regression_Example'; + let experimentId; + try { + const experiment = await mlflow.getExperimentByName(experimentName); + experimentId = experiment.experiment_id; + } catch { + experimentId = await mlflow.createExperiment(experimentName); + } + console.log(`MLflow Experiment ID: ${experimentId}`); + + // Create run + const run = await mlflow.createRun( + experimentId, + 'Simple Linear Regression' + ); + const runId = run.info.run_id; + console.log(`MLflow Run ID: ${runId}`); + + // Log hyperparameters + const params = [ + { key: 'learning_rate', value: HYPERPARAMETERS.learningRate.toString() }, + { key: 'epochs', value: HYPERPARAMETERS.epochs.toString() }, + { key: 'batch_size', value: HYPERPARAMETERS.batchSize.toString() }, + { + key: 'validation_split', + value: HYPERPARAMETERS.validationSplit.toString(), + }, + { key: 'train_test_split', value: DATA_CONFIG.trainTestSplit.toString() }, + { key: 'num_samples', value: DATA_CONFIG.numSamples.toString() }, + ]; + await mlflow.logBatch(runId, undefined, params); + + // Log dataset info + const datasetInfo = { + dataset: { + name: 'synthetic_linear_regression_data', + }, + }; + await mlflow.logInputs(runId, [datasetInfo]); + + // Generate and prepare data + console.log('Generating data...'); + const { xTrain, yTrain, xTest, yTest } = generateData(); + + // Train model + console.log('Creating and training model...'); + const model = createModel(); + const history = await trainModel(model, xTrain, yTrain, runId); + + // Evaluate model + const evaluation = evaluateModel(model, xTest, yTest); + + // Save model artifects + const __filename = fileURLToPath(import.meta.url); + const __dirname = dirname(__filename); + const artifactsPath = `${__dirname}/../mlruns/${experimentId}/${runId}/artifacts`; + await model.save(`file://${artifactsPath}`); + + // Log evaluation metrics + const finalMetrics = [ + { key: 'test_mse', value: evaluation.metrics.mse, timestamp: Date.now() }, + { + key: 'test_rmse', + value: evaluation.metrics.rmse, + timestamp: Date.now(), + }, + { key: 'test_mae', value: evaluation.metrics.mae, timestamp: Date.now() }, + { key: 'test_r2', value: evaluation.metrics.r2, timestamp: Date.now() }, + ]; + await mlflow.logBatch(runId, finalMetrics); + + // Log model parameters + const paramTags = [ + { key: 'model_weight', value: evaluation.parameters.weight.toString() }, + { key: 'model_bias', value: evaluation.parameters.bias.toString() }, + ]; + await mlflow.logBatch(runId, undefined, undefined, paramTags); + + // Register model if performance meets threshold + if (evaluation.metrics.r2 > 0.9) { + const modelName = 'LinearRegression'; + try { + let modelExists = true; + try { + await mlflow.getRegisteredModel(modelName); + } catch (err) { + modelExists = false; + } + + if (!modelExists) { + await mlflow.createRegisteredModel( + modelName, + [{ key: 'task', value: 'regression' }], + 'Simple linear regression model' + ); + } + + const modelVersion = await mlflow.createModelVersion( + modelName, + `runs:/${runId}/model`, + runId, + [ + { key: 'r2', value: evaluation.metrics.r2.toString() }, + { key: 'rmse', value: evaluation.metrics.rmse.toString() }, + ] + ); + + if (evaluation.metrics.r2 > 0.95) { + await mlflow.transitionModelVersionStage( + modelName, + modelVersion.version, + 'staging', + true + ); + } + } catch (e) { + console.error('Model registration error:', e.message); + } + } + + // Log additional metadata + const tags = [ + { key: 'model_type', value: 'linear_regression' }, + { key: 'data_source', value: 'synthetic' }, + ]; + await mlflow.logBatch(runId, undefined, undefined, tags); + + // Finish run + await mlflow.updateRun(runId, 'FINISHED'); + + // Cleanup + tf.dispose([xTrain, yTrain, xTest, yTest]); + + console.log('\nMLflow tracking completed successfully!'); + console.log( + `View run details at http://localhost:5001/#/experiments/${experimentId}/runs/${runId}` + ); + } catch (error) { + console.error('Error:', error); + } +} + +main(); diff --git a/mlflow/package-lock.json b/mlflow/package-lock.json index a21f38fe..8288f448 100644 --- a/mlflow/package-lock.json +++ b/mlflow/package-lock.json @@ -8,6 +8,9 @@ "name": "mlflow-js", "version": "1.0.0", "license": "MIT", + "dependencies": { + "@tensorflow/tfjs-node": "^4.22.0" + }, "devDependencies": { "@eslint/js": "^9.12.0", "@types/eslint__js": "^8.42.3", @@ -500,34 +503,10 @@ "node": "^18.18.0 || ^20.9.0 || >=21.1.0" } }, - "node_modules/@eslint/config-array/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, - "license": "MIT", - "dependencies": { - "balanced-match": "^1.0.0", - "concat-map": "0.0.1" - } - }, - "node_modules/@eslint/config-array/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, - "license": "ISC", - "dependencies": { - "brace-expansion": "^1.1.7" - }, - "engines": { - "node": "*" - } - }, "node_modules/@eslint/core": { - "version": "0.6.0", - "resolved": "https://registry.npmjs.org/@eslint/core/-/core-0.6.0.tgz", - "integrity": "sha512-8I2Q8ykA4J0x0o7cg67FPVnehcqWTBehu/lmY+bolPFHGjh49YzGBMXTvpqVgEbBdvNCSxj6iFgiIyHzf03lzg==", + "version": "0.7.0", + "resolved": "https://registry.npmjs.org/@eslint/core/-/core-0.7.0.tgz", + "integrity": "sha512-xp5Jirz5DyPYlPiKat8jaq0EmYvDXKKpzTbxXMpT9eqlRJkRKIz9AGMdlvYjih+im+QlhWrpvVjl8IPC/lHlUw==", "dev": true, "license": "Apache-2.0", "engines": { @@ -558,34 +537,10 @@ "url": "https://opencollective.com/eslint" } }, - "node_modules/@eslint/eslintrc/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, - "license": "MIT", - "dependencies": { - "balanced-match": "^1.0.0", - "concat-map": "0.0.1" - } - }, - "node_modules/@eslint/eslintrc/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, - "license": "ISC", - "dependencies": { - "brace-expansion": "^1.1.7" - }, - "engines": { - "node": "*" - } - }, "node_modules/@eslint/js": { - "version": "9.12.0", - "resolved": "https://registry.npmjs.org/@eslint/js/-/js-9.12.0.tgz", - "integrity": "sha512-eohesHH8WFRUprDNyEREgqP6beG6htMeUYeCpkEgBCieCMme5r9zFWjzAJp//9S+Kub4rqE+jXe9Cp1a7IYIIA==", + "version": "9.13.0", + "resolved": "https://registry.npmjs.org/@eslint/js/-/js-9.13.0.tgz", + "integrity": "sha512-IFLyoY4d72Z5y/6o/BazFBezupzI/taV8sGumxTAVw3lXG9A6md1Dc34T9s1FoD/an9pJH8RHbAxsaEbBed9lA==", "dev": true, "license": "MIT", "engines": { @@ -603,9 +558,9 @@ } }, "node_modules/@eslint/plugin-kit": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/@eslint/plugin-kit/-/plugin-kit-0.2.0.tgz", - "integrity": "sha512-vH9PiIMMwvhCx31Af3HiGzsVNULDbyVkHXwlemn/B0TFj/00ho3y55efXrUZTfQipxoHC5u4xq6zblww1zm1Ig==", + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/@eslint/plugin-kit/-/plugin-kit-0.2.1.tgz", + "integrity": "sha512-HFZ4Mp26nbWk9d/BpvP0YNL6W4UoZF0VFcTw/aPPA8RpOxeFQgK+ClABGgAUXs9Y/RGX/l1vOmrqz1MQt9MNuw==", "dev": true, "license": "Apache-2.0", "dependencies": { @@ -685,6 +640,60 @@ "node": ">=12" } }, + "node_modules/@isaacs/cliui/node_modules/ansi-regex": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.1.0.tgz", + "integrity": "sha512-7HSX4QQb4CspciLpVFwyRe79O3xsIZDDLER21kERQ71oaPodF8jL725AgJMFAYbooIqolJoRLuM81SpeUkpkvA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/ansi-regex?sponsor=1" + } + }, + "node_modules/@isaacs/cliui/node_modules/emoji-regex": { + "version": "9.2.2", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-9.2.2.tgz", + "integrity": "sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==", + "dev": true, + "license": "MIT" + }, + "node_modules/@isaacs/cliui/node_modules/string-width": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-5.1.2.tgz", + "integrity": "sha512-HnLOCR3vjcY8beoNLtcjZ5/nxn2afmME6lhrDrebokqMap+XbeW8n9TXpPDOqdGK5qcI3oT0GKTW6wC7EMiVqA==", + "dev": true, + "license": "MIT", + "dependencies": { + "eastasianwidth": "^0.2.0", + "emoji-regex": "^9.2.2", + "strip-ansi": "^7.0.1" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/@isaacs/cliui/node_modules/strip-ansi": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.1.0.tgz", + "integrity": "sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-regex": "^6.0.1" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/strip-ansi?sponsor=1" + } + }, "node_modules/@jridgewell/resolve-uri": { "version": "3.1.2", "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.2.tgz", @@ -713,15 +722,94 @@ "@jridgewell/sourcemap-codec": "^1.4.10" } }, + "node_modules/@mapbox/node-pre-gyp": { + "version": "1.0.9", + "resolved": "https://registry.npmjs.org/@mapbox/node-pre-gyp/-/node-pre-gyp-1.0.9.tgz", + "integrity": "sha512-aDF3S3rK9Q2gey/WAttUlISduDItz5BU3306M9Eyv6/oS40aMprnopshtlKTykxRNIBEZuRMaZAnbrQ4QtKGyw==", + "license": "BSD-3-Clause", + "dependencies": { + "detect-libc": "^2.0.0", + "https-proxy-agent": "^5.0.0", + "make-dir": "^3.1.0", + "node-fetch": "^2.6.7", + "nopt": "^5.0.0", + "npmlog": "^5.0.1", + "rimraf": "^3.0.2", + "semver": "^7.3.5", + "tar": "^6.1.11" + }, + "bin": { + "node-pre-gyp": "bin/node-pre-gyp" + } + }, + "node_modules/@mapbox/node-pre-gyp/node_modules/agent-base": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-6.0.2.tgz", + "integrity": "sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ==", + "license": "MIT", + "dependencies": { + "debug": "4" + }, + "engines": { + "node": ">= 6.0.0" + } + }, + "node_modules/@mapbox/node-pre-gyp/node_modules/glob": { + "version": "7.2.3", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", + "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", + "deprecated": "Glob versions prior to v9 are no longer supported", + "license": "ISC", + "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/@mapbox/node-pre-gyp/node_modules/https-proxy-agent": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-5.0.1.tgz", + "integrity": "sha512-dFcAjpTQFgoLMzC2VwU+C/CbS7uRL0lWmxDITmqm7C+7F0Odmj6s9l6alZc6AELXhrnggM2CeWSXHGOdX2YtwA==", + "license": "MIT", + "dependencies": { + "agent-base": "6", + "debug": "4" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/@mapbox/node-pre-gyp/node_modules/rimraf": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", + "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==", + "deprecated": "Rimraf versions prior to v4 are no longer supported", + "license": "ISC", + "dependencies": { + "glob": "^7.1.3" + }, + "bin": { + "rimraf": "bin.js" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, "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, -<<<<<<< HEAD -======= "license": "MIT", ->>>>>>> dev "dependencies": { "@nodelib/fs.stat": "2.0.5", "run-parallel": "^1.1.9" @@ -735,10 +823,7 @@ "resolved": "https://registry.npmjs.org/@nodelib/fs.stat/-/fs.stat-2.0.5.tgz", "integrity": "sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==", "dev": true, -<<<<<<< HEAD -======= "license": "MIT", ->>>>>>> dev "engines": { "node": ">= 8" } @@ -748,10 +833,7 @@ "resolved": "https://registry.npmjs.org/@nodelib/fs.walk/-/fs.walk-1.2.8.tgz", "integrity": "sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==", "dev": true, -<<<<<<< HEAD -======= "license": "MIT", ->>>>>>> dev "dependencies": { "@nodelib/fs.scandir": "2.1.5", "fastq": "^1.6.0" @@ -760,8 +842,6 @@ "node": ">= 8" } }, -<<<<<<< HEAD -======= "node_modules/@shikijs/core": { "version": "1.22.0", "resolved": "https://registry.npmjs.org/@shikijs/core/-/core-1.22.0.tgz", @@ -818,7 +898,213 @@ "dev": true, "license": "MIT" }, ->>>>>>> dev + "node_modules/@tensorflow/tfjs": { + "version": "4.22.0", + "resolved": "https://registry.npmjs.org/@tensorflow/tfjs/-/tfjs-4.22.0.tgz", + "integrity": "sha512-0TrIrXs6/b7FLhLVNmfh8Sah6JgjBPH4mZ8JGb7NU6WW+cx00qK5BcAZxw7NCzxj6N8MRAIfHq+oNbPUNG5VAg==", + "license": "Apache-2.0", + "dependencies": { + "@tensorflow/tfjs-backend-cpu": "4.22.0", + "@tensorflow/tfjs-backend-webgl": "4.22.0", + "@tensorflow/tfjs-converter": "4.22.0", + "@tensorflow/tfjs-core": "4.22.0", + "@tensorflow/tfjs-data": "4.22.0", + "@tensorflow/tfjs-layers": "4.22.0", + "argparse": "^1.0.10", + "chalk": "^4.1.0", + "core-js": "3.29.1", + "regenerator-runtime": "^0.13.5", + "yargs": "^16.0.3" + }, + "bin": { + "tfjs-custom-module": "dist/tools/custom_module/cli.js" + } + }, + "node_modules/@tensorflow/tfjs-backend-cpu": { + "version": "4.22.0", + "resolved": "https://registry.npmjs.org/@tensorflow/tfjs-backend-cpu/-/tfjs-backend-cpu-4.22.0.tgz", + "integrity": "sha512-1u0FmuLGuRAi8D2c3cocHTASGXOmHc/4OvoVDENJayjYkS119fcTcQf4iHrtLthWyDIPy3JiPhRrZQC9EwnhLw==", + "license": "Apache-2.0", + "dependencies": { + "@types/seedrandom": "^2.4.28", + "seedrandom": "^3.0.5" + }, + "engines": { + "yarn": ">= 1.3.2" + }, + "peerDependencies": { + "@tensorflow/tfjs-core": "4.22.0" + } + }, + "node_modules/@tensorflow/tfjs-backend-webgl": { + "version": "4.22.0", + "resolved": "https://registry.npmjs.org/@tensorflow/tfjs-backend-webgl/-/tfjs-backend-webgl-4.22.0.tgz", + "integrity": "sha512-H535XtZWnWgNwSzv538czjVlbJebDl5QTMOth4RXr2p/kJ1qSIXE0vZvEtO+5EC9b00SvhplECny2yDewQb/Yg==", + "license": "Apache-2.0", + "dependencies": { + "@tensorflow/tfjs-backend-cpu": "4.22.0", + "@types/offscreencanvas": "~2019.3.0", + "@types/seedrandom": "^2.4.28", + "seedrandom": "^3.0.5" + }, + "engines": { + "yarn": ">= 1.3.2" + }, + "peerDependencies": { + "@tensorflow/tfjs-core": "4.22.0" + } + }, + "node_modules/@tensorflow/tfjs-converter": { + "version": "4.22.0", + "resolved": "https://registry.npmjs.org/@tensorflow/tfjs-converter/-/tfjs-converter-4.22.0.tgz", + "integrity": "sha512-PT43MGlnzIo+YfbsjM79Lxk9lOq6uUwZuCc8rrp0hfpLjF6Jv8jS84u2jFb+WpUeuF4K33ZDNx8CjiYrGQ2trQ==", + "license": "Apache-2.0", + "peerDependencies": { + "@tensorflow/tfjs-core": "4.22.0" + } + }, + "node_modules/@tensorflow/tfjs-core": { + "version": "4.22.0", + "resolved": "https://registry.npmjs.org/@tensorflow/tfjs-core/-/tfjs-core-4.22.0.tgz", + "integrity": "sha512-LEkOyzbknKFoWUwfkr59vSB68DMJ4cjwwHgicXN0DUi3a0Vh1Er3JQqCI1Hl86GGZQvY8ezVrtDIvqR1ZFW55A==", + "license": "Apache-2.0", + "dependencies": { + "@types/long": "^4.0.1", + "@types/offscreencanvas": "~2019.7.0", + "@types/seedrandom": "^2.4.28", + "@webgpu/types": "0.1.38", + "long": "4.0.0", + "node-fetch": "~2.6.1", + "seedrandom": "^3.0.5" + }, + "engines": { + "yarn": ">= 1.3.2" + } + }, + "node_modules/@tensorflow/tfjs-core/node_modules/@types/offscreencanvas": { + "version": "2019.7.3", + "resolved": "https://registry.npmjs.org/@types/offscreencanvas/-/offscreencanvas-2019.7.3.tgz", + "integrity": "sha512-ieXiYmgSRXUDeOntE1InxjWyvEelZGP63M+cGuquuRLuIKKT1osnkXjxev9B7d1nXSug5vpunx+gNlbVxMlC9A==", + "license": "MIT" + }, + "node_modules/@tensorflow/tfjs-core/node_modules/node-fetch": { + "version": "2.6.13", + "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.6.13.tgz", + "integrity": "sha512-StxNAxh15zr77QvvkmveSQ8uCQ4+v5FkvNTj0OESmiHu+VRi/gXArXtkWMElOsOUNLtUEvI4yS+rdtOHZTwlQA==", + "license": "MIT", + "dependencies": { + "whatwg-url": "^5.0.0" + }, + "engines": { + "node": "4.x || >=6.0.0" + }, + "peerDependencies": { + "encoding": "^0.1.0" + }, + "peerDependenciesMeta": { + "encoding": { + "optional": true + } + } + }, + "node_modules/@tensorflow/tfjs-data": { + "version": "4.22.0", + "resolved": "https://registry.npmjs.org/@tensorflow/tfjs-data/-/tfjs-data-4.22.0.tgz", + "integrity": "sha512-dYmF3LihQIGvtgJrt382hSRH4S0QuAp2w1hXJI2+kOaEqo5HnUPG0k5KA6va+S1yUhx7UBToUKCBHeLHFQRV4w==", + "license": "Apache-2.0", + "dependencies": { + "@types/node-fetch": "^2.1.2", + "node-fetch": "~2.6.1", + "string_decoder": "^1.3.0" + }, + "peerDependencies": { + "@tensorflow/tfjs-core": "4.22.0", + "seedrandom": "^3.0.5" + } + }, + "node_modules/@tensorflow/tfjs-data/node_modules/node-fetch": { + "version": "2.6.13", + "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.6.13.tgz", + "integrity": "sha512-StxNAxh15zr77QvvkmveSQ8uCQ4+v5FkvNTj0OESmiHu+VRi/gXArXtkWMElOsOUNLtUEvI4yS+rdtOHZTwlQA==", + "license": "MIT", + "dependencies": { + "whatwg-url": "^5.0.0" + }, + "engines": { + "node": "4.x || >=6.0.0" + }, + "peerDependencies": { + "encoding": "^0.1.0" + }, + "peerDependenciesMeta": { + "encoding": { + "optional": true + } + } + }, + "node_modules/@tensorflow/tfjs-layers": { + "version": "4.22.0", + "resolved": "https://registry.npmjs.org/@tensorflow/tfjs-layers/-/tfjs-layers-4.22.0.tgz", + "integrity": "sha512-lybPj4ZNj9iIAPUj7a8ZW1hg8KQGfqWLlCZDi9eM/oNKCCAgchiyzx8OrYoWmRrB+AM6VNEeIT+2gZKg5ReihA==", + "license": "Apache-2.0 AND MIT", + "peerDependencies": { + "@tensorflow/tfjs-core": "4.22.0" + } + }, + "node_modules/@tensorflow/tfjs-node": { + "version": "4.22.0", + "resolved": "https://registry.npmjs.org/@tensorflow/tfjs-node/-/tfjs-node-4.22.0.tgz", + "integrity": "sha512-uHrXeUlfgkMxTZqHkESSV7zSdKdV0LlsBeblqkuKU9nnfxB1pC6DtoyYVaLxznzZy7WQSegjcohxxCjAf6Dc7w==", + "hasInstallScript": true, + "license": "Apache-2.0", + "dependencies": { + "@mapbox/node-pre-gyp": "1.0.9", + "@tensorflow/tfjs": "4.22.0", + "adm-zip": "^0.5.2", + "google-protobuf": "^3.9.2", + "https-proxy-agent": "^2.2.1", + "progress": "^2.0.0", + "rimraf": "^2.6.2", + "tar": "^6.2.1" + }, + "engines": { + "node": ">=8.11.0" + } + }, + "node_modules/@tensorflow/tfjs-node/node_modules/glob": { + "version": "7.2.3", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", + "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", + "deprecated": "Glob versions prior to v9 are no longer supported", + "license": "ISC", + "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/@tensorflow/tfjs-node/node_modules/rimraf": { + "version": "2.7.1", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.7.1.tgz", + "integrity": "sha512-uWjbaKIK3T1OSVptzX7Nl6PvQ3qAGtKEtVRjRuazjfL3Bx5eI409VZSqgND+4UNnmzLVdPj9FqFJNPqBZFve4w==", + "deprecated": "Rimraf versions prior to v4 are no longer supported", + "license": "ISC", + "dependencies": { + "glob": "^7.1.3" + }, + "bin": { + "rimraf": "bin.js" + } + }, "node_modules/@tsconfig/node10": { "version": "1.0.11", "resolved": "https://registry.npmjs.org/@tsconfig/node10/-/node10-1.0.11.tgz", @@ -892,6 +1178,12 @@ "dev": true, "license": "MIT" }, + "node_modules/@types/long": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/@types/long/-/long-4.0.2.tgz", + "integrity": "sha512-MqTGEo5bj5t157U6fA/BiDynNkn0YknVdh48CMPkTSpFTVmvao5UQmm7uEF6xBEo7qIMAlY/JSleYaE6VOdpaA==", + "license": "MIT" + }, "node_modules/@types/mdast": { "version": "4.0.4", "resolved": "https://registry.npmjs.org/@types/mdast/-/mdast-4.0.4.tgz", @@ -903,15 +1195,36 @@ } }, "node_modules/@types/node": { - "version": "22.7.4", - "resolved": "https://registry.npmjs.org/@types/node/-/node-22.7.4.tgz", - "integrity": "sha512-y+NPi1rFzDs1NdQHHToqeiX2TIS79SWEAw9GYhkkx8bD0ChpfqC+n2j5OXOCpzfojBEBt6DnEnnG9MY0zk1XLg==", - "dev": true, + "version": "22.7.9", + "resolved": "https://registry.npmjs.org/@types/node/-/node-22.7.9.tgz", + "integrity": "sha512-jrTfRC7FM6nChvU7X2KqcrgquofrWLFDeYC1hKfwNWomVvrn7JIksqf344WN2X/y8xrgqBd2dJATZV4GbatBfg==", "license": "MIT", "dependencies": { "undici-types": "~6.19.2" } }, + "node_modules/@types/node-fetch": { + "version": "2.6.11", + "resolved": "https://registry.npmjs.org/@types/node-fetch/-/node-fetch-2.6.11.tgz", + "integrity": "sha512-24xFj9R5+rfQJLRyM56qh+wnVSYhyXC2tkoBndtY0U+vubqNsYXGjufB2nn8Q6gt0LrARwL6UBtMCSVCwl4B1g==", + "license": "MIT", + "dependencies": { + "@types/node": "*", + "form-data": "^4.0.0" + } + }, + "node_modules/@types/offscreencanvas": { + "version": "2019.3.0", + "resolved": "https://registry.npmjs.org/@types/offscreencanvas/-/offscreencanvas-2019.3.0.tgz", + "integrity": "sha512-esIJx9bQg+QYF0ra8GnvfianIY8qWB0GBx54PK5Eps6m+xTj86KLavHv6qDhzKcu5UUOgNfJ2pWaIIV7TRUd9Q==", + "license": "MIT" + }, + "node_modules/@types/seedrandom": { + "version": "2.4.34", + "resolved": "https://registry.npmjs.org/@types/seedrandom/-/seedrandom-2.4.34.tgz", + "integrity": "sha512-ytDiArvrn/3Xk6/vtylys5tlY6eo7Ane0hvcx++TKo6RxQXuVfW0AF/oeWqAj9dN29SyhtawuXstgmPlwNcv/A==", + "license": "MIT" + }, "node_modules/@types/unist": { "version": "3.0.3", "resolved": "https://registry.npmjs.org/@types/unist/-/unist-3.0.3.tgz", @@ -920,17 +1233,17 @@ "license": "MIT" }, "node_modules/@typescript-eslint/eslint-plugin": { - "version": "8.8.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-8.8.0.tgz", - "integrity": "sha512-wORFWjU30B2WJ/aXBfOm1LX9v9nyt9D3jsSOxC3cCaTQGCW5k4jNpmjFv3U7p/7s4yvdjHzwtv2Sd2dOyhjS0A==", + "version": "8.11.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-8.11.0.tgz", + "integrity": "sha512-KhGn2LjW1PJT2A/GfDpiyOfS4a8xHQv2myUagTM5+zsormOmBlYsnQ6pobJ8XxJmh6hnHwa2Mbe3fPrDJoDhbA==", "dev": true, "license": "MIT", "dependencies": { "@eslint-community/regexpp": "^4.10.0", - "@typescript-eslint/scope-manager": "8.8.0", - "@typescript-eslint/type-utils": "8.8.0", - "@typescript-eslint/utils": "8.8.0", - "@typescript-eslint/visitor-keys": "8.8.0", + "@typescript-eslint/scope-manager": "8.11.0", + "@typescript-eslint/type-utils": "8.11.0", + "@typescript-eslint/utils": "8.11.0", + "@typescript-eslint/visitor-keys": "8.11.0", "graphemer": "^1.4.0", "ignore": "^5.3.1", "natural-compare": "^1.4.0", @@ -954,16 +1267,16 @@ } }, "node_modules/@typescript-eslint/parser": { - "version": "8.8.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-8.8.0.tgz", - "integrity": "sha512-uEFUsgR+tl8GmzmLjRqz+VrDv4eoaMqMXW7ruXfgThaAShO9JTciKpEsB+TvnfFfbg5IpujgMXVV36gOJRLtZg==", + "version": "8.11.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-8.11.0.tgz", + "integrity": "sha512-lmt73NeHdy1Q/2ul295Qy3uninSqi6wQI18XwSpm8w0ZbQXUpjCAWP1Vlv/obudoBiIjJVjlztjQ+d/Md98Yxg==", "dev": true, "license": "BSD-2-Clause", "dependencies": { - "@typescript-eslint/scope-manager": "8.8.0", - "@typescript-eslint/types": "8.8.0", - "@typescript-eslint/typescript-estree": "8.8.0", - "@typescript-eslint/visitor-keys": "8.8.0", + "@typescript-eslint/scope-manager": "8.11.0", + "@typescript-eslint/types": "8.11.0", + "@typescript-eslint/typescript-estree": "8.11.0", + "@typescript-eslint/visitor-keys": "8.11.0", "debug": "^4.3.4" }, "engines": { @@ -983,14 +1296,14 @@ } }, "node_modules/@typescript-eslint/scope-manager": { - "version": "8.8.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-8.8.0.tgz", - "integrity": "sha512-EL8eaGC6gx3jDd8GwEFEV091210U97J0jeEHrAYvIYosmEGet4wJ+g0SYmLu+oRiAwbSA5AVrt6DxLHfdd+bUg==", + "version": "8.11.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-8.11.0.tgz", + "integrity": "sha512-Uholz7tWhXmA4r6epo+vaeV7yjdKy5QFCERMjs1kMVsLRKIrSdM6o21W2He9ftp5PP6aWOVpD5zvrvuHZC0bMQ==", "dev": true, "license": "MIT", "dependencies": { - "@typescript-eslint/types": "8.8.0", - "@typescript-eslint/visitor-keys": "8.8.0" + "@typescript-eslint/types": "8.11.0", + "@typescript-eslint/visitor-keys": "8.11.0" }, "engines": { "node": "^18.18.0 || ^20.9.0 || >=21.1.0" @@ -1001,14 +1314,14 @@ } }, "node_modules/@typescript-eslint/type-utils": { - "version": "8.8.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-8.8.0.tgz", - "integrity": "sha512-IKwJSS7bCqyCeG4NVGxnOP6lLT9Okc3Zj8hLO96bpMkJab+10HIfJbMouLrlpyOr3yrQ1cA413YPFiGd1mW9/Q==", + "version": "8.11.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-8.11.0.tgz", + "integrity": "sha512-ItiMfJS6pQU0NIKAaybBKkuVzo6IdnAhPFZA/2Mba/uBjuPQPet/8+zh5GtLHwmuFRShZx+8lhIs7/QeDHflOg==", "dev": true, "license": "MIT", "dependencies": { - "@typescript-eslint/typescript-estree": "8.8.0", - "@typescript-eslint/utils": "8.8.0", + "@typescript-eslint/typescript-estree": "8.11.0", + "@typescript-eslint/utils": "8.11.0", "debug": "^4.3.4", "ts-api-utils": "^1.3.0" }, @@ -1026,9 +1339,9 @@ } }, "node_modules/@typescript-eslint/types": { - "version": "8.8.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-8.8.0.tgz", - "integrity": "sha512-QJwc50hRCgBd/k12sTykOJbESe1RrzmX6COk8Y525C9l7oweZ+1lw9JiU56im7Amm8swlz00DRIlxMYLizr2Vw==", + "version": "8.11.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-8.11.0.tgz", + "integrity": "sha512-tn6sNMHf6EBAYMvmPUaKaVeYvhUsrE6x+bXQTxjQRp360h1giATU0WvgeEys1spbvb5R+VpNOZ+XJmjD8wOUHw==", "dev": true, "license": "MIT", "engines": { @@ -1040,14 +1353,14 @@ } }, "node_modules/@typescript-eslint/typescript-estree": { - "version": "8.8.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-8.8.0.tgz", - "integrity": "sha512-ZaMJwc/0ckLz5DaAZ+pNLmHv8AMVGtfWxZe/x2JVEkD5LnmhWiQMMcYT7IY7gkdJuzJ9P14fRy28lUrlDSWYdw==", + "version": "8.11.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-8.11.0.tgz", + "integrity": "sha512-yHC3s1z1RCHoCz5t06gf7jH24rr3vns08XXhfEqzYpd6Hll3z/3g23JRi0jM8A47UFKNc3u/y5KIMx8Ynbjohg==", "dev": true, "license": "BSD-2-Clause", "dependencies": { - "@typescript-eslint/types": "8.8.0", - "@typescript-eslint/visitor-keys": "8.8.0", + "@typescript-eslint/types": "8.11.0", + "@typescript-eslint/visitor-keys": "8.11.0", "debug": "^4.3.4", "fast-glob": "^3.3.2", "is-glob": "^4.0.3", @@ -1068,6 +1381,16 @@ } } }, + "node_modules/@typescript-eslint/typescript-estree/node_modules/brace-expansion": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", + "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", + "dev": true, + "license": "MIT", + "dependencies": { + "balanced-match": "^1.0.0" + } + }, "node_modules/@typescript-eslint/typescript-estree/node_modules/minimatch": { "version": "9.0.5", "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.5.tgz", @@ -1085,16 +1408,16 @@ } }, "node_modules/@typescript-eslint/utils": { - "version": "8.8.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-8.8.0.tgz", - "integrity": "sha512-QE2MgfOTem00qrlPgyByaCHay9yb1+9BjnMFnSFkUKQfu7adBXDTnCAivURnuPPAG/qiB+kzKkZKmKfaMT0zVg==", + "version": "8.11.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-8.11.0.tgz", + "integrity": "sha512-CYiX6WZcbXNJV7UNB4PLDIBtSdRmRI/nb0FMyqHPTQD1rMjA0foPLaPUV39C/MxkTd/QKSeX+Gb34PPsDVC35g==", "dev": true, "license": "MIT", "dependencies": { "@eslint-community/eslint-utils": "^4.4.0", - "@typescript-eslint/scope-manager": "8.8.0", - "@typescript-eslint/types": "8.8.0", - "@typescript-eslint/typescript-estree": "8.8.0" + "@typescript-eslint/scope-manager": "8.11.0", + "@typescript-eslint/types": "8.11.0", + "@typescript-eslint/typescript-estree": "8.11.0" }, "engines": { "node": "^18.18.0 || ^20.9.0 || >=21.1.0" @@ -1108,13 +1431,13 @@ } }, "node_modules/@typescript-eslint/visitor-keys": { - "version": "8.8.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-8.8.0.tgz", - "integrity": "sha512-8mq51Lx6Hpmd7HnA2fcHQo3YgfX1qbccxQOgZcb4tvasu//zXRaA1j5ZRFeCw/VRAdFi4mRM9DnZw0Nu0Q2d1g==", + "version": "8.11.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-8.11.0.tgz", + "integrity": "sha512-EaewX6lxSjRJnc+99+dqzTeoDZUfyrA52d2/HRrkI830kgovWsmIiTfmr0NZorzqic7ga+1bS60lRBUgR3n/Bw==", "dev": true, "license": "MIT", "dependencies": { - "@typescript-eslint/types": "8.8.0", + "@typescript-eslint/types": "8.11.0", "eslint-visitor-keys": "^3.4.3" }, "engines": { @@ -1145,10 +1468,22 @@ "dev": true, "license": "ISC" }, + "node_modules/@webgpu/types": { + "version": "0.1.38", + "resolved": "https://registry.npmjs.org/@webgpu/types/-/types-0.1.38.tgz", + "integrity": "sha512-7LrhVKz2PRh+DD7+S+PVaFd5HxaWQvoMqBbsV9fNJO1pjUs1P8bM2vQVNfk+3URTqbuTI7gkXi0rfsN0IadoBA==", + "license": "BSD-3-Clause" + }, + "node_modules/abbrev": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/abbrev/-/abbrev-1.1.1.tgz", + "integrity": "sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q==", + "license": "ISC" + }, "node_modules/acorn": { - "version": "8.12.1", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.12.1.tgz", - "integrity": "sha512-tcpGyI9zbizT9JbV6oYE477V6mTlXvvi0T0G3SNIYE2apm/G5huBa1+K89VGeovbg+jycCrfhl3ADxErOuO6Jg==", + "version": "8.13.0", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.13.0.tgz", + "integrity": "sha512-8zSiw54Oxrdym50NlZ9sUusyO1Z1ZchgRLWRaK6c86XJFClyCgFKetdowBg5bKxyp/u+CDBJG4Mpp0m3HLZl9w==", "dev": true, "license": "MIT", "bin": { @@ -1181,9 +1516,30 @@ "node": ">=0.4.0" } }, - "node_modules/ajv": { - "version": "6.12.6", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", + "node_modules/adm-zip": { + "version": "0.5.16", + "resolved": "https://registry.npmjs.org/adm-zip/-/adm-zip-0.5.16.tgz", + "integrity": "sha512-TGw5yVi4saajsSEgz25grObGHEUaDrniwvA2qwSC060KfqGPdglhvPMA2lPIoxs3PQIItj2iag35fONcQqgUaQ==", + "license": "MIT", + "engines": { + "node": ">=12.0" + } + }, + "node_modules/agent-base": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-4.3.0.tgz", + "integrity": "sha512-salcGninV0nPrwpGNn4VTXBb1SOuXQBiqbrNXoeizJsHrsL6ERFM2Ne3JUSBWRE6aeNJI2ROP/WEEIDUiDe3cg==", + "license": "MIT", + "dependencies": { + "es6-promisify": "^5.0.0" + }, + "engines": { + "node": ">= 4.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, "license": "MIT", @@ -1199,26 +1555,24 @@ } }, "node_modules/ansi-regex": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.1.0.tgz", - "integrity": "sha512-7HSX4QQb4CspciLpVFwyRe79O3xsIZDDLER21kERQ71oaPodF8jL725AgJMFAYbooIqolJoRLuM81SpeUkpkvA==", - "dev": true, + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", "license": "MIT", "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/chalk/ansi-regex?sponsor=1" + "node": ">=8" } }, "node_modules/ansi-styles": { - "version": "6.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-6.2.1.tgz", - "integrity": "sha512-bN798gFfQX+viw3R7yrGWRqnrN2oRkEkUjjl4JNn4E8GxxbjtG3FbrEIIY3l8/hrwUwIeCZvi4QuOTP4MErVug==", - "dev": true, + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", "license": "MIT", + "dependencies": { + "color-convert": "^2.0.1" + }, "engines": { - "node": ">=12" + "node": ">=8" }, "funding": { "url": "https://github.com/chalk/ansi-styles?sponsor=1" @@ -1229,6 +1583,7 @@ "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.3.tgz", "integrity": "sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw==", "dev": true, + "license": "ISC", "dependencies": { "normalize-path": "^3.0.0", "picomatch": "^2.0.4" @@ -1237,16 +1592,24 @@ "node": ">= 8" } }, - "node_modules/anymatch/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" + "node_modules/aproba": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/aproba/-/aproba-2.0.0.tgz", + "integrity": "sha512-lYe4Gx7QT+MKGbDsA+Z+he/Wtef0BiwDOlK/XkBrdfsh9J/jPPXbX0tE9x9cl27Tmu5gg3QUbUrQYa/y+KOHPQ==", + "license": "ISC" + }, + "node_modules/are-we-there-yet": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/are-we-there-yet/-/are-we-there-yet-2.0.0.tgz", + "integrity": "sha512-Ci/qENmwHnsYo9xKIcUJN5LeDKdJ6R1Z1j9V/J5wyq8nh/mYPEpIKJbBZXtZjG04HiK7zV/p6Vs9952MrMeUIw==", + "deprecated": "This package is no longer supported.", + "license": "ISC", + "dependencies": { + "delegates": "^1.0.0", + "readable-stream": "^3.6.0" }, - "funding": { - "url": "https://github.com/sponsors/jonschlinkert" + "engines": { + "node": ">=10" } }, "node_modules/arg": { @@ -1256,29 +1619,35 @@ "dev": true, "license": "MIT" }, -<<<<<<< HEAD + "node_modules/argparse": { + "version": "1.0.10", + "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz", + "integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==", + "license": "MIT", + "dependencies": { + "sprintf-js": "~1.0.2" + } + }, "node_modules/array-union": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/array-union/-/array-union-2.1.0.tgz", "integrity": "sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw==", "dev": true, + "license": "MIT", "engines": { "node": ">=8" } -======= - "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, - "license": "Python-2.0" ->>>>>>> dev + }, + "node_modules/asynckit": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", + "integrity": "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==", + "license": "MIT" }, "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, "license": "MIT" }, "node_modules/binary-extensions": { @@ -1286,6 +1655,7 @@ "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.3.0.tgz", "integrity": "sha512-Ceh+7ox5qe7LJuLHoY0feh3pHuUDHAcRUeyL2VYghZwfpkNIy/+8Ocg0a3UuSoYzavmylwuLWQOf3hl0jjMMIw==", "dev": true, + "license": "MIT", "engines": { "node": ">=8" }, @@ -1294,13 +1664,13 @@ } }, "node_modules/brace-expansion": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", - "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", - "dev": true, + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", "license": "MIT", "dependencies": { - "balanced-match": "^1.0.0" + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" } }, "node_modules/braces": { @@ -1308,10 +1678,7 @@ "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.3.tgz", "integrity": "sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==", "dev": true, -<<<<<<< HEAD -======= "license": "MIT", ->>>>>>> dev "dependencies": { "fill-range": "^7.1.1" }, @@ -1319,30 +1686,6 @@ "node": ">=8" } }, -<<<<<<< HEAD - "node_modules/chokidar": { - "version": "3.6.0", - "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.6.0.tgz", - "integrity": "sha512-7VT13fmjotKpGipCW9JEQAusEPE+Ei8nl6/g4FBAmIm0GOOLMua9NDDo/DWp0ZAxCr3cPq5ZpBqmPAQgDda2Pw==", - "dev": true, - "dependencies": { - "anymatch": "~3.1.2", - "braces": "~3.0.2", - "glob-parent": "~5.1.2", - "is-binary-path": "~2.1.0", - "is-glob": "~4.0.1", - "normalize-path": "~3.0.0", - "readdirp": "~3.6.0" - }, - "engines": { - "node": ">= 8.10.0" - }, - "funding": { - "url": "https://paulmillr.com/funding/" - }, - "optionalDependencies": { - "fsevents": "~2.3.2" -======= "node_modules/callsites": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz", @@ -1368,7 +1711,6 @@ "version": "4.1.2", "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", - "dev": true, "license": "MIT", "dependencies": { "ansi-styles": "^4.1.0", @@ -1381,22 +1723,6 @@ "url": "https://github.com/chalk/chalk?sponsor=1" } }, - "node_modules/chalk/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, - "license": "MIT", - "dependencies": { - "color-convert": "^2.0.1" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" - } - }, "node_modules/character-entities-html4": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/character-entities-html4/-/character-entities-html4-2.1.0.tgz", @@ -1417,14 +1743,87 @@ "funding": { "type": "github", "url": "https://github.com/sponsors/wooorm" ->>>>>>> dev + } + }, + "node_modules/chokidar": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.6.0.tgz", + "integrity": "sha512-7VT13fmjotKpGipCW9JEQAusEPE+Ei8nl6/g4FBAmIm0GOOLMua9NDDo/DWp0ZAxCr3cPq5ZpBqmPAQgDda2Pw==", + "dev": true, + "license": "MIT", + "dependencies": { + "anymatch": "~3.1.2", + "braces": "~3.0.2", + "glob-parent": "~5.1.2", + "is-binary-path": "~2.1.0", + "is-glob": "~4.0.1", + "normalize-path": "~3.0.0", + "readdirp": "~3.6.0" + }, + "engines": { + "node": ">= 8.10.0" + }, + "funding": { + "url": "https://paulmillr.com/funding/" + }, + "optionalDependencies": { + "fsevents": "~2.3.2" + } + }, + "node_modules/chokidar/node_modules/glob-parent": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", + "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", + "dev": true, + "license": "ISC", + "dependencies": { + "is-glob": "^4.0.1" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/chownr": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/chownr/-/chownr-2.0.0.tgz", + "integrity": "sha512-bIomtDF5KGpdogkLd9VspvFzk9KfpyyGlS8YFVZl7TGPBHL5snIOnxeshwVgPteQ9b4Eydl+pVbIyE1DcvCWgQ==", + "license": "ISC", + "engines": { + "node": ">=10" + } + }, + "node_modules/cliui": { + "version": "7.0.4", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-7.0.4.tgz", + "integrity": "sha512-OcRE68cOsVMXp1Yvonl/fzkQOyjLSu/8bhPDfQt0e0/Eb283TKP20Fs2MqoPsr9SwA595rRCA+QMzYc9nBP+JQ==", + "license": "ISC", + "dependencies": { + "string-width": "^4.2.0", + "strip-ansi": "^6.0.0", + "wrap-ansi": "^7.0.0" + } + }, + "node_modules/cliui/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==", + "license": "MIT", + "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/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, "license": "MIT", "dependencies": { "color-name": "~1.1.4" @@ -1437,20 +1836,29 @@ "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, "license": "MIT" }, -<<<<<<< HEAD - "node_modules/commander": { - "version": "9.5.0", - "resolved": "https://registry.npmjs.org/commander/-/commander-9.5.0.tgz", - "integrity": "sha512-KRs7WVDKg86PWiuAqhDrAQnTXZKraVcCc6vFdL14qrZ/DcWwuRo7VoiYXalXO7S5GKpqYiVEwCbgFDfxNHKJBQ==", - "dev": true, + "node_modules/color-support": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/color-support/-/color-support-1.1.3.tgz", + "integrity": "sha512-qiBjkpbMLO/HL68y+lh4q0/O1MZFj2RX6X/KmMa3+gJD3z+WwI1ZzDHysvqHGS3mP6mznPckpXmw1nI9cJjyRg==", + "license": "ISC", + "bin": { + "color-support": "bin.js" + } + }, + "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==", + "license": "MIT", + "dependencies": { + "delayed-stream": "~1.0.0" + }, "engines": { - "node": "^12.20.0 || >=14" + "node": ">= 0.8" } }, -======= "node_modules/comma-separated-tokens": { "version": "2.0.3", "resolved": "https://registry.npmjs.org/comma-separated-tokens/-/comma-separated-tokens-2.0.3.tgz", @@ -1462,14 +1870,39 @@ "url": "https://github.com/sponsors/wooorm" } }, + "node_modules/commander": { + "version": "9.5.0", + "resolved": "https://registry.npmjs.org/commander/-/commander-9.5.0.tgz", + "integrity": "sha512-KRs7WVDKg86PWiuAqhDrAQnTXZKraVcCc6vFdL14qrZ/DcWwuRo7VoiYXalXO7S5GKpqYiVEwCbgFDfxNHKJBQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": "^12.20.0 || >=14" + } + }, "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, "license": "MIT" }, ->>>>>>> dev + "node_modules/console-control-strings": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/console-control-strings/-/console-control-strings-1.1.0.tgz", + "integrity": "sha512-ty/fTekppD2fIwRvnZAVdeOiGd1c7YXEixbgJTNzqcxJWKQnjJ/V1bNEEE6hygpM3WjwHFUVK6HTjWSzV4a8sQ==", + "license": "ISC" + }, + "node_modules/core-js": { + "version": "3.29.1", + "resolved": "https://registry.npmjs.org/core-js/-/core-js-3.29.1.tgz", + "integrity": "sha512-+jwgnhg6cQxKYIIjGtAHq2nwUOolo9eoFZ4sHfUH09BLXBgxnH4gA0zEd+t+BO2cNB8idaBtZFcFTRjQJRJmAw==", + "hasInstallScript": true, + "license": "MIT", + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/core-js" + } + }, "node_modules/create-require": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/create-require/-/create-require-1.1.1.tgz", @@ -1496,7 +1929,6 @@ "version": "4.3.7", "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.7.tgz", "integrity": "sha512-Er2nc/H7RrMXZBFCEim6TCmMk02Z8vLC2Rbi1KEBggpo0fS6l0S1nnapwmIi3yW/+GOJap1Krg4w0Hg80oCqgQ==", - "dev": true, "license": "MIT", "dependencies": { "ms": "^2.1.3" @@ -1517,6 +1949,21 @@ "dev": true, "license": "MIT" }, + "node_modules/delayed-stream": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", + "integrity": "sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==", + "license": "MIT", + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/delegates": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/delegates/-/delegates-1.0.0.tgz", + "integrity": "sha512-bd2L678uiWATM6m5Z1VzNCErI3jiGzt6HGY8OVICs40JQq/HALfbyNJmp0UDakEY4pMMaN0Ly5om/B1VI/+xfQ==", + "license": "MIT" + }, "node_modules/dequal": { "version": "2.0.3", "resolved": "https://registry.npmjs.org/dequal/-/dequal-2.0.3.tgz", @@ -1527,6 +1974,15 @@ "node": ">=6" } }, + "node_modules/detect-libc": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-2.0.3.tgz", + "integrity": "sha512-bwy0MGW55bG41VqxxypOsdSdGqLwXPI/focwgTYCFMbdUiBAxLg9CFzG08sz2aqzknwiX7Hkl0bQENjg8iLByw==", + "license": "Apache-2.0", + "engines": { + "node": ">=8" + } + }, "node_modules/devlop": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/devlop/-/devlop-1.1.0.tgz", @@ -1556,6 +2012,7 @@ "resolved": "https://registry.npmjs.org/dir-glob/-/dir-glob-3.0.1.tgz", "integrity": "sha512-WkrWp9GR4KXfKGYzOLmTuGVi1UWFfws377n9cc55/tb6DuqyF6pcQ5AbiHEshaDpY9v6oaSr2XCDidGmMwdzIA==", "dev": true, + "license": "MIT", "dependencies": { "path-type": "^4.0.0" }, @@ -1571,10 +2028,9 @@ "license": "MIT" }, "node_modules/emoji-regex": { - "version": "9.2.2", - "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-9.2.2.tgz", - "integrity": "sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==", - "dev": true, + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", "license": "MIT" }, "node_modules/entities": { @@ -1590,6 +2046,21 @@ "url": "https://github.com/fb55/entities?sponsor=1" } }, + "node_modules/es6-promise": { + "version": "4.2.8", + "resolved": "https://registry.npmjs.org/es6-promise/-/es6-promise-4.2.8.tgz", + "integrity": "sha512-HJDGx5daxeIvxdBxvG2cb9g4tEvwIk3i8+nhX0yGrYmZUzbkdg8QbDevheDB8gd0//uPj4c1EQua8Q+MViT0/w==", + "license": "MIT" + }, + "node_modules/es6-promisify": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/es6-promisify/-/es6-promisify-5.0.0.tgz", + "integrity": "sha512-C+d6UdsYDk0lMebHNR4S2NybQMMngAOnOwYBQjTOiv0MkoJMP0Myw2mgpDLBcpfCmRLxyFqYhS/CfOENq4SJhQ==", + "license": "MIT", + "dependencies": { + "es6-promise": "^4.0.3" + } + }, "node_modules/esbuild": { "version": "0.23.1", "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.23.1.tgz", @@ -1630,8 +2101,15 @@ "@esbuild/win32-x64": "0.23.1" } }, -<<<<<<< HEAD -======= + "node_modules/escalade": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.2.0.tgz", + "integrity": "sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA==", + "license": "MIT", + "engines": { + "node": ">=6" + } + }, "node_modules/escape-string-regexp": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz", @@ -1646,18 +2124,18 @@ } }, "node_modules/eslint": { - "version": "9.12.0", - "resolved": "https://registry.npmjs.org/eslint/-/eslint-9.12.0.tgz", - "integrity": "sha512-UVIOlTEWxwIopRL1wgSQYdnVDcEvs2wyaO6DGo5mXqe3r16IoCNWkR29iHhyaP4cICWjbgbmFUGAhh0GJRuGZw==", + "version": "9.13.0", + "resolved": "https://registry.npmjs.org/eslint/-/eslint-9.13.0.tgz", + "integrity": "sha512-EYZK6SX6zjFHST/HRytOdA/zE72Cq/bfw45LSyuwrdvcclb/gqV8RRQxywOBEWO2+WDpva6UZa4CcDeJKzUCFA==", "dev": true, "license": "MIT", "dependencies": { "@eslint-community/eslint-utils": "^4.2.0", "@eslint-community/regexpp": "^4.11.0", "@eslint/config-array": "^0.18.0", - "@eslint/core": "^0.6.0", + "@eslint/core": "^0.7.0", "@eslint/eslintrc": "^3.1.0", - "@eslint/js": "9.12.0", + "@eslint/js": "9.13.0", "@eslint/plugin-kit": "^0.2.0", "@humanfs/node": "^0.16.5", "@humanwhocodes/module-importer": "^1.0.1", @@ -1736,30 +2214,6 @@ "url": "https://opencollective.com/eslint" } }, - "node_modules/eslint/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, - "license": "MIT", - "dependencies": { - "balanced-match": "^1.0.0", - "concat-map": "0.0.1" - } - }, - "node_modules/eslint/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, - "license": "ISC", - "dependencies": { - "brace-expansion": "^1.1.7" - }, - "engines": { - "node": "*" - } - }, "node_modules/espree": { "version": "10.2.0", "resolved": "https://registry.npmjs.org/espree/-/espree-10.2.0.tgz", @@ -1831,16 +2285,12 @@ "dev": true, "license": "MIT" }, ->>>>>>> dev "node_modules/fast-glob": { "version": "3.3.2", "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.3.2.tgz", "integrity": "sha512-oX2ruAFQwf/Orj8m737Y5adxDQO0LAB7/S5MnxCdTNDd4p6BsyIVsv9JQsATbTSq8KHRpLwIHbVlUNatxd+1Ow==", "dev": true, -<<<<<<< HEAD -======= "license": "MIT", ->>>>>>> dev "dependencies": { "@nodelib/fs.stat": "^2.0.2", "@nodelib/fs.walk": "^1.2.3", @@ -1852,8 +2302,6 @@ "node": ">=8.6.0" } }, -<<<<<<< HEAD -======= "node_modules/fast-glob/node_modules/glob-parent": { "version": "5.1.2", "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", @@ -1881,22 +2329,16 @@ "dev": true, "license": "MIT" }, ->>>>>>> dev "node_modules/fastq": { "version": "1.17.1", "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.17.1.tgz", "integrity": "sha512-sRVD3lWVIXWg6By68ZN7vho9a1pQcN/WBFaAAsDDFzlJjvoGx0P8z7V1t72grFJfJhu3YPZBuu25f7Kaw2jN1w==", "dev": true, -<<<<<<< HEAD -======= "license": "ISC", ->>>>>>> dev "dependencies": { "reusify": "^1.0.4" } }, -<<<<<<< HEAD -======= "node_modules/file-entry-cache": { "version": "8.0.0", "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-8.0.0.tgz", @@ -1910,16 +2352,12 @@ "node": ">=16.0.0" } }, ->>>>>>> dev "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, -<<<<<<< HEAD -======= "license": "MIT", ->>>>>>> dev "dependencies": { "to-regex-range": "^5.0.1" }, @@ -1927,8 +2365,6 @@ "node": ">=8" } }, -<<<<<<< HEAD -======= "node_modules/find-up": { "version": "5.0.0", "resolved": "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz", @@ -1967,7 +2403,6 @@ "dev": true, "license": "ISC" }, ->>>>>>> dev "node_modules/foreground-child": { "version": "3.3.0", "resolved": "https://registry.npmjs.org/foreground-child/-/foreground-child-3.3.0.tgz", @@ -1985,6 +2420,63 @@ "url": "https://github.com/sponsors/isaacs" } }, + "node_modules/foreground-child/node_modules/signal-exit": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-4.1.0.tgz", + "integrity": "sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==", + "dev": true, + "license": "ISC", + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/form-data": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.1.tgz", + "integrity": "sha512-tzN8e4TX8+kkxGPK8D5u0FNmjPUjw3lwC9lSLxxoB/+GtsJG91CO8bSWy73APlgAZzZbXEYZJuxjkHH2w+Ezhw==", + "license": "MIT", + "dependencies": { + "asynckit": "^0.4.0", + "combined-stream": "^1.0.8", + "mime-types": "^2.1.12" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/fs-minipass": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/fs-minipass/-/fs-minipass-2.1.0.tgz", + "integrity": "sha512-V/JgOLFCS+R6Vcq0slCuaeWEdNC3ouDlJMNIsacH2VtALiu9mV4LPrHc5cDl8k5aw6J8jwgWWpiTo5RYhmIzvg==", + "license": "ISC", + "dependencies": { + "minipass": "^3.0.0" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/fs-minipass/node_modules/minipass": { + "version": "3.3.6", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-3.3.6.tgz", + "integrity": "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw==", + "license": "ISC", + "dependencies": { + "yallist": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "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==", + "license": "ISC" + }, "node_modules/fsevents": { "version": "2.3.3", "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz", @@ -2000,6 +2492,36 @@ "node": "^8.16.0 || ^10.6.0 || >=11.0.0" } }, + "node_modules/gauge": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/gauge/-/gauge-3.0.2.tgz", + "integrity": "sha512-+5J6MS/5XksCuXq++uFRsnUd7Ovu1XenbeuIuNRJxYWjgQbPuFhT14lAvsWfqfAmnwluf1OwMjz39HjfLPci0Q==", + "deprecated": "This package is no longer supported.", + "license": "ISC", + "dependencies": { + "aproba": "^1.0.3 || ^2.0.0", + "color-support": "^1.1.2", + "console-control-strings": "^1.0.0", + "has-unicode": "^2.0.1", + "object-assign": "^4.1.1", + "signal-exit": "^3.0.0", + "string-width": "^4.2.3", + "strip-ansi": "^6.0.1", + "wide-align": "^1.1.2" + }, + "engines": { + "node": ">=10" + } + }, + "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==", + "license": "ISC", + "engines": { + "node": "6.* || 8.* || >= 10.*" + } + }, "node_modules/get-tsconfig": { "version": "4.8.1", "resolved": "https://registry.npmjs.org/get-tsconfig/-/get-tsconfig-4.8.1.tgz", @@ -2038,44 +2560,42 @@ } }, "node_modules/glob-parent": { -<<<<<<< HEAD - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", - "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", + "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, + "license": "ISC", "dependencies": { - "is-glob": "^4.0.1" + "is-glob": "^4.0.3" }, "engines": { - "node": ">= 6" + "node": ">=10.13.0" } }, - "node_modules/globby": { - "version": "11.1.0", - "resolved": "https://registry.npmjs.org/globby/-/globby-11.1.0.tgz", - "integrity": "sha512-jhIXaOzy1sb8IyocaruWSn1TjmnBVs8Ayhcy83rmxNJ8q2uWKCAj3CnJY+KpGSXCueAPc0i05kVvVKtP1t9S3g==", + "node_modules/glob/node_modules/brace-expansion": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", + "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", "dev": true, + "license": "MIT", "dependencies": { - "array-union": "^2.1.0", - "dir-glob": "^3.0.1", - "fast-glob": "^3.2.9", - "ignore": "^5.2.0", - "merge2": "^1.4.1", - "slash": "^3.0.0" - }, - "engines": { - "node": ">=10" -======= - "version": "6.0.2", - "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-6.0.2.tgz", - "integrity": "sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==", + "balanced-match": "^1.0.0" + } + }, + "node_modules/glob/node_modules/minimatch": { + "version": "10.0.1", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-10.0.1.tgz", + "integrity": "sha512-ethXTt3SGGR+95gudmqJ1eNhRO7eGEGIgYA9vnPatK4/etz2MEVDno5GMCibdMTuBMyElzIlgxMna3K94XDIDQ==", "dev": true, "license": "ISC", "dependencies": { - "is-glob": "^4.0.3" + "brace-expansion": "^2.0.1" }, "engines": { - "node": ">=10.13.0" + "node": "20 || >=22" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" } }, "node_modules/globals": { @@ -2085,15 +2605,39 @@ "dev": true, "license": "MIT", "engines": { - "node": ">=18" ->>>>>>> dev + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/globby": { + "version": "11.1.0", + "resolved": "https://registry.npmjs.org/globby/-/globby-11.1.0.tgz", + "integrity": "sha512-jhIXaOzy1sb8IyocaruWSn1TjmnBVs8Ayhcy83rmxNJ8q2uWKCAj3CnJY+KpGSXCueAPc0i05kVvVKtP1t9S3g==", + "dev": true, + "license": "MIT", + "dependencies": { + "array-union": "^2.1.0", + "dir-glob": "^3.0.1", + "fast-glob": "^3.2.9", + "ignore": "^5.2.0", + "merge2": "^1.4.1", + "slash": "^3.0.0" + }, + "engines": { + "node": ">=10" }, "funding": { "url": "https://github.com/sponsors/sindresorhus" } }, -<<<<<<< HEAD -======= + "node_modules/google-protobuf": { + "version": "3.21.4", + "resolved": "https://registry.npmjs.org/google-protobuf/-/google-protobuf-3.21.4.tgz", + "integrity": "sha512-MnG7N936zcKTco4Jd2PX2U96Kf9PxygAPKBug+74LHzmHXmceN16MmRcdgZv+DGef/S9YvQAfRsNCn4cjf9yyQ==", + "license": "(BSD-3-Clause AND Apache-2.0)" + }, "node_modules/graphemer": { "version": "1.4.0", "resolved": "https://registry.npmjs.org/graphemer/-/graphemer-1.4.0.tgz", @@ -2105,12 +2649,17 @@ "version": "4.0.0", "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", - "dev": true, "license": "MIT", "engines": { "node": ">=8" } }, + "node_modules/has-unicode": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/has-unicode/-/has-unicode-2.0.1.tgz", + "integrity": "sha512-8Rf9Y83NBReMnx0gFzA8JImQACstCYWUplepDa9xprwwtmgEZUF0h/i5xSA625zB/I37EtrswSST6OXxwaaIJQ==", + "license": "ISC" + }, "node_modules/hast-util-to-html": { "version": "9.0.3", "resolved": "https://registry.npmjs.org/hast-util-to-html/-/hast-util-to-html-9.0.3.tgz", @@ -2160,32 +2709,38 @@ "url": "https://github.com/sponsors/wooorm" } }, ->>>>>>> dev + "node_modules/https-proxy-agent": { + "version": "2.2.4", + "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-2.2.4.tgz", + "integrity": "sha512-OmvfoQ53WLjtA9HeYP9RNrWMJzzAz1JGaSFr1nijg0PVR1JaD/xbJq1mdEIIlxGpXp9eSe/O2LgU9DJmTPd0Eg==", + "license": "MIT", + "dependencies": { + "agent-base": "^4.3.0", + "debug": "^3.1.0" + }, + "engines": { + "node": ">= 4.5.0" + } + }, + "node_modules/https-proxy-agent/node_modules/debug": { + "version": "3.2.7", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz", + "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==", + "license": "MIT", + "dependencies": { + "ms": "^2.1.1" + } + }, "node_modules/ignore": { "version": "5.3.2", "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.3.2.tgz", "integrity": "sha512-hsBTNUqQTDwkWtcdYI2i06Y/nUBEsNEDJKjWdigLvegy8kDuJAS8uRlpkkcQpyEXL0Z/pjDy5HBmMjRCJ2gq+g==", "dev": true, -<<<<<<< HEAD -======= "license": "MIT", ->>>>>>> dev "engines": { "node": ">= 4" } }, -<<<<<<< HEAD - "node_modules/is-binary-path": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz", - "integrity": "sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==", - "dev": true, - "dependencies": { - "binary-extensions": "^2.0.0" - }, - "engines": { - "node": ">=8" -======= "node_modules/import-fresh": { "version": "3.3.0", "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.0.tgz", @@ -2211,7 +2766,36 @@ "license": "MIT", "engines": { "node": ">=0.8.19" ->>>>>>> dev + } + }, + "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==", + "deprecated": "This module is not supported, and leaks memory. Do not use it. Check out lru-cache if you want a good and tested way to coalesce async requests by a key value, which is much more comprehensive and powerful.", + "license": "ISC", + "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==", + "license": "ISC" + }, + "node_modules/is-binary-path": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz", + "integrity": "sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==", + "dev": true, + "license": "MIT", + "dependencies": { + "binary-extensions": "^2.0.0" + }, + "engines": { + "node": ">=8" } }, "node_modules/is-extglob": { @@ -2219,10 +2803,7 @@ "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", "integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==", "dev": true, -<<<<<<< HEAD -======= "license": "MIT", ->>>>>>> dev "engines": { "node": ">=0.10.0" } @@ -2231,7 +2812,6 @@ "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, "license": "MIT", "engines": { "node": ">=8" @@ -2242,10 +2822,7 @@ "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz", "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==", "dev": true, -<<<<<<< HEAD -======= "license": "MIT", ->>>>>>> dev "dependencies": { "is-extglob": "^2.1.1" }, @@ -2258,10 +2835,7 @@ "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", "dev": true, -<<<<<<< HEAD -======= "license": "MIT", ->>>>>>> dev "engines": { "node": ">=0.12.0" } @@ -2302,6 +2876,13 @@ "js-yaml": "bin/js-yaml.js" } }, + "node_modules/js-yaml/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, + "license": "Python-2.0" + }, "node_modules/json-buffer": { "version": "3.0.1", "resolved": "https://registry.npmjs.org/json-buffer/-/json-buffer-3.0.1.tgz", @@ -2380,6 +2961,12 @@ "dev": true, "license": "MIT" }, + "node_modules/long": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/long/-/long-4.0.0.tgz", + "integrity": "sha512-XsP+KhQif4bjX1kbuSiySJFNAehNxgLb6hPRGJ9QsUr8ajHkuXGdrHmFUTUUXhDwVX2R5bY4JNZEwbUiMhV+MA==", + "license": "Apache-2.0" + }, "node_modules/lru-cache": { "version": "11.0.1", "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-11.0.1.tgz", @@ -2397,6 +2984,30 @@ "dev": true, "license": "MIT" }, + "node_modules/make-dir": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-3.1.0.tgz", + "integrity": "sha512-g3FeP20LNwhALb/6Cz6Dd4F2ngze0jz7tbzrD2wAV+o9FeNHe4rL+yK2md0J/fiSf1sa1ADhXqi5+oVwOM/eGw==", + "license": "MIT", + "dependencies": { + "semver": "^6.0.0" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/make-dir/node_modules/semver": { + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", + "license": "ISC", + "bin": { + "semver": "bin/semver.js" + } + }, "node_modules/make-error": { "version": "1.3.6", "resolved": "https://registry.npmjs.org/make-error/-/make-error-1.3.6.tgz", @@ -2404,8 +3015,6 @@ "dev": true, "license": "ISC" }, -<<<<<<< HEAD -======= "node_modules/markdown-it": { "version": "14.1.0", "resolved": "https://registry.npmjs.org/markdown-it/-/markdown-it-14.1.0.tgz", @@ -2424,6 +3033,13 @@ "markdown-it": "bin/markdown-it.mjs" } }, + "node_modules/markdown-it/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, + "license": "Python-2.0" + }, "node_modules/mdast-util-to-hast": { "version": "13.2.0", "resolved": "https://registry.npmjs.org/mdast-util-to-hast/-/mdast-util-to-hast-13.2.0.tgz", @@ -2453,22 +3069,16 @@ "dev": true, "license": "MIT" }, ->>>>>>> dev "node_modules/merge2": { "version": "1.4.1", "resolved": "https://registry.npmjs.org/merge2/-/merge2-1.4.1.tgz", "integrity": "sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==", "dev": true, -<<<<<<< HEAD -======= "license": "MIT", ->>>>>>> dev "engines": { "node": ">= 8" } }, -<<<<<<< HEAD -======= "node_modules/micromark-util-character": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/micromark-util-character/-/micromark-util-character-2.1.0.tgz", @@ -2563,16 +3173,12 @@ ], "license": "MIT" }, ->>>>>>> dev "node_modules/micromatch": { "version": "4.0.8", "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.8.tgz", "integrity": "sha512-PXwfBhYu0hBCPw8Dn0E+WDYb7af3dSLVWKi3HGv84IdF4TyFoC0ysxFd0Goxw7nSv4T/PzEJQxsYsEiFCKo2BA==", "dev": true, -<<<<<<< HEAD -======= "license": "MIT", ->>>>>>> dev "dependencies": { "braces": "^3.0.3", "picomatch": "^2.3.1" @@ -2581,35 +3187,37 @@ "node": ">=8.6" } }, -<<<<<<< HEAD - "node_modules/micromatch/node_modules/picomatch": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", - "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==", - "dev": true, + "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==", + "license": "MIT", "engines": { - "node": ">=8.6" + "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==", + "license": "MIT", + "dependencies": { + "mime-db": "1.52.0" }, - "funding": { - "url": "https://github.com/sponsors/jonschlinkert" + "engines": { + "node": ">= 0.6" } }, -======= ->>>>>>> dev "node_modules/minimatch": { - "version": "10.0.1", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-10.0.1.tgz", - "integrity": "sha512-ethXTt3SGGR+95gudmqJ1eNhRO7eGEGIgYA9vnPatK4/etz2MEVDno5GMCibdMTuBMyElzIlgxMna3K94XDIDQ==", - "dev": true, + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", "license": "ISC", "dependencies": { - "brace-expansion": "^2.0.1" + "brace-expansion": "^1.1.7" }, "engines": { - "node": "20 || >=22" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" + "node": "*" } }, "node_modules/minipass": { @@ -2622,12 +3230,55 @@ "node": ">=16 || 14 >=14.17" } }, -<<<<<<< HEAD + "node_modules/minizlib": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/minizlib/-/minizlib-2.1.2.tgz", + "integrity": "sha512-bAxsR8BVfj60DWXHE3u30oHzfl4G7khkSuPW+qvpd7jFRHm7dLxOjUk1EHACJ/hxLY8phGJ0YhYHZo7jil7Qdg==", + "license": "MIT", + "dependencies": { + "minipass": "^3.0.0", + "yallist": "^4.0.0" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/minizlib/node_modules/minipass": { + "version": "3.3.6", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-3.3.6.tgz", + "integrity": "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw==", + "license": "ISC", + "dependencies": { + "yallist": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/mkdirp": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-1.0.4.tgz", + "integrity": "sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==", + "license": "MIT", + "bin": { + "mkdirp": "bin/cmd.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/ms": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", + "license": "MIT" + }, "node_modules/mylas": { "version": "2.1.13", "resolved": "https://registry.npmjs.org/mylas/-/mylas-2.1.13.tgz", "integrity": "sha512-+MrqnJRtxdF+xngFfUUkIMQrUUL0KsxbADUkn23Z/4ibGg192Q+z+CQyiYwvWTsYjJygmMR8+w3ZDa98Zh6ESg==", "dev": true, + "license": "MIT", "engines": { "node": ">=12.0.0" }, @@ -2636,27 +3287,88 @@ "url": "https://github.com/sponsors/raouldeheer" } }, + "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, + "license": "MIT" + }, + "node_modules/node-fetch": { + "version": "2.7.0", + "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.7.0.tgz", + "integrity": "sha512-c4FRfUm/dbcWZ7U+1Wq0AwCyFL+3nt2bEw05wfxSz+DWpWsitgmSgYmy2dQdWyKC1694ELPqMs/YzUSNozLt8A==", + "license": "MIT", + "dependencies": { + "whatwg-url": "^5.0.0" + }, + "engines": { + "node": "4.x || >=6.0.0" + }, + "peerDependencies": { + "encoding": "^0.1.0" + }, + "peerDependenciesMeta": { + "encoding": { + "optional": true + } + } + }, + "node_modules/nopt": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/nopt/-/nopt-5.0.0.tgz", + "integrity": "sha512-Tbj67rffqceeLpcRXrT7vKAN8CwfPeIBgM7E6iBkmKLV7bEMwpGgYLGv0jACUsECaa/vuxP0IjEont6umdMgtQ==", + "license": "ISC", + "dependencies": { + "abbrev": "1" + }, + "bin": { + "nopt": "bin/nopt.js" + }, + "engines": { + "node": ">=6" + } + }, "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, + "license": "MIT", "engines": { "node": ">=0.10.0" -======= - "node_modules/ms": { - "version": "2.1.3", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", - "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", - "dev": true, - "license": "MIT" + } }, - "node_modules/natural-compare": { + "node_modules/npmlog": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/npmlog/-/npmlog-5.0.1.tgz", + "integrity": "sha512-AqZtDUWOMKs1G/8lwylVjrdYgqA4d9nu8hc+0gzRxlDb1I10+FHBGMXs6aiQHFdCUUlqH99MUMuLfzWDNDtfxw==", + "deprecated": "This package is no longer supported.", + "license": "ISC", + "dependencies": { + "are-we-there-yet": "^2.0.0", + "console-control-strings": "^1.1.0", + "gauge": "^3.0.0", + "set-blocking": "^2.0.0" + } + }, + "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==", + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/once": { "version": "1.4.0", - "resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz", - "integrity": "sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==", - "dev": true, - "license": "MIT" + "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", + "integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==", + "license": "ISC", + "dependencies": { + "wrappy": "1" + } }, "node_modules/oniguruma-to-js": { "version": "0.4.3", @@ -2719,7 +3431,6 @@ }, "funding": { "url": "https://github.com/sponsors/sindresorhus" ->>>>>>> dev } }, "node_modules/package-json-from-dist": { @@ -2752,6 +3463,15 @@ "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==", + "license": "MIT", + "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", @@ -2779,36 +3499,16 @@ "url": "https://github.com/sponsors/isaacs" } }, -<<<<<<< HEAD "node_modules/path-type": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/path-type/-/path-type-4.0.0.tgz", "integrity": "sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==", "dev": true, + "license": "MIT", "engines": { "node": ">=8" } }, - "node_modules/plimit-lit": { - "version": "1.6.1", - "resolved": "https://registry.npmjs.org/plimit-lit/-/plimit-lit-1.6.1.tgz", - "integrity": "sha512-B7+VDyb8Tl6oMJT9oSO2CW8XC/T4UcJGrwOVoNGwOQsQYhlpfajmrMj5xeejqaASq3V/EqThyOeATEOMuSEXiA==", - "dev": true, - "dependencies": { - "queue-lit": "^1.5.1" - }, - "engines": { - "node": ">=12" - } - }, - "node_modules/queue-lit": { - "version": "1.5.2", - "resolved": "https://registry.npmjs.org/queue-lit/-/queue-lit-1.5.2.tgz", - "integrity": "sha512-tLc36IOPeMAubu8BkW8YDBV+WyIgKlYU7zUNs0J5Vk9skSZ4JfGlPOqplP0aHdfv7HL0B2Pg6nwiq60Qc6M2Hw==", - "dev": true, - "engines": { - "node": ">=12" -======= "node_modules/picomatch": { "version": "2.3.1", "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", @@ -2822,6 +3522,19 @@ "url": "https://github.com/sponsors/jonschlinkert" } }, + "node_modules/plimit-lit": { + "version": "1.6.1", + "resolved": "https://registry.npmjs.org/plimit-lit/-/plimit-lit-1.6.1.tgz", + "integrity": "sha512-B7+VDyb8Tl6oMJT9oSO2CW8XC/T4UcJGrwOVoNGwOQsQYhlpfajmrMj5xeejqaASq3V/EqThyOeATEOMuSEXiA==", + "dev": true, + "license": "MIT", + "dependencies": { + "queue-lit": "^1.5.1" + }, + "engines": { + "node": ">=12" + } + }, "node_modules/prelude-ls": { "version": "1.2.1", "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.2.1.tgz", @@ -2832,6 +3545,15 @@ "node": ">= 0.8.0" } }, + "node_modules/progress": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/progress/-/progress-2.0.3.tgz", + "integrity": "sha512-7PiHtLll5LdnKIMw100I+8xJXR5gW2QwWYkT6iJva0bXitZKa/XMrSbdmg3r2Xnaidz9Qumd0VPaMrZlF9V9sA==", + "license": "MIT", + "engines": { + "node": ">=0.4.0" + } + }, "node_modules/property-information": { "version": "6.5.0", "resolved": "https://registry.npmjs.org/property-information/-/property-information-6.5.0.tgz", @@ -2861,7 +3583,16 @@ "license": "MIT", "engines": { "node": ">=6" ->>>>>>> dev + } + }, + "node_modules/queue-lit": { + "version": "1.5.2", + "resolved": "https://registry.npmjs.org/queue-lit/-/queue-lit-1.5.2.tgz", + "integrity": "sha512-tLc36IOPeMAubu8BkW8YDBV+WyIgKlYU7zUNs0J5Vk9skSZ4JfGlPOqplP0aHdfv7HL0B2Pg6nwiq60Qc6M2Hw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12" } }, "node_modules/queue-microtask": { @@ -2882,14 +3613,29 @@ "type": "consulting", "url": "https://feross.org/support" } -<<<<<<< HEAD - ] + ], + "license": "MIT" + }, + "node_modules/readable-stream": { + "version": "3.6.2", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz", + "integrity": "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==", + "license": "MIT", + "dependencies": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + }, + "engines": { + "node": ">= 6" + } }, "node_modules/readdirp": { "version": "3.6.0", "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz", "integrity": "sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==", "dev": true, + "license": "MIT", "dependencies": { "picomatch": "^2.2.1" }, @@ -2897,18 +3643,10 @@ "node": ">=8.10.0" } }, - "node_modules/readdirp/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/regenerator-runtime": { + "version": "0.13.11", + "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.13.11.tgz", + "integrity": "sha512-kY1AZVr2Ra+t+piVaJ4gxaFaReZVH40AKNo7UCX6W+dEwBo/2oZJzqfuN1qLq1oL45o56cPaTXELwrTh8Fpggg==", "license": "MIT" }, "node_modules/regex": { @@ -2918,6 +3656,15 @@ "dev": true, "license": "MIT" }, + "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==", + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, "node_modules/resolve-from": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz", @@ -2926,7 +3673,6 @@ "license": "MIT", "engines": { "node": ">=4" ->>>>>>> dev } }, "node_modules/resolve-pkg-maps": { @@ -2944,10 +3690,7 @@ "resolved": "https://registry.npmjs.org/reusify/-/reusify-1.0.4.tgz", "integrity": "sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw==", "dev": true, -<<<<<<< HEAD -======= "license": "MIT", ->>>>>>> dev "engines": { "iojs": ">=1.0.0", "node": ">=0.10.0" @@ -2992,21 +3735,41 @@ "url": "https://feross.org/support" } ], -<<<<<<< HEAD -======= "license": "MIT", ->>>>>>> dev "dependencies": { "queue-microtask": "^1.2.2" } }, -<<<<<<< HEAD -======= + "node_modules/safe-buffer": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", + "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "license": "MIT" + }, + "node_modules/seedrandom": { + "version": "3.0.5", + "resolved": "https://registry.npmjs.org/seedrandom/-/seedrandom-3.0.5.tgz", + "integrity": "sha512-8OwmbklUNzwezjGInmZ+2clQmExQPvomqjL7LFqOYqtmuxRgQYqOD3mHaU+MvZn5FLUeVxVfQjwLZW/n/JFuqg==", + "license": "MIT" + }, "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, "license": "ISC", "bin": { "semver": "bin/semver.js" @@ -3015,7 +3778,12 @@ "node": ">=10" } }, ->>>>>>> dev + "node_modules/set-blocking": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/set-blocking/-/set-blocking-2.0.0.tgz", + "integrity": "sha512-KiKBS8AnWGEyLzofFfmvKwpdPzqiy16LvQfK3yv/fVH7Bj13/wl3JSR1J+rfgRE9q7xUJK4qvgS8raSOeLUehw==", + "license": "ISC" + }, "node_modules/shebang-command": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", @@ -3055,27 +3823,21 @@ } }, "node_modules/signal-exit": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-4.1.0.tgz", - "integrity": "sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==", - "dev": true, - "license": "ISC", - "engines": { - "node": ">=14" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } + "version": "3.0.7", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.7.tgz", + "integrity": "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==", + "license": "ISC" }, -<<<<<<< HEAD "node_modules/slash": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/slash/-/slash-3.0.0.tgz", "integrity": "sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==", "dev": true, + "license": "MIT", "engines": { "node": ">=8" -======= + } + }, "node_modules/space-separated-tokens": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/space-separated-tokens/-/space-separated-tokens-2.0.2.tgz", @@ -3085,33 +3847,27 @@ "funding": { "type": "github", "url": "https://github.com/sponsors/wooorm" ->>>>>>> dev } }, - "node_modules/string-width": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-5.1.2.tgz", - "integrity": "sha512-HnLOCR3vjcY8beoNLtcjZ5/nxn2afmME6lhrDrebokqMap+XbeW8n9TXpPDOqdGK5qcI3oT0GKTW6wC7EMiVqA==", - "dev": true, + "node_modules/sprintf-js": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz", + "integrity": "sha512-D9cPgkvLlV3t3IzL0D0YLvGA9Ahk4PcvVwUbN0dSGr1aP0Nrt4AEnTUbuGvquEC0mA64Gqt1fzirlRs5ibXx8g==", + "license": "BSD-3-Clause" + }, + "node_modules/string_decoder": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz", + "integrity": "sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==", "license": "MIT", "dependencies": { - "eastasianwidth": "^0.2.0", - "emoji-regex": "^9.2.2", - "strip-ansi": "^7.0.1" - }, - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "safe-buffer": "~5.2.0" } }, - "node_modules/string-width-cjs": { - "name": "string-width", + "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, "license": "MIT", "dependencies": { "emoji-regex": "^8.0.0", @@ -3122,31 +3878,17 @@ "node": ">=8" } }, - "node_modules/string-width-cjs/node_modules/ansi-regex": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", - "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=8" - } - }, - "node_modules/string-width-cjs/node_modules/emoji-regex": { - "version": "8.0.0", - "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", - "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", - "dev": true, - "license": "MIT" - }, - "node_modules/string-width-cjs/node_modules/strip-ansi": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", - "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "node_modules/string-width-cjs": { + "name": "string-width", + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", "dev": true, "license": "MIT", "dependencies": { - "ansi-regex": "^5.0.1" + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" }, "engines": { "node": ">=8" @@ -3168,19 +3910,15 @@ } }, "node_modules/strip-ansi": { - "version": "7.1.0", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.1.0.tgz", - "integrity": "sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==", - "dev": true, + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", "license": "MIT", "dependencies": { - "ansi-regex": "^6.0.1" + "ansi-regex": "^5.0.1" }, "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/chalk/strip-ansi?sponsor=1" + "node": ">=8" } }, "node_modules/strip-ansi-cjs": { @@ -3197,18 +3935,6 @@ "node": ">=8" } }, - "node_modules/strip-ansi-cjs/node_modules/ansi-regex": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", - "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=8" - } - }, -<<<<<<< HEAD -======= "node_modules/strip-json-comments": { "version": "3.1.1", "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz", @@ -3226,7 +3952,6 @@ "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, "license": "MIT", "dependencies": { "has-flag": "^4.0.0" @@ -3235,6 +3960,32 @@ "node": ">=8" } }, + "node_modules/tar": { + "version": "6.2.1", + "resolved": "https://registry.npmjs.org/tar/-/tar-6.2.1.tgz", + "integrity": "sha512-DZ4yORTwrbTj/7MZYq2w+/ZFdI6OZ/f9SFHR+71gIVUZhOQPHzVCLpvRnPgyaMpfWxxk/4ONva3GQSyNIKRv6A==", + "license": "ISC", + "dependencies": { + "chownr": "^2.0.0", + "fs-minipass": "^2.0.0", + "minipass": "^5.0.0", + "minizlib": "^2.1.1", + "mkdirp": "^1.0.3", + "yallist": "^4.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/tar/node_modules/minipass": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-5.0.0.tgz", + "integrity": "sha512-3FnjYuehv9k6ovOEbyOswadCDPX1piCfhV8ncmYtHOjuPwylVWsghTLo7rabjC3Rx5xD4HDx8Wm1xnMF7S5qFQ==", + "license": "ISC", + "engines": { + "node": ">=8" + } + }, "node_modules/text-table": { "version": "0.2.0", "resolved": "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz", @@ -3242,16 +3993,12 @@ "dev": true, "license": "MIT" }, ->>>>>>> dev "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, -<<<<<<< HEAD -======= "license": "MIT", ->>>>>>> dev "dependencies": { "is-number": "^7.0.0" }, @@ -3259,8 +4006,12 @@ "node": ">=8.0" } }, -<<<<<<< HEAD -======= + "node_modules/tr46": { + "version": "0.0.3", + "resolved": "https://registry.npmjs.org/tr46/-/tr46-0.0.3.tgz", + "integrity": "sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw==", + "license": "MIT" + }, "node_modules/trim-lines": { "version": "3.0.1", "resolved": "https://registry.npmjs.org/trim-lines/-/trim-lines-3.0.1.tgz", @@ -3285,7 +4036,6 @@ "typescript": ">=4.2.0" } }, ->>>>>>> dev "node_modules/ts-node": { "version": "10.9.2", "resolved": "https://registry.npmjs.org/ts-node/-/ts-node-10.9.2.tgz", @@ -3382,9 +4132,9 @@ } }, "node_modules/typedoc": { - "version": "0.26.9", - "resolved": "https://registry.npmjs.org/typedoc/-/typedoc-0.26.9.tgz", - "integrity": "sha512-Rc7QpWL7EtmrT8yxV0GmhOR6xHgFnnhphbD9Suti3fz3um7ZOrou6q/g9d6+zC5PssTLZmjaW4Upmzv8T1rCcQ==", + "version": "0.26.10", + "resolved": "https://registry.npmjs.org/typedoc/-/typedoc-0.26.10.tgz", + "integrity": "sha512-xLmVKJ8S21t+JeuQLNueebEuTVphx6IrP06CdV7+0WVflUSW3SPmR+h1fnWVdAR/FQePEgsSWCUHXqKKjzuUAw==", "dev": true, "license": "Apache-2.0", "dependencies": { @@ -3404,6 +4154,16 @@ "typescript": "4.6.x || 4.7.x || 4.8.x || 4.9.x || 5.0.x || 5.1.x || 5.2.x || 5.3.x || 5.4.x || 5.5.x || 5.6.x" } }, + "node_modules/typedoc/node_modules/brace-expansion": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", + "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", + "dev": true, + "license": "MIT", + "dependencies": { + "balanced-match": "^1.0.0" + } + }, "node_modules/typedoc/node_modules/minimatch": { "version": "9.0.5", "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.5.tgz", @@ -3421,10 +4181,11 @@ } }, "node_modules/typescript": { - "version": "5.6.2", - "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.6.2.tgz", - "integrity": "sha512-NW8ByodCSNCwZeghjN3o+JX5OFH0Ojg6sadjEKY4huZ52TqbJTJnDo5+Tw98lSy63NZvi4n+ez5m2u5d4PkZyw==", + "version": "5.6.3", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.6.3.tgz", + "integrity": "sha512-hjcS1mhfuyi4WW8IWtjP7brDrG2cuDZukyrYrSauoXGNgx0S7zceP07adYkJycEr56BOUTNPzbInooiN3fn1qw==", "dev": true, + "license": "Apache-2.0", "bin": { "tsc": "bin/tsc", "tsserver": "bin/tsserver" @@ -3434,15 +4195,15 @@ } }, "node_modules/typescript-eslint": { - "version": "8.8.0", - "resolved": "https://registry.npmjs.org/typescript-eslint/-/typescript-eslint-8.8.0.tgz", - "integrity": "sha512-BjIT/VwJ8+0rVO01ZQ2ZVnjE1svFBiRczcpr1t1Yxt7sT25VSbPfrJtDsQ8uQTy2pilX5nI9gwxhUyLULNentw==", + "version": "8.11.0", + "resolved": "https://registry.npmjs.org/typescript-eslint/-/typescript-eslint-8.11.0.tgz", + "integrity": "sha512-cBRGnW3FSlxaYwU8KfAewxFK5uzeOAp0l2KebIlPDOT5olVi65KDG/yjBooPBG0kGW/HLkoz1c/iuBFehcS3IA==", "dev": true, "license": "MIT", "dependencies": { - "@typescript-eslint/eslint-plugin": "8.8.0", - "@typescript-eslint/parser": "8.8.0", - "@typescript-eslint/utils": "8.8.0" + "@typescript-eslint/eslint-plugin": "8.11.0", + "@typescript-eslint/parser": "8.11.0", + "@typescript-eslint/utils": "8.11.0" }, "engines": { "node": "^18.18.0 || ^20.9.0 || >=21.1.0" @@ -3468,7 +4229,6 @@ "version": "6.19.8", "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-6.19.8.tgz", "integrity": "sha512-ve2KP6f/JnbPBFyobGHuerC9g1FYGn/F8n1LWTwNxCEzd6IfqTwUQcNXgEtmmQ6DlRrC1hrSrBnCZPokRrDHjw==", - "dev": true, "license": "MIT" }, "node_modules/unist-util-is": { @@ -3554,6 +4314,12 @@ "punycode": "^2.1.0" } }, + "node_modules/util-deprecate": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", + "integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==", + "license": "MIT" + }, "node_modules/v8-compile-cache-lib": { "version": "3.0.1", "resolved": "https://registry.npmjs.org/v8-compile-cache-lib/-/v8-compile-cache-lib-3.0.1.tgz", @@ -3591,6 +4357,22 @@ "url": "https://opencollective.com/unified" } }, + "node_modules/webidl-conversions": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-3.0.1.tgz", + "integrity": "sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ==", + "license": "BSD-2-Clause" + }, + "node_modules/whatwg-url": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-5.0.0.tgz", + "integrity": "sha512-saE57nupxk6v3HY35+jzBwYa0rKSy0XR8JSxZPwgLr7ys0IBzhGviA1/TUGJLmSVqs8pb9AnvICXEuOHLprYTw==", + "license": "MIT", + "dependencies": { + "tr46": "~0.0.3", + "webidl-conversions": "^3.0.0" + } + }, "node_modules/which": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", @@ -3607,6 +4389,15 @@ "node": ">= 8" } }, + "node_modules/wide-align": { + "version": "1.1.5", + "resolved": "https://registry.npmjs.org/wide-align/-/wide-align-1.1.5.tgz", + "integrity": "sha512-eDMORYaPNZ4sQIuuYPDHdQvf4gyCF9rEEV/yPxGfwPkRodwEgiMUUXTx/dex+Me0wxx53S+NgUHaP7y3MGlDmg==", + "license": "ISC", + "dependencies": { + "string-width": "^1.0.2 || 2 || 3 || 4" + } + }, "node_modules/word-wrap": { "version": "1.2.5", "resolved": "https://registry.npmjs.org/word-wrap/-/word-wrap-1.2.5.tgz", @@ -3654,67 +4445,94 @@ "url": "https://github.com/chalk/wrap-ansi?sponsor=1" } }, - "node_modules/wrap-ansi-cjs/node_modules/ansi-regex": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", - "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", + "node_modules/wrap-ansi/node_modules/ansi-regex": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.1.0.tgz", + "integrity": "sha512-7HSX4QQb4CspciLpVFwyRe79O3xsIZDDLER21kERQ71oaPodF8jL725AgJMFAYbooIqolJoRLuM81SpeUkpkvA==", "dev": true, "license": "MIT", "engines": { - "node": ">=8" + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/ansi-regex?sponsor=1" } }, - "node_modules/wrap-ansi-cjs/node_modules/ansi-styles": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", - "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "node_modules/wrap-ansi/node_modules/ansi-styles": { + "version": "6.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-6.2.1.tgz", + "integrity": "sha512-bN798gFfQX+viw3R7yrGWRqnrN2oRkEkUjjl4JNn4E8GxxbjtG3FbrEIIY3l8/hrwUwIeCZvi4QuOTP4MErVug==", "dev": true, "license": "MIT", - "dependencies": { - "color-convert": "^2.0.1" - }, "engines": { - "node": ">=8" + "node": ">=12" }, "funding": { "url": "https://github.com/chalk/ansi-styles?sponsor=1" } }, - "node_modules/wrap-ansi-cjs/node_modules/emoji-regex": { - "version": "8.0.0", - "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", - "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", + "node_modules/wrap-ansi/node_modules/emoji-regex": { + "version": "9.2.2", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-9.2.2.tgz", + "integrity": "sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==", "dev": true, "license": "MIT" }, - "node_modules/wrap-ansi-cjs/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==", + "node_modules/wrap-ansi/node_modules/string-width": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-5.1.2.tgz", + "integrity": "sha512-HnLOCR3vjcY8beoNLtcjZ5/nxn2afmME6lhrDrebokqMap+XbeW8n9TXpPDOqdGK5qcI3oT0GKTW6wC7EMiVqA==", "dev": true, "license": "MIT", "dependencies": { - "emoji-regex": "^8.0.0", - "is-fullwidth-code-point": "^3.0.0", - "strip-ansi": "^6.0.1" + "eastasianwidth": "^0.2.0", + "emoji-regex": "^9.2.2", + "strip-ansi": "^7.0.1" }, "engines": { - "node": ">=8" + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/wrap-ansi-cjs/node_modules/strip-ansi": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", - "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "node_modules/wrap-ansi/node_modules/strip-ansi": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.1.0.tgz", + "integrity": "sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==", "dev": true, "license": "MIT", "dependencies": { - "ansi-regex": "^5.0.1" + "ansi-regex": "^6.0.1" }, "engines": { - "node": ">=8" + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/strip-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==", + "license": "ISC" + }, + "node_modules/y18n": { + "version": "5.0.8", + "resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz", + "integrity": "sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==", + "license": "ISC", + "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==", + "license": "ISC" + }, "node_modules/yaml": { "version": "2.6.0", "resolved": "https://registry.npmjs.org/yaml/-/yaml-2.6.0.tgz", @@ -3728,6 +4546,33 @@ "node": ">= 14" } }, + "node_modules/yargs": { + "version": "16.2.0", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-16.2.0.tgz", + "integrity": "sha512-D1mvvtDG0L5ft/jGWkLpG1+m0eQxOfaBvTNELraWj22wSVUMWxZUvYgJYcKh6jGGIkJFhH4IZPQhR4TKpc8mBw==", + "license": "MIT", + "dependencies": { + "cliui": "^7.0.2", + "escalade": "^3.1.1", + "get-caller-file": "^2.0.5", + "require-directory": "^2.1.1", + "string-width": "^4.2.0", + "y18n": "^5.0.5", + "yargs-parser": "^20.2.2" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/yargs-parser": { + "version": "20.2.9", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-20.2.9.tgz", + "integrity": "sha512-y11nGElTIV+CT3Zv9t7VKl+Q3hTQoT9a1Qzezhhl6Rp21gJ/IVTW7Z3y9EWXhuUBC2Shnf+DX0antecpAwSP8w==", + "license": "ISC", + "engines": { + "node": ">=10" + } + }, "node_modules/yn": { "version": "3.1.1", "resolved": "https://registry.npmjs.org/yn/-/yn-3.1.1.tgz", diff --git a/mlflow/package.json b/mlflow/package.json index ab0cdce2..2667f7f3 100644 --- a/mlflow/package.json +++ b/mlflow/package.json @@ -42,5 +42,8 @@ }, "engines": { "node": ">=22.7.0" + }, + "dependencies": { + "@tensorflow/tfjs-node": "^4.22.0" } } From e18e303290e7e18b93d845a7920da0be9940a5ed Mon Sep 17 00:00:00 2001 From: Stephany Ho Date: Wed, 23 Oct 2024 22:15:48 -0400 Subject: [PATCH 206/357] Setup Jest config --- mlflow/jest.config.ts | 13 + mlflow/package-lock.json | 6595 +++++++++++++++++++++++++++++++------- mlflow/package.json | 7 +- 3 files changed, 5471 insertions(+), 1144 deletions(-) create mode 100644 mlflow/jest.config.ts diff --git a/mlflow/jest.config.ts b/mlflow/jest.config.ts new file mode 100644 index 00000000..ac9ff7f3 --- /dev/null +++ b/mlflow/jest.config.ts @@ -0,0 +1,13 @@ +import type { Config } from '@jest/types'; +const config: Config.InitialOptions = { + preset: 'ts-jest', // allows Jest to handle TS files without requiring to transpile them first + testEnvironment: 'node', // appropriate for most Node.js and TS projects + transform: { + '^.+\\.(ts|tsx)$': ['ts-jest', { tsconfig: 'tsconfig.json' }], + }, + roots: ['/src', '/tests/'], + moduleNameMapper: { '^@utils/(.*)$': '/src/utils/$1' }, + moduleFileExtensions: ['ts', 'js'], + moduleDirectories: ['node_modules', 'src'], +}; +export default config; diff --git a/mlflow/package-lock.json b/mlflow/package-lock.json index d01d536f..aa95ed08 100644 --- a/mlflow/package-lock.json +++ b/mlflow/package-lock.json @@ -11,9 +11,14 @@ "devDependencies": { "@eslint/js": "^9.12.0", "@types/eslint__js": "^8.42.3", + "@types/jest": "^29.5.14", "@types/node": "^22.5.4", + "@types/supertest": "^6.0.2", "eslint": "^9.12.0", + "jest": "^29.7.0", "rimraf": "^6.0.1", + "supertest": "^7.0.0", + "ts-jest": "^29.2.5", "ts-node": "^10.9.2", "tsc-alias": "^1.8.10", "tsx": "^4.19.1", @@ -25,704 +30,722 @@ "node": ">=22.7.0" } }, - "node_modules/@cspotcode/source-map-support": { - "version": "0.8.1", - "resolved": "https://registry.npmjs.org/@cspotcode/source-map-support/-/source-map-support-0.8.1.tgz", - "integrity": "sha512-IchNf6dN4tHoMFIn/7OE8LWZ19Y6q/67Bmf6vnGREv8RSbBVb9LPJxEcnwrcwX6ixSvaiGoomAUvu4YSxXrVgw==", + "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, - "license": "MIT", + "license": "Apache-2.0", "dependencies": { - "@jridgewell/trace-mapping": "0.3.9" + "@jridgewell/gen-mapping": "^0.3.5", + "@jridgewell/trace-mapping": "^0.3.24" }, "engines": { - "node": ">=12" + "node": ">=6.0.0" } }, - "node_modules/@esbuild/linux-x64": { - "version": "0.23.1", - "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.23.1.tgz", - "integrity": "sha512-EV6+ovTsEXCPAp58g2dD68LxoP/wK5pRvgy0J/HxPGB009omFPv3Yet0HiaqvrIrgPTBuC6wCH1LTOY91EO5hQ==", - "cpu": [ - "x64" - ], + "node_modules/@ampproject/remapping/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, "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=18" + "dependencies": { + "@jridgewell/resolve-uri": "^3.1.0", + "@jridgewell/sourcemap-codec": "^1.4.14" } }, - "node_modules/@eslint-community/eslint-utils": { - "version": "4.4.0", - "resolved": "https://registry.npmjs.org/@eslint-community/eslint-utils/-/eslint-utils-4.4.0.tgz", - "integrity": "sha512-1/sA4dwrzBAyeUoQ6oxahHKmrZvsnLCg4RfxW3ZFGGmQkSNQPFNLV9CUEFQP1x9EYXHTo5p6xdhZM1Ne9p/AfA==", + "node_modules/@babel/code-frame": { + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.25.9.tgz", + "integrity": "sha512-z88xeGxnzehn2sqZ8UdGQEvYErF1odv2CftxInpSYJt6uHuPe9YjahKZITGs3l5LeI9d2ROG+obuDAoSlqbNfQ==", "dev": true, "license": "MIT", "dependencies": { - "eslint-visitor-keys": "^3.3.0" + "@babel/highlight": "^7.25.9", + "picocolors": "^1.0.0" }, "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" - }, - "peerDependencies": { - "eslint": "^6.0.0 || ^7.0.0 || >=8.0.0" + "node": ">=6.9.0" } }, - "node_modules/@eslint-community/eslint-utils/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==", + "node_modules/@babel/compat-data": { + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.25.9.tgz", + "integrity": "sha512-yD+hEuJ/+wAJ4Ox2/rpNv5HIuPG82x3ZlQvYVn8iYCprdxzE7P1udpGF1jyjQVBU4dgznN+k2h103vxZ7NdPyw==", "dev": true, - "license": "Apache-2.0", + "license": "MIT", "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + "node": ">=6.9.0" + } + }, + "node_modules/@babel/core": { + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.25.9.tgz", + "integrity": "sha512-WYvQviPw+Qyib0v92AwNIrdLISTp7RfDkM7bPqBvpbnhY4wq8HvHBZREVdYDXk98C8BkOIVnHAY3yvj7AVISxQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@ampproject/remapping": "^2.2.0", + "@babel/code-frame": "^7.25.9", + "@babel/generator": "^7.25.9", + "@babel/helper-compilation-targets": "^7.25.9", + "@babel/helper-module-transforms": "^7.25.9", + "@babel/helpers": "^7.25.9", + "@babel/parser": "^7.25.9", + "@babel/template": "^7.25.9", + "@babel/traverse": "^7.25.9", + "@babel/types": "^7.25.9", + "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": { - "url": "https://opencollective.com/eslint" + "type": "opencollective", + "url": "https://opencollective.com/babel" } }, - "node_modules/@eslint-community/regexpp": { - "version": "4.11.1", - "resolved": "https://registry.npmjs.org/@eslint-community/regexpp/-/regexpp-4.11.1.tgz", - "integrity": "sha512-m4DVN9ZqskZoLU5GlWZadwDnYo3vAEydiUayB9widCl9ffWx2IvPnp6n3on5rJmziJSw9Bv+Z3ChDVdMwXCY8Q==", + "node_modules/@babel/core/node_modules/semver": { + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", "dev": true, - "license": "MIT", - "engines": { - "node": "^12.0.0 || ^14.0.0 || >=16.0.0" + "license": "ISC", + "bin": { + "semver": "bin/semver.js" } }, - "node_modules/@eslint/config-array": { - "version": "0.18.0", - "resolved": "https://registry.npmjs.org/@eslint/config-array/-/config-array-0.18.0.tgz", - "integrity": "sha512-fTxvnS1sRMu3+JjXwJG0j/i4RT9u4qJ+lqS/yCGap4lH4zZGzQ7tu+xZqQmcMZq5OBZDL4QRxQzRjkWcGt8IVw==", + "node_modules/@babel/generator": { + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.25.9.tgz", + "integrity": "sha512-omlUGkr5EaoIJrhLf9CJ0TvjBRpd9+AXRG//0GEQ9THSo8wPiTlbpy1/Ow8ZTrbXpjd9FHXfbFQx32I04ht0FA==", "dev": true, - "license": "Apache-2.0", + "license": "MIT", "dependencies": { - "@eslint/object-schema": "^2.1.4", - "debug": "^4.3.1", - "minimatch": "^3.1.2" + "@babel/types": "^7.25.9", + "@jridgewell/gen-mapping": "^0.3.5", + "@jridgewell/trace-mapping": "^0.3.25", + "jsesc": "^3.0.2" }, "engines": { - "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + "node": ">=6.9.0" } }, - "node_modules/@eslint/config-array/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==", + "node_modules/@babel/generator/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, "license": "MIT", "dependencies": { - "balanced-match": "^1.0.0", - "concat-map": "0.0.1" + "@jridgewell/resolve-uri": "^3.1.0", + "@jridgewell/sourcemap-codec": "^1.4.14" } }, - "node_modules/@eslint/config-array/node_modules/minimatch": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", - "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "node_modules/@babel/helper-compilation-targets": { + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.25.9.tgz", + "integrity": "sha512-j9Db8Suy6yV/VHa4qzrj9yZfZxhLWQdVnRlXxmKLYlhWUVB1sB2G5sxuWYXk/whHD9iW76PmNzxZ4UCnTQTVEQ==", "dev": true, - "license": "ISC", + "license": "MIT", "dependencies": { - "brace-expansion": "^1.1.7" + "@babel/compat-data": "^7.25.9", + "@babel/helper-validator-option": "^7.25.9", + "browserslist": "^4.24.0", + "lru-cache": "^5.1.1", + "semver": "^6.3.1" }, "engines": { - "node": "*" + "node": ">=6.9.0" } }, - "node_modules/@eslint/core": { - "version": "0.6.0", - "resolved": "https://registry.npmjs.org/@eslint/core/-/core-0.6.0.tgz", - "integrity": "sha512-8I2Q8ykA4J0x0o7cg67FPVnehcqWTBehu/lmY+bolPFHGjh49YzGBMXTvpqVgEbBdvNCSxj6iFgiIyHzf03lzg==", + "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, - "license": "Apache-2.0", - "engines": { - "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + "license": "ISC", + "dependencies": { + "yallist": "^3.0.2" } }, - "node_modules/@eslint/eslintrc": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-3.1.0.tgz", - "integrity": "sha512-4Bfj15dVJdoy3RfZmmo86RK1Fwzn6SstsvK9JS+BaVKqC6QQQQyXekNaC+g+LKNgkQ+2VhGAzm6hO40AhMR3zQ==", + "node_modules/@babel/helper-compilation-targets/node_modules/semver": { + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", + "dev": true, + "license": "ISC", + "bin": { + "semver": "bin/semver.js" + } + }, + "node_modules/@babel/helper-module-imports": { + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.25.9.tgz", + "integrity": "sha512-tnUA4RsrmflIM6W6RFTLFSXITtl0wKjgpnLgXyowocVPrbYrLUXSBXDgTs8BlbmIzIdlBySRQjINYs2BAkiLtw==", "dev": true, "license": "MIT", "dependencies": { - "ajv": "^6.12.4", - "debug": "^4.3.2", - "espree": "^10.0.1", - "globals": "^14.0.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" + "@babel/traverse": "^7.25.9", + "@babel/types": "^7.25.9" }, "engines": { - "node": "^18.18.0 || ^20.9.0 || >=21.1.0" - }, - "funding": { - "url": "https://opencollective.com/eslint" + "node": ">=6.9.0" } }, - "node_modules/@eslint/eslintrc/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==", + "node_modules/@babel/helper-module-transforms": { + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.25.9.tgz", + "integrity": "sha512-TvLZY/F3+GvdRYFZFyxMvnsKi+4oJdgZzU3BoGN9Uc2d9C6zfNwJcKKhjqLAhK8i46mv93jsO74fDh3ih6rpHA==", "dev": true, "license": "MIT", "dependencies": { - "balanced-match": "^1.0.0", - "concat-map": "0.0.1" + "@babel/helper-module-imports": "^7.25.9", + "@babel/helper-simple-access": "^7.25.9", + "@babel/helper-validator-identifier": "^7.25.9", + "@babel/traverse": "^7.25.9" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" } }, - "node_modules/@eslint/eslintrc/node_modules/minimatch": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", - "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "node_modules/@babel/helper-plugin-utils": { + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.25.9.tgz", + "integrity": "sha512-kSMlyUVdWe25rEsRGviIgOWnoT/nfABVWlqt9N19/dIPWViAOW2s9wznP5tURbs/IDuNk4gPy3YdYRgH3uxhBw==", "dev": true, - "license": "ISC", - "dependencies": { - "brace-expansion": "^1.1.7" - }, + "license": "MIT", "engines": { - "node": "*" + "node": ">=6.9.0" } }, - "node_modules/@eslint/js": { - "version": "9.12.0", - "resolved": "https://registry.npmjs.org/@eslint/js/-/js-9.12.0.tgz", - "integrity": "sha512-eohesHH8WFRUprDNyEREgqP6beG6htMeUYeCpkEgBCieCMme5r9zFWjzAJp//9S+Kub4rqE+jXe9Cp1a7IYIIA==", + "node_modules/@babel/helper-simple-access": { + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/helper-simple-access/-/helper-simple-access-7.25.9.tgz", + "integrity": "sha512-c6WHXuiaRsJTyHYLJV75t9IqsmTbItYfdj99PnzYGQZkYKvan5/2jKJ7gu31J3/BJ/A18grImSPModuyG/Eo0Q==", "dev": true, "license": "MIT", + "dependencies": { + "@babel/traverse": "^7.25.9", + "@babel/types": "^7.25.9" + }, "engines": { - "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + "node": ">=6.9.0" } }, - "node_modules/@eslint/object-schema": { - "version": "2.1.4", - "resolved": "https://registry.npmjs.org/@eslint/object-schema/-/object-schema-2.1.4.tgz", - "integrity": "sha512-BsWiH1yFGjXXS2yvrf5LyuoSIIbPrGUWob917o+BTKuZ7qJdxX8aJLRxs1fS9n6r7vESrq1OUqb68dANcFXuQQ==", + "node_modules/@babel/helper-string-parser": { + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.25.9.tgz", + "integrity": "sha512-4A/SCr/2KLd5jrtOMFzaKjVtAei3+2r/NChoBNoZ3EyP/+GlhoaEGoWOZUmFmoITP7zOJyHIMm+DYRd8o3PvHA==", "dev": true, - "license": "Apache-2.0", + "license": "MIT", "engines": { - "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + "node": ">=6.9.0" } }, - "node_modules/@eslint/plugin-kit": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/@eslint/plugin-kit/-/plugin-kit-0.2.0.tgz", - "integrity": "sha512-vH9PiIMMwvhCx31Af3HiGzsVNULDbyVkHXwlemn/B0TFj/00ho3y55efXrUZTfQipxoHC5u4xq6zblww1zm1Ig==", + "node_modules/@babel/helper-validator-identifier": { + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.25.9.tgz", + "integrity": "sha512-Ed61U6XJc3CVRfkERJWDz4dJwKe7iLmmJsbOGu9wSloNSFttHV0I8g6UAgb7qnK5ly5bGLPd4oXZlxCdANBOWQ==", "dev": true, - "license": "Apache-2.0", - "dependencies": { - "levn": "^0.4.1" - }, + "license": "MIT", "engines": { - "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + "node": ">=6.9.0" } }, - "node_modules/@humanfs/core": { - "version": "0.19.0", - "resolved": "https://registry.npmjs.org/@humanfs/core/-/core-0.19.0.tgz", - "integrity": "sha512-2cbWIHbZVEweE853g8jymffCA+NCMiuqeECeBBLm8dg2oFdjuGJhgN4UAbI+6v0CKbbhvtXA4qV8YR5Ji86nmw==", + "node_modules/@babel/helper-validator-option": { + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-option/-/helper-validator-option-7.25.9.tgz", + "integrity": "sha512-e/zv1co8pp55dNdEcCynfj9X7nyUKUXoUEwfXqaZt0omVOmDe9oOTdKStH4GmAw6zxMFs50ZayuMfHDKlO7Tfw==", "dev": true, - "license": "Apache-2.0", + "license": "MIT", "engines": { - "node": ">=18.18.0" + "node": ">=6.9.0" } }, - "node_modules/@humanfs/node": { - "version": "0.16.5", - "resolved": "https://registry.npmjs.org/@humanfs/node/-/node-0.16.5.tgz", - "integrity": "sha512-KSPA4umqSG4LHYRodq31VDwKAvaTF4xmVlzM8Aeh4PlU1JQ3IG0wiA8C25d3RQ9nJyM3mBHyI53K06VVL/oFFg==", + "node_modules/@babel/helpers": { + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.25.9.tgz", + "integrity": "sha512-oKWp3+usOJSzDZOucZUAMayhPz/xVjzymyDzUN8dk0Wd3RWMlGLXi07UCQ/CgQVb8LvXx3XBajJH4XGgkt7H7g==", "dev": true, - "license": "Apache-2.0", + "license": "MIT", "dependencies": { - "@humanfs/core": "^0.19.0", - "@humanwhocodes/retry": "^0.3.0" + "@babel/template": "^7.25.9", + "@babel/types": "^7.25.9" }, "engines": { - "node": ">=18.18.0" + "node": ">=6.9.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==", + "node_modules/@babel/highlight": { + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.25.9.tgz", + "integrity": "sha512-llL88JShoCsth8fF8R4SJnIn+WLvR6ccFxu1H3FlMhDontdcmZWf2HgIZ7AIqV3Xcck1idlohrN4EUBQz6klbw==", "dev": true, - "license": "Apache-2.0", - "engines": { - "node": ">=12.22" + "license": "MIT", + "dependencies": { + "@babel/helper-validator-identifier": "^7.25.9", + "chalk": "^2.4.2", + "js-tokens": "^4.0.0", + "picocolors": "^1.0.0" }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/nzakas" + "engines": { + "node": ">=6.9.0" } }, - "node_modules/@humanwhocodes/retry": { - "version": "0.3.1", - "resolved": "https://registry.npmjs.org/@humanwhocodes/retry/-/retry-0.3.1.tgz", - "integrity": "sha512-JBxkERygn7Bv/GbN5Rv8Ul6LVknS+5Bp6RgDC/O8gEBU/yeH5Ui5C/OlWrTb6qct7LjjfT6Re2NxB0ln0yYybA==", + "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, - "license": "Apache-2.0", - "engines": { - "node": ">=18.18" + "license": "MIT", + "dependencies": { + "color-convert": "^1.9.0" }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/nzakas" + "engines": { + "node": ">=4" } }, - "node_modules/@isaacs/cliui": { - "version": "8.0.2", - "resolved": "https://registry.npmjs.org/@isaacs/cliui/-/cliui-8.0.2.tgz", - "integrity": "sha512-O8jcjabXaleOG9DQ0+ARXWZBTfnP4WNAqzuiJK7ll44AmxGKv/J2M4TPjxjY3znBCfvBXFzucm1twdyFybFqEA==", + "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, - "license": "ISC", + "license": "MIT", "dependencies": { - "string-width": "^5.1.2", - "string-width-cjs": "npm:string-width@^4.2.0", - "strip-ansi": "^7.0.1", - "strip-ansi-cjs": "npm:strip-ansi@^6.0.1", - "wrap-ansi": "^8.1.0", - "wrap-ansi-cjs": "npm:wrap-ansi@^7.0.0" + "ansi-styles": "^3.2.1", + "escape-string-regexp": "^1.0.5", + "supports-color": "^5.3.0" }, "engines": { - "node": ">=12" + "node": ">=4" } }, - "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==", + "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, "license": "MIT", - "engines": { - "node": ">=6.0.0" + "dependencies": { + "color-name": "1.1.3" } }, - "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==", + "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, "license": "MIT" }, - "node_modules/@jridgewell/trace-mapping": { - "version": "0.3.9", - "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.9.tgz", - "integrity": "sha512-3Belt6tdc8bPgAtbcmdtNJlirVoTmEb5e2gC94PnkwEW9jI6CAHUeoG85tjWP5WquqfavoMtMwiG4P926ZKKuQ==", + "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, "license": "MIT", - "dependencies": { - "@jridgewell/resolve-uri": "^3.0.3", - "@jridgewell/sourcemap-codec": "^1.4.10" + "engines": { + "node": ">=0.8.0" } }, - "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==", + "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, "license": "MIT", - "dependencies": { - "@nodelib/fs.stat": "2.0.5", - "run-parallel": "^1.1.9" - }, "engines": { - "node": ">= 8" + "node": ">=4" } }, - "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==", + "node_modules/@babel/highlight/node_modules/supports-color": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", + "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", "dev": true, "license": "MIT", + "dependencies": { + "has-flag": "^3.0.0" + }, "engines": { - "node": ">= 8" + "node": ">=4" } }, - "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==", + "node_modules/@babel/parser": { + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.25.9.tgz", + "integrity": "sha512-aI3jjAAO1fh7vY/pBGsn1i9LDbRP43+asrRlkPuTXW5yHXtd1NgTEMudbBoDDxrf1daEEfPJqR+JBMakzrR4Dg==", "dev": true, "license": "MIT", "dependencies": { - "@nodelib/fs.scandir": "2.1.5", - "fastq": "^1.6.0" + "@babel/types": "^7.25.9" + }, + "bin": { + "parser": "bin/babel-parser.js" }, "engines": { - "node": ">= 8" + "node": ">=6.0.0" } }, - "node_modules/@shikijs/core": { - "version": "1.22.0", - "resolved": "https://registry.npmjs.org/@shikijs/core/-/core-1.22.0.tgz", - "integrity": "sha512-S8sMe4q71TJAW+qG93s5VaiihujRK6rqDFqBnxqvga/3LvqHEnxqBIOPkt//IdXVtHkQWKu4nOQNk0uBGicU7Q==", + "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, "license": "MIT", "dependencies": { - "@shikijs/engine-javascript": "1.22.0", - "@shikijs/engine-oniguruma": "1.22.0", - "@shikijs/types": "1.22.0", - "@shikijs/vscode-textmate": "^9.3.0", - "@types/hast": "^3.0.4", - "hast-util-to-html": "^9.0.3" + "@babel/helper-plugin-utils": "^7.8.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" } }, - "node_modules/@shikijs/engine-javascript": { - "version": "1.22.0", - "resolved": "https://registry.npmjs.org/@shikijs/engine-javascript/-/engine-javascript-1.22.0.tgz", - "integrity": "sha512-AeEtF4Gcck2dwBqCFUKYfsCq0s+eEbCEbkUuFou53NZ0sTGnJnJ/05KHQFZxpii5HMXbocV9URYVowOP2wH5kw==", + "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, "license": "MIT", "dependencies": { - "@shikijs/types": "1.22.0", - "@shikijs/vscode-textmate": "^9.3.0", - "oniguruma-to-js": "0.4.3" + "@babel/helper-plugin-utils": "^7.8.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" } }, - "node_modules/@shikijs/engine-oniguruma": { - "version": "1.22.0", - "resolved": "https://registry.npmjs.org/@shikijs/engine-oniguruma/-/engine-oniguruma-1.22.0.tgz", - "integrity": "sha512-5iBVjhu/DYs1HB0BKsRRFipRrD7rqjxlWTj4F2Pf+nQSPqc3kcyqFFeZXnBMzDf0HdqaFVvhDRAGiYNvyLP+Mw==", + "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, "license": "MIT", "dependencies": { - "@shikijs/types": "1.22.0", - "@shikijs/vscode-textmate": "^9.3.0" + "@babel/helper-plugin-utils": "^7.12.13" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" } }, - "node_modules/@shikijs/types": { - "version": "1.22.0", - "resolved": "https://registry.npmjs.org/@shikijs/types/-/types-1.22.0.tgz", - "integrity": "sha512-Fw/Nr7FGFhlQqHfxzZY8Cwtwk5E9nKDUgeLjZgt3UuhcM3yJR9xj3ZGNravZZok8XmEZMiYkSMTPlPkULB8nww==", + "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, "license": "MIT", "dependencies": { - "@shikijs/vscode-textmate": "^9.3.0", - "@types/hast": "^3.0.4" + "@babel/helper-plugin-utils": "^7.14.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" } }, - "node_modules/@shikijs/vscode-textmate": { - "version": "9.3.0", - "resolved": "https://registry.npmjs.org/@shikijs/vscode-textmate/-/vscode-textmate-9.3.0.tgz", - "integrity": "sha512-jn7/7ky30idSkd/O5yDBfAnVt+JJpepofP/POZ1iMOxK59cOfqIgg/Dj0eFsjOTMw+4ycJN0uhZH/Eb0bs/EUA==", - "dev": true, - "license": "MIT" - }, - "node_modules/@tsconfig/node10": { - "version": "1.0.11", - "resolved": "https://registry.npmjs.org/@tsconfig/node10/-/node10-1.0.11.tgz", - "integrity": "sha512-DcRjDCujK/kCk/cUe8Xz8ZSpm8mS3mNNpta+jGCA6USEDfktlNvm1+IuZ9eTcDbNk41BHwpHHeW+N1lKCz4zOw==", - "dev": true, - "license": "MIT" - }, - "node_modules/@tsconfig/node12": { - "version": "1.0.11", - "resolved": "https://registry.npmjs.org/@tsconfig/node12/-/node12-1.0.11.tgz", - "integrity": "sha512-cqefuRsh12pWyGsIoBKJA9luFu3mRxCA+ORZvA4ktLSzIuCUtWVxGIuXigEwO5/ywWFMZ2QEGKWvkZG1zDMTag==", - "dev": true, - "license": "MIT" - }, - "node_modules/@tsconfig/node14": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/@tsconfig/node14/-/node14-1.0.3.tgz", - "integrity": "sha512-ysT8mhdixWK6Hw3i1V2AeRqZ5WfXg1G43mqoYlM2nc6388Fq5jcXyr5mRsqViLx/GJYdoL0bfXD8nmF+Zn/Iow==", + "node_modules/@babel/plugin-syntax-import-attributes": { + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-import-attributes/-/plugin-syntax-import-attributes-7.25.9.tgz", + "integrity": "sha512-u3EN9ub8LyYvgTnrgp8gboElouayiwPdnM7x5tcnW3iSt09/lQYPwMNK40I9IUxo7QOZhAsPHCmmuO7EPdruqg==", "dev": true, - "license": "MIT" + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.25.9" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } }, - "node_modules/@tsconfig/node16": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/@tsconfig/node16/-/node16-1.0.4.tgz", - "integrity": "sha512-vxhUy4J8lyeyinH7Azl1pdd43GJhZH/tP2weN8TntQblOY+A0XbT8DJk1/oCPuOOyg/Ja757rG0CgHcWC8OfMA==", + "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, - "license": "MIT" + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.10.4" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } }, - "node_modules/@types/eslint": { - "version": "9.6.1", - "resolved": "https://registry.npmjs.org/@types/eslint/-/eslint-9.6.1.tgz", - "integrity": "sha512-FXx2pKgId/WyYo2jXw63kk7/+TY7u7AziEJxJAnSFzHlqTAS3Ync6SvgYAN/k4/PQpnnVuzoMuVnByKK2qp0ag==", + "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, "license": "MIT", "dependencies": { - "@types/estree": "*", - "@types/json-schema": "*" + "@babel/helper-plugin-utils": "^7.8.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" } }, - "node_modules/@types/eslint__js": { - "version": "8.42.3", - "resolved": "https://registry.npmjs.org/@types/eslint__js/-/eslint__js-8.42.3.tgz", - "integrity": "sha512-alfG737uhmPdnvkrLdZLcEKJ/B8s9Y4hrZ+YAdzUeoArBlSUERA2E87ROfOaS4jd/C45fzOoZzidLc1IPwLqOw==", + "node_modules/@babel/plugin-syntax-jsx": { + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-jsx/-/plugin-syntax-jsx-7.25.9.tgz", + "integrity": "sha512-ld6oezHQMZsZfp6pWtbjaNDF2tiiCYYDqQszHt5VV437lewP9aSi2Of99CK0D0XB21k7FLgnLcmQKyKzynfeAA==", "dev": true, "license": "MIT", "dependencies": { - "@types/eslint": "*" + "@babel/helper-plugin-utils": "^7.25.9" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" } }, - "node_modules/@types/estree": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.6.tgz", - "integrity": "sha512-AYnb1nQyY49te+VRAVgmzfcgjYS91mY5P0TKUDCLEM+gNnA+3T6rWITXRLYCpahpqSQbN5cE+gHpnPyXjHWxcw==", + "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, - "license": "MIT" + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.10.4" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } }, - "node_modules/@types/hast": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/@types/hast/-/hast-3.0.4.tgz", - "integrity": "sha512-WPs+bbQw5aCj+x6laNGWLH3wviHtoCv/P3+otBhbOhJgG8qtpdAMlTCxLtsTWA7LH1Oh/bFCHsBn0TPS5m30EQ==", + "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, "license": "MIT", "dependencies": { - "@types/unist": "*" + "@babel/helper-plugin-utils": "^7.8.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" } }, - "node_modules/@types/json-schema": { - "version": "7.0.15", - "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.15.tgz", - "integrity": "sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA==", + "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, - "license": "MIT" + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.10.4" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } }, - "node_modules/@types/mdast": { - "version": "4.0.4", - "resolved": "https://registry.npmjs.org/@types/mdast/-/mdast-4.0.4.tgz", - "integrity": "sha512-kGaNbPh1k7AFzgpud/gMdvIm5xuECykRR+JnWKQno9TAXVa6WIVCGTPvYGekIDL4uwCZQSYbUxNBSb1aUo79oA==", + "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, "license": "MIT", "dependencies": { - "@types/unist": "*" + "@babel/helper-plugin-utils": "^7.8.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" } }, - "node_modules/@types/node": { - "version": "22.7.4", - "resolved": "https://registry.npmjs.org/@types/node/-/node-22.7.4.tgz", - "integrity": "sha512-y+NPi1rFzDs1NdQHHToqeiX2TIS79SWEAw9GYhkkx8bD0ChpfqC+n2j5OXOCpzfojBEBt6DnEnnG9MY0zk1XLg==", + "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, "license": "MIT", "dependencies": { - "undici-types": "~6.19.2" + "@babel/helper-plugin-utils": "^7.8.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" } }, - "node_modules/@types/unist": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/@types/unist/-/unist-3.0.3.tgz", - "integrity": "sha512-ko/gIFJRv177XgZsZcBwnqJN5x/Gien8qNOn0D5bQU/zAzVf9Zt3BlcUiLqhV9y4ARk0GbT3tnUiPNgnTXzc/Q==", + "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, - "license": "MIT" + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.8.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } }, - "node_modules/@typescript-eslint/eslint-plugin": { - "version": "8.8.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-8.8.0.tgz", - "integrity": "sha512-wORFWjU30B2WJ/aXBfOm1LX9v9nyt9D3jsSOxC3cCaTQGCW5k4jNpmjFv3U7p/7s4yvdjHzwtv2Sd2dOyhjS0A==", + "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, "license": "MIT", "dependencies": { - "@eslint-community/regexpp": "^4.10.0", - "@typescript-eslint/scope-manager": "8.8.0", - "@typescript-eslint/type-utils": "8.8.0", - "@typescript-eslint/utils": "8.8.0", - "@typescript-eslint/visitor-keys": "8.8.0", - "graphemer": "^1.4.0", - "ignore": "^5.3.1", - "natural-compare": "^1.4.0", - "ts-api-utils": "^1.3.0" + "@babel/helper-plugin-utils": "^7.14.5" }, "engines": { - "node": "^18.18.0 || ^20.9.0 || >=21.1.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" + "node": ">=6.9.0" }, "peerDependencies": { - "@typescript-eslint/parser": "^8.0.0 || ^8.0.0-alpha.0", - "eslint": "^8.57.0 || ^9.0.0" - }, - "peerDependenciesMeta": { - "typescript": { - "optional": true - } + "@babel/core": "^7.0.0-0" } }, - "node_modules/@typescript-eslint/parser": { - "version": "8.8.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-8.8.0.tgz", - "integrity": "sha512-uEFUsgR+tl8GmzmLjRqz+VrDv4eoaMqMXW7ruXfgThaAShO9JTciKpEsB+TvnfFfbg5IpujgMXVV36gOJRLtZg==", + "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, - "license": "BSD-2-Clause", + "license": "MIT", "dependencies": { - "@typescript-eslint/scope-manager": "8.8.0", - "@typescript-eslint/types": "8.8.0", - "@typescript-eslint/typescript-estree": "8.8.0", - "@typescript-eslint/visitor-keys": "8.8.0", - "debug": "^4.3.4" + "@babel/helper-plugin-utils": "^7.14.5" }, "engines": { - "node": "^18.18.0 || ^20.9.0 || >=21.1.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" + "node": ">=6.9.0" }, "peerDependencies": { - "eslint": "^8.57.0 || ^9.0.0" - }, - "peerDependenciesMeta": { - "typescript": { - "optional": true - } + "@babel/core": "^7.0.0-0" } }, - "node_modules/@typescript-eslint/scope-manager": { - "version": "8.8.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-8.8.0.tgz", - "integrity": "sha512-EL8eaGC6gx3jDd8GwEFEV091210U97J0jeEHrAYvIYosmEGet4wJ+g0SYmLu+oRiAwbSA5AVrt6DxLHfdd+bUg==", + "node_modules/@babel/plugin-syntax-typescript": { + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-typescript/-/plugin-syntax-typescript-7.25.9.tgz", + "integrity": "sha512-hjMgRy5hb8uJJjUcdWunWVcoi9bGpJp8p5Ol1229PoN6aytsLwNMgmdftO23wnCLMfVmTwZDWMPNq/D1SY60JQ==", "dev": true, "license": "MIT", "dependencies": { - "@typescript-eslint/types": "8.8.0", - "@typescript-eslint/visitor-keys": "8.8.0" + "@babel/helper-plugin-utils": "^7.25.9" }, "engines": { - "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + "node": ">=6.9.0" }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" + "peerDependencies": { + "@babel/core": "^7.0.0-0" } }, - "node_modules/@typescript-eslint/type-utils": { - "version": "8.8.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-8.8.0.tgz", - "integrity": "sha512-IKwJSS7bCqyCeG4NVGxnOP6lLT9Okc3Zj8hLO96bpMkJab+10HIfJbMouLrlpyOr3yrQ1cA413YPFiGd1mW9/Q==", + "node_modules/@babel/template": { + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.25.9.tgz", + "integrity": "sha512-9DGttpmPvIxBb/2uwpVo3dqJ+O6RooAFOS+lB+xDqoE2PVCE8nfoHMdZLpfCQRLwvohzXISPZcgxt80xLfsuwg==", "dev": true, "license": "MIT", "dependencies": { - "@typescript-eslint/typescript-estree": "8.8.0", - "@typescript-eslint/utils": "8.8.0", - "debug": "^4.3.4", - "ts-api-utils": "^1.3.0" + "@babel/code-frame": "^7.25.9", + "@babel/parser": "^7.25.9", + "@babel/types": "^7.25.9" }, "engines": { - "node": "^18.18.0 || ^20.9.0 || >=21.1.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" + "node": ">=6.9.0" + } + }, + "node_modules/@babel/traverse": { + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.25.9.tgz", + "integrity": "sha512-ZCuvfwOwlz/bawvAuvcj8rrithP2/N55Tzz342AkTvq4qaWbGfmCk/tKhNaV2cthijKrPAA8SRJV5WWe7IBMJw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/code-frame": "^7.25.9", + "@babel/generator": "^7.25.9", + "@babel/parser": "^7.25.9", + "@babel/template": "^7.25.9", + "@babel/types": "^7.25.9", + "debug": "^4.3.1", + "globals": "^11.1.0" }, - "peerDependenciesMeta": { - "typescript": { - "optional": true - } + "engines": { + "node": ">=6.9.0" } }, - "node_modules/@typescript-eslint/types": { - "version": "8.8.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-8.8.0.tgz", - "integrity": "sha512-QJwc50hRCgBd/k12sTykOJbESe1RrzmX6COk8Y525C9l7oweZ+1lw9JiU56im7Amm8swlz00DRIlxMYLizr2Vw==", + "node_modules/@babel/traverse/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, "license": "MIT", "engines": { - "node": "^18.18.0 || ^20.9.0 || >=21.1.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" + "node": ">=4" } }, - "node_modules/@typescript-eslint/typescript-estree": { - "version": "8.8.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-8.8.0.tgz", - "integrity": "sha512-ZaMJwc/0ckLz5DaAZ+pNLmHv8AMVGtfWxZe/x2JVEkD5LnmhWiQMMcYT7IY7gkdJuzJ9P14fRy28lUrlDSWYdw==", + "node_modules/@babel/types": { + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.25.9.tgz", + "integrity": "sha512-OwS2CM5KocvQ/k7dFJa8i5bNGJP0hXWfVCfDkqRFP1IreH1JDC7wG6eCYCi0+McbfT8OR/kNqsI0UU0xP9H6PQ==", "dev": true, - "license": "BSD-2-Clause", + "license": "MIT", "dependencies": { - "@typescript-eslint/types": "8.8.0", - "@typescript-eslint/visitor-keys": "8.8.0", - "debug": "^4.3.4", - "fast-glob": "^3.3.2", - "is-glob": "^4.0.3", - "minimatch": "^9.0.4", - "semver": "^7.6.0", - "ts-api-utils": "^1.3.0" + "@babel/helper-string-parser": "^7.25.9", + "@babel/helper-validator-identifier": "^7.25.9" }, "engines": { - "node": "^18.18.0 || ^20.9.0 || >=21.1.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - }, - "peerDependenciesMeta": { - "typescript": { - "optional": true - } + "node": ">=6.9.0" } }, - "node_modules/@typescript-eslint/typescript-estree/node_modules/minimatch": { - "version": "9.0.5", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.5.tgz", - "integrity": "sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow==", + "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, - "license": "ISC", + "license": "MIT" + }, + "node_modules/@cspotcode/source-map-support": { + "version": "0.8.1", + "resolved": "https://registry.npmjs.org/@cspotcode/source-map-support/-/source-map-support-0.8.1.tgz", + "integrity": "sha512-IchNf6dN4tHoMFIn/7OE8LWZ19Y6q/67Bmf6vnGREv8RSbBVb9LPJxEcnwrcwX6ixSvaiGoomAUvu4YSxXrVgw==", + "dev": true, + "license": "MIT", "dependencies": { - "brace-expansion": "^2.0.1" + "@jridgewell/trace-mapping": "0.3.9" }, "engines": { - "node": ">=16 || 14 >=14.17" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" + "node": ">=12" } }, - "node_modules/@typescript-eslint/utils": { - "version": "8.8.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-8.8.0.tgz", - "integrity": "sha512-QE2MgfOTem00qrlPgyByaCHay9yb1+9BjnMFnSFkUKQfu7adBXDTnCAivURnuPPAG/qiB+kzKkZKmKfaMT0zVg==", + "node_modules/@esbuild/linux-x64": { + "version": "0.23.1", + "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.23.1.tgz", + "integrity": "sha512-EV6+ovTsEXCPAp58g2dD68LxoP/wK5pRvgy0J/HxPGB009omFPv3Yet0HiaqvrIrgPTBuC6wCH1LTOY91EO5hQ==", + "cpu": [ + "x64" + ], "dev": true, "license": "MIT", - "dependencies": { - "@eslint-community/eslint-utils": "^4.4.0", - "@typescript-eslint/scope-manager": "8.8.0", - "@typescript-eslint/types": "8.8.0", - "@typescript-eslint/typescript-estree": "8.8.0" - }, + "optional": true, + "os": [ + "linux" + ], "engines": { - "node": "^18.18.0 || ^20.9.0 || >=21.1.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - }, - "peerDependencies": { - "eslint": "^8.57.0 || ^9.0.0" + "node": ">=18" } }, - "node_modules/@typescript-eslint/visitor-keys": { - "version": "8.8.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-8.8.0.tgz", - "integrity": "sha512-8mq51Lx6Hpmd7HnA2fcHQo3YgfX1qbccxQOgZcb4tvasu//zXRaA1j5ZRFeCw/VRAdFi4mRM9DnZw0Nu0Q2d1g==", + "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, "license": "MIT", "dependencies": { - "@typescript-eslint/types": "8.8.0", - "eslint-visitor-keys": "^3.4.3" + "eslint-visitor-keys": "^3.3.0" }, "engines": { - "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" + "peerDependencies": { + "eslint": "^6.0.0 || ^7.0.0 || >=8.0.0" } }, - "node_modules/@typescript-eslint/visitor-keys/node_modules/eslint-visitor-keys": { + "node_modules/@eslint-community/eslint-utils/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==", @@ -735,601 +758,565 @@ "url": "https://opencollective.com/eslint" } }, - "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==", + "node_modules/@eslint-community/regexpp": { + "version": "4.11.1", + "resolved": "https://registry.npmjs.org/@eslint-community/regexpp/-/regexpp-4.11.1.tgz", + "integrity": "sha512-m4DVN9ZqskZoLU5GlWZadwDnYo3vAEydiUayB9widCl9ffWx2IvPnp6n3on5rJmziJSw9Bv+Z3ChDVdMwXCY8Q==", "dev": true, - "license": "ISC" + "license": "MIT", + "engines": { + "node": "^12.0.0 || ^14.0.0 || >=16.0.0" + } }, - "node_modules/acorn": { - "version": "8.12.1", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.12.1.tgz", - "integrity": "sha512-tcpGyI9zbizT9JbV6oYE477V6mTlXvvi0T0G3SNIYE2apm/G5huBa1+K89VGeovbg+jycCrfhl3ADxErOuO6Jg==", + "node_modules/@eslint/config-array": { + "version": "0.18.0", + "resolved": "https://registry.npmjs.org/@eslint/config-array/-/config-array-0.18.0.tgz", + "integrity": "sha512-fTxvnS1sRMu3+JjXwJG0j/i4RT9u4qJ+lqS/yCGap4lH4zZGzQ7tu+xZqQmcMZq5OBZDL4QRxQzRjkWcGt8IVw==", "dev": true, - "license": "MIT", - "bin": { - "acorn": "bin/acorn" + "license": "Apache-2.0", + "dependencies": { + "@eslint/object-schema": "^2.1.4", + "debug": "^4.3.1", + "minimatch": "^3.1.2" }, "engines": { - "node": ">=0.4.0" + "node": "^18.18.0 || ^20.9.0 || >=21.1.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==", + "node_modules/@eslint/config-array/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, "license": "MIT", - "peerDependencies": { - "acorn": "^6.0.0 || ^7.0.0 || ^8.0.0" + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" } }, - "node_modules/acorn-walk": { - "version": "8.3.4", - "resolved": "https://registry.npmjs.org/acorn-walk/-/acorn-walk-8.3.4.tgz", - "integrity": "sha512-ueEepnujpqee2o5aIYnvHU6C0A42MNdsIDeqy5BydrkuC5R1ZuUFnm27EeFJGoEHJQgn3uleRvmTXaJgfXbt4g==", + "node_modules/@eslint/config-array/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, - "license": "MIT", + "license": "ISC", "dependencies": { - "acorn": "^8.11.0" + "brace-expansion": "^1.1.7" }, "engines": { - "node": ">=0.4.0" + "node": "*" } }, - "node_modules/ajv": { - "version": "6.12.6", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", - "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", + "node_modules/@eslint/core": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/@eslint/core/-/core-0.6.0.tgz", + "integrity": "sha512-8I2Q8ykA4J0x0o7cg67FPVnehcqWTBehu/lmY+bolPFHGjh49YzGBMXTvpqVgEbBdvNCSxj6iFgiIyHzf03lzg==", "dev": true, - "license": "MIT", - "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" + "license": "Apache-2.0", + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" } }, - "node_modules/ansi-regex": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.1.0.tgz", - "integrity": "sha512-7HSX4QQb4CspciLpVFwyRe79O3xsIZDDLER21kERQ71oaPodF8jL725AgJMFAYbooIqolJoRLuM81SpeUkpkvA==", + "node_modules/@eslint/eslintrc": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-3.1.0.tgz", + "integrity": "sha512-4Bfj15dVJdoy3RfZmmo86RK1Fwzn6SstsvK9JS+BaVKqC6QQQQyXekNaC+g+LKNgkQ+2VhGAzm6hO40AhMR3zQ==", "dev": true, "license": "MIT", + "dependencies": { + "ajv": "^6.12.4", + "debug": "^4.3.2", + "espree": "^10.0.1", + "globals": "^14.0.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" + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" }, "funding": { - "url": "https://github.com/chalk/ansi-regex?sponsor=1" + "url": "https://opencollective.com/eslint" } }, - "node_modules/ansi-styles": { - "version": "6.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-6.2.1.tgz", - "integrity": "sha512-bN798gFfQX+viw3R7yrGWRqnrN2oRkEkUjjl4JNn4E8GxxbjtG3FbrEIIY3l8/hrwUwIeCZvi4QuOTP4MErVug==", + "node_modules/@eslint/eslintrc/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, "license": "MIT", - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.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==", + "node_modules/@eslint/eslintrc/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, "license": "ISC", "dependencies": { - "normalize-path": "^3.0.0", - "picomatch": "^2.0.4" + "brace-expansion": "^1.1.7" }, "engines": { - "node": ">= 8" + "node": "*" } }, - "node_modules/arg": { - "version": "4.1.3", - "resolved": "https://registry.npmjs.org/arg/-/arg-4.1.3.tgz", - "integrity": "sha512-58S9QDqG0Xx27YwPSt9fJxivjYl432YCwfDMfZ+71RAqUrZef7LrKQZ3LHLOwCS4FLNBplP533Zx895SeOCHvA==", - "dev": true, - "license": "MIT" - }, - "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, - "license": "Python-2.0" - }, - "node_modules/array-union": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/array-union/-/array-union-2.1.0.tgz", - "integrity": "sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw==", + "node_modules/@eslint/js": { + "version": "9.12.0", + "resolved": "https://registry.npmjs.org/@eslint/js/-/js-9.12.0.tgz", + "integrity": "sha512-eohesHH8WFRUprDNyEREgqP6beG6htMeUYeCpkEgBCieCMme5r9zFWjzAJp//9S+Kub4rqE+jXe9Cp1a7IYIIA==", "dev": true, "license": "MIT", "engines": { - "node": ">=8" + "node": "^18.18.0 || ^20.9.0 || >=21.1.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==", + "node_modules/@eslint/object-schema": { + "version": "2.1.4", + "resolved": "https://registry.npmjs.org/@eslint/object-schema/-/object-schema-2.1.4.tgz", + "integrity": "sha512-BsWiH1yFGjXXS2yvrf5LyuoSIIbPrGUWob917o+BTKuZ7qJdxX8aJLRxs1fS9n6r7vESrq1OUqb68dANcFXuQQ==", "dev": true, - "license": "MIT" + "license": "Apache-2.0", + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + } }, - "node_modules/binary-extensions": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.3.0.tgz", - "integrity": "sha512-Ceh+7ox5qe7LJuLHoY0feh3pHuUDHAcRUeyL2VYghZwfpkNIy/+8Ocg0a3UuSoYzavmylwuLWQOf3hl0jjMMIw==", + "node_modules/@eslint/plugin-kit": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/@eslint/plugin-kit/-/plugin-kit-0.2.0.tgz", + "integrity": "sha512-vH9PiIMMwvhCx31Af3HiGzsVNULDbyVkHXwlemn/B0TFj/00ho3y55efXrUZTfQipxoHC5u4xq6zblww1zm1Ig==", "dev": true, - "license": "MIT", - "engines": { - "node": ">=8" + "license": "Apache-2.0", + "dependencies": { + "levn": "^0.4.1" }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" } }, - "node_modules/brace-expansion": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", - "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", + "node_modules/@humanfs/core": { + "version": "0.19.0", + "resolved": "https://registry.npmjs.org/@humanfs/core/-/core-0.19.0.tgz", + "integrity": "sha512-2cbWIHbZVEweE853g8jymffCA+NCMiuqeECeBBLm8dg2oFdjuGJhgN4UAbI+6v0CKbbhvtXA4qV8YR5Ji86nmw==", "dev": true, - "license": "MIT", - "dependencies": { - "balanced-match": "^1.0.0" + "license": "Apache-2.0", + "engines": { + "node": ">=18.18.0" } }, - "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==", + "node_modules/@humanfs/node": { + "version": "0.16.5", + "resolved": "https://registry.npmjs.org/@humanfs/node/-/node-0.16.5.tgz", + "integrity": "sha512-KSPA4umqSG4LHYRodq31VDwKAvaTF4xmVlzM8Aeh4PlU1JQ3IG0wiA8C25d3RQ9nJyM3mBHyI53K06VVL/oFFg==", "dev": true, - "license": "MIT", + "license": "Apache-2.0", "dependencies": { - "fill-range": "^7.1.1" + "@humanfs/core": "^0.19.0", + "@humanwhocodes/retry": "^0.3.0" }, "engines": { - "node": ">=8" + "node": ">=18.18.0" } }, - "node_modules/callsites": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz", - "integrity": "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==", + "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, - "license": "MIT", + "license": "Apache-2.0", "engines": { - "node": ">=6" + "node": ">=12.22" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/nzakas" } }, - "node_modules/ccount": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/ccount/-/ccount-2.0.1.tgz", - "integrity": "sha512-eyrF0jiFpY+3drT6383f1qhkbGsLSifNAjA61IUjZjmLCWjItY6LB9ft9YhoDgwfmclB2zhu51Lc7+95b8NRAg==", + "node_modules/@humanwhocodes/retry": { + "version": "0.3.1", + "resolved": "https://registry.npmjs.org/@humanwhocodes/retry/-/retry-0.3.1.tgz", + "integrity": "sha512-JBxkERygn7Bv/GbN5Rv8Ul6LVknS+5Bp6RgDC/O8gEBU/yeH5Ui5C/OlWrTb6qct7LjjfT6Re2NxB0ln0yYybA==", "dev": true, - "license": "MIT", + "license": "Apache-2.0", + "engines": { + "node": ">=18.18" + }, "funding": { "type": "github", - "url": "https://github.com/sponsors/wooorm" + "url": "https://github.com/sponsors/nzakas" } }, - "node_modules/chalk": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", - "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "node_modules/@isaacs/cliui": { + "version": "8.0.2", + "resolved": "https://registry.npmjs.org/@isaacs/cliui/-/cliui-8.0.2.tgz", + "integrity": "sha512-O8jcjabXaleOG9DQ0+ARXWZBTfnP4WNAqzuiJK7ll44AmxGKv/J2M4TPjxjY3znBCfvBXFzucm1twdyFybFqEA==", "dev": true, - "license": "MIT", + "license": "ISC", "dependencies": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" + "string-width": "^5.1.2", + "string-width-cjs": "npm:string-width@^4.2.0", + "strip-ansi": "^7.0.1", + "strip-ansi-cjs": "npm:strip-ansi@^6.0.1", + "wrap-ansi": "^8.1.0", + "wrap-ansi-cjs": "npm:wrap-ansi@^7.0.0" }, "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/chalk/chalk?sponsor=1" + "node": ">=12" } }, - "node_modules/chalk/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==", + "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, - "license": "MIT", + "license": "ISC", "dependencies": { - "color-convert": "^2.0.1" + "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" - }, - "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" } }, - "node_modules/character-entities-html4": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/character-entities-html4/-/character-entities-html4-2.1.0.tgz", - "integrity": "sha512-1v7fgQRj6hnSwFpq1Eu0ynr/CDEw0rXo2B61qXrLNdHZmPKgb7fqS1a2JwF0rISo9q77jDI8VMEHoApn8qDoZA==", + "node_modules/@istanbuljs/load-nyc-config/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, "license": "MIT", - "funding": { - "type": "github", - "url": "https://github.com/sponsors/wooorm" + "dependencies": { + "sprintf-js": "~1.0.2" } }, - "node_modules/character-entities-legacy": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/character-entities-legacy/-/character-entities-legacy-3.0.0.tgz", - "integrity": "sha512-RpPp0asT/6ufRm//AJVwpViZbGM/MkjQFxJccQRHmISF/22NBtsHqAWmL+/pmkPWoIUJdWyeVleTl1wydHATVQ==", + "node_modules/@istanbuljs/load-nyc-config/node_modules/find-up": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz", + "integrity": "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==", "dev": true, "license": "MIT", - "funding": { - "type": "github", - "url": "https://github.com/sponsors/wooorm" + "dependencies": { + "locate-path": "^5.0.0", + "path-exists": "^4.0.0" + }, + "engines": { + "node": ">=8" } }, - "node_modules/chokidar": { - "version": "3.6.0", - "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.6.0.tgz", - "integrity": "sha512-7VT13fmjotKpGipCW9JEQAusEPE+Ei8nl6/g4FBAmIm0GOOLMua9NDDo/DWp0ZAxCr3cPq5ZpBqmPAQgDda2Pw==", + "node_modules/@istanbuljs/load-nyc-config/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, "license": "MIT", "dependencies": { - "anymatch": "~3.1.2", - "braces": "~3.0.2", - "glob-parent": "~5.1.2", - "is-binary-path": "~2.1.0", - "is-glob": "~4.0.1", - "normalize-path": "~3.0.0", - "readdirp": "~3.6.0" - }, - "engines": { - "node": ">= 8.10.0" - }, - "funding": { - "url": "https://paulmillr.com/funding/" + "argparse": "^1.0.7", + "esprima": "^4.0.0" }, - "optionalDependencies": { - "fsevents": "~2.3.2" + "bin": { + "js-yaml": "bin/js-yaml.js" } }, - "node_modules/chokidar/node_modules/glob-parent": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", - "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", + "node_modules/@istanbuljs/load-nyc-config/node_modules/locate-path": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz", + "integrity": "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==", "dev": true, - "license": "ISC", + "license": "MIT", "dependencies": { - "is-glob": "^4.0.1" + "p-locate": "^4.1.0" }, "engines": { - "node": ">= 6" + "node": ">=8" } }, - "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==", + "node_modules/@istanbuljs/load-nyc-config/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, "license": "MIT", "dependencies": { - "color-name": "~1.1.4" + "p-try": "^2.0.0" }, "engines": { - "node": ">=7.0.0" + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "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, - "license": "MIT" - }, - "node_modules/comma-separated-tokens": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/comma-separated-tokens/-/comma-separated-tokens-2.0.3.tgz", - "integrity": "sha512-Fu4hJdvzeylCfQPp9SGWidpzrMs7tTrlu6Vb8XGaRGck8QSNZJJp538Wrb60Lax4fPwR64ViY468OIUTbRlGZg==", + "node_modules/@istanbuljs/load-nyc-config/node_modules/p-locate": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-4.1.0.tgz", + "integrity": "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==", "dev": true, "license": "MIT", - "funding": { - "type": "github", - "url": "https://github.com/sponsors/wooorm" + "dependencies": { + "p-limit": "^2.2.0" + }, + "engines": { + "node": ">=8" } }, - "node_modules/commander": { - "version": "9.5.0", - "resolved": "https://registry.npmjs.org/commander/-/commander-9.5.0.tgz", - "integrity": "sha512-KRs7WVDKg86PWiuAqhDrAQnTXZKraVcCc6vFdL14qrZ/DcWwuRo7VoiYXalXO7S5GKpqYiVEwCbgFDfxNHKJBQ==", + "node_modules/@istanbuljs/load-nyc-config/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, "license": "MIT", "engines": { - "node": "^12.20.0 || >=14" + "node": ">=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, - "license": "MIT" - }, - "node_modules/create-require": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/create-require/-/create-require-1.1.1.tgz", - "integrity": "sha512-dcKFX3jn0MpIaXjisoRvexIJVEKzaq7z2rZKxf+MSr9TkdmHmsU4m2lcLojrj/FHl8mk5VxMmYA+ftRkP/3oKQ==", + "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, - "license": "MIT" + "license": "MIT", + "engines": { + "node": ">=8" + } }, - "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==", + "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, "license": "MIT", "dependencies": { - "path-key": "^3.1.0", - "shebang-command": "^2.0.0", - "which": "^2.0.1" + "@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": ">= 8" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, - "node_modules/debug": { - "version": "4.3.7", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.7.tgz", - "integrity": "sha512-Er2nc/H7RrMXZBFCEim6TCmMk02Z8vLC2Rbi1KEBggpo0fS6l0S1nnapwmIi3yW/+GOJap1Krg4w0Hg80oCqgQ==", + "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, "license": "MIT", "dependencies": { - "ms": "^2.1.3" + "@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": ">=6.0" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + }, + "peerDependencies": { + "node-notifier": "^8.0.1 || ^9.0.0 || ^10.0.0" }, "peerDependenciesMeta": { - "supports-color": { + "node-notifier": { "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, - "license": "MIT" - }, - "node_modules/dequal": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/dequal/-/dequal-2.0.3.tgz", - "integrity": "sha512-0je+qPKHEMohvfRTCEo3CrPG6cAzAYgmzKyxRiYSSDkS6eGJdyVJm7WaYA5ECaAD9wLB2T4EEeymA5aFVcYXCA==", + "node_modules/@jest/core/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, "license": "MIT", "engines": { - "node": ">=6" + "node": ">=8" } }, - "node_modules/devlop": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/devlop/-/devlop-1.1.0.tgz", - "integrity": "sha512-RWmIqhcFf1lRYBvNmr7qTNuyCt/7/ns2jbpp1+PalgE/rDQcBT0fioSMUpJ93irlUhC5hrg4cYqe6U+0ImW0rA==", + "node_modules/@jest/core/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, "license": "MIT", "dependencies": { - "dequal": "^2.0.0" + "ansi-regex": "^5.0.1" }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/wooorm" + "engines": { + "node": ">=8" } }, - "node_modules/diff": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/diff/-/diff-4.0.2.tgz", - "integrity": "sha512-58lmxKSA4BNyLz+HHMUzlOEpg09FV+ev6ZMe3vJihgdxzgcwZ8VoEEPmALCZG9LmqfVoNMMKpttIYTVG6uDY7A==", + "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, - "license": "BSD-3-Clause", + "license": "MIT", + "dependencies": { + "@jest/fake-timers": "^29.7.0", + "@jest/types": "^29.6.3", + "@types/node": "*", + "jest-mock": "^29.7.0" + }, "engines": { - "node": ">=0.3.1" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, - "node_modules/dir-glob": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/dir-glob/-/dir-glob-3.0.1.tgz", - "integrity": "sha512-WkrWp9GR4KXfKGYzOLmTuGVi1UWFfws377n9cc55/tb6DuqyF6pcQ5AbiHEshaDpY9v6oaSr2XCDidGmMwdzIA==", + "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, "license": "MIT", "dependencies": { - "path-type": "^4.0.0" + "expect": "^29.7.0", + "jest-snapshot": "^29.7.0" }, "engines": { - "node": ">=8" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, - "node_modules/eastasianwidth": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/eastasianwidth/-/eastasianwidth-0.2.0.tgz", - "integrity": "sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA==", - "dev": true, - "license": "MIT" - }, - "node_modules/emoji-regex": { - "version": "9.2.2", - "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-9.2.2.tgz", - "integrity": "sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==", - "dev": true, - "license": "MIT" - }, - "node_modules/entities": { - "version": "4.5.0", - "resolved": "https://registry.npmjs.org/entities/-/entities-4.5.0.tgz", - "integrity": "sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw==", + "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, - "license": "BSD-2-Clause", - "engines": { - "node": ">=0.12" + "license": "MIT", + "dependencies": { + "jest-get-type": "^29.6.3" }, - "funding": { - "url": "https://github.com/fb55/entities?sponsor=1" + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, - "node_modules/esbuild": { - "version": "0.23.1", - "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.23.1.tgz", - "integrity": "sha512-VVNz/9Sa0bs5SELtn3f7qhJCDPCF5oMEl5cO9/SSinpE9hbPVvxbd572HH5AKiP7WD8INO53GgfDDhRjkylHEg==", + "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, - "hasInstallScript": true, "license": "MIT", - "bin": { - "esbuild": "bin/esbuild" + "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": ">=18" - }, - "optionalDependencies": { - "@esbuild/aix-ppc64": "0.23.1", - "@esbuild/android-arm": "0.23.1", - "@esbuild/android-arm64": "0.23.1", - "@esbuild/android-x64": "0.23.1", - "@esbuild/darwin-arm64": "0.23.1", - "@esbuild/darwin-x64": "0.23.1", - "@esbuild/freebsd-arm64": "0.23.1", - "@esbuild/freebsd-x64": "0.23.1", - "@esbuild/linux-arm": "0.23.1", - "@esbuild/linux-arm64": "0.23.1", - "@esbuild/linux-ia32": "0.23.1", - "@esbuild/linux-loong64": "0.23.1", - "@esbuild/linux-mips64el": "0.23.1", - "@esbuild/linux-ppc64": "0.23.1", - "@esbuild/linux-riscv64": "0.23.1", - "@esbuild/linux-s390x": "0.23.1", - "@esbuild/linux-x64": "0.23.1", - "@esbuild/netbsd-x64": "0.23.1", - "@esbuild/openbsd-arm64": "0.23.1", - "@esbuild/openbsd-x64": "0.23.1", - "@esbuild/sunos-x64": "0.23.1", - "@esbuild/win32-arm64": "0.23.1", - "@esbuild/win32-ia32": "0.23.1", - "@esbuild/win32-x64": "0.23.1" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, - "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==", + "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, "license": "MIT", - "engines": { - "node": ">=10" + "dependencies": { + "@jest/environment": "^29.7.0", + "@jest/expect": "^29.7.0", + "@jest/types": "^29.6.3", + "jest-mock": "^29.7.0" }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, - "node_modules/eslint": { - "version": "9.12.0", - "resolved": "https://registry.npmjs.org/eslint/-/eslint-9.12.0.tgz", - "integrity": "sha512-UVIOlTEWxwIopRL1wgSQYdnVDcEvs2wyaO6DGo5mXqe3r16IoCNWkR29iHhyaP4cICWjbgbmFUGAhh0GJRuGZw==", + "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, "license": "MIT", "dependencies": { - "@eslint-community/eslint-utils": "^4.2.0", - "@eslint-community/regexpp": "^4.11.0", - "@eslint/config-array": "^0.18.0", - "@eslint/core": "^0.6.0", - "@eslint/eslintrc": "^3.1.0", - "@eslint/js": "9.12.0", - "@eslint/plugin-kit": "^0.2.0", - "@humanfs/node": "^0.16.5", - "@humanwhocodes/module-importer": "^1.0.1", - "@humanwhocodes/retry": "^0.3.1", - "@types/estree": "^1.0.6", - "@types/json-schema": "^7.0.15", - "ajv": "^6.12.4", + "@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", - "cross-spawn": "^7.0.2", - "debug": "^4.3.2", - "escape-string-regexp": "^4.0.0", - "eslint-scope": "^8.1.0", - "eslint-visitor-keys": "^4.1.0", - "espree": "^10.2.0", - "esquery": "^1.5.0", - "esutils": "^2.0.2", - "fast-deep-equal": "^3.1.3", - "file-entry-cache": "^8.0.0", - "find-up": "^5.0.0", - "glob-parent": "^6.0.2", - "ignore": "^5.2.0", - "imurmurhash": "^0.1.4", - "is-glob": "^4.0.0", - "json-stable-stringify-without-jsonify": "^1.0.1", - "lodash.merge": "^4.6.2", - "minimatch": "^3.1.2", - "natural-compare": "^1.4.0", - "optionator": "^0.9.3", - "text-table": "^0.2.0" - }, - "bin": { - "eslint": "bin/eslint.js" - }, - "engines": { - "node": "^18.18.0 || ^20.9.0 || >=21.1.0" - }, - "funding": { - "url": "https://eslint.org/donate" + "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": { - "jiti": "*" + "node-notifier": "^8.0.1 || ^9.0.0 || ^10.0.0" }, "peerDependenciesMeta": { - "jiti": { + "node-notifier": { "optional": true } } }, - "node_modules/eslint-scope": { - "version": "8.1.0", - "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-8.1.0.tgz", - "integrity": "sha512-14dSvlhaVhKKsa9Fx1l8A17s7ah7Ef7wCakJ10LYk6+GYmP9yDti2oq2SEwcyndt6knfcZyhyxwY3i9yL78EQw==", + "node_modules/@jest/reporters/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, - "license": "BSD-2-Clause", + "license": "MIT", "dependencies": { - "esrecurse": "^4.3.0", - "estraverse": "^5.2.0" - }, - "engines": { - "node": "^18.18.0 || ^20.9.0 || >=21.1.0" - }, - "funding": { - "url": "https://opencollective.com/eslint" + "@jridgewell/resolve-uri": "^3.1.0", + "@jridgewell/sourcemap-codec": "^1.4.14" } }, - "node_modules/eslint-visitor-keys": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-4.1.0.tgz", - "integrity": "sha512-Q7lok0mqMUSf5a/AdAZkA5a/gHcO6snwQClVNNvFKCAVlxXucdU8pKydU5ZVZjBx5xr37vGbFFWtLQYreLzrZg==", + "node_modules/@jest/reporters/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, - "license": "Apache-2.0", + "license": "MIT", "engines": { - "node": "^18.18.0 || ^20.9.0 || >=21.1.0" - }, - "funding": { - "url": "https://opencollective.com/eslint" + "node": ">=8" } }, - "node_modules/eslint/node_modules/brace-expansion": { + "node_modules/@jest/reporters/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==", @@ -1340,7 +1327,29 @@ "concat-map": "0.0.1" } }, - "node_modules/eslint/node_modules/minimatch": { + "node_modules/@jest/reporters/node_modules/glob": { + "version": "7.2.3", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", + "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", + "deprecated": "Glob versions prior to v9 are no longer supported", + "dev": true, + "license": "ISC", + "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/@jest/reporters/node_modules/minimatch": { "version": "3.1.2", "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", @@ -1353,478 +1362,3755 @@ "node": "*" } }, - "node_modules/espree": { - "version": "10.2.0", - "resolved": "https://registry.npmjs.org/espree/-/espree-10.2.0.tgz", - "integrity": "sha512-upbkBJbckcCNBDBDXEbuhjbP68n+scUd3k/U2EkyM9nw+I/jPiL4cLF/Al06CF96wRltFda16sxDFrxsI1v0/g==", + "node_modules/@jest/reporters/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, - "license": "BSD-2-Clause", + "license": "MIT", "dependencies": { - "acorn": "^8.12.0", - "acorn-jsx": "^5.3.2", - "eslint-visitor-keys": "^4.1.0" + "ansi-regex": "^5.0.1" }, "engines": { - "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + "node": ">=8" + } + }, + "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, + "license": "MIT", + "dependencies": { + "@sinclair/typebox": "^0.27.8" }, - "funding": { - "url": "https://opencollective.com/eslint" + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, - "node_modules/esquery": { - "version": "1.6.0", - "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.6.0.tgz", - "integrity": "sha512-ca9pw9fomFcKPvFLXhBKUK90ZvGibiGOvRJNbjljY7s7uq/5YO4BOzcYtJqExdx99rF6aAcnRxHmcUHcz6sQsg==", + "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, - "license": "BSD-3-Clause", + "license": "MIT", "dependencies": { - "estraverse": "^5.1.0" + "@jridgewell/trace-mapping": "^0.3.18", + "callsites": "^3.0.0", + "graceful-fs": "^4.2.9" }, "engines": { - "node": ">=0.10" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, - "node_modules/esrecurse": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.3.0.tgz", - "integrity": "sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==", + "node_modules/@jest/source-map/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, - "license": "BSD-2-Clause", + "license": "MIT", "dependencies": { - "estraverse": "^5.2.0" + "@jridgewell/resolve-uri": "^3.1.0", + "@jridgewell/sourcemap-codec": "^1.4.14" + } + }, + "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, + "license": "MIT", + "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": ">=4.0" + "node": "^14.15.0 || ^16.10.0 || >=18.0.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==", + "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, - "license": "BSD-2-Clause", + "license": "MIT", + "dependencies": { + "@jest/test-result": "^29.7.0", + "graceful-fs": "^4.2.9", + "jest-haste-map": "^29.7.0", + "slash": "^3.0.0" + }, "engines": { - "node": ">=4.0" + "node": "^14.15.0 || ^16.10.0 || >=18.0.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==", + "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, - "license": "BSD-2-Clause", + "license": "MIT", + "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/transform/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, + "license": "MIT", + "dependencies": { + "@jridgewell/resolve-uri": "^3.1.0", + "@jridgewell/sourcemap-codec": "^1.4.14" + } + }, + "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, + "license": "MIT", + "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, + "license": "MIT", + "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/gen-mapping/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, + "license": "MIT", + "dependencies": { + "@jridgewell/resolve-uri": "^3.1.0", + "@jridgewell/sourcemap-codec": "^1.4.14" + } + }, + "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, + "license": "MIT", + "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, + "license": "MIT", + "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, + "license": "MIT" + }, + "node_modules/@jridgewell/trace-mapping": { + "version": "0.3.9", + "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.9.tgz", + "integrity": "sha512-3Belt6tdc8bPgAtbcmdtNJlirVoTmEb5e2gC94PnkwEW9jI6CAHUeoG85tjWP5WquqfavoMtMwiG4P926ZKKuQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jridgewell/resolve-uri": "^3.0.3", + "@jridgewell/sourcemap-codec": "^1.4.10" + } + }, + "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, + "license": "MIT", + "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, + "license": "MIT", + "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, + "license": "MIT", + "dependencies": { + "@nodelib/fs.scandir": "2.1.5", + "fastq": "^1.6.0" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/@shikijs/core": { + "version": "1.22.0", + "resolved": "https://registry.npmjs.org/@shikijs/core/-/core-1.22.0.tgz", + "integrity": "sha512-S8sMe4q71TJAW+qG93s5VaiihujRK6rqDFqBnxqvga/3LvqHEnxqBIOPkt//IdXVtHkQWKu4nOQNk0uBGicU7Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "@shikijs/engine-javascript": "1.22.0", + "@shikijs/engine-oniguruma": "1.22.0", + "@shikijs/types": "1.22.0", + "@shikijs/vscode-textmate": "^9.3.0", + "@types/hast": "^3.0.4", + "hast-util-to-html": "^9.0.3" + } + }, + "node_modules/@shikijs/engine-javascript": { + "version": "1.22.0", + "resolved": "https://registry.npmjs.org/@shikijs/engine-javascript/-/engine-javascript-1.22.0.tgz", + "integrity": "sha512-AeEtF4Gcck2dwBqCFUKYfsCq0s+eEbCEbkUuFou53NZ0sTGnJnJ/05KHQFZxpii5HMXbocV9URYVowOP2wH5kw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@shikijs/types": "1.22.0", + "@shikijs/vscode-textmate": "^9.3.0", + "oniguruma-to-js": "0.4.3" + } + }, + "node_modules/@shikijs/engine-oniguruma": { + "version": "1.22.0", + "resolved": "https://registry.npmjs.org/@shikijs/engine-oniguruma/-/engine-oniguruma-1.22.0.tgz", + "integrity": "sha512-5iBVjhu/DYs1HB0BKsRRFipRrD7rqjxlWTj4F2Pf+nQSPqc3kcyqFFeZXnBMzDf0HdqaFVvhDRAGiYNvyLP+Mw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@shikijs/types": "1.22.0", + "@shikijs/vscode-textmate": "^9.3.0" + } + }, + "node_modules/@shikijs/types": { + "version": "1.22.0", + "resolved": "https://registry.npmjs.org/@shikijs/types/-/types-1.22.0.tgz", + "integrity": "sha512-Fw/Nr7FGFhlQqHfxzZY8Cwtwk5E9nKDUgeLjZgt3UuhcM3yJR9xj3ZGNravZZok8XmEZMiYkSMTPlPkULB8nww==", + "dev": true, + "license": "MIT", + "dependencies": { + "@shikijs/vscode-textmate": "^9.3.0", + "@types/hast": "^3.0.4" + } + }, + "node_modules/@shikijs/vscode-textmate": { + "version": "9.3.0", + "resolved": "https://registry.npmjs.org/@shikijs/vscode-textmate/-/vscode-textmate-9.3.0.tgz", + "integrity": "sha512-jn7/7ky30idSkd/O5yDBfAnVt+JJpepofP/POZ1iMOxK59cOfqIgg/Dj0eFsjOTMw+4ycJN0uhZH/Eb0bs/EUA==", + "dev": true, + "license": "MIT" + }, + "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, + "license": "MIT" + }, + "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, + "license": "BSD-3-Clause", + "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, + "license": "BSD-3-Clause", + "dependencies": { + "@sinonjs/commons": "^3.0.0" + } + }, + "node_modules/@tsconfig/node10": { + "version": "1.0.11", + "resolved": "https://registry.npmjs.org/@tsconfig/node10/-/node10-1.0.11.tgz", + "integrity": "sha512-DcRjDCujK/kCk/cUe8Xz8ZSpm8mS3mNNpta+jGCA6USEDfktlNvm1+IuZ9eTcDbNk41BHwpHHeW+N1lKCz4zOw==", + "dev": true, + "license": "MIT" + }, + "node_modules/@tsconfig/node12": { + "version": "1.0.11", + "resolved": "https://registry.npmjs.org/@tsconfig/node12/-/node12-1.0.11.tgz", + "integrity": "sha512-cqefuRsh12pWyGsIoBKJA9luFu3mRxCA+ORZvA4ktLSzIuCUtWVxGIuXigEwO5/ywWFMZ2QEGKWvkZG1zDMTag==", + "dev": true, + "license": "MIT" + }, + "node_modules/@tsconfig/node14": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/@tsconfig/node14/-/node14-1.0.3.tgz", + "integrity": "sha512-ysT8mhdixWK6Hw3i1V2AeRqZ5WfXg1G43mqoYlM2nc6388Fq5jcXyr5mRsqViLx/GJYdoL0bfXD8nmF+Zn/Iow==", + "dev": true, + "license": "MIT" + }, + "node_modules/@tsconfig/node16": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/@tsconfig/node16/-/node16-1.0.4.tgz", + "integrity": "sha512-vxhUy4J8lyeyinH7Azl1pdd43GJhZH/tP2weN8TntQblOY+A0XbT8DJk1/oCPuOOyg/Ja757rG0CgHcWC8OfMA==", + "dev": true, + "license": "MIT" + }, + "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, + "license": "MIT", + "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, + "license": "MIT", + "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, + "license": "MIT", + "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, + "license": "MIT", + "dependencies": { + "@babel/types": "^7.20.7" + } + }, + "node_modules/@types/cookiejar": { + "version": "2.1.5", + "resolved": "https://registry.npmjs.org/@types/cookiejar/-/cookiejar-2.1.5.tgz", + "integrity": "sha512-he+DHOWReW0nghN24E1WUqM0efK4kI9oTqDm6XmK8ZPe2djZ90BSNdGnIyCLzCPw7/pogPlGbzI2wHGGmi4O/Q==", + "dev": true, + "license": "MIT" + }, + "node_modules/@types/eslint": { + "version": "9.6.1", + "resolved": "https://registry.npmjs.org/@types/eslint/-/eslint-9.6.1.tgz", + "integrity": "sha512-FXx2pKgId/WyYo2jXw63kk7/+TY7u7AziEJxJAnSFzHlqTAS3Ync6SvgYAN/k4/PQpnnVuzoMuVnByKK2qp0ag==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/estree": "*", + "@types/json-schema": "*" + } + }, + "node_modules/@types/eslint__js": { + "version": "8.42.3", + "resolved": "https://registry.npmjs.org/@types/eslint__js/-/eslint__js-8.42.3.tgz", + "integrity": "sha512-alfG737uhmPdnvkrLdZLcEKJ/B8s9Y4hrZ+YAdzUeoArBlSUERA2E87ROfOaS4jd/C45fzOoZzidLc1IPwLqOw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/eslint": "*" + } + }, + "node_modules/@types/estree": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.6.tgz", + "integrity": "sha512-AYnb1nQyY49te+VRAVgmzfcgjYS91mY5P0TKUDCLEM+gNnA+3T6rWITXRLYCpahpqSQbN5cE+gHpnPyXjHWxcw==", + "dev": true, + "license": "MIT" + }, + "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, + "license": "MIT", + "dependencies": { + "@types/node": "*" + } + }, + "node_modules/@types/hast": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/@types/hast/-/hast-3.0.4.tgz", + "integrity": "sha512-WPs+bbQw5aCj+x6laNGWLH3wviHtoCv/P3+otBhbOhJgG8qtpdAMlTCxLtsTWA7LH1Oh/bFCHsBn0TPS5m30EQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/unist": "*" + } + }, + "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, + "license": "MIT" + }, + "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, + "license": "MIT", + "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, + "license": "MIT", + "dependencies": { + "@types/istanbul-lib-report": "*" + } + }, + "node_modules/@types/jest": { + "version": "29.5.14", + "resolved": "https://registry.npmjs.org/@types/jest/-/jest-29.5.14.tgz", + "integrity": "sha512-ZN+4sdnLUbo8EVvVc2ao0GFW6oVrQRPn4K2lglySj7APvSrgzxHiNNK99us4WDMi57xxA2yggblIAMNhXOotLQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "expect": "^29.0.0", + "pretty-format": "^29.0.0" + } + }, + "node_modules/@types/json-schema": { + "version": "7.0.15", + "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.15.tgz", + "integrity": "sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA==", + "dev": true, + "license": "MIT" + }, + "node_modules/@types/mdast": { + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/@types/mdast/-/mdast-4.0.4.tgz", + "integrity": "sha512-kGaNbPh1k7AFzgpud/gMdvIm5xuECykRR+JnWKQno9TAXVa6WIVCGTPvYGekIDL4uwCZQSYbUxNBSb1aUo79oA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/unist": "*" + } + }, + "node_modules/@types/methods": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/@types/methods/-/methods-1.1.4.tgz", + "integrity": "sha512-ymXWVrDiCxTBE3+RIrrP533E70eA+9qu7zdWoHuOmGujkYtzf4HQF96b8nwHLqhuf4ykX61IGRIB38CC6/sImQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/@types/node": { + "version": "22.7.4", + "resolved": "https://registry.npmjs.org/@types/node/-/node-22.7.4.tgz", + "integrity": "sha512-y+NPi1rFzDs1NdQHHToqeiX2TIS79SWEAw9GYhkkx8bD0ChpfqC+n2j5OXOCpzfojBEBt6DnEnnG9MY0zk1XLg==", + "dev": true, + "license": "MIT", + "dependencies": { + "undici-types": "~6.19.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, + "license": "MIT" + }, + "node_modules/@types/superagent": { + "version": "8.1.9", + "resolved": "https://registry.npmjs.org/@types/superagent/-/superagent-8.1.9.tgz", + "integrity": "sha512-pTVjI73witn+9ILmoJdajHGW2jkSaOzhiFYF1Rd3EQ94kymLqB9PjD9ISg7WaALC7+dCHT0FGe9T2LktLq/3GQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/cookiejar": "^2.1.5", + "@types/methods": "^1.1.4", + "@types/node": "*", + "form-data": "^4.0.0" + } + }, + "node_modules/@types/supertest": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/@types/supertest/-/supertest-6.0.2.tgz", + "integrity": "sha512-137ypx2lk/wTQbW6An6safu9hXmajAifU/s7szAHLN/FeIm5w7yR0Wkl9fdJMRSHwOn4HLAI0DaB2TOORuhPDg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/methods": "^1.1.4", + "@types/superagent": "^8.1.0" + } + }, + "node_modules/@types/unist": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/@types/unist/-/unist-3.0.3.tgz", + "integrity": "sha512-ko/gIFJRv177XgZsZcBwnqJN5x/Gien8qNOn0D5bQU/zAzVf9Zt3BlcUiLqhV9y4ARk0GbT3tnUiPNgnTXzc/Q==", + "dev": true, + "license": "MIT" + }, + "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, + "license": "MIT", + "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, + "license": "MIT" + }, + "node_modules/@typescript-eslint/eslint-plugin": { + "version": "8.8.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-8.8.0.tgz", + "integrity": "sha512-wORFWjU30B2WJ/aXBfOm1LX9v9nyt9D3jsSOxC3cCaTQGCW5k4jNpmjFv3U7p/7s4yvdjHzwtv2Sd2dOyhjS0A==", + "dev": true, + "license": "MIT", + "dependencies": { + "@eslint-community/regexpp": "^4.10.0", + "@typescript-eslint/scope-manager": "8.8.0", + "@typescript-eslint/type-utils": "8.8.0", + "@typescript-eslint/utils": "8.8.0", + "@typescript-eslint/visitor-keys": "8.8.0", + "graphemer": "^1.4.0", + "ignore": "^5.3.1", + "natural-compare": "^1.4.0", + "ts-api-utils": "^1.3.0" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "@typescript-eslint/parser": "^8.0.0 || ^8.0.0-alpha.0", + "eslint": "^8.57.0 || ^9.0.0" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, + "node_modules/@typescript-eslint/parser": { + "version": "8.8.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-8.8.0.tgz", + "integrity": "sha512-uEFUsgR+tl8GmzmLjRqz+VrDv4eoaMqMXW7ruXfgThaAShO9JTciKpEsB+TvnfFfbg5IpujgMXVV36gOJRLtZg==", + "dev": true, + "license": "BSD-2-Clause", + "dependencies": { + "@typescript-eslint/scope-manager": "8.8.0", + "@typescript-eslint/types": "8.8.0", + "@typescript-eslint/typescript-estree": "8.8.0", + "@typescript-eslint/visitor-keys": "8.8.0", + "debug": "^4.3.4" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "eslint": "^8.57.0 || ^9.0.0" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, + "node_modules/@typescript-eslint/scope-manager": { + "version": "8.8.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-8.8.0.tgz", + "integrity": "sha512-EL8eaGC6gx3jDd8GwEFEV091210U97J0jeEHrAYvIYosmEGet4wJ+g0SYmLu+oRiAwbSA5AVrt6DxLHfdd+bUg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@typescript-eslint/types": "8.8.0", + "@typescript-eslint/visitor-keys": "8.8.0" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + } + }, + "node_modules/@typescript-eslint/type-utils": { + "version": "8.8.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-8.8.0.tgz", + "integrity": "sha512-IKwJSS7bCqyCeG4NVGxnOP6lLT9Okc3Zj8hLO96bpMkJab+10HIfJbMouLrlpyOr3yrQ1cA413YPFiGd1mW9/Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "@typescript-eslint/typescript-estree": "8.8.0", + "@typescript-eslint/utils": "8.8.0", + "debug": "^4.3.4", + "ts-api-utils": "^1.3.0" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, + "node_modules/@typescript-eslint/types": { + "version": "8.8.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-8.8.0.tgz", + "integrity": "sha512-QJwc50hRCgBd/k12sTykOJbESe1RrzmX6COk8Y525C9l7oweZ+1lw9JiU56im7Amm8swlz00DRIlxMYLizr2Vw==", + "dev": true, + "license": "MIT", + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + } + }, + "node_modules/@typescript-eslint/typescript-estree": { + "version": "8.8.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-8.8.0.tgz", + "integrity": "sha512-ZaMJwc/0ckLz5DaAZ+pNLmHv8AMVGtfWxZe/x2JVEkD5LnmhWiQMMcYT7IY7gkdJuzJ9P14fRy28lUrlDSWYdw==", + "dev": true, + "license": "BSD-2-Clause", + "dependencies": { + "@typescript-eslint/types": "8.8.0", + "@typescript-eslint/visitor-keys": "8.8.0", + "debug": "^4.3.4", + "fast-glob": "^3.3.2", + "is-glob": "^4.0.3", + "minimatch": "^9.0.4", + "semver": "^7.6.0", + "ts-api-utils": "^1.3.0" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, + "node_modules/@typescript-eslint/typescript-estree/node_modules/minimatch": { + "version": "9.0.5", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.5.tgz", + "integrity": "sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow==", + "dev": true, + "license": "ISC", + "dependencies": { + "brace-expansion": "^2.0.1" + }, + "engines": { + "node": ">=16 || 14 >=14.17" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/@typescript-eslint/utils": { + "version": "8.8.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-8.8.0.tgz", + "integrity": "sha512-QE2MgfOTem00qrlPgyByaCHay9yb1+9BjnMFnSFkUKQfu7adBXDTnCAivURnuPPAG/qiB+kzKkZKmKfaMT0zVg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@eslint-community/eslint-utils": "^4.4.0", + "@typescript-eslint/scope-manager": "8.8.0", + "@typescript-eslint/types": "8.8.0", + "@typescript-eslint/typescript-estree": "8.8.0" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "eslint": "^8.57.0 || ^9.0.0" + } + }, + "node_modules/@typescript-eslint/visitor-keys": { + "version": "8.8.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-8.8.0.tgz", + "integrity": "sha512-8mq51Lx6Hpmd7HnA2fcHQo3YgfX1qbccxQOgZcb4tvasu//zXRaA1j5ZRFeCw/VRAdFi4mRM9DnZw0Nu0Q2d1g==", + "dev": true, + "license": "MIT", + "dependencies": { + "@typescript-eslint/types": "8.8.0", + "eslint-visitor-keys": "^3.4.3" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + } + }, + "node_modules/@typescript-eslint/visitor-keys/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, + "license": "Apache-2.0", + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "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, + "license": "ISC" + }, + "node_modules/acorn": { + "version": "8.12.1", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.12.1.tgz", + "integrity": "sha512-tcpGyI9zbizT9JbV6oYE477V6mTlXvvi0T0G3SNIYE2apm/G5huBa1+K89VGeovbg+jycCrfhl3ADxErOuO6Jg==", + "dev": true, + "license": "MIT", + "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, + "license": "MIT", + "peerDependencies": { + "acorn": "^6.0.0 || ^7.0.0 || ^8.0.0" + } + }, + "node_modules/acorn-walk": { + "version": "8.3.4", + "resolved": "https://registry.npmjs.org/acorn-walk/-/acorn-walk-8.3.4.tgz", + "integrity": "sha512-ueEepnujpqee2o5aIYnvHU6C0A42MNdsIDeqy5BydrkuC5R1ZuUFnm27EeFJGoEHJQgn3uleRvmTXaJgfXbt4g==", + "dev": true, + "license": "MIT", + "dependencies": { + "acorn": "^8.11.0" + }, + "engines": { + "node": ">=0.4.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, + "license": "MIT", + "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, + "license": "MIT", + "dependencies": { + "type-fest": "^0.21.3" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/ansi-regex": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.1.0.tgz", + "integrity": "sha512-7HSX4QQb4CspciLpVFwyRe79O3xsIZDDLER21kERQ71oaPodF8jL725AgJMFAYbooIqolJoRLuM81SpeUkpkvA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/ansi-regex?sponsor=1" + } + }, + "node_modules/ansi-styles": { + "version": "6.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-6.2.1.tgz", + "integrity": "sha512-bN798gFfQX+viw3R7yrGWRqnrN2oRkEkUjjl4JNn4E8GxxbjtG3FbrEIIY3l8/hrwUwIeCZvi4QuOTP4MErVug==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12" + }, + "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, + "license": "ISC", + "dependencies": { + "normalize-path": "^3.0.0", + "picomatch": "^2.0.4" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/arg": { + "version": "4.1.3", + "resolved": "https://registry.npmjs.org/arg/-/arg-4.1.3.tgz", + "integrity": "sha512-58S9QDqG0Xx27YwPSt9fJxivjYl432YCwfDMfZ+71RAqUrZef7LrKQZ3LHLOwCS4FLNBplP533Zx895SeOCHvA==", + "dev": true, + "license": "MIT" + }, + "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, + "license": "Python-2.0" + }, + "node_modules/array-union": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/array-union/-/array-union-2.1.0.tgz", + "integrity": "sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/asap": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/asap/-/asap-2.0.6.tgz", + "integrity": "sha512-BSHWgDSAiKs50o2Re8ppvp3seVHXSRM44cdSsT9FfNEUUZLOGWVCsiWaRPWM1Znn+mqZ1OfVZ3z3DWEzSp7hRA==", + "dev": true, + "license": "MIT" + }, + "node_modules/async": { + "version": "3.2.6", + "resolved": "https://registry.npmjs.org/async/-/async-3.2.6.tgz", + "integrity": "sha512-htCUDlxyyCLMgaM3xXg0C0LW2xqfuQ6p05pCEIsXuyQ+a1koYKTuBMzRNwmybfLgvJDMd0r1LTn4+E0Ti6C2AA==", + "dev": true, + "license": "MIT" + }, + "node_modules/asynckit": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", + "integrity": "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==", + "dev": true, + "license": "MIT" + }, + "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, + "license": "MIT", + "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, + "license": "BSD-3-Clause", + "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, + "license": "BSD-3-Clause", + "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-istanbul/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, + "license": "ISC", + "bin": { + "semver": "bin/semver.js" + } + }, + "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, + "license": "MIT", + "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, + "license": "MIT", + "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, + "license": "MIT", + "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, + "license": "MIT" + }, + "node_modules/binary-extensions": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.3.0.tgz", + "integrity": "sha512-Ceh+7ox5qe7LJuLHoY0feh3pHuUDHAcRUeyL2VYghZwfpkNIy/+8Ocg0a3UuSoYzavmylwuLWQOf3hl0jjMMIw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/brace-expansion": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", + "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", + "dev": true, + "license": "MIT", + "dependencies": { + "balanced-match": "^1.0.0" + } + }, + "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, + "license": "MIT", + "dependencies": { + "fill-range": "^7.1.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/browserslist": { + "version": "4.24.2", + "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.24.2.tgz", + "integrity": "sha512-ZIc+Q62revdMcqC6aChtW4jz3My3klmCO1fEmINZY/8J3EpBg5/A/D0AKmBveUh6pgoeycoMkVMko84tuYS+Gg==", + "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" + } + ], + "license": "MIT", + "dependencies": { + "caniuse-lite": "^1.0.30001669", + "electron-to-chromium": "^1.5.41", + "node-releases": "^2.0.18", + "update-browserslist-db": "^1.1.1" + }, + "bin": { + "browserslist": "cli.js" + }, + "engines": { + "node": "^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7" + } + }, + "node_modules/bs-logger": { + "version": "0.2.6", + "resolved": "https://registry.npmjs.org/bs-logger/-/bs-logger-0.2.6.tgz", + "integrity": "sha512-pd8DCoxmbgc7hyPKOvxtqNcjYoOsABPQdcCUjGp3d42VR2CX1ORhk2A87oqqu5R1kk+76nsxZupkmyd+MVtCog==", + "dev": true, + "license": "MIT", + "dependencies": { + "fast-json-stable-stringify": "2.x" + }, + "engines": { + "node": ">= 6" + } + }, + "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, + "license": "Apache-2.0", + "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, + "license": "MIT" + }, + "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==", + "dev": true, + "license": "MIT", + "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, + "license": "MIT", + "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, + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/caniuse-lite": { + "version": "1.0.30001669", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001669.tgz", + "integrity": "sha512-DlWzFDJqstqtIVx1zeSpIMLjunf5SmwOw0N2Ck/QSQdS8PLS4+9HrLaYei4w8BIAL7IB/UEDu889d8vhCTPA0w==", + "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" + } + ], + "license": "CC-BY-4.0" + }, + "node_modules/ccount": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/ccount/-/ccount-2.0.1.tgz", + "integrity": "sha512-eyrF0jiFpY+3drT6383f1qhkbGsLSifNAjA61IUjZjmLCWjItY6LB9ft9YhoDgwfmclB2zhu51Lc7+95b8NRAg==", + "dev": true, + "license": "MIT", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "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, + "license": "MIT", + "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/chalk/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, + "license": "MIT", + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?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, + "license": "MIT", + "engines": { + "node": ">=10" + } + }, + "node_modules/character-entities-html4": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/character-entities-html4/-/character-entities-html4-2.1.0.tgz", + "integrity": "sha512-1v7fgQRj6hnSwFpq1Eu0ynr/CDEw0rXo2B61qXrLNdHZmPKgb7fqS1a2JwF0rISo9q77jDI8VMEHoApn8qDoZA==", + "dev": true, + "license": "MIT", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/character-entities-legacy": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/character-entities-legacy/-/character-entities-legacy-3.0.0.tgz", + "integrity": "sha512-RpPp0asT/6ufRm//AJVwpViZbGM/MkjQFxJccQRHmISF/22NBtsHqAWmL+/pmkPWoIUJdWyeVleTl1wydHATVQ==", + "dev": true, + "license": "MIT", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/chokidar": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.6.0.tgz", + "integrity": "sha512-7VT13fmjotKpGipCW9JEQAusEPE+Ei8nl6/g4FBAmIm0GOOLMua9NDDo/DWp0ZAxCr3cPq5ZpBqmPAQgDda2Pw==", + "dev": true, + "license": "MIT", + "dependencies": { + "anymatch": "~3.1.2", + "braces": "~3.0.2", + "glob-parent": "~5.1.2", + "is-binary-path": "~2.1.0", + "is-glob": "~4.0.1", + "normalize-path": "~3.0.0", + "readdirp": "~3.6.0" + }, + "engines": { + "node": ">= 8.10.0" + }, + "funding": { + "url": "https://paulmillr.com/funding/" + }, + "optionalDependencies": { + "fsevents": "~2.3.2" + } + }, + "node_modules/chokidar/node_modules/glob-parent": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", + "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", + "dev": true, + "license": "ISC", + "dependencies": { + "is-glob": "^4.0.1" + }, + "engines": { + "node": ">= 6" + } + }, + "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" + } + ], + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/cjs-module-lexer": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/cjs-module-lexer/-/cjs-module-lexer-1.4.1.tgz", + "integrity": "sha512-cuSVIHi9/9E/+821Qjdvngor+xpnlwnuwIyZOaLmHBVdXL+gP+I6QQB9VkO7RI77YIcTV+S1W9AreJ5eN63JBA==", + "dev": true, + "license": "MIT" + }, + "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, + "license": "ISC", + "dependencies": { + "string-width": "^4.2.0", + "strip-ansi": "^6.0.1", + "wrap-ansi": "^7.0.0" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/cliui/node_modules/ansi-regex": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/cliui/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, + "license": "MIT", + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/cliui/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, + "license": "MIT" + }, + "node_modules/cliui/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, + "license": "MIT", + "dependencies": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/cliui/node_modules/strip-ansi": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-regex": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/cliui/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, + "license": "MIT", + "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/co": { + "version": "4.6.0", + "resolved": "https://registry.npmjs.org/co/-/co-4.6.0.tgz", + "integrity": "sha512-QVb0dM5HvG+uaxitm8wONl7jltx8dqhfU33DcqtOZcLSVIKSDDLDi7+0LbAKiyI8hD9u42m2YxXSkMGWThaecQ==", + "dev": true, + "license": "MIT", + "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, + "license": "MIT" + }, + "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, + "license": "MIT", + "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, + "license": "MIT" + }, + "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==", + "dev": true, + "license": "MIT", + "dependencies": { + "delayed-stream": "~1.0.0" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/comma-separated-tokens": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/comma-separated-tokens/-/comma-separated-tokens-2.0.3.tgz", + "integrity": "sha512-Fu4hJdvzeylCfQPp9SGWidpzrMs7tTrlu6Vb8XGaRGck8QSNZJJp538Wrb60Lax4fPwR64ViY468OIUTbRlGZg==", + "dev": true, + "license": "MIT", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/commander": { + "version": "9.5.0", + "resolved": "https://registry.npmjs.org/commander/-/commander-9.5.0.tgz", + "integrity": "sha512-KRs7WVDKg86PWiuAqhDrAQnTXZKraVcCc6vFdL14qrZ/DcWwuRo7VoiYXalXO7S5GKpqYiVEwCbgFDfxNHKJBQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": "^12.20.0 || >=14" + } + }, + "node_modules/component-emitter": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/component-emitter/-/component-emitter-1.3.1.tgz", + "integrity": "sha512-T0+barUSQRTUQASh8bx02dl+DhF54GtIDY13Y3m9oWTklKbb3Wv974meRpeZ3lp1JpLVECWWNHC4vaG2XHXouQ==", + "dev": true, + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "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, + "license": "MIT" + }, + "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, + "license": "MIT" + }, + "node_modules/cookiejar": { + "version": "2.1.4", + "resolved": "https://registry.npmjs.org/cookiejar/-/cookiejar-2.1.4.tgz", + "integrity": "sha512-LDx6oHrK+PhzLKJU9j5S7/Y3jM/mUHvD/DeI1WQmJn652iPC5Y4TBzC9l+5OMOXlyTTA+SmVUPm0HQUwpD5Jqw==", + "dev": true, + "license": "MIT" + }, + "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, + "license": "MIT", + "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/create-require": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/create-require/-/create-require-1.1.1.tgz", + "integrity": "sha512-dcKFX3jn0MpIaXjisoRvexIJVEKzaq7z2rZKxf+MSr9TkdmHmsU4m2lcLojrj/FHl8mk5VxMmYA+ftRkP/3oKQ==", + "dev": true, + "license": "MIT" + }, + "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, + "license": "MIT", + "dependencies": { + "path-key": "^3.1.0", + "shebang-command": "^2.0.0", + "which": "^2.0.1" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/debug": { + "version": "4.3.7", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.7.tgz", + "integrity": "sha512-Er2nc/H7RrMXZBFCEim6TCmMk02Z8vLC2Rbi1KEBggpo0fS6l0S1nnapwmIi3yW/+GOJap1Krg4w0Hg80oCqgQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "ms": "^2.1.3" + }, + "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, + "license": "MIT", + "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, + "license": "MIT" + }, + "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, + "license": "MIT", + "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==", + "dev": true, + "license": "MIT", + "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/delayed-stream": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", + "integrity": "sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/dequal": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/dequal/-/dequal-2.0.3.tgz", + "integrity": "sha512-0je+qPKHEMohvfRTCEo3CrPG6cAzAYgmzKyxRiYSSDkS6eGJdyVJm7WaYA5ECaAD9wLB2T4EEeymA5aFVcYXCA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "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, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/devlop": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/devlop/-/devlop-1.1.0.tgz", + "integrity": "sha512-RWmIqhcFf1lRYBvNmr7qTNuyCt/7/ns2jbpp1+PalgE/rDQcBT0fioSMUpJ93irlUhC5hrg4cYqe6U+0ImW0rA==", + "dev": true, + "license": "MIT", + "dependencies": { + "dequal": "^2.0.0" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/dezalgo": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/dezalgo/-/dezalgo-1.0.4.tgz", + "integrity": "sha512-rXSP0bf+5n0Qonsb+SVVfNfIsimO4HEtmnIpPHY8Q1UCzKlQrDMfdobr8nJOOsRgWCyMRqeSBQzmWUMq7zvVig==", + "dev": true, + "license": "ISC", + "dependencies": { + "asap": "^2.0.0", + "wrappy": "1" + } + }, + "node_modules/diff": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/diff/-/diff-4.0.2.tgz", + "integrity": "sha512-58lmxKSA4BNyLz+HHMUzlOEpg09FV+ev6ZMe3vJihgdxzgcwZ8VoEEPmALCZG9LmqfVoNMMKpttIYTVG6uDY7A==", + "dev": true, + "license": "BSD-3-Clause", + "engines": { + "node": ">=0.3.1" + } + }, + "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, + "license": "MIT", + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/dir-glob": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/dir-glob/-/dir-glob-3.0.1.tgz", + "integrity": "sha512-WkrWp9GR4KXfKGYzOLmTuGVi1UWFfws377n9cc55/tb6DuqyF6pcQ5AbiHEshaDpY9v6oaSr2XCDidGmMwdzIA==", + "dev": true, + "license": "MIT", + "dependencies": { + "path-type": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/eastasianwidth": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/eastasianwidth/-/eastasianwidth-0.2.0.tgz", + "integrity": "sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA==", + "dev": true, + "license": "MIT" + }, + "node_modules/ejs": { + "version": "3.1.10", + "resolved": "https://registry.npmjs.org/ejs/-/ejs-3.1.10.tgz", + "integrity": "sha512-UeJmFfOrAQS8OJWPZ4qtgHyWExa088/MtK5UEyoJGFH67cDEXkZSviOiKRCZ4Xij0zxI3JECgYs3oKx+AizQBA==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "jake": "^10.8.5" + }, + "bin": { + "ejs": "bin/cli.js" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/electron-to-chromium": { + "version": "1.5.45", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.45.tgz", + "integrity": "sha512-vOzZS6uZwhhbkZbcRyiy99Wg+pYFV5hk+5YaECvx0+Z31NR3Tt5zS6dze2OepT6PCTzVzT0dIJItti+uAW5zmw==", + "dev": true, + "license": "ISC" + }, + "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, + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sindresorhus/emittery?sponsor=1" + } + }, + "node_modules/emoji-regex": { + "version": "9.2.2", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-9.2.2.tgz", + "integrity": "sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==", + "dev": true, + "license": "MIT" + }, + "node_modules/entities": { + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/entities/-/entities-4.5.0.tgz", + "integrity": "sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw==", + "dev": true, + "license": "BSD-2-Clause", + "engines": { + "node": ">=0.12" + }, + "funding": { + "url": "https://github.com/fb55/entities?sponsor=1" + } + }, + "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, + "license": "MIT", + "dependencies": { + "is-arrayish": "^0.2.1" + } + }, + "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==", + "dev": true, + "license": "MIT", + "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==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/esbuild": { + "version": "0.23.1", + "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.23.1.tgz", + "integrity": "sha512-VVNz/9Sa0bs5SELtn3f7qhJCDPCF5oMEl5cO9/SSinpE9hbPVvxbd572HH5AKiP7WD8INO53GgfDDhRjkylHEg==", + "dev": true, + "hasInstallScript": true, + "license": "MIT", + "bin": { + "esbuild": "bin/esbuild" + }, + "engines": { + "node": ">=18" + }, + "optionalDependencies": { + "@esbuild/aix-ppc64": "0.23.1", + "@esbuild/android-arm": "0.23.1", + "@esbuild/android-arm64": "0.23.1", + "@esbuild/android-x64": "0.23.1", + "@esbuild/darwin-arm64": "0.23.1", + "@esbuild/darwin-x64": "0.23.1", + "@esbuild/freebsd-arm64": "0.23.1", + "@esbuild/freebsd-x64": "0.23.1", + "@esbuild/linux-arm": "0.23.1", + "@esbuild/linux-arm64": "0.23.1", + "@esbuild/linux-ia32": "0.23.1", + "@esbuild/linux-loong64": "0.23.1", + "@esbuild/linux-mips64el": "0.23.1", + "@esbuild/linux-ppc64": "0.23.1", + "@esbuild/linux-riscv64": "0.23.1", + "@esbuild/linux-s390x": "0.23.1", + "@esbuild/linux-x64": "0.23.1", + "@esbuild/netbsd-x64": "0.23.1", + "@esbuild/openbsd-arm64": "0.23.1", + "@esbuild/openbsd-x64": "0.23.1", + "@esbuild/sunos-x64": "0.23.1", + "@esbuild/win32-arm64": "0.23.1", + "@esbuild/win32-ia32": "0.23.1", + "@esbuild/win32-x64": "0.23.1" + } + }, + "node_modules/escalade": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.2.0.tgz", + "integrity": "sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "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, + "license": "MIT", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/eslint": { + "version": "9.12.0", + "resolved": "https://registry.npmjs.org/eslint/-/eslint-9.12.0.tgz", + "integrity": "sha512-UVIOlTEWxwIopRL1wgSQYdnVDcEvs2wyaO6DGo5mXqe3r16IoCNWkR29iHhyaP4cICWjbgbmFUGAhh0GJRuGZw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@eslint-community/eslint-utils": "^4.2.0", + "@eslint-community/regexpp": "^4.11.0", + "@eslint/config-array": "^0.18.0", + "@eslint/core": "^0.6.0", + "@eslint/eslintrc": "^3.1.0", + "@eslint/js": "9.12.0", + "@eslint/plugin-kit": "^0.2.0", + "@humanfs/node": "^0.16.5", + "@humanwhocodes/module-importer": "^1.0.1", + "@humanwhocodes/retry": "^0.3.1", + "@types/estree": "^1.0.6", + "@types/json-schema": "^7.0.15", + "ajv": "^6.12.4", + "chalk": "^4.0.0", + "cross-spawn": "^7.0.2", + "debug": "^4.3.2", + "escape-string-regexp": "^4.0.0", + "eslint-scope": "^8.1.0", + "eslint-visitor-keys": "^4.1.0", + "espree": "^10.2.0", + "esquery": "^1.5.0", + "esutils": "^2.0.2", + "fast-deep-equal": "^3.1.3", + "file-entry-cache": "^8.0.0", + "find-up": "^5.0.0", + "glob-parent": "^6.0.2", + "ignore": "^5.2.0", + "imurmurhash": "^0.1.4", + "is-glob": "^4.0.0", + "json-stable-stringify-without-jsonify": "^1.0.1", + "lodash.merge": "^4.6.2", + "minimatch": "^3.1.2", + "natural-compare": "^1.4.0", + "optionator": "^0.9.3", + "text-table": "^0.2.0" + }, + "bin": { + "eslint": "bin/eslint.js" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "url": "https://eslint.org/donate" + }, + "peerDependencies": { + "jiti": "*" + }, + "peerDependenciesMeta": { + "jiti": { + "optional": true + } + } + }, + "node_modules/eslint-scope": { + "version": "8.1.0", + "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-8.1.0.tgz", + "integrity": "sha512-14dSvlhaVhKKsa9Fx1l8A17s7ah7Ef7wCakJ10LYk6+GYmP9yDti2oq2SEwcyndt6knfcZyhyxwY3i9yL78EQw==", + "dev": true, + "license": "BSD-2-Clause", + "dependencies": { + "esrecurse": "^4.3.0", + "estraverse": "^5.2.0" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/eslint-visitor-keys": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-4.1.0.tgz", + "integrity": "sha512-Q7lok0mqMUSf5a/AdAZkA5a/gHcO6snwQClVNNvFKCAVlxXucdU8pKydU5ZVZjBx5xr37vGbFFWtLQYreLzrZg==", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/eslint/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, + "license": "MIT", + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "node_modules/eslint/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, + "license": "ISC", + "dependencies": { + "brace-expansion": "^1.1.7" + }, + "engines": { + "node": "*" + } + }, + "node_modules/espree": { + "version": "10.2.0", + "resolved": "https://registry.npmjs.org/espree/-/espree-10.2.0.tgz", + "integrity": "sha512-upbkBJbckcCNBDBDXEbuhjbP68n+scUd3k/U2EkyM9nw+I/jPiL4cLF/Al06CF96wRltFda16sxDFrxsI1v0/g==", + "dev": true, + "license": "BSD-2-Clause", + "dependencies": { + "acorn": "^8.12.0", + "acorn-jsx": "^5.3.2", + "eslint-visitor-keys": "^4.1.0" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.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, + "license": "BSD-2-Clause", + "bin": { + "esparse": "bin/esparse.js", + "esvalidate": "bin/esvalidate.js" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/esquery": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.6.0.tgz", + "integrity": "sha512-ca9pw9fomFcKPvFLXhBKUK90ZvGibiGOvRJNbjljY7s7uq/5YO4BOzcYtJqExdx99rF6aAcnRxHmcUHcz6sQsg==", + "dev": true, + "license": "BSD-3-Clause", + "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, + "license": "BSD-2-Clause", + "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, + "license": "BSD-2-Clause", + "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, + "license": "BSD-2-Clause", + "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, + "license": "MIT", + "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/execa/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, + "license": "ISC" + }, + "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, + "license": "MIT", + "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, + "license": "MIT" + }, + "node_modules/fast-glob": { + "version": "3.3.2", + "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.3.2.tgz", + "integrity": "sha512-oX2ruAFQwf/Orj8m737Y5adxDQO0LAB7/S5MnxCdTNDd4p6BsyIVsv9JQsATbTSq8KHRpLwIHbVlUNatxd+1Ow==", + "dev": true, + "license": "MIT", + "dependencies": { + "@nodelib/fs.stat": "^2.0.2", + "@nodelib/fs.walk": "^1.2.3", + "glob-parent": "^5.1.2", + "merge2": "^1.3.0", + "micromatch": "^4.0.4" + }, + "engines": { + "node": ">=8.6.0" + } + }, + "node_modules/fast-glob/node_modules/glob-parent": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", + "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", + "dev": true, + "license": "ISC", + "dependencies": { + "is-glob": "^4.0.1" + }, + "engines": { + "node": ">= 6" + } + }, + "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, + "license": "MIT" + }, + "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, + "license": "MIT" + }, + "node_modules/fast-safe-stringify": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/fast-safe-stringify/-/fast-safe-stringify-2.1.1.tgz", + "integrity": "sha512-W+KJc2dmILlPplD/H4K9l9LcAHAfPtP6BY84uVLXQ6Evcz9Lcg33Y2z1IVblT6xdY54PXYVHEv+0Wpq8Io6zkA==", + "dev": true, + "license": "MIT" + }, + "node_modules/fastq": { + "version": "1.17.1", + "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.17.1.tgz", + "integrity": "sha512-sRVD3lWVIXWg6By68ZN7vho9a1pQcN/WBFaAAsDDFzlJjvoGx0P8z7V1t72grFJfJhu3YPZBuu25f7Kaw2jN1w==", + "dev": true, + "license": "ISC", + "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, + "license": "Apache-2.0", + "dependencies": { + "bser": "2.1.1" + } + }, + "node_modules/file-entry-cache": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-8.0.0.tgz", + "integrity": "sha512-XXTUwCvisa5oacNGRP9SfNtYBNAMi+RPwBFmblZEF7N7swHYQS6/Zfk7SRwx4D5j3CH211YNRco1DEMNVfZCnQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "flat-cache": "^4.0.0" + }, + "engines": { + "node": ">=16.0.0" + } + }, + "node_modules/filelist": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/filelist/-/filelist-1.0.4.tgz", + "integrity": "sha512-w1cEuf3S+DrLCQL7ET6kz+gmlJdbq9J7yXCSjK/OZCPA+qEN1WyF4ZAf0YYJa4/shHJra2t/d/r8SV4Ji+x+8Q==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "minimatch": "^5.0.1" + } + }, + "node_modules/filelist/node_modules/minimatch": { + "version": "5.1.6", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-5.1.6.tgz", + "integrity": "sha512-lKwV/1brpG6mBUFHtb7NUmtABCb2WZZmm2wNiOA5hAb8VdCS4B3dtMWyvcoViccwAW/COERjXLt0zP1zXUN26g==", + "dev": true, + "license": "ISC", + "dependencies": { + "brace-expansion": "^2.0.1" + }, + "engines": { + "node": ">=10" + } + }, + "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, + "license": "MIT", + "dependencies": { + "to-regex-range": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "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, + "license": "MIT", + "dependencies": { + "locate-path": "^6.0.0", + "path-exists": "^4.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/flat-cache": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-4.0.1.tgz", + "integrity": "sha512-f7ccFPK3SXFHpx15UIGyRJ/FJQctuKZ0zVuN3frBo4HnK3cay9VEW0R6yPYFHC0AgqhukPzKjq22t5DmAyqGyw==", + "dev": true, + "license": "MIT", + "dependencies": { + "flatted": "^3.2.9", + "keyv": "^4.5.4" + }, + "engines": { + "node": ">=16" + } + }, + "node_modules/flatted": { + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.3.1.tgz", + "integrity": "sha512-X8cqMLLie7KsNUDSdzeN8FYK9rEt4Dt67OsG/DNGnYTSDBG4uFAJFBnUeiV+zCVAvwFy56IjM9sH51jVaEhNxw==", + "dev": true, + "license": "ISC" + }, + "node_modules/foreground-child": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/foreground-child/-/foreground-child-3.3.0.tgz", + "integrity": "sha512-Ld2g8rrAyMYFXBhEqMz8ZAHBi4J4uS1i/CxGMDnjyFWddMXLVcDp051DZfu+t7+ab7Wv6SMqpWmyFIj5UbfFvg==", + "dev": true, + "license": "ISC", + "dependencies": { + "cross-spawn": "^7.0.0", + "signal-exit": "^4.0.1" + }, + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/form-data": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.1.tgz", + "integrity": "sha512-tzN8e4TX8+kkxGPK8D5u0FNmjPUjw3lwC9lSLxxoB/+GtsJG91CO8bSWy73APlgAZzZbXEYZJuxjkHH2w+Ezhw==", + "dev": true, + "license": "MIT", + "dependencies": { + "asynckit": "^0.4.0", + "combined-stream": "^1.0.8", + "mime-types": "^2.1.12" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/formidable": { + "version": "3.5.2", + "resolved": "https://registry.npmjs.org/formidable/-/formidable-3.5.2.tgz", + "integrity": "sha512-Jqc1btCy3QzRbJaICGwKcBfGWuLADRerLzDqi2NwSt/UkXLsHJw2TVResiaoBufHVHy9aSgClOHCeJsSsFLTbg==", + "dev": true, + "license": "MIT", + "dependencies": { + "dezalgo": "^1.0.4", + "hexoid": "^2.0.0", + "once": "^1.4.0" + }, + "funding": { + "url": "https://ko-fi.com/tunnckoCore/commissions" + } + }, + "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, + "license": "ISC" + }, + "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, + "license": "MIT", + "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==", + "dev": true, + "license": "MIT", + "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, + "license": "MIT", + "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, + "license": "ISC", + "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==", + "dev": true, + "license": "MIT", + "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, + "license": "MIT", + "engines": { + "node": ">=8.0.0" + } + }, + "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, + "license": "MIT", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/get-tsconfig": { + "version": "4.8.1", + "resolved": "https://registry.npmjs.org/get-tsconfig/-/get-tsconfig-4.8.1.tgz", + "integrity": "sha512-k9PN+cFBmaLWtVz29SkUoqU5O0slLuHJXt/2P+tMVFT+phsSGXGkp9t3rQIqdz0e+06EHNGs3oM6ZX1s2zHxRg==", + "dev": true, + "license": "MIT", + "dependencies": { + "resolve-pkg-maps": "^1.0.0" + }, + "funding": { + "url": "https://github.com/privatenumber/get-tsconfig?sponsor=1" + } + }, + "node_modules/glob": { + "version": "11.0.0", + "resolved": "https://registry.npmjs.org/glob/-/glob-11.0.0.tgz", + "integrity": "sha512-9UiX/Bl6J2yaBbxKoEBRm4Cipxgok8kQYcOPEhScPwebu2I0HoQOuYdIO6S3hLuWoZgpDpwQZMzTFxgpkyT76g==", + "dev": true, + "license": "ISC", + "dependencies": { + "foreground-child": "^3.1.0", + "jackspeak": "^4.0.1", + "minimatch": "^10.0.0", + "minipass": "^7.1.2", + "package-json-from-dist": "^1.0.0", + "path-scurry": "^2.0.0" + }, + "bin": { + "glob": "dist/esm/bin.mjs" + }, + "engines": { + "node": "20 || >=22" + }, + "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, + "license": "ISC", + "dependencies": { + "is-glob": "^4.0.3" + }, + "engines": { + "node": ">=10.13.0" + } + }, + "node_modules/globals": { + "version": "14.0.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-14.0.0.tgz", + "integrity": "sha512-oahGvuMGQlPw/ivIYBjVSrWAfWLBeku5tpPE2fOPLi+WHffIWbuh2tCjhyQhTBPMf5E9jDEH4FOmTYgYwbKwtQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/globby": { + "version": "11.1.0", + "resolved": "https://registry.npmjs.org/globby/-/globby-11.1.0.tgz", + "integrity": "sha512-jhIXaOzy1sb8IyocaruWSn1TjmnBVs8Ayhcy83rmxNJ8q2uWKCAj3CnJY+KpGSXCueAPc0i05kVvVKtP1t9S3g==", + "dev": true, + "license": "MIT", + "dependencies": { + "array-union": "^2.1.0", + "dir-glob": "^3.0.1", + "fast-glob": "^3.2.9", + "ignore": "^5.2.0", + "merge2": "^1.4.1", + "slash": "^3.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/gopd": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/gopd/-/gopd-1.0.1.tgz", + "integrity": "sha512-d65bNlIadxvpb/A2abVdlqKqV563juRnZ1Wtk6s1sIR8uNsXR70xqIzVqxVf1eTqDunwT2MkczEeaezCKTZhwA==", + "dev": true, + "license": "MIT", + "dependencies": { + "get-intrinsic": "^1.1.3" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/graceful-fs": { + "version": "4.2.11", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.11.tgz", + "integrity": "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==", + "dev": true, + "license": "ISC" + }, + "node_modules/graphemer": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/graphemer/-/graphemer-1.4.0.tgz", + "integrity": "sha512-EtKwoO6kxCL9WO5xipiHTZlSzBm7WLT627TqC/uVRd0HKmq8NXyebnNYxDoBi7wt8eTWrUrKXCOVaFq9x1kgag==", + "dev": true, + "license": "MIT" + }, + "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, + "license": "MIT", + "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==", + "dev": true, + "license": "MIT", + "dependencies": { + "es-define-property": "^1.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/has-proto": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/has-proto/-/has-proto-1.0.3.tgz", + "integrity": "sha512-SJ1amZAJUiZS+PhsVLf5tGydlaVB8EdFpaSO4gmiUKUOxk8qzn5AIy4ZeJUmh22znIdk/uMAUT2pl3FxzVUH+Q==", + "dev": true, + "license": "MIT", + "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==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/hasown": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.2.tgz", + "integrity": "sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "function-bind": "^1.1.2" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/hast-util-to-html": { + "version": "9.0.3", + "resolved": "https://registry.npmjs.org/hast-util-to-html/-/hast-util-to-html-9.0.3.tgz", + "integrity": "sha512-M17uBDzMJ9RPCqLMO92gNNUDuBSq10a25SDBI08iCCxmorf4Yy6sYHK57n9WAbRAAaU+DuR4W6GN9K4DFZesYg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/hast": "^3.0.0", + "@types/unist": "^3.0.0", + "ccount": "^2.0.0", + "comma-separated-tokens": "^2.0.0", + "hast-util-whitespace": "^3.0.0", + "html-void-elements": "^3.0.0", + "mdast-util-to-hast": "^13.0.0", + "property-information": "^6.0.0", + "space-separated-tokens": "^2.0.0", + "stringify-entities": "^4.0.0", + "zwitch": "^2.0.4" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/hast-util-whitespace": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/hast-util-whitespace/-/hast-util-whitespace-3.0.0.tgz", + "integrity": "sha512-88JUN06ipLwsnv+dVn+OIYOvAuvBMy/Qoi6O7mQHxdPXpjy+Cd6xRkWwux7DKO+4sYILtLBRIKgsdpS2gQc7qw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/hast": "^3.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/hexoid": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/hexoid/-/hexoid-2.0.0.tgz", + "integrity": "sha512-qlspKUK7IlSQv2o+5I7yhUd7TxlOG2Vr5LTa3ve2XSNVKAL/n/u/7KLvKmFNimomDIKvZFXWHv0T12mv7rT8Aw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "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, + "license": "MIT" + }, + "node_modules/html-void-elements": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/html-void-elements/-/html-void-elements-3.0.0.tgz", + "integrity": "sha512-bEqo66MRXsUGxWHV5IP0PUiAWwoEjba4VCzg0LjFJBpchPaTfyfCKTG6bc5F8ucKec3q5y6qOdGyYTSBEvhCrg==", + "dev": true, + "license": "MIT", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "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, + "license": "Apache-2.0", + "engines": { + "node": ">=10.17.0" + } + }, + "node_modules/ignore": { + "version": "5.3.2", + "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.3.2.tgz", + "integrity": "sha512-hsBTNUqQTDwkWtcdYI2i06Y/nUBEsNEDJKjWdigLvegy8kDuJAS8uRlpkkcQpyEXL0Z/pjDy5HBmMjRCJ2gq+g==", + "dev": true, + "license": "MIT", + "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, + "license": "MIT", + "dependencies": { + "parent-module": "^1.0.0", + "resolve-from": "^4.0.0" + }, + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "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, + "license": "MIT", + "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, + "license": "MIT", + "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==", + "deprecated": "This module is not supported, and leaks memory. Do not use it. Check out lru-cache if you want a good and tested way to coalesce async requests by a key value, which is much more comprehensive and powerful.", + "dev": true, + "license": "ISC", + "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, + "license": "ISC" + }, + "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, + "license": "MIT" + }, + "node_modules/is-binary-path": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz", + "integrity": "sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==", + "dev": true, + "license": "MIT", + "dependencies": { + "binary-extensions": "^2.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/is-core-module": { + "version": "2.15.1", + "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.15.1.tgz", + "integrity": "sha512-z0vtXSwucUJtANQWldhbtbt7BnL0vxiFjIdDLAatwhDYty2bad6s+rijD6Ri4YuYJubLzIJLUidCh09e1djEVQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "hasown": "^2.0.2" + }, + "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, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "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, + "license": "MIT", + "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, + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "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, + "license": "MIT", + "dependencies": { + "is-extglob": "^2.1.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "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, + "license": "MIT", + "engines": { + "node": ">=0.12.0" + } + }, + "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, + "license": "MIT", + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/isexe": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", + "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==", + "dev": true, + "license": "ISC" + }, + "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, + "license": "BSD-3-Clause", + "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, + "license": "BSD-3-Clause", + "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-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, + "license": "BSD-3-Clause", + "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, + "license": "BSD-3-Clause", + "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, + "license": "BSD-3-Clause", + "dependencies": { + "html-escaper": "^2.0.0", + "istanbul-lib-report": "^3.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/jackspeak": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/jackspeak/-/jackspeak-4.0.2.tgz", + "integrity": "sha512-bZsjR/iRjl1Nk1UkjGpAzLNfQtzuijhn2g+pbZb98HQ1Gk8vM9hfbxeMBP+M2/UUdwj0RqGG3mlvk2MsAqwvEw==", + "dev": true, + "license": "BlueOak-1.0.0", + "dependencies": { + "@isaacs/cliui": "^8.0.2" + }, + "engines": { + "node": "20 || >=22" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/jake": { + "version": "10.9.2", + "resolved": "https://registry.npmjs.org/jake/-/jake-10.9.2.tgz", + "integrity": "sha512-2P4SQ0HrLQ+fw6llpLnOaGAvN2Zu6778SJMrCUwns4fOoG9ayrTiZk3VV8sCPkVZF8ab0zksVpS8FDY5pRCNBA==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "async": "^3.2.3", + "chalk": "^4.0.2", + "filelist": "^1.0.4", + "minimatch": "^3.1.2" + }, + "bin": { + "jake": "bin/cli.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/jake/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, + "license": "MIT", + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "node_modules/jake/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, + "license": "ISC", + "dependencies": { + "brace-expansion": "^1.1.7" + }, + "engines": { + "node": "*" + } + }, + "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, + "license": "MIT", + "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, + "license": "MIT", + "dependencies": { + "execa": "^5.0.0", + "jest-util": "^29.7.0", + "p-limit": "^3.1.0" + }, "engines": { - "node": ">=0.10.0" + "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==", + "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, - "license": "MIT" + "license": "MIT", + "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/fast-glob": { - "version": "3.3.2", - "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.3.2.tgz", - "integrity": "sha512-oX2ruAFQwf/Orj8m737Y5adxDQO0LAB7/S5MnxCdTNDd4p6BsyIVsv9JQsATbTSq8KHRpLwIHbVlUNatxd+1Ow==", + "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, "license": "MIT", "dependencies": { - "@nodelib/fs.stat": "^2.0.2", - "@nodelib/fs.walk": "^1.2.3", - "glob-parent": "^5.1.2", - "merge2": "^1.3.0", - "micromatch": "^4.0.4" + "@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": ">=8.6.0" + "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/fast-glob/node_modules/glob-parent": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", - "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", + "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, - "license": "ISC", + "license": "MIT", "dependencies": { - "is-glob": "^4.0.1" + "@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": ">= 6" + "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/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==", + "node_modules/jest-config/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, - "license": "MIT" + "license": "MIT", + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } }, - "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==", + "node_modules/jest-config/node_modules/glob": { + "version": "7.2.3", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", + "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", + "deprecated": "Glob versions prior to v9 are no longer supported", "dev": true, - "license": "MIT" + "license": "ISC", + "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/fastq": { - "version": "1.17.1", - "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.17.1.tgz", - "integrity": "sha512-sRVD3lWVIXWg6By68ZN7vho9a1pQcN/WBFaAAsDDFzlJjvoGx0P8z7V1t72grFJfJhu3YPZBuu25f7Kaw2jN1w==", + "node_modules/jest-config/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, "license": "ISC", "dependencies": { - "reusify": "^1.0.4" + "brace-expansion": "^1.1.7" + }, + "engines": { + "node": "*" } }, - "node_modules/file-entry-cache": { - "version": "8.0.0", - "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-8.0.0.tgz", - "integrity": "sha512-XXTUwCvisa5oacNGRP9SfNtYBNAMi+RPwBFmblZEF7N7swHYQS6/Zfk7SRwx4D5j3CH211YNRco1DEMNVfZCnQ==", + "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, "license": "MIT", "dependencies": { - "flat-cache": "^4.0.0" + "chalk": "^4.0.0", + "diff-sequences": "^29.6.3", + "jest-get-type": "^29.6.3", + "pretty-format": "^29.7.0" }, "engines": { - "node": ">=16.0.0" + "node": "^14.15.0 || ^16.10.0 || >=18.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==", + "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, "license": "MIT", "dependencies": { - "to-regex-range": "^5.0.1" + "detect-newline": "^3.0.0" }, "engines": { - "node": ">=8" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, - "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==", + "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, "license": "MIT", "dependencies": { - "locate-path": "^6.0.0", - "path-exists": "^4.0.0" + "@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": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, - "node_modules/flat-cache": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-4.0.1.tgz", - "integrity": "sha512-f7ccFPK3SXFHpx15UIGyRJ/FJQctuKZ0zVuN3frBo4HnK3cay9VEW0R6yPYFHC0AgqhukPzKjq22t5DmAyqGyw==", + "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, "license": "MIT", "dependencies": { - "flatted": "^3.2.9", - "keyv": "^4.5.4" + "@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": ">=16" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, - "node_modules/flatted": { - "version": "3.3.1", - "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.3.1.tgz", - "integrity": "sha512-X8cqMLLie7KsNUDSdzeN8FYK9rEt4Dt67OsG/DNGnYTSDBG4uFAJFBnUeiV+zCVAvwFy56IjM9sH51jVaEhNxw==", + "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, - "license": "ISC" + "license": "MIT", + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } }, - "node_modules/foreground-child": { - "version": "3.3.0", - "resolved": "https://registry.npmjs.org/foreground-child/-/foreground-child-3.3.0.tgz", - "integrity": "sha512-Ld2g8rrAyMYFXBhEqMz8ZAHBi4J4uS1i/CxGMDnjyFWddMXLVcDp051DZfu+t7+ab7Wv6SMqpWmyFIj5UbfFvg==", + "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, - "license": "ISC", + "license": "MIT", "dependencies": { - "cross-spawn": "^7.0.0", - "signal-exit": "^4.0.1" + "@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" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" }, - "funding": { - "url": "https://github.com/sponsors/isaacs" + "optionalDependencies": { + "fsevents": "^2.3.2" } }, - "node_modules/get-tsconfig": { - "version": "4.8.1", - "resolved": "https://registry.npmjs.org/get-tsconfig/-/get-tsconfig-4.8.1.tgz", - "integrity": "sha512-k9PN+cFBmaLWtVz29SkUoqU5O0slLuHJXt/2P+tMVFT+phsSGXGkp9t3rQIqdz0e+06EHNGs3oM6ZX1s2zHxRg==", + "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, "license": "MIT", "dependencies": { - "resolve-pkg-maps": "^1.0.0" + "jest-get-type": "^29.6.3", + "pretty-format": "^29.7.0" }, - "funding": { - "url": "https://github.com/privatenumber/get-tsconfig?sponsor=1" + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, - "node_modules/glob": { - "version": "11.0.0", - "resolved": "https://registry.npmjs.org/glob/-/glob-11.0.0.tgz", - "integrity": "sha512-9UiX/Bl6J2yaBbxKoEBRm4Cipxgok8kQYcOPEhScPwebu2I0HoQOuYdIO6S3hLuWoZgpDpwQZMzTFxgpkyT76g==", + "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, - "license": "ISC", + "license": "MIT", "dependencies": { - "foreground-child": "^3.1.0", - "jackspeak": "^4.0.1", - "minimatch": "^10.0.0", - "minipass": "^7.1.2", - "package-json-from-dist": "^1.0.0", - "path-scurry": "^2.0.0" - }, - "bin": { - "glob": "dist/esm/bin.mjs" + "chalk": "^4.0.0", + "jest-diff": "^29.7.0", + "jest-get-type": "^29.6.3", + "pretty-format": "^29.7.0" }, "engines": { - "node": "20 || >=22" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, - "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==", + "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, - "license": "ISC", + "license": "MIT", "dependencies": { - "is-glob": "^4.0.3" + "@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": ">=10.13.0" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, - "node_modules/globals": { - "version": "14.0.0", - "resolved": "https://registry.npmjs.org/globals/-/globals-14.0.0.tgz", - "integrity": "sha512-oahGvuMGQlPw/ivIYBjVSrWAfWLBeku5tpPE2fOPLi+WHffIWbuh2tCjhyQhTBPMf5E9jDEH4FOmTYgYwbKwtQ==", + "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, "license": "MIT", - "engines": { - "node": ">=18" + "dependencies": { + "@jest/types": "^29.6.3", + "@types/node": "*", + "jest-util": "^29.7.0" }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, - "node_modules/globby": { - "version": "11.1.0", - "resolved": "https://registry.npmjs.org/globby/-/globby-11.1.0.tgz", - "integrity": "sha512-jhIXaOzy1sb8IyocaruWSn1TjmnBVs8Ayhcy83rmxNJ8q2uWKCAj3CnJY+KpGSXCueAPc0i05kVvVKtP1t9S3g==", + "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, "license": "MIT", - "dependencies": { - "array-union": "^2.1.0", - "dir-glob": "^3.0.1", - "fast-glob": "^3.2.9", - "ignore": "^5.2.0", - "merge2": "^1.4.1", - "slash": "^3.0.0" - }, "engines": { - "node": ">=10" + "node": ">=6" }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "peerDependencies": { + "jest-resolve": "*" + }, + "peerDependenciesMeta": { + "jest-resolve": { + "optional": true + } } }, - "node_modules/graphemer": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/graphemer/-/graphemer-1.4.0.tgz", - "integrity": "sha512-EtKwoO6kxCL9WO5xipiHTZlSzBm7WLT627TqC/uVRd0HKmq8NXyebnNYxDoBi7wt8eTWrUrKXCOVaFq9x1kgag==", + "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, - "license": "MIT" + "license": "MIT", + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } }, - "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==", + "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, "license": "MIT", + "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": ">=8" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, - "node_modules/hast-util-to-html": { - "version": "9.0.3", - "resolved": "https://registry.npmjs.org/hast-util-to-html/-/hast-util-to-html-9.0.3.tgz", - "integrity": "sha512-M17uBDzMJ9RPCqLMO92gNNUDuBSq10a25SDBI08iCCxmorf4Yy6sYHK57n9WAbRAAaU+DuR4W6GN9K4DFZesYg==", + "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, "license": "MIT", "dependencies": { - "@types/hast": "^3.0.0", - "@types/unist": "^3.0.0", - "ccount": "^2.0.0", - "comma-separated-tokens": "^2.0.0", - "hast-util-whitespace": "^3.0.0", - "html-void-elements": "^3.0.0", - "mdast-util-to-hast": "^13.0.0", - "property-information": "^6.0.0", - "space-separated-tokens": "^2.0.0", - "stringify-entities": "^4.0.0", - "zwitch": "^2.0.4" + "jest-regex-util": "^29.6.3", + "jest-snapshot": "^29.7.0" }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } - }, - "node_modules/hast-util-whitespace": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/hast-util-whitespace/-/hast-util-whitespace-3.0.0.tgz", - "integrity": "sha512-88JUN06ipLwsnv+dVn+OIYOvAuvBMy/Qoi6O7mQHxdPXpjy+Cd6xRkWwux7DKO+4sYILtLBRIKgsdpS2gQc7qw==", + }, + "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, "license": "MIT", "dependencies": { - "@types/hast": "^3.0.0" + "@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" }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, - "node_modules/html-void-elements": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/html-void-elements/-/html-void-elements-3.0.0.tgz", - "integrity": "sha512-bEqo66MRXsUGxWHV5IP0PUiAWwoEjba4VCzg0LjFJBpchPaTfyfCKTG6bc5F8ucKec3q5y6qOdGyYTSBEvhCrg==", + "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, "license": "MIT", - "funding": { - "type": "github", - "url": "https://github.com/sponsors/wooorm" + "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/ignore": { - "version": "5.3.2", - "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.3.2.tgz", - "integrity": "sha512-hsBTNUqQTDwkWtcdYI2i06Y/nUBEsNEDJKjWdigLvegy8kDuJAS8uRlpkkcQpyEXL0Z/pjDy5HBmMjRCJ2gq+g==", + "node_modules/jest-runtime/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, "license": "MIT", - "engines": { - "node": ">= 4" + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" } }, - "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==", + "node_modules/jest-runtime/node_modules/glob": { + "version": "7.2.3", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", + "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", + "deprecated": "Glob versions prior to v9 are no longer supported", "dev": true, - "license": "MIT", + "license": "ISC", "dependencies": { - "parent-module": "^1.0.0", - "resolve-from": "^4.0.0" + "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": ">=6" + "node": "*" }, "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "url": "https://github.com/sponsors/isaacs" } }, - "node_modules/imurmurhash": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz", - "integrity": "sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==", + "node_modules/jest-runtime/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, + "license": "ISC", + "dependencies": { + "brace-expansion": "^1.1.7" + }, + "engines": { + "node": "*" + } + }, + "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, "license": "MIT", + "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": ">=0.8.19" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, - "node_modules/is-binary-path": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz", - "integrity": "sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==", + "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, "license": "MIT", "dependencies": { - "binary-extensions": "^2.0.0" + "@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": ">=8" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, - "node_modules/is-extglob": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", - "integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==", + "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, "license": "MIT", + "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": ">=0.10.0" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, - "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==", + "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, "license": "MIT", "engines": { - "node": ">=8" + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "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==", + "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, "license": "MIT", "dependencies": { - "is-extglob": "^2.1.1" + "@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": ">=0.10.0" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, - "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==", + "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, "license": "MIT", + "dependencies": { + "@types/node": "*", + "jest-util": "^29.7.0", + "merge-stream": "^2.0.0", + "supports-color": "^8.0.0" + }, "engines": { - "node": ">=0.12.0" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, - "node_modules/isexe": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", - "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==", - "dev": true, - "license": "ISC" - }, - "node_modules/jackspeak": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/jackspeak/-/jackspeak-4.0.2.tgz", - "integrity": "sha512-bZsjR/iRjl1Nk1UkjGpAzLNfQtzuijhn2g+pbZb98HQ1Gk8vM9hfbxeMBP+M2/UUdwj0RqGG3mlvk2MsAqwvEw==", + "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, - "license": "BlueOak-1.0.0", + "license": "MIT", "dependencies": { - "@isaacs/cliui": "^8.0.2" + "has-flag": "^4.0.0" }, "engines": { - "node": "20 || >=22" + "node": ">=10" }, "funding": { - "url": "https://github.com/sponsors/isaacs" + "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, + "license": "MIT" + }, "node_modules/js-yaml": { "version": "4.1.0", "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz", @@ -1838,6 +5124,19 @@ "js-yaml": "bin/js-yaml.js" } }, + "node_modules/jsesc": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-3.0.2.tgz", + "integrity": "sha512-xKqzzWXDttJuOcawBt4KnKHHIf5oQ/Cxax+0PWFG+DFDgHNAdi+TXECADI+RYiFUMmx8792xsMbbgXj4CwnP4g==", + "dev": true, + "license": "MIT", + "bin": { + "jsesc": "bin/jsesc" + }, + "engines": { + "node": ">=6" + } + }, "node_modules/json-buffer": { "version": "3.0.1", "resolved": "https://registry.npmjs.org/json-buffer/-/json-buffer-3.0.1.tgz", @@ -1845,6 +5144,13 @@ "dev": true, "license": "MIT" }, + "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, + "license": "MIT" + }, "node_modules/json-schema-traverse": { "version": "0.4.1", "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", @@ -1859,6 +5165,19 @@ "dev": true, "license": "MIT" }, + "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, + "license": "MIT", + "bin": { + "json5": "lib/cli.js" + }, + "engines": { + "node": ">=6" + } + }, "node_modules/keyv": { "version": "4.5.4", "resolved": "https://registry.npmjs.org/keyv/-/keyv-4.5.4.tgz", @@ -1869,6 +5188,26 @@ "json-buffer": "3.0.1" } }, + "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, + "license": "MIT", + "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, + "license": "MIT", + "engines": { + "node": ">=6" + } + }, "node_modules/levn": { "version": "0.4.1", "resolved": "https://registry.npmjs.org/levn/-/levn-0.4.1.tgz", @@ -1883,6 +5222,13 @@ "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, + "license": "MIT" + }, "node_modules/linkify-it": { "version": "5.0.0", "resolved": "https://registry.npmjs.org/linkify-it/-/linkify-it-5.0.0.tgz", @@ -1909,6 +5255,13 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/lodash.memoize": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/lodash.memoize/-/lodash.memoize-4.1.2.tgz", + "integrity": "sha512-t7j+NzmgnQzTAYXcsHYLgimltOV1MXHtlOWf6GjL9Kj8GK5FInw5JotxvbOs+IvV1/Dzo04/fCGfLVs7aXb4Ag==", + "dev": true, + "license": "MIT" + }, "node_modules/lodash.merge": { "version": "4.6.2", "resolved": "https://registry.npmjs.org/lodash.merge/-/lodash.merge-4.6.2.tgz", @@ -1933,6 +5286,22 @@ "dev": true, "license": "MIT" }, + "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, + "license": "MIT", + "dependencies": { + "semver": "^7.5.3" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/make-error": { "version": "1.3.6", "resolved": "https://registry.npmjs.org/make-error/-/make-error-1.3.6.tgz", @@ -1940,6 +5309,16 @@ "dev": true, "license": "ISC" }, + "node_modules/makeerror": { + "version": "1.0.12", + "resolved": "https://registry.npmjs.org/makeerror/-/makeerror-1.0.12.tgz", + "integrity": "sha512-JmqCvUhmt43madlpFzG4BQzG2Z3m6tvQDNKdClZnO3VbIudJYmxsT0FNJMeiB2+JTSlTQTSbU8QdesVmwJcmLg==", + "dev": true, + "license": "BSD-3-Clause", + "dependencies": { + "tmpl": "1.0.5" + } + }, "node_modules/markdown-it": { "version": "14.1.0", "resolved": "https://registry.npmjs.org/markdown-it/-/markdown-it-14.1.0.tgz", @@ -1987,6 +5366,13 @@ "dev": true, "license": "MIT" }, + "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, + "license": "MIT" + }, "node_modules/merge2": { "version": "1.4.1", "resolved": "https://registry.npmjs.org/merge2/-/merge2-1.4.1.tgz", @@ -1997,6 +5383,16 @@ "node": ">= 8" } }, + "node_modules/methods": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/methods/-/methods-1.1.2.tgz", + "integrity": "sha512-iclAHeNqNm68zFtnZ0e+1L2yUIdvzNoauKU4WBA3VvH/vPFieF7qfRlwUZU+DA9P9bPXIS90ulxoUoCH23sV2w==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, "node_modules/micromark-util-character": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/micromark-util-character/-/micromark-util-character-2.1.0.tgz", @@ -2105,6 +5501,52 @@ "node": ">=8.6" } }, + "node_modules/mime": { + "version": "2.6.0", + "resolved": "https://registry.npmjs.org/mime/-/mime-2.6.0.tgz", + "integrity": "sha512-USPkMeET31rOMiarsBNIHZKLGgvKc/LrjofAnBlOttf5ajRvqiRA8QsenbcooctK6d6Ts6aqZXBA+XbkKthiQg==", + "dev": true, + "license": "MIT", + "bin": { + "mime": "cli.js" + }, + "engines": { + "node": ">=4.0.0" + } + }, + "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==", + "dev": true, + "license": "MIT", + "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==", + "dev": true, + "license": "MIT", + "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, + "license": "MIT", + "engines": { + "node": ">=6" + } + }, "node_modules/minimatch": { "version": "10.0.1", "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-10.0.1.tgz", @@ -2159,6 +5601,20 @@ "dev": true, "license": "MIT" }, + "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, + "license": "MIT" + }, + "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, + "license": "MIT" + }, "node_modules/normalize-path": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz", @@ -2166,7 +5622,59 @@ "dev": true, "license": "MIT", "engines": { - "node": ">=0.10.0" + "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, + "license": "MIT", + "dependencies": { + "path-key": "^3.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/object-inspect": { + "version": "1.13.2", + "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.13.2.tgz", + "integrity": "sha512-IRZSRuzJiynemAXPYtPe5BoI/RESNYR7TYm50MC5Mqbd3Jmw5y790sErYw3V6SryFJD64b74qQQs9wn5Bg/k3g==", + "dev": true, + "license": "MIT", + "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, + "license": "ISC", + "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, + "license": "MIT", + "dependencies": { + "mimic-fn": "^2.1.0" + }, + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, "node_modules/oniguruma-to-js": { @@ -2232,6 +5740,16 @@ "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, + "license": "MIT", + "engines": { + "node": ">=6" + } + }, "node_modules/package-json-from-dist": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/package-json-from-dist/-/package-json-from-dist-1.0.1.tgz", @@ -2252,6 +5770,25 @@ "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, + "license": "MIT", + "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", @@ -2262,6 +5799,16 @@ "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, + "license": "MIT", + "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", @@ -2272,6 +5819,13 @@ "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, + "license": "MIT" + }, "node_modules/path-scurry": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/path-scurry/-/path-scurry-2.0.0.tgz", @@ -2299,6 +5853,13 @@ "node": ">=8" } }, + "node_modules/picocolors": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.1.1.tgz", + "integrity": "sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==", + "dev": true, + "license": "ISC" + }, "node_modules/picomatch": { "version": "2.3.1", "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", @@ -2312,6 +5873,85 @@ "url": "https://github.com/sponsors/jonschlinkert" } }, + "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, + "license": "MIT", + "engines": { + "node": ">= 6" + } + }, + "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, + "license": "MIT", + "dependencies": { + "find-up": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/pkg-dir/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, + "license": "MIT", + "dependencies": { + "locate-path": "^5.0.0", + "path-exists": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/pkg-dir/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, + "license": "MIT", + "dependencies": { + "p-locate": "^4.1.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/pkg-dir/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, + "license": "MIT", + "dependencies": { + "p-try": "^2.0.0" + }, + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/pkg-dir/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, + "license": "MIT", + "dependencies": { + "p-limit": "^2.2.0" + }, + "engines": { + "node": ">=8" + } + }, "node_modules/plimit-lit": { "version": "1.6.1", "resolved": "https://registry.npmjs.org/plimit-lit/-/plimit-lit-1.6.1.tgz", @@ -2335,6 +5975,48 @@ "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, + "license": "MIT", + "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, + "license": "MIT", + "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, + "license": "MIT", + "dependencies": { + "kleur": "^3.0.3", + "sisteransi": "^1.0.5" + }, + "engines": { + "node": ">= 6" + } + }, "node_modules/property-information": { "version": "6.5.0", "resolved": "https://registry.npmjs.org/property-information/-/property-information-6.5.0.tgz", @@ -2366,6 +6048,39 @@ "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" + } + ], + "license": "MIT" + }, + "node_modules/qs": { + "version": "6.13.0", + "resolved": "https://registry.npmjs.org/qs/-/qs-6.13.0.tgz", + "integrity": "sha512-+38qI9SOr8tfZ4QmJNplMUxqjbe7LKvvZgWdExBOmd+egZTtjLB67Gu0HRX3u/XOq7UU2Nx6nsjvS16Z9uwfpg==", + "dev": true, + "license": "BSD-3-Clause", + "dependencies": { + "side-channel": "^1.0.6" + }, + "engines": { + "node": ">=0.6" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/queue-lit": { "version": "1.5.2", "resolved": "https://registry.npmjs.org/queue-lit/-/queue-lit-1.5.2.tgz", @@ -2397,6 +6112,13 @@ ], "license": "MIT" }, + "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, + "license": "MIT" + }, "node_modules/readdirp": { "version": "3.6.0", "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz", @@ -2417,6 +6139,57 @@ "dev": true, "license": "MIT" }, + "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, + "license": "MIT", + "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, + "license": "MIT", + "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, + "license": "MIT", + "dependencies": { + "resolve-from": "^5.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/resolve-cwd/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, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, "node_modules/resolve-from": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz", @@ -2437,6 +6210,16 @@ "url": "https://github.com/privatenumber/resolve-pkg-maps?sponsor=1" } }, + "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, + "license": "MIT", + "engines": { + "node": ">=10" + } + }, "node_modules/reusify": { "version": "1.0.4", "resolved": "https://registry.npmjs.org/reusify/-/reusify-1.0.4.tgz", @@ -2505,6 +6288,24 @@ "node": ">=10" } }, + "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==", + "dev": true, + "license": "MIT", + "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/shebang-command": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", @@ -2543,6 +6344,25 @@ "@types/hast": "^3.0.4" } }, + "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==", + "dev": true, + "license": "MIT", + "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": "4.1.0", "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-4.1.0.tgz", @@ -2556,6 +6376,13 @@ "url": "https://github.com/sponsors/isaacs" } }, + "node_modules/sisteransi": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/sisteransi/-/sisteransi-1.0.5.tgz", + "integrity": "sha512-bLGGlR1QxBcynn2d5YmDX4MGjlZvy2MRBDRNHLJ8VI6l6+9FUiyTFNJ0IveOSP0bcXgVDPRcfGqA0pjaqUpfVg==", + "dev": true, + "license": "MIT" + }, "node_modules/slash": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/slash/-/slash-3.0.0.tgz", @@ -2566,15 +6393,103 @@ "node": ">=8" } }, - "node_modules/space-separated-tokens": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/space-separated-tokens/-/space-separated-tokens-2.0.2.tgz", - "integrity": "sha512-PEGlAwrG8yXGXRjW32fGbg66JAlOAwbObuqVoJpv/mRgoWDQfgH1wDPvtzWyUSNAXBGSk8h755YDbbcEy3SH2Q==", + "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, + "license": "BSD-3-Clause", + "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, + "license": "MIT", + "dependencies": { + "buffer-from": "^1.0.0", + "source-map": "^0.6.0" + } + }, + "node_modules/space-separated-tokens": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/space-separated-tokens/-/space-separated-tokens-2.0.2.tgz", + "integrity": "sha512-PEGlAwrG8yXGXRjW32fGbg66JAlOAwbObuqVoJpv/mRgoWDQfgH1wDPvtzWyUSNAXBGSk8h755YDbbcEy3SH2Q==", + "dev": true, + "license": "MIT", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "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, + "license": "BSD-3-Clause" + }, + "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, + "license": "MIT", + "dependencies": { + "escape-string-regexp": "^2.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/stack-utils/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, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "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, + "license": "MIT", + "dependencies": { + "char-regex": "^1.0.2", + "strip-ansi": "^6.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/string-length/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, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/string-length/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, "license": "MIT", - "funding": { - "type": "github", - "url": "https://github.com/sponsors/wooorm" + "dependencies": { + "ansi-regex": "^5.0.1" + }, + "engines": { + "node": ">=8" } }, "node_modules/string-width": { @@ -2696,6 +6611,26 @@ "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, + "license": "MIT", + "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, + "license": "MIT", + "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", @@ -2709,6 +6644,41 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/superagent": { + "version": "9.0.2", + "resolved": "https://registry.npmjs.org/superagent/-/superagent-9.0.2.tgz", + "integrity": "sha512-xuW7dzkUpcJq7QnhOsnNUgtYp3xRwpt2F7abdRYIpCsAt0hhUqia0EdxyXZQQpNmGtsCzYHryaKSV3q3GJnq7w==", + "dev": true, + "license": "MIT", + "dependencies": { + "component-emitter": "^1.3.0", + "cookiejar": "^2.1.4", + "debug": "^4.3.4", + "fast-safe-stringify": "^2.1.1", + "form-data": "^4.0.0", + "formidable": "^3.5.1", + "methods": "^1.1.2", + "mime": "2.6.0", + "qs": "^6.11.0" + }, + "engines": { + "node": ">=14.18.0" + } + }, + "node_modules/supertest": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/supertest/-/supertest-7.0.0.tgz", + "integrity": "sha512-qlsr7fIC0lSddmA3tzojvzubYxvlGtzumcdHgPwbFWMISQwL22MhM2Y3LNt+6w9Yyx7559VW5ab70dgphm8qQA==", + "dev": true, + "license": "MIT", + "dependencies": { + "methods": "^1.1.2", + "superagent": "^9.0.1" + }, + "engines": { + "node": ">=14.18.0" + } + }, "node_modules/supports-color": { "version": "7.2.0", "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", @@ -2722,6 +6692,80 @@ "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, + "license": "MIT", + "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, + "license": "ISC", + "dependencies": { + "@istanbuljs/schema": "^0.1.2", + "glob": "^7.1.4", + "minimatch": "^3.0.4" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/test-exclude/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, + "license": "MIT", + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "node_modules/test-exclude/node_modules/glob": { + "version": "7.2.3", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", + "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", + "deprecated": "Glob versions prior to v9 are no longer supported", + "dev": true, + "license": "ISC", + "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/test-exclude/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, + "license": "ISC", + "dependencies": { + "brace-expansion": "^1.1.7" + }, + "engines": { + "node": "*" + } + }, "node_modules/text-table": { "version": "0.2.0", "resolved": "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz", @@ -2729,6 +6773,13 @@ "dev": true, "license": "MIT" }, + "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, + "license": "BSD-3-Clause" + }, "node_modules/to-regex-range": { "version": "5.0.1", "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", @@ -2766,6 +6817,55 @@ "typescript": ">=4.2.0" } }, + "node_modules/ts-jest": { + "version": "29.2.5", + "resolved": "https://registry.npmjs.org/ts-jest/-/ts-jest-29.2.5.tgz", + "integrity": "sha512-KD8zB2aAZrcKIdGk4OwpJggeLcH1FgrICqDSROWqlnJXGCXK4Mn6FcdK2B6670Xr73lHMG1kHw8R87A0ecZ+vA==", + "dev": true, + "license": "MIT", + "dependencies": { + "bs-logger": "^0.2.6", + "ejs": "^3.1.10", + "fast-json-stable-stringify": "^2.1.0", + "jest-util": "^29.0.0", + "json5": "^2.2.3", + "lodash.memoize": "^4.1.2", + "make-error": "^1.3.6", + "semver": "^7.6.3", + "yargs-parser": "^21.1.1" + }, + "bin": { + "ts-jest": "cli.js" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || ^18.0.0 || >=20.0.0" + }, + "peerDependencies": { + "@babel/core": ">=7.0.0-beta.0 <8", + "@jest/transform": "^29.0.0", + "@jest/types": "^29.0.0", + "babel-jest": "^29.0.0", + "jest": "^29.0.0", + "typescript": ">=4.3 <6" + }, + "peerDependenciesMeta": { + "@babel/core": { + "optional": true + }, + "@jest/transform": { + "optional": true + }, + "@jest/types": { + "optional": true + }, + "babel-jest": { + "optional": true + }, + "esbuild": { + "optional": true + } + } + }, "node_modules/ts-node": { "version": "10.9.2", "resolved": "https://registry.npmjs.org/ts-node/-/ts-node-10.9.2.tgz", @@ -2861,6 +6961,29 @@ "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, + "license": "MIT", + "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, + "license": "(MIT OR CC0-1.0)", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/typedoc": { "version": "0.26.9", "resolved": "https://registry.npmjs.org/typedoc/-/typedoc-0.26.9.tgz", @@ -3025,6 +7148,37 @@ "url": "https://opencollective.com/unified" } }, + "node_modules/update-browserslist-db": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.1.1.tgz", + "integrity": "sha512-R8UzCaa9Az+38REPiJ1tXlImTJXlVfgHZsglwBD/k6nj76ctsH1E3q4doGrukiLQd3sGQYu56r5+lo5r94l29A==", + "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" + } + ], + "license": "MIT", + "dependencies": { + "escalade": "^3.2.0", + "picocolors": "^1.1.0" + }, + "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", @@ -3042,6 +7196,32 @@ "dev": true, "license": "MIT" }, + "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, + "license": "ISC", + "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/v8-to-istanbul/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, + "license": "MIT", + "dependencies": { + "@jridgewell/resolve-uri": "^3.1.0", + "@jridgewell/sourcemap-codec": "^1.4.14" + } + }, "node_modules/vfile": { "version": "6.0.3", "resolved": "https://registry.npmjs.org/vfile/-/vfile-6.0.3.tgz", @@ -3072,6 +7252,16 @@ "url": "https://opencollective.com/unified" } }, + "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, + "license": "Apache-2.0", + "dependencies": { + "makeerror": "1.0.12" + } + }, "node_modules/which": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", @@ -3196,6 +7386,51 @@ "node": ">=8" } }, + "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, + "license": "ISC" + }, + "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, + "license": "ISC", + "dependencies": { + "imurmurhash": "^0.1.4", + "signal-exit": "^3.0.7" + }, + "engines": { + "node": "^12.13.0 || ^14.15.0 || >=16.0.0" + } + }, + "node_modules/write-file-atomic/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, + "license": "ISC" + }, + "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, + "license": "ISC", + "engines": { + "node": ">=10" + } + }, + "node_modules/yallist": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-3.1.1.tgz", + "integrity": "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==", + "dev": true, + "license": "ISC" + }, "node_modules/yaml": { "version": "2.6.0", "resolved": "https://registry.npmjs.org/yaml/-/yaml-2.6.0.tgz", @@ -3209,6 +7444,80 @@ "node": ">= 14" } }, + "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, + "license": "MIT", + "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, + "license": "ISC", + "engines": { + "node": ">=12" + } + }, + "node_modules/yargs/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, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/yargs/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, + "license": "MIT" + }, + "node_modules/yargs/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, + "license": "MIT", + "dependencies": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/yargs/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, + "license": "MIT", + "dependencies": { + "ansi-regex": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, "node_modules/yn": { "version": "3.1.1", "resolved": "https://registry.npmjs.org/yn/-/yn-3.1.1.tgz", diff --git a/mlflow/package.json b/mlflow/package.json index ab0cdce2..1a8a8f6c 100644 --- a/mlflow/package.json +++ b/mlflow/package.json @@ -14,7 +14,7 @@ "scripts": { "clean": "rimraf lib", "build": "npm run clean && tsc -p tsconfig.json && tsc-alias -p tsconfig.json", - "test": "", + "test": "jest", "lint": "eslint .", "docs": "typedoc src/index.ts" }, @@ -30,9 +30,14 @@ "devDependencies": { "@eslint/js": "^9.12.0", "@types/eslint__js": "^8.42.3", + "@types/jest": "^29.5.14", "@types/node": "^22.5.4", + "@types/supertest": "^6.0.2", "eslint": "^9.12.0", + "jest": "^29.7.0", "rimraf": "^6.0.1", + "supertest": "^7.0.0", + "ts-jest": "^29.2.5", "ts-node": "^10.9.2", "tsc-alias": "^1.8.10", "tsx": "^4.19.1", From 5791d124eef4ac62532a2701313214e3567c7934 Mon Sep 17 00:00:00 2001 From: Stephany Ho Date: Wed, 23 Oct 2024 22:21:48 -0400 Subject: [PATCH 207/357] Jest example with createRun --- mlflow/tests/RunClient.test.ts | 134 +++++++++++++++++++++++++++++++++ mlflow/tsconfig.json | 2 + 2 files changed, 136 insertions(+) create mode 100644 mlflow/tests/RunClient.test.ts diff --git a/mlflow/tests/RunClient.test.ts b/mlflow/tests/RunClient.test.ts new file mode 100644 index 00000000..50ea09ad --- /dev/null +++ b/mlflow/tests/RunClient.test.ts @@ -0,0 +1,134 @@ +import { describe, test, expect, beforeEach, it } from '@jest/globals'; +import request from 'supertest'; +import RunClient from '../src/tracking/RunClient'; +import { ApiError } from '../src/utils/apiError'; + +const baseUrl = 'http://127.0.0.1:5000'; + +interface Run { + info: { + run_id: string; + run_name: string; + experiment_id: string; + status: string; + start_time: number; + end_time: number; + artifact_uri: string; + lifecycle_stage: string; + }; + data: { + metrics: Array<{ key: string; value: number }>; + params: Array<{ key: string; value: number }>; + tags: Array<{ key: string; value: number }>; + }; + inputs: Array<{ + tags?: Array<{ key: string; value: string }>; + dataset: { + name: string; + digest: string; + source_type: string; + source: string; + schema?: string; + profile?: string; + }; + }>; +} + +describe('RunClient', () => { + let client: RunClient; + + beforeEach(() => { + client = new RunClient('http://127.0.0.1:5000'); + }); + + describe('createRun', () => { + // POST - Create a new run within an experiment + test('- Should create a run with experiment_id', async () => { + const experiment_id = '876374673578277025'; + + const response = (await client.createRun(experiment_id)) as Run; + + expect(response.info.experiment_id).toBe(experiment_id); + }); + + test('- Should create a run with optional run_name', async () => { + const experiment_id = '876374673578277025'; + const run_name = 'Test Run 1'; + + const response = (await client.createRun(experiment_id, run_name)) as Run; + + expect(response.info.run_name).toBe(run_name); + expect(response.data.tags).toContainEqual({ + key: 'mlflow.runName', + value: run_name, + }); + }); + + test('- Should create a run with optional tags', async () => { + const experiment_id = '876374673578277025'; + const tags = [ + { key: 'test_key1', value: 'test_value1' }, + { key: 'test_key2', value: 'test_value2' }, + ]; + + const response = (await client.createRun( + experiment_id, + undefined, + undefined, + tags + )) as Run; + + expect(response.data).toHaveProperty('tags'); + tags.forEach((tag) => { + expect(response.data.tags).toContainEqual(tag); + }); + }); + + test('- Should create a run with all parameters', async () => { + const experiment_id = '876374673578277025'; + const run_name = 'Test Run 2'; + const start_time = Date.now(); + const tags = [{ key: 'test_key', value: 'test_value' }]; + + const response = (await client.createRun( + experiment_id, + run_name, + start_time, + tags + )) as Run; + + expect(response.info.experiment_id).toBe(experiment_id); + expect(response.info.run_name).toBe(run_name); + expect(response.info.start_time).toBe(start_time); + expect(response.data.tags).toContainEqual(tags[0]); + }); + + test('- Should handle API errors', async () => { + const invalid_id = 'invalid_id'; + + // the thrown error is specifically an instance of 'ApiError' + await expect(client.createRun(invalid_id)).rejects.toThrow(ApiError); + + // the thrown error message with invalid_id somewhere in the message + await expect(client.createRun(invalid_id)).rejects.toThrow( + /Error creating run:.+invalid_id/ + ); + }); + }); +}); + +describe('MLflow API Integration Tests', () => { + it('- Should create a run using direct API call', async () => { + const experiment_id = '876374673578277025'; + const run_name = 'Test Run'; + + const response = await request(baseUrl) + .post('/api/2.0/mlflow/runs/create') + .send({ experiment_id, run_name }) + .expect(200); + + expect(response.body).toHaveProperty('run'); + expect(response.body.run.info.experiment_id).toBe(experiment_id); + expect(response.body.run.info.run_name).toBe(run_name); + }); +}); diff --git a/mlflow/tsconfig.json b/mlflow/tsconfig.json index 44c5e84b..56c101ec 100644 --- a/mlflow/tsconfig.json +++ b/mlflow/tsconfig.json @@ -7,6 +7,8 @@ "rootDir": "./src", "outDir": "./lib", + "types": ["jest"], + // Module Resolution Options "moduleResolution": "node", "baseUrl": ".", From b0a2ee63857f04fe36358a24a6822fd2ead5c255 Mon Sep 17 00:00:00 2001 From: Yiqun Zheng <16813562+yiqunzheng@users.noreply.github.com> Date: Wed, 23 Oct 2024 19:29:35 -0700 Subject: [PATCH 208/357] revise gitignore --- mlflow/.gitignore | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/mlflow/.gitignore b/mlflow/.gitignore index b8a1302f..c5f218af 100644 --- a/mlflow/.gitignore +++ b/mlflow/.gitignore @@ -13,6 +13,4 @@ mlruns/ lib/ # Temporary files -temp/ - -package-lock.json \ No newline at end of file +temp/ \ No newline at end of file From 1cb09cbe4b47133b55367f19a73c382aaebbe22f Mon Sep 17 00:00:00 2001 From: Yiqun Zheng <16813562+yiqunzheng@users.noreply.github.com> Date: Wed, 23 Oct 2024 19:34:06 -0700 Subject: [PATCH 209/357] Reset package-lock.json --- mlflow/package-lock.json | 968 ++++++++++++++++----------------------- 1 file changed, 400 insertions(+), 568 deletions(-) diff --git a/mlflow/package-lock.json b/mlflow/package-lock.json index cccf343e..ff241243 100644 --- a/mlflow/package-lock.json +++ b/mlflow/package-lock.json @@ -40,6 +40,278 @@ "node": ">=12" } }, + "node_modules/@esbuild/aix-ppc64": { + "version": "0.23.1", + "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.23.1.tgz", + "integrity": "sha512-6VhYk1diRqrhBAqpJEdjASR/+WVRtfjpqKuNw11cLiaWpAT/Uu+nokB+UJnevzy/P9C/ty6AOe0dwueMrGh/iQ==", + "cpu": [ + "ppc64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "aix" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/android-arm": { + "version": "0.23.1", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.23.1.tgz", + "integrity": "sha512-uz6/tEy2IFm9RYOyvKl88zdzZfwEfKZmnX9Cj1BHjeSGNuGLuMD1kR8y5bteYmwqKm1tj8m4cb/aKEorr6fHWQ==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/android-arm64": { + "version": "0.23.1", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.23.1.tgz", + "integrity": "sha512-xw50ipykXcLstLeWH7WRdQuysJqejuAGPd30vd1i5zSyKK3WE+ijzHmLKxdiCMtH1pHz78rOg0BKSYOSB/2Khw==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/android-x64": { + "version": "0.23.1", + "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.23.1.tgz", + "integrity": "sha512-nlN9B69St9BwUoB+jkyU090bru8L0NA3yFvAd7k8dNsVH8bi9a8cUAUSEcEEgTp2z3dbEDGJGfP6VUnkQnlReg==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/darwin-arm64": { + "version": "0.23.1", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.23.1.tgz", + "integrity": "sha512-YsS2e3Wtgnw7Wq53XXBLcV6JhRsEq8hkfg91ESVadIrzr9wO6jJDMZnCQbHm1Guc5t/CdDiFSSfWP58FNuvT3Q==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/darwin-x64": { + "version": "0.23.1", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.23.1.tgz", + "integrity": "sha512-aClqdgTDVPSEGgoCS8QDG37Gu8yc9lTHNAQlsztQ6ENetKEO//b8y31MMu2ZaPbn4kVsIABzVLXYLhCGekGDqw==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/freebsd-arm64": { + "version": "0.23.1", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.23.1.tgz", + "integrity": "sha512-h1k6yS8/pN/NHlMl5+v4XPfikhJulk4G+tKGFIOwURBSFzE8bixw1ebjluLOjfwtLqY0kewfjLSrO6tN2MgIhA==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/freebsd-x64": { + "version": "0.23.1", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.23.1.tgz", + "integrity": "sha512-lK1eJeyk1ZX8UklqFd/3A60UuZ/6UVfGT2LuGo3Wp4/z7eRTRYY+0xOu2kpClP+vMTi9wKOfXi2vjUpO1Ro76g==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-arm": { + "version": "0.23.1", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.23.1.tgz", + "integrity": "sha512-CXXkzgn+dXAPs3WBwE+Kvnrf4WECwBdfjfeYHpMeVxWE0EceB6vhWGShs6wi0IYEqMSIzdOF1XjQ/Mkm5d7ZdQ==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-arm64": { + "version": "0.23.1", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.23.1.tgz", + "integrity": "sha512-/93bf2yxencYDnItMYV/v116zff6UyTjo4EtEQjUBeGiVpMmffDNUyD9UN2zV+V3LRV3/on4xdZ26NKzn6754g==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-ia32": { + "version": "0.23.1", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.23.1.tgz", + "integrity": "sha512-VTN4EuOHwXEkXzX5nTvVY4s7E/Krz7COC8xkftbbKRYAl96vPiUssGkeMELQMOnLOJ8k3BY1+ZY52tttZnHcXQ==", + "cpu": [ + "ia32" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-loong64": { + "version": "0.23.1", + "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.23.1.tgz", + "integrity": "sha512-Vx09LzEoBa5zDnieH8LSMRToj7ir/Jeq0Gu6qJ/1GcBq9GkfoEAoXvLiW1U9J1qE/Y/Oyaq33w5p2ZWrNNHNEw==", + "cpu": [ + "loong64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-mips64el": { + "version": "0.23.1", + "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.23.1.tgz", + "integrity": "sha512-nrFzzMQ7W4WRLNUOU5dlWAqa6yVeI0P78WKGUo7lg2HShq/yx+UYkeNSE0SSfSure0SqgnsxPvmAUu/vu0E+3Q==", + "cpu": [ + "mips64el" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-ppc64": { + "version": "0.23.1", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.23.1.tgz", + "integrity": "sha512-dKN8fgVqd0vUIjxuJI6P/9SSSe/mB9rvA98CSH2sJnlZ/OCZWO1DJvxj8jvKTfYUdGfcq2dDxoKaC6bHuTlgcw==", + "cpu": [ + "ppc64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-riscv64": { + "version": "0.23.1", + "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.23.1.tgz", + "integrity": "sha512-5AV4Pzp80fhHL83JM6LoA6pTQVWgB1HovMBsLQ9OZWLDqVY8MVobBXNSmAJi//Csh6tcY7e7Lny2Hg1tElMjIA==", + "cpu": [ + "riscv64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-s390x": { + "version": "0.23.1", + "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.23.1.tgz", + "integrity": "sha512-9ygs73tuFCe6f6m/Tb+9LtYxWR4c9yg7zjt2cYkjDbDpV/xVn+68cQxMXCjUpYwEkze2RcU/rMnfIXNRFmSoDw==", + "cpu": [ + "s390x" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, "node_modules/@esbuild/linux-x64": { "version": "0.23.1", "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.23.1.tgz", @@ -57,6 +329,125 @@ "node": ">=18" } }, + "node_modules/@esbuild/netbsd-x64": { + "version": "0.23.1", + "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.23.1.tgz", + "integrity": "sha512-aevEkCNu7KlPRpYLjwmdcuNz6bDFiE7Z8XC4CPqExjTvrHugh28QzUXVOZtiYghciKUacNktqxdpymplil1beA==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "netbsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/openbsd-arm64": { + "version": "0.23.1", + "resolved": "https://registry.npmjs.org/@esbuild/openbsd-arm64/-/openbsd-arm64-0.23.1.tgz", + "integrity": "sha512-3x37szhLexNA4bXhLrCC/LImN/YtWis6WXr1VESlfVtVeoFJBRINPJ3f0a/6LV8zpikqoUg4hyXw0sFBt5Cr+Q==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "openbsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/openbsd-x64": { + "version": "0.23.1", + "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.23.1.tgz", + "integrity": "sha512-aY2gMmKmPhxfU+0EdnN+XNtGbjfQgwZj43k8G3fyrDM/UdZww6xrWxmDkuz2eCZchqVeABjV5BpildOrUbBTqA==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "openbsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/sunos-x64": { + "version": "0.23.1", + "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.23.1.tgz", + "integrity": "sha512-RBRT2gqEl0IKQABT4XTj78tpk9v7ehp+mazn2HbUeZl1YMdaGAQqhapjGTCe7uw7y0frDi4gS0uHzhvpFuI1sA==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "sunos" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/win32-arm64": { + "version": "0.23.1", + "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.23.1.tgz", + "integrity": "sha512-4O+gPR5rEBe2FpKOVyiJ7wNDPA8nGzDuJ6gN4okSA1gEOYZ67N8JPk58tkWtdtPeLz7lBnY6I5L3jdsr3S+A6A==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/win32-ia32": { + "version": "0.23.1", + "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.23.1.tgz", + "integrity": "sha512-BcaL0Vn6QwCwre3Y717nVHZbAa4UBEigzFm6VdsVdT/MbZ38xoj1X9HPkZhbmaBGUD1W8vxAfffbDe8bA6AKnQ==", + "cpu": [ + "ia32" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/win32-x64": { + "version": "0.23.1", + "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.23.1.tgz", + "integrity": "sha512-BHpFFeslkWrXWyUPnbKm+xYYVYruCinGcftSBaa8zoF9hZO4BcSCFUvHVTtzpIY6YzUnYtuEhZ+C9iEXjxnasg==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=18" + } + }, "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", @@ -450,62 +841,6 @@ "node": ">= 8" } }, - "node_modules/@shikijs/core": { - "version": "1.22.0", - "resolved": "https://registry.npmjs.org/@shikijs/core/-/core-1.22.0.tgz", - "integrity": "sha512-S8sMe4q71TJAW+qG93s5VaiihujRK6rqDFqBnxqvga/3LvqHEnxqBIOPkt//IdXVtHkQWKu4nOQNk0uBGicU7Q==", - "dev": true, - "license": "MIT", - "dependencies": { - "@shikijs/engine-javascript": "1.22.0", - "@shikijs/engine-oniguruma": "1.22.0", - "@shikijs/types": "1.22.0", - "@shikijs/vscode-textmate": "^9.3.0", - "@types/hast": "^3.0.4", - "hast-util-to-html": "^9.0.3" - } - }, - "node_modules/@shikijs/engine-javascript": { - "version": "1.22.0", - "resolved": "https://registry.npmjs.org/@shikijs/engine-javascript/-/engine-javascript-1.22.0.tgz", - "integrity": "sha512-AeEtF4Gcck2dwBqCFUKYfsCq0s+eEbCEbkUuFou53NZ0sTGnJnJ/05KHQFZxpii5HMXbocV9URYVowOP2wH5kw==", - "dev": true, - "license": "MIT", - "dependencies": { - "@shikijs/types": "1.22.0", - "@shikijs/vscode-textmate": "^9.3.0", - "oniguruma-to-js": "0.4.3" - } - }, - "node_modules/@shikijs/engine-oniguruma": { - "version": "1.22.0", - "resolved": "https://registry.npmjs.org/@shikijs/engine-oniguruma/-/engine-oniguruma-1.22.0.tgz", - "integrity": "sha512-5iBVjhu/DYs1HB0BKsRRFipRrD7rqjxlWTj4F2Pf+nQSPqc3kcyqFFeZXnBMzDf0HdqaFVvhDRAGiYNvyLP+Mw==", - "dev": true, - "license": "MIT", - "dependencies": { - "@shikijs/types": "1.22.0", - "@shikijs/vscode-textmate": "^9.3.0" - } - }, - "node_modules/@shikijs/types": { - "version": "1.22.0", - "resolved": "https://registry.npmjs.org/@shikijs/types/-/types-1.22.0.tgz", - "integrity": "sha512-Fw/Nr7FGFhlQqHfxzZY8Cwtwk5E9nKDUgeLjZgt3UuhcM3yJR9xj3ZGNravZZok8XmEZMiYkSMTPlPkULB8nww==", - "dev": true, - "license": "MIT", - "dependencies": { - "@shikijs/vscode-textmate": "^9.3.0", - "@types/hast": "^3.0.4" - } - }, - "node_modules/@shikijs/vscode-textmate": { - "version": "9.3.0", - "resolved": "https://registry.npmjs.org/@shikijs/vscode-textmate/-/vscode-textmate-9.3.0.tgz", - "integrity": "sha512-jn7/7ky30idSkd/O5yDBfAnVt+JJpepofP/POZ1iMOxK59cOfqIgg/Dj0eFsjOTMw+4ycJN0uhZH/Eb0bs/EUA==", - "dev": true, - "license": "MIT" - }, "node_modules/@tensorflow/tfjs": { "version": "4.22.0", "resolved": "https://registry.npmjs.org/@tensorflow/tfjs/-/tfjs-4.22.0.tgz", @@ -782,16 +1117,6 @@ "integrity": "sha512-MqTGEo5bj5t157U6fA/BiDynNkn0YknVdh48CMPkTSpFTVmvao5UQmm7uEF6xBEo7qIMAlY/JSleYaE6VOdpaA==", "license": "MIT" }, - "node_modules/@types/mdast": { - "version": "4.0.4", - "resolved": "https://registry.npmjs.org/@types/mdast/-/mdast-4.0.4.tgz", - "integrity": "sha512-kGaNbPh1k7AFzgpud/gMdvIm5xuECykRR+JnWKQno9TAXVa6WIVCGTPvYGekIDL4uwCZQSYbUxNBSb1aUo79oA==", - "dev": true, - "license": "MIT", - "dependencies": { - "@types/unist": "*" - } - }, "node_modules/@types/node": { "version": "22.7.9", "resolved": "https://registry.npmjs.org/@types/node/-/node-22.7.9.tgz", @@ -823,13 +1148,6 @@ "integrity": "sha512-ytDiArvrn/3Xk6/vtylys5tlY6eo7Ane0hvcx++TKo6RxQXuVfW0AF/oeWqAj9dN29SyhtawuXstgmPlwNcv/A==", "license": "MIT" }, - "node_modules/@types/unist": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/@types/unist/-/unist-3.0.3.tgz", - "integrity": "sha512-ko/gIFJRv177XgZsZcBwnqJN5x/Gien8qNOn0D5bQU/zAzVf9Zt3BlcUiLqhV9y4ARk0GbT3tnUiPNgnTXzc/Q==", - "dev": true, - "license": "MIT" - }, "node_modules/@typescript-eslint/eslint-plugin": { "version": "8.11.0", "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-8.11.0.tgz", @@ -1059,13 +1377,6 @@ "url": "https://opencollective.com/eslint" } }, - "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, - "license": "ISC" - }, "node_modules/@webgpu/types": { "version": "0.1.38", "resolved": "https://registry.npmjs.org/@webgpu/types/-/types-0.1.38.tgz", @@ -1182,7 +1493,6 @@ "integrity": "sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw==", "dev": true, "license": "ISC", - "license": "ISC", "dependencies": { "normalize-path": "^3.0.0", "picomatch": "^2.0.4" @@ -1233,7 +1543,6 @@ "integrity": "sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw==", "dev": true, "license": "MIT", - "license": "MIT", "engines": { "node": ">=8" } @@ -1256,7 +1565,6 @@ "integrity": "sha512-Ceh+7ox5qe7LJuLHoY0feh3pHuUDHAcRUeyL2VYghZwfpkNIy/+8Ocg0a3UuSoYzavmylwuLWQOf3hl0jjMMIw==", "dev": true, "license": "MIT", - "license": "MIT", "engines": { "node": ">=8" }, @@ -1313,28 +1621,6 @@ "url": "https://github.com/chalk/chalk?sponsor=1" } }, - "node_modules/character-entities-html4": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/character-entities-html4/-/character-entities-html4-2.1.0.tgz", - "integrity": "sha512-1v7fgQRj6hnSwFpq1Eu0ynr/CDEw0rXo2B61qXrLNdHZmPKgb7fqS1a2JwF0rISo9q77jDI8VMEHoApn8qDoZA==", - "dev": true, - "license": "MIT", - "funding": { - "type": "github", - "url": "https://github.com/sponsors/wooorm" - } - }, - "node_modules/character-entities-legacy": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/character-entities-legacy/-/character-entities-legacy-3.0.0.tgz", - "integrity": "sha512-RpPp0asT/6ufRm//AJVwpViZbGM/MkjQFxJccQRHmISF/22NBtsHqAWmL+/pmkPWoIUJdWyeVleTl1wydHATVQ==", - "dev": true, - "license": "MIT", - "funding": { - "type": "github", - "url": "https://github.com/sponsors/wooorm" - } - }, "node_modules/chokidar": { "version": "3.6.0", "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.6.0.tgz", @@ -1449,27 +1735,6 @@ "node": ">= 0.8" } }, - "node_modules/comma-separated-tokens": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/comma-separated-tokens/-/comma-separated-tokens-2.0.3.tgz", - "integrity": "sha512-Fu4hJdvzeylCfQPp9SGWidpzrMs7tTrlu6Vb8XGaRGck8QSNZJJp538Wrb60Lax4fPwR64ViY468OIUTbRlGZg==", - "dev": true, - "license": "MIT", - "funding": { - "type": "github", - "url": "https://github.com/sponsors/wooorm" - } - }, - "node_modules/commander": { - "version": "9.5.0", - "resolved": "https://registry.npmjs.org/commander/-/commander-9.5.0.tgz", - "integrity": "sha512-KRs7WVDKg86PWiuAqhDrAQnTXZKraVcCc6vFdL14qrZ/DcWwuRo7VoiYXalXO7S5GKpqYiVEwCbgFDfxNHKJBQ==", - "dev": true, - "license": "MIT", - "engines": { - "node": "^12.20.0 || >=14" - } - }, "node_modules/commander": { "version": "9.5.0", "resolved": "https://registry.npmjs.org/commander/-/commander-9.5.0.tgz", @@ -1564,37 +1829,13 @@ "integrity": "sha512-bd2L678uiWATM6m5Z1VzNCErI3jiGzt6HGY8OVICs40JQq/HALfbyNJmp0UDakEY4pMMaN0Ly5om/B1VI/+xfQ==", "license": "MIT" }, - "node_modules/dequal": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/dequal/-/dequal-2.0.3.tgz", - "integrity": "sha512-0je+qPKHEMohvfRTCEo3CrPG6cAzAYgmzKyxRiYSSDkS6eGJdyVJm7WaYA5ECaAD9wLB2T4EEeymA5aFVcYXCA==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=6" - } - }, "node_modules/detect-libc": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-2.0.3.tgz", - "integrity": "sha512-bwy0MGW55bG41VqxxypOsdSdGqLwXPI/focwgTYCFMbdUiBAxLg9CFzG08sz2aqzknwiX7Hkl0bQENjg8iLByw==", - "license": "Apache-2.0", - "engines": { - "node": ">=8" - } - }, - "node_modules/devlop": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/devlop/-/devlop-1.1.0.tgz", - "integrity": "sha512-RWmIqhcFf1lRYBvNmr7qTNuyCt/7/ns2jbpp1+PalgE/rDQcBT0fioSMUpJ93irlUhC5hrg4cYqe6U+0ImW0rA==", - "dev": true, - "license": "MIT", - "dependencies": { - "dequal": "^2.0.0" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/wooorm" + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-2.0.3.tgz", + "integrity": "sha512-bwy0MGW55bG41VqxxypOsdSdGqLwXPI/focwgTYCFMbdUiBAxLg9CFzG08sz2aqzknwiX7Hkl0bQENjg8iLByw==", + "license": "Apache-2.0", + "engines": { + "node": ">=8" } }, "node_modules/diff": { @@ -1613,7 +1854,6 @@ "integrity": "sha512-WkrWp9GR4KXfKGYzOLmTuGVi1UWFfws377n9cc55/tb6DuqyF6pcQ5AbiHEshaDpY9v6oaSr2XCDidGmMwdzIA==", "dev": true, "license": "MIT", - "license": "MIT", "dependencies": { "path-type": "^4.0.0" }, @@ -1634,19 +1874,6 @@ "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", "license": "MIT" }, - "node_modules/entities": { - "version": "4.5.0", - "resolved": "https://registry.npmjs.org/entities/-/entities-4.5.0.tgz", - "integrity": "sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw==", - "dev": true, - "license": "BSD-2-Clause", - "engines": { - "node": ">=0.12" - }, - "funding": { - "url": "https://github.com/fb55/entities?sponsor=1" - } - }, "node_modules/es6-promise": { "version": "4.2.8", "resolved": "https://registry.npmjs.org/es6-promise/-/es6-promise-4.2.8.tgz", @@ -2161,18 +2388,13 @@ } }, "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==", "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, "license": "ISC", - "license": "ISC", "dependencies": { "is-glob": "^4.0.3" - "is-glob": "^4.0.3" }, "engines": { "node": ">=10.13.0" @@ -2184,7 +2406,6 @@ "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", "dev": true, "license": "MIT", - "license": "MIT", "dependencies": { "balanced-match": "^1.0.0" } @@ -2267,55 +2488,6 @@ "integrity": "sha512-8Rf9Y83NBReMnx0gFzA8JImQACstCYWUplepDa9xprwwtmgEZUF0h/i5xSA625zB/I37EtrswSST6OXxwaaIJQ==", "license": "ISC" }, - "node_modules/hast-util-to-html": { - "version": "9.0.3", - "resolved": "https://registry.npmjs.org/hast-util-to-html/-/hast-util-to-html-9.0.3.tgz", - "integrity": "sha512-M17uBDzMJ9RPCqLMO92gNNUDuBSq10a25SDBI08iCCxmorf4Yy6sYHK57n9WAbRAAaU+DuR4W6GN9K4DFZesYg==", - "dev": true, - "license": "MIT", - "dependencies": { - "@types/hast": "^3.0.0", - "@types/unist": "^3.0.0", - "ccount": "^2.0.0", - "comma-separated-tokens": "^2.0.0", - "hast-util-whitespace": "^3.0.0", - "html-void-elements": "^3.0.0", - "mdast-util-to-hast": "^13.0.0", - "property-information": "^6.0.0", - "space-separated-tokens": "^2.0.0", - "stringify-entities": "^4.0.0", - "zwitch": "^2.0.4" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, - "node_modules/hast-util-whitespace": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/hast-util-whitespace/-/hast-util-whitespace-3.0.0.tgz", - "integrity": "sha512-88JUN06ipLwsnv+dVn+OIYOvAuvBMy/Qoi6O7mQHxdPXpjy+Cd6xRkWwux7DKO+4sYILtLBRIKgsdpS2gQc7qw==", - "dev": true, - "license": "MIT", - "dependencies": { - "@types/hast": "^3.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, - "node_modules/html-void-elements": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/html-void-elements/-/html-void-elements-3.0.0.tgz", - "integrity": "sha512-bEqo66MRXsUGxWHV5IP0PUiAWwoEjba4VCzg0LjFJBpchPaTfyfCKTG6bc5F8ucKec3q5y6qOdGyYTSBEvhCrg==", - "dev": true, - "license": "MIT", - "funding": { - "type": "github", - "url": "https://github.com/sponsors/wooorm" - } - }, "node_modules/https-proxy-agent": { "version": "2.2.4", "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-2.2.4.tgz", @@ -2574,13 +2746,6 @@ "node": "20 || >=22" } }, - "node_modules/lunr": { - "version": "2.3.9", - "resolved": "https://registry.npmjs.org/lunr/-/lunr-2.3.9.tgz", - "integrity": "sha512-zTU3DaZaF3Rt9rhN3uBMGQD3dD2/vFQqnvZCDv4dl5iOzq2IZQqTxu90r4E5J+nP70J3ilqVCrbho2eWaeW8Ow==", - "dev": true, - "license": "MIT" - }, "node_modules/make-dir": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-3.1.0.tgz", @@ -2612,60 +2777,6 @@ "dev": true, "license": "ISC" }, - "node_modules/markdown-it": { - "version": "14.1.0", - "resolved": "https://registry.npmjs.org/markdown-it/-/markdown-it-14.1.0.tgz", - "integrity": "sha512-a54IwgWPaeBCAAsv13YgmALOF1elABB08FxO9i+r4VFk5Vl4pKokRPeX8u5TCgSsPi6ec1otfLjdOpVcgbpshg==", - "dev": true, - "license": "MIT", - "dependencies": { - "argparse": "^2.0.1", - "entities": "^4.4.0", - "linkify-it": "^5.0.0", - "mdurl": "^2.0.0", - "punycode.js": "^2.3.1", - "uc.micro": "^2.1.0" - }, - "bin": { - "markdown-it": "bin/markdown-it.mjs" - } - }, - "node_modules/markdown-it/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, - "license": "Python-2.0" - }, - "node_modules/mdast-util-to-hast": { - "version": "13.2.0", - "resolved": "https://registry.npmjs.org/mdast-util-to-hast/-/mdast-util-to-hast-13.2.0.tgz", - "integrity": "sha512-QGYKEuUsYT9ykKBCMOEDLsU5JRObWQusAolFMeko/tYPufNkRffBAQjIE+99jbA87xv6FgmjLtwjh9wBWajwAA==", - "dev": true, - "license": "MIT", - "dependencies": { - "@types/hast": "^3.0.0", - "@types/mdast": "^4.0.0", - "@ungap/structured-clone": "^1.0.0", - "devlop": "^1.0.0", - "micromark-util-sanitize-uri": "^2.0.0", - "trim-lines": "^3.0.0", - "unist-util-position": "^5.0.0", - "unist-util-visit": "^5.0.0", - "vfile": "^6.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, - "node_modules/mdurl": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/mdurl/-/mdurl-2.0.0.tgz", - "integrity": "sha512-Lf+9+2r+Tdp5wXDXC4PcIBjTDtq4UKjCPMQhKIuzpJNW0b96kVqSwW0bT7FhRSfmAiFYgP+SCRvdrDozfh0U5w==", - "dev": true, - "license": "MIT" - }, "node_modules/merge2": { "version": "1.4.1", "resolved": "https://registry.npmjs.org/merge2/-/merge2-1.4.1.tgz", @@ -2676,100 +2787,6 @@ "node": ">= 8" } }, - "node_modules/micromark-util-character": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/micromark-util-character/-/micromark-util-character-2.1.0.tgz", - "integrity": "sha512-KvOVV+X1yLBfs9dCBSopq/+G1PcgT3lAK07mC4BzXi5E7ahzMAF8oIupDDJ6mievI6F+lAATkbQQlQixJfT3aQ==", - "dev": true, - "funding": [ - { - "type": "GitHub Sponsors", - "url": "https://github.com/sponsors/unifiedjs" - }, - { - "type": "OpenCollective", - "url": "https://opencollective.com/unified" - } - ], - "license": "MIT", - "dependencies": { - "micromark-util-symbol": "^2.0.0", - "micromark-util-types": "^2.0.0" - } - }, - "node_modules/micromark-util-encode": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/micromark-util-encode/-/micromark-util-encode-2.0.0.tgz", - "integrity": "sha512-pS+ROfCXAGLWCOc8egcBvT0kf27GoWMqtdarNfDcjb6YLuV5cM3ioG45Ys2qOVqeqSbjaKg72vU+Wby3eddPsA==", - "dev": true, - "funding": [ - { - "type": "GitHub Sponsors", - "url": "https://github.com/sponsors/unifiedjs" - }, - { - "type": "OpenCollective", - "url": "https://opencollective.com/unified" - } - ], - "license": "MIT" - }, - "node_modules/micromark-util-sanitize-uri": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/micromark-util-sanitize-uri/-/micromark-util-sanitize-uri-2.0.0.tgz", - "integrity": "sha512-WhYv5UEcZrbAtlsnPuChHUAsu/iBPOVaEVsntLBIdpibO0ddy8OzavZz3iL2xVvBZOpolujSliP65Kq0/7KIYw==", - "dev": true, - "funding": [ - { - "type": "GitHub Sponsors", - "url": "https://github.com/sponsors/unifiedjs" - }, - { - "type": "OpenCollective", - "url": "https://opencollective.com/unified" - } - ], - "license": "MIT", - "dependencies": { - "micromark-util-character": "^2.0.0", - "micromark-util-encode": "^2.0.0", - "micromark-util-symbol": "^2.0.0" - } - }, - "node_modules/micromark-util-symbol": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/micromark-util-symbol/-/micromark-util-symbol-2.0.0.tgz", - "integrity": "sha512-8JZt9ElZ5kyTnO94muPxIGS8oyElRJaiJO8EzV6ZSyGQ1Is8xwl4Q45qU5UOg+bGH4AikWziz0iN4sFLWs8PGw==", - "dev": true, - "funding": [ - { - "type": "GitHub Sponsors", - "url": "https://github.com/sponsors/unifiedjs" - }, - { - "type": "OpenCollective", - "url": "https://opencollective.com/unified" - } - ], - "license": "MIT" - }, - "node_modules/micromark-util-types": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/micromark-util-types/-/micromark-util-types-2.0.0.tgz", - "integrity": "sha512-oNh6S2WMHWRZrmutsRmDDfkzKtxF+bc2VxLC9dvtrDIRFln627VsFP6fLMgTryGDljgLPjkrzQSDcPrjPyDJ5w==", - "dev": true, - "funding": [ - { - "type": "GitHub Sponsors", - "url": "https://github.com/sponsors/unifiedjs" - }, - { - "type": "OpenCollective", - "url": "https://opencollective.com/unified" - } - ], - "license": "MIT" - }, "node_modules/micromatch": { "version": "4.0.8", "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.8.tgz", @@ -2777,10 +2794,11 @@ "dev": true, "license": "MIT", "dependencies": { - "mime-db": "1.52.0" + "braces": "^3.0.3", + "picomatch": "^2.3.1" }, "engines": { - "node": ">= 0.6" + "node": ">=8.6" } }, "node_modules/mime-db": { @@ -2875,7 +2893,6 @@ "integrity": "sha512-+MrqnJRtxdF+xngFfUUkIMQrUUL0KsxbADUkn23Z/4ibGg192Q+z+CQyiYwvWTsYjJygmMR8+w3ZDa98Zh6ESg==", "dev": true, "license": "MIT", - "license": "MIT", "engines": { "node": ">=12.0.0" }, @@ -2932,7 +2949,6 @@ "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==", "dev": true, "license": "MIT", - "license": "MIT", "engines": { "node": ">=0.10.0" } @@ -2968,19 +2984,6 @@ "wrappy": "1" } }, - "node_modules/oniguruma-to-js": { - "version": "0.4.3", - "resolved": "https://registry.npmjs.org/oniguruma-to-js/-/oniguruma-to-js-0.4.3.tgz", - "integrity": "sha512-X0jWUcAlxORhOqqBREgPMgnshB7ZGYszBNspP+tS9hPD3l13CdaXcHbgImoHUHlrvGx/7AvFEkTRhAGYh+jzjQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "regex": "^4.3.2" - }, - "funding": { - "url": "https://github.com/sponsors/antfu" - } - }, "node_modules/optionator": { "version": "0.9.4", "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.9.4.tgz", @@ -3103,7 +3106,6 @@ "integrity": "sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==", "dev": true, "license": "MIT", - "license": "MIT", "engines": { "node": ">=8" } @@ -3134,19 +3136,6 @@ "node": ">=12" } }, - "node_modules/plimit-lit": { - "version": "1.6.1", - "resolved": "https://registry.npmjs.org/plimit-lit/-/plimit-lit-1.6.1.tgz", - "integrity": "sha512-B7+VDyb8Tl6oMJT9oSO2CW8XC/T4UcJGrwOVoNGwOQsQYhlpfajmrMj5xeejqaASq3V/EqThyOeATEOMuSEXiA==", - "dev": true, - "license": "MIT", - "dependencies": { - "queue-lit": "^1.5.1" - }, - "engines": { - "node": ">=12" - } - }, "node_modules/prelude-ls": { "version": "1.2.1", "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.2.1.tgz", @@ -3166,17 +3155,6 @@ "node": ">=0.4.0" } }, - "node_modules/property-information": { - "version": "6.5.0", - "resolved": "https://registry.npmjs.org/property-information/-/property-information-6.5.0.tgz", - "integrity": "sha512-PgTgs/BlvHxOu8QuEN7wi5A0OmXaBcHpmCSTehcs6Uuu9IkDIEo13Hy7n898RHfrQ49vKCoGeWZSaAK01nwVig==", - "dev": true, - "license": "MIT", - "funding": { - "type": "github", - "url": "https://github.com/sponsors/wooorm" - } - }, "node_modules/punycode": { "version": "2.3.1", "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.1.tgz", @@ -3187,26 +3165,6 @@ "node": ">=6" } }, - "node_modules/punycode.js": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/punycode.js/-/punycode.js-2.3.1.tgz", - "integrity": "sha512-uxFIHU0YlHYhDQtV4R9J6a52SLx28BCjT+4ieh7IGbgwVJWO+km431c4yRlREUAsAmt/uMjQUyQHNEPf0M39CA==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=6" - } - }, - "node_modules/queue-lit": { - "version": "1.5.2", - "resolved": "https://registry.npmjs.org/queue-lit/-/queue-lit-1.5.2.tgz", - "integrity": "sha512-tLc36IOPeMAubu8BkW8YDBV+WyIgKlYU7zUNs0J5Vk9skSZ4JfGlPOqplP0aHdfv7HL0B2Pg6nwiq60Qc6M2Hw==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=12" - } - }, "node_modules/queue-lit": { "version": "1.5.2", "resolved": "https://registry.npmjs.org/queue-lit/-/queue-lit-1.5.2.tgz", @@ -3258,7 +3216,6 @@ "integrity": "sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==", "dev": true, "license": "MIT", - "license": "MIT", "dependencies": { "picomatch": "^2.2.1" }, @@ -3272,13 +3229,6 @@ "integrity": "sha512-kY1AZVr2Ra+t+piVaJ4gxaFaReZVH40AKNo7UCX6W+dEwBo/2oZJzqfuN1qLq1oL45o56cPaTXELwrTh8Fpggg==", "license": "MIT" }, - "node_modules/regex": { - "version": "4.3.3", - "resolved": "https://registry.npmjs.org/regex/-/regex-4.3.3.tgz", - "integrity": "sha512-r/AadFO7owAq1QJVeZ/nq9jNS1vyZt+6t1p/E59B56Rn2GCya+gr1KSyOzNL/er+r+B7phv5jG2xU2Nz1YkmJg==", - "dev": true, - "license": "MIT" - }, "node_modules/require-directory": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz", @@ -3442,23 +3392,9 @@ "integrity": "sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==", "dev": true, "license": "MIT", - "license": "MIT", "engines": { "node": ">=8" } - }, - } - }, - "node_modules/space-separated-tokens": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/space-separated-tokens/-/space-separated-tokens-2.0.2.tgz", - "integrity": "sha512-PEGlAwrG8yXGXRjW32fGbg66JAlOAwbObuqVoJpv/mRgoWDQfgH1wDPvtzWyUSNAXBGSk8h755YDbbcEy3SH2Q==", - "dev": true, - "license": "MIT", - "funding": { - "type": "github", - "url": "https://github.com/sponsors/wooorm" - } }, "node_modules/sprintf-js": { "version": "1.0.3", @@ -3608,17 +3544,6 @@ "integrity": "sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw==", "license": "MIT" }, - "node_modules/trim-lines": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/trim-lines/-/trim-lines-3.0.1.tgz", - "integrity": "sha512-kRj8B+YHZCc9kQYdWfJB2/oUl9rA99qbowYYBtr4ui4mZyAQ2JpvVBd/6U2YloATfqBhBTSMhTpgBHtU0Mf3Rg==", - "dev": true, - "license": "MIT", - "funding": { - "type": "github", - "url": "https://github.com/sponsors/wooorm" - } - }, "node_modules/ts-api-utils": { "version": "1.3.0", "resolved": "https://registry.npmjs.org/ts-api-utils/-/ts-api-utils-1.3.0.tgz", @@ -3727,62 +3652,12 @@ "node": ">= 0.8.0" } }, - "node_modules/typedoc": { - "version": "0.26.10", - "resolved": "https://registry.npmjs.org/typedoc/-/typedoc-0.26.10.tgz", - "integrity": "sha512-xLmVKJ8S21t+JeuQLNueebEuTVphx6IrP06CdV7+0WVflUSW3SPmR+h1fnWVdAR/FQePEgsSWCUHXqKKjzuUAw==", - "dev": true, - "license": "Apache-2.0", - "dependencies": { - "lunr": "^2.3.9", - "markdown-it": "^14.1.0", - "minimatch": "^9.0.5", - "shiki": "^1.16.2", - "yaml": "^2.5.1" - }, - "bin": { - "typedoc": "bin/typedoc" - }, - "engines": { - "node": ">= 18" - }, - "peerDependencies": { - "typescript": "4.6.x || 4.7.x || 4.8.x || 4.9.x || 5.0.x || 5.1.x || 5.2.x || 5.3.x || 5.4.x || 5.5.x || 5.6.x" - } - }, - "node_modules/typedoc/node_modules/brace-expansion": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", - "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", - "dev": true, - "license": "MIT", - "dependencies": { - "balanced-match": "^1.0.0" - } - }, - "node_modules/typedoc/node_modules/minimatch": { - "version": "9.0.5", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.5.tgz", - "integrity": "sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow==", - "dev": true, - "license": "ISC", - "dependencies": { - "brace-expansion": "^2.0.1" - }, - "engines": { - "node": ">=16 || 14 >=14.17" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, "node_modules/typescript": { "version": "5.6.3", "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.6.3.tgz", "integrity": "sha512-hjcS1mhfuyi4WW8IWtjP7brDrG2cuDZukyrYrSauoXGNgx0S7zceP07adYkJycEr56BOUTNPzbInooiN3fn1qw==", "dev": true, "license": "Apache-2.0", - "license": "Apache-2.0", "bin": { "tsc": "bin/tsc", "tsserver": "bin/tsserver" @@ -3844,36 +3719,6 @@ "dev": true, "license": "MIT" }, - "node_modules/vfile": { - "version": "6.0.3", - "resolved": "https://registry.npmjs.org/vfile/-/vfile-6.0.3.tgz", - "integrity": "sha512-KzIbH/9tXat2u30jf+smMwFCsno4wHVdNmzFyL+T/L3UGqqk6JKfVqOFOZEpZSHADH1k40ab6NUIXZq422ov3Q==", - "dev": true, - "license": "MIT", - "dependencies": { - "@types/unist": "^3.0.0", - "vfile-message": "^4.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, - "node_modules/vfile-message": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/vfile-message/-/vfile-message-4.0.2.tgz", - "integrity": "sha512-jRDZ1IMLttGj41KcZvlrYAaI3CfqpLpfpf+Mfig13viT6NKvRzWZ+lXz0Y5D60w6uJIBAOGq9mSHf0gktF0duw==", - "dev": true, - "license": "MIT", - "dependencies": { - "@types/unist": "^3.0.0", - "unist-util-stringify-position": "^4.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, "node_modules/webidl-conversions": { "version": "3.0.1", "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-3.0.1.tgz", @@ -4050,19 +3895,6 @@ "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", "license": "ISC" }, - "node_modules/yaml": { - "version": "2.6.0", - "resolved": "https://registry.npmjs.org/yaml/-/yaml-2.6.0.tgz", - "integrity": "sha512-a6ae//JvKDEra2kdi1qzCyrJW/WZCgFi8ydDV+eXExl95t+5R+ijnqHJbz9tmMh8FUjx3iv2fCQ4dclAQlO2UQ==", - "dev": true, - "license": "ISC", - "bin": { - "yaml": "bin.mjs" - }, - "engines": { - "node": ">= 14" - } - }, "node_modules/yargs": { "version": "16.2.0", "resolved": "https://registry.npmjs.org/yargs/-/yargs-16.2.0.tgz", From 1204bb28bce28c899543b6b167a5ca04526983f1 Mon Sep 17 00:00:00 2001 From: Austin Fraser Date: Wed, 23 Oct 2024 19:44:54 -0700 Subject: [PATCH 210/357] completed iframe players in DemoCard.tsx --- mlflow-site/package.json | 9 ++--- mlflow-site/src/app/components/Demo.tsx | 5 +++ mlflow-site/src/app/components/DemoCard.tsx | 38 ++++++++++++--------- 3 files changed, 31 insertions(+), 21 deletions(-) diff --git a/mlflow-site/package.json b/mlflow-site/package.json index ae9b78d7..2b2f5cfb 100644 --- a/mlflow-site/package.json +++ b/mlflow-site/package.json @@ -9,18 +9,19 @@ "lint": "next lint" }, "dependencies": { + "next": "14.2.15", "react": "^18", "react-dom": "^18", - "next": "14.2.15" + "react-player": "^2.16.0" }, "devDependencies": { - "typescript": "^5", "@types/node": "^20", "@types/react": "^18", "@types/react-dom": "^18", + "eslint": "^8", + "eslint-config-next": "14.2.15", "postcss": "^8", "tailwindcss": "^3.4.1", - "eslint": "^8", - "eslint-config-next": "14.2.15" + "typescript": "^5" } } diff --git a/mlflow-site/src/app/components/Demo.tsx b/mlflow-site/src/app/components/Demo.tsx index 83b4d0a2..11e5cd82 100644 --- a/mlflow-site/src/app/components/Demo.tsx +++ b/mlflow-site/src/app/components/Demo.tsx @@ -12,12 +12,17 @@ const Demo = () => { 'Description for what\'s happening in Demo 2. This block of text will contain all the info needed to understand the demo.', 'Description for what\'s happening in Demo 3. This block of text will contain all the info needed to understand the demo.' ]; + const demoCardVideos = [ + "https://player.vimeo.com/video/1022732764", + "https://player.vimeo.com/video/1022732772", + ]; for (let i = 0; i < 3; i++) { demos.push( ); } diff --git a/mlflow-site/src/app/components/DemoCard.tsx b/mlflow-site/src/app/components/DemoCard.tsx index b2a34307..572c907d 100644 --- a/mlflow-site/src/app/components/DemoCard.tsx +++ b/mlflow-site/src/app/components/DemoCard.tsx @@ -1,29 +1,33 @@ -import Image from 'next/image'; - const DemoCard = ({ header, blurb, + video }: { key: string; blurb: string; header: string; + video: string; }) => { return ( -
- -
-
{header}
-
{blurb}
+
+
+