From 9422e1aef5bcacda6d02956c7967e80f24b1f8b9 Mon Sep 17 00:00:00 2001 From: Daniil Kirichenko Date: Thu, 29 Jun 2023 13:16:46 +0300 Subject: [PATCH 01/57] [v0.1.0-beta.1] Initial commit --- .eslintrc.cjs | 131 +++++++++++++++++++++++++++++++++++++ .gitignore | 4 ++ README.md | 2 +- package.json | 48 ++++++++++++++ src/api-errors.js | 80 ++++++++++++++++++++++ src/driver.js | 14 ++++ src/error.js | 30 +++++++++ src/main.js | 73 +++++++++++++++++++++ src/request.js | 64 ++++++++++++++++++ src/response.js | 66 +++++++++++++++++++ test/api/echo.js | 6 ++ test/api/error.api.js | 8 +++ test/api/error.internal.js | 6 ++ test/main.js | 21 ++++++ 14 files changed, 552 insertions(+), 1 deletion(-) create mode 100644 .eslintrc.cjs create mode 100644 .gitignore create mode 100644 package.json create mode 100644 src/api-errors.js create mode 100644 src/driver.js create mode 100644 src/error.js create mode 100644 src/main.js create mode 100644 src/request.js create mode 100644 src/response.js create mode 100644 test/api/echo.js create mode 100644 test/api/error.api.js create mode 100644 test/api/error.internal.js create mode 100644 test/main.js diff --git a/.eslintrc.cjs b/.eslintrc.cjs new file mode 100644 index 0000000..d3bc01f --- /dev/null +++ b/.eslintrc.cjs @@ -0,0 +1,131 @@ + +module.exports = { + root: true, + parser: '@babel/eslint-parser', + parserOptions: { + ecmaVersion: 2022, + sourceType: 'module', + requireConfigFile: false, + }, + env: { + es2022: true, + node: true, + }, + extends: [ + 'eslint:recommended', + 'xo', + 'plugin:import/recommended', + 'plugin:promise/recommended', + 'plugin:unicorn/recommended', + 'plugin:node/recommended', + ], + plugins: [ + 'import', + 'promise', + 'unicorn', + 'node', + ], + rules: { + 'array-bracket-spacing': [ + 'error', + 'always', + { + arraysInArrays: false, + objectsInArrays: false, + }, + ], + 'arrow-parens': [ + 'warn', + 'always', + ], + 'brace-style': [ + 'error', + 'stroustrup', + ], + 'camelcase': 'off', + 'capitalized-comments': 'off', + 'import/extensions': [ + 'error', + 'always', + ], + 'indent': [ + 'error', + 'tab', + { + ImportDeclaration: 'off', + SwitchCase: 1, + }, + ], + 'new-cap': [ + 'error', + { + newIsCap: true, + capIsNew: true, + properties: false, + }, + ], + 'no-multi-spaces': [ + 'error', + { + exceptions: { + Property: true, + ImportDeclaration: true, + }, + }, + ], + 'no-promise-executor-return': 'off', + 'no-unused-vars': 'warn', + 'object-curly-spacing': [ + 'warn', + 'always', + { + arraysInObjects: true, + objectsInObjects: true, + }, + ], + 'padding-line-between-statements': [ + 'error', + { + blankLine: 'never', + prev: 'case', + next: 'break', + }, + ], + 'quote-props': [ + 'error', + 'consistent-as-needed', + { + numbers: true, + }, + ], + 'quotes': [ + 'error', + 'single', + ], + 'unicorn/no-null': 'off', + 'unicorn/numeric-separators-style': [ + 'warn', + { + onlyIfContainsSeparator: true, + }, + ], + 'unicorn/prefer-ternary': [ + 'error', + 'only-single-line', + ], + 'unicorn/prevent-abbreviations': [ + 'error', + { + allowList: { + args: true, + env: true, + }, + }, + ], + 'unicorn/switch-case-braces': [ + 'warn', + 'avoid', + ], + 'node/no-unsupported-features/es-syntax': 'off', + }, +}; diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..74446f4 --- /dev/null +++ b/.gitignore @@ -0,0 +1,4 @@ + +.DS_Store +node_modules +pnpm-lock.yaml diff --git a/README.md b/README.md index 4c56471..d1ade38 100644 --- a/README.md +++ b/README.md @@ -1 +1 @@ -# core \ No newline at end of file +# @hyperapi/core diff --git a/package.json b/package.json new file mode 100644 index 0000000..82ffda3 --- /dev/null +++ b/package.json @@ -0,0 +1,48 @@ +{ + "name": "@hyperapi/core", + "version": "0.1.0-beta.1", + "description": "This package is a core for HyperAPI project.", + "publishConfig": { + "access": "public", + "tag": "beta" + }, + "type": "module", + "main": "src/main.js", + "exports": { + ".": "./src/main.js", + "./api-errors": "./src/api-errors.js", + "./driver": "./src/driver.js", + "./error": "./src/error.js", + "./request": "./src/request.js", + "./response": "./src/response.js" + }, + "peerDependencies": { + "oh-my-props": ">= 3.0.0-beta.10" + }, + "devDependencies": { + "@babel/eslint-parser": "7.21.8", + "eslint": "8.41.0", + "eslint-config-xo": "0.43.1", + "eslint-plugin-import": "2.27.5", + "eslint-plugin-node": "11.1.0", + "eslint-plugin-promise": "6.1.1", + "eslint-plugin-unicorn": "47.0.0" + }, + "engines": { + "node": ">=10.0.0" + }, + "repository": { + "type": "git", + "url": "git+https://github.com/hyperapi/core.git" + }, + "keywords": [ + "hyperapi", + "api" + ], + "author": "Daniil Kirichenko (https://twitter.com/kirickme)", + "license": "MIT", + "bugs": { + "url": "https://github.com/hyperapi/core/issues" + }, + "homepage": "https://github.com/hyperapi/core#readme" +} \ No newline at end of file diff --git a/src/api-errors.js b/src/api-errors.js new file mode 100644 index 0000000..f6706ee --- /dev/null +++ b/src/api-errors.js @@ -0,0 +1,80 @@ + +import HyperAPIError from './error.js'; + +export class HyperAPIAuthorizationError extends HyperAPIError { + code = 1; + description = 'Authorization error'; + httpStatus = 401; +} + +export class HyperAPIInvalidParametersError extends HyperAPIError { + code = 2; + description = 'One of the parameters specified was missing or invalid'; + httpStatus = 400; +} + +export class HyperAPIInternalError extends HyperAPIError { + code = 3; + description = 'Internal error'; + httpStatus = 500; +} + +export class HyperAPIForbiddenError extends HyperAPIError { + code = 4; + description = 'You do not have permission to perform this action'; + httpStatus = 403; +} + +export class HyperAPIUnknownMethodError extends HyperAPIError { + code = 5; + description = 'Unknown method called'; + httpStatus = 404; +} + +export class HyperAPIObjectsLimitError extends HyperAPIError { + code = 6; + description = 'Too many objects requested'; + httpStatus = 400; +} + +export class HyperAPIRateLimitError extends HyperAPIError { + code = 7; + description = 'Rate limit exceeded'; + httpStatus = 429; +} + +export class HyperAPICaptchaError extends HyperAPIError { + code = 8; + description = 'Captcha required'; + httpStatus = 400; +} + +export class HyperAPIBusyError extends HyperAPIError { + code = 10; + description = 'Endpoint is busy'; + httpStatus = 503; +} + +export class HyperAPIConfirmationError extends HyperAPIError { + code = 11; + description = 'Confirmation required'; + httpStatus = 400; +} + +export class HyperAPIOTPError extends HyperAPIError { + code = 12; + description = 'One-time password required'; + httpStatus = 400; +} + +export class HyperAPIMaintenanceError extends HyperAPIError { + code = 98; + description = 'Endpoint is in maintenance mode'; + httpStatus = 503; +} + +export class HyperAPIUnknownError extends HyperAPIError { + code = 99; + description = 'Unknown error'; + httpStatus = 500; +} diff --git a/src/driver.js b/src/driver.js new file mode 100644 index 0000000..a8807ab --- /dev/null +++ b/src/driver.js @@ -0,0 +1,14 @@ + +import HyperAPIRequest from './request.js'; + +export default class HyperAPIDriver extends EventTarget { + /* async */ onRequest(request) { + if (request instanceof HyperAPIRequest !== true) { + throw new TypeError('Argument 0 must be an instance of HyperAPIRequest.'); + } + + this.dispatchEvent(request); + + return request.wait(); + } +} diff --git a/src/error.js b/src/error.js new file mode 100644 index 0000000..11c84e4 --- /dev/null +++ b/src/error.js @@ -0,0 +1,30 @@ + +export default class HyperAPIError extends Error { + #data; + + constructor(data) { + super(); + + this.#data = data; + } + + get message() { + return `${this.description} (code ${this.code})`; + } + + getResponse() { + const response = { + code: this.code, + }; + + if (typeof this.description === 'string') { + response.description = this.description; + } + + if (this.#data) { + response.data = this.#data; + } + + return response; + } +} diff --git a/src/main.js b/src/main.js new file mode 100644 index 0000000..f3c3d4d --- /dev/null +++ b/src/main.js @@ -0,0 +1,73 @@ + +import { join as joinPath } from 'node:path'; + +import { HyperAPIUnknownError } from './api-errors.js'; +import HyperAPIDriver from './driver.js'; +import HyperAPIError from './error.js'; +import HyperAPIResponse from './response.js'; + +export default class HyperAPI { + // #driver; + #root; + // #middleware; + #turnDriverOff; + + constructor({ + driver, + root = joinPath(process.cwd(), 'hyper-api'), + // middleware = [], + }) { + if (driver instanceof HyperAPIDriver !== true) { + throw new TypeError('Property "driver" must be an instance of HyperAPIDriver.'); + } + // this.#driver = driver; + + this.#root = root; + // this.#middleware = middleware; + + const handler = (request) => { + this.#handler(request) + .then((response) => request.respondWith(response)) + .catch(() => {}); // #handler never throws + }; + + driver.addEventListener( + 'HyperAPIRequest', + handler, + ); + + this.#turnDriverOff = () => { + driver.removeEventListener( + 'HyperAPIRequest', + handler, + ); + }; + } + + async #handler(request) { + try { + try { + const module = await request._getModule(this.#root); + + return new HyperAPIResponse( + await module.default(request), + ); + } + catch (error) { + if (error instanceof HyperAPIError !== true) { + console.error(error); + throw new HyperAPIUnknownError(); + } + + throw error; + } + } + catch (error) { + return new HyperAPIResponse(error); + } + } + + destroy() { + this.#turnDriverOff(); + } +} diff --git a/src/request.js b/src/request.js new file mode 100644 index 0000000..0076deb --- /dev/null +++ b/src/request.js @@ -0,0 +1,64 @@ + +import { join as joinPath } from 'node:path'; + +import { HyperAPIUnknownMethodError } from './api-errors.js'; + +export default class HyperAPIRequest extends Event { + #data = {}; + + constructor(method, args) { + super('HyperAPIRequest'); + + this.method = method; + this.args = args; + this.flags = {}; + } + + get(key) { + return this.#data[key]; + } + + set(key, value) { + this.#data[key] = value; + } + + get data() { + return Object.freeze(this.#data); + } + + async _getModule(root) { + const filenames = [ + this.method, + `${this.method}.js`, + joinPath(this.method, 'index.js'), + ]; + + for (const filename of filenames) { + try { + // eslint-disable-next-line no-await-in-loop + return await import( + joinPath( + root, + filename, + ) + ); + } + catch {} + } + + throw new HyperAPIUnknownMethodError(); + } + + #resolve; + #promise = new Promise((resolve) => { + this.#resolve = resolve; + }); + + wait() { + return this.#promise; + } + + respondWith(response) { + this.#resolve(response); + } +} diff --git a/src/response.js b/src/response.js new file mode 100644 index 0000000..796d688 --- /dev/null +++ b/src/response.js @@ -0,0 +1,66 @@ + +import HyperAPIError from './error.js'; + +export default class HyperAPIResponse { + constructor(value) { + if (value instanceof HyperAPIError) { + this.error = value; + } + else if ( + (value !== null && typeof value === 'object') // object + || Array.isArray(value) // array + || typeof value === 'string' // string + || typeof value === 'number' // number + || typeof value === 'boolean' // boolean + ) { + this.data = value; + } + else { + throw new TypeError('Argument 0 must be an instance of HyperAPIError or a valid response value.'); + } + } + + object() { + const data = { + code: this.error?.code ?? 0, + }; + + if (this.error && typeof this.error.description === 'string') { + data.description = this.error.description; + } + + if (this.data !== undefined) { + data.data = this.data; + } + + return data; + } + + array() { + const result = [ + this.error?.code ?? 0, + ]; + + if (this.error) { + result.push(this.error.description ?? ''); + } + + if (this.data !== undefined) { + result.push(this.data); + } + + return result; + } + + json() { + return JSON.stringify( + this.object(), + ); + } + + compactJSON() { + return JSON.stringify( + this.array(), + ); + } +} diff --git a/test/api/echo.js b/test/api/echo.js new file mode 100644 index 0000000..041828c --- /dev/null +++ b/test/api/echo.js @@ -0,0 +1,6 @@ + +export default function (request) { + console.log(request); + + return `Hello, ${request.args.name}!`; +} diff --git a/test/api/error.api.js b/test/api/error.api.js new file mode 100644 index 0000000..2ddc294 --- /dev/null +++ b/test/api/error.api.js @@ -0,0 +1,8 @@ + +import { HyperAPIBusyError } from '../../src/api-errors.js'; + +export default function (request) { + console.log(request); + + throw new HyperAPIBusyError(); +} diff --git a/test/api/error.internal.js b/test/api/error.internal.js new file mode 100644 index 0000000..d975703 --- /dev/null +++ b/test/api/error.internal.js @@ -0,0 +1,6 @@ + +export default function (request) { + console.log(request); + + throw new TypeError('Invalid something given.'); +} diff --git a/test/main.js b/test/main.js new file mode 100644 index 0000000..0f1d778 --- /dev/null +++ b/test/main.js @@ -0,0 +1,21 @@ + +import HyperAPIDriver from '../src/driver.js'; +import HyperAPI from '../src/main.js'; +import HyperAPIRequest from '../src/request.js'; + +const driver = new HyperAPIDriver(); +const api = new HyperAPI({ + driver, + root: new URL('api', import.meta.url).pathname, +}); + +const response = await driver.onRequest( + new HyperAPIRequest( + process.argv[2], + { + name: 'world', + }, + ), +); +console.log('response =', response); +console.log('response =', response.array()); From 7c9cf28474247740706815842ecde08e9f46e678 Mon Sep 17 00:00:00 2001 From: Daniil Kirichenko Date: Sat, 1 Jul 2023 23:07:54 +0300 Subject: [PATCH 02/57] [v0.1.0-beta.2] Tests & OhMyProps version bump --- .eslintrc.cjs | 2 + package.json | 12 +++-- src/main.js | 42 ++++++++++++---- test/api/echo.js | 11 ++++- test/api/error.api.js | 4 +- test/api/error.internal.js | 4 +- test/main.js | 98 ++++++++++++++++++++++++++++++++++---- 7 files changed, 141 insertions(+), 32 deletions(-) diff --git a/.eslintrc.cjs b/.eslintrc.cjs index d3bc01f..8ca1c1a 100644 --- a/.eslintrc.cjs +++ b/.eslintrc.cjs @@ -9,6 +9,7 @@ module.exports = { }, env: { es2022: true, + browser: true, node: true, }, extends: [ @@ -75,6 +76,7 @@ module.exports = { ], 'no-promise-executor-return': 'off', 'no-unused-vars': 'warn', + 'node/no-unpublished-import': 'off', 'object-curly-spacing': [ 'warn', 'always', diff --git a/package.json b/package.json index 82ffda3..9bd2738 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@hyperapi/core", - "version": "0.1.0-beta.1", + "version": "0.1.0-beta.2", "description": "This package is a core for HyperAPI project.", "publishConfig": { "access": "public", @@ -17,7 +17,7 @@ "./response": "./src/response.js" }, "peerDependencies": { - "oh-my-props": ">= 3.0.0-beta.10" + "oh-my-props": ">= 3.0.0-beta.20" }, "devDependencies": { "@babel/eslint-parser": "7.21.8", @@ -26,11 +26,15 @@ "eslint-plugin-import": "2.27.5", "eslint-plugin-node": "11.1.0", "eslint-plugin-promise": "6.1.1", - "eslint-plugin-unicorn": "47.0.0" + "eslint-plugin-unicorn": "47.0.0", + "mocha": "^10.2.0" }, "engines": { "node": ">=10.0.0" }, + "scripts": { + "test": "mocha" + }, "repository": { "type": "git", "url": "git+https://github.com/hyperapi/core.git" @@ -45,4 +49,4 @@ "url": "https://github.com/hyperapi/core/issues" }, "homepage": "https://github.com/hyperapi/core#readme" -} \ No newline at end of file +} diff --git a/src/main.js b/src/main.js index f3c3d4d..0d3614d 100644 --- a/src/main.js +++ b/src/main.js @@ -1,10 +1,15 @@ import { join as joinPath } from 'node:path'; -import { HyperAPIUnknownError } from './api-errors.js'; -import HyperAPIDriver from './driver.js'; -import HyperAPIError from './error.js'; -import HyperAPIResponse from './response.js'; +import { + HyperAPIInternalError, + HyperAPIInvalidParametersError } from './api-errors.js'; +import HyperAPIDriver from './driver.js'; +import HyperAPIError from './error.js'; +import HyperAPIResponse from './response.js'; +import { + OhMyPropsType, + OhMyPropsValueError } from 'oh-my-props'; export default class HyperAPI { // #driver; @@ -47,16 +52,12 @@ export default class HyperAPI { async #handler(request) { try { try { - const module = await request._getModule(this.#root); - - return new HyperAPIResponse( - await module.default(request), - ); + return await this.#useModule(request); } catch (error) { if (error instanceof HyperAPIError !== true) { console.error(error); - throw new HyperAPIUnknownError(); + throw new HyperAPIInternalError(); } throw error; @@ -67,6 +68,27 @@ export default class HyperAPI { } } + async #useModule(request) { + const module = await request._getModule(this.#root); + + if (module.args instanceof OhMyPropsType) { + try { + request.args = module.args.cast(request.args); + } + catch (error) { + if (error instanceof OhMyPropsValueError) { + throw new HyperAPIInvalidParametersError(); + } + + throw error; + } + } + + return new HyperAPIResponse( + await module.default(request), + ); + } + destroy() { this.#turnDriverOff(); } diff --git a/test/api/echo.js b/test/api/echo.js index 041828c..9acf92f 100644 --- a/test/api/echo.js +++ b/test/api/echo.js @@ -1,6 +1,13 @@ -export default function (request) { - console.log(request); +import { OhMyPropsObjectValidator } from 'oh-my-props'; +export default function (request) { return `Hello, ${request.args.name}!`; } + +export const args = new OhMyPropsObjectValidator({ + name: { + type: String, + required: true, + }, +}); diff --git a/test/api/error.api.js b/test/api/error.api.js index 2ddc294..940a3d8 100644 --- a/test/api/error.api.js +++ b/test/api/error.api.js @@ -1,8 +1,6 @@ import { HyperAPIBusyError } from '../../src/api-errors.js'; -export default function (request) { - console.log(request); - +export default function () { throw new HyperAPIBusyError(); } diff --git a/test/api/error.internal.js b/test/api/error.internal.js index d975703..6d240a5 100644 --- a/test/api/error.internal.js +++ b/test/api/error.internal.js @@ -1,6 +1,4 @@ -export default function (request) { - console.log(request); - +export default function () { throw new TypeError('Invalid something given.'); } diff --git a/test/main.js b/test/main.js index 0f1d778..cfb6e63 100644 --- a/test/main.js +++ b/test/main.js @@ -1,4 +1,10 @@ +import { + strictEqual, + notStrictEqual, + deepStrictEqual } from 'node:assert/strict'; +import { describe, it } from 'mocha'; + import HyperAPIDriver from '../src/driver.js'; import HyperAPI from '../src/main.js'; import HyperAPIRequest from '../src/request.js'; @@ -9,13 +15,85 @@ const api = new HyperAPI({ root: new URL('api', import.meta.url).pathname, }); -const response = await driver.onRequest( - new HyperAPIRequest( - process.argv[2], - { - name: 'world', - }, - ), -); -console.log('response =', response); -console.log('response =', response.array()); +async function request(method, args = {}) { + const response = await driver.onRequest( + new HyperAPIRequest( + method, + args, + ), + ); + + return response.array(); +} + +describe('HyperAPI', () => { + it('correct request', async () => { + deepStrictEqual( + await request( + 'echo', + { + name: 'world', + }, + ), + [ + 0, + 'Hello, world!', + ], + ); + }); + + it('invalid arguments', async () => { + deepStrictEqual( + await request( + 'echo', + { + name: 123, + }, + ), + [ + 2, + 'One of the parameters specified was missing or invalid', + ], + ); + }); + + it('missing arguments', async () => { + deepStrictEqual( + await request('echo'), + [ + 2, + 'One of the parameters specified was missing or invalid', + ], + ); + }); + + it('api error', async () => { + deepStrictEqual( + await request('error.api'), + [ + 10, + 'Endpoint is busy', + ], + ); + }); + + it('internal error', async () => { + deepStrictEqual( + await request('error.internal'), + [ + 3, + 'Internal error', + ], + ); + }); + + it('unknown method', async () => { + deepStrictEqual( + await request('error.unknown-method'), + [ + 5, + 'Unknown method called', + ], + ); + }); +}); From ef72deebb4e46a7d9b10601c6e27c068c5500361 Mon Sep 17 00:00:00 2001 From: Daniil Kirichenko Date: Sun, 2 Jul 2023 14:50:16 +0300 Subject: [PATCH 03/57] [v0.1.0-beta.2] Syntax fix --- test/main.js | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/test/main.js b/test/main.js index cfb6e63..28eba0c 100644 --- a/test/main.js +++ b/test/main.js @@ -1,9 +1,8 @@ +import { deepStrictEqual } from 'node:assert/strict'; import { - strictEqual, - notStrictEqual, - deepStrictEqual } from 'node:assert/strict'; -import { describe, it } from 'mocha'; + describe, + it } from 'mocha'; import HyperAPIDriver from '../src/driver.js'; import HyperAPI from '../src/main.js'; From 6eb268e5e4ad5eb04148ee134293640b0abae1bc Mon Sep 17 00:00:00 2001 From: Daniil Kirichenko Date: Wed, 30 Aug 2023 20:01:06 +0300 Subject: [PATCH 04/57] [v0.1.0-beta.3] Added JSDoc ~ changed API response format --- .eslintrc.cjs | 2 ++ package.json | 3 +- src/api-errors.js | 32 +++++++---------- src/driver.js | 12 ++++++- src/error.js | 61 ++++++++++++++++++++++++++------- src/main.js | 70 +++++++++++++++++++++++--------------- src/request.js | 46 ++++++++++++++++++------- src/response.js | 59 ++++++++++---------------------- test/api/echo.js | 5 ++- test/api/error.api.js | 1 + test/api/error.internal.js | 1 + test/main.js | 50 +++++++++++++-------------- 12 files changed, 202 insertions(+), 140 deletions(-) diff --git a/.eslintrc.cjs b/.eslintrc.cjs index 8ca1c1a..f933123 100644 --- a/.eslintrc.cjs +++ b/.eslintrc.cjs @@ -16,12 +16,14 @@ module.exports = { 'eslint:recommended', 'xo', 'plugin:import/recommended', + 'plugin:jsdoc/recommended', 'plugin:promise/recommended', 'plugin:unicorn/recommended', 'plugin:node/recommended', ], plugins: [ 'import', + 'jsdoc', 'promise', 'unicorn', 'node', diff --git a/package.json b/package.json index 9bd2738..983c5c2 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@hyperapi/core", - "version": "0.1.0-beta.2", + "version": "0.1.0-beta.3", "description": "This package is a core for HyperAPI project.", "publishConfig": { "access": "public", @@ -24,6 +24,7 @@ "eslint": "8.41.0", "eslint-config-xo": "0.43.1", "eslint-plugin-import": "2.27.5", + "eslint-plugin-jsdoc": "46.5.0", "eslint-plugin-node": "11.1.0", "eslint-plugin-promise": "6.1.1", "eslint-plugin-unicorn": "47.0.0", diff --git a/src/api-errors.js b/src/api-errors.js index f6706ee..e0b407e 100644 --- a/src/api-errors.js +++ b/src/api-errors.js @@ -4,77 +4,71 @@ import HyperAPIError from './error.js'; export class HyperAPIAuthorizationError extends HyperAPIError { code = 1; description = 'Authorization error'; - httpStatus = 401; + httpStatus = 401; // Unauthorized } export class HyperAPIInvalidParametersError extends HyperAPIError { code = 2; description = 'One of the parameters specified was missing or invalid'; - httpStatus = 400; + httpStatus = 400; // Bad Request } export class HyperAPIInternalError extends HyperAPIError { code = 3; description = 'Internal error'; - httpStatus = 500; + httpStatus = 500; // Internal Server Error } export class HyperAPIForbiddenError extends HyperAPIError { code = 4; description = 'You do not have permission to perform this action'; - httpStatus = 403; + httpStatus = 403; // Forbidden } export class HyperAPIUnknownMethodError extends HyperAPIError { code = 5; description = 'Unknown method called'; - httpStatus = 404; + httpStatus = 404; // Not Found } export class HyperAPIObjectsLimitError extends HyperAPIError { code = 6; description = 'Too many objects requested'; - httpStatus = 400; + httpStatus = 400; // Bad Request } export class HyperAPIRateLimitError extends HyperAPIError { code = 7; description = 'Rate limit exceeded'; - httpStatus = 429; + httpStatus = 429; // Too Many Requests } export class HyperAPICaptchaError extends HyperAPIError { code = 8; description = 'Captcha required'; - httpStatus = 400; + httpStatus = 428; // Precondition Required } export class HyperAPIBusyError extends HyperAPIError { code = 10; description = 'Endpoint is busy'; - httpStatus = 503; + httpStatus = 503; // Service Unavailable } export class HyperAPIConfirmationError extends HyperAPIError { code = 11; description = 'Confirmation required'; - httpStatus = 400; + httpStatus = 409; // Conflict } export class HyperAPIOTPError extends HyperAPIError { code = 12; description = 'One-time password required'; - httpStatus = 400; + httpStatus = 401; // Unauthorized } export class HyperAPIMaintenanceError extends HyperAPIError { - code = 98; + code = 13; description = 'Endpoint is in maintenance mode'; - httpStatus = 503; -} - -export class HyperAPIUnknownError extends HyperAPIError { - code = 99; - description = 'Unknown error'; - httpStatus = 500; + httpStatus = 503; // Service Unavailable } diff --git a/src/driver.js b/src/driver.js index a8807ab..feee26f 100644 --- a/src/driver.js +++ b/src/driver.js @@ -1,8 +1,18 @@ import HyperAPIRequest from './request.js'; +/** + * @typedef {import('./response.js').default} HyperAPIResponse + */ + export default class HyperAPIDriver extends EventTarget { - /* async */ onRequest(request) { + /** + * Processes a request and waits for the response. + * @async + * @param {HyperAPIRequest} request The HyperAPI request. + * @returns {Promise} The HyperAPI response. + */ + onRequest(request) { if (request instanceof HyperAPIRequest !== true) { throw new TypeError('Argument 0 must be an instance of HyperAPIRequest.'); } diff --git a/src/error.js b/src/error.js index 11c84e4..7e9cb59 100644 --- a/src/error.js +++ b/src/error.js @@ -1,30 +1,67 @@ export default class HyperAPIError extends Error { - #data; + /** + * The error code. + * @type {number} + * @readonly + */ + code; - constructor(data) { + /** + * The error description. + * @type {string?} + * @readonly + */ + description = null; + + /** + * The error data. + * @type {{[key: string]: *}?} + * @readonly + */ + data = null; + + /** + * @param {{[key: string]: *}?} data The error data. Cannot contain "code" or "description" properties. + */ + constructor(data = null) { super(); - this.#data = data; + if ( + data !== null + && typeof data !== 'object' + ) { + throw new TypeError('Argument 0 must be an object or not be provided'); + } + + if ( + data + && ( + 'code' in data + || 'description' in data + ) + ) { + throw new TypeError('Argument 0 must not contain "code" or "description" properties'); + } + + this.data = data; } get message() { - return `${this.description} (code ${this.code})`; + return `${this.description ?? ''} (code ${this.code})`; } getResponse() { - const response = { + const result = { code: this.code, }; - if (typeof this.description === 'string') { - response.description = this.description; + result.description = this.description; } - if (this.#data) { - response.data = this.#data; - } - - return response; + return { + ...result, + ...this.data, + }; } } diff --git a/src/main.js b/src/main.js index 0d3614d..4286c07 100644 --- a/src/main.js +++ b/src/main.js @@ -12,59 +12,68 @@ import { OhMyPropsValueError } from 'oh-my-props'; export default class HyperAPI { - // #driver; + #driver; #root; - // #middleware; #turnDriverOff; + /** + * Creates a HyperAPI instance. + * @param {object} options The options. + * @param {HyperAPIDriver} options.driver The HyperAPI driver. + * @param {string=} options.root The root directory for API methods modules. Defaults to "/hyper-api" inside the current working directory. + */ constructor({ driver, - root = joinPath(process.cwd(), 'hyper-api'), - // middleware = [], + root = joinPath( + process.cwd(), + 'hyper-api', + ), }) { if (driver instanceof HyperAPIDriver !== true) { throw new TypeError('Property "driver" must be an instance of HyperAPIDriver.'); } - // this.#driver = driver; + this.#driver = driver; this.#root = root; - // this.#middleware = middleware; + this.#setUpListener(); + } + + #setUpListener() { const handler = (request) => { - this.#handler(request) - .then((response) => request.respondWith(response)) - .catch(() => {}); // #handler never throws + this.#handleRequest(request) + .then((response) => request._respondWith( + new HyperAPIResponse(response), + )) + .catch(() => {}); // never throws }; - driver.addEventListener( + this.#driver.addEventListener( 'HyperAPIRequest', handler, ); this.#turnDriverOff = () => { - driver.removeEventListener( + this.#driver.removeEventListener( 'HyperAPIRequest', handler, ); }; } - async #handler(request) { + async #handleRequest(request) { try { - try { - return await this.#useModule(request); - } - catch (error) { - if (error instanceof HyperAPIError !== true) { - console.error(error); - throw new HyperAPIInternalError(); - } - - throw error; - } + return await this.#useModule(request); } catch (error) { - return new HyperAPIResponse(error); + // error must be an instance of HyperAPIError + if (error instanceof HyperAPIError !== true) { + console.error(error); + // eslint-disable-next-line no-ex-assign + error = new HyperAPIInternalError(); + } + + return error; } } @@ -84,12 +93,19 @@ export default class HyperAPI { } } - return new HyperAPIResponse( - await module.default(request), - ); + return module.default(request); } + /** + * Destroys the HyperAPI instance. + */ destroy() { this.#turnDriverOff(); } } + +export * from './api-errors.js'; +export { default as HyperAPIDriver } from './driver.js'; +export { default as HyperAPIError } from './error.js'; +export { default as HyperAPIRequest } from './request.js'; +export { default as HyperAPIResponse } from './response.js'; diff --git a/src/request.js b/src/request.js index 0076deb..00004b3 100644 --- a/src/request.js +++ b/src/request.js @@ -3,34 +3,48 @@ import { join as joinPath } from 'node:path'; import { HyperAPIUnknownMethodError } from './api-errors.js'; +/** + * @typedef {import('./response.js').default} HyperAPIResponse + */ + export default class HyperAPIRequest extends Event { - #data = {}; + #data = new Map(); - constructor(method, args) { + /** + * @param {string} module_path The relative path to the API method module. + * @param {Array<*>} args The arguments to pass to the API method. + */ + constructor(module_path, args) { super('HyperAPIRequest'); - this.method = method; + this.module_path = module_path; this.args = args; this.flags = {}; } + /** + * @param {*} key The key to get. + * @returns {*} The value. + */ get(key) { - return this.#data[key]; + return this.#data.get(key); } + /** + * @param {*} key The key to set. + * @param {*} value The value to set. + */ set(key, value) { - this.#data[key] = value; - } - - get data() { - return Object.freeze(this.#data); + this.#data.set(key, value); } async _getModule(root) { const filenames = [ - this.method, - `${this.method}.js`, - joinPath(this.method, 'index.js'), + this.module_path, + `${this.module_path}.js`, + `${this.module_path}.mjs`, + `${this.module_path}.cjs`, + joinPath(this.module_path, 'index.js'), ]; for (const filename of filenames) { @@ -54,11 +68,17 @@ export default class HyperAPIRequest extends Event { this.#resolve = resolve; }); + /** + * @returns {Promise} The response. + */ wait() { return this.#promise; } - respondWith(response) { + /** + * @param {HyperAPIResponse} response The response. + */ + _respondWith(response) { this.#resolve(response); } } diff --git a/src/response.js b/src/response.js index 796d688..41d4b8f 100644 --- a/src/response.js +++ b/src/response.js @@ -2,6 +2,10 @@ import HyperAPIError from './error.js'; export default class HyperAPIResponse { + /** + * Creates a HyperAPI response. + * @param {HyperAPIError|object|Array} value The error or the response value. + */ constructor(value) { if (value instanceof HyperAPIError) { this.error = value; @@ -9,58 +13,31 @@ export default class HyperAPIResponse { else if ( (value !== null && typeof value === 'object') // object || Array.isArray(value) // array - || typeof value === 'string' // string - || typeof value === 'number' // number - || typeof value === 'boolean' // boolean ) { this.data = value; } else { - throw new TypeError('Argument 0 must be an instance of HyperAPIError or a valid response value.'); + throw new TypeError('Argument 0 must be an instance of HyperAPIError or be an object or an array.'); } } - object() { - const data = { - code: this.error?.code ?? 0, - }; - - if (this.error && typeof this.error.description === 'string') { - data.description = this.error.description; - } - - if (this.data !== undefined) { - data.data = this.data; - } - - return data; + /** + * @returns {boolean} Whether the response is successful. + * @readonly + */ + get is_success() { + return this.error === undefined; } - array() { - const result = [ - this.error?.code ?? 0, - ]; - + /** + * Returns response as an object. For example, that can be used as the body of a HTTP response. + * @returns {{[key: string]: *}?} The response. + */ + getResponse() { if (this.error) { - result.push(this.error.description ?? ''); + return this.error.getResponse(); } - if (this.data !== undefined) { - result.push(this.data); - } - - return result; - } - - json() { - return JSON.stringify( - this.object(), - ); - } - - compactJSON() { - return JSON.stringify( - this.array(), - ); + return this.data; } } diff --git a/test/api/echo.js b/test/api/echo.js index 9acf92f..4dfa126 100644 --- a/test/api/echo.js +++ b/test/api/echo.js @@ -1,8 +1,11 @@ +/* eslint-disable jsdoc/require-jsdoc */ import { OhMyPropsObjectValidator } from 'oh-my-props'; export default function (request) { - return `Hello, ${request.args.name}!`; + return { + message: `Hello, ${request.args.name}!`, + }; } export const args = new OhMyPropsObjectValidator({ diff --git a/test/api/error.api.js b/test/api/error.api.js index 940a3d8..97cd4bd 100644 --- a/test/api/error.api.js +++ b/test/api/error.api.js @@ -1,3 +1,4 @@ +/* eslint-disable jsdoc/require-jsdoc */ import { HyperAPIBusyError } from '../../src/api-errors.js'; diff --git a/test/api/error.internal.js b/test/api/error.internal.js index 6d240a5..ba6abd9 100644 --- a/test/api/error.internal.js +++ b/test/api/error.internal.js @@ -1,3 +1,4 @@ +/* eslint-disable jsdoc/require-jsdoc */ export default function () { throw new TypeError('Invalid something given.'); diff --git a/test/main.js b/test/main.js index 28eba0c..e87a51d 100644 --- a/test/main.js +++ b/test/main.js @@ -1,3 +1,4 @@ +/* eslint-disable jsdoc/require-jsdoc */ import { deepStrictEqual } from 'node:assert/strict'; import { @@ -22,7 +23,7 @@ async function request(method, args = {}) { ), ); - return response.array(); + return response.getResponse(); } describe('HyperAPI', () => { @@ -34,10 +35,9 @@ describe('HyperAPI', () => { name: 'world', }, ), - [ - 0, - 'Hello, world!', - ], + { + message: 'Hello, world!', + }, ); }); @@ -49,50 +49,50 @@ describe('HyperAPI', () => { name: 123, }, ), - [ - 2, - 'One of the parameters specified was missing or invalid', - ], + { + code: 2, + description: 'One of the parameters specified was missing or invalid', + }, ); }); it('missing arguments', async () => { deepStrictEqual( await request('echo'), - [ - 2, - 'One of the parameters specified was missing or invalid', - ], + { + code: 2, + description: 'One of the parameters specified was missing or invalid', + }, ); }); it('api error', async () => { deepStrictEqual( await request('error.api'), - [ - 10, - 'Endpoint is busy', - ], + { + code: 10, + description: 'Endpoint is busy', + }, ); }); it('internal error', async () => { deepStrictEqual( await request('error.internal'), - [ - 3, - 'Internal error', - ], + { + code: 3, + description: 'Internal error', + }, ); }); it('unknown method', async () => { deepStrictEqual( await request('error.unknown-method'), - [ - 5, - 'Unknown method called', - ], + { + code: 5, + description: 'Unknown method called', + }, ); }); }); From e721f67cef90e178e7274439ffcbe1d82247c123 Mon Sep 17 00:00:00 2001 From: Daniil Kirichenko Date: Sat, 2 Sep 2023 15:35:03 +0300 Subject: [PATCH 05/57] [v0.1.0-beta.4] Bugfix ~ fixed a bug when server did not response when api method returned value of invalid type --- package.json | 2 +- src/main.js | 7 +++---- test/api/echo.async.js | 23 +++++++++++++++++++++++ test/api/error.type.js | 5 +++++ test/main.js | 26 +++++++++++++++++++++++++- 5 files changed, 57 insertions(+), 6 deletions(-) create mode 100644 test/api/echo.async.js create mode 100644 test/api/error.type.js diff --git a/package.json b/package.json index 983c5c2..99ffcd5 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@hyperapi/core", - "version": "0.1.0-beta.3", + "version": "0.1.0-beta.4", "description": "This package is a core for HyperAPI project.", "publishConfig": { "access": "public", diff --git a/src/main.js b/src/main.js index 4286c07..770ed62 100644 --- a/src/main.js +++ b/src/main.js @@ -42,9 +42,7 @@ export default class HyperAPI { #setUpListener() { const handler = (request) => { this.#handleRequest(request) - .then((response) => request._respondWith( - new HyperAPIResponse(response), - )) + .then((hyperAPIResponse) => request._respondWith(hyperAPIResponse)) .catch(() => {}); // never throws }; @@ -63,7 +61,8 @@ export default class HyperAPI { async #handleRequest(request) { try { - return await this.#useModule(request); + const response = await this.#useModule(request); + return new HyperAPIResponse(response); } catch (error) { // error must be an instance of HyperAPIError diff --git a/test/api/echo.async.js b/test/api/echo.async.js new file mode 100644 index 0000000..b32fe0b --- /dev/null +++ b/test/api/echo.async.js @@ -0,0 +1,23 @@ +/* eslint-disable jsdoc/require-jsdoc */ + +import { OhMyPropsObjectValidator } from 'oh-my-props'; + +export default async function (request) { + await new Promise((resolve) => { + setTimeout( + resolve, + 10, + ); + }); + + return { + message: `Hello, ${request.args.name}!`, + }; +} + +export const args = new OhMyPropsObjectValidator({ + name: { + type: String, + required: true, + }, +}); diff --git a/test/api/error.type.js b/test/api/error.type.js new file mode 100644 index 0000000..1b124e9 --- /dev/null +++ b/test/api/error.type.js @@ -0,0 +1,5 @@ +/* eslint-disable jsdoc/require-jsdoc */ + +export default function () { + return true; +} diff --git a/test/main.js b/test/main.js index e87a51d..e3a1b6e 100644 --- a/test/main.js +++ b/test/main.js @@ -27,7 +27,7 @@ async function request(method, args = {}) { } describe('HyperAPI', () => { - it('correct request', async () => { + it('correct request (sync)', async () => { deepStrictEqual( await request( 'echo', @@ -41,6 +41,20 @@ describe('HyperAPI', () => { ); }); + it('correct request (async)', async () => { + deepStrictEqual( + await request( + 'echo.async', + { + name: 'user', + }, + ), + { + message: 'Hello, user!', + }, + ); + }); + it('invalid arguments', async () => { deepStrictEqual( await request( @@ -86,6 +100,16 @@ describe('HyperAPI', () => { ); }); + it('invalid return type', async () => { + deepStrictEqual( + await request('error.type'), + { + code: 3, + description: 'Internal error', + }, + ); + }); + it('unknown method', async () => { deepStrictEqual( await request('error.unknown-method'), From b3bdb9e9a5a46f3070de6e36ab20ac3ddc3356cc Mon Sep 17 00:00:00 2001 From: Daniil Kirichenko Date: Sat, 2 Sep 2023 16:22:03 +0300 Subject: [PATCH 06/57] [v0.1.0-beta.5] Bugfix ~ fixed a bug when server returned HyperAPIError instead of HyperAPIResponse --- package.json | 2 +- src/main.js | 27 +++++++++++++--- test/main.js | 89 ++++++++++++++++++++++++++++++++++------------------ 3 files changed, 81 insertions(+), 37 deletions(-) diff --git a/package.json b/package.json index 99ffcd5..b1d6b8c 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@hyperapi/core", - "version": "0.1.0-beta.4", + "version": "0.1.0-beta.5", "description": "This package is a core for HyperAPI project.", "publishConfig": { "access": "public", diff --git a/src/main.js b/src/main.js index 770ed62..0876058 100644 --- a/src/main.js +++ b/src/main.js @@ -11,6 +11,10 @@ import { OhMyPropsType, OhMyPropsValueError } from 'oh-my-props'; +/** + * @typedef {import('./request.js').default} HyperAPIRequest + */ + export default class HyperAPI { #driver; #root; @@ -40,10 +44,18 @@ export default class HyperAPI { } #setUpListener() { - const handler = (request) => { - this.#handleRequest(request) - .then((hyperAPIResponse) => request._respondWith(hyperAPIResponse)) - .catch(() => {}); // never throws + const handler = async (request) => { + try { + request._respondWith( + await this.#handleRequest(request), + ); + } + catch (error) { + // should never happen + console.error('Unexpected error happened:'); + console.error(error); + process.exit(); // eslint-disable-line no-process-exit, unicorn/no-process-exit + } }; this.#driver.addEventListener( @@ -59,6 +71,11 @@ export default class HyperAPI { }; } + /** + * Processes a request and returns the response. + * @param {HyperAPIRequest} request The HyperAPI request. + * @returns {Promise} The HyperAPI response. + */ async #handleRequest(request) { try { const response = await this.#useModule(request); @@ -72,7 +89,7 @@ export default class HyperAPI { error = new HyperAPIInternalError(); } - return error; + return new HyperAPIResponse(error); } } diff --git a/test/main.js b/test/main.js index e3a1b6e..edaa981 100644 --- a/test/main.js +++ b/test/main.js @@ -23,7 +23,10 @@ async function request(method, args = {}) { ), ); - return response.getResponse(); + return [ + response.is_success, + response.getResponse(), + ]; } describe('HyperAPI', () => { @@ -35,9 +38,12 @@ describe('HyperAPI', () => { name: 'world', }, ), - { - message: 'Hello, world!', - }, + [ + true, + { + message: 'Hello, world!', + }, + ], ); }); @@ -49,9 +55,12 @@ describe('HyperAPI', () => { name: 'user', }, ), - { - message: 'Hello, user!', - }, + [ + true, + { + message: 'Hello, user!', + }, + ], ); }); @@ -63,60 +72,78 @@ describe('HyperAPI', () => { name: 123, }, ), - { - code: 2, - description: 'One of the parameters specified was missing or invalid', - }, + [ + false, + { + code: 2, + description: 'One of the parameters specified was missing or invalid', + }, + ], ); }); it('missing arguments', async () => { deepStrictEqual( await request('echo'), - { - code: 2, - description: 'One of the parameters specified was missing or invalid', - }, + [ + false, + { + code: 2, + description: 'One of the parameters specified was missing or invalid', + }, + ], ); }); it('api error', async () => { deepStrictEqual( await request('error.api'), - { - code: 10, - description: 'Endpoint is busy', - }, + [ + false, + { + code: 10, + description: 'Endpoint is busy', + }, + ], ); }); it('internal error', async () => { deepStrictEqual( await request('error.internal'), - { - code: 3, - description: 'Internal error', - }, + [ + false, + { + code: 3, + description: 'Internal error', + }, + ], ); }); it('invalid return type', async () => { deepStrictEqual( await request('error.type'), - { - code: 3, - description: 'Internal error', - }, + [ + false, + { + code: 3, + description: 'Internal error', + }, + ], ); }); it('unknown method', async () => { deepStrictEqual( await request('error.unknown-method'), - { - code: 5, - description: 'Unknown method called', - }, + [ + false, + { + code: 5, + description: 'Unknown method called', + }, + ], ); }); }); From b80c84c409385672561960cd7acebbe75edcdb42 Mon Sep 17 00:00:00 2001 From: Daniil Kirichenko Date: Sun, 24 Dec 2023 20:44:30 +0300 Subject: [PATCH 07/57] Support for any validator + removed oh-my-props + cjs support Tests: ~ mocha replaced with jest ~ bun tests --- .eslintrc.cjs | 3 + .npmignore | 4 + dist/hyperapi-core.cjs | 381 ++++++++++++++++++++++++++++++++++++++++ dist/hyperapi.cjs | 387 +++++++++++++++++++++++++++++++++++++++++ package.json | 28 +-- src/api-errors.js | 2 +- src/driver.js | 4 +- src/error.js | 2 +- src/main.js | 39 ++--- src/main.test.js | 138 +++++++++++++++ src/request.js | 2 +- src/response.js | 4 +- test/api/echo.async.js | 23 ++- test/api/echo.js | 23 ++- test/main.js | 149 ---------------- test/validator.js | 24 +++ 16 files changed, 1000 insertions(+), 213 deletions(-) create mode 100644 .npmignore create mode 100644 dist/hyperapi-core.cjs create mode 100644 dist/hyperapi.cjs create mode 100644 src/main.test.js delete mode 100644 test/main.js create mode 100644 test/validator.js diff --git a/.eslintrc.cjs b/.eslintrc.cjs index f933123..bed5291 100644 --- a/.eslintrc.cjs +++ b/.eslintrc.cjs @@ -28,6 +28,9 @@ module.exports = { 'unicorn', 'node', ], + ignorePatterns: [ + 'dist/**/*', + ], rules: { 'array-bracket-spacing': [ 'error', diff --git a/.npmignore b/.npmignore new file mode 100644 index 0000000..3394edf --- /dev/null +++ b/.npmignore @@ -0,0 +1,4 @@ + +.eslintrc.cjs +test/ +**/*.test.js diff --git a/dist/hyperapi-core.cjs b/dist/hyperapi-core.cjs new file mode 100644 index 0000000..427b75b --- /dev/null +++ b/dist/hyperapi-core.cjs @@ -0,0 +1,381 @@ +var __defProp = Object.defineProperty; +var __getOwnPropDesc = Object.getOwnPropertyDescriptor; +var __getOwnPropNames = Object.getOwnPropertyNames; +var __hasOwnProp = Object.prototype.hasOwnProperty; +var __export = (target, all) => { + for (var name in all) + __defProp(target, name, { get: all[name], enumerable: true }); +}; +var __copyProps = (to, from, except, desc) => { + if (from && typeof from === "object" || typeof from === "function") { + for (let key of __getOwnPropNames(from)) + if (!__hasOwnProp.call(to, key) && key !== except) + __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable }); + } + return to; +}; +var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod); + +// src/main.js +var main_exports = {}; +__export(main_exports, { + HyperAPI: () => HyperAPI, + HyperAPIAuthorizationError: () => HyperAPIAuthorizationError, + HyperAPIBusyError: () => HyperAPIBusyError, + HyperAPICaptchaError: () => HyperAPICaptchaError, + HyperAPIConfirmationError: () => HyperAPIConfirmationError, + HyperAPIDriver: () => HyperAPIDriver, + HyperAPIError: () => HyperAPIError, + HyperAPIForbiddenError: () => HyperAPIForbiddenError, + HyperAPIInternalError: () => HyperAPIInternalError, + HyperAPIInvalidParametersError: () => HyperAPIInvalidParametersError, + HyperAPIMaintenanceError: () => HyperAPIMaintenanceError, + HyperAPIOTPError: () => HyperAPIOTPError, + HyperAPIObjectsLimitError: () => HyperAPIObjectsLimitError, + HyperAPIRateLimitError: () => HyperAPIRateLimitError, + HyperAPIRequest: () => HyperAPIRequest, + HyperAPIResponse: () => HyperAPIResponse, + HyperAPIUnknownMethodError: () => HyperAPIUnknownMethodError +}); +module.exports = __toCommonJS(main_exports); +var import_node_path2 = require("node:path"); + +// src/error.js +var HyperAPIError = class extends Error { + /** + * The error code. + * @type {number} + * @readonly + */ + code; + /** + * The error description. + * @type {string?} + * @readonly + */ + description = null; + /** + * The error data. + * @type {{[key: string]: *}?} + * @readonly + */ + data = null; + /** + * @param {{[key: string]: *}?} data The error data. Cannot contain "code" or "description" properties. + */ + constructor(data = null) { + super(); + if (data !== null && typeof data !== "object") { + throw new TypeError("Argument 0 must be an object or not be provided"); + } + if (data && ("code" in data || "description" in data)) { + throw new TypeError('Argument 0 must not contain "code" or "description" properties'); + } + this.data = data; + } + get message() { + return `${this.description ?? ""} (code ${this.code})`; + } + getResponse() { + const result = { + code: this.code + }; + if (typeof this.description === "string") { + result.description = this.description; + } + return { + ...result, + ...this.data + }; + } +}; + +// src/api-errors.js +var HyperAPIAuthorizationError = class extends HyperAPIError { + code = 1; + description = "Authorization error"; + httpStatus = 401; + // Unauthorized +}; +var HyperAPIInvalidParametersError = class extends HyperAPIError { + code = 2; + description = "One of the parameters specified was missing or invalid"; + httpStatus = 400; + // Bad Request +}; +var HyperAPIInternalError = class extends HyperAPIError { + code = 3; + description = "Internal error"; + httpStatus = 500; + // Internal Server Error +}; +var HyperAPIForbiddenError = class extends HyperAPIError { + code = 4; + description = "You do not have permission to perform this action"; + httpStatus = 403; + // Forbidden +}; +var HyperAPIUnknownMethodError = class extends HyperAPIError { + code = 5; + description = "Unknown method called"; + httpStatus = 404; + // Not Found +}; +var HyperAPIObjectsLimitError = class extends HyperAPIError { + code = 6; + description = "Too many objects requested"; + httpStatus = 400; + // Bad Request +}; +var HyperAPIRateLimitError = class extends HyperAPIError { + code = 7; + description = "Rate limit exceeded"; + httpStatus = 429; + // Too Many Requests +}; +var HyperAPICaptchaError = class extends HyperAPIError { + code = 8; + description = "Captcha required"; + httpStatus = 428; + // Precondition Required +}; +var HyperAPIBusyError = class extends HyperAPIError { + code = 10; + description = "Endpoint is busy"; + httpStatus = 503; + // Service Unavailable +}; +var HyperAPIConfirmationError = class extends HyperAPIError { + code = 11; + description = "Confirmation required"; + httpStatus = 409; + // Conflict +}; +var HyperAPIOTPError = class extends HyperAPIError { + code = 12; + description = "One-time password required"; + httpStatus = 401; + // Unauthorized +}; +var HyperAPIMaintenanceError = class extends HyperAPIError { + code = 13; + description = "Endpoint is in maintenance mode"; + httpStatus = 503; + // Service Unavailable +}; + +// src/request.js +var import_node_path = require("node:path"); +var HyperAPIRequest = class extends Event { + #data = /* @__PURE__ */ new Map(); + /** + * @param {string} module_path The relative path to the API method module. + * @param {Array<*>} args The arguments to pass to the API method. + */ + constructor(module_path, args) { + super("HyperAPIRequest"); + this.module_path = module_path; + this.args = args; + this.flags = {}; + } + /** + * @param {*} key The key to get. + * @returns {*} The value. + */ + get(key) { + return this.#data.get(key); + } + /** + * @param {*} key The key to set. + * @param {*} value The value to set. + */ + set(key, value) { + this.#data.set(key, value); + } + async _getModule(root) { + const filenames = [ + this.module_path, + `${this.module_path}.js`, + `${this.module_path}.mjs`, + `${this.module_path}.cjs`, + (0, import_node_path.join)(this.module_path, "index.js") + ]; + for (const filename of filenames) { + try { + return await import((0, import_node_path.join)( + root, + filename + )); + } catch { + } + } + throw new HyperAPIUnknownMethodError(); + } + #resolve; + #promise = new Promise((resolve) => { + this.#resolve = resolve; + }); + /** + * @returns {Promise} The response. + */ + wait() { + return this.#promise; + } + /** + * @param {HyperAPIResponse} response The response. + */ + _respondWith(response) { + this.#resolve(response); + } +}; + +// src/driver.js +var HyperAPIDriver = class extends EventTarget { + /** + * Processes a request and waits for the response. + * @async + * @param {HyperAPIRequest} request The HyperAPI request. + * @returns {Promise} The HyperAPI response. + */ + onRequest(request) { + if (request instanceof HyperAPIRequest !== true) { + throw new TypeError("Argument 0 must be an instance of HyperAPIRequest."); + } + this.dispatchEvent(request); + return request.wait(); + } +}; + +// src/response.js +var HyperAPIResponse = class { + /** + * Creates a HyperAPI response. + * @param {HyperAPIError|object|Array} value The error or the response value. + */ + constructor(value) { + if (value instanceof HyperAPIError) { + this.error = value; + } else if (value !== null && typeof value === "object" || Array.isArray(value)) { + this.data = value; + } else { + throw new TypeError("Argument 0 must be an instance of HyperAPIError or be an object or an array."); + } + } + /** + * @returns {boolean} Whether the response is successful. + * @readonly + */ + get is_success() { + return this.error === void 0; + } + /** + * Returns response as an object. For example, that can be used as the body of a HTTP response. + * @returns {{[key: string]: *}?} The response. + */ + getResponse() { + if (this.error) { + return this.error.getResponse(); + } + return this.data; + } +}; + +// src/main.js +var HyperAPI = class { + #driver; + #root; + #turnDriverOff; + /** + * Creates a HyperAPI instance. + * @param {object} options The options. + * @param {HyperAPIDriver} options.driver The HyperAPI driver. + * @param {string=} options.root The root directory for API methods modules. Defaults to "/hyper-api" inside the current working directory. + */ + constructor({ + driver, + root = (0, import_node_path2.join)( + process.cwd(), + "hyper-api" + ) + }) { + if (driver instanceof HyperAPIDriver !== true) { + throw new TypeError('Property "driver" must be an instance of HyperAPIDriver.'); + } + this.#driver = driver; + this.#root = root; + this.#setUpListener(); + } + #setUpListener() { + const handler = async (request) => { + try { + request._respondWith( + await this.#handleRequest(request) + ); + } catch (error) { + console.error("Unexpected error happened:"); + console.error(error); + process.exit(); + } + }; + this.#driver.addEventListener( + "HyperAPIRequest", + handler + ); + this.#turnDriverOff = () => { + this.#driver.removeEventListener( + "HyperAPIRequest", + handler + ); + }; + } + /** + * Processes a request and returns the response. + * @param {HyperAPIRequest} request The HyperAPI request. + * @returns {Promise} The HyperAPI response. + */ + async #handleRequest(request) { + try { + const response = await this.#useModule(request); + return new HyperAPIResponse(response); + } catch (error) { + if (error instanceof HyperAPIError !== true) { + console.error(error); + error = new HyperAPIInternalError(); + } + return new HyperAPIResponse(error); + } + } + async #useModule(request) { + const module2 = await request._getModule(this.#root); + if (typeof module2.argsValidator === "function") { + request.args = await module2.argsValidator(request.args); + } + return module2.default(request); + } + /** + * Destroys the HyperAPI instance. + */ + destroy() { + this.#turnDriverOff(); + } +}; +// Annotate the CommonJS export names for ESM import in node: +0 && (module.exports = { + HyperAPI, + HyperAPIAuthorizationError, + HyperAPIBusyError, + HyperAPICaptchaError, + HyperAPIConfirmationError, + HyperAPIDriver, + HyperAPIError, + HyperAPIForbiddenError, + HyperAPIInternalError, + HyperAPIInvalidParametersError, + HyperAPIMaintenanceError, + HyperAPIOTPError, + HyperAPIObjectsLimitError, + HyperAPIRateLimitError, + HyperAPIRequest, + HyperAPIResponse, + HyperAPIUnknownMethodError +}); diff --git a/dist/hyperapi.cjs b/dist/hyperapi.cjs new file mode 100644 index 0000000..326dba6 --- /dev/null +++ b/dist/hyperapi.cjs @@ -0,0 +1,387 @@ +var __defProp = Object.defineProperty; +var __getOwnPropDesc = Object.getOwnPropertyDescriptor; +var __getOwnPropNames = Object.getOwnPropertyNames; +var __hasOwnProp = Object.prototype.hasOwnProperty; +var __export = (target, all) => { + for (var name in all) + __defProp(target, name, { get: all[name], enumerable: true }); +}; +var __copyProps = (to, from, except, desc) => { + if (from && typeof from === "object" || typeof from === "function") { + for (let key of __getOwnPropNames(from)) + if (!__hasOwnProp.call(to, key) && key !== except) + __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable }); + } + return to; +}; +var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod); + +// src/main.js +var main_exports = {}; +__export(main_exports, { + HyperAPIAuthorizationError: () => HyperAPIAuthorizationError, + HyperAPIBusyError: () => HyperAPIBusyError, + HyperAPICaptchaError: () => HyperAPICaptchaError, + HyperAPIConfirmationError: () => HyperAPIConfirmationError, + HyperAPIDriver: () => HyperAPIDriver, + HyperAPIError: () => HyperAPIError, + HyperAPIForbiddenError: () => HyperAPIForbiddenError, + HyperAPIInternalError: () => HyperAPIInternalError, + HyperAPIInvalidParametersError: () => HyperAPIInvalidParametersError, + HyperAPIMaintenanceError: () => HyperAPIMaintenanceError, + HyperAPIOTPError: () => HyperAPIOTPError, + HyperAPIObjectsLimitError: () => HyperAPIObjectsLimitError, + HyperAPIRateLimitError: () => HyperAPIRateLimitError, + HyperAPIRequest: () => HyperAPIRequest, + HyperAPIResponse: () => HyperAPIResponse, + HyperAPIUnknownMethodError: () => HyperAPIUnknownMethodError, + default: () => HyperAPI +}); +module.exports = __toCommonJS(main_exports); +var import_node_path2 = require("node:path"); + +// src/error.js +var HyperAPIError = class extends Error { + /** + * The error code. + * @type {number} + * @readonly + */ + code; + /** + * The error description. + * @type {string?} + * @readonly + */ + description = null; + /** + * The error data. + * @type {{[key: string]: *}?} + * @readonly + */ + data = null; + /** + * @param {{[key: string]: *}?} data The error data. Cannot contain "code" or "description" properties. + */ + constructor(data = null) { + super(); + if (data !== null && typeof data !== "object") { + throw new TypeError("Argument 0 must be an object or not be provided"); + } + if (data && ("code" in data || "description" in data)) { + throw new TypeError('Argument 0 must not contain "code" or "description" properties'); + } + this.data = data; + } + get message() { + return `${this.description ?? ""} (code ${this.code})`; + } + getResponse() { + const result = { + code: this.code + }; + if (typeof this.description === "string") { + result.description = this.description; + } + return { + ...result, + ...this.data + }; + } +}; + +// src/api-errors.js +var HyperAPIAuthorizationError = class extends HyperAPIError { + code = 1; + description = "Authorization error"; + httpStatus = 401; + // Unauthorized +}; +var HyperAPIInvalidParametersError = class extends HyperAPIError { + code = 2; + description = "One of the parameters specified was missing or invalid"; + httpStatus = 400; + // Bad Request +}; +var HyperAPIInternalError = class extends HyperAPIError { + code = 3; + description = "Internal error"; + httpStatus = 500; + // Internal Server Error +}; +var HyperAPIForbiddenError = class extends HyperAPIError { + code = 4; + description = "You do not have permission to perform this action"; + httpStatus = 403; + // Forbidden +}; +var HyperAPIUnknownMethodError = class extends HyperAPIError { + code = 5; + description = "Unknown method called"; + httpStatus = 404; + // Not Found +}; +var HyperAPIObjectsLimitError = class extends HyperAPIError { + code = 6; + description = "Too many objects requested"; + httpStatus = 400; + // Bad Request +}; +var HyperAPIRateLimitError = class extends HyperAPIError { + code = 7; + description = "Rate limit exceeded"; + httpStatus = 429; + // Too Many Requests +}; +var HyperAPICaptchaError = class extends HyperAPIError { + code = 8; + description = "Captcha required"; + httpStatus = 428; + // Precondition Required +}; +var HyperAPIBusyError = class extends HyperAPIError { + code = 10; + description = "Endpoint is busy"; + httpStatus = 503; + // Service Unavailable +}; +var HyperAPIConfirmationError = class extends HyperAPIError { + code = 11; + description = "Confirmation required"; + httpStatus = 409; + // Conflict +}; +var HyperAPIOTPError = class extends HyperAPIError { + code = 12; + description = "One-time password required"; + httpStatus = 401; + // Unauthorized +}; +var HyperAPIMaintenanceError = class extends HyperAPIError { + code = 13; + description = "Endpoint is in maintenance mode"; + httpStatus = 503; + // Service Unavailable +}; + +// src/request.js +var import_node_path = require("node:path"); +var HyperAPIRequest = class extends Event { + #data = /* @__PURE__ */ new Map(); + /** + * @param {string} module_path The relative path to the API method module. + * @param {Array<*>} args The arguments to pass to the API method. + */ + constructor(module_path, args) { + super("HyperAPIRequest"); + this.module_path = module_path; + this.args = args; + this.flags = {}; + } + /** + * @param {*} key The key to get. + * @returns {*} The value. + */ + get(key) { + return this.#data.get(key); + } + /** + * @param {*} key The key to set. + * @param {*} value The value to set. + */ + set(key, value) { + this.#data.set(key, value); + } + async _getModule(root) { + const filenames = [ + this.module_path, + `${this.module_path}.js`, + `${this.module_path}.mjs`, + `${this.module_path}.cjs`, + (0, import_node_path.join)(this.module_path, "index.js") + ]; + for (const filename of filenames) { + try { + return await import((0, import_node_path.join)( + root, + filename + )); + } catch { + } + } + throw new HyperAPIUnknownMethodError(); + } + #resolve; + #promise = new Promise((resolve) => { + this.#resolve = resolve; + }); + /** + * @returns {Promise} The response. + */ + wait() { + return this.#promise; + } + /** + * @param {HyperAPIResponse} response The response. + */ + _respondWith(response) { + this.#resolve(response); + } +}; + +// src/driver.js +var HyperAPIDriver = class extends EventTarget { + /** + * Processes a request and waits for the response. + * @async + * @param {HyperAPIRequest} request The HyperAPI request. + * @returns {Promise} The HyperAPI response. + */ + onRequest(request) { + if (request instanceof HyperAPIRequest !== true) { + throw new TypeError("Argument 0 must be an instance of HyperAPIRequest."); + } + this.dispatchEvent(request); + return request.wait(); + } +}; + +// src/response.js +var HyperAPIResponse = class { + /** + * Creates a HyperAPI response. + * @param {HyperAPIError|object|Array} value The error or the response value. + */ + constructor(value) { + if (value instanceof HyperAPIError) { + this.error = value; + } else if (value !== null && typeof value === "object" || Array.isArray(value)) { + this.data = value; + } else { + throw new TypeError("Argument 0 must be an instance of HyperAPIError or be an object or an array."); + } + } + /** + * @returns {boolean} Whether the response is successful. + * @readonly + */ + get is_success() { + return this.error === void 0; + } + /** + * Returns response as an object. For example, that can be used as the body of a HTTP response. + * @returns {{[key: string]: *}?} The response. + */ + getResponse() { + if (this.error) { + return this.error.getResponse(); + } + return this.data; + } +}; + +// src/main.js +var HyperAPI = class { + #driver; + #root; + #turnDriverOff; + /** + * Creates a HyperAPI instance. + * @param {object} options The options. + * @param {HyperAPIDriver} options.driver The HyperAPI driver. + * @param {string=} options.root The root directory for API methods modules. Defaults to "/hyper-api" inside the current working directory. + */ + constructor({ + driver, + root = (0, import_node_path2.join)( + process.cwd(), + "hyper-api" + ) + }) { + if (driver instanceof HyperAPIDriver !== true) { + throw new TypeError('Property "driver" must be an instance of HyperAPIDriver.'); + } + this.#driver = driver; + this.#root = root; + this.#setUpListener(); + } + #setUpListener() { + const handler = async (request) => { + try { + request._respondWith( + await this.#handleRequest(request) + ); + } catch (error) { + console.error("Unexpected error happened:"); + console.error(error); + process.exit(); + } + }; + this.#driver.addEventListener( + "HyperAPIRequest", + handler + ); + this.#turnDriverOff = () => { + this.#driver.removeEventListener( + "HyperAPIRequest", + handler + ); + }; + } + /** + * Processes a request and returns the response. + * @param {HyperAPIRequest} request The HyperAPI request. + * @returns {Promise} The HyperAPI response. + */ + async #handleRequest(request) { + try { + const response = await this.#useModule(request); + return new HyperAPIResponse(response); + } catch (error) { + if (error instanceof HyperAPIError !== true) { + console.error(error); + error = new HyperAPIInternalError(); + } + return new HyperAPIResponse(error); + } + } + async #useModule(request) { + const module2 = await request._getModule(this.#root); + if (module2.args instanceof OhMyPropsType) { + try { + request.args = module2.args.cast(request.args); + } catch (error) { + if (error instanceof OhMyPropsValueError) { + throw new HyperAPIInvalidParametersError(); + } + throw error; + } + } + return module2.default(request); + } + /** + * Destroys the HyperAPI instance. + */ + destroy() { + this.#turnDriverOff(); + } +}; +// Annotate the CommonJS export names for ESM import in node: +0 && (module.exports = { + HyperAPIAuthorizationError, + HyperAPIBusyError, + HyperAPICaptchaError, + HyperAPIConfirmationError, + HyperAPIDriver, + HyperAPIError, + HyperAPIForbiddenError, + HyperAPIInternalError, + HyperAPIInvalidParametersError, + HyperAPIMaintenanceError, + HyperAPIOTPError, + HyperAPIObjectsLimitError, + HyperAPIRateLimitError, + HyperAPIRequest, + HyperAPIResponse, + HyperAPIUnknownMethodError +}); diff --git a/package.json b/package.json index b1d6b8c..2122335 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@hyperapi/core", - "version": "0.1.0-beta.5", + "version": "0.1.0-beta.6", "description": "This package is a core for HyperAPI project.", "publishConfig": { "access": "public", @@ -9,15 +9,13 @@ "type": "module", "main": "src/main.js", "exports": { - ".": "./src/main.js", - "./api-errors": "./src/api-errors.js", - "./driver": "./src/driver.js", - "./error": "./src/error.js", - "./request": "./src/request.js", - "./response": "./src/response.js" + ".": { + "import": "./src/main.js", + "require": "./dist/hyperapi-core.cjs" + } }, - "peerDependencies": { - "oh-my-props": ">= 3.0.0-beta.20" + "engines": { + "node": ">=10.0.0" }, "devDependencies": { "@babel/eslint-parser": "7.21.8", @@ -28,13 +26,15 @@ "eslint-plugin-node": "11.1.0", "eslint-plugin-promise": "6.1.1", "eslint-plugin-unicorn": "47.0.0", - "mocha": "^10.2.0" - }, - "engines": { - "node": ">=10.0.0" + "jest": "^29.7.0", + "valibot": "^0.24.1" }, "scripts": { - "test": "mocha" + "test": "npm run test-node && bun test", + "test-node": "NODE_OPTIONS=--experimental-vm-modules jest --forceExit", + "build": "bun run build-cjs", + "build-cjs": "bunx esbuild --bundle --platform=node --format=cjs --packages=external --outfile=dist/hyperapi-core.cjs src/main.js", + "npm-publish": "bun run build && bun run eslint . && bun run test && npm publish --tag beta" }, "repository": { "type": "git", diff --git a/src/api-errors.js b/src/api-errors.js index e0b407e..1e6dac1 100644 --- a/src/api-errors.js +++ b/src/api-errors.js @@ -1,5 +1,5 @@ -import HyperAPIError from './error.js'; +import { HyperAPIError } from './error.js'; export class HyperAPIAuthorizationError extends HyperAPIError { code = 1; diff --git a/src/driver.js b/src/driver.js index feee26f..641e2fc 100644 --- a/src/driver.js +++ b/src/driver.js @@ -1,11 +1,11 @@ -import HyperAPIRequest from './request.js'; +import { HyperAPIRequest } from './request.js'; /** * @typedef {import('./response.js').default} HyperAPIResponse */ -export default class HyperAPIDriver extends EventTarget { +export class HyperAPIDriver extends EventTarget { /** * Processes a request and waits for the response. * @async diff --git a/src/error.js b/src/error.js index 7e9cb59..6fe3319 100644 --- a/src/error.js +++ b/src/error.js @@ -1,5 +1,5 @@ -export default class HyperAPIError extends Error { +export class HyperAPIError extends Error { /** * The error code. * @type {number} diff --git a/src/main.js b/src/main.js index 0876058..0309726 100644 --- a/src/main.js +++ b/src/main.js @@ -1,21 +1,15 @@ -import { join as joinPath } from 'node:path'; - -import { - HyperAPIInternalError, - HyperAPIInvalidParametersError } from './api-errors.js'; -import HyperAPIDriver from './driver.js'; -import HyperAPIError from './error.js'; -import HyperAPIResponse from './response.js'; -import { - OhMyPropsType, - OhMyPropsValueError } from 'oh-my-props'; +import { join as joinPath } from 'node:path'; +import { HyperAPIInternalError } from './api-errors.js'; +import { HyperAPIDriver } from './driver.js'; +import { HyperAPIError } from './error.js'; +import { HyperAPIResponse } from './response.js'; /** * @typedef {import('./request.js').default} HyperAPIRequest */ -export default class HyperAPI { +export class HyperAPI { #driver; #root; #turnDriverOff; @@ -96,17 +90,8 @@ export default class HyperAPI { async #useModule(request) { const module = await request._getModule(this.#root); - if (module.args instanceof OhMyPropsType) { - try { - request.args = module.args.cast(request.args); - } - catch (error) { - if (error instanceof OhMyPropsValueError) { - throw new HyperAPIInvalidParametersError(); - } - - throw error; - } + if (typeof module.argsValidator === 'function') { + request.args = await module.argsValidator(request.args); } return module.default(request); @@ -121,7 +106,7 @@ export default class HyperAPI { } export * from './api-errors.js'; -export { default as HyperAPIDriver } from './driver.js'; -export { default as HyperAPIError } from './error.js'; -export { default as HyperAPIRequest } from './request.js'; -export { default as HyperAPIResponse } from './response.js'; +export { HyperAPIDriver } from './driver.js'; +export { HyperAPIError } from './error.js'; +export { HyperAPIRequest } from './request.js'; +export { HyperAPIResponse } from './response.js'; diff --git a/src/main.test.js b/src/main.test.js new file mode 100644 index 0000000..81d8eea --- /dev/null +++ b/src/main.test.js @@ -0,0 +1,138 @@ + +/* global describe, test, expect */ +/* eslint-disable jsdoc/require-jsdoc */ + +import { HyperAPIDriver } from './driver.js'; +import { HyperAPI } from './main.js'; +import { HyperAPIRequest } from './request.js'; + +const driver = new HyperAPIDriver(); +const api = new HyperAPI({ + driver, + root: new URL('../test/api', import.meta.url).pathname, +}); + +async function request(method, args = {}) { + const response = await driver.onRequest( + new HyperAPIRequest( + method, + args, + ), + ); + + return [ + response.is_success, + response.getResponse(), + ]; +} + +describe('HyperAPI', () => { + test('correct request (sync)', async () => { + const result = await request( + 'echo', + { + name: 'world', + }, + ); + + expect(result).toStrictEqual([ + true, + { + message: 'Hello, world!', + }, + ]); + }); + + test('correct request (async)', async () => { + const result = await request( + 'echo.async', + { + name: 'user', + }, + ); + + expect(result).toStrictEqual([ + true, + { + message: 'Hello, user!', + }, + ]); + }); + + test('invalid arguments', async () => { + const result = await request( + 'echo', + { + name: 123, + }, + ); + + expect(result).toStrictEqual([ + false, + { + code: 2, + description: 'One of the parameters specified was missing or invalid', + }, + ]); + }); + + test('missing arguments', async () => { + const result = await request('echo'); + + expect(result).toStrictEqual([ + false, + { + code: 2, + description: 'One of the parameters specified was missing or invalid', + }, + ]); + }); + + test('api error', async () => { + const result = await request('error.api'); + + expect(result).toStrictEqual([ + false, + { + code: 10, + description: 'Endpoint is busy', + }, + ]); + }); + + test('internal error', async () => { + const result = await request('error.internal'); + + expect(result).toStrictEqual([ + false, + { + code: 3, + description: 'Internal error', + }, + ]); + }); + + test('invalid return type', async () => { + const result = await request('error.type'); + + expect(result).toStrictEqual([ + false, + { + code: 3, + description: 'Internal error', + }, + ]); + }); + + test('unknown method', async () => { + const result = await request('error.unknown-method'); + + expect(result).toStrictEqual([ + false, + { + code: 5, + description: 'Unknown method called', + }, + ]); + }); +}); diff --git a/src/request.js b/src/request.js index 00004b3..9db9bc3 100644 --- a/src/request.js +++ b/src/request.js @@ -7,7 +7,7 @@ import { HyperAPIUnknownMethodError } from './api-errors.js'; * @typedef {import('./response.js').default} HyperAPIResponse */ -export default class HyperAPIRequest extends Event { +export class HyperAPIRequest extends Event { #data = new Map(); /** diff --git a/src/response.js b/src/response.js index 41d4b8f..8a8446c 100644 --- a/src/response.js +++ b/src/response.js @@ -1,7 +1,7 @@ -import HyperAPIError from './error.js'; +import { HyperAPIError } from './error.js'; -export default class HyperAPIResponse { +export class HyperAPIResponse { /** * Creates a HyperAPI response. * @param {HyperAPIError|object|Array} value The error or the response value. diff --git a/test/api/echo.async.js b/test/api/echo.async.js index b32fe0b..11055b8 100644 --- a/test/api/echo.async.js +++ b/test/api/echo.async.js @@ -1,6 +1,5 @@ -/* eslint-disable jsdoc/require-jsdoc */ -import { OhMyPropsObjectValidator } from 'oh-my-props'; +/* eslint-disable jsdoc/require-jsdoc */ export default async function (request) { await new Promise((resolve) => { @@ -15,9 +14,17 @@ export default async function (request) { }; } -export const args = new OhMyPropsObjectValidator({ - name: { - type: String, - required: true, - }, -}); +import { + never, + object, + string } from 'valibot'; +import { valibot } from '../validator.js'; + +export const argsValidator = valibot.bind( + object( + { + name: string(), + }, + never(), + ), +); diff --git a/test/api/echo.js b/test/api/echo.js index 4dfa126..7566ac4 100644 --- a/test/api/echo.js +++ b/test/api/echo.js @@ -1,6 +1,5 @@ -/* eslint-disable jsdoc/require-jsdoc */ -import { OhMyPropsObjectValidator } from 'oh-my-props'; +/* eslint-disable jsdoc/require-jsdoc */ export default function (request) { return { @@ -8,9 +7,17 @@ export default function (request) { }; } -export const args = new OhMyPropsObjectValidator({ - name: { - type: String, - required: true, - }, -}); +import { + never, + object, + string } from 'valibot'; +import { valibot } from '../validator.js'; + +export const argsValidator = valibot.bind( + object( + { + name: string(), + }, + never(), + ), +); diff --git a/test/main.js b/test/main.js deleted file mode 100644 index edaa981..0000000 --- a/test/main.js +++ /dev/null @@ -1,149 +0,0 @@ -/* eslint-disable jsdoc/require-jsdoc */ - -import { deepStrictEqual } from 'node:assert/strict'; -import { - describe, - it } from 'mocha'; - -import HyperAPIDriver from '../src/driver.js'; -import HyperAPI from '../src/main.js'; -import HyperAPIRequest from '../src/request.js'; - -const driver = new HyperAPIDriver(); -const api = new HyperAPI({ - driver, - root: new URL('api', import.meta.url).pathname, -}); - -async function request(method, args = {}) { - const response = await driver.onRequest( - new HyperAPIRequest( - method, - args, - ), - ); - - return [ - response.is_success, - response.getResponse(), - ]; -} - -describe('HyperAPI', () => { - it('correct request (sync)', async () => { - deepStrictEqual( - await request( - 'echo', - { - name: 'world', - }, - ), - [ - true, - { - message: 'Hello, world!', - }, - ], - ); - }); - - it('correct request (async)', async () => { - deepStrictEqual( - await request( - 'echo.async', - { - name: 'user', - }, - ), - [ - true, - { - message: 'Hello, user!', - }, - ], - ); - }); - - it('invalid arguments', async () => { - deepStrictEqual( - await request( - 'echo', - { - name: 123, - }, - ), - [ - false, - { - code: 2, - description: 'One of the parameters specified was missing or invalid', - }, - ], - ); - }); - - it('missing arguments', async () => { - deepStrictEqual( - await request('echo'), - [ - false, - { - code: 2, - description: 'One of the parameters specified was missing or invalid', - }, - ], - ); - }); - - it('api error', async () => { - deepStrictEqual( - await request('error.api'), - [ - false, - { - code: 10, - description: 'Endpoint is busy', - }, - ], - ); - }); - - it('internal error', async () => { - deepStrictEqual( - await request('error.internal'), - [ - false, - { - code: 3, - description: 'Internal error', - }, - ], - ); - }); - - it('invalid return type', async () => { - deepStrictEqual( - await request('error.type'), - [ - false, - { - code: 3, - description: 'Internal error', - }, - ], - ); - }); - - it('unknown method', async () => { - deepStrictEqual( - await request('error.unknown-method'), - [ - false, - { - code: 5, - description: 'Unknown method called', - }, - ], - ); - }); -}); diff --git a/test/validator.js b/test/validator.js new file mode 100644 index 0000000..e539afe --- /dev/null +++ b/test/validator.js @@ -0,0 +1,24 @@ + +import { + parse, + ValiError } from 'valibot'; +import { HyperAPIInvalidParametersError } from '../src/api-errors.js'; + +/** + * Validates the given value using Valibot schema. + * @param {any} value The value to validate. + * @returns {any} The validated value. + */ +export function valibot(value) { + try { + return parse(this, value); + } + catch (error) { + if (error instanceof ValiError) { + // console.error(error); + throw new HyperAPIInvalidParametersError(); + } + + throw error; + } +} From 9df67f82ae7d25eb04711fd8b3007d34e70a0f37 Mon Sep 17 00:00:00 2001 From: Daniil Kirichenko Date: Sun, 24 Dec 2023 21:43:44 +0300 Subject: [PATCH 08/57] Updated tests file --- package.json | 3 +-- src/main.test.js | 1 + 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/package.json b/package.json index 2122335..0cc493a 100644 --- a/package.json +++ b/package.json @@ -3,8 +3,7 @@ "version": "0.1.0-beta.6", "description": "This package is a core for HyperAPI project.", "publishConfig": { - "access": "public", - "tag": "beta" + "access": "public" }, "type": "module", "main": "src/main.js", diff --git a/src/main.test.js b/src/main.test.js index 81d8eea..0bc1078 100644 --- a/src/main.test.js +++ b/src/main.test.js @@ -7,6 +7,7 @@ import { HyperAPI } from './main.js'; import { HyperAPIRequest } from './request.js'; const driver = new HyperAPIDriver(); +// eslint-disable-next-line no-unused-vars const api = new HyperAPI({ driver, root: new URL('../test/api', import.meta.url).pathname, From dad1d57c6f6e112520fa66d486eb999fe89ed868 Mon Sep 17 00:00:00 2001 From: Daniil Kirichenko Date: Wed, 3 Jan 2024 00:45:40 +0300 Subject: [PATCH 09/57] Correct error handling when importing API module --- dist/hyperapi-core.cjs | 18 ++++++++++++----- package.json | 4 ++-- src/main.test.js | 37 ++++++++++++++++++++++++++++++++++ src/request.js | 32 ++++++++++++++++++++++------- test/api/dir/nested.js | 8 ++++++++ test/api/error.import.field.js | 8 ++++++++ test/api/error.import.path.js | 8 ++++++++ test/api/error.internal.js | 2 +- 8 files changed, 102 insertions(+), 15 deletions(-) create mode 100644 test/api/dir/nested.js create mode 100644 test/api/error.import.field.js create mode 100644 test/api/error.import.path.js diff --git a/dist/hyperapi-core.cjs b/dist/hyperapi-core.cjs index 427b75b..325a746 100644 --- a/dist/hyperapi-core.cjs +++ b/dist/hyperapi-core.cjs @@ -201,12 +201,20 @@ var HyperAPIRequest = class extends Event { (0, import_node_path.join)(this.module_path, "index.js") ]; for (const filename of filenames) { + const path = (0, import_node_path.join)( + root, + filename + ); try { - return await import((0, import_node_path.join)( - root, - filename - )); - } catch { + return await import(path); + } catch (error) { + if (error.code === "MODULE_NOT_FOUND" || error.code === "ERR_MODULE_NOT_FOUND") { + const path_error = error.moduleName ?? error.specifier; + if (path === path_error) { + continue; + } + } + throw error; } } throw new HyperAPIUnknownMethodError(); diff --git a/package.json b/package.json index 0cc493a..3f2d5df 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@hyperapi/core", - "version": "0.1.0-beta.6", + "version": "0.1.0-beta.7", "description": "This package is a core for HyperAPI project.", "publishConfig": { "access": "public" @@ -29,7 +29,7 @@ "valibot": "^0.24.1" }, "scripts": { - "test": "npm run test-node && bun test", + "test": "bun test && npm run test-node", "test-node": "NODE_OPTIONS=--experimental-vm-modules jest --forceExit", "build": "bun run build-cjs", "build-cjs": "bunx esbuild --bundle --platform=node --format=cjs --packages=external --outfile=dist/hyperapi-core.cjs src/main.js", diff --git a/src/main.test.js b/src/main.test.js index 0bc1078..063bff9 100644 --- a/src/main.test.js +++ b/src/main.test.js @@ -44,6 +44,19 @@ describe('HyperAPI', () => { ]); }); + test('method in directory', async () => { + const result = await request( + 'dir/nested', + ); + + expect(result).toStrictEqual([ + true, + { + ok: true, + }, + ]); + }); + test('correct request (async)', async () => { const result = await request( 'echo.async', @@ -136,4 +149,28 @@ describe('HyperAPI', () => { }, ]); }); + + test('invalid import path inside module', async () => { + const result = await request('error.import.path'); + + expect(result).toStrictEqual([ + false, + { + code: 3, + description: 'Internal error', + }, + ]); + }); + + test('invalid import field inside module', async () => { + const result = await request('error.import.field'); + + expect(result).toStrictEqual([ + false, + { + code: 3, + description: 'Internal error', + }, + ]); + }); }); diff --git a/src/request.js b/src/request.js index 9db9bc3..22488a1 100644 --- a/src/request.js +++ b/src/request.js @@ -7,6 +7,11 @@ import { HyperAPIUnknownMethodError } from './api-errors.js'; * @typedef {import('./response.js').default} HyperAPIResponse */ +const ERROR_CODES_MODULE_NOT_FOUND = new Set([ + 'MODULE_NOT_FOUND', + 'ERR_MODULE_NOT_FOUND', +]); + export class HyperAPIRequest extends Event { #data = new Map(); @@ -48,16 +53,29 @@ export class HyperAPIRequest extends Event { ]; for (const filename of filenames) { + const path = joinPath( + root, + filename, + ); + try { // eslint-disable-next-line no-await-in-loop - return await import( - joinPath( - root, - filename, - ) - ); + return await import(path); + } + catch (error) { + if ( + error.code === 'MODULE_NOT_FOUND' // node + || error.code === 'ERR_MODULE_NOT_FOUND' // bun + ) { + const path_error = error.moduleName ?? error.specifier; // node ?? bun + // skip error only if we cannot found the module itself + if (path === path_error) { + continue; + } + } + + throw error; } - catch {} } throw new HyperAPIUnknownMethodError(); diff --git a/test/api/dir/nested.js b/test/api/dir/nested.js new file mode 100644 index 0000000..f3f3acf --- /dev/null +++ b/test/api/dir/nested.js @@ -0,0 +1,8 @@ + +/* eslint-disable jsdoc/require-jsdoc */ + +export default function () { + return { + ok: true, + }; +} diff --git a/test/api/error.import.field.js b/test/api/error.import.field.js new file mode 100644 index 0000000..d2e6e28 --- /dev/null +++ b/test/api/error.import.field.js @@ -0,0 +1,8 @@ +/* eslint-disable jsdoc/require-jsdoc */ + +// eslint-disable-next-line import/named +import { foo } from '../validator.js'; + +export default function () { + return foo; +} diff --git a/test/api/error.import.path.js b/test/api/error.import.path.js new file mode 100644 index 0000000..8ba5243 --- /dev/null +++ b/test/api/error.import.path.js @@ -0,0 +1,8 @@ +/* eslint-disable jsdoc/require-jsdoc */ + +// eslint-disable-next-line import/no-unresolved, node/no-missing-import +import { foo } from '../invalid.js'; + +export default function () { + return foo; +} diff --git a/test/api/error.internal.js b/test/api/error.internal.js index ba6abd9..a45ad0a 100644 --- a/test/api/error.internal.js +++ b/test/api/error.internal.js @@ -1,5 +1,5 @@ /* eslint-disable jsdoc/require-jsdoc */ export default function () { - throw new TypeError('Invalid something given.'); + throw new TypeError('This is a test error inside API module.'); } From cc220749f478a9bac5e2d8ba4a8c8db845b1e26c Mon Sep 17 00:00:00 2001 From: Daniil Kirichenko Date: Fri, 5 Jan 2024 17:06:29 +0300 Subject: [PATCH 10/57] Module path fix --- dist/hyperapi-core.cjs | 2 +- package.json | 2 +- src/request.js | 12 ++++-------- 3 files changed, 6 insertions(+), 10 deletions(-) diff --git a/dist/hyperapi-core.cjs b/dist/hyperapi-core.cjs index 325a746..726d9e6 100644 --- a/dist/hyperapi-core.cjs +++ b/dist/hyperapi-core.cjs @@ -209,7 +209,7 @@ var HyperAPIRequest = class extends Event { return await import(path); } catch (error) { if (error.code === "MODULE_NOT_FOUND" || error.code === "ERR_MODULE_NOT_FOUND") { - const path_error = error.moduleName ?? error.specifier; + const path_error = error.moduleName ?? error.specifier ?? new URL(error.url).pathname; if (path === path_error) { continue; } diff --git a/package.json b/package.json index 3f2d5df..4836ac0 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@hyperapi/core", - "version": "0.1.0-beta.7", + "version": "0.1.0-beta.8", "description": "This package is a core for HyperAPI project.", "publishConfig": { "access": "public" diff --git a/src/request.js b/src/request.js index 22488a1..01e8593 100644 --- a/src/request.js +++ b/src/request.js @@ -1,17 +1,11 @@ -import { join as joinPath } from 'node:path'; - +import { join as joinPath } from 'node:path'; import { HyperAPIUnknownMethodError } from './api-errors.js'; /** * @typedef {import('./response.js').default} HyperAPIResponse */ -const ERROR_CODES_MODULE_NOT_FOUND = new Set([ - 'MODULE_NOT_FOUND', - 'ERR_MODULE_NOT_FOUND', -]); - export class HyperAPIRequest extends Event { #data = new Map(); @@ -67,7 +61,9 @@ export class HyperAPIRequest extends Event { error.code === 'MODULE_NOT_FOUND' // node || error.code === 'ERR_MODULE_NOT_FOUND' // bun ) { - const path_error = error.moduleName ?? error.specifier; // node ?? bun + const path_error = error.moduleName // node + ?? error.specifier // bun + ?? new URL(error.url).pathname; // node v20.10 in raw, not in jest's test env // skip error only if we cannot found the module itself if (path === path_error) { continue; From c79a9904c773829973e30a23347161d71c519b28 Mon Sep 17 00:00:00 2001 From: Daniil Kirichenko Date: Fri, 5 Jan 2024 17:09:44 +0300 Subject: [PATCH 11/57] Not its allowed to return `undefined` from API methods. --- dist/hyperapi-core.cjs | 2 ++ package.json | 2 +- src/response.js | 3 +++ 3 files changed, 6 insertions(+), 1 deletion(-) diff --git a/dist/hyperapi-core.cjs b/dist/hyperapi-core.cjs index 726d9e6..c55b5d8 100644 --- a/dist/hyperapi-core.cjs +++ b/dist/hyperapi-core.cjs @@ -263,6 +263,8 @@ var HyperAPIResponse = class { constructor(value) { if (value instanceof HyperAPIError) { this.error = value; + } else if (value === void 0) { + this.data = {}; } else if (value !== null && typeof value === "object" || Array.isArray(value)) { this.data = value; } else { diff --git a/package.json b/package.json index 4836ac0..5e54b45 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@hyperapi/core", - "version": "0.1.0-beta.8", + "version": "0.1.0-beta.9", "description": "This package is a core for HyperAPI project.", "publishConfig": { "access": "public" diff --git a/src/response.js b/src/response.js index 8a8446c..38a776c 100644 --- a/src/response.js +++ b/src/response.js @@ -10,6 +10,9 @@ export class HyperAPIResponse { if (value instanceof HyperAPIError) { this.error = value; } + else if (value === undefined) { + this.data = {}; + } else if ( (value !== null && typeof value === 'object') // object || Array.isArray(value) // array From a39dd252ea37cff1ad657a7e8a6f3718acdae2a1 Mon Sep 17 00:00:00 2001 From: Daniil Kirichenko Date: Sat, 18 May 2024 23:34:53 +0300 Subject: [PATCH 12/57] [0.1.0-beta.10] Root path update + now, by default, root path is 'hyper-api' located by the entrypoint script of the process --- dist/hyperapi-core.cjs | 3 ++- package.json | 5 +++-- src/main.js | 10 +++++++--- 3 files changed, 12 insertions(+), 6 deletions(-) diff --git a/dist/hyperapi-core.cjs b/dist/hyperapi-core.cjs index c55b5d8..6690667 100644 --- a/dist/hyperapi-core.cjs +++ b/dist/hyperapi-core.cjs @@ -291,6 +291,7 @@ var HyperAPIResponse = class { }; // src/main.js +var ENTRYPOINT_PATH = (0, import_node_path2.dirname)(process.argv[1]); var HyperAPI = class { #driver; #root; @@ -304,7 +305,7 @@ var HyperAPI = class { constructor({ driver, root = (0, import_node_path2.join)( - process.cwd(), + ENTRYPOINT_PATH, "hyper-api" ) }) { diff --git a/package.json b/package.json index 5e54b45..f9c58b5 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@hyperapi/core", - "version": "0.1.0-beta.9", + "version": "0.1.0-beta.10", "description": "This package is a core for HyperAPI project.", "publishConfig": { "access": "public" @@ -33,7 +33,8 @@ "test-node": "NODE_OPTIONS=--experimental-vm-modules jest --forceExit", "build": "bun run build-cjs", "build-cjs": "bunx esbuild --bundle --platform=node --format=cjs --packages=external --outfile=dist/hyperapi-core.cjs src/main.js", - "npm-publish": "bun run build && bun run eslint . && bun run test && npm publish --tag beta" + "npm-publish": "bun run build && bun run eslint . && bun run test && npm publish", + "npm-publish-beta": "bun run build && bun run eslint . && bun run test && npm publish --tag beta" }, "repository": { "type": "git", diff --git a/src/main.js b/src/main.js index 0309726..d7f1cf7 100644 --- a/src/main.js +++ b/src/main.js @@ -1,12 +1,16 @@ -import { join as joinPath } from 'node:path'; +import { + dirname, + join as joinPath } from 'node:path'; import { HyperAPIInternalError } from './api-errors.js'; import { HyperAPIDriver } from './driver.js'; import { HyperAPIError } from './error.js'; import { HyperAPIResponse } from './response.js'; +const ENTRYPOINT_PATH = dirname(process.argv[1]); + /** - * @typedef {import('./request.js').default} HyperAPIRequest + * @typedef {import('./request.js').HyperAPIRequest} HyperAPIRequest */ export class HyperAPI { @@ -23,7 +27,7 @@ export class HyperAPI { constructor({ driver, root = joinPath( - process.cwd(), + ENTRYPOINT_PATH, 'hyper-api', ), }) { From d24a4fb2254d8afc9616f3e9f87153da4ad01067 Mon Sep 17 00:00:00 2001 From: Daniil Kirichenko Date: Wed, 26 Jun 2024 15:24:51 +0300 Subject: [PATCH 13/57] [v0.2.0-beta.2] Types! + added types + removed methods get() and set() from HyperAPIRequest: drivers now should extend HyperAPIRequest to add custom fields + other minor changes --- .eslintrc.cjs | 45 +- .gitignore | 1 - dist/hyperapi.cjs | 387 --- dist/{hyperapi-core.cjs => main.cjs} | 267 +- package.json | 25 +- pnpm-lock.yaml | 3444 ++++++++++++++++++++++++++ src/driver.js | 33 +- src/error.js | 59 +- src/main.js | 142 +- src/main.test.js | 15 +- src/request.js | 100 +- src/response.js | 12 +- test/api/echo.async.js | 14 +- test/api/echo.js | 14 +- test/api/error.import.field.js | 8 +- test/api/error.import.path.js | 2 +- tsconfig.json | 18 + types/api-errors.d.ts | 49 + types/driver.d.ts | 9 + types/error.d.ts | 63 + types/main.d.ts | 41 + types/request.d.ts | 29 + types/response.d.ts | 24 + 23 files changed, 4100 insertions(+), 701 deletions(-) delete mode 100644 dist/hyperapi.cjs rename dist/{hyperapi-core.cjs => main.cjs} (68%) create mode 100644 pnpm-lock.yaml create mode 100644 tsconfig.json create mode 100644 types/api-errors.d.ts create mode 100644 types/driver.d.ts create mode 100644 types/error.d.ts create mode 100644 types/main.d.ts create mode 100644 types/request.d.ts create mode 100644 types/response.d.ts diff --git a/.eslintrc.cjs b/.eslintrc.cjs index bed5291..86fbad0 100644 --- a/.eslintrc.cjs +++ b/.eslintrc.cjs @@ -9,7 +9,6 @@ module.exports = { }, env: { es2022: true, - browser: true, node: true, }, extends: [ @@ -30,10 +29,19 @@ module.exports = { ], ignorePatterns: [ 'dist/**/*', + 'node_modules*/**/*', + 'types/**/*', ], rules: { - 'array-bracket-spacing': [ + 'arrow-body-style': [ 'error', + 'as-needed', + { + requireReturnForObjectLiteral: true, + }, + ], + 'array-bracket-spacing': [ + 'warn', 'always', { arraysInArrays: false, @@ -50,10 +58,29 @@ module.exports = { ], 'camelcase': 'off', 'capitalized-comments': 'off', + 'comma-dangle': [ + 'warn', + 'always-multiline', + ], + 'func-names': 'off', 'import/extensions': [ 'error', 'always', ], + 'import/order': [ + 'error', + { + groups: [ + [ + 'builtin', + 'external', + ], + 'internal', + 'parent', + 'sibling', + ], + }, + ], 'indent': [ 'error', 'tab', @@ -62,6 +89,7 @@ module.exports = { SwitchCase: 1, }, ], + 'jsdoc/require-jsdoc': 'error', 'new-cap': [ 'error', { @@ -79,8 +107,11 @@ module.exports = { }, }, ], + 'no-multiple-empty-lines': 'warn', 'no-promise-executor-return': 'off', + 'no-trailing-spaces': 'warn', 'no-unused-vars': 'warn', + 'node/no-missing-import': 'off', 'node/no-unpublished-import': 'off', 'object-curly-spacing': [ 'warn', @@ -109,6 +140,10 @@ module.exports = { 'error', 'single', ], + 'radix': [ + 'warn', + 'as-needed', + ], 'unicorn/no-null': 'off', 'unicorn/numeric-separators-style': [ 'warn', @@ -116,16 +151,14 @@ module.exports = { onlyIfContainsSeparator: true, }, ], - 'unicorn/prefer-ternary': [ - 'error', - 'only-single-line', - ], + 'unicorn/prefer-ternary': 'off', 'unicorn/prevent-abbreviations': [ 'error', { allowList: { args: true, env: true, + fn: true, }, }, ], diff --git a/.gitignore b/.gitignore index 74446f4..6675c5d 100644 --- a/.gitignore +++ b/.gitignore @@ -1,4 +1,3 @@ .DS_Store node_modules -pnpm-lock.yaml diff --git a/dist/hyperapi.cjs b/dist/hyperapi.cjs deleted file mode 100644 index 326dba6..0000000 --- a/dist/hyperapi.cjs +++ /dev/null @@ -1,387 +0,0 @@ -var __defProp = Object.defineProperty; -var __getOwnPropDesc = Object.getOwnPropertyDescriptor; -var __getOwnPropNames = Object.getOwnPropertyNames; -var __hasOwnProp = Object.prototype.hasOwnProperty; -var __export = (target, all) => { - for (var name in all) - __defProp(target, name, { get: all[name], enumerable: true }); -}; -var __copyProps = (to, from, except, desc) => { - if (from && typeof from === "object" || typeof from === "function") { - for (let key of __getOwnPropNames(from)) - if (!__hasOwnProp.call(to, key) && key !== except) - __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable }); - } - return to; -}; -var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod); - -// src/main.js -var main_exports = {}; -__export(main_exports, { - HyperAPIAuthorizationError: () => HyperAPIAuthorizationError, - HyperAPIBusyError: () => HyperAPIBusyError, - HyperAPICaptchaError: () => HyperAPICaptchaError, - HyperAPIConfirmationError: () => HyperAPIConfirmationError, - HyperAPIDriver: () => HyperAPIDriver, - HyperAPIError: () => HyperAPIError, - HyperAPIForbiddenError: () => HyperAPIForbiddenError, - HyperAPIInternalError: () => HyperAPIInternalError, - HyperAPIInvalidParametersError: () => HyperAPIInvalidParametersError, - HyperAPIMaintenanceError: () => HyperAPIMaintenanceError, - HyperAPIOTPError: () => HyperAPIOTPError, - HyperAPIObjectsLimitError: () => HyperAPIObjectsLimitError, - HyperAPIRateLimitError: () => HyperAPIRateLimitError, - HyperAPIRequest: () => HyperAPIRequest, - HyperAPIResponse: () => HyperAPIResponse, - HyperAPIUnknownMethodError: () => HyperAPIUnknownMethodError, - default: () => HyperAPI -}); -module.exports = __toCommonJS(main_exports); -var import_node_path2 = require("node:path"); - -// src/error.js -var HyperAPIError = class extends Error { - /** - * The error code. - * @type {number} - * @readonly - */ - code; - /** - * The error description. - * @type {string?} - * @readonly - */ - description = null; - /** - * The error data. - * @type {{[key: string]: *}?} - * @readonly - */ - data = null; - /** - * @param {{[key: string]: *}?} data The error data. Cannot contain "code" or "description" properties. - */ - constructor(data = null) { - super(); - if (data !== null && typeof data !== "object") { - throw new TypeError("Argument 0 must be an object or not be provided"); - } - if (data && ("code" in data || "description" in data)) { - throw new TypeError('Argument 0 must not contain "code" or "description" properties'); - } - this.data = data; - } - get message() { - return `${this.description ?? ""} (code ${this.code})`; - } - getResponse() { - const result = { - code: this.code - }; - if (typeof this.description === "string") { - result.description = this.description; - } - return { - ...result, - ...this.data - }; - } -}; - -// src/api-errors.js -var HyperAPIAuthorizationError = class extends HyperAPIError { - code = 1; - description = "Authorization error"; - httpStatus = 401; - // Unauthorized -}; -var HyperAPIInvalidParametersError = class extends HyperAPIError { - code = 2; - description = "One of the parameters specified was missing or invalid"; - httpStatus = 400; - // Bad Request -}; -var HyperAPIInternalError = class extends HyperAPIError { - code = 3; - description = "Internal error"; - httpStatus = 500; - // Internal Server Error -}; -var HyperAPIForbiddenError = class extends HyperAPIError { - code = 4; - description = "You do not have permission to perform this action"; - httpStatus = 403; - // Forbidden -}; -var HyperAPIUnknownMethodError = class extends HyperAPIError { - code = 5; - description = "Unknown method called"; - httpStatus = 404; - // Not Found -}; -var HyperAPIObjectsLimitError = class extends HyperAPIError { - code = 6; - description = "Too many objects requested"; - httpStatus = 400; - // Bad Request -}; -var HyperAPIRateLimitError = class extends HyperAPIError { - code = 7; - description = "Rate limit exceeded"; - httpStatus = 429; - // Too Many Requests -}; -var HyperAPICaptchaError = class extends HyperAPIError { - code = 8; - description = "Captcha required"; - httpStatus = 428; - // Precondition Required -}; -var HyperAPIBusyError = class extends HyperAPIError { - code = 10; - description = "Endpoint is busy"; - httpStatus = 503; - // Service Unavailable -}; -var HyperAPIConfirmationError = class extends HyperAPIError { - code = 11; - description = "Confirmation required"; - httpStatus = 409; - // Conflict -}; -var HyperAPIOTPError = class extends HyperAPIError { - code = 12; - description = "One-time password required"; - httpStatus = 401; - // Unauthorized -}; -var HyperAPIMaintenanceError = class extends HyperAPIError { - code = 13; - description = "Endpoint is in maintenance mode"; - httpStatus = 503; - // Service Unavailable -}; - -// src/request.js -var import_node_path = require("node:path"); -var HyperAPIRequest = class extends Event { - #data = /* @__PURE__ */ new Map(); - /** - * @param {string} module_path The relative path to the API method module. - * @param {Array<*>} args The arguments to pass to the API method. - */ - constructor(module_path, args) { - super("HyperAPIRequest"); - this.module_path = module_path; - this.args = args; - this.flags = {}; - } - /** - * @param {*} key The key to get. - * @returns {*} The value. - */ - get(key) { - return this.#data.get(key); - } - /** - * @param {*} key The key to set. - * @param {*} value The value to set. - */ - set(key, value) { - this.#data.set(key, value); - } - async _getModule(root) { - const filenames = [ - this.module_path, - `${this.module_path}.js`, - `${this.module_path}.mjs`, - `${this.module_path}.cjs`, - (0, import_node_path.join)(this.module_path, "index.js") - ]; - for (const filename of filenames) { - try { - return await import((0, import_node_path.join)( - root, - filename - )); - } catch { - } - } - throw new HyperAPIUnknownMethodError(); - } - #resolve; - #promise = new Promise((resolve) => { - this.#resolve = resolve; - }); - /** - * @returns {Promise} The response. - */ - wait() { - return this.#promise; - } - /** - * @param {HyperAPIResponse} response The response. - */ - _respondWith(response) { - this.#resolve(response); - } -}; - -// src/driver.js -var HyperAPIDriver = class extends EventTarget { - /** - * Processes a request and waits for the response. - * @async - * @param {HyperAPIRequest} request The HyperAPI request. - * @returns {Promise} The HyperAPI response. - */ - onRequest(request) { - if (request instanceof HyperAPIRequest !== true) { - throw new TypeError("Argument 0 must be an instance of HyperAPIRequest."); - } - this.dispatchEvent(request); - return request.wait(); - } -}; - -// src/response.js -var HyperAPIResponse = class { - /** - * Creates a HyperAPI response. - * @param {HyperAPIError|object|Array} value The error or the response value. - */ - constructor(value) { - if (value instanceof HyperAPIError) { - this.error = value; - } else if (value !== null && typeof value === "object" || Array.isArray(value)) { - this.data = value; - } else { - throw new TypeError("Argument 0 must be an instance of HyperAPIError or be an object or an array."); - } - } - /** - * @returns {boolean} Whether the response is successful. - * @readonly - */ - get is_success() { - return this.error === void 0; - } - /** - * Returns response as an object. For example, that can be used as the body of a HTTP response. - * @returns {{[key: string]: *}?} The response. - */ - getResponse() { - if (this.error) { - return this.error.getResponse(); - } - return this.data; - } -}; - -// src/main.js -var HyperAPI = class { - #driver; - #root; - #turnDriverOff; - /** - * Creates a HyperAPI instance. - * @param {object} options The options. - * @param {HyperAPIDriver} options.driver The HyperAPI driver. - * @param {string=} options.root The root directory for API methods modules. Defaults to "/hyper-api" inside the current working directory. - */ - constructor({ - driver, - root = (0, import_node_path2.join)( - process.cwd(), - "hyper-api" - ) - }) { - if (driver instanceof HyperAPIDriver !== true) { - throw new TypeError('Property "driver" must be an instance of HyperAPIDriver.'); - } - this.#driver = driver; - this.#root = root; - this.#setUpListener(); - } - #setUpListener() { - const handler = async (request) => { - try { - request._respondWith( - await this.#handleRequest(request) - ); - } catch (error) { - console.error("Unexpected error happened:"); - console.error(error); - process.exit(); - } - }; - this.#driver.addEventListener( - "HyperAPIRequest", - handler - ); - this.#turnDriverOff = () => { - this.#driver.removeEventListener( - "HyperAPIRequest", - handler - ); - }; - } - /** - * Processes a request and returns the response. - * @param {HyperAPIRequest} request The HyperAPI request. - * @returns {Promise} The HyperAPI response. - */ - async #handleRequest(request) { - try { - const response = await this.#useModule(request); - return new HyperAPIResponse(response); - } catch (error) { - if (error instanceof HyperAPIError !== true) { - console.error(error); - error = new HyperAPIInternalError(); - } - return new HyperAPIResponse(error); - } - } - async #useModule(request) { - const module2 = await request._getModule(this.#root); - if (module2.args instanceof OhMyPropsType) { - try { - request.args = module2.args.cast(request.args); - } catch (error) { - if (error instanceof OhMyPropsValueError) { - throw new HyperAPIInvalidParametersError(); - } - throw error; - } - } - return module2.default(request); - } - /** - * Destroys the HyperAPI instance. - */ - destroy() { - this.#turnDriverOff(); - } -}; -// Annotate the CommonJS export names for ESM import in node: -0 && (module.exports = { - HyperAPIAuthorizationError, - HyperAPIBusyError, - HyperAPICaptchaError, - HyperAPIConfirmationError, - HyperAPIDriver, - HyperAPIError, - HyperAPIForbiddenError, - HyperAPIInternalError, - HyperAPIInvalidParametersError, - HyperAPIMaintenanceError, - HyperAPIOTPError, - HyperAPIObjectsLimitError, - HyperAPIRateLimitError, - HyperAPIRequest, - HyperAPIResponse, - HyperAPIUnknownMethodError -}); diff --git a/dist/hyperapi-core.cjs b/dist/main.cjs similarity index 68% rename from dist/hyperapi-core.cjs rename to dist/main.cjs index 6690667..4364b1d 100644 --- a/dist/hyperapi-core.cjs +++ b/dist/main.cjs @@ -38,7 +38,7 @@ __export(main_exports, { HyperAPIUnknownMethodError: () => HyperAPIUnknownMethodError }); module.exports = __toCommonJS(main_exports); -var import_node_path2 = require("node:path"); +var import_node_path = require("node:path"); // src/error.js var HyperAPIError = class extends Error { @@ -56,26 +56,35 @@ var HyperAPIError = class extends Error { description = null; /** * The error data. - * @type {{[key: string]: *}?} + * @type {{[key: string]: any}} * @readonly */ - data = null; + data; + /** @type {number?} */ + httpStatus; + /** @type {Record?} */ + httpHeaders; /** - * @param {{[key: string]: *}?} data The error data. Cannot contain "code" or "description" properties. + * @param {{[key: string]: any}} [data] The error data. */ - constructor(data = null) { + constructor(data) { super(); - if (data !== null && typeof data !== "object") { + if (data !== null && typeof data === "object") { + this.data = data; + } else if (data !== void 0) { throw new TypeError("Argument 0 must be an object or not be provided"); } - if (data && ("code" in data || "description" in data)) { - throw new TypeError('Argument 0 must not contain "code" or "description" properties'); - } - this.data = data; } + /** + * @returns {string} - + */ get message() { return `${this.description ?? ""} (code ${this.code})`; } + /** + * Creates response object. + * @returns {HyperAPIErrorResponse} - + */ getResponse() { const result = { code: this.code @@ -83,10 +92,10 @@ var HyperAPIError = class extends Error { if (typeof this.description === "string") { result.description = this.description; } - return { - ...result, - ...this.data - }; + if (this.data) { + result.data = this.data; + } + return result; } }; @@ -165,102 +174,46 @@ var HyperAPIMaintenanceError = class extends HyperAPIError { }; // src/request.js -var import_node_path = require("node:path"); +var import_node_crypto = require("node:crypto"); var HyperAPIRequest = class extends Event { - #data = /* @__PURE__ */ new Map(); /** - * @param {string} module_path The relative path to the API method module. - * @param {Array<*>} args The arguments to pass to the API method. - */ - constructor(module_path, args) { - super("HyperAPIRequest"); - this.module_path = module_path; - this.args = args; - this.flags = {}; - } - /** - * @param {*} key The key to get. - * @returns {*} The value. - */ - get(key) { - return this.#data.get(key); - } - /** - * @param {*} key The key to set. - * @param {*} value The value to set. + * The unique identifier for this request. + * @type {string} + * @readonly */ - set(key, value) { - this.#data.set(key, value); - } - async _getModule(root) { - const filenames = [ - this.module_path, - `${this.module_path}.js`, - `${this.module_path}.mjs`, - `${this.module_path}.cjs`, - (0, import_node_path.join)(this.module_path, "index.js") - ]; - for (const filename of filenames) { - const path = (0, import_node_path.join)( - root, - filename - ); - try { - return await import(path); - } catch (error) { - if (error.code === "MODULE_NOT_FOUND" || error.code === "ERR_MODULE_NOT_FOUND") { - const path_error = error.moduleName ?? error.specifier ?? new URL(error.url).pathname; - if (path === path_error) { - continue; - } - } - throw error; - } - } - throw new HyperAPIUnknownMethodError(); - } - #resolve; - #promise = new Promise((resolve) => { - this.#resolve = resolve; - }); + response_event_name = "response:" + (0, import_node_crypto.randomUUID)(); /** - * @returns {Promise} The response. + * The relative path to the JavaScript module that contains requested API method. + * @type {string} + * @readonly */ - wait() { - return this.#promise; - } + module_path; /** - * @param {HyperAPIResponse} response The response. + * Request arguments to pass to the API method. + * @type {HyperAPIRequestArgs} + * @readonly */ - _respondWith(response) { - this.#resolve(response); - } -}; - -// src/driver.js -var HyperAPIDriver = class extends EventTarget { + args; /** - * Processes a request and waits for the response. - * @async - * @param {HyperAPIRequest} request The HyperAPI request. - * @returns {Promise} The HyperAPI response. + * @param {string} module_path The relative path to the API method module. + * @param {HyperAPIRequestArgs} args The arguments to pass to the API method. */ - onRequest(request) { - if (request instanceof HyperAPIRequest !== true) { - throw new TypeError("Argument 0 must be an instance of HyperAPIRequest."); - } - this.dispatchEvent(request); - return request.wait(); + constructor(module_path, args) { + super("request"); + this.module_path = module_path; + this.args = args; } }; // src/response.js -var HyperAPIResponse = class { +var HyperAPIResponse = class extends Event { /** * Creates a HyperAPI response. - * @param {HyperAPIError|object|Array} value The error or the response value. + * @param {HyperAPIRequest} request The request. + * @param {HyperAPIError | Record | any[]} value The error or the response value. */ - constructor(value) { + constructor(request, value) { + super(request.response_event_name); if (value instanceof HyperAPIError) { this.error = value; } else if (value === void 0) { @@ -290,21 +243,49 @@ var HyperAPIResponse = class { } }; +// src/driver.js +var HyperAPIDriver = class extends EventTarget { + /** + * @param {HyperAPIRequest} request - + * @returns {Promise} - + */ + async processRequest(request) { + const promise = new Promise((resolve) => { + this.addEventListener( + request.response_event_name, + (response) => { + if (response instanceof HyperAPIResponse) { + resolve(response); + } + }, + { + once: true + } + ); + }); + this.dispatchEvent(request); + return promise; + } +}; + // src/main.js -var ENTRYPOINT_PATH = (0, import_node_path2.dirname)(process.argv[1]); +var ENTRYPOINT_PATH = (0, import_node_path.dirname)(process.argv[1]); var HyperAPI = class { + /** @type {HyperAPIDriver} The HyperAPI driver. */ #driver; + /** @type {string} The root directory for API methods modules. */ #root; - #turnDriverOff; + /** @type {function(HyperAPIRequest): void} Handles a request. */ + #requestHandler; /** * Creates a HyperAPI instance. * @param {object} options The options. * @param {HyperAPIDriver} options.driver The HyperAPI driver. - * @param {string=} options.root The root directory for API methods modules. Defaults to "/hyper-api" inside the current working directory. + * @param {string} [options.root] The root directory for API methods modules. Default: `hyper-api` directory alongside the entrypoint script. */ constructor({ driver, - root = (0, import_node_path2.join)( + root = (0, import_node_path.join)( ENTRYPOINT_PATH, "hyper-api" ) @@ -313,31 +294,33 @@ var HyperAPI = class { throw new TypeError('Property "driver" must be an instance of HyperAPIDriver.'); } this.#driver = driver; - this.#root = root; - this.#setUpListener(); - } - #setUpListener() { - const handler = async (request) => { + this.#requestHandler = async (request) => { try { - request._respondWith( - await this.#handleRequest(request) - ); + const response = await this.#handleRequest(request); + this.#driver.dispatchEvent(response); } catch (error) { console.error("Unexpected error happened:"); console.error(error); - process.exit(); + console.error("This error should not have reached this point."); + console.error("This is probably a bug in the HyperAPI driver you are using or in the HyperAPI itself."); + console.error("Now exiting the process."); + process.exit(1); } }; this.#driver.addEventListener( - "HyperAPIRequest", - handler + "request", + this.#requestHandler + ); + this.#root = root; + } + /** + * Removes the request event listener from the driver. + */ + #turnDriverOff() { + this.#driver.removeEventListener( + "request", + this.#requestHandler ); - this.#turnDriverOff = () => { - this.#driver.removeEventListener( - "HyperAPIRequest", - handler - ); - }; } /** * Processes a request and returns the response. @@ -346,18 +329,64 @@ var HyperAPI = class { */ async #handleRequest(request) { try { - const response = await this.#useModule(request); - return new HyperAPIResponse(response); + const response_data = await this.#useModule(request); + return new HyperAPIResponse( + request, + response_data + ); } catch (error) { if (error instanceof HyperAPIError !== true) { console.error(error); error = new HyperAPIInternalError(); } - return new HyperAPIResponse(error); + return new HyperAPIResponse( + request, + error + ); + } + } + /** + * Processes a request and returns the response. + * @param {HyperAPIRequest} request The HyperAPI request. + * @returns {Promise} The HyperAPI response. + */ + async #getModule(request) { + const filenames = [ + request.module_path, + `${request.module_path}.js`, + `${request.module_path}.mjs`, + `${request.module_path}.cjs`, + (0, import_node_path.join)(request.module_path, "index.js") + ]; + for (const filename of filenames) { + const path = (0, import_node_path.join)( + this.#root, + filename + ); + try { + return await import(path); + } catch (error) { + if (error.code === "MODULE_NOT_FOUND" || error.code === "ERR_MODULE_NOT_FOUND") { + const path_error = error.moduleName ?? error.specifier ?? new URL(error.url).pathname; + if (path === path_error) { + continue; + } + } + if (error instanceof Error && error.message.startsWith(`Failed to load url ${path} `)) { + continue; + } + throw error; + } } + throw new HyperAPIUnknownMethodError(); } + /** + * Processes a request and returns the response. + * @param {HyperAPIRequest} request The HyperAPI request. + * @returns {Promise} The HyperAPI response. + */ async #useModule(request) { - const module2 = await request._getModule(this.#root); + const module2 = await this.#getModule(request); if (typeof module2.argsValidator === "function") { request.args = await module2.argsValidator(request.args); } diff --git a/package.json b/package.json index f9c58b5..769a3b0 100644 --- a/package.json +++ b/package.json @@ -1,16 +1,17 @@ { "name": "@hyperapi/core", - "version": "0.1.0-beta.10", - "description": "This package is a core for HyperAPI project.", + "version": "0.2.0-beta.2", + "description": "Core package of the HyperAPI project.", "publishConfig": { "access": "public" }, "type": "module", "main": "src/main.js", + "types": "types/main.d.ts", "exports": { ".": { "import": "./src/main.js", - "require": "./dist/hyperapi-core.cjs" + "require": "./dist/main.cjs" } }, "engines": { @@ -18,6 +19,7 @@ }, "devDependencies": { "@babel/eslint-parser": "7.21.8", + "@types/node": "^20.14.8", "eslint": "8.41.0", "eslint-config-xo": "0.43.1", "eslint-plugin-import": "2.27.5", @@ -25,16 +27,17 @@ "eslint-plugin-node": "11.1.0", "eslint-plugin-promise": "6.1.1", "eslint-plugin-unicorn": "47.0.0", - "jest": "^29.7.0", - "valibot": "^0.24.1" + "valibot": "^0.35", + "vitest": "^1.6" }, "scripts": { - "test": "bun test && npm run test-node", - "test-node": "NODE_OPTIONS=--experimental-vm-modules jest --forceExit", - "build": "bun run build-cjs", - "build-cjs": "bunx esbuild --bundle --platform=node --format=cjs --packages=external --outfile=dist/hyperapi-core.cjs src/main.js", - "npm-publish": "bun run build && bun run eslint . && bun run test && npm publish", - "npm-publish-beta": "bun run build && bun run eslint . && bun run test && npm publish --tag beta" + "test": "npm run test:vitest && bun test --coverage", + "test:vitest": "vitest run --no-file-parallelism", + "build": "bun run build:types && bun run build:cjs", + "build:cjs": "bunx esbuild --bundle --platform=node --format=cjs --packages=external --outfile=dist/main.cjs src/main.js", + "build:types": "bunx tsc --skipLibCheck --declaration --emitDeclarationOnly --outDir types", + "publish:npm": "pnpm i && bun run build && eslint . && bunx tsc --skipLibCheck --noemit && bun run test && npm publish", + "publish:npm:beta": "bun run publish:npm --tag beta" }, "repository": { "type": "git", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml new file mode 100644 index 0000000..22aab0c --- /dev/null +++ b/pnpm-lock.yaml @@ -0,0 +1,3444 @@ +lockfileVersion: '9.0' + +settings: + autoInstallPeers: true + excludeLinksFromLockfile: false + +importers: + + .: + devDependencies: + '@babel/eslint-parser': + specifier: 7.21.8 + version: 7.21.8(@babel/core@7.24.7)(eslint@8.41.0) + '@types/node': + specifier: ^20.14.8 + version: 20.14.8 + eslint: + specifier: 8.41.0 + version: 8.41.0 + eslint-config-xo: + specifier: 0.43.1 + version: 0.43.1(eslint@8.41.0) + eslint-plugin-import: + specifier: 2.27.5 + version: 2.27.5(eslint@8.41.0) + eslint-plugin-jsdoc: + specifier: 46.5.0 + version: 46.5.0(eslint@8.41.0) + eslint-plugin-node: + specifier: 11.1.0 + version: 11.1.0(eslint@8.41.0) + eslint-plugin-promise: + specifier: 6.1.1 + version: 6.1.1(eslint@8.41.0) + eslint-plugin-unicorn: + specifier: 47.0.0 + version: 47.0.0(eslint@8.41.0) + valibot: + specifier: ^0.35 + version: 0.35.0 + vitest: + specifier: ^1.6 + version: 1.6.0(@types/node@20.14.8) + +packages: + + '@ampproject/remapping@2.3.0': + resolution: {integrity: sha512-30iZtAPgz+LTIYoeivqYo853f02jBYSd5uGnGpkFV0M3xOt9aN73erkgYAmZU43x4VfqcnLxW9Kpg3R5LC4YYw==} + engines: {node: '>=6.0.0'} + + '@babel/code-frame@7.24.7': + resolution: {integrity: sha512-BcYH1CVJBO9tvyIZ2jVeXgSIMvGZ2FDRvDdOIVQyuklNKSsx+eppDEBq/g47Ayw+RqNFE+URvOShmf+f/qwAlA==} + engines: {node: '>=6.9.0'} + + '@babel/compat-data@7.24.7': + resolution: {integrity: sha512-qJzAIcv03PyaWqxRgO4mSU3lihncDT296vnyuE2O8uA4w3UHWI4S3hgeZd1L8W1Bft40w9JxJ2b412iDUFFRhw==} + engines: {node: '>=6.9.0'} + + '@babel/core@7.24.7': + resolution: {integrity: sha512-nykK+LEK86ahTkX/3TgauT0ikKoNCfKHEaZYTUVupJdTLzGNvrblu4u6fa7DhZONAltdf8e662t/abY8idrd/g==} + engines: {node: '>=6.9.0'} + + '@babel/eslint-parser@7.21.8': + resolution: {integrity: sha512-HLhI+2q+BP3sf78mFUZNCGc10KEmoUqtUT1OCdMZsN+qr4qFeLUod62/zAnF3jNQstwyasDkZnVXwfK2Bml7MQ==} + engines: {node: ^10.13.0 || ^12.13.0 || >=14.0.0} + peerDependencies: + '@babel/core': '>=7.11.0' + eslint: ^7.5.0 || ^8.0.0 + + '@babel/generator@7.24.7': + resolution: {integrity: sha512-oipXieGC3i45Y1A41t4tAqpnEZWgB/lC6Ehh6+rOviR5XWpTtMmLN+fGjz9vOiNRt0p6RtO6DtD0pdU3vpqdSA==} + engines: {node: '>=6.9.0'} + + '@babel/helper-compilation-targets@7.24.7': + resolution: {integrity: sha512-ctSdRHBi20qWOfy27RUb4Fhp07KSJ3sXcuSvTrXrc4aG8NSYDo1ici3Vhg9bg69y5bj0Mr1lh0aeEgTvc12rMg==} + engines: {node: '>=6.9.0'} + + '@babel/helper-environment-visitor@7.24.7': + resolution: {integrity: sha512-DoiN84+4Gnd0ncbBOM9AZENV4a5ZiL39HYMyZJGZ/AZEykHYdJw0wW3kdcsh9/Kn+BRXHLkkklZ51ecPKmI1CQ==} + engines: {node: '>=6.9.0'} + + '@babel/helper-function-name@7.24.7': + resolution: {integrity: sha512-FyoJTsj/PEUWu1/TYRiXTIHc8lbw+TDYkZuoE43opPS5TrI7MyONBE1oNvfguEXAD9yhQRrVBnXdXzSLQl9XnA==} + engines: {node: '>=6.9.0'} + + '@babel/helper-hoist-variables@7.24.7': + resolution: {integrity: sha512-MJJwhkoGy5c4ehfoRyrJ/owKeMl19U54h27YYftT0o2teQ3FJ3nQUf/I3LlJsX4l3qlw7WRXUmiyajvHXoTubQ==} + engines: {node: '>=6.9.0'} + + '@babel/helper-module-imports@7.24.7': + resolution: {integrity: sha512-8AyH3C+74cgCVVXow/myrynrAGv+nTVg5vKu2nZph9x7RcRwzmh0VFallJuFTZ9mx6u4eSdXZfcOzSqTUm0HCA==} + engines: {node: '>=6.9.0'} + + '@babel/helper-module-transforms@7.24.7': + resolution: {integrity: sha512-1fuJEwIrp+97rM4RWdO+qrRsZlAeL1lQJoPqtCYWv0NL115XM93hIH4CSRln2w52SqvmY5hqdtauB6QFCDiZNQ==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0 + + '@babel/helper-simple-access@7.24.7': + resolution: {integrity: sha512-zBAIvbCMh5Ts+b86r/CjU+4XGYIs+R1j951gxI3KmmxBMhCg4oQMsv6ZXQ64XOm/cvzfU1FmoCyt6+owc5QMYg==} + engines: {node: '>=6.9.0'} + + '@babel/helper-split-export-declaration@7.24.7': + resolution: {integrity: sha512-oy5V7pD+UvfkEATUKvIjvIAH/xCzfsFVw7ygW2SI6NClZzquT+mwdTfgfdbUiceh6iQO0CHtCPsyze/MZ2YbAA==} + engines: {node: '>=6.9.0'} + + '@babel/helper-string-parser@7.24.7': + resolution: {integrity: sha512-7MbVt6xrwFQbunH2DNQsAP5sTGxfqQtErvBIvIMi6EQnbgUOuVYanvREcmFrOPhoXBrTtjhhP+lW+o5UfK+tDg==} + engines: {node: '>=6.9.0'} + + '@babel/helper-validator-identifier@7.24.7': + resolution: {integrity: sha512-rR+PBcQ1SMQDDyF6X0wxtG8QyLCgUB0eRAGguqRLfkCA87l7yAP7ehq8SNj96OOGTO8OBV70KhuFYcIkHXOg0w==} + engines: {node: '>=6.9.0'} + + '@babel/helper-validator-option@7.24.7': + resolution: {integrity: sha512-yy1/KvjhV/ZCL+SM7hBrvnZJ3ZuT9OuZgIJAGpPEToANvc3iM6iDvBnRjtElWibHU6n8/LPR/EjX9EtIEYO3pw==} + engines: {node: '>=6.9.0'} + + '@babel/helpers@7.24.7': + resolution: {integrity: sha512-NlmJJtvcw72yRJRcnCmGvSi+3jDEg8qFu3z0AFoymmzLx5ERVWyzd9kVXr7Th9/8yIJi2Zc6av4Tqz3wFs8QWg==} + engines: {node: '>=6.9.0'} + + '@babel/highlight@7.24.7': + resolution: {integrity: sha512-EStJpq4OuY8xYfhGVXngigBJRWxftKX9ksiGDnmlY3o7B/V7KIAc9X4oiK87uPJSc/vs5L869bem5fhZa8caZw==} + engines: {node: '>=6.9.0'} + + '@babel/parser@7.24.7': + resolution: {integrity: sha512-9uUYRm6OqQrCqQdG1iCBwBPZgN8ciDBro2nIOFaiRz1/BCxaI7CNvQbDHvsArAC7Tw9Hda/B3U+6ui9u4HWXPw==} + engines: {node: '>=6.0.0'} + hasBin: true + + '@babel/template@7.24.7': + resolution: {integrity: sha512-jYqfPrU9JTF0PmPy1tLYHW4Mp4KlgxJD9l2nP9fD6yT/ICi554DmrWBAEYpIelzjHf1msDP3PxJIRt/nFNfBig==} + engines: {node: '>=6.9.0'} + + '@babel/traverse@7.24.7': + resolution: {integrity: sha512-yb65Ed5S/QAcewNPh0nZczy9JdYXkkAbIsEo+P7BE7yO3txAY30Y/oPa3QkQ5It3xVG2kpKMg9MsdxZaO31uKA==} + engines: {node: '>=6.9.0'} + + '@babel/types@7.24.7': + resolution: {integrity: sha512-XEFXSlxiG5td2EJRe8vOmRbaXVgfcBlszKujvVmWIK/UpywWljQCfzAv3RQCGujWQ1RD4YYWEAqDXfuJiy8f5Q==} + engines: {node: '>=6.9.0'} + + '@es-joy/jsdoccomment@0.40.1': + resolution: {integrity: sha512-YORCdZSusAlBrFpZ77pJjc5r1bQs5caPWtAu+WWmiSo+8XaUzseapVrfAtiRFbQWnrBxxLLEwF6f6ZG/UgCQCg==} + engines: {node: '>=16'} + + '@esbuild/aix-ppc64@0.21.5': + resolution: {integrity: sha512-1SDgH6ZSPTlggy1yI6+Dbkiz8xzpHJEVAlF/AM1tHPLsf5STom9rwtjE4hKAF20FfXXNTFqEYXyJNWh1GiZedQ==} + engines: {node: '>=12'} + cpu: [ppc64] + os: [aix] + + '@esbuild/android-arm64@0.21.5': + resolution: {integrity: sha512-c0uX9VAUBQ7dTDCjq+wdyGLowMdtR/GoC2U5IYk/7D1H1JYC0qseD7+11iMP2mRLN9RcCMRcjC4YMclCzGwS/A==} + engines: {node: '>=12'} + cpu: [arm64] + os: [android] + + '@esbuild/android-arm@0.21.5': + resolution: {integrity: sha512-vCPvzSjpPHEi1siZdlvAlsPxXl7WbOVUBBAowWug4rJHb68Ox8KualB+1ocNvT5fjv6wpkX6o/iEpbDrf68zcg==} + engines: {node: '>=12'} + cpu: [arm] + os: [android] + + '@esbuild/android-x64@0.21.5': + resolution: {integrity: sha512-D7aPRUUNHRBwHxzxRvp856rjUHRFW1SdQATKXH2hqA0kAZb1hKmi02OpYRacl0TxIGz/ZmXWlbZgjwWYaCakTA==} + engines: {node: '>=12'} + cpu: [x64] + os: [android] + + '@esbuild/darwin-arm64@0.21.5': + resolution: {integrity: sha512-DwqXqZyuk5AiWWf3UfLiRDJ5EDd49zg6O9wclZ7kUMv2WRFr4HKjXp/5t8JZ11QbQfUS6/cRCKGwYhtNAY88kQ==} + engines: {node: '>=12'} + cpu: [arm64] + os: [darwin] + + '@esbuild/darwin-x64@0.21.5': + resolution: {integrity: sha512-se/JjF8NlmKVG4kNIuyWMV/22ZaerB+qaSi5MdrXtd6R08kvs2qCN4C09miupktDitvh8jRFflwGFBQcxZRjbw==} + engines: {node: '>=12'} + cpu: [x64] + os: [darwin] + + '@esbuild/freebsd-arm64@0.21.5': + resolution: {integrity: sha512-5JcRxxRDUJLX8JXp/wcBCy3pENnCgBR9bN6JsY4OmhfUtIHe3ZW0mawA7+RDAcMLrMIZaf03NlQiX9DGyB8h4g==} + engines: {node: '>=12'} + cpu: [arm64] + os: [freebsd] + + '@esbuild/freebsd-x64@0.21.5': + resolution: {integrity: sha512-J95kNBj1zkbMXtHVH29bBriQygMXqoVQOQYA+ISs0/2l3T9/kj42ow2mpqerRBxDJnmkUDCaQT/dfNXWX/ZZCQ==} + engines: {node: '>=12'} + cpu: [x64] + os: [freebsd] + + '@esbuild/linux-arm64@0.21.5': + resolution: {integrity: sha512-ibKvmyYzKsBeX8d8I7MH/TMfWDXBF3db4qM6sy+7re0YXya+K1cem3on9XgdT2EQGMu4hQyZhan7TeQ8XkGp4Q==} + engines: {node: '>=12'} + cpu: [arm64] + os: [linux] + + '@esbuild/linux-arm@0.21.5': + resolution: {integrity: sha512-bPb5AHZtbeNGjCKVZ9UGqGwo8EUu4cLq68E95A53KlxAPRmUyYv2D6F0uUI65XisGOL1hBP5mTronbgo+0bFcA==} + engines: {node: '>=12'} + cpu: [arm] + os: [linux] + + '@esbuild/linux-ia32@0.21.5': + resolution: {integrity: sha512-YvjXDqLRqPDl2dvRODYmmhz4rPeVKYvppfGYKSNGdyZkA01046pLWyRKKI3ax8fbJoK5QbxblURkwK/MWY18Tg==} + engines: {node: '>=12'} + cpu: [ia32] + os: [linux] + + '@esbuild/linux-loong64@0.21.5': + resolution: {integrity: sha512-uHf1BmMG8qEvzdrzAqg2SIG/02+4/DHB6a9Kbya0XDvwDEKCoC8ZRWI5JJvNdUjtciBGFQ5PuBlpEOXQj+JQSg==} + engines: {node: '>=12'} + cpu: [loong64] + os: [linux] + + '@esbuild/linux-mips64el@0.21.5': + resolution: {integrity: sha512-IajOmO+KJK23bj52dFSNCMsz1QP1DqM6cwLUv3W1QwyxkyIWecfafnI555fvSGqEKwjMXVLokcV5ygHW5b3Jbg==} + engines: {node: '>=12'} + cpu: [mips64el] + os: [linux] + + '@esbuild/linux-ppc64@0.21.5': + resolution: {integrity: sha512-1hHV/Z4OEfMwpLO8rp7CvlhBDnjsC3CttJXIhBi+5Aj5r+MBvy4egg7wCbe//hSsT+RvDAG7s81tAvpL2XAE4w==} + engines: {node: '>=12'} + cpu: [ppc64] + os: [linux] + + '@esbuild/linux-riscv64@0.21.5': + resolution: {integrity: sha512-2HdXDMd9GMgTGrPWnJzP2ALSokE/0O5HhTUvWIbD3YdjME8JwvSCnNGBnTThKGEB91OZhzrJ4qIIxk/SBmyDDA==} + engines: {node: '>=12'} + cpu: [riscv64] + os: [linux] + + '@esbuild/linux-s390x@0.21.5': + resolution: {integrity: sha512-zus5sxzqBJD3eXxwvjN1yQkRepANgxE9lgOW2qLnmr8ikMTphkjgXu1HR01K4FJg8h1kEEDAqDcZQtbrRnB41A==} + engines: {node: '>=12'} + cpu: [s390x] + os: [linux] + + '@esbuild/linux-x64@0.21.5': + resolution: {integrity: sha512-1rYdTpyv03iycF1+BhzrzQJCdOuAOtaqHTWJZCWvijKD2N5Xu0TtVC8/+1faWqcP9iBCWOmjmhoH94dH82BxPQ==} + engines: {node: '>=12'} + cpu: [x64] + os: [linux] + + '@esbuild/netbsd-x64@0.21.5': + resolution: {integrity: sha512-Woi2MXzXjMULccIwMnLciyZH4nCIMpWQAs049KEeMvOcNADVxo0UBIQPfSmxB3CWKedngg7sWZdLvLczpe0tLg==} + engines: {node: '>=12'} + cpu: [x64] + os: [netbsd] + + '@esbuild/openbsd-x64@0.21.5': + resolution: {integrity: sha512-HLNNw99xsvx12lFBUwoT8EVCsSvRNDVxNpjZ7bPn947b8gJPzeHWyNVhFsaerc0n3TsbOINvRP2byTZ5LKezow==} + engines: {node: '>=12'} + cpu: [x64] + os: [openbsd] + + '@esbuild/sunos-x64@0.21.5': + resolution: {integrity: sha512-6+gjmFpfy0BHU5Tpptkuh8+uw3mnrvgs+dSPQXQOv3ekbordwnzTVEb4qnIvQcYXq6gzkyTnoZ9dZG+D4garKg==} + engines: {node: '>=12'} + cpu: [x64] + os: [sunos] + + '@esbuild/win32-arm64@0.21.5': + resolution: {integrity: sha512-Z0gOTd75VvXqyq7nsl93zwahcTROgqvuAcYDUr+vOv8uHhNSKROyU961kgtCD1e95IqPKSQKH7tBTslnS3tA8A==} + engines: {node: '>=12'} + cpu: [arm64] + os: [win32] + + '@esbuild/win32-ia32@0.21.5': + resolution: {integrity: sha512-SWXFF1CL2RVNMaVs+BBClwtfZSvDgtL//G/smwAc5oVK/UPu2Gu9tIaRgFmYFFKrmg3SyAjSrElf0TiJ1v8fYA==} + engines: {node: '>=12'} + cpu: [ia32] + os: [win32] + + '@esbuild/win32-x64@0.21.5': + resolution: {integrity: sha512-tQd/1efJuzPC6rCFwEvLtci/xNFcTZknmXs98FYDfGE4wP9ClFV98nyKrzJKVPMhdDnjzLhdUyMX4PsQAPjwIw==} + engines: {node: '>=12'} + cpu: [x64] + os: [win32] + + '@eslint-community/eslint-utils@4.4.0': + resolution: {integrity: sha512-1/sA4dwrzBAyeUoQ6oxahHKmrZvsnLCg4RfxW3ZFGGmQkSNQPFNLV9CUEFQP1x9EYXHTo5p6xdhZM1Ne9p/AfA==} + engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} + peerDependencies: + eslint: ^6.0.0 || ^7.0.0 || >=8.0.0 + + '@eslint-community/regexpp@4.10.1': + resolution: {integrity: sha512-Zm2NGpWELsQAD1xsJzGQpYfvICSsFkEpU0jxBjfdC6uNEWXcHnfs9hScFWtXVDVl+rBQJGrl4g1vcKIejpH9dA==} + engines: {node: ^12.0.0 || ^14.0.0 || >=16.0.0} + + '@eslint/eslintrc@2.1.4': + resolution: {integrity: sha512-269Z39MS6wVJtsoUl10L60WdkhJVdPG24Q4eZTH3nnF6lpvSShEK3wQjDX9JRWAUPvPh7COouPpU9IrqaZFvtQ==} + engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} + + '@eslint/js@8.41.0': + resolution: {integrity: sha512-LxcyMGxwmTh2lY9FwHPGWOHmYFCZvbrFCBZL4FzSSsxsRPuhrYUg/49/0KDfW8tnIEaEHtfmn6+NPN+1DqaNmA==} + engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} + + '@humanwhocodes/config-array@0.11.14': + resolution: {integrity: sha512-3T8LkOmg45BV5FICb15QQMsyUSWrQ8AygVfC7ZG32zOalnqrilm018ZVCw0eapXux8FtA33q8PSRSstjee3jSg==} + engines: {node: '>=10.10.0'} + deprecated: Use @eslint/config-array instead + + '@humanwhocodes/module-importer@1.0.1': + resolution: {integrity: sha512-bxveV4V8v5Yb4ncFTT3rPSgZBOpCkjfK0y4oVVVJwIuDVBRMDXrPyXRL988i5ap9m9bnyEEjWfm5WkBmtffLfA==} + engines: {node: '>=12.22'} + + '@humanwhocodes/object-schema@2.0.3': + resolution: {integrity: sha512-93zYdMES/c1D69yZiKDBj0V24vqNzB/koF26KPaagAfd3P/4gUlh3Dys5ogAK+Exi9QyzlD8x/08Zt7wIKcDcA==} + deprecated: Use @eslint/object-schema instead + + '@jest/schemas@29.6.3': + resolution: {integrity: sha512-mo5j5X+jIZmJQveBKeS/clAueipV7KgiX1vMgCxam1RNYiqE1w62n0/tJJnHtjW8ZHcQco5gY85jA3mi0L+nSA==} + engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} + + '@jridgewell/gen-mapping@0.3.5': + resolution: {integrity: sha512-IzL8ZoEDIBRWEzlCcRhOaCupYyN5gdIK+Q6fbFdPDg6HqX6jpkItn7DFIpW9LQzXG6Df9sA7+OKnq0qlz/GaQg==} + engines: {node: '>=6.0.0'} + + '@jridgewell/resolve-uri@3.1.2': + resolution: {integrity: sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw==} + engines: {node: '>=6.0.0'} + + '@jridgewell/set-array@1.2.1': + resolution: {integrity: sha512-R8gLRTZeyp03ymzP/6Lil/28tGeGEzhx1q2k703KGWRAI1VdvPIXdG70VJc2pAMw3NA6JKL5hhFu1sJX0Mnn/A==} + engines: {node: '>=6.0.0'} + + '@jridgewell/sourcemap-codec@1.4.15': + resolution: {integrity: sha512-eF2rxCRulEKXHTRiDrDy6erMYWqNw4LPdQ8UQA4huuxaQsVeRPFl2oM8oDGxMFhJUWZf9McpLtJasDDZb/Bpeg==} + + '@jridgewell/trace-mapping@0.3.25': + resolution: {integrity: sha512-vNk6aEwybGtawWmy/PzwnGDOjCkLWSD2wqvjGGAgOAwCGWySYXfYoxt00IJkTF+8Lb57DwOb3Aa0o9CApepiYQ==} + + '@nicolo-ribaudo/eslint-scope-5-internals@5.1.1-v1': + resolution: {integrity: sha512-54/JRvkLIzzDWshCWfuhadfrfZVPiElY8Fcgmg1HroEly/EDSszzhBAsarCux+D/kOslTRquNzuyGSmUSTTHGg==} + + '@nodelib/fs.scandir@2.1.5': + resolution: {integrity: sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==} + engines: {node: '>= 8'} + + '@nodelib/fs.stat@2.0.5': + resolution: {integrity: sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==} + engines: {node: '>= 8'} + + '@nodelib/fs.walk@1.2.8': + resolution: {integrity: sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==} + engines: {node: '>= 8'} + + '@rollup/rollup-android-arm-eabi@4.18.0': + resolution: {integrity: sha512-Tya6xypR10giZV1XzxmH5wr25VcZSncG0pZIjfePT0OVBvqNEurzValetGNarVrGiq66EBVAFn15iYX4w6FKgQ==} + cpu: [arm] + os: [android] + + '@rollup/rollup-android-arm64@4.18.0': + resolution: {integrity: sha512-avCea0RAP03lTsDhEyfy+hpfr85KfyTctMADqHVhLAF3MlIkq83CP8UfAHUssgXTYd+6er6PaAhx/QGv4L1EiA==} + cpu: [arm64] + os: [android] + + '@rollup/rollup-darwin-arm64@4.18.0': + resolution: {integrity: sha512-IWfdwU7KDSm07Ty0PuA/W2JYoZ4iTj3TUQjkVsO/6U+4I1jN5lcR71ZEvRh52sDOERdnNhhHU57UITXz5jC1/w==} + cpu: [arm64] + os: [darwin] + + '@rollup/rollup-darwin-x64@4.18.0': + resolution: {integrity: sha512-n2LMsUz7Ynu7DoQrSQkBf8iNrjOGyPLrdSg802vk6XT3FtsgX6JbE8IHRvposskFm9SNxzkLYGSq9QdpLYpRNA==} + cpu: [x64] + os: [darwin] + + '@rollup/rollup-linux-arm-gnueabihf@4.18.0': + resolution: {integrity: sha512-C/zbRYRXFjWvz9Z4haRxcTdnkPt1BtCkz+7RtBSuNmKzMzp3ZxdM28Mpccn6pt28/UWUCTXa+b0Mx1k3g6NOMA==} + cpu: [arm] + os: [linux] + + '@rollup/rollup-linux-arm-musleabihf@4.18.0': + resolution: {integrity: sha512-l3m9ewPgjQSXrUMHg93vt0hYCGnrMOcUpTz6FLtbwljo2HluS4zTXFy2571YQbisTnfTKPZ01u/ukJdQTLGh9A==} + cpu: [arm] + os: [linux] + + '@rollup/rollup-linux-arm64-gnu@4.18.0': + resolution: {integrity: sha512-rJ5D47d8WD7J+7STKdCUAgmQk49xuFrRi9pZkWoRD1UeSMakbcepWXPF8ycChBoAqs1pb2wzvbY6Q33WmN2ftw==} + cpu: [arm64] + os: [linux] + + '@rollup/rollup-linux-arm64-musl@4.18.0': + resolution: {integrity: sha512-be6Yx37b24ZwxQ+wOQXXLZqpq4jTckJhtGlWGZs68TgdKXJgw54lUUoFYrg6Zs/kjzAQwEwYbp8JxZVzZLRepQ==} + cpu: [arm64] + os: [linux] + + '@rollup/rollup-linux-powerpc64le-gnu@4.18.0': + resolution: {integrity: sha512-hNVMQK+qrA9Todu9+wqrXOHxFiD5YmdEi3paj6vP02Kx1hjd2LLYR2eaN7DsEshg09+9uzWi2W18MJDlG0cxJA==} + cpu: [ppc64] + os: [linux] + + '@rollup/rollup-linux-riscv64-gnu@4.18.0': + resolution: {integrity: sha512-ROCM7i+m1NfdrsmvwSzoxp9HFtmKGHEqu5NNDiZWQtXLA8S5HBCkVvKAxJ8U+CVctHwV2Gb5VUaK7UAkzhDjlg==} + cpu: [riscv64] + os: [linux] + + '@rollup/rollup-linux-s390x-gnu@4.18.0': + resolution: {integrity: sha512-0UyyRHyDN42QL+NbqevXIIUnKA47A+45WyasO+y2bGJ1mhQrfrtXUpTxCOrfxCR4esV3/RLYyucGVPiUsO8xjg==} + cpu: [s390x] + os: [linux] + + '@rollup/rollup-linux-x64-gnu@4.18.0': + resolution: {integrity: sha512-xuglR2rBVHA5UsI8h8UbX4VJ470PtGCf5Vpswh7p2ukaqBGFTnsfzxUBetoWBWymHMxbIG0Cmx7Y9qDZzr648w==} + cpu: [x64] + os: [linux] + + '@rollup/rollup-linux-x64-musl@4.18.0': + resolution: {integrity: sha512-LKaqQL9osY/ir2geuLVvRRs+utWUNilzdE90TpyoX0eNqPzWjRm14oMEE+YLve4k/NAqCdPkGYDaDF5Sw+xBfg==} + cpu: [x64] + os: [linux] + + '@rollup/rollup-win32-arm64-msvc@4.18.0': + resolution: {integrity: sha512-7J6TkZQFGo9qBKH0pk2cEVSRhJbL6MtfWxth7Y5YmZs57Pi+4x6c2dStAUvaQkHQLnEQv1jzBUW43GvZW8OFqA==} + cpu: [arm64] + os: [win32] + + '@rollup/rollup-win32-ia32-msvc@4.18.0': + resolution: {integrity: sha512-Txjh+IxBPbkUB9+SXZMpv+b/vnTEtFyfWZgJ6iyCmt2tdx0OF5WhFowLmnh8ENGNpfUlUZkdI//4IEmhwPieNg==} + cpu: [ia32] + os: [win32] + + '@rollup/rollup-win32-x64-msvc@4.18.0': + resolution: {integrity: sha512-UOo5FdvOL0+eIVTgS4tIdbW+TtnBLWg1YBCcU2KWM7nuNwRz9bksDX1bekJJCpu25N1DVWaCwnT39dVQxzqS8g==} + cpu: [x64] + os: [win32] + + '@sinclair/typebox@0.27.8': + resolution: {integrity: sha512-+Fj43pSMwJs4KRrH/938Uf+uAELIgVBmQzg/q1YG10djyfA3TnrU8N8XzqCh/okZdszqBQTZf96idMfE5lnwTA==} + + '@types/estree@1.0.5': + resolution: {integrity: sha512-/kYRxGDLWzHOB7q+wtSUQlFrtcdUccpfy+X+9iMBpHK8QLLhx2wIPYuS5DYtR9Wa/YlZAbIovy7qVdB1Aq6Lyw==} + + '@types/json5@0.0.29': + resolution: {integrity: sha512-dRLjCWHYg4oaA77cxO64oO+7JwCwnIzkZPdrrC71jQmQtlhM556pwKo5bUzqvZndkVbeFLIIi+9TC40JNF5hNQ==} + + '@types/node@20.14.8': + resolution: {integrity: sha512-DO+2/jZinXfROG7j7WKFn/3C6nFwxy2lLpgLjEXJz+0XKphZlTLJ14mo8Vfg8X5BWN6XjyESXq+LcYdT7tR3bA==} + + '@types/normalize-package-data@2.4.4': + resolution: {integrity: sha512-37i+OaWTh9qeK4LSHPsyRC7NahnGotNuZvjLSgcPzblpHB3rrCJxAOgI5gCdKm7coonsaX1Of0ILiTcnZjbfxA==} + + '@vitest/expect@1.6.0': + resolution: {integrity: sha512-ixEvFVQjycy/oNgHjqsL6AZCDduC+tflRluaHIzKIsdbzkLn2U/iBnVeJwB6HsIjQBdfMR8Z0tRxKUsvFJEeWQ==} + + '@vitest/runner@1.6.0': + resolution: {integrity: sha512-P4xgwPjwesuBiHisAVz/LSSZtDjOTPYZVmNAnpHHSR6ONrf8eCJOFRvUwdHn30F5M1fxhqtl7QZQUk2dprIXAg==} + + '@vitest/snapshot@1.6.0': + resolution: {integrity: sha512-+Hx43f8Chus+DCmygqqfetcAZrDJwvTj0ymqjQq4CvmpKFSTVteEOBzCusu1x2tt4OJcvBflyHUE0DZSLgEMtQ==} + + '@vitest/spy@1.6.0': + resolution: {integrity: sha512-leUTap6B/cqi/bQkXUu6bQV5TZPx7pmMBKBQiI0rJA8c3pB56ZsaTbREnF7CJfmvAS4V2cXIBAh/3rVwrrCYgw==} + + '@vitest/utils@1.6.0': + resolution: {integrity: sha512-21cPiuGMoMZwiOHa2i4LXkMkMkCGzA+MVFV70jRwHo95dL4x/ts5GZhML1QWuy7yfp3WzK3lRvZi3JnXTYqrBw==} + + acorn-jsx@5.3.2: + resolution: {integrity: sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==} + peerDependencies: + acorn: ^6.0.0 || ^7.0.0 || ^8.0.0 + + acorn-walk@8.3.3: + resolution: {integrity: sha512-MxXdReSRhGO7VlFe1bRG/oI7/mdLV9B9JJT0N8vZOhF7gFRR5l3M8W9G8JxmKV+JC5mGqJ0QvqfSOLsCPa4nUw==} + engines: {node: '>=0.4.0'} + + acorn@8.12.0: + resolution: {integrity: sha512-RTvkC4w+KNXrM39/lWCUaG0IbRkWdCv7W/IOW9oU6SawyxulvkQy5HQPVTKxEjczcUvapcrw3cFx/60VN/NRNw==} + engines: {node: '>=0.4.0'} + hasBin: true + + ajv@6.12.6: + resolution: {integrity: sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==} + + ansi-regex@5.0.1: + resolution: {integrity: sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==} + engines: {node: '>=8'} + + ansi-styles@3.2.1: + resolution: {integrity: sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==} + engines: {node: '>=4'} + + ansi-styles@4.3.0: + resolution: {integrity: sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==} + engines: {node: '>=8'} + + ansi-styles@5.2.0: + resolution: {integrity: sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA==} + engines: {node: '>=10'} + + are-docs-informative@0.0.2: + resolution: {integrity: sha512-ixiS0nLNNG5jNQzgZJNoUpBKdo9yTYZMGJ+QgT2jmjR7G7+QHRCc4v6LQ3NgE7EBJq+o0ams3waJwkrlBom8Ig==} + engines: {node: '>=14'} + + argparse@2.0.1: + resolution: {integrity: sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==} + + array-buffer-byte-length@1.0.1: + resolution: {integrity: sha512-ahC5W1xgou+KTXix4sAO8Ki12Q+jf4i0+tmk3sC+zgcynshkHxzpXdImBehiUYKKKDwvfFiJl1tZt6ewscS1Mg==} + engines: {node: '>= 0.4'} + + array-includes@3.1.8: + resolution: {integrity: sha512-itaWrbYbqpGXkGhZPGUulwnhVf5Hpy1xiCFsGqyIGglbBxmG5vSjxQen3/WGOjPpNEv1RtBLKxbmVXm8HpJStQ==} + engines: {node: '>= 0.4'} + + array.prototype.flat@1.3.2: + resolution: {integrity: sha512-djYB+Zx2vLewY8RWlNCUdHjDXs2XOgm602S9E7P/UpHgfeHL00cRiIF+IN/G/aUJ7kGPb6yO/ErDI5V2s8iycA==} + engines: {node: '>= 0.4'} + + array.prototype.flatmap@1.3.2: + resolution: {integrity: sha512-Ewyx0c9PmpcsByhSW4r+9zDU7sGjFc86qf/kKtuSCRdhfbk0SNLLkaT5qvcHnRGgc5NP/ly/y+qkXkqONX54CQ==} + engines: {node: '>= 0.4'} + + arraybuffer.prototype.slice@1.0.3: + resolution: {integrity: sha512-bMxMKAjg13EBSVscxTaYA4mRc5t1UAXa2kXiGTNfZ079HIWXEkKmkgFrh/nJqamaLSrXO5H4WFFkPEaLJWbs3A==} + engines: {node: '>= 0.4'} + + assertion-error@1.1.0: + resolution: {integrity: sha512-jgsaNduz+ndvGyFt3uSuWqvy4lCnIJiovtouQN5JZHOKCS2QuhEdbcQHFhVksz2N2U9hXJo8odG7ETyWlEeuDw==} + + available-typed-arrays@1.0.7: + resolution: {integrity: sha512-wvUjBtSGN7+7SjNpq/9M2Tg350UZD3q62IFZLbRAR1bSMlCo1ZaeW+BJ+D090e4hIIZLBcTDWe4Mh4jvUDajzQ==} + engines: {node: '>= 0.4'} + + balanced-match@1.0.2: + resolution: {integrity: sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==} + + brace-expansion@1.1.11: + resolution: {integrity: sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==} + + browserslist@4.23.1: + resolution: {integrity: sha512-TUfofFo/KsK/bWZ9TWQ5O26tsWW4Uhmt8IYklbnUa70udB6P2wA7w7o4PY4muaEPBQaAX+CEnmmIA41NVHtPVw==} + engines: {node: ^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7} + hasBin: true + + builtin-modules@3.3.0: + resolution: {integrity: sha512-zhaCDicdLuWN5UbN5IMnFqNMhNfo919sH85y2/ea+5Yg9TsTkeZxpL+JLbp6cgYFS4sRLp3YV4S6yDuqVWHYOw==} + engines: {node: '>=6'} + + cac@6.7.14: + resolution: {integrity: sha512-b6Ilus+c3RrdDk+JhLKUAQfzzgLEPy6wcXqS7f/xe1EETvsDP6GORG7SFuOs6cID5YkqchW/LXZbX5bc8j7ZcQ==} + engines: {node: '>=8'} + + call-bind@1.0.7: + resolution: {integrity: sha512-GHTSNSYICQ7scH7sZ+M2rFopRoLh8t2bLSW6BbgrtLsahOIB5iyAVJf9GjWK3cYTDaMj4XdBpM1cA6pIS0Kv2w==} + engines: {node: '>= 0.4'} + + callsites@3.1.0: + resolution: {integrity: sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==} + engines: {node: '>=6'} + + caniuse-lite@1.0.30001636: + resolution: {integrity: sha512-bMg2vmr8XBsbL6Lr0UHXy/21m84FTxDLWn2FSqMd5PrlbMxwJlQnC2YWYxVgp66PZE+BBNF2jYQUBKCo1FDeZg==} + + chai@4.4.1: + resolution: {integrity: sha512-13sOfMv2+DWduEU+/xbun3LScLoqN17nBeTLUsmDfKdoiC1fr0n9PU4guu4AhRcOVFk/sW8LyZWHuhWtQZiF+g==} + engines: {node: '>=4'} + + chalk@2.4.2: + resolution: {integrity: sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==} + engines: {node: '>=4'} + + chalk@4.1.2: + resolution: {integrity: sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==} + engines: {node: '>=10'} + + check-error@1.0.3: + resolution: {integrity: sha512-iKEoDYaRmd1mxM90a2OEfWhjsjPpYPuQ+lMYsoxB126+t8fw7ySEO48nmDg5COTjxDI65/Y2OWpeEHk3ZOe8zg==} + + ci-info@3.9.0: + resolution: {integrity: sha512-NIxF55hv4nSqQswkAeiOi1r83xy8JldOFDTWiug55KBu9Jnblncd2U6ViHmYgHf01TPZS77NJBhBMKdWj9HQMQ==} + engines: {node: '>=8'} + + clean-regexp@1.0.0: + resolution: {integrity: sha512-GfisEZEJvzKrmGWkvfhgzcz/BllN1USeqD2V6tg14OAOgaCD2Z/PUEuxnAZ/nPvmaHRG7a8y77p1T/IRQ4D1Hw==} + engines: {node: '>=4'} + + color-convert@1.9.3: + resolution: {integrity: sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==} + + color-convert@2.0.1: + resolution: {integrity: sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==} + engines: {node: '>=7.0.0'} + + color-name@1.1.3: + resolution: {integrity: sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==} + + color-name@1.1.4: + resolution: {integrity: sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==} + + comment-parser@1.4.0: + resolution: {integrity: sha512-QLyTNiZ2KDOibvFPlZ6ZngVsZ/0gYnE6uTXi5aoDg8ed3AkJAz4sEje3Y8a29hQ1s6A99MZXe47fLAXQ1rTqaw==} + engines: {node: '>= 12.0.0'} + + concat-map@0.0.1: + resolution: {integrity: sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==} + + confbox@0.1.7: + resolution: {integrity: sha512-uJcB/FKZtBMCJpK8MQji6bJHgu1tixKPxRLeGkNzBoOZzpnZUJm0jm2/sBDWcuBx1dYgxV4JU+g5hmNxCyAmdA==} + + confusing-browser-globals@1.0.11: + resolution: {integrity: sha512-JsPKdmh8ZkmnHxDk55FZ1TqVLvEQTvoByJZRN9jzI0UjxK/QgAmsphz7PGtqgPieQZ/CQcHWXCR7ATDNhGe+YA==} + + convert-source-map@2.0.0: + resolution: {integrity: sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg==} + + cross-spawn@7.0.3: + resolution: {integrity: sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==} + engines: {node: '>= 8'} + + data-view-buffer@1.0.1: + resolution: {integrity: sha512-0lht7OugA5x3iJLOWFhWK/5ehONdprk0ISXqVFn/NFrDu+cuc8iADFrGQz5BnRK7LLU3JmkbXSxaqX+/mXYtUA==} + engines: {node: '>= 0.4'} + + data-view-byte-length@1.0.1: + resolution: {integrity: sha512-4J7wRJD3ABAzr8wP+OcIcqq2dlUKp4DVflx++hs5h5ZKydWMI6/D/fAot+yh6g2tHh8fLFTvNOaVN357NvSrOQ==} + engines: {node: '>= 0.4'} + + data-view-byte-offset@1.0.0: + resolution: {integrity: sha512-t/Ygsytq+R995EJ5PZlD4Cu56sWa8InXySaViRzw9apusqsOO2bQP+SbYzAhR0pFKoB+43lYy8rWban9JSuXnA==} + engines: {node: '>= 0.4'} + + debug@3.2.7: + resolution: {integrity: sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==} + peerDependencies: + supports-color: '*' + peerDependenciesMeta: + supports-color: + optional: true + + debug@4.3.4: + resolution: {integrity: sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==} + engines: {node: '>=6.0'} + peerDependencies: + supports-color: '*' + peerDependenciesMeta: + supports-color: + optional: true + + deep-eql@4.1.4: + resolution: {integrity: sha512-SUwdGfqdKOwxCPeVYjwSyRpJ7Z+fhpwIAtmCUdZIWZ/YP5R9WAsyuSgpLVDi9bjWoN2LXHNss/dk3urXtdQxGg==} + engines: {node: '>=6'} + + deep-is@0.1.4: + resolution: {integrity: sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==} + + define-data-property@1.1.4: + resolution: {integrity: sha512-rBMvIzlpA8v6E+SJZoo++HAYqsLrkg7MSfIinMPFhmkorw7X+dOXVJQs+QT69zGkzMyfDnIMN2Wid1+NbL3T+A==} + engines: {node: '>= 0.4'} + + define-properties@1.2.1: + resolution: {integrity: sha512-8QmQKqEASLd5nx0U1B1okLElbUuuttJ/AnYmRXbbbGDWh6uS208EjD4Xqq/I9wK7u0v6O08XhTWnt5XtEbR6Dg==} + engines: {node: '>= 0.4'} + + diff-sequences@29.6.3: + resolution: {integrity: sha512-EjePK1srD3P08o2j4f0ExnylqRs5B9tJjcp9t1krH2qRi8CCdsYfwe9JgSLurFBWwq4uOlipzfk5fHNvwFKr8Q==} + engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} + + doctrine@2.1.0: + resolution: {integrity: sha512-35mSku4ZXK0vfCuHEDAwt55dg2jNajHZ1odvF+8SSr82EsZY4QmXfuWso8oEd8zRhVObSN18aM0CjSdoBX7zIw==} + engines: {node: '>=0.10.0'} + + doctrine@3.0.0: + resolution: {integrity: sha512-yS+Q5i3hBf7GBkd4KG8a7eBNNWNGLTaEwwYWUijIYM7zrlYDM0BFXHjjPWlWZ1Rg7UaddZeIDmi9jF3HmqiQ2w==} + engines: {node: '>=6.0.0'} + + electron-to-chromium@1.4.811: + resolution: {integrity: sha512-CDyzcJ5XW78SHzsIOdn27z8J4ist8eaFLhdto2hSMSJQgsiwvbv2fbizcKUICryw1Wii1TI/FEkvzvJsR3awrA==} + + error-ex@1.3.2: + resolution: {integrity: sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g==} + + es-abstract@1.23.3: + resolution: {integrity: sha512-e+HfNH61Bj1X9/jLc5v1owaLYuHdeHHSQlkhCBiTK8rBvKaULl/beGMxwrMXjpYrv4pz22BlY570vVePA2ho4A==} + engines: {node: '>= 0.4'} + + es-define-property@1.0.0: + resolution: {integrity: sha512-jxayLKShrEqqzJ0eumQbVhTYQM27CfT1T35+gCgDFoL82JLsXqTJ76zv6A0YLOgEnLUMvLzsDsGIrl8NFpT2gQ==} + engines: {node: '>= 0.4'} + + es-errors@1.3.0: + resolution: {integrity: sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==} + engines: {node: '>= 0.4'} + + es-object-atoms@1.0.0: + resolution: {integrity: sha512-MZ4iQ6JwHOBQjahnjwaC1ZtIBH+2ohjamzAO3oaHcXYup7qxjF2fixyH+Q71voWHeOkI2q/TnJao/KfXYIZWbw==} + engines: {node: '>= 0.4'} + + es-set-tostringtag@2.0.3: + resolution: {integrity: sha512-3T8uNMC3OQTHkFUsFq8r/BwAXLHvU/9O9mE0fBc/MY5iq/8H7ncvO947LmYA6ldWw9Uh8Yhf25zu6n7nML5QWQ==} + engines: {node: '>= 0.4'} + + es-shim-unscopables@1.0.2: + resolution: {integrity: sha512-J3yBRXCzDu4ULnQwxyToo/OjdMx6akgVC7K6few0a7F/0wLtmKKN7I73AH5T2836UuXRqN7Qg+IIUw/+YJksRw==} + + es-to-primitive@1.2.1: + resolution: {integrity: sha512-QCOllgZJtaUo9miYBcLChTUaHNjJF3PYs1VidD7AwiEj1kYxKeQTctLAezAOH5ZKRH0g2IgPn6KwB4IT8iRpvA==} + engines: {node: '>= 0.4'} + + esbuild@0.21.5: + resolution: {integrity: sha512-mg3OPMV4hXywwpoDxu3Qda5xCKQi+vCTZq8S9J/EpkhB2HzKXq4SNFZE3+NK93JYxc8VMSep+lOUSC/RVKaBqw==} + engines: {node: '>=12'} + hasBin: true + + escalade@3.1.2: + resolution: {integrity: sha512-ErCHMCae19vR8vQGe50xIsVomy19rg6gFu3+r3jkEO46suLMWBksvVyoGgQV+jOfl84ZSOSlmv6Gxa89PmTGmA==} + engines: {node: '>=6'} + + escape-string-regexp@1.0.5: + resolution: {integrity: sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==} + engines: {node: '>=0.8.0'} + + escape-string-regexp@4.0.0: + resolution: {integrity: sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==} + engines: {node: '>=10'} + + eslint-config-xo@0.43.1: + resolution: {integrity: sha512-azv1L2PysRA0NkZOgbndUpN+581L7wPqkgJOgxxw3hxwXAbJgD6Hqb/SjHRiACifXt/AvxCzE/jIKFAlI7XjvQ==} + engines: {node: '>=12'} + peerDependencies: + eslint: '>=8.27.0' + + eslint-import-resolver-node@0.3.9: + resolution: {integrity: sha512-WFj2isz22JahUv+B788TlO3N6zL3nNJGU8CcZbPZvVEkBPaJdCV4vy5wyghty5ROFbCRnm132v8BScu5/1BQ8g==} + + eslint-module-utils@2.8.1: + resolution: {integrity: sha512-rXDXR3h7cs7dy9RNpUlQf80nX31XWJEyGq1tRMo+6GsO5VmTe4UTwtmonAD4ZkAsrfMVDA2wlGJ3790Ys+D49Q==} + engines: {node: '>=4'} + peerDependencies: + '@typescript-eslint/parser': '*' + eslint: '*' + eslint-import-resolver-node: '*' + eslint-import-resolver-typescript: '*' + eslint-import-resolver-webpack: '*' + peerDependenciesMeta: + '@typescript-eslint/parser': + optional: true + eslint: + optional: true + eslint-import-resolver-node: + optional: true + eslint-import-resolver-typescript: + optional: true + eslint-import-resolver-webpack: + optional: true + + eslint-plugin-es@3.0.1: + resolution: {integrity: sha512-GUmAsJaN4Fc7Gbtl8uOBlayo2DqhwWvEzykMHSCZHU3XdJ+NSzzZcVhXh3VxX5icqQ+oQdIEawXX8xkR3mIFmQ==} + engines: {node: '>=8.10.0'} + peerDependencies: + eslint: '>=4.19.1' + + eslint-plugin-import@2.27.5: + resolution: {integrity: sha512-LmEt3GVofgiGuiE+ORpnvP+kAm3h6MLZJ4Q5HCyHADofsb4VzXFsRiWj3c0OFiV+3DWFh0qg3v9gcPlfc3zRow==} + engines: {node: '>=4'} + peerDependencies: + '@typescript-eslint/parser': '*' + eslint: ^2 || ^3 || ^4 || ^5 || ^6 || ^7.2.0 || ^8 + peerDependenciesMeta: + '@typescript-eslint/parser': + optional: true + + eslint-plugin-jsdoc@46.5.0: + resolution: {integrity: sha512-aulXdA4I1dyWpzyS1Nh/GNoS6PavzeucxEapnMR4JUERowWvaEk2Y4A5irpHAcdXtBBHLVe8WIhdXNjoAlGQgA==} + engines: {node: '>=16'} + peerDependencies: + eslint: ^7.0.0 || ^8.0.0 + + eslint-plugin-node@11.1.0: + resolution: {integrity: sha512-oUwtPJ1W0SKD0Tr+wqu92c5xuCeQqB3hSCHasn/ZgjFdA9iDGNkNf2Zi9ztY7X+hNuMib23LNGRm6+uN+KLE3g==} + engines: {node: '>=8.10.0'} + peerDependencies: + eslint: '>=5.16.0' + + eslint-plugin-promise@6.1.1: + resolution: {integrity: sha512-tjqWDwVZQo7UIPMeDReOpUgHCmCiH+ePnVT+5zVapL0uuHnegBUs2smM13CzOs2Xb5+MHMRFTs9v24yjba4Oig==} + engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} + peerDependencies: + eslint: ^7.0.0 || ^8.0.0 + + eslint-plugin-unicorn@47.0.0: + resolution: {integrity: sha512-ivB3bKk7fDIeWOUmmMm9o3Ax9zbMz1Bsza/R2qm46ufw4T6VBFBaJIR1uN3pCKSmSXm8/9Nri8V+iUut1NhQGA==} + engines: {node: '>=16'} + peerDependencies: + eslint: '>=8.38.0' + + eslint-scope@5.1.1: + resolution: {integrity: sha512-2NxwbF/hZ0KpepYN0cNbo+FN6XoK7GaHlQhgx/hIZl6Va0bF45RQOOwhLIy8lQDbuCiadSLCBnH2CFYquit5bw==} + engines: {node: '>=8.0.0'} + + eslint-scope@7.2.2: + resolution: {integrity: sha512-dOt21O7lTMhDM+X9mB4GX+DZrZtCUJPL/wlcTqxyrx5IvO0IYtILdtrQGQp+8n5S0gwSVmOf9NQrjMOgfQZlIg==} + engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} + + eslint-utils@2.1.0: + resolution: {integrity: sha512-w94dQYoauyvlDc43XnGB8lU3Zt713vNChgt4EWwhXAP2XkBvndfxF0AgIqKOOasjPIPzj9JqgwkwbCYD0/V3Zg==} + engines: {node: '>=6'} + + eslint-visitor-keys@1.3.0: + resolution: {integrity: sha512-6J72N8UNa462wa/KFODt/PJ3IU60SDpC3QXC1Hjc1BXXpfL2C9R5+AU7jhe0F6GREqVMh4Juu+NY7xn+6dipUQ==} + engines: {node: '>=4'} + + eslint-visitor-keys@2.1.0: + resolution: {integrity: sha512-0rSmRBzXgDzIsD6mGdJgevzgezI534Cer5L/vyMX0kHzT/jiB43jRhd9YUlMGYLQy2zprNmoT8qasCGtY+QaKw==} + engines: {node: '>=10'} + + eslint-visitor-keys@3.4.3: + resolution: {integrity: sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag==} + engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} + + eslint@8.41.0: + resolution: {integrity: sha512-WQDQpzGBOP5IrXPo4Hc0814r4/v2rrIsB0rhT7jtunIalgg6gYXWhRMOejVO8yH21T/FGaxjmFjBMNqcIlmH1Q==} + engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} + hasBin: true + + espree@9.6.1: + resolution: {integrity: sha512-oruZaFkjorTpF32kDSI5/75ViwGeZginGGy2NoOSg3Q9bnwlnmDm4HLnkl0RE3n+njDXR037aY1+x58Z/zFdwQ==} + engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} + + esquery@1.5.0: + resolution: {integrity: sha512-YQLXUplAwJgCydQ78IMJywZCceoqk1oH01OERdSAJc/7U2AylwjhSCLDEtqwg811idIS/9fIU5GjG73IgjKMVg==} + engines: {node: '>=0.10'} + + esrecurse@4.3.0: + resolution: {integrity: sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==} + engines: {node: '>=4.0'} + + estraverse@4.3.0: + resolution: {integrity: sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw==} + engines: {node: '>=4.0'} + + estraverse@5.3.0: + resolution: {integrity: sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==} + engines: {node: '>=4.0'} + + estree-walker@3.0.3: + resolution: {integrity: sha512-7RUKfXgSMMkzt6ZuXmqapOurLGPPfgj6l9uRZ7lRGolvk0y2yocc35LdcxKC5PQZdn2DMqioAQ2NoWcrTKmm6g==} + + esutils@2.0.3: + resolution: {integrity: sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==} + engines: {node: '>=0.10.0'} + + execa@8.0.1: + resolution: {integrity: sha512-VyhnebXciFV2DESc+p6B+y0LjSm0krU4OgJN44qFAhBY0TJ+1V61tYD2+wHusZ6F9n5K+vl8k0sTy7PEfV4qpg==} + engines: {node: '>=16.17'} + + fast-deep-equal@3.1.3: + resolution: {integrity: sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==} + + fast-json-stable-stringify@2.1.0: + resolution: {integrity: sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==} + + fast-levenshtein@2.0.6: + resolution: {integrity: sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==} + + fastq@1.17.1: + resolution: {integrity: sha512-sRVD3lWVIXWg6By68ZN7vho9a1pQcN/WBFaAAsDDFzlJjvoGx0P8z7V1t72grFJfJhu3YPZBuu25f7Kaw2jN1w==} + + file-entry-cache@6.0.1: + resolution: {integrity: sha512-7Gps/XWymbLk2QLYK4NzpMOrYjMhdIxXuIvy2QBsLE6ljuodKvdkWs/cpyJJ3CVIVpH0Oi1Hvg1ovbMzLdFBBg==} + engines: {node: ^10.12.0 || >=12.0.0} + + find-up@4.1.0: + resolution: {integrity: sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==} + engines: {node: '>=8'} + + find-up@5.0.0: + resolution: {integrity: sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==} + engines: {node: '>=10'} + + flat-cache@3.2.0: + resolution: {integrity: sha512-CYcENa+FtcUKLmhhqyctpclsq7QF38pKjZHsGNiSQF5r4FtoKDWabFDl3hzaEQMvT1LHEysw5twgLvpYYb4vbw==} + engines: {node: ^10.12.0 || >=12.0.0} + + flatted@3.3.1: + resolution: {integrity: sha512-X8cqMLLie7KsNUDSdzeN8FYK9rEt4Dt67OsG/DNGnYTSDBG4uFAJFBnUeiV+zCVAvwFy56IjM9sH51jVaEhNxw==} + + for-each@0.3.3: + resolution: {integrity: sha512-jqYfLp7mo9vIyQf8ykW2v7A+2N4QjeCeI5+Dz9XraiO1ign81wjiH7Fb9vSOWvQfNtmSa4H2RoQTrrXivdUZmw==} + + fs.realpath@1.0.0: + resolution: {integrity: sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==} + + fsevents@2.3.3: + resolution: {integrity: sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==} + engines: {node: ^8.16.0 || ^10.6.0 || >=11.0.0} + os: [darwin] + + function-bind@1.1.2: + resolution: {integrity: sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==} + + function.prototype.name@1.1.6: + resolution: {integrity: sha512-Z5kx79swU5P27WEayXM1tBi5Ze/lbIyiNgU3qyXUOf9b2rgXYyF9Dy9Cx+IQv/Lc8WCG6L82zwUPpSS9hGehIg==} + engines: {node: '>= 0.4'} + + functions-have-names@1.2.3: + resolution: {integrity: sha512-xckBUXyTIqT97tq2x2AMb+g163b5JFysYk0x4qxNFwbfQkmNZoiRHb6sPzI9/QV33WeuvVYBUIiD4NzNIyqaRQ==} + + gensync@1.0.0-beta.2: + resolution: {integrity: sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg==} + engines: {node: '>=6.9.0'} + + get-func-name@2.0.2: + resolution: {integrity: sha512-8vXOvuE167CtIc3OyItco7N/dpRtBbYOsPsXCz7X/PMnlGjYjSGuZJgM1Y7mmew7BKf9BqvLX2tnOVy1BBUsxQ==} + + get-intrinsic@1.2.4: + resolution: {integrity: sha512-5uYhsJH8VJBTv7oslg4BznJYhDoRI6waYCxMmCdnTrcCrHA/fCFKoTFz2JKKE0HdDFUF7/oQuhzumXJK7paBRQ==} + engines: {node: '>= 0.4'} + + get-stream@8.0.1: + resolution: {integrity: sha512-VaUJspBffn/LMCJVoMvSAdmscJyS1auj5Zulnn5UoYcY531UWmdwhRWkcGKnGU93m5HSXP9LP2usOryrBtQowA==} + engines: {node: '>=16'} + + get-symbol-description@1.0.2: + resolution: {integrity: sha512-g0QYk1dZBxGwk+Ngc+ltRH2IBp2f7zBkBMBJZCDerh6EhlhSR6+9irMCuT/09zD6qkarHUSn529sK/yL4S27mg==} + engines: {node: '>= 0.4'} + + glob-parent@6.0.2: + resolution: {integrity: sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==} + engines: {node: '>=10.13.0'} + + glob@7.2.3: + resolution: {integrity: sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==} + deprecated: Glob versions prior to v9 are no longer supported + + globals@11.12.0: + resolution: {integrity: sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA==} + engines: {node: '>=4'} + + globals@13.24.0: + resolution: {integrity: sha512-AhO5QUcj8llrbG09iWhPU2B204J1xnPeL8kQmVorSsy+Sjj1sk8gIyh6cUocGmH4L0UuhAJy+hJMRA4mgA4mFQ==} + engines: {node: '>=8'} + + globalthis@1.0.4: + resolution: {integrity: sha512-DpLKbNU4WylpxJykQujfCcwYWiV/Jhm50Goo0wrVILAv5jOr9d+H+UR3PhSCD2rCCEIg0uc+G+muBTwD54JhDQ==} + engines: {node: '>= 0.4'} + + gopd@1.0.1: + resolution: {integrity: sha512-d65bNlIadxvpb/A2abVdlqKqV563juRnZ1Wtk6s1sIR8uNsXR70xqIzVqxVf1eTqDunwT2MkczEeaezCKTZhwA==} + + graphemer@1.4.0: + resolution: {integrity: sha512-EtKwoO6kxCL9WO5xipiHTZlSzBm7WLT627TqC/uVRd0HKmq8NXyebnNYxDoBi7wt8eTWrUrKXCOVaFq9x1kgag==} + + has-bigints@1.0.2: + resolution: {integrity: sha512-tSvCKtBr9lkF0Ex0aQiP9N+OpV4zi2r/Nee5VkRDbaqv35RLYMzbwQfFSZZH0kR+Rd6302UJZ2p/bJCEoR3VoQ==} + + has-flag@3.0.0: + resolution: {integrity: sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==} + engines: {node: '>=4'} + + has-flag@4.0.0: + resolution: {integrity: sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==} + engines: {node: '>=8'} + + has-property-descriptors@1.0.2: + resolution: {integrity: sha512-55JNKuIW+vq4Ke1BjOTjM2YctQIvCT7GFzHwmfZPGo5wnrgkid0YQtnAleFSqumZm4az3n2BS+erby5ipJdgrg==} + + has-proto@1.0.3: + resolution: {integrity: sha512-SJ1amZAJUiZS+PhsVLf5tGydlaVB8EdFpaSO4gmiUKUOxk8qzn5AIy4ZeJUmh22znIdk/uMAUT2pl3FxzVUH+Q==} + engines: {node: '>= 0.4'} + + has-symbols@1.0.3: + resolution: {integrity: sha512-l3LCuF6MgDNwTDKkdYGEihYjt5pRPbEg46rtlmnSPlUbgmB8LOIrKJbYYFBSbnPaJexMKtiPO8hmeRjRz2Td+A==} + engines: {node: '>= 0.4'} + + has-tostringtag@1.0.2: + resolution: {integrity: sha512-NqADB8VjPFLM2V0VvHUewwwsw0ZWBaIdgo+ieHtK3hasLz4qeCRjYcqfB6AQrBggRKppKF8L52/VqdVsO47Dlw==} + engines: {node: '>= 0.4'} + + has@1.0.4: + resolution: {integrity: sha512-qdSAmqLF6209RFj4VVItywPMbm3vWylknmB3nvNiUIs72xAimcM8nVYxYr7ncvZq5qzk9MKIZR8ijqD/1QuYjQ==} + engines: {node: '>= 0.4.0'} + + hasown@2.0.2: + resolution: {integrity: sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==} + engines: {node: '>= 0.4'} + + hosted-git-info@2.8.9: + resolution: {integrity: sha512-mxIDAb9Lsm6DoOJ7xH+5+X4y1LU/4Hi50L9C5sIswK3JzULS4bwk1FvjdBgvYR4bzT4tuUQiC15FE2f5HbLvYw==} + + human-signals@5.0.0: + resolution: {integrity: sha512-AXcZb6vzzrFAUE61HnN4mpLqd/cSIwNQjtNWR0euPm6y0iqx3G4gOXaIDdtdDwZmhwe82LA6+zinmW4UBWVePQ==} + engines: {node: '>=16.17.0'} + + ignore@5.3.1: + resolution: {integrity: sha512-5Fytz/IraMjqpwfd34ke28PTVMjZjJG2MPn5t7OE4eUCUNf8BAa7b5WUS9/Qvr6mwOQS7Mk6vdsMno5he+T8Xw==} + engines: {node: '>= 4'} + + import-fresh@3.3.0: + resolution: {integrity: sha512-veYYhQa+D1QBKznvhUHxb8faxlrwUnxseDAbAp457E0wLNio2bOSKnjYDhMj+YiAq61xrMGhQk9iXVk5FzgQMw==} + engines: {node: '>=6'} + + imurmurhash@0.1.4: + resolution: {integrity: sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==} + engines: {node: '>=0.8.19'} + + indent-string@4.0.0: + resolution: {integrity: sha512-EdDDZu4A2OyIK7Lr/2zG+w5jmbuk1DVBnEwREQvBzspBJkCEbRa8GxU1lghYcaGJCnRWibjDXlq779X1/y5xwg==} + engines: {node: '>=8'} + + inflight@1.0.6: + resolution: {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. + + inherits@2.0.4: + resolution: {integrity: sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==} + + internal-slot@1.0.7: + resolution: {integrity: sha512-NGnrKwXzSms2qUUih/ILZ5JBqNTSa1+ZmP6flaIp6KmSElgE9qdndzS3cqjrDovwFdmwsGsLdeFgB6suw+1e9g==} + engines: {node: '>= 0.4'} + + is-array-buffer@3.0.4: + resolution: {integrity: sha512-wcjaerHw0ydZwfhiKbXJWLDY8A7yV7KhjQOpb83hGgGfId/aQa4TOvwyzn2PuswW2gPCYEL/nEAiSVpdOj1lXw==} + engines: {node: '>= 0.4'} + + is-arrayish@0.2.1: + resolution: {integrity: sha512-zz06S8t0ozoDXMG+ube26zeCTNXcKIPJZJi8hBrF4idCLms4CG9QtK7qBl1boi5ODzFpjswb5JPmHCbMpjaYzg==} + + is-bigint@1.0.4: + resolution: {integrity: sha512-zB9CruMamjym81i2JZ3UMn54PKGsQzsJeo6xvN3HJJ4CAsQNB6iRutp2To77OfCNuoxspsIhzaPoO1zyCEhFOg==} + + is-boolean-object@1.1.2: + resolution: {integrity: sha512-gDYaKHJmnj4aWxyj6YHyXVpdQawtVLHU5cb+eztPGczf6cjuTdwve5ZIEfgXqH4e57An1D1AKf8CZ3kYrQRqYA==} + engines: {node: '>= 0.4'} + + is-builtin-module@3.2.1: + resolution: {integrity: sha512-BSLE3HnV2syZ0FK0iMA/yUGplUeMmNz4AW5fnTunbCIqZi4vG3WjJT9FHMy5D69xmAYBHXQhJdALdpwVxV501A==} + engines: {node: '>=6'} + + is-callable@1.2.7: + resolution: {integrity: sha512-1BC0BVFhS/p0qtw6enp8e+8OD0UrK0oFLztSjNzhcKA3WDuJxxAPXzPuPtKkjEY9UUoEWlX/8fgKeu2S8i9JTA==} + engines: {node: '>= 0.4'} + + is-core-module@2.14.0: + resolution: {integrity: sha512-a5dFJih5ZLYlRtDc0dZWP7RiKr6xIKzmn/oAYCDvdLThadVgyJwlaoQPmRtMSpz+rk0OGAgIu+TcM9HUF0fk1A==} + engines: {node: '>= 0.4'} + + is-data-view@1.0.1: + resolution: {integrity: sha512-AHkaJrsUVW6wq6JS8y3JnM/GJF/9cf+k20+iDzlSaJrinEo5+7vRiteOSwBhHRiAyQATN1AmY4hwzxJKPmYf+w==} + engines: {node: '>= 0.4'} + + is-date-object@1.0.5: + resolution: {integrity: sha512-9YQaSxsAiSwcvS33MBk3wTCVnWK+HhF8VZR2jRxehM16QcVOdHqPn4VPHmRK4lSr38n9JriurInLcP90xsYNfQ==} + engines: {node: '>= 0.4'} + + is-extglob@2.1.1: + resolution: {integrity: sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==} + engines: {node: '>=0.10.0'} + + is-glob@4.0.3: + resolution: {integrity: sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==} + engines: {node: '>=0.10.0'} + + is-negative-zero@2.0.3: + resolution: {integrity: sha512-5KoIu2Ngpyek75jXodFvnafB6DJgr3u8uuK0LEZJjrU19DrMD3EVERaR8sjz8CCGgpZvxPl9SuE1GMVPFHx1mw==} + engines: {node: '>= 0.4'} + + is-number-object@1.0.7: + resolution: {integrity: sha512-k1U0IRzLMo7ZlYIfzRu23Oh6MiIFasgpb9X76eqfFZAqwH44UI4KTBvBYIZ1dSL9ZzChTB9ShHfLkR4pdW5krQ==} + engines: {node: '>= 0.4'} + + is-path-inside@3.0.3: + resolution: {integrity: sha512-Fd4gABb+ycGAmKou8eMftCupSir5lRxqf4aD/vd0cD2qc4HL07OjCeuHMr8Ro4CoMaeCKDB0/ECBOVWjTwUvPQ==} + engines: {node: '>=8'} + + is-regex@1.1.4: + resolution: {integrity: sha512-kvRdxDsxZjhzUX07ZnLydzS1TU/TJlTUHHY4YLL87e37oUA49DfkLqgy+VjFocowy29cKvcSiu+kIv728jTTVg==} + engines: {node: '>= 0.4'} + + is-shared-array-buffer@1.0.3: + resolution: {integrity: sha512-nA2hv5XIhLR3uVzDDfCIknerhx8XUKnstuOERPNNIinXG7v9u+ohXF67vxm4TPTEPU6lm61ZkwP3c9PCB97rhg==} + engines: {node: '>= 0.4'} + + is-stream@3.0.0: + resolution: {integrity: sha512-LnQR4bZ9IADDRSkvpqMGvt/tEJWclzklNgSw48V5EAaAeDd6qGvN8ei6k5p0tvxSR171VmGyHuTiAOfxAbr8kA==} + engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} + + is-string@1.0.7: + resolution: {integrity: sha512-tE2UXzivje6ofPW7l23cjDOMa09gb7xlAqG6jG5ej6uPV32TlWP3NKPigtaGeHNu9fohccRYvIiZMfOOnOYUtg==} + engines: {node: '>= 0.4'} + + is-symbol@1.0.4: + resolution: {integrity: sha512-C/CPBqKWnvdcxqIARxyOh4v1UUEOCHpgDa0WYgpKDFMszcrPcffg5uhwSgPCLD2WWxmq6isisz87tzT01tuGhg==} + engines: {node: '>= 0.4'} + + is-typed-array@1.1.13: + resolution: {integrity: sha512-uZ25/bUAlUY5fR4OKT4rZQEBrzQWYV9ZJYGGsUmEJ6thodVJ1HX64ePQ6Z0qPWP+m+Uq6e9UugrE38jeYsDSMw==} + engines: {node: '>= 0.4'} + + is-weakref@1.0.2: + resolution: {integrity: sha512-qctsuLZmIQ0+vSSMfoVvyFe2+GSEvnmZ2ezTup1SBse9+twCCeial6EEi3Nc2KFcf6+qz2FBPnjXsk8xhKSaPQ==} + + isarray@2.0.5: + resolution: {integrity: sha512-xHjhDr3cNBK0BzdUJSPXZntQUx/mwMS5Rw4A7lPJ90XGAO6ISP/ePDNuo0vhqOZU+UD5JoodwCAAoZQd3FeAKw==} + + isexe@2.0.0: + resolution: {integrity: sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==} + + js-tokens@4.0.0: + resolution: {integrity: sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==} + + js-tokens@9.0.0: + resolution: {integrity: sha512-WriZw1luRMlmV3LGJaR6QOJjWwgLUTf89OwT2lUOyjX2dJGBwgmIkbcz+7WFZjrZM635JOIR517++e/67CP9dQ==} + + js-yaml@4.1.0: + resolution: {integrity: sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==} + hasBin: true + + jsdoc-type-pratt-parser@4.0.0: + resolution: {integrity: sha512-YtOli5Cmzy3q4dP26GraSOeAhqecewG04hoO8DY56CH4KJ9Fvv5qKWUCCo3HZob7esJQHCv6/+bnTy72xZZaVQ==} + engines: {node: '>=12.0.0'} + + jsesc@0.5.0: + resolution: {integrity: sha512-uZz5UnB7u4T9LvwmFqXii7pZSouaRPorGs5who1Ip7VO0wxanFvBL7GkM6dTHlgX+jhBApRetaWpnDabOeTcnA==} + hasBin: true + + jsesc@2.5.2: + resolution: {integrity: sha512-OYu7XEzjkCQ3C5Ps3QIZsQfNpqoJyZZA99wd9aWd05NCtC5pWOkShK2mkL6HXQR6/Cy2lbNdPlZBpuQHXE63gA==} + engines: {node: '>=4'} + hasBin: true + + jsesc@3.0.2: + resolution: {integrity: sha512-xKqzzWXDttJuOcawBt4KnKHHIf5oQ/Cxax+0PWFG+DFDgHNAdi+TXECADI+RYiFUMmx8792xsMbbgXj4CwnP4g==} + engines: {node: '>=6'} + hasBin: true + + json-buffer@3.0.1: + resolution: {integrity: sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ==} + + json-parse-even-better-errors@2.3.1: + resolution: {integrity: sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w==} + + json-schema-traverse@0.4.1: + resolution: {integrity: sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==} + + json-stable-stringify-without-jsonify@1.0.1: + resolution: {integrity: sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw==} + + json5@1.0.2: + resolution: {integrity: sha512-g1MWMLBiz8FKi1e4w0UyVL3w+iJceWAFBAaBnnGKOpNa5f8TLktkbre1+s6oICydWAm+HRUGTmI+//xv2hvXYA==} + hasBin: true + + json5@2.2.3: + resolution: {integrity: sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg==} + engines: {node: '>=6'} + hasBin: true + + keyv@4.5.4: + resolution: {integrity: sha512-oxVHkHR/EJf2CNXnWxRLW6mg7JyCCUcG0DtEGmL2ctUo1PNTin1PUil+r/+4r5MpVgC/fn1kjsx7mjSujKqIpw==} + + levn@0.4.1: + resolution: {integrity: sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==} + engines: {node: '>= 0.8.0'} + + lines-and-columns@1.2.4: + resolution: {integrity: sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg==} + + local-pkg@0.5.0: + resolution: {integrity: sha512-ok6z3qlYyCDS4ZEU27HaU6x/xZa9Whf8jD4ptH5UZTQYZVYeb9bnZ3ojVhiJNLiXK1Hfc0GNbLXcmZ5plLDDBg==} + engines: {node: '>=14'} + + locate-path@5.0.0: + resolution: {integrity: sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==} + engines: {node: '>=8'} + + locate-path@6.0.0: + resolution: {integrity: sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==} + engines: {node: '>=10'} + + lodash.merge@4.6.2: + resolution: {integrity: sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==} + + lodash@4.17.21: + resolution: {integrity: sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==} + + loupe@2.3.7: + resolution: {integrity: sha512-zSMINGVYkdpYSOBmLi0D1Uo7JU9nVdQKrHxC8eYlV+9YKK9WePqAlL7lSlorG/U2Fw1w0hTBmaa/jrQ3UbPHtA==} + + lru-cache@5.1.1: + resolution: {integrity: sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==} + + magic-string@0.30.10: + resolution: {integrity: sha512-iIRwTIf0QKV3UAnYK4PU8uiEc4SRh5jX0mwpIwETPpHdhVM4f53RSwS/vXvN1JhGX+Cs7B8qIq3d6AH49O5fAQ==} + + merge-stream@2.0.0: + resolution: {integrity: sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w==} + + mimic-fn@4.0.0: + resolution: {integrity: sha512-vqiC06CuhBTUdZH+RYl8sFrL096vA45Ok5ISO6sE/Mr1jRbGH4Csnhi8f3wKVl7x8mO4Au7Ir9D3Oyv1VYMFJw==} + engines: {node: '>=12'} + + min-indent@1.0.1: + resolution: {integrity: sha512-I9jwMn07Sy/IwOj3zVkVik2JTvgpaykDZEigL6Rx6N9LbMywwUSMtxET+7lVoDLLd3O3IXwJwvuuns8UB/HeAg==} + engines: {node: '>=4'} + + minimatch@3.1.2: + resolution: {integrity: sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==} + + minimist@1.2.8: + resolution: {integrity: sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==} + + mlly@1.7.1: + resolution: {integrity: sha512-rrVRZRELyQzrIUAVMHxP97kv+G786pHmOKzuFII8zDYahFBS7qnHh2AlYSl1GAHhaMPCz6/oHjVMcfFYgFYHgA==} + + ms@2.1.2: + resolution: {integrity: sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==} + + nanoid@3.3.7: + resolution: {integrity: sha512-eSRppjcPIatRIMC1U6UngP8XFcz8MQWGQdt1MTBQ7NaAmvXDfvNxbvWV3x2y6CdEUciCSsDHDQZbhYaB8QEo2g==} + engines: {node: ^10 || ^12 || ^13.7 || ^14 || >=15.0.1} + hasBin: true + + natural-compare@1.4.0: + resolution: {integrity: sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==} + + node-releases@2.0.14: + resolution: {integrity: sha512-y10wOWt8yZpqXmOgRo77WaHEmhYQYGNA6y421PKsKYWEK8aW+cqAphborZDhqfyKrbZEN92CN1X2KbafY2s7Yw==} + + normalize-package-data@2.5.0: + resolution: {integrity: sha512-/5CMN3T0R4XTj4DcGaexo+roZSdSFW/0AOOTROrjxzCG1wrWXEsGbRKevjlIL+ZDE4sZlJr5ED4YW0yqmkK+eA==} + + npm-run-path@5.3.0: + resolution: {integrity: sha512-ppwTtiJZq0O/ai0z7yfudtBpWIoxM8yE6nHi1X47eFR2EWORqfbu6CnPlNsjeN683eT0qG6H/Pyf9fCcvjnnnQ==} + engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} + + object-inspect@1.13.2: + resolution: {integrity: sha512-IRZSRuzJiynemAXPYtPe5BoI/RESNYR7TYm50MC5Mqbd3Jmw5y790sErYw3V6SryFJD64b74qQQs9wn5Bg/k3g==} + engines: {node: '>= 0.4'} + + object-keys@1.1.1: + resolution: {integrity: sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==} + engines: {node: '>= 0.4'} + + object.assign@4.1.5: + resolution: {integrity: sha512-byy+U7gp+FVwmyzKPYhW2h5l3crpmGsxl7X2s8y43IgxvG4g3QZ6CffDtsNQy1WsmZpQbO+ybo0AlW7TY6DcBQ==} + engines: {node: '>= 0.4'} + + object.values@1.2.0: + resolution: {integrity: sha512-yBYjY9QX2hnRmZHAjG/f13MzmBzxzYgQhFrke06TTyKY5zSTEqkOeukBzIdVA3j3ulu8Qa3MbVFShV7T2RmGtQ==} + engines: {node: '>= 0.4'} + + once@1.4.0: + resolution: {integrity: sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==} + + onetime@6.0.0: + resolution: {integrity: sha512-1FlR+gjXK7X+AsAHso35MnyN5KqGwJRi/31ft6x0M194ht7S+rWAvd7PHss9xSKMzE0asv1pyIHaJYq+BbacAQ==} + engines: {node: '>=12'} + + optionator@0.9.4: + resolution: {integrity: sha512-6IpQ7mKUxRcZNLIObR0hz7lxsapSSIYNZJwXPGeF0mTVqGKFIXj1DQcMoT22S3ROcLyY/rz0PWaWZ9ayWmad9g==} + engines: {node: '>= 0.8.0'} + + p-limit@2.3.0: + resolution: {integrity: sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==} + engines: {node: '>=6'} + + p-limit@3.1.0: + resolution: {integrity: sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==} + engines: {node: '>=10'} + + p-limit@5.0.0: + resolution: {integrity: sha512-/Eaoq+QyLSiXQ4lyYV23f14mZRQcXnxfHrN0vCai+ak9G0pp9iEQukIIZq5NccEvwRB8PUnZT0KsOoDCINS1qQ==} + engines: {node: '>=18'} + + p-locate@4.1.0: + resolution: {integrity: sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==} + engines: {node: '>=8'} + + p-locate@5.0.0: + resolution: {integrity: sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==} + engines: {node: '>=10'} + + p-try@2.2.0: + resolution: {integrity: sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==} + engines: {node: '>=6'} + + parent-module@1.0.1: + resolution: {integrity: sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==} + engines: {node: '>=6'} + + parse-json@5.2.0: + resolution: {integrity: sha512-ayCKvm/phCGxOkYRSCM82iDwct8/EonSEgCSxWxD7ve6jHggsFl4fZVQBPRNgQoKiuV/odhFrGzQXZwbifC8Rg==} + engines: {node: '>=8'} + + path-exists@4.0.0: + resolution: {integrity: sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==} + engines: {node: '>=8'} + + path-is-absolute@1.0.1: + resolution: {integrity: sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==} + engines: {node: '>=0.10.0'} + + path-key@3.1.1: + resolution: {integrity: sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==} + engines: {node: '>=8'} + + path-key@4.0.0: + resolution: {integrity: sha512-haREypq7xkM7ErfgIyA0z+Bj4AGKlMSdlQE2jvJo6huWD1EdkKYV+G/T4nq0YEF2vgTT8kqMFKo1uHn950r4SQ==} + engines: {node: '>=12'} + + path-parse@1.0.7: + resolution: {integrity: sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==} + + pathe@1.1.2: + resolution: {integrity: sha512-whLdWMYL2TwI08hn8/ZqAbrVemu0LNaNNJZX73O6qaIdCTfXutsLhMkjdENX0qhsQ9uIimo4/aQOmXkoon2nDQ==} + + pathval@1.1.1: + resolution: {integrity: sha512-Dp6zGqpTdETdR63lehJYPeIOqpiNBNtc7BpWSLrOje7UaIsE5aY92r/AunQA7rsXvet3lrJ3JnZX29UPTKXyKQ==} + + picocolors@1.0.0: + resolution: {integrity: sha512-1fygroTLlHu66zi26VoTDv8yRgm0Fccecssto+MhsZ0D/DGW2sm8E8AjW7NU5VVTRt5GxbeZ5qBuJr+HyLYkjQ==} + + picocolors@1.0.1: + resolution: {integrity: sha512-anP1Z8qwhkbmu7MFP5iTt+wQKXgwzf7zTyGlcdzabySa9vd0Xt392U0rVmz9poOaBj0uHJKyyo9/upk0HrEQew==} + + pkg-types@1.1.1: + resolution: {integrity: sha512-ko14TjmDuQJ14zsotODv7dBlwxKhUKQEhuhmbqo1uCi9BB0Z2alo/wAXg6q1dTR5TyuqYyWhjtfe/Tsh+X28jQ==} + + pluralize@8.0.0: + resolution: {integrity: sha512-Nc3IT5yHzflTfbjgqWcCPpo7DaKy4FnpB0l/zCAW0Tc7jxAiuqSxHasntB3D7887LSrA93kDJ9IXovxJYxyLCA==} + engines: {node: '>=4'} + + possible-typed-array-names@1.0.0: + resolution: {integrity: sha512-d7Uw+eZoloe0EHDIYoe+bQ5WXnGMOpmiZFTuMWCwpjzzkL2nTjcKiAk4hh8TjnGye2TwWOk3UXucZ+3rbmBa8Q==} + engines: {node: '>= 0.4'} + + postcss@8.4.38: + resolution: {integrity: sha512-Wglpdk03BSfXkHoQa3b/oulrotAkwrlLDRSOb9D0bN86FdRyE9lppSp33aHNPgBa0JKCoB+drFLZkQoRRYae5A==} + engines: {node: ^10 || ^12 || >=14} + + prelude-ls@1.2.1: + resolution: {integrity: sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==} + engines: {node: '>= 0.8.0'} + + pretty-format@29.7.0: + resolution: {integrity: sha512-Pdlw/oPxN+aXdmM9R00JVC9WVFoCLTKJvDVLgmJ+qAffBMxsV85l/Lu7sNx4zSzPyoL2euImuEwHhOXdEgNFZQ==} + engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} + + punycode@2.3.1: + resolution: {integrity: sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==} + engines: {node: '>=6'} + + queue-microtask@1.2.3: + resolution: {integrity: sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==} + + react-is@18.2.0: + resolution: {integrity: sha512-xWGDIW6x921xtzPkhiULtthJHoJvBbF3q26fzloPCK0hsvxtPVelvftw3zjbHWSkR2km9Z+4uxbDDK/6Zw9B8w==} + + read-pkg-up@7.0.1: + resolution: {integrity: sha512-zK0TB7Xd6JpCLmlLmufqykGE+/TlOePD6qKClNW7hHDKFh/J7/7gCWGR7joEQEW1bKq3a3yUZSObOoWLFQ4ohg==} + engines: {node: '>=8'} + + read-pkg@5.2.0: + resolution: {integrity: sha512-Ug69mNOpfvKDAc2Q8DRpMjjzdtrnv9HcSMX+4VsZxD1aZ6ZzrIE7rlzXBtWTyhULSMKg076AW6WR5iZpD0JiOg==} + engines: {node: '>=8'} + + regexp-tree@0.1.27: + resolution: {integrity: sha512-iETxpjK6YoRWJG5o6hXLwvjYAoW+FEZn9os0PD/b6AP6xQwsa/Y7lCVgIixBbUPMfhu+i2LtdeAqVTgGlQarfA==} + hasBin: true + + regexp.prototype.flags@1.5.2: + resolution: {integrity: sha512-NcDiDkTLuPR+++OCKB0nWafEmhg/Da8aUPLPMQbK+bxKKCm1/S5he+AqYa4PlMCVBalb4/yxIRub6qkEx5yJbw==} + engines: {node: '>= 0.4'} + + regexpp@3.2.0: + resolution: {integrity: sha512-pq2bWo9mVD43nbts2wGv17XLiNLya+GklZ8kaDLV2Z08gDCsGpnKn9BFMepvWuHCbyVvY7J5o5+BVvoQbmlJLg==} + engines: {node: '>=8'} + + regjsparser@0.10.0: + resolution: {integrity: sha512-qx+xQGZVsy55CH0a1hiVwHmqjLryfh7wQyF5HO07XJ9f7dQMY/gPQHhlyDkIzJKC+x2fUCpCcUODUUUFrm7SHA==} + hasBin: true + + resolve-from@4.0.0: + resolution: {integrity: sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==} + engines: {node: '>=4'} + + resolve@1.22.8: + resolution: {integrity: sha512-oKWePCxqpd6FlLvGV1VU0x7bkPmmCNolxzjMf4NczoDnQcIWrAF+cPtZn5i6n+RfD2d9i0tzpKnG6Yk168yIyw==} + hasBin: true + + reusify@1.0.4: + resolution: {integrity: sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw==} + engines: {iojs: '>=1.0.0', node: '>=0.10.0'} + + rimraf@3.0.2: + resolution: {integrity: sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==} + deprecated: Rimraf versions prior to v4 are no longer supported + hasBin: true + + rollup@4.18.0: + resolution: {integrity: sha512-QmJz14PX3rzbJCN1SG4Xe/bAAX2a6NpCP8ab2vfu2GiUr8AQcr2nCV/oEO3yneFarB67zk8ShlIyWb2LGTb3Sg==} + engines: {node: '>=18.0.0', npm: '>=8.0.0'} + hasBin: true + + run-parallel@1.2.0: + resolution: {integrity: sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==} + + safe-array-concat@1.1.2: + resolution: {integrity: sha512-vj6RsCsWBCf19jIeHEfkRMw8DPiBb+DMXklQ/1SGDHOMlHdPUkZXFQ2YdplS23zESTijAcurb1aSgJA3AgMu1Q==} + engines: {node: '>=0.4'} + + safe-regex-test@1.0.3: + resolution: {integrity: sha512-CdASjNJPvRa7roO6Ra/gLYBTzYzzPyyBXxIMdGW3USQLyjWEls2RgW5UBTXaQVp+OrpeCK3bLem8smtmheoRuw==} + engines: {node: '>= 0.4'} + + safe-regex@2.1.1: + resolution: {integrity: sha512-rx+x8AMzKb5Q5lQ95Zoi6ZbJqwCLkqi3XuJXp5P3rT8OEc6sZCJG5AE5dU3lsgRr/F4Bs31jSlVN+j5KrsGu9A==} + + semver@5.7.2: + resolution: {integrity: sha512-cBznnQ9KjJqU67B52RMC65CMarK2600WFnbkcaiwWq3xy/5haFJlshgnpjovMVJ+Hff49d8GEn0b87C5pDQ10g==} + hasBin: true + + semver@6.3.1: + resolution: {integrity: sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==} + hasBin: true + + semver@7.6.2: + resolution: {integrity: sha512-FNAIBWCx9qcRhoHcgcJ0gvU7SN1lYU2ZXuSfl04bSC5OpvDHFyJCjdNHomPXxjQlCBU67YW64PzY7/VIEH7F2w==} + engines: {node: '>=10'} + hasBin: true + + set-function-length@1.2.2: + resolution: {integrity: sha512-pgRc4hJ4/sNjWCSS9AmnS40x3bNMDTknHgL5UaMBTMyJnU90EgWh1Rz+MC9eFu4BuN/UwZjKQuY/1v3rM7HMfg==} + engines: {node: '>= 0.4'} + + set-function-name@2.0.2: + resolution: {integrity: sha512-7PGFlmtwsEADb0WYyvCMa1t+yke6daIG4Wirafur5kcf+MhUnPms1UeR0CKQdTZD81yESwMHbtn+TR+dMviakQ==} + engines: {node: '>= 0.4'} + + shebang-command@2.0.0: + resolution: {integrity: sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==} + engines: {node: '>=8'} + + shebang-regex@3.0.0: + resolution: {integrity: sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==} + engines: {node: '>=8'} + + side-channel@1.0.6: + resolution: {integrity: sha512-fDW/EZ6Q9RiO8eFG8Hj+7u/oW+XrPTIChwCOM2+th2A6OblDtYYIpve9m+KvI9Z4C9qSEXlaGR6bTEYHReuglA==} + engines: {node: '>= 0.4'} + + siginfo@2.0.0: + resolution: {integrity: sha512-ybx0WO1/8bSBLEWXZvEd7gMW3Sn3JFlW3TvX1nREbDLRNQNaeNN8WK0meBwPdAaOI7TtRRRJn/Es1zhrrCHu7g==} + + signal-exit@4.1.0: + resolution: {integrity: sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==} + engines: {node: '>=14'} + + source-map-js@1.2.0: + resolution: {integrity: sha512-itJW8lvSA0TXEphiRoawsCksnlf8SyvmFzIhltqAHluXd88pkCd+cXJVHTDwdCr0IzwptSm035IHQktUu1QUMg==} + engines: {node: '>=0.10.0'} + + spdx-correct@3.2.0: + resolution: {integrity: sha512-kN9dJbvnySHULIluDHy32WHRUu3Og7B9sbY7tsFLctQkIqnMh3hErYgdMjTYuqmcXX+lK5T1lnUt3G7zNswmZA==} + + spdx-exceptions@2.5.0: + resolution: {integrity: sha512-PiU42r+xO4UbUS1buo3LPJkjlO7430Xn5SVAhdpzzsPHsjbYVflnnFdATgabnLude+Cqu25p6N+g2lw/PFsa4w==} + + spdx-expression-parse@3.0.1: + resolution: {integrity: sha512-cbqHunsQWnJNE6KhVSMsMeH5H/L9EpymbzqTQ3uLwNCLZ1Q481oWaofqH7nO6V07xlXwY6PhQdQ2IedWx/ZK4Q==} + + spdx-license-ids@3.0.18: + resolution: {integrity: sha512-xxRs31BqRYHwiMzudOrpSiHtZ8i/GeionCBDSilhYRj+9gIcI8wCZTlXZKu9vZIVqViP3dcp9qE5G6AlIaD+TQ==} + + stackback@0.0.2: + resolution: {integrity: sha512-1XMJE5fQo1jGH6Y/7ebnwPOBEkIEnT4QF32d5R1+VXdXveM0IBMJt8zfaxX1P3QhVwrYe+576+jkANtSS2mBbw==} + + std-env@3.7.0: + resolution: {integrity: sha512-JPbdCEQLj1w5GilpiHAx3qJvFndqybBysA3qUOnznweH4QbNYUsW/ea8QzSrnh0vNsezMMw5bcVool8lM0gwzg==} + + string.prototype.trim@1.2.9: + resolution: {integrity: sha512-klHuCNxiMZ8MlsOihJhJEBJAiMVqU3Z2nEXWfWnIqjN0gEFS9J9+IxKozWWtQGcgoa1WUZzLjKPTr4ZHNFTFxw==} + engines: {node: '>= 0.4'} + + string.prototype.trimend@1.0.8: + resolution: {integrity: sha512-p73uL5VCHCO2BZZ6krwwQE3kCzM7NKmis8S//xEC6fQonchbum4eP6kR4DLEjQFO3Wnj3Fuo8NM0kOSjVdHjZQ==} + + string.prototype.trimstart@1.0.8: + resolution: {integrity: sha512-UXSH262CSZY1tfu3G3Secr6uGLCFVPMhIqHjlgCUtCCcgihYc/xKs9djMTMUOb2j1mVSeU8EU6NWc/iQKU6Gfg==} + engines: {node: '>= 0.4'} + + strip-ansi@6.0.1: + resolution: {integrity: sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==} + engines: {node: '>=8'} + + strip-bom@3.0.0: + resolution: {integrity: sha512-vavAMRXOgBVNF6nyEEmL3DBK19iRpDcoIwW+swQ+CbGiu7lju6t+JklA1MHweoWtadgt4ISVUsXLyDq34ddcwA==} + engines: {node: '>=4'} + + strip-final-newline@3.0.0: + resolution: {integrity: sha512-dOESqjYr96iWYylGObzd39EuNTa5VJxyvVAEm5Jnh7KGo75V43Hk1odPQkNDyXNmUR6k+gEiDVXnjB8HJ3crXw==} + engines: {node: '>=12'} + + strip-indent@3.0.0: + resolution: {integrity: sha512-laJTa3Jb+VQpaC6DseHhF7dXVqHTfJPCRDaEbid/drOhgitgYku/letMUqOXFoWV0zIIUbjpdH2t+tYj4bQMRQ==} + engines: {node: '>=8'} + + strip-json-comments@3.1.1: + resolution: {integrity: sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==} + engines: {node: '>=8'} + + strip-literal@2.1.0: + resolution: {integrity: sha512-Op+UycaUt/8FbN/Z2TWPBLge3jWrP3xj10f3fnYxf052bKuS3EKs1ZQcVGjnEMdsNVAM+plXRdmjrZ/KgG3Skw==} + + supports-color@5.5.0: + resolution: {integrity: sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==} + engines: {node: '>=4'} + + supports-color@7.2.0: + resolution: {integrity: sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==} + engines: {node: '>=8'} + + supports-preserve-symlinks-flag@1.0.0: + resolution: {integrity: sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==} + engines: {node: '>= 0.4'} + + text-table@0.2.0: + resolution: {integrity: sha512-N+8UisAXDGk8PFXP4HAzVR9nbfmVJ3zYLAWiTIoqC5v5isinhr+r5uaO8+7r3BMfuNIufIsA7RdpVgacC2cSpw==} + + tinybench@2.8.0: + resolution: {integrity: sha512-1/eK7zUnIklz4JUUlL+658n58XO2hHLQfSk1Zf2LKieUjxidN16eKFEoDEfjHc3ohofSSqK3X5yO6VGb6iW8Lw==} + + tinypool@0.8.4: + resolution: {integrity: sha512-i11VH5gS6IFeLY3gMBQ00/MmLncVP7JLXOw1vlgkytLmJK7QnEr7NXf0LBdxfmNPAeyetukOk0bOYrJrFGjYJQ==} + engines: {node: '>=14.0.0'} + + tinyspy@2.2.1: + resolution: {integrity: sha512-KYad6Vy5VDWV4GH3fjpseMQ/XU2BhIYP7Vzd0LG44qRWm/Yt2WCOTicFdvmgo6gWaqooMQCawTtILVQJupKu7A==} + engines: {node: '>=14.0.0'} + + to-fast-properties@2.0.0: + resolution: {integrity: sha512-/OaKK0xYrs3DmxRYqL/yDc+FxFUVYhDlXMhRmv3z915w2HF1tnN1omB354j8VUGO/hbRzyD6Y3sA7v7GS/ceog==} + engines: {node: '>=4'} + + tsconfig-paths@3.15.0: + resolution: {integrity: sha512-2Ac2RgzDe/cn48GvOe3M+o82pEFewD3UPbyoUHHdKasHwJKjds4fLXWf/Ux5kATBKN20oaFGu+jbElp1pos0mg==} + + type-check@0.4.0: + resolution: {integrity: sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==} + engines: {node: '>= 0.8.0'} + + type-detect@4.0.8: + resolution: {integrity: sha512-0fr/mIH1dlO+x7TlcMy+bIDqKPsw/70tVyeHW787goQjhmqaZe10uwLujubK9q9Lg6Fiho1KUKDYz0Z7k7g5/g==} + engines: {node: '>=4'} + + type-fest@0.20.2: + resolution: {integrity: sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ==} + engines: {node: '>=10'} + + type-fest@0.6.0: + resolution: {integrity: sha512-q+MB8nYR1KDLrgr4G5yemftpMC7/QLqVndBmEEdqzmNj5dcFOO4Oo8qlwZE3ULT3+Zim1F8Kq4cBnikNhlCMlg==} + engines: {node: '>=8'} + + type-fest@0.8.1: + resolution: {integrity: sha512-4dbzIzqvjtgiM5rw1k5rEHtBANKmdudhGyBEajN01fEyhaAIhsoKNy6y7+IN93IfpFtwY9iqi7kD+xwKhQsNJA==} + engines: {node: '>=8'} + + typed-array-buffer@1.0.2: + resolution: {integrity: sha512-gEymJYKZtKXzzBzM4jqa9w6Q1Jjm7x2d+sh19AdsD4wqnMPDYyvwpsIc2Q/835kHuo3BEQ7CjelGhfTsoBb2MQ==} + engines: {node: '>= 0.4'} + + typed-array-byte-length@1.0.1: + resolution: {integrity: sha512-3iMJ9q0ao7WE9tWcaYKIptkNBuOIcZCCT0d4MRvuuH88fEoEH62IuQe0OtraD3ebQEoTRk8XCBoknUNc1Y67pw==} + engines: {node: '>= 0.4'} + + typed-array-byte-offset@1.0.2: + resolution: {integrity: sha512-Ous0vodHa56FviZucS2E63zkgtgrACj7omjwd/8lTEMEPFFyjfixMZ1ZXenpgCFBBt4EC1J2XsyVS2gkG0eTFA==} + engines: {node: '>= 0.4'} + + typed-array-length@1.0.6: + resolution: {integrity: sha512-/OxDN6OtAk5KBpGb28T+HZc2M+ADtvRxXrKKbUwtsLgdoxgX13hyy7ek6bFRl5+aBs2yZzB0c4CnQfAtVypW/g==} + engines: {node: '>= 0.4'} + + ufo@1.5.3: + resolution: {integrity: sha512-Y7HYmWaFwPUmkoQCUIAYpKqkOf+SbVj/2fJJZ4RJMCfZp0rTGwRbzQD+HghfnhKOjL9E01okqz+ncJskGYfBNw==} + + unbox-primitive@1.0.2: + resolution: {integrity: sha512-61pPlCD9h51VoreyJ0BReideM3MDKMKnh6+V9L08331ipq6Q8OFXZYiqP6n/tbHx4s5I9uRhcye6BrbkizkBDw==} + + undici-types@5.26.5: + resolution: {integrity: sha512-JlCMO+ehdEIKqlFxk6IfVoAUVmgz7cU7zD/h9XZ0qzeosSHmUJVOzSQvvYSYWXkFXC+IfLKSIffhv0sVZup6pA==} + + update-browserslist-db@1.0.16: + resolution: {integrity: sha512-KVbTxlBYlckhF5wgfyZXTWnMn7MMZjMu9XG8bPlliUOP9ThaF4QnhP8qrjrH7DRzHfSk0oQv1wToW+iA5GajEQ==} + hasBin: true + peerDependencies: + browserslist: '>= 4.21.0' + + uri-js@4.4.1: + resolution: {integrity: sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==} + + valibot@0.35.0: + resolution: {integrity: sha512-+i2aCRkReTrd5KBN/dW2BrPOvFnU5LXTV2xjZnjnqUIO8YUx6P2+MgRrkwF2FhkexgyKq/NIZdPdknhHf5A/Ww==} + + validate-npm-package-license@3.0.4: + resolution: {integrity: sha512-DpKm2Ui/xN7/HQKCtpZxoRWBhZ9Z0kqtygG8XCgNQ8ZlDnxuQmWhj566j8fN4Cu3/JmbhsDo7fcAJq4s9h27Ew==} + + vite-node@1.6.0: + resolution: {integrity: sha512-de6HJgzC+TFzOu0NTC4RAIsyf/DY/ibWDYQUcuEA84EMHhcefTUGkjFHKKEJhQN4A+6I0u++kr3l36ZF2d7XRw==} + engines: {node: ^18.0.0 || >=20.0.0} + hasBin: true + + vite@5.3.1: + resolution: {integrity: sha512-XBmSKRLXLxiaPYamLv3/hnP/KXDai1NDexN0FpkTaZXTfycHvkRHoenpgl/fvuK/kPbB6xAgoyiryAhQNxYmAQ==} + engines: {node: ^18.0.0 || >=20.0.0} + hasBin: true + peerDependencies: + '@types/node': ^18.0.0 || >=20.0.0 + less: '*' + lightningcss: ^1.21.0 + sass: '*' + stylus: '*' + sugarss: '*' + terser: ^5.4.0 + peerDependenciesMeta: + '@types/node': + optional: true + less: + optional: true + lightningcss: + optional: true + sass: + optional: true + stylus: + optional: true + sugarss: + optional: true + terser: + optional: true + + vitest@1.6.0: + resolution: {integrity: sha512-H5r/dN06swuFnzNFhq/dnz37bPXnq8xB2xB5JOVk8K09rUtoeNN+LHWkoQ0A/i3hvbUKKcCei9KpbxqHMLhLLA==} + engines: {node: ^18.0.0 || >=20.0.0} + hasBin: true + peerDependencies: + '@edge-runtime/vm': '*' + '@types/node': ^18.0.0 || >=20.0.0 + '@vitest/browser': 1.6.0 + '@vitest/ui': 1.6.0 + happy-dom: '*' + jsdom: '*' + peerDependenciesMeta: + '@edge-runtime/vm': + optional: true + '@types/node': + optional: true + '@vitest/browser': + optional: true + '@vitest/ui': + optional: true + happy-dom: + optional: true + jsdom: + optional: true + + which-boxed-primitive@1.0.2: + resolution: {integrity: sha512-bwZdv0AKLpplFY2KZRX6TvyuN7ojjr7lwkg6ml0roIy9YeuSr7JS372qlNW18UQYzgYK9ziGcerWqZOmEn9VNg==} + + which-typed-array@1.1.15: + resolution: {integrity: sha512-oV0jmFtUky6CXfkqehVvBP/LSWJ2sy4vWMioiENyJLePrBO/yKyV9OyJySfAKosh+RYkIl5zJCNZ8/4JncrpdA==} + engines: {node: '>= 0.4'} + + which@2.0.2: + resolution: {integrity: sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==} + engines: {node: '>= 8'} + hasBin: true + + why-is-node-running@2.2.2: + resolution: {integrity: sha512-6tSwToZxTOcotxHeA+qGCq1mVzKR3CwcJGmVcY+QE8SHy6TnpFnh8PAvPNHYr7EcuVeG0QSMxtYCuO1ta/G/oA==} + engines: {node: '>=8'} + hasBin: true + + word-wrap@1.2.5: + resolution: {integrity: sha512-BN22B5eaMMI9UMtjrGd5g5eCYPpCPDUy0FJXbYsaT5zYxjFOckS53SQDE3pWkVoWpHXVb3BrYcEN4Twa55B5cA==} + engines: {node: '>=0.10.0'} + + wrappy@1.0.2: + resolution: {integrity: sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==} + + yallist@3.1.1: + resolution: {integrity: sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==} + + yocto-queue@0.1.0: + resolution: {integrity: sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==} + engines: {node: '>=10'} + + yocto-queue@1.0.0: + resolution: {integrity: sha512-9bnSc/HEW2uRy67wc+T8UwauLuPJVn28jb+GtJY16iiKWyvmYJRXVT4UamsAEGQfPohgr2q4Tq0sQbQlxTfi1g==} + engines: {node: '>=12.20'} + +snapshots: + + '@ampproject/remapping@2.3.0': + dependencies: + '@jridgewell/gen-mapping': 0.3.5 + '@jridgewell/trace-mapping': 0.3.25 + + '@babel/code-frame@7.24.7': + dependencies: + '@babel/highlight': 7.24.7 + picocolors: 1.0.0 + + '@babel/compat-data@7.24.7': {} + + '@babel/core@7.24.7': + dependencies: + '@ampproject/remapping': 2.3.0 + '@babel/code-frame': 7.24.7 + '@babel/generator': 7.24.7 + '@babel/helper-compilation-targets': 7.24.7 + '@babel/helper-module-transforms': 7.24.7(@babel/core@7.24.7) + '@babel/helpers': 7.24.7 + '@babel/parser': 7.24.7 + '@babel/template': 7.24.7 + '@babel/traverse': 7.24.7 + '@babel/types': 7.24.7 + convert-source-map: 2.0.0 + debug: 4.3.4 + gensync: 1.0.0-beta.2 + json5: 2.2.3 + semver: 6.3.1 + transitivePeerDependencies: + - supports-color + + '@babel/eslint-parser@7.21.8(@babel/core@7.24.7)(eslint@8.41.0)': + dependencies: + '@babel/core': 7.24.7 + '@nicolo-ribaudo/eslint-scope-5-internals': 5.1.1-v1 + eslint: 8.41.0 + eslint-visitor-keys: 2.1.0 + semver: 6.3.1 + + '@babel/generator@7.24.7': + dependencies: + '@babel/types': 7.24.7 + '@jridgewell/gen-mapping': 0.3.5 + '@jridgewell/trace-mapping': 0.3.25 + jsesc: 2.5.2 + + '@babel/helper-compilation-targets@7.24.7': + dependencies: + '@babel/compat-data': 7.24.7 + '@babel/helper-validator-option': 7.24.7 + browserslist: 4.23.1 + lru-cache: 5.1.1 + semver: 6.3.1 + + '@babel/helper-environment-visitor@7.24.7': + dependencies: + '@babel/types': 7.24.7 + + '@babel/helper-function-name@7.24.7': + dependencies: + '@babel/template': 7.24.7 + '@babel/types': 7.24.7 + + '@babel/helper-hoist-variables@7.24.7': + dependencies: + '@babel/types': 7.24.7 + + '@babel/helper-module-imports@7.24.7': + dependencies: + '@babel/traverse': 7.24.7 + '@babel/types': 7.24.7 + transitivePeerDependencies: + - supports-color + + '@babel/helper-module-transforms@7.24.7(@babel/core@7.24.7)': + dependencies: + '@babel/core': 7.24.7 + '@babel/helper-environment-visitor': 7.24.7 + '@babel/helper-module-imports': 7.24.7 + '@babel/helper-simple-access': 7.24.7 + '@babel/helper-split-export-declaration': 7.24.7 + '@babel/helper-validator-identifier': 7.24.7 + transitivePeerDependencies: + - supports-color + + '@babel/helper-simple-access@7.24.7': + dependencies: + '@babel/traverse': 7.24.7 + '@babel/types': 7.24.7 + transitivePeerDependencies: + - supports-color + + '@babel/helper-split-export-declaration@7.24.7': + dependencies: + '@babel/types': 7.24.7 + + '@babel/helper-string-parser@7.24.7': {} + + '@babel/helper-validator-identifier@7.24.7': {} + + '@babel/helper-validator-option@7.24.7': {} + + '@babel/helpers@7.24.7': + dependencies: + '@babel/template': 7.24.7 + '@babel/types': 7.24.7 + + '@babel/highlight@7.24.7': + dependencies: + '@babel/helper-validator-identifier': 7.24.7 + chalk: 2.4.2 + js-tokens: 4.0.0 + picocolors: 1.0.0 + + '@babel/parser@7.24.7': + dependencies: + '@babel/types': 7.24.7 + + '@babel/template@7.24.7': + dependencies: + '@babel/code-frame': 7.24.7 + '@babel/parser': 7.24.7 + '@babel/types': 7.24.7 + + '@babel/traverse@7.24.7': + dependencies: + '@babel/code-frame': 7.24.7 + '@babel/generator': 7.24.7 + '@babel/helper-environment-visitor': 7.24.7 + '@babel/helper-function-name': 7.24.7 + '@babel/helper-hoist-variables': 7.24.7 + '@babel/helper-split-export-declaration': 7.24.7 + '@babel/parser': 7.24.7 + '@babel/types': 7.24.7 + debug: 4.3.4 + globals: 11.12.0 + transitivePeerDependencies: + - supports-color + + '@babel/types@7.24.7': + dependencies: + '@babel/helper-string-parser': 7.24.7 + '@babel/helper-validator-identifier': 7.24.7 + to-fast-properties: 2.0.0 + + '@es-joy/jsdoccomment@0.40.1': + dependencies: + comment-parser: 1.4.0 + esquery: 1.5.0 + jsdoc-type-pratt-parser: 4.0.0 + + '@esbuild/aix-ppc64@0.21.5': + optional: true + + '@esbuild/android-arm64@0.21.5': + optional: true + + '@esbuild/android-arm@0.21.5': + optional: true + + '@esbuild/android-x64@0.21.5': + optional: true + + '@esbuild/darwin-arm64@0.21.5': + optional: true + + '@esbuild/darwin-x64@0.21.5': + optional: true + + '@esbuild/freebsd-arm64@0.21.5': + optional: true + + '@esbuild/freebsd-x64@0.21.5': + optional: true + + '@esbuild/linux-arm64@0.21.5': + optional: true + + '@esbuild/linux-arm@0.21.5': + optional: true + + '@esbuild/linux-ia32@0.21.5': + optional: true + + '@esbuild/linux-loong64@0.21.5': + optional: true + + '@esbuild/linux-mips64el@0.21.5': + optional: true + + '@esbuild/linux-ppc64@0.21.5': + optional: true + + '@esbuild/linux-riscv64@0.21.5': + optional: true + + '@esbuild/linux-s390x@0.21.5': + optional: true + + '@esbuild/linux-x64@0.21.5': + optional: true + + '@esbuild/netbsd-x64@0.21.5': + optional: true + + '@esbuild/openbsd-x64@0.21.5': + optional: true + + '@esbuild/sunos-x64@0.21.5': + optional: true + + '@esbuild/win32-arm64@0.21.5': + optional: true + + '@esbuild/win32-ia32@0.21.5': + optional: true + + '@esbuild/win32-x64@0.21.5': + optional: true + + '@eslint-community/eslint-utils@4.4.0(eslint@8.41.0)': + dependencies: + eslint: 8.41.0 + eslint-visitor-keys: 3.4.3 + + '@eslint-community/regexpp@4.10.1': {} + + '@eslint/eslintrc@2.1.4': + dependencies: + ajv: 6.12.6 + debug: 4.3.4 + espree: 9.6.1 + globals: 13.24.0 + ignore: 5.3.1 + import-fresh: 3.3.0 + js-yaml: 4.1.0 + minimatch: 3.1.2 + strip-json-comments: 3.1.1 + transitivePeerDependencies: + - supports-color + + '@eslint/js@8.41.0': {} + + '@humanwhocodes/config-array@0.11.14': + dependencies: + '@humanwhocodes/object-schema': 2.0.3 + debug: 4.3.4 + minimatch: 3.1.2 + transitivePeerDependencies: + - supports-color + + '@humanwhocodes/module-importer@1.0.1': {} + + '@humanwhocodes/object-schema@2.0.3': {} + + '@jest/schemas@29.6.3': + dependencies: + '@sinclair/typebox': 0.27.8 + + '@jridgewell/gen-mapping@0.3.5': + dependencies: + '@jridgewell/set-array': 1.2.1 + '@jridgewell/sourcemap-codec': 1.4.15 + '@jridgewell/trace-mapping': 0.3.25 + + '@jridgewell/resolve-uri@3.1.2': {} + + '@jridgewell/set-array@1.2.1': {} + + '@jridgewell/sourcemap-codec@1.4.15': {} + + '@jridgewell/trace-mapping@0.3.25': + dependencies: + '@jridgewell/resolve-uri': 3.1.2 + '@jridgewell/sourcemap-codec': 1.4.15 + + '@nicolo-ribaudo/eslint-scope-5-internals@5.1.1-v1': + dependencies: + eslint-scope: 5.1.1 + + '@nodelib/fs.scandir@2.1.5': + dependencies: + '@nodelib/fs.stat': 2.0.5 + run-parallel: 1.2.0 + + '@nodelib/fs.stat@2.0.5': {} + + '@nodelib/fs.walk@1.2.8': + dependencies: + '@nodelib/fs.scandir': 2.1.5 + fastq: 1.17.1 + + '@rollup/rollup-android-arm-eabi@4.18.0': + optional: true + + '@rollup/rollup-android-arm64@4.18.0': + optional: true + + '@rollup/rollup-darwin-arm64@4.18.0': + optional: true + + '@rollup/rollup-darwin-x64@4.18.0': + optional: true + + '@rollup/rollup-linux-arm-gnueabihf@4.18.0': + optional: true + + '@rollup/rollup-linux-arm-musleabihf@4.18.0': + optional: true + + '@rollup/rollup-linux-arm64-gnu@4.18.0': + optional: true + + '@rollup/rollup-linux-arm64-musl@4.18.0': + optional: true + + '@rollup/rollup-linux-powerpc64le-gnu@4.18.0': + optional: true + + '@rollup/rollup-linux-riscv64-gnu@4.18.0': + optional: true + + '@rollup/rollup-linux-s390x-gnu@4.18.0': + optional: true + + '@rollup/rollup-linux-x64-gnu@4.18.0': + optional: true + + '@rollup/rollup-linux-x64-musl@4.18.0': + optional: true + + '@rollup/rollup-win32-arm64-msvc@4.18.0': + optional: true + + '@rollup/rollup-win32-ia32-msvc@4.18.0': + optional: true + + '@rollup/rollup-win32-x64-msvc@4.18.0': + optional: true + + '@sinclair/typebox@0.27.8': {} + + '@types/estree@1.0.5': {} + + '@types/json5@0.0.29': {} + + '@types/node@20.14.8': + dependencies: + undici-types: 5.26.5 + + '@types/normalize-package-data@2.4.4': {} + + '@vitest/expect@1.6.0': + dependencies: + '@vitest/spy': 1.6.0 + '@vitest/utils': 1.6.0 + chai: 4.4.1 + + '@vitest/runner@1.6.0': + dependencies: + '@vitest/utils': 1.6.0 + p-limit: 5.0.0 + pathe: 1.1.2 + + '@vitest/snapshot@1.6.0': + dependencies: + magic-string: 0.30.10 + pathe: 1.1.2 + pretty-format: 29.7.0 + + '@vitest/spy@1.6.0': + dependencies: + tinyspy: 2.2.1 + + '@vitest/utils@1.6.0': + dependencies: + diff-sequences: 29.6.3 + estree-walker: 3.0.3 + loupe: 2.3.7 + pretty-format: 29.7.0 + + acorn-jsx@5.3.2(acorn@8.12.0): + dependencies: + acorn: 8.12.0 + + acorn-walk@8.3.3: + dependencies: + acorn: 8.12.0 + + acorn@8.12.0: {} + + ajv@6.12.6: + dependencies: + fast-deep-equal: 3.1.3 + fast-json-stable-stringify: 2.1.0 + json-schema-traverse: 0.4.1 + uri-js: 4.4.1 + + ansi-regex@5.0.1: {} + + ansi-styles@3.2.1: + dependencies: + color-convert: 1.9.3 + + ansi-styles@4.3.0: + dependencies: + color-convert: 2.0.1 + + ansi-styles@5.2.0: {} + + are-docs-informative@0.0.2: {} + + argparse@2.0.1: {} + + array-buffer-byte-length@1.0.1: + dependencies: + call-bind: 1.0.7 + is-array-buffer: 3.0.4 + + array-includes@3.1.8: + dependencies: + call-bind: 1.0.7 + define-properties: 1.2.1 + es-abstract: 1.23.3 + es-object-atoms: 1.0.0 + get-intrinsic: 1.2.4 + is-string: 1.0.7 + + array.prototype.flat@1.3.2: + dependencies: + call-bind: 1.0.7 + define-properties: 1.2.1 + es-abstract: 1.23.3 + es-shim-unscopables: 1.0.2 + + array.prototype.flatmap@1.3.2: + dependencies: + call-bind: 1.0.7 + define-properties: 1.2.1 + es-abstract: 1.23.3 + es-shim-unscopables: 1.0.2 + + arraybuffer.prototype.slice@1.0.3: + dependencies: + array-buffer-byte-length: 1.0.1 + call-bind: 1.0.7 + define-properties: 1.2.1 + es-abstract: 1.23.3 + es-errors: 1.3.0 + get-intrinsic: 1.2.4 + is-array-buffer: 3.0.4 + is-shared-array-buffer: 1.0.3 + + assertion-error@1.1.0: {} + + available-typed-arrays@1.0.7: + dependencies: + possible-typed-array-names: 1.0.0 + + balanced-match@1.0.2: {} + + brace-expansion@1.1.11: + dependencies: + balanced-match: 1.0.2 + concat-map: 0.0.1 + + browserslist@4.23.1: + dependencies: + caniuse-lite: 1.0.30001636 + electron-to-chromium: 1.4.811 + node-releases: 2.0.14 + update-browserslist-db: 1.0.16(browserslist@4.23.1) + + builtin-modules@3.3.0: {} + + cac@6.7.14: {} + + call-bind@1.0.7: + 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.2 + + callsites@3.1.0: {} + + caniuse-lite@1.0.30001636: {} + + chai@4.4.1: + dependencies: + assertion-error: 1.1.0 + check-error: 1.0.3 + deep-eql: 4.1.4 + get-func-name: 2.0.2 + loupe: 2.3.7 + pathval: 1.1.1 + type-detect: 4.0.8 + + chalk@2.4.2: + dependencies: + ansi-styles: 3.2.1 + escape-string-regexp: 1.0.5 + supports-color: 5.5.0 + + chalk@4.1.2: + dependencies: + ansi-styles: 4.3.0 + supports-color: 7.2.0 + + check-error@1.0.3: + dependencies: + get-func-name: 2.0.2 + + ci-info@3.9.0: {} + + clean-regexp@1.0.0: + dependencies: + escape-string-regexp: 1.0.5 + + color-convert@1.9.3: + dependencies: + color-name: 1.1.3 + + color-convert@2.0.1: + dependencies: + color-name: 1.1.4 + + color-name@1.1.3: {} + + color-name@1.1.4: {} + + comment-parser@1.4.0: {} + + concat-map@0.0.1: {} + + confbox@0.1.7: {} + + confusing-browser-globals@1.0.11: {} + + convert-source-map@2.0.0: {} + + cross-spawn@7.0.3: + dependencies: + path-key: 3.1.1 + shebang-command: 2.0.0 + which: 2.0.2 + + data-view-buffer@1.0.1: + dependencies: + call-bind: 1.0.7 + es-errors: 1.3.0 + is-data-view: 1.0.1 + + data-view-byte-length@1.0.1: + dependencies: + call-bind: 1.0.7 + es-errors: 1.3.0 + is-data-view: 1.0.1 + + data-view-byte-offset@1.0.0: + dependencies: + call-bind: 1.0.7 + es-errors: 1.3.0 + is-data-view: 1.0.1 + + debug@3.2.7: + dependencies: + ms: 2.1.2 + + debug@4.3.4: + dependencies: + ms: 2.1.2 + + deep-eql@4.1.4: + dependencies: + type-detect: 4.0.8 + + deep-is@0.1.4: {} + + define-data-property@1.1.4: + dependencies: + es-define-property: 1.0.0 + es-errors: 1.3.0 + gopd: 1.0.1 + + define-properties@1.2.1: + dependencies: + define-data-property: 1.1.4 + has-property-descriptors: 1.0.2 + object-keys: 1.1.1 + + diff-sequences@29.6.3: {} + + doctrine@2.1.0: + dependencies: + esutils: 2.0.3 + + doctrine@3.0.0: + dependencies: + esutils: 2.0.3 + + electron-to-chromium@1.4.811: {} + + error-ex@1.3.2: + dependencies: + is-arrayish: 0.2.1 + + es-abstract@1.23.3: + 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.4 + 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.2 + 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 + + es-define-property@1.0.0: + dependencies: + get-intrinsic: 1.2.4 + + es-errors@1.3.0: {} + + es-object-atoms@1.0.0: + dependencies: + es-errors: 1.3.0 + + es-set-tostringtag@2.0.3: + dependencies: + get-intrinsic: 1.2.4 + has-tostringtag: 1.0.2 + hasown: 2.0.2 + + es-shim-unscopables@1.0.2: + dependencies: + hasown: 2.0.2 + + es-to-primitive@1.2.1: + dependencies: + is-callable: 1.2.7 + is-date-object: 1.0.5 + is-symbol: 1.0.4 + + esbuild@0.21.5: + optionalDependencies: + '@esbuild/aix-ppc64': 0.21.5 + '@esbuild/android-arm': 0.21.5 + '@esbuild/android-arm64': 0.21.5 + '@esbuild/android-x64': 0.21.5 + '@esbuild/darwin-arm64': 0.21.5 + '@esbuild/darwin-x64': 0.21.5 + '@esbuild/freebsd-arm64': 0.21.5 + '@esbuild/freebsd-x64': 0.21.5 + '@esbuild/linux-arm': 0.21.5 + '@esbuild/linux-arm64': 0.21.5 + '@esbuild/linux-ia32': 0.21.5 + '@esbuild/linux-loong64': 0.21.5 + '@esbuild/linux-mips64el': 0.21.5 + '@esbuild/linux-ppc64': 0.21.5 + '@esbuild/linux-riscv64': 0.21.5 + '@esbuild/linux-s390x': 0.21.5 + '@esbuild/linux-x64': 0.21.5 + '@esbuild/netbsd-x64': 0.21.5 + '@esbuild/openbsd-x64': 0.21.5 + '@esbuild/sunos-x64': 0.21.5 + '@esbuild/win32-arm64': 0.21.5 + '@esbuild/win32-ia32': 0.21.5 + '@esbuild/win32-x64': 0.21.5 + + escalade@3.1.2: {} + + escape-string-regexp@1.0.5: {} + + escape-string-regexp@4.0.0: {} + + eslint-config-xo@0.43.1(eslint@8.41.0): + dependencies: + confusing-browser-globals: 1.0.11 + eslint: 8.41.0 + + eslint-import-resolver-node@0.3.9: + dependencies: + debug: 3.2.7 + is-core-module: 2.14.0 + resolve: 1.22.8 + transitivePeerDependencies: + - supports-color + + eslint-module-utils@2.8.1(eslint-import-resolver-node@0.3.9)(eslint@8.41.0): + dependencies: + debug: 3.2.7 + optionalDependencies: + eslint: 8.41.0 + eslint-import-resolver-node: 0.3.9 + transitivePeerDependencies: + - supports-color + + eslint-plugin-es@3.0.1(eslint@8.41.0): + dependencies: + eslint: 8.41.0 + eslint-utils: 2.1.0 + regexpp: 3.2.0 + + eslint-plugin-import@2.27.5(eslint@8.41.0): + dependencies: + array-includes: 3.1.8 + array.prototype.flat: 1.3.2 + array.prototype.flatmap: 1.3.2 + debug: 3.2.7 + doctrine: 2.1.0 + eslint: 8.41.0 + eslint-import-resolver-node: 0.3.9 + eslint-module-utils: 2.8.1(eslint-import-resolver-node@0.3.9)(eslint@8.41.0) + has: 1.0.4 + is-core-module: 2.14.0 + is-glob: 4.0.3 + minimatch: 3.1.2 + object.values: 1.2.0 + resolve: 1.22.8 + semver: 6.3.1 + tsconfig-paths: 3.15.0 + transitivePeerDependencies: + - eslint-import-resolver-typescript + - eslint-import-resolver-webpack + - supports-color + + eslint-plugin-jsdoc@46.5.0(eslint@8.41.0): + dependencies: + '@es-joy/jsdoccomment': 0.40.1 + are-docs-informative: 0.0.2 + comment-parser: 1.4.0 + debug: 4.3.4 + escape-string-regexp: 4.0.0 + eslint: 8.41.0 + esquery: 1.5.0 + is-builtin-module: 3.2.1 + semver: 7.6.2 + spdx-expression-parse: 3.0.1 + transitivePeerDependencies: + - supports-color + + eslint-plugin-node@11.1.0(eslint@8.41.0): + dependencies: + eslint: 8.41.0 + eslint-plugin-es: 3.0.1(eslint@8.41.0) + eslint-utils: 2.1.0 + ignore: 5.3.1 + minimatch: 3.1.2 + resolve: 1.22.8 + semver: 6.3.1 + + eslint-plugin-promise@6.1.1(eslint@8.41.0): + dependencies: + eslint: 8.41.0 + + eslint-plugin-unicorn@47.0.0(eslint@8.41.0): + dependencies: + '@babel/helper-validator-identifier': 7.24.7 + '@eslint-community/eslint-utils': 4.4.0(eslint@8.41.0) + ci-info: 3.9.0 + clean-regexp: 1.0.0 + eslint: 8.41.0 + esquery: 1.5.0 + indent-string: 4.0.0 + is-builtin-module: 3.2.1 + jsesc: 3.0.2 + lodash: 4.17.21 + pluralize: 8.0.0 + read-pkg-up: 7.0.1 + regexp-tree: 0.1.27 + regjsparser: 0.10.0 + safe-regex: 2.1.1 + semver: 7.6.2 + strip-indent: 3.0.0 + + eslint-scope@5.1.1: + dependencies: + esrecurse: 4.3.0 + estraverse: 4.3.0 + + eslint-scope@7.2.2: + dependencies: + esrecurse: 4.3.0 + estraverse: 5.3.0 + + eslint-utils@2.1.0: + dependencies: + eslint-visitor-keys: 1.3.0 + + eslint-visitor-keys@1.3.0: {} + + eslint-visitor-keys@2.1.0: {} + + eslint-visitor-keys@3.4.3: {} + + eslint@8.41.0: + dependencies: + '@eslint-community/eslint-utils': 4.4.0(eslint@8.41.0) + '@eslint-community/regexpp': 4.10.1 + '@eslint/eslintrc': 2.1.4 + '@eslint/js': 8.41.0 + '@humanwhocodes/config-array': 0.11.14 + '@humanwhocodes/module-importer': 1.0.1 + '@nodelib/fs.walk': 1.2.8 + ajv: 6.12.6 + chalk: 4.1.2 + cross-spawn: 7.0.3 + debug: 4.3.4 + 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.5.0 + esutils: 2.0.3 + fast-deep-equal: 3.1.3 + file-entry-cache: 6.0.1 + find-up: 5.0.0 + glob-parent: 6.0.2 + globals: 13.24.0 + graphemer: 1.4.0 + ignore: 5.3.1 + import-fresh: 3.3.0 + imurmurhash: 0.1.4 + is-glob: 4.0.3 + 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.4 + strip-ansi: 6.0.1 + strip-json-comments: 3.1.1 + text-table: 0.2.0 + transitivePeerDependencies: + - supports-color + + espree@9.6.1: + dependencies: + acorn: 8.12.0 + acorn-jsx: 5.3.2(acorn@8.12.0) + eslint-visitor-keys: 3.4.3 + + esquery@1.5.0: + dependencies: + estraverse: 5.3.0 + + esrecurse@4.3.0: + dependencies: + estraverse: 5.3.0 + + estraverse@4.3.0: {} + + estraverse@5.3.0: {} + + estree-walker@3.0.3: + dependencies: + '@types/estree': 1.0.5 + + esutils@2.0.3: {} + + execa@8.0.1: + dependencies: + cross-spawn: 7.0.3 + get-stream: 8.0.1 + human-signals: 5.0.0 + is-stream: 3.0.0 + merge-stream: 2.0.0 + npm-run-path: 5.3.0 + onetime: 6.0.0 + signal-exit: 4.1.0 + strip-final-newline: 3.0.0 + + fast-deep-equal@3.1.3: {} + + fast-json-stable-stringify@2.1.0: {} + + fast-levenshtein@2.0.6: {} + + fastq@1.17.1: + dependencies: + reusify: 1.0.4 + + file-entry-cache@6.0.1: + dependencies: + flat-cache: 3.2.0 + + find-up@4.1.0: + dependencies: + locate-path: 5.0.0 + path-exists: 4.0.0 + + find-up@5.0.0: + dependencies: + locate-path: 6.0.0 + path-exists: 4.0.0 + + flat-cache@3.2.0: + dependencies: + flatted: 3.3.1 + keyv: 4.5.4 + rimraf: 3.0.2 + + flatted@3.3.1: {} + + for-each@0.3.3: + dependencies: + is-callable: 1.2.7 + + fs.realpath@1.0.0: {} + + fsevents@2.3.3: + optional: true + + function-bind@1.1.2: {} + + function.prototype.name@1.1.6: + dependencies: + call-bind: 1.0.7 + define-properties: 1.2.1 + es-abstract: 1.23.3 + functions-have-names: 1.2.3 + + functions-have-names@1.2.3: {} + + gensync@1.0.0-beta.2: {} + + get-func-name@2.0.2: {} + + get-intrinsic@1.2.4: + dependencies: + es-errors: 1.3.0 + function-bind: 1.1.2 + has-proto: 1.0.3 + has-symbols: 1.0.3 + hasown: 2.0.2 + + get-stream@8.0.1: {} + + get-symbol-description@1.0.2: + dependencies: + call-bind: 1.0.7 + es-errors: 1.3.0 + get-intrinsic: 1.2.4 + + glob-parent@6.0.2: + dependencies: + is-glob: 4.0.3 + + glob@7.2.3: + dependencies: + fs.realpath: 1.0.0 + inflight: 1.0.6 + inherits: 2.0.4 + minimatch: 3.1.2 + once: 1.4.0 + path-is-absolute: 1.0.1 + + globals@11.12.0: {} + + globals@13.24.0: + dependencies: + type-fest: 0.20.2 + + globalthis@1.0.4: + dependencies: + define-properties: 1.2.1 + gopd: 1.0.1 + + gopd@1.0.1: + dependencies: + get-intrinsic: 1.2.4 + + graphemer@1.4.0: {} + + has-bigints@1.0.2: {} + + has-flag@3.0.0: {} + + has-flag@4.0.0: {} + + has-property-descriptors@1.0.2: + dependencies: + es-define-property: 1.0.0 + + has-proto@1.0.3: {} + + has-symbols@1.0.3: {} + + has-tostringtag@1.0.2: + dependencies: + has-symbols: 1.0.3 + + has@1.0.4: {} + + hasown@2.0.2: + dependencies: + function-bind: 1.1.2 + + hosted-git-info@2.8.9: {} + + human-signals@5.0.0: {} + + ignore@5.3.1: {} + + import-fresh@3.3.0: + dependencies: + parent-module: 1.0.1 + resolve-from: 4.0.0 + + imurmurhash@0.1.4: {} + + indent-string@4.0.0: {} + + inflight@1.0.6: + dependencies: + once: 1.4.0 + wrappy: 1.0.2 + + inherits@2.0.4: {} + + internal-slot@1.0.7: + dependencies: + es-errors: 1.3.0 + hasown: 2.0.2 + side-channel: 1.0.6 + + is-array-buffer@3.0.4: + dependencies: + call-bind: 1.0.7 + get-intrinsic: 1.2.4 + + is-arrayish@0.2.1: {} + + is-bigint@1.0.4: + dependencies: + has-bigints: 1.0.2 + + is-boolean-object@1.1.2: + dependencies: + call-bind: 1.0.7 + has-tostringtag: 1.0.2 + + is-builtin-module@3.2.1: + dependencies: + builtin-modules: 3.3.0 + + is-callable@1.2.7: {} + + is-core-module@2.14.0: + dependencies: + hasown: 2.0.2 + + is-data-view@1.0.1: + dependencies: + is-typed-array: 1.1.13 + + is-date-object@1.0.5: + dependencies: + has-tostringtag: 1.0.2 + + is-extglob@2.1.1: {} + + is-glob@4.0.3: + dependencies: + is-extglob: 2.1.1 + + is-negative-zero@2.0.3: {} + + is-number-object@1.0.7: + dependencies: + has-tostringtag: 1.0.2 + + is-path-inside@3.0.3: {} + + is-regex@1.1.4: + dependencies: + call-bind: 1.0.7 + has-tostringtag: 1.0.2 + + is-shared-array-buffer@1.0.3: + dependencies: + call-bind: 1.0.7 + + is-stream@3.0.0: {} + + is-string@1.0.7: + dependencies: + has-tostringtag: 1.0.2 + + is-symbol@1.0.4: + dependencies: + has-symbols: 1.0.3 + + is-typed-array@1.1.13: + dependencies: + which-typed-array: 1.1.15 + + is-weakref@1.0.2: + dependencies: + call-bind: 1.0.7 + + isarray@2.0.5: {} + + isexe@2.0.0: {} + + js-tokens@4.0.0: {} + + js-tokens@9.0.0: {} + + js-yaml@4.1.0: + dependencies: + argparse: 2.0.1 + + jsdoc-type-pratt-parser@4.0.0: {} + + jsesc@0.5.0: {} + + jsesc@2.5.2: {} + + jsesc@3.0.2: {} + + json-buffer@3.0.1: {} + + json-parse-even-better-errors@2.3.1: {} + + json-schema-traverse@0.4.1: {} + + json-stable-stringify-without-jsonify@1.0.1: {} + + json5@1.0.2: + dependencies: + minimist: 1.2.8 + + json5@2.2.3: {} + + keyv@4.5.4: + dependencies: + json-buffer: 3.0.1 + + levn@0.4.1: + dependencies: + prelude-ls: 1.2.1 + type-check: 0.4.0 + + lines-and-columns@1.2.4: {} + + local-pkg@0.5.0: + dependencies: + mlly: 1.7.1 + pkg-types: 1.1.1 + + locate-path@5.0.0: + dependencies: + p-locate: 4.1.0 + + locate-path@6.0.0: + dependencies: + p-locate: 5.0.0 + + lodash.merge@4.6.2: {} + + lodash@4.17.21: {} + + loupe@2.3.7: + dependencies: + get-func-name: 2.0.2 + + lru-cache@5.1.1: + dependencies: + yallist: 3.1.1 + + magic-string@0.30.10: + dependencies: + '@jridgewell/sourcemap-codec': 1.4.15 + + merge-stream@2.0.0: {} + + mimic-fn@4.0.0: {} + + min-indent@1.0.1: {} + + minimatch@3.1.2: + dependencies: + brace-expansion: 1.1.11 + + minimist@1.2.8: {} + + mlly@1.7.1: + dependencies: + acorn: 8.12.0 + pathe: 1.1.2 + pkg-types: 1.1.1 + ufo: 1.5.3 + + ms@2.1.2: {} + + nanoid@3.3.7: {} + + natural-compare@1.4.0: {} + + node-releases@2.0.14: {} + + normalize-package-data@2.5.0: + dependencies: + hosted-git-info: 2.8.9 + resolve: 1.22.8 + semver: 5.7.2 + validate-npm-package-license: 3.0.4 + + npm-run-path@5.3.0: + dependencies: + path-key: 4.0.0 + + object-inspect@1.13.2: {} + + object-keys@1.1.1: {} + + object.assign@4.1.5: + dependencies: + call-bind: 1.0.7 + define-properties: 1.2.1 + has-symbols: 1.0.3 + object-keys: 1.1.1 + + object.values@1.2.0: + dependencies: + call-bind: 1.0.7 + define-properties: 1.2.1 + es-object-atoms: 1.0.0 + + once@1.4.0: + dependencies: + wrappy: 1.0.2 + + onetime@6.0.0: + dependencies: + mimic-fn: 4.0.0 + + optionator@0.9.4: + dependencies: + deep-is: 0.1.4 + fast-levenshtein: 2.0.6 + levn: 0.4.1 + prelude-ls: 1.2.1 + type-check: 0.4.0 + word-wrap: 1.2.5 + + p-limit@2.3.0: + dependencies: + p-try: 2.2.0 + + p-limit@3.1.0: + dependencies: + yocto-queue: 0.1.0 + + p-limit@5.0.0: + dependencies: + yocto-queue: 1.0.0 + + p-locate@4.1.0: + dependencies: + p-limit: 2.3.0 + + p-locate@5.0.0: + dependencies: + p-limit: 3.1.0 + + p-try@2.2.0: {} + + parent-module@1.0.1: + dependencies: + callsites: 3.1.0 + + parse-json@5.2.0: + dependencies: + '@babel/code-frame': 7.24.7 + error-ex: 1.3.2 + json-parse-even-better-errors: 2.3.1 + lines-and-columns: 1.2.4 + + path-exists@4.0.0: {} + + path-is-absolute@1.0.1: {} + + path-key@3.1.1: {} + + path-key@4.0.0: {} + + path-parse@1.0.7: {} + + pathe@1.1.2: {} + + pathval@1.1.1: {} + + picocolors@1.0.0: {} + + picocolors@1.0.1: {} + + pkg-types@1.1.1: + dependencies: + confbox: 0.1.7 + mlly: 1.7.1 + pathe: 1.1.2 + + pluralize@8.0.0: {} + + possible-typed-array-names@1.0.0: {} + + postcss@8.4.38: + dependencies: + nanoid: 3.3.7 + picocolors: 1.0.1 + source-map-js: 1.2.0 + + prelude-ls@1.2.1: {} + + pretty-format@29.7.0: + dependencies: + '@jest/schemas': 29.6.3 + ansi-styles: 5.2.0 + react-is: 18.2.0 + + punycode@2.3.1: {} + + queue-microtask@1.2.3: {} + + react-is@18.2.0: {} + + read-pkg-up@7.0.1: + dependencies: + find-up: 4.1.0 + read-pkg: 5.2.0 + type-fest: 0.8.1 + + read-pkg@5.2.0: + dependencies: + '@types/normalize-package-data': 2.4.4 + normalize-package-data: 2.5.0 + parse-json: 5.2.0 + type-fest: 0.6.0 + + regexp-tree@0.1.27: {} + + regexp.prototype.flags@1.5.2: + dependencies: + call-bind: 1.0.7 + define-properties: 1.2.1 + es-errors: 1.3.0 + set-function-name: 2.0.2 + + regexpp@3.2.0: {} + + regjsparser@0.10.0: + dependencies: + jsesc: 0.5.0 + + resolve-from@4.0.0: {} + + resolve@1.22.8: + dependencies: + is-core-module: 2.14.0 + path-parse: 1.0.7 + supports-preserve-symlinks-flag: 1.0.0 + + reusify@1.0.4: {} + + rimraf@3.0.2: + dependencies: + glob: 7.2.3 + + rollup@4.18.0: + dependencies: + '@types/estree': 1.0.5 + optionalDependencies: + '@rollup/rollup-android-arm-eabi': 4.18.0 + '@rollup/rollup-android-arm64': 4.18.0 + '@rollup/rollup-darwin-arm64': 4.18.0 + '@rollup/rollup-darwin-x64': 4.18.0 + '@rollup/rollup-linux-arm-gnueabihf': 4.18.0 + '@rollup/rollup-linux-arm-musleabihf': 4.18.0 + '@rollup/rollup-linux-arm64-gnu': 4.18.0 + '@rollup/rollup-linux-arm64-musl': 4.18.0 + '@rollup/rollup-linux-powerpc64le-gnu': 4.18.0 + '@rollup/rollup-linux-riscv64-gnu': 4.18.0 + '@rollup/rollup-linux-s390x-gnu': 4.18.0 + '@rollup/rollup-linux-x64-gnu': 4.18.0 + '@rollup/rollup-linux-x64-musl': 4.18.0 + '@rollup/rollup-win32-arm64-msvc': 4.18.0 + '@rollup/rollup-win32-ia32-msvc': 4.18.0 + '@rollup/rollup-win32-x64-msvc': 4.18.0 + fsevents: 2.3.3 + + run-parallel@1.2.0: + dependencies: + queue-microtask: 1.2.3 + + safe-array-concat@1.1.2: + dependencies: + call-bind: 1.0.7 + get-intrinsic: 1.2.4 + has-symbols: 1.0.3 + isarray: 2.0.5 + + safe-regex-test@1.0.3: + dependencies: + call-bind: 1.0.7 + es-errors: 1.3.0 + is-regex: 1.1.4 + + safe-regex@2.1.1: + dependencies: + regexp-tree: 0.1.27 + + semver@5.7.2: {} + + semver@6.3.1: {} + + semver@7.6.2: {} + + set-function-length@1.2.2: + 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 + + set-function-name@2.0.2: + dependencies: + define-data-property: 1.1.4 + es-errors: 1.3.0 + functions-have-names: 1.2.3 + has-property-descriptors: 1.0.2 + + shebang-command@2.0.0: + dependencies: + shebang-regex: 3.0.0 + + shebang-regex@3.0.0: {} + + side-channel@1.0.6: + dependencies: + call-bind: 1.0.7 + es-errors: 1.3.0 + get-intrinsic: 1.2.4 + object-inspect: 1.13.2 + + siginfo@2.0.0: {} + + signal-exit@4.1.0: {} + + source-map-js@1.2.0: {} + + spdx-correct@3.2.0: + dependencies: + spdx-expression-parse: 3.0.1 + spdx-license-ids: 3.0.18 + + spdx-exceptions@2.5.0: {} + + spdx-expression-parse@3.0.1: + dependencies: + spdx-exceptions: 2.5.0 + spdx-license-ids: 3.0.18 + + spdx-license-ids@3.0.18: {} + + stackback@0.0.2: {} + + std-env@3.7.0: {} + + string.prototype.trim@1.2.9: + dependencies: + call-bind: 1.0.7 + define-properties: 1.2.1 + es-abstract: 1.23.3 + es-object-atoms: 1.0.0 + + string.prototype.trimend@1.0.8: + dependencies: + call-bind: 1.0.7 + define-properties: 1.2.1 + es-object-atoms: 1.0.0 + + string.prototype.trimstart@1.0.8: + dependencies: + call-bind: 1.0.7 + define-properties: 1.2.1 + es-object-atoms: 1.0.0 + + strip-ansi@6.0.1: + dependencies: + ansi-regex: 5.0.1 + + strip-bom@3.0.0: {} + + strip-final-newline@3.0.0: {} + + strip-indent@3.0.0: + dependencies: + min-indent: 1.0.1 + + strip-json-comments@3.1.1: {} + + strip-literal@2.1.0: + dependencies: + js-tokens: 9.0.0 + + supports-color@5.5.0: + dependencies: + has-flag: 3.0.0 + + supports-color@7.2.0: + dependencies: + has-flag: 4.0.0 + + supports-preserve-symlinks-flag@1.0.0: {} + + text-table@0.2.0: {} + + tinybench@2.8.0: {} + + tinypool@0.8.4: {} + + tinyspy@2.2.1: {} + + to-fast-properties@2.0.0: {} + + tsconfig-paths@3.15.0: + dependencies: + '@types/json5': 0.0.29 + json5: 1.0.2 + minimist: 1.2.8 + strip-bom: 3.0.0 + + type-check@0.4.0: + dependencies: + prelude-ls: 1.2.1 + + type-detect@4.0.8: {} + + type-fest@0.20.2: {} + + type-fest@0.6.0: {} + + type-fest@0.8.1: {} + + typed-array-buffer@1.0.2: + dependencies: + call-bind: 1.0.7 + es-errors: 1.3.0 + is-typed-array: 1.1.13 + + typed-array-byte-length@1.0.1: + 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 + + typed-array-byte-offset@1.0.2: + 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 + + typed-array-length@1.0.6: + 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 + + ufo@1.5.3: {} + + unbox-primitive@1.0.2: + dependencies: + call-bind: 1.0.7 + has-bigints: 1.0.2 + has-symbols: 1.0.3 + which-boxed-primitive: 1.0.2 + + undici-types@5.26.5: {} + + update-browserslist-db@1.0.16(browserslist@4.23.1): + dependencies: + browserslist: 4.23.1 + escalade: 3.1.2 + picocolors: 1.0.1 + + uri-js@4.4.1: + dependencies: + punycode: 2.3.1 + + valibot@0.35.0: {} + + validate-npm-package-license@3.0.4: + dependencies: + spdx-correct: 3.2.0 + spdx-expression-parse: 3.0.1 + + vite-node@1.6.0(@types/node@20.14.8): + dependencies: + cac: 6.7.14 + debug: 4.3.4 + pathe: 1.1.2 + picocolors: 1.0.1 + vite: 5.3.1(@types/node@20.14.8) + transitivePeerDependencies: + - '@types/node' + - less + - lightningcss + - sass + - stylus + - sugarss + - supports-color + - terser + + vite@5.3.1(@types/node@20.14.8): + dependencies: + esbuild: 0.21.5 + postcss: 8.4.38 + rollup: 4.18.0 + optionalDependencies: + '@types/node': 20.14.8 + fsevents: 2.3.3 + + vitest@1.6.0(@types/node@20.14.8): + dependencies: + '@vitest/expect': 1.6.0 + '@vitest/runner': 1.6.0 + '@vitest/snapshot': 1.6.0 + '@vitest/spy': 1.6.0 + '@vitest/utils': 1.6.0 + acorn-walk: 8.3.3 + chai: 4.4.1 + debug: 4.3.4 + execa: 8.0.1 + local-pkg: 0.5.0 + magic-string: 0.30.10 + pathe: 1.1.2 + picocolors: 1.0.1 + std-env: 3.7.0 + strip-literal: 2.1.0 + tinybench: 2.8.0 + tinypool: 0.8.4 + vite: 5.3.1(@types/node@20.14.8) + vite-node: 1.6.0(@types/node@20.14.8) + why-is-node-running: 2.2.2 + optionalDependencies: + '@types/node': 20.14.8 + transitivePeerDependencies: + - less + - lightningcss + - sass + - stylus + - sugarss + - supports-color + - terser + + which-boxed-primitive@1.0.2: + dependencies: + is-bigint: 1.0.4 + is-boolean-object: 1.1.2 + is-number-object: 1.0.7 + is-string: 1.0.7 + is-symbol: 1.0.4 + + which-typed-array@1.1.15: + 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 + + which@2.0.2: + dependencies: + isexe: 2.0.0 + + why-is-node-running@2.2.2: + dependencies: + siginfo: 2.0.0 + stackback: 0.0.2 + + word-wrap@1.2.5: {} + + wrappy@1.0.2: {} + + yallist@3.1.1: {} + + yocto-queue@0.1.0: {} + + yocto-queue@1.0.0: {} diff --git a/src/driver.js b/src/driver.js index 641e2fc..e4db53b 100644 --- a/src/driver.js +++ b/src/driver.js @@ -1,24 +1,29 @@ -import { HyperAPIRequest } from './request.js'; - -/** - * @typedef {import('./response.js').default} HyperAPIResponse - */ +import { HyperAPIRequest } from './request.js'; +import { HyperAPIResponse } from './response.js'; export class HyperAPIDriver extends EventTarget { /** - * Processes a request and waits for the response. - * @async - * @param {HyperAPIRequest} request The HyperAPI request. - * @returns {Promise} The HyperAPI response. + * @param {HyperAPIRequest} request - + * @returns {Promise} - */ - onRequest(request) { - if (request instanceof HyperAPIRequest !== true) { - throw new TypeError('Argument 0 must be an instance of HyperAPIRequest.'); - } + async processRequest(request) { + const promise = new Promise((resolve) => { + this.addEventListener( + request.response_event_name, + (response) => { + if (response instanceof HyperAPIResponse) { + resolve(response); + } + }, + { + once: true, + }, + ); + }); this.dispatchEvent(request); - return request.wait(); + return promise; } } diff --git a/src/error.js b/src/error.js index 6fe3319..24b0691 100644 --- a/src/error.js +++ b/src/error.js @@ -1,4 +1,11 @@ +/** + * @typedef {object} HyperAPIErrorResponse + * @property {number} code - The error code. + * @property {string} [description] - The error description. + * @property {{[key: string]: any}} [data] - The error data. + */ + export class HyperAPIError extends Error { /** * The error code. @@ -16,52 +23,56 @@ export class HyperAPIError extends Error { /** * The error data. - * @type {{[key: string]: *}?} + * @type {{[key: string]: any}} * @readonly */ - data = null; + data; + + /** @type {number?} */ + httpStatus; + + /** @type {Record?} */ + httpHeaders; /** - * @param {{[key: string]: *}?} data The error data. Cannot contain "code" or "description" properties. + * @param {{[key: string]: any}} [data] The error data. */ - constructor(data = null) { + constructor(data) { super(); - if ( - data !== null - && typeof data !== 'object' - ) { - throw new TypeError('Argument 0 must be an object or not be provided'); + if (data !== null && typeof data === 'object') { + this.data = data; } - - if ( - data - && ( - 'code' in data - || 'description' in data - ) - ) { - throw new TypeError('Argument 0 must not contain "code" or "description" properties'); + else if (data !== undefined) { + throw new TypeError('Argument 0 must be an object or not be provided'); } - - this.data = data; } + /** + * @returns {string} - + */ get message() { return `${this.description ?? ''} (code ${this.code})`; } + /** + * Creates response object. + * @returns {HyperAPIErrorResponse} - + */ getResponse() { + /** @type {HyperAPIErrorResponse} */ const result = { code: this.code, }; + if (typeof this.description === 'string') { result.description = this.description; } - return { - ...result, - ...this.data, - }; + if (this.data) { + result.data = this.data; + } + + return result; } } diff --git a/src/main.js b/src/main.js index d7f1cf7..23656aa 100644 --- a/src/main.js +++ b/src/main.js @@ -1,28 +1,39 @@ +/** + * @typedef {object} HyperAPIModule + * @property {function(HyperAPIRequest): HyperAPIModuleResponse | Promise} default Core function of the API method. + * @property {function({ [key: string]: any }): { [key: string]: any } | Promise<{ [key: string]: any }>} [argsValidator] - Function that validates `args` property of the HyperAPIRequest. Should return validated args or throw an error. + * @typedef {Record | any[] | undefined} HyperAPIModuleResponse + */ + import { dirname, join as joinPath } from 'node:path'; -import { HyperAPIInternalError } from './api-errors.js'; +import { + HyperAPIInternalError, + HyperAPIUnknownMethodError } from './api-errors.js'; import { HyperAPIDriver } from './driver.js'; import { HyperAPIError } from './error.js'; +import { HyperAPIRequest } from './request.js'; import { HyperAPIResponse } from './response.js'; const ENTRYPOINT_PATH = dirname(process.argv[1]); -/** - * @typedef {import('./request.js').HyperAPIRequest} HyperAPIRequest - */ - export class HyperAPI { + /** @type {HyperAPIDriver} The HyperAPI driver. */ #driver; + + /** @type {string} The root directory for API methods modules. */ #root; - #turnDriverOff; + + /** @type {function(HyperAPIRequest): void} Handles a request. */ + #requestHandler; /** * Creates a HyperAPI instance. * @param {object} options The options. * @param {HyperAPIDriver} options.driver The HyperAPI driver. - * @param {string=} options.root The root directory for API methods modules. Defaults to "/hyper-api" inside the current working directory. + * @param {string} [options.root] The root directory for API methods modules. Default: `hyper-api` directory alongside the entrypoint script. */ constructor({ driver, @@ -36,37 +47,41 @@ export class HyperAPI { } this.#driver = driver; - this.#root = root; - - this.#setUpListener(); - } - - #setUpListener() { - const handler = async (request) => { + this.#requestHandler = async (request) => { try { - request._respondWith( - await this.#handleRequest(request), - ); + const response = await this.#handleRequest(request); + + this.#driver.dispatchEvent(response); } catch (error) { // should never happen console.error('Unexpected error happened:'); console.error(error); - process.exit(); // eslint-disable-line no-process-exit, unicorn/no-process-exit + console.error('This error should not have reached this point.'); + console.error('This is probably a bug in the HyperAPI driver you are using or in the HyperAPI itself.'); + console.error('Now exiting the process.'); + + // eslint-disable-next-line no-process-exit, unicorn/no-process-exit + process.exit(1); } }; this.#driver.addEventListener( - 'HyperAPIRequest', - handler, + 'request', + this.#requestHandler, ); - this.#turnDriverOff = () => { - this.#driver.removeEventListener( - 'HyperAPIRequest', - handler, - ); - }; + this.#root = root; + } + + /** + * Removes the request event listener from the driver. + */ + #turnDriverOff() { + this.#driver.removeEventListener( + 'request', + this.#requestHandler, + ); } /** @@ -76,8 +91,11 @@ export class HyperAPI { */ async #handleRequest(request) { try { - const response = await this.#useModule(request); - return new HyperAPIResponse(response); + const response_data = await this.#useModule(request); + return new HyperAPIResponse( + request, + response_data, + ); } catch (error) { // error must be an instance of HyperAPIError @@ -87,14 +105,78 @@ export class HyperAPI { error = new HyperAPIInternalError(); } - return new HyperAPIResponse(error); + return new HyperAPIResponse( + request, + error, + ); } } + /** + * Processes a request and returns the response. + * @param {HyperAPIRequest} request The HyperAPI request. + * @returns {Promise} The HyperAPI response. + */ + async #getModule(request) { + const filenames = [ + request.module_path, + `${request.module_path}.js`, + `${request.module_path}.mjs`, + `${request.module_path}.cjs`, + joinPath(request.module_path, 'index.js'), + ]; + + for (const filename of filenames) { + const path = joinPath( + this.#root, + filename, + ); + + try { + // eslint-disable-next-line no-await-in-loop + return await import(path); + } + catch (error) { + if ( + error.code === 'MODULE_NOT_FOUND' // node + || error.code === 'ERR_MODULE_NOT_FOUND' // bun + ) { + const path_error = error.moduleName // node + ?? error.specifier // bun + ?? new URL(error.url).pathname; // node v20.10 in raw, not in jest's test env + + // skip error only if we cannot found the module itself + if (path === path_error) { + continue; + } + } + + // vitest + if ( + error instanceof Error + && error.message.startsWith(`Failed to load url ${path} `) + ) { + continue; + } + + throw error; + } + } + + throw new HyperAPIUnknownMethodError(); + } + + /** + * Processes a request and returns the response. + * @param {HyperAPIRequest} request The HyperAPI request. + * @returns {Promise} The HyperAPI response. + */ async #useModule(request) { - const module = await request._getModule(this.#root); + const module = await this.#getModule(request); if (typeof module.argsValidator === 'function') { + // We assign to the readonly property "args" only internally, so we can safely ignore the TS error. + // @ts-ignore request.args = await module.argsValidator(request.args); } diff --git a/src/main.test.js b/src/main.test.js index 063bff9..65036f0 100644 --- a/src/main.test.js +++ b/src/main.test.js @@ -1,20 +1,25 @@ -/* global describe, test, expect */ /* eslint-disable jsdoc/require-jsdoc */ +// @ts-check + +import { + afterAll, + describe, + test, + expect } from 'vitest'; import { HyperAPIDriver } from './driver.js'; import { HyperAPI } from './main.js'; import { HyperAPIRequest } from './request.js'; const driver = new HyperAPIDriver(); -// eslint-disable-next-line no-unused-vars const api = new HyperAPI({ driver, root: new URL('../test/api', import.meta.url).pathname, }); async function request(method, args = {}) { - const response = await driver.onRequest( + const response = await driver.processRequest( new HyperAPIRequest( method, args, @@ -27,6 +32,10 @@ async function request(method, args = {}) { ]; } +afterAll(() => { + api.destroy(); +}); + describe('HyperAPI', () => { test('correct request (sync)', async () => { const result = await request( diff --git a/src/request.js b/src/request.js index 01e8593..9173558 100644 --- a/src/request.js +++ b/src/request.js @@ -1,98 +1,40 @@ -import { join as joinPath } from 'node:path'; -import { HyperAPIUnknownMethodError } from './api-errors.js'; +import { randomUUID } from 'node:crypto'; /** - * @typedef {import('./response.js').default} HyperAPIResponse + * @class HyperAPIRequest + * @template {Record} [HyperAPIRequestArgs={}] */ - export class HyperAPIRequest extends Event { - #data = new Map(); - /** - * @param {string} module_path The relative path to the API method module. - * @param {Array<*>} args The arguments to pass to the API method. + * The unique identifier for this request. + * @type {string} + * @readonly */ - constructor(module_path, args) { - super('HyperAPIRequest'); - - this.module_path = module_path; - this.args = args; - this.flags = {}; - } + response_event_name = 'response:' + randomUUID(); /** - * @param {*} key The key to get. - * @returns {*} The value. + * The relative path to the JavaScript module that contains requested API method. + * @type {string} + * @readonly */ - get(key) { - return this.#data.get(key); - } + module_path; /** - * @param {*} key The key to set. - * @param {*} value The value to set. + * Request arguments to pass to the API method. + * @type {HyperAPIRequestArgs} + * @readonly */ - set(key, value) { - this.#data.set(key, value); - } - - async _getModule(root) { - const filenames = [ - this.module_path, - `${this.module_path}.js`, - `${this.module_path}.mjs`, - `${this.module_path}.cjs`, - joinPath(this.module_path, 'index.js'), - ]; - - for (const filename of filenames) { - const path = joinPath( - root, - filename, - ); - - try { - // eslint-disable-next-line no-await-in-loop - return await import(path); - } - catch (error) { - if ( - error.code === 'MODULE_NOT_FOUND' // node - || error.code === 'ERR_MODULE_NOT_FOUND' // bun - ) { - const path_error = error.moduleName // node - ?? error.specifier // bun - ?? new URL(error.url).pathname; // node v20.10 in raw, not in jest's test env - // skip error only if we cannot found the module itself - if (path === path_error) { - continue; - } - } - - throw error; - } - } - - throw new HyperAPIUnknownMethodError(); - } - - #resolve; - #promise = new Promise((resolve) => { - this.#resolve = resolve; - }); + args; /** - * @returns {Promise} The response. + * @param {string} module_path The relative path to the API method module. + * @param {HyperAPIRequestArgs} args The arguments to pass to the API method. */ - wait() { - return this.#promise; - } + constructor(module_path, args) { + super('request'); - /** - * @param {HyperAPIResponse} response The response. - */ - _respondWith(response) { - this.#resolve(response); + this.module_path = module_path; + this.args = args; } } diff --git a/src/response.js b/src/response.js index 38a776c..ed64ae3 100644 --- a/src/response.js +++ b/src/response.js @@ -1,12 +1,16 @@ -import { HyperAPIError } from './error.js'; +import { HyperAPIError } from './error.js'; +import { HyperAPIRequest } from './request.js'; -export class HyperAPIResponse { +export class HyperAPIResponse extends Event { /** * Creates a HyperAPI response. - * @param {HyperAPIError|object|Array} value The error or the response value. + * @param {HyperAPIRequest} request The request. + * @param {HyperAPIError | Record | any[]} value The error or the response value. */ - constructor(value) { + constructor(request, value) { + super(request.response_event_name); + if (value instanceof HyperAPIError) { this.error = value; } diff --git a/test/api/echo.async.js b/test/api/echo.async.js index 11055b8..cbbf1f3 100644 --- a/test/api/echo.async.js +++ b/test/api/echo.async.js @@ -14,17 +14,11 @@ export default async function (request) { }; } -import { - never, - object, - string } from 'valibot'; +import * as v from 'valibot'; import { valibot } from '../validator.js'; export const argsValidator = valibot.bind( - object( - { - name: string(), - }, - never(), - ), + v.strictObject({ + name: v.string(), + }), ); diff --git a/test/api/echo.js b/test/api/echo.js index 7566ac4..45a46a6 100644 --- a/test/api/echo.js +++ b/test/api/echo.js @@ -7,17 +7,11 @@ export default function (request) { }; } -import { - never, - object, - string } from 'valibot'; +import * as v from 'valibot'; import { valibot } from '../validator.js'; export const argsValidator = valibot.bind( - object( - { - name: string(), - }, - never(), - ), + v.strictObject({ + name: v.string(), + }), ); diff --git a/test/api/error.import.field.js b/test/api/error.import.field.js index d2e6e28..35a970d 100644 --- a/test/api/error.import.field.js +++ b/test/api/error.import.field.js @@ -1,8 +1,12 @@ /* eslint-disable jsdoc/require-jsdoc */ // eslint-disable-next-line import/named -import { foo } from '../validator.js'; +import { deadbeef } from '../validator.js'; export default function () { - return foo; + return true; +} + +export function _() { + return deadbeef; } diff --git a/test/api/error.import.path.js b/test/api/error.import.path.js index 8ba5243..3854034 100644 --- a/test/api/error.import.path.js +++ b/test/api/error.import.path.js @@ -1,6 +1,6 @@ /* eslint-disable jsdoc/require-jsdoc */ -// eslint-disable-next-line import/no-unresolved, node/no-missing-import +// eslint-disable-next-line import/no-unresolved import { foo } from '../invalid.js'; export default function () { diff --git a/tsconfig.json b/tsconfig.json new file mode 100644 index 0000000..79c8b45 --- /dev/null +++ b/tsconfig.json @@ -0,0 +1,18 @@ +{ + "compilerOptions": { + "target": "es2022", + "noImplicitAny": true, + "checkJs": true, + "allowJs": true, + "module": "ESNext", + "moduleResolution": "node" + }, + "include": [ + "src/**/*" + ], + "exclude": [ + "node_modules/", + "dist/", + "**/*.test.*" + ] +} diff --git a/types/api-errors.d.ts b/types/api-errors.d.ts new file mode 100644 index 0000000..d9f64ad --- /dev/null +++ b/types/api-errors.d.ts @@ -0,0 +1,49 @@ +export class HyperAPIAuthorizationError extends HyperAPIError { + code: number; + description: string; +} +export class HyperAPIInvalidParametersError extends HyperAPIError { + code: number; + description: string; +} +export class HyperAPIInternalError extends HyperAPIError { + code: number; + description: string; +} +export class HyperAPIForbiddenError extends HyperAPIError { + code: number; + description: string; +} +export class HyperAPIUnknownMethodError extends HyperAPIError { + code: number; + description: string; +} +export class HyperAPIObjectsLimitError extends HyperAPIError { + code: number; + description: string; +} +export class HyperAPIRateLimitError extends HyperAPIError { + code: number; + description: string; +} +export class HyperAPICaptchaError extends HyperAPIError { + code: number; + description: string; +} +export class HyperAPIBusyError extends HyperAPIError { + code: number; + description: string; +} +export class HyperAPIConfirmationError extends HyperAPIError { + code: number; + description: string; +} +export class HyperAPIOTPError extends HyperAPIError { + code: number; + description: string; +} +export class HyperAPIMaintenanceError extends HyperAPIError { + code: number; + description: string; +} +import { HyperAPIError } from './error.js'; diff --git a/types/driver.d.ts b/types/driver.d.ts new file mode 100644 index 0000000..d0689aa --- /dev/null +++ b/types/driver.d.ts @@ -0,0 +1,9 @@ +export class HyperAPIDriver extends EventTarget { + /** + * @param {HyperAPIRequest} request - + * @returns {Promise} - + */ + processRequest(request: HyperAPIRequest): Promise; +} +import { HyperAPIRequest } from './request.js'; +import { HyperAPIResponse } from './response.js'; diff --git a/types/error.d.ts b/types/error.d.ts new file mode 100644 index 0000000..ab22e20 --- /dev/null +++ b/types/error.d.ts @@ -0,0 +1,63 @@ +/** + * @typedef {object} HyperAPIErrorResponse + * @property {number} code - The error code. + * @property {string} [description] - The error description. + * @property {{[key: string]: any}} [data] - The error data. + */ +export class HyperAPIError extends Error { + /** + * @param {{[key: string]: any}} [data] The error data. + */ + constructor(data?: { + [key: string]: any; + }); + /** + * The error code. + * @type {number} + * @readonly + */ + readonly code: number; + /** + * The error description. + * @type {string?} + * @readonly + */ + readonly description: string | null; + /** + * The error data. + * @type {{[key: string]: any}} + * @readonly + */ + readonly data: { + [key: string]: any; + }; + /** @type {number?} */ + httpStatus: number | null; + /** @type {Record?} */ + httpHeaders: Record | null; + /** + * @returns {string} - + */ + get message(): string; + /** + * Creates response object. + * @returns {HyperAPIErrorResponse} - + */ + getResponse(): HyperAPIErrorResponse; +} +export type HyperAPIErrorResponse = { + /** + * - The error code. + */ + code: number; + /** + * - The error description. + */ + description?: string; + /** + * - The error data. + */ + data?: { + [key: string]: any; + }; +}; diff --git a/types/main.d.ts b/types/main.d.ts new file mode 100644 index 0000000..7e6d90e --- /dev/null +++ b/types/main.d.ts @@ -0,0 +1,41 @@ +export class HyperAPI { + /** + * Creates a HyperAPI instance. + * @param {object} options The options. + * @param {HyperAPIDriver} options.driver The HyperAPI driver. + * @param {string} [options.root] The root directory for API methods modules. Default: `hyper-api` directory alongside the entrypoint script. + */ + constructor({ driver, root, }: { + driver: HyperAPIDriver; + root?: string; + }); + /** + * Destroys the HyperAPI instance. + */ + destroy(): void; + #private; +} +export * from "./api-errors.js"; +export { HyperAPIDriver } from "./driver.js"; +export { HyperAPIError } from "./error.js"; +export { HyperAPIRequest } from "./request.js"; +export { HyperAPIResponse } from "./response.js"; +export type HyperAPIModule = { + /** + * Core function of the API method. + */ + default: (arg0: HyperAPIRequest) => HyperAPIModuleResponse | Promise; + /** + * - Function that validates `args` property of the HyperAPIRequest. Should return validated args or throw an error. + */ + argsValidator?: (arg0: { + [key: string]: any; + }) => { + [key: string]: any; + } | Promise<{ + [key: string]: any; + }>; +}; +export type HyperAPIModuleResponse = Record | any[] | undefined; +import { HyperAPIDriver } from './driver.js'; +import { HyperAPIRequest } from './request.js'; diff --git a/types/request.d.ts b/types/request.d.ts new file mode 100644 index 0000000..2966b59 --- /dev/null +++ b/types/request.d.ts @@ -0,0 +1,29 @@ +/** + * @class HyperAPIRequest + * @template {Record} [HyperAPIRequestArgs={}] + */ +export class HyperAPIRequest = {}> extends Event { + /** + * @param {string} module_path The relative path to the API method module. + * @param {HyperAPIRequestArgs} args The arguments to pass to the API method. + */ + constructor(module_path: string, args: HyperAPIRequestArgs); + /** + * The unique identifier for this request. + * @type {string} + * @readonly + */ + readonly response_event_name: string; + /** + * The relative path to the JavaScript module that contains requested API method. + * @type {string} + * @readonly + */ + readonly module_path: string; + /** + * Request arguments to pass to the API method. + * @type {HyperAPIRequestArgs} + * @readonly + */ + readonly args: HyperAPIRequestArgs; +} diff --git a/types/response.d.ts b/types/response.d.ts new file mode 100644 index 0000000..f5d17f1 --- /dev/null +++ b/types/response.d.ts @@ -0,0 +1,24 @@ +export class HyperAPIResponse extends Event { + /** + * Creates a HyperAPI response. + * @param {HyperAPIRequest} request The request. + * @param {HyperAPIError | Record | any[]} value The error or the response value. + */ + constructor(request: HyperAPIRequest, value: HyperAPIError | Record | any[]); + error: HyperAPIError; + data: any[] | Record; + /** + * @returns {boolean} Whether the response is successful. + * @readonly + */ + readonly get is_success(): boolean; + /** + * Returns response as an object. For example, that can be used as the body of a HTTP response. + * @returns {{[key: string]: *}?} The response. + */ + getResponse(): { + [key: string]: any; + } | null; +} +import { HyperAPIError } from './error.js'; +import { HyperAPIRequest } from './request.js'; From 31ad4a202c175dd3710ca8d447765322857f7d64 Mon Sep 17 00:00:00 2001 From: Daniil Kirichenko Date: Mon, 1 Jul 2024 17:21:29 +0300 Subject: [PATCH 14/57] [v0.2.0-beta.3] Fixed crash on older Node versions - reworked extraction of the module specifier from ERR_MODULE_NOT_FOUND error --- dist/main.cjs | 52 +++++++++-- package.json | 7 +- src/main.js | 25 ++--- src/main.test.js | 2 - src/utils/extract-module-not-found-path.js | 78 ++++++++++++++++ .../extract-module-not-found-path.test.js | 93 +++++++++++++++++++ test/err_module_not_found/dependency.mjs | 3 + test/err_module_not_found/main.mjs | 14 +++ .../utils/extract-module-not-found-path.d.ts | 15 +++ 9 files changed, 260 insertions(+), 29 deletions(-) create mode 100644 src/utils/extract-module-not-found-path.js create mode 100644 src/utils/extract-module-not-found-path.test.js create mode 100644 test/err_module_not_found/dependency.mjs create mode 100644 test/err_module_not_found/main.mjs create mode 100644 types/utils/extract-module-not-found-path.d.ts diff --git a/dist/main.cjs b/dist/main.cjs index 4364b1d..b31cad3 100644 --- a/dist/main.cjs +++ b/dist/main.cjs @@ -38,7 +38,7 @@ __export(main_exports, { HyperAPIUnknownMethodError: () => HyperAPIUnknownMethodError }); module.exports = __toCommonJS(main_exports); -var import_node_path = require("node:path"); +var import_node_path2 = require("node:path"); // src/error.js var HyperAPIError = class extends Error { @@ -268,8 +268,44 @@ var HyperAPIDriver = class extends EventTarget { } }; +// src/utils/extract-module-not-found-path.js +var import_node_path = require("node:path"); +var REGEXP_MODULE_SPECIFIER = /Cannot find module ["'](.+)["'] (?:imported\s)?from/; +var REGEXP_MODULE_REQUESTER = /\s(?:imported\s)?from ["'](.+)["']/; +function extractPath(error) { + if (typeof error.specifier === "string") { + return error.specifier; + } + if (error.url instanceof URL) { + return error.url.pathname; + } + if (typeof error.url === "string") { + return new URL(error.url).pathname; + } + const match = error.message.match(REGEXP_MODULE_SPECIFIER); + if (match !== null) { + return match[1]; + } + throw error; +} +function extractModuleNotFoundPath(error) { + const path = extractPath(error); + if (path.startsWith("/")) { + return path; + } + const match = error.message.match(REGEXP_MODULE_REQUESTER); + if (match !== null) { + const specifier_from = match[1]; + return (0, import_node_path.join)( + (0, import_node_path.dirname)(specifier_from), + path + ); + } + throw error; +} + // src/main.js -var ENTRYPOINT_PATH = (0, import_node_path.dirname)(process.argv[1]); +var ENTRYPOINT_PATH = (0, import_node_path2.dirname)(process.argv[1]); var HyperAPI = class { /** @type {HyperAPIDriver} The HyperAPI driver. */ #driver; @@ -285,7 +321,7 @@ var HyperAPI = class { */ constructor({ driver, - root = (0, import_node_path.join)( + root = (0, import_node_path2.join)( ENTRYPOINT_PATH, "hyper-api" ) @@ -356,19 +392,19 @@ var HyperAPI = class { `${request.module_path}.js`, `${request.module_path}.mjs`, `${request.module_path}.cjs`, - (0, import_node_path.join)(request.module_path, "index.js") + (0, import_node_path2.join)(request.module_path, "index.js") ]; for (const filename of filenames) { - const path = (0, import_node_path.join)( + const path = (0, import_node_path2.join)( this.#root, filename ); try { return await import(path); } catch (error) { - if (error.code === "MODULE_NOT_FOUND" || error.code === "ERR_MODULE_NOT_FOUND") { - const path_error = error.moduleName ?? error.specifier ?? new URL(error.url).pathname; - if (path === path_error) { + if (error.code === "ERR_MODULE_NOT_FOUND") { + const path_not_found = extractModuleNotFoundPath(error); + if (path === path_not_found) { continue; } } diff --git a/package.json b/package.json index 769a3b0..cc4ca7a 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@hyperapi/core", - "version": "0.2.0-beta.2", + "version": "0.2.0-beta.3", "description": "Core package of the HyperAPI project.", "publishConfig": { "access": "public" @@ -32,12 +32,11 @@ }, "scripts": { "test": "npm run test:vitest && bun test --coverage", - "test:vitest": "vitest run --no-file-parallelism", + "test:vitest": "vitest run --no-file-parallelism --exclude '**/extract-*'", "build": "bun run build:types && bun run build:cjs", "build:cjs": "bunx esbuild --bundle --platform=node --format=cjs --packages=external --outfile=dist/main.cjs src/main.js", "build:types": "bunx tsc --skipLibCheck --declaration --emitDeclarationOnly --outDir types", - "publish:npm": "pnpm i && bun run build && eslint . && bunx tsc --skipLibCheck --noemit && bun run test && npm publish", - "publish:npm:beta": "bun run publish:npm --tag beta" + "publish:npm": "pnpm i && bun run build && eslint . && bunx tsc --skipLibCheck --noemit && bun run test && npm publish" }, "repository": { "type": "git", diff --git a/src/main.js b/src/main.js index 23656aa..38fa077 100644 --- a/src/main.js +++ b/src/main.js @@ -8,14 +8,15 @@ import { dirname, - join as joinPath } from 'node:path'; + join as joinPath } from 'node:path'; import { HyperAPIInternalError, - HyperAPIUnknownMethodError } from './api-errors.js'; -import { HyperAPIDriver } from './driver.js'; -import { HyperAPIError } from './error.js'; -import { HyperAPIRequest } from './request.js'; -import { HyperAPIResponse } from './response.js'; + HyperAPIUnknownMethodError } from './api-errors.js'; +import { HyperAPIDriver } from './driver.js'; +import { HyperAPIError } from './error.js'; +import { HyperAPIRequest } from './request.js'; +import { HyperAPIResponse } from './response.js'; +import { extractModuleNotFoundPath } from './utils/extract-module-not-found-path.js'; const ENTRYPOINT_PATH = dirname(process.argv[1]); @@ -137,16 +138,10 @@ export class HyperAPI { return await import(path); } catch (error) { - if ( - error.code === 'MODULE_NOT_FOUND' // node - || error.code === 'ERR_MODULE_NOT_FOUND' // bun - ) { - const path_error = error.moduleName // node - ?? error.specifier // bun - ?? new URL(error.url).pathname; // node v20.10 in raw, not in jest's test env - + if (error.code === 'ERR_MODULE_NOT_FOUND') { + const path_not_found = extractModuleNotFoundPath(error); // skip error only if we cannot found the module itself - if (path === path_error) { + if (path === path_not_found) { continue; } } diff --git a/src/main.test.js b/src/main.test.js index 65036f0..fe61af5 100644 --- a/src/main.test.js +++ b/src/main.test.js @@ -1,8 +1,6 @@ /* eslint-disable jsdoc/require-jsdoc */ -// @ts-check - import { afterAll, describe, diff --git a/src/utils/extract-module-not-found-path.js b/src/utils/extract-module-not-found-path.js new file mode 100644 index 0000000..41a2ad6 --- /dev/null +++ b/src/utils/extract-module-not-found-path.js @@ -0,0 +1,78 @@ + +import { + dirname, + join as joinPath } from 'node:path'; + +// typedef does not work for some reason. + +// /** +// * @typedef {Error} ModuleNotFoundError +// * @property {'ERR_MODULE_NOT_FOUND'} code The error code. +// * @property {string} [specifier] - Path to the module that was not found. +// */ +class ModuleNotFoundError extends Error { + /** @type {string} */ + code = 'ERR_MODULE_NOT_FOUND'; + /** @type {string | undefined} */ + specifier; + /** @type {string | URL | undefined} */ + url; +} + +const REGEXP_MODULE_SPECIFIER = /Cannot find module ["'](.+)["'] (?:imported\s)?from/; +const REGEXP_MODULE_REQUESTER = /\s(?:imported\s)?from ["'](.+)["']/; + +/** + * Extracts path from error as is. + * @param {ModuleNotFoundError} error The error. + * @returns {string} The path to the module that was not found. + */ +function extractPath(error) { + // Bun + if (typeof error.specifier === 'string') { + return error.specifier; + } + + // Node 20.6 ... 20.7 + if (error.url instanceof URL) { + return error.url.pathname; + } + + // Node 20.8+ + if (typeof error.url === 'string') { + return new URL(error.url).pathname; + } + + const match = error.message.match(REGEXP_MODULE_SPECIFIER); + if (match !== null) { + return match[1]; + } + + throw error; +} + +/** + * Extracts the path to module-not-found from an ERR_MODULE_NOT_FOUND error. + * @param {ModuleNotFoundError} error The error. + * @returns {string} The path to the module that was not found. + */ +export function extractModuleNotFoundPath(error) { + const path = extractPath(error); + + if (path.startsWith('/')) { + return path; + } + + // Bun returns relative paths, so we have to extract path to the module that requested the missing module from the error message. + const match = error.message.match(REGEXP_MODULE_REQUESTER); + if (match !== null) { + const specifier_from = match[1]; + + return joinPath( + dirname(specifier_from), + path, + ); + } + + throw error; +} diff --git a/src/utils/extract-module-not-found-path.test.js b/src/utils/extract-module-not-found-path.test.js new file mode 100644 index 0000000..03bd90a --- /dev/null +++ b/src/utils/extract-module-not-found-path.test.js @@ -0,0 +1,93 @@ +/* global Bun */ + +import { + beforeAll, + describe, + test, + expect } from 'vitest'; + +const IMAGES = [ + // no fields, extracting path from message + 'node:14-slim', + 'node:16-slim', + 'node:18-slim', + 'node:20.0-slim', + 'node:20.4-slim', + // field "url" as an instance of URL + 'node:20.6-slim', + // field "url" as string + 'node:20.8-slim', + 'node:22-slim', + // bun + 'oven/bun:1.0', + 'oven/bun:1.1.0-slim', + 'oven/bun:1.1.17-slim', +]; + +beforeAll(async () => { + let count = 0; + + await Promise.all( + IMAGES.map((image) => (async () => { + const proc = Bun.spawn([ + 'docker', + 'pull', + image, + ]); + + await proc.exited; + + console.log('pulled', image, `(${++count} of ${IMAGES.length})`); + })()), + ); +}); + +const PATHS = [ + { + title: 'existing module imports non-existing module', + path: './dependency.mjs', + path_expect: '/app/test/err_module_not_found/test.js', + }, + { + title: 'requested module itself does not exist', + path: './not-exists.mjs', + path_expect: '/app/test/err_module_not_found/not-exists.mjs', + }, +]; + +// const ROOT_DIRECTORY = process.cwd(); +// console.log('ROOT_DIRECTORY', ROOT_DIRECTORY); + +for (const { title, path, path_expect } of PATHS) { + describe(title, () => { + for (const image of IMAGES) { + const args = [ + 'docker', + 'run', + '--rm', + '-v', + `${process.cwd()}:/app`, + '-w', + '/app', + image, + 'test/err_module_not_found/main.mjs', + ]; + + test(image, async () => { + const proc = Bun.spawn([ + ...args, + path, + ]); + + await proc.exited; + + expect(proc.exitCode).toBe(0); + + const stdout = await new Response(proc.stdout).text(); + const path_received = stdout.trim(); + + expect(path_received).toBe(path_expect); + }); + } + }); +} diff --git a/test/err_module_not_found/dependency.mjs b/test/err_module_not_found/dependency.mjs new file mode 100644 index 0000000..186ad66 --- /dev/null +++ b/test/err_module_not_found/dependency.mjs @@ -0,0 +1,3 @@ + +// eslint-disable-next-line import/no-unresolved, no-unused-vars +import * as v from './test.js'; diff --git a/test/err_module_not_found/main.mjs b/test/err_module_not_found/main.mjs new file mode 100644 index 0000000..e227079 --- /dev/null +++ b/test/err_module_not_found/main.mjs @@ -0,0 +1,14 @@ + +import { extractModuleNotFoundPath } from '../../src/utils/extract-module-not-found-path.js'; + +try { + await import(process.argv[2]); + + // eslint-disable-next-line no-process-exit, unicorn/no-process-exit + process.exit(128); +} +catch (error) { + console.log( + extractModuleNotFoundPath(error), + ); +} diff --git a/types/utils/extract-module-not-found-path.d.ts b/types/utils/extract-module-not-found-path.d.ts new file mode 100644 index 0000000..d6afbf3 --- /dev/null +++ b/types/utils/extract-module-not-found-path.d.ts @@ -0,0 +1,15 @@ +/** + * Extracts the path to module-not-found from an ERR_MODULE_NOT_FOUND error. + * @param {ModuleNotFoundError} error The error. + * @returns {string} The path to the module that was not found. + */ +export function extractModuleNotFoundPath(error: ModuleNotFoundError): string; +declare class ModuleNotFoundError extends Error { + /** @type {string} */ + code: string; + /** @type {string | undefined} */ + specifier: string | undefined; + /** @type {string | URL | undefined} */ + url: string | URL | undefined; +} +export {}; From 31fd9dd3e693f3d557a6c32da561b269a39298f8 Mon Sep 17 00:00:00 2001 From: Daniil Kirichenko Date: Tue, 17 Sep 2024 13:18:18 +0300 Subject: [PATCH 15/57] [v0.3.0-beta.1] Typescript - rewritten to Typescript - changed internal APIs for drivers --- .eslintrc.cjs | 171 - .npmignore | 27 +- bun.lockb | Bin 0 -> 118712 bytes dist/esm/api-errors.d.ts | 61 + dist/esm/api-errors.js | 61 + dist/esm/driver.d.ts | 9 + dist/esm/driver.js | 1 + dist/esm/error.d.ts | 26 + dist/esm/error.js | 38 + dist/esm/error.test.d.ts | 1 + dist/esm/error.test.js | 11 + dist/esm/main.d.ts | 46 + dist/esm/main.js | 137 + dist/esm/main.test.d.ts | 1 + dist/esm/main.test.js | 143 + dist/esm/module.d.ts | 9 + dist/esm/module.js | 1 + dist/esm/request.d.ts | 7 + dist/esm/request.js | 1 + dist/esm/response.d.ts | 3 + dist/esm/response.js | 1 + dist/esm/router.d.ts | 21 + dist/esm/router.js | 103 + dist/esm/utils/is-record.d.ts | 6 + dist/esm/utils/is-record.js | 12 + dist/esm/utils/types.d.ts | 5 + dist/esm/utils/types.js | 1 + dist/main.cjs | 478 +-- eslint.config.js | 1 + package.json | 42 +- pnpm-lock.yaml | 3444 ----------------- src/{api-errors.js => api-errors.ts} | 30 +- src/driver.js | 29 - src/driver.ts | 16 + src/error.js | 78 - src/error.test.ts | 17 + src/error.ts | 56 + src/main.js | 193 - src/main.test.js | 183 - src/main.test.ts | 184 + src/main.ts | 227 ++ src/module.ts | 20 + src/request.js | 40 - src/request.ts | 14 + src/response.js | 50 - src/response.ts | 5 + src/router.ts | 171 + src/utils/extract-module-not-found-path.js | 78 - .../extract-module-not-found-path.test.js | 93 - src/utils/is-record.ts | 12 + src/utils/types.ts | 4 + test/api/dir/nested.js | 8 - test/api/echo.async.js | 24 - test/api/echo.js | 17 - test/api/error.api.js | 7 - test/api/error.import.field.js | 12 - test/api/error.import.path.js | 8 - test/api/error.type.js | 5 - test/err_module_not_found/dependency.mjs | 3 - test/err_module_not_found/main.mjs | 14 - test/hyper-api/echo.[post].ts | 26 + test/hyper-api/echo.ts | 18 + test/hyper-api/errors/api.test.ts | 44 + test/hyper-api/errors/api.ts | 27 + test/hyper-api/errors/internal.test.ts | 21 + .../errors/internal.ts} | 0 test/setup.ts | 125 + test/validator.js | 24 - tsconfig.json | 33 +- types/api-errors.d.ts | 49 - types/driver.d.ts | 9 - types/error.d.ts | 63 - types/main.d.ts | 41 - types/request.d.ts | 29 - types/response.d.ts | 24 - .../utils/extract-module-not-found-path.d.ts | 15 - 76 files changed, 1977 insertions(+), 5037 deletions(-) delete mode 100644 .eslintrc.cjs create mode 100755 bun.lockb create mode 100644 dist/esm/api-errors.d.ts create mode 100644 dist/esm/api-errors.js create mode 100644 dist/esm/driver.d.ts create mode 100644 dist/esm/driver.js create mode 100644 dist/esm/error.d.ts create mode 100644 dist/esm/error.js create mode 100644 dist/esm/error.test.d.ts create mode 100644 dist/esm/error.test.js create mode 100644 dist/esm/main.d.ts create mode 100644 dist/esm/main.js create mode 100644 dist/esm/main.test.d.ts create mode 100644 dist/esm/main.test.js create mode 100644 dist/esm/module.d.ts create mode 100644 dist/esm/module.js create mode 100644 dist/esm/request.d.ts create mode 100644 dist/esm/request.js create mode 100644 dist/esm/response.d.ts create mode 100644 dist/esm/response.js create mode 100644 dist/esm/router.d.ts create mode 100644 dist/esm/router.js create mode 100644 dist/esm/utils/is-record.d.ts create mode 100644 dist/esm/utils/is-record.js create mode 100644 dist/esm/utils/types.d.ts create mode 100644 dist/esm/utils/types.js create mode 100644 eslint.config.js delete mode 100644 pnpm-lock.yaml rename src/{api-errors.js => api-errors.ts} (51%) delete mode 100644 src/driver.js create mode 100644 src/driver.ts delete mode 100644 src/error.js create mode 100644 src/error.test.ts create mode 100644 src/error.ts delete mode 100644 src/main.js delete mode 100644 src/main.test.js create mode 100644 src/main.test.ts create mode 100644 src/main.ts create mode 100644 src/module.ts delete mode 100644 src/request.js create mode 100644 src/request.ts delete mode 100644 src/response.js create mode 100644 src/response.ts create mode 100644 src/router.ts delete mode 100644 src/utils/extract-module-not-found-path.js delete mode 100644 src/utils/extract-module-not-found-path.test.js create mode 100644 src/utils/is-record.ts create mode 100644 src/utils/types.ts delete mode 100644 test/api/dir/nested.js delete mode 100644 test/api/echo.async.js delete mode 100644 test/api/echo.js delete mode 100644 test/api/error.api.js delete mode 100644 test/api/error.import.field.js delete mode 100644 test/api/error.import.path.js delete mode 100644 test/api/error.type.js delete mode 100644 test/err_module_not_found/dependency.mjs delete mode 100644 test/err_module_not_found/main.mjs create mode 100644 test/hyper-api/echo.[post].ts create mode 100644 test/hyper-api/echo.ts create mode 100644 test/hyper-api/errors/api.test.ts create mode 100644 test/hyper-api/errors/api.ts create mode 100644 test/hyper-api/errors/internal.test.ts rename test/{api/error.internal.js => hyper-api/errors/internal.ts} (100%) create mode 100644 test/setup.ts delete mode 100644 test/validator.js delete mode 100644 types/api-errors.d.ts delete mode 100644 types/driver.d.ts delete mode 100644 types/error.d.ts delete mode 100644 types/main.d.ts delete mode 100644 types/request.d.ts delete mode 100644 types/response.d.ts delete mode 100644 types/utils/extract-module-not-found-path.d.ts diff --git a/.eslintrc.cjs b/.eslintrc.cjs deleted file mode 100644 index 86fbad0..0000000 --- a/.eslintrc.cjs +++ /dev/null @@ -1,171 +0,0 @@ - -module.exports = { - root: true, - parser: '@babel/eslint-parser', - parserOptions: { - ecmaVersion: 2022, - sourceType: 'module', - requireConfigFile: false, - }, - env: { - es2022: true, - node: true, - }, - extends: [ - 'eslint:recommended', - 'xo', - 'plugin:import/recommended', - 'plugin:jsdoc/recommended', - 'plugin:promise/recommended', - 'plugin:unicorn/recommended', - 'plugin:node/recommended', - ], - plugins: [ - 'import', - 'jsdoc', - 'promise', - 'unicorn', - 'node', - ], - ignorePatterns: [ - 'dist/**/*', - 'node_modules*/**/*', - 'types/**/*', - ], - rules: { - 'arrow-body-style': [ - 'error', - 'as-needed', - { - requireReturnForObjectLiteral: true, - }, - ], - 'array-bracket-spacing': [ - 'warn', - 'always', - { - arraysInArrays: false, - objectsInArrays: false, - }, - ], - 'arrow-parens': [ - 'warn', - 'always', - ], - 'brace-style': [ - 'error', - 'stroustrup', - ], - 'camelcase': 'off', - 'capitalized-comments': 'off', - 'comma-dangle': [ - 'warn', - 'always-multiline', - ], - 'func-names': 'off', - 'import/extensions': [ - 'error', - 'always', - ], - 'import/order': [ - 'error', - { - groups: [ - [ - 'builtin', - 'external', - ], - 'internal', - 'parent', - 'sibling', - ], - }, - ], - 'indent': [ - 'error', - 'tab', - { - ImportDeclaration: 'off', - SwitchCase: 1, - }, - ], - 'jsdoc/require-jsdoc': 'error', - 'new-cap': [ - 'error', - { - newIsCap: true, - capIsNew: true, - properties: false, - }, - ], - 'no-multi-spaces': [ - 'error', - { - exceptions: { - Property: true, - ImportDeclaration: true, - }, - }, - ], - 'no-multiple-empty-lines': 'warn', - 'no-promise-executor-return': 'off', - 'no-trailing-spaces': 'warn', - 'no-unused-vars': 'warn', - 'node/no-missing-import': 'off', - 'node/no-unpublished-import': 'off', - 'object-curly-spacing': [ - 'warn', - 'always', - { - arraysInObjects: true, - objectsInObjects: true, - }, - ], - 'padding-line-between-statements': [ - 'error', - { - blankLine: 'never', - prev: 'case', - next: 'break', - }, - ], - 'quote-props': [ - 'error', - 'consistent-as-needed', - { - numbers: true, - }, - ], - 'quotes': [ - 'error', - 'single', - ], - 'radix': [ - 'warn', - 'as-needed', - ], - 'unicorn/no-null': 'off', - 'unicorn/numeric-separators-style': [ - 'warn', - { - onlyIfContainsSeparator: true, - }, - ], - 'unicorn/prefer-ternary': 'off', - 'unicorn/prevent-abbreviations': [ - 'error', - { - allowList: { - args: true, - env: true, - fn: true, - }, - }, - ], - 'unicorn/switch-case-braces': [ - 'warn', - 'avoid', - ], - 'node/no-unsupported-features/es-syntax': 'off', - }, -}; diff --git a/.npmignore b/.npmignore index 3394edf..ee2885d 100644 --- a/.npmignore +++ b/.npmignore @@ -1,4 +1,25 @@ - -.eslintrc.cjs +# ignore tests +**/*.test.* +**/*.test.d.ts test/ -**/*.test.js + +# ignore source files of the Typescript project +src/ + +# ignore configs +.luarc.json +biome.json +# these names cannot be declared using {js,mjs,cjs} syntax +# is this case rule n/no-unpublished-import screams at me +eslint.config.js +eslint.config.mjs +eslint.config.cjs +tsconfig.json + +# ignore repo configs +.github/ +.gitea/ + +# ignore IDE files +.idea +.nova diff --git a/bun.lockb b/bun.lockb new file mode 100755 index 0000000000000000000000000000000000000000..18657feda4544e43d3bea60c3c82c2267ecacf77 GIT binary patch literal 118712 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 extends HyperAPIError { + code: number; + description: string; + httpStatus: number; +} +export declare class HyperAPIInvalidParametersError extends HyperAPIError { + code: number; + description: string; + httpStatus: number; +} +export declare class HyperAPIInternalError extends HyperAPIError { + code: number; + description: string; + httpStatus: number; +} +export declare class HyperAPIForbiddenError extends HyperAPIError { + code: number; + description: string; + httpStatus: number; +} +export declare class HyperAPIUnknownMethodError extends HyperAPIError { + code: number; + description: string; + httpStatus: number; +} +export declare class HyperAPIObjectsLimitError extends HyperAPIError { + code: number; + description: string; + httpStatus: number; +} +export declare class HyperAPIRateLimitError extends HyperAPIError { + code: number; + description: string; + httpStatus: number; +} +export declare class HyperAPICaptchaError extends HyperAPIError { + code: number; + description: string; + httpStatus: number; +} +export declare class HyperAPIBusyError extends HyperAPIError { + code: number; + description: string; + httpStatus: number; +} +export declare class HyperAPIConfirmationError extends HyperAPIError { + code: number; + description: string; + httpStatus: number; +} +export declare class HyperAPIOTPError extends HyperAPIError { + code: number; + description: string; + httpStatus: number; +} +export declare class HyperAPIMaintenanceError extends HyperAPIError { + code: number; + description: string; + httpStatus: number; +} diff --git a/dist/esm/api-errors.js b/dist/esm/api-errors.js new file mode 100644 index 0000000..0d92728 --- /dev/null +++ b/dist/esm/api-errors.js @@ -0,0 +1,61 @@ +import { HyperAPIError, } from './error'; +export class HyperAPIAuthorizationError extends HyperAPIError { + code = 1; + description = 'Authorization error'; + httpStatus = 401; // Unauthorized +} +export class HyperAPIInvalidParametersError extends HyperAPIError { + code = 2; + description = 'One of the parameters specified was missing or invalid'; + httpStatus = 400; // Bad Request +} +export class HyperAPIInternalError extends HyperAPIError { + code = 3; + description = 'Internal error'; + httpStatus = 500; // Internal Server Error +} +export class HyperAPIForbiddenError extends HyperAPIError { + code = 4; + description = 'You do not have permission to perform this action'; + httpStatus = 403; // Forbidden +} +export class HyperAPIUnknownMethodError extends HyperAPIError { + code = 5; + description = 'Unknown method called'; + httpStatus = 404; // Not Found +} +export class HyperAPIObjectsLimitError extends HyperAPIError { + code = 6; + description = 'Too many objects requested'; + httpStatus = 400; // Bad Request +} +export class HyperAPIRateLimitError extends HyperAPIError { + code = 7; + description = 'Rate limit exceeded'; + httpStatus = 429; // Too Many Requests +} +export class HyperAPICaptchaError extends HyperAPIError { + code = 8; + description = 'Captcha required'; + httpStatus = 428; // Precondition Required +} +export class HyperAPIBusyError extends HyperAPIError { + code = 10; + description = 'Endpoint is busy'; + httpStatus = 503; // Service Unavailable +} +export class HyperAPIConfirmationError extends HyperAPIError { + code = 11; + description = 'Confirmation required'; + httpStatus = 409; // Conflict +} +export class HyperAPIOTPError extends HyperAPIError { + code = 12; + description = 'One-time password required'; + httpStatus = 401; // Unauthorized +} +export class HyperAPIMaintenanceError extends HyperAPIError { + code = 13; + description = 'Endpoint is in maintenance mode'; + httpStatus = 503; // Service Unavailable +} diff --git a/dist/esm/driver.d.ts b/dist/esm/driver.d.ts new file mode 100644 index 0000000..9360e63 --- /dev/null +++ b/dist/esm/driver.d.ts @@ -0,0 +1,9 @@ +import type { HyperAPIRequest } from './request'; +import type { HyperAPIResponse } from './response'; +import { MaybePromise } from './utils/types'; +export type HyperAPIDriverHandler = (request: R) => MaybePromise; +export interface HyperAPIDriver { + start(handler: HyperAPIDriverHandler): void; + stop(): void; +} +export type InferDriverRequest = D extends HyperAPIDriver ? R : never; diff --git a/dist/esm/driver.js b/dist/esm/driver.js new file mode 100644 index 0000000..cb0ff5c --- /dev/null +++ b/dist/esm/driver.js @@ -0,0 +1 @@ +export {}; diff --git a/dist/esm/error.d.ts b/dist/esm/error.d.ts new file mode 100644 index 0000000..279e608 --- /dev/null +++ b/dist/esm/error.d.ts @@ -0,0 +1,26 @@ +interface HyperAPIErrorResponse { + code: number; + description?: string; + data?: Record; +} +export type ErrorData = Record | undefined; +export declare class HyperAPIError | undefined> extends Error { + /** The error code. */ + readonly code: number; + /** The error description. */ + readonly description: string; + /** The error data. */ + readonly data?: D; + /** HTTP status code. */ + readonly httpStatus?: number; + /** HTTP headers to return. */ + readonly httpHeaders?: Record; + constructor(data?: D); + get message(): string; + /** + * Creates response object. + * @returns - + */ + getResponse(): HyperAPIErrorResponse; +} +export {}; diff --git a/dist/esm/error.js b/dist/esm/error.js new file mode 100644 index 0000000..353bfa6 --- /dev/null +++ b/dist/esm/error.js @@ -0,0 +1,38 @@ +import { isRecord } from './utils/is-record'; +export class HyperAPIError extends Error { + /** The error code. */ + code = 0; + /** The error description. */ + description = 'HyperAPI error'; + /** The error data. */ + data; + /** HTTP status code. */ + httpStatus; + /** HTTP headers to return. */ + httpHeaders; + constructor(data) { + super(); + if (isRecord(data)) { + this.data = data; + } + } + get message() { + return `${this.description} (code ${this.code}).`; + } + /** + * Creates response object. + * @returns - + */ + getResponse() { + const response = { + code: this.code, + }; + if (typeof this.description === 'string') { + response.description = this.description; + } + if (this.data) { + response.data = this.data; + } + return response; + } +} diff --git a/dist/esm/error.test.d.ts b/dist/esm/error.test.d.ts new file mode 100644 index 0000000..cb0ff5c --- /dev/null +++ b/dist/esm/error.test.d.ts @@ -0,0 +1 @@ +export {}; diff --git a/dist/esm/error.test.js b/dist/esm/error.test.js new file mode 100644 index 0000000..8dbb23b --- /dev/null +++ b/dist/esm/error.test.js @@ -0,0 +1,11 @@ +/* eslint-disable @typescript-eslint/no-explicit-any */ +import { test, expect, } from 'vitest'; +import { HyperAPIError } from './error'; +class HyperAPICustomError extends HyperAPIError { + code = 1001; + description = 'This is a custom error'; +} +test('custom error', () => { + const error = new HyperAPICustomError(); + expect(error.message).toBe('This is a custom error (code 1001).'); +}); diff --git a/dist/esm/main.d.ts b/dist/esm/main.d.ts new file mode 100644 index 0000000..c6d48d4 --- /dev/null +++ b/dist/esm/main.d.ts @@ -0,0 +1,46 @@ +import type { HyperAPIDriver, InferDriverRequest } from './driver'; +import type { HyperAPIModule } from './module'; +import type { HyperAPIRequest } from './request'; +export declare class HyperAPI, R extends InferDriverRequest, M extends HyperAPIModule = HyperAPIModule> { + private router; + private driver; + /** + * Creates a HyperAPI instance. + * @param options The options. + * @param options.driver The driver. + * @param [options.root] The root directory for API methods modules. Default: `hyper-api` directory alongside the entrypoint script. + */ + constructor({ driver, root, }: { + driver: D; + root?: string; + }); + private handlers; + /** + * Use this hook add properties to the request before it is send to the API module. + * + * This hook can be set only once. + * @param transformer The callback function. + */ + setTransformer(transformer: typeof this.handlers['transformer']): void; + /** + * Adds a hook to be called when the API module is imported. + * @param callback - + */ + onModule(callback: typeof this.handlers['module'][number]): void; + /** + * Adds a hook to be called right before the response is sent back. + * + * This hook called only if the request was processed by the API module. If unknown method was requested, this hook is not called. + * @param callback - + */ + onResponse(callback: typeof this.handlers['response'][number]): void; + private processRequest; + /** Destroys the HyperAPI instance. */ + destroy(): void; +} +export * from './api-errors'; +export type { HyperAPIDriver, HyperAPIDriverHandler, } from './driver'; +export { HyperAPIError } from './error'; +export type { HyperAPIModule, InferModule, } from './module'; +export type { HyperAPIRequest, HyperAPIRequestArgs, } from './request'; +export type { HyperAPIResponse } from './response'; diff --git a/dist/esm/main.js b/dist/esm/main.js new file mode 100644 index 0000000..48660b9 --- /dev/null +++ b/dist/esm/main.js @@ -0,0 +1,137 @@ +import nodePath from 'node:path'; +import { HyperAPIInternalError, HyperAPIUnknownMethodError, } from './api-errors'; +import { HyperAPIError } from './error'; +import { createRouter, useRouter, } from './router'; +const ENTRYPOINT_PATH = nodePath.dirname(process.argv[1]); +export class HyperAPI { + router; + driver; + /** + * Creates a HyperAPI instance. + * @param options The options. + * @param options.driver The driver. + * @param [options.root] The root directory for API methods modules. Default: `hyper-api` directory alongside the entrypoint script. + */ + constructor({ driver, root = nodePath.join(ENTRYPOINT_PATH, 'hyper-api'), }) { + this.driver = driver; + this.router = createRouter(root); + this.driver.start(async (driver_request) => { + const [request, module_, response,] = await this.processRequest(driver_request); + if (request && module_) { + for (const hook of this.handlers.response) { + try { + // eslint-disable-next-line no-await-in-loop + await hook(request, module_, response); + } + catch (error) { + /* eslint-disable no-console */ + console.error('Error in "response" hook:'); + console.error(error); + /* eslint-enable no-console */ + } + } + } + return response; + }); + } + handlers = { + transformer: undefined, + module: [], + response: [], + }; + /** + * Use this hook add properties to the request before it is send to the API module. + * + * This hook can be set only once. + * @param transformer The callback function. + */ + setTransformer(transformer) { + if (this.handlers.transformer) { + throw new Error('Transformer has already been set.'); + } + this.handlers.transformer = transformer; + } + /** + * Adds a hook to be called when the API module is imported. + * @param callback - + */ + onModule(callback) { + this.handlers.module.push(callback); + } + /** + * Adds a hook to be called right before the response is sent back. + * + * This hook called only if the request was processed by the API module. If unknown method was requested, this hook is not called. + * @param callback - + */ + onResponse(callback) { + this.handlers.response.push(callback); + } + async processRequest(driver_request) { + let request = null; + let module_ = null; + try { + if (driver_request.path.startsWith('/') !== true) { + driver_request.path = `/${driver_request.path}`; + } + const router_response = await useRouter(this.router, driver_request.method, driver_request.path); + if (!router_response) { + return [ + request, + module_, + new HyperAPIUnknownMethodError(), + ]; + } + driver_request.args = { + ...driver_request.args, + ...router_response.args, + }; + // Send request to the outside user + request = this.handlers.transformer + ? await this.handlers.transformer(driver_request) + : driver_request; + // IDEA: "onBeforeModule" hook? + module_ = (await import(router_response.module_path)); + if (module_.argsValidator) { + request.args = module_.argsValidator(request.args); + } + for (const hook of this.handlers.module) { + // eslint-disable-next-line no-await-in-loop + await hook(request, module_); + } + // IDEA: "onBeforeExecute" hook? + const response = await module_.default(request); + // IDEA: "onExecute" hook? + return [ + request, + module_, + response, + ]; + } + catch (error) { + if (error instanceof HyperAPIError) { + return [ + request, + module_, + error, + ]; + } + // eslint-disable-next-line no-console + console.error(error); + return [ + request, + module_, + new HyperAPIInternalError(), + ]; + } + throw new Error('Unreachable'); + } + /** Destroys the HyperAPI instance. */ + destroy() { + this.handlers.transformer = undefined; + this.handlers.module.splice(0); + this.handlers.response.splice(0); + } +} +export * from './api-errors'; +export { HyperAPIError } from './error'; diff --git a/dist/esm/main.test.d.ts b/dist/esm/main.test.d.ts new file mode 100644 index 0000000..cb0ff5c --- /dev/null +++ b/dist/esm/main.test.d.ts @@ -0,0 +1 @@ +export {}; diff --git a/dist/esm/main.test.js b/dist/esm/main.test.js new file mode 100644 index 0000000..516ab4d --- /dev/null +++ b/dist/esm/main.test.js @@ -0,0 +1,143 @@ +import { afterAll, describe, test, expect, } from 'vitest'; +import { driver, hyperApi, } from '../test/setup'; +afterAll(() => { + hyperApi.destroy(); +}); +describe('routing', () => { + describe('methods', () => { + test('ALL', async () => { + const result = await driver.trigger('GET', 'echo', { + name: 'world', + }); + expect(result).toStrictEqual([ + true, + { + method: 'ALL', + message: 'Hello, world!', + }, + ]); + }); + test('POST', async () => { + const result = await driver.trigger('POST', 'echo', { + name: 'deadbeef', + }); + expect(result).toStrictEqual([ + true, + { + method: 'POST', + message: 'Hello, deadbeef!', + }, + ]); + }); + }); + // test('method in directory', async () => { + // const result = await request( + // 'dir/nested', + // ); + // expect(result).toStrictEqual([ + // true, + // { + // ok: true, + // }, + // ]); + // }); + // test('correct request (async)', async () => { + // const result = await request( + // 'echo.async', + // { + // name: 'user', + // }, + // ); + // expect(result).toStrictEqual([ + // true, + // { + // message: 'Hello, user!', + // }, + // ]); + // }); + // test('invalid arguments', async () => { + // const result = await request( + // 'echo', + // { + // name: 123, + // }, + // ); + // expect(result).toStrictEqual([ + // false, + // { + // code: 2, + // description: 'One of the parameters specified was missing or invalid', + // }, + // ]); + // }); + // test('missing arguments', async () => { + // const result = await request('echo'); + // expect(result).toStrictEqual([ + // false, + // { + // code: 2, + // description: 'One of the parameters specified was missing or invalid', + // }, + // ]); + // }); + // test('api error', async () => { + // const result = await request('error.api'); + // expect(result).toStrictEqual([ + // false, + // { + // code: 10, + // description: 'Endpoint is busy', + // }, + // ]); + // }); + // test('internal error', async () => { + // const result = await request('error.internal'); + // expect(result).toStrictEqual([ + // false, + // { + // code: 3, + // description: 'Internal error', + // }, + // ]); + // }); + // test('invalid return type', async () => { + // const result = await request('error.type'); + // expect(result).toStrictEqual([ + // false, + // { + // code: 3, + // description: 'Internal error', + // }, + // ]); + // }); + // test('unknown method', async () => { + // const result = await request('error.unknown-method'); + // expect(result).toStrictEqual([ + // false, + // { + // code: 5, + // description: 'Unknown method called', + // }, + // ]); + // }); + // test('invalid import path inside module', async () => { + // const result = await request('error.import.path'); + // expect(result).toStrictEqual([ + // false, + // { + // code: 3, + // description: 'Internal error', + // }, + // ]); + // }); + // test('invalid import field inside module', async () => { + // const result = await request('error.import.field'); + // expect(result).toStrictEqual([ + // false, + // { + // code: 3, + // description: 'Internal error', + // }, + // ]); + // }); +}); diff --git a/dist/esm/module.d.ts b/dist/esm/module.d.ts new file mode 100644 index 0000000..ca33951 --- /dev/null +++ b/dist/esm/module.d.ts @@ -0,0 +1,9 @@ +import { HyperAPI } from './main'; +import type { HyperAPIRequest, HyperAPIRequestArgs } from './request'; +import type { MaybePromise } from './utils/types'; +export type HyperAPIModuleResponse = Record | unknown[] | undefined; +export interface HyperAPIModule> { + readonly default: (request: R) => MaybePromise; + readonly argsValidator: (args: unknown) => R extends HyperAPIRequest ? A : never; +} +export type InferModule> = H extends HyperAPI ? M : never; diff --git a/dist/esm/module.js b/dist/esm/module.js new file mode 100644 index 0000000..cb0ff5c --- /dev/null +++ b/dist/esm/module.js @@ -0,0 +1 @@ +export {}; diff --git a/dist/esm/request.d.ts b/dist/esm/request.d.ts new file mode 100644 index 0000000..4ead616 --- /dev/null +++ b/dist/esm/request.d.ts @@ -0,0 +1,7 @@ +import type { EmptyObject, HTTPMethod } from './utils/types'; +export type HyperAPIRequestArgs = Record; +export interface HyperAPIRequest { + method: HTTPMethod; + path: string; + args: A; +} diff --git a/dist/esm/request.js b/dist/esm/request.js new file mode 100644 index 0000000..cb0ff5c --- /dev/null +++ b/dist/esm/request.js @@ -0,0 +1 @@ +export {}; diff --git a/dist/esm/response.d.ts b/dist/esm/response.d.ts new file mode 100644 index 0000000..9b61a74 --- /dev/null +++ b/dist/esm/response.d.ts @@ -0,0 +1,3 @@ +import { HyperAPIError } from './error'; +import { HyperAPIModuleResponse } from './module'; +export type HyperAPIResponse = HyperAPIModuleResponse | HyperAPIError; diff --git a/dist/esm/response.js b/dist/esm/response.js new file mode 100644 index 0000000..cb0ff5c --- /dev/null +++ b/dist/esm/response.js @@ -0,0 +1 @@ +export {}; diff --git a/dist/esm/router.d.ts b/dist/esm/router.d.ts new file mode 100644 index 0000000..1c3f152 --- /dev/null +++ b/dist/esm/router.d.ts @@ -0,0 +1,21 @@ +import { type IRequest, type IttyRouterType } from 'itty-router'; +import { HTTPMethod } from './utils/types'; +/** + * Creates new IttyRouter from filesystem. + * @param path The path to scan. + * @returns The new IttyRouter. + */ +export declare function createRouter(path: string): IttyRouterType; +interface RouterResponse { + module_path: string; + args: Record; +} +/** + * Fetches data from router. + * @param router The router to fetch data from. + * @param method The HTTP method. + * @param path The path to fetch data from. + * @returns The response. + */ +export declare function useRouter(router: IttyRouterType, method: HTTPMethod, path: string): Promise; +export {}; diff --git a/dist/esm/router.js b/dist/esm/router.js new file mode 100644 index 0000000..f1bdd75 --- /dev/null +++ b/dist/esm/router.js @@ -0,0 +1,103 @@ +/* eslint-disable n/no-sync */ +import { IttyRouter, } from 'itty-router'; +import { readdirSync } from 'node:fs'; +import nodePath from 'node:path'; +/** + * Creates new IttyRouter from filesystem. + * @param path The path to scan. + * @returns The new IttyRouter. + */ +export function createRouter(path) { + // eslint-disable-next-line new-cap + const router = IttyRouter(); + scanDirectory(router, path); + return router; +} +/** + * Fetches data from router. + * @param router The router to fetch data from. + * @param method The HTTP method. + * @param path The path to fetch data from. + * @returns The response. + */ +export function useRouter(router, method, path) { + return router.fetch({ + method, + url: `file://${path}`, + }); +} +const REGEXP_FILE_EXTENSION = /\.(js|mjs|cjs|ts)$/; +const REGEXP_HTTP_METHOD = /\.\[(delete|get|head|options|patch|post|put)]$/; +const REGEXP_PATH_SLUG = /\[(\w+)]/g; +/** + * Scans directory for routes. + * @param router The router to add routes to. + * @param path The path to scan. + * @param [regexp_parts] The parts of the regular expression. + */ +function scanDirectory(router, path, regexp_parts = ['']) { + const result = readdirSync(path, { + withFileTypes: true, + }); + const routes = { + 0: [], // routes with no method and no slug + 1: [], // routes with method and no slug + 2: [], // routes with no method and slug + 3: [], // routes with method and slug + }; + for (const entry of result) { + const entry_path = nodePath.join(path, entry.name); + if (entry.isFile()) { + let file_name = entry.name; + if (REGEXP_FILE_EXTENSION.test(file_name)) { + file_name = file_name.replace(REGEXP_FILE_EXTENSION, ''); + let method = 'all'; + const method_match = file_name.match(REGEXP_HTTP_METHOD); + const has_method = method_match ? 1 : 0; + if (method_match) { + method = method_match[1]; + file_name = file_name.replace(REGEXP_HTTP_METHOD, ''); + } + const has_slug = REGEXP_PATH_SLUG.test(file_name) ? 2 : 0; + file_name = file_name.replaceAll(REGEXP_PATH_SLUG, ':$1'); + // console.log( + // entry_path, + // method, + // [ + // ...regexp_parts, + // file_name, + // ].join(nodePath.sep), + // ); + // eslint-disable-next-line no-bitwise + routes[has_method | has_slug].push({ + method, + path: [ + ...regexp_parts, + file_name, + ].join(nodePath.sep), + module_path: entry_path, + }); + } + } + else { + scanDirectory(router, entry_path, [ + ...regexp_parts, + entry.name.replaceAll(REGEXP_PATH_SLUG, ':$1'), + ]); + } + } + for (const route of [ + ...routes[1], + ...routes[3], + ...routes[0], + ...routes[2], + ]) { + router[route.method](route.path, (r) => { + const response = { + module_path: route.module_path, + args: r.params, + }; + return response; + }); + } +} diff --git a/dist/esm/utils/is-record.d.ts b/dist/esm/utils/is-record.d.ts new file mode 100644 index 0000000..b3e9d51 --- /dev/null +++ b/dist/esm/utils/is-record.d.ts @@ -0,0 +1,6 @@ +/** + * Check if a value is a record. + * @param value - + * @returns - + */ +export declare function isRecord(value: unknown): value is Record; diff --git a/dist/esm/utils/is-record.js b/dist/esm/utils/is-record.js new file mode 100644 index 0000000..350e9df --- /dev/null +++ b/dist/esm/utils/is-record.js @@ -0,0 +1,12 @@ +/** + * Check if a value is a record. + * @param value - + * @returns - + */ +export function isRecord(value) { + return typeof value === 'object' + && value !== null + && !Array.isArray(value) + && value.constructor === Object + && Object.prototype.toString.call(value) === '[object Object]'; +} diff --git a/dist/esm/utils/types.d.ts b/dist/esm/utils/types.d.ts new file mode 100644 index 0000000..d050ecd --- /dev/null +++ b/dist/esm/utils/types.d.ts @@ -0,0 +1,5 @@ +export type EmptyObject = Omit<{ + p: never; +}, 'p'>; +export type MaybePromise = T | Promise; +export type HTTPMethod = 'DELETE' | 'GET' | 'HEAD' | 'OPTIONS' | 'PATCH' | 'POST' | 'PUT' | 'UNKNOWN'; diff --git a/dist/esm/utils/types.js b/dist/esm/utils/types.js new file mode 100644 index 0000000..cb0ff5c --- /dev/null +++ b/dist/esm/utils/types.js @@ -0,0 +1 @@ +export {}; diff --git a/dist/main.cjs b/dist/main.cjs index b31cad3..41ed216 100644 --- a/dist/main.cjs +++ b/dist/main.cjs @@ -1,6 +1,9 @@ +"use strict"; +var __create = Object.create; var __defProp = Object.defineProperty; var __getOwnPropDesc = Object.getOwnPropertyDescriptor; var __getOwnPropNames = Object.getOwnPropertyNames; +var __getProtoOf = Object.getPrototypeOf; var __hasOwnProp = Object.prototype.hasOwnProperty; var __export = (target, all) => { for (var name in all) @@ -14,9 +17,17 @@ var __copyProps = (to, from, except, desc) => { } return to; }; +var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps( + // If the importer is in node compatibility mode or this is not an ESM + // file that has been converted to a CommonJS file using a Babel- + // compatible transform (i.e. "__esModule" has not been set), then set + // "default" to the CommonJS "module.exports" for node compatibility. + isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target, + mod +)); var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod); -// src/main.js +// dist/esm/main.js var main_exports = {}; __export(main_exports, { HyperAPI: () => HyperAPI, @@ -24,7 +35,6 @@ __export(main_exports, { HyperAPIBusyError: () => HyperAPIBusyError, HyperAPICaptchaError: () => HyperAPICaptchaError, HyperAPIConfirmationError: () => HyperAPIConfirmationError, - HyperAPIDriver: () => HyperAPIDriver, HyperAPIError: () => HyperAPIError, HyperAPIForbiddenError: () => HyperAPIForbiddenError, HyperAPIInternalError: () => HyperAPIInternalError, @@ -33,73 +43,56 @@ __export(main_exports, { HyperAPIOTPError: () => HyperAPIOTPError, HyperAPIObjectsLimitError: () => HyperAPIObjectsLimitError, HyperAPIRateLimitError: () => HyperAPIRateLimitError, - HyperAPIRequest: () => HyperAPIRequest, - HyperAPIResponse: () => HyperAPIResponse, HyperAPIUnknownMethodError: () => HyperAPIUnknownMethodError }); module.exports = __toCommonJS(main_exports); -var import_node_path2 = require("node:path"); +var import_node_path2 = __toESM(require("node:path"), 1); -// src/error.js +// dist/esm/utils/is-record.js +function isRecord(value) { + return typeof value === "object" && value !== null && !Array.isArray(value) && value.constructor === Object && Object.prototype.toString.call(value) === "[object Object]"; +} + +// dist/esm/error.js var HyperAPIError = class extends Error { - /** - * The error code. - * @type {number} - * @readonly - */ - code; - /** - * The error description. - * @type {string?} - * @readonly - */ - description = null; - /** - * The error data. - * @type {{[key: string]: any}} - * @readonly - */ + /** The error code. */ + code = 0; + /** The error description. */ + description = "HyperAPI error"; + /** The error data. */ data; - /** @type {number?} */ + /** HTTP status code. */ httpStatus; - /** @type {Record?} */ + /** HTTP headers to return. */ httpHeaders; - /** - * @param {{[key: string]: any}} [data] The error data. - */ constructor(data) { super(); - if (data !== null && typeof data === "object") { + if (isRecord(data)) { this.data = data; - } else if (data !== void 0) { - throw new TypeError("Argument 0 must be an object or not be provided"); } } - /** - * @returns {string} - - */ get message() { - return `${this.description ?? ""} (code ${this.code})`; + return `${this.description} (code ${this.code}).`; } /** * Creates response object. - * @returns {HyperAPIErrorResponse} - + * @returns - */ getResponse() { - const result = { + const response = { code: this.code }; if (typeof this.description === "string") { - result.description = this.description; + response.description = this.description; } if (this.data) { - result.data = this.data; + response.data = this.data; } - return result; + return response; } }; -// src/api-errors.js +// dist/esm/api-errors.js var HyperAPIAuthorizationError = class extends HyperAPIError { code = 1; description = "Authorization error"; @@ -173,266 +166,202 @@ var HyperAPIMaintenanceError = class extends HyperAPIError { // Service Unavailable }; -// src/request.js -var import_node_crypto = require("node:crypto"); -var HyperAPIRequest = class extends Event { - /** - * The unique identifier for this request. - * @type {string} - * @readonly - */ - response_event_name = "response:" + (0, import_node_crypto.randomUUID)(); - /** - * The relative path to the JavaScript module that contains requested API method. - * @type {string} - * @readonly - */ - module_path; - /** - * Request arguments to pass to the API method. - * @type {HyperAPIRequestArgs} - * @readonly - */ - args; - /** - * @param {string} module_path The relative path to the API method module. - * @param {HyperAPIRequestArgs} args The arguments to pass to the API method. - */ - constructor(module_path, args) { - super("request"); - this.module_path = module_path; - this.args = args; - } -}; - -// src/response.js -var HyperAPIResponse = class extends Event { - /** - * Creates a HyperAPI response. - * @param {HyperAPIRequest} request The request. - * @param {HyperAPIError | Record | any[]} value The error or the response value. - */ - constructor(request, value) { - super(request.response_event_name); - if (value instanceof HyperAPIError) { - this.error = value; - } else if (value === void 0) { - this.data = {}; - } else if (value !== null && typeof value === "object" || Array.isArray(value)) { - this.data = value; +// dist/esm/router.js +var import_itty_router = require("itty-router"); +var import_node_fs = require("node:fs"); +var import_node_path = __toESM(require("node:path"), 1); +function createRouter(path) { + const router = (0, import_itty_router.IttyRouter)(); + scanDirectory(router, path); + return router; +} +function useRouter(router, method, path) { + return router.fetch({ + method, + url: `file://${path}` + }); +} +var REGEXP_FILE_EXTENSION = /\.(js|mjs|cjs|ts)$/; +var REGEXP_HTTP_METHOD = /\.\[(delete|get|head|options|patch|post|put)]$/; +var REGEXP_PATH_SLUG = /\[(\w+)]/g; +function scanDirectory(router, path, regexp_parts = [""]) { + const result = (0, import_node_fs.readdirSync)(path, { + withFileTypes: true + }); + const routes = { + 0: [], + // routes with no method and no slug + 1: [], + // routes with method and no slug + 2: [], + // routes with no method and slug + 3: [] + // routes with method and slug + }; + for (const entry of result) { + const entry_path = import_node_path.default.join(path, entry.name); + if (entry.isFile()) { + let file_name = entry.name; + if (REGEXP_FILE_EXTENSION.test(file_name)) { + file_name = file_name.replace(REGEXP_FILE_EXTENSION, ""); + let method = "all"; + const method_match = file_name.match(REGEXP_HTTP_METHOD); + const has_method = method_match ? 1 : 0; + if (method_match) { + method = method_match[1]; + file_name = file_name.replace(REGEXP_HTTP_METHOD, ""); + } + const has_slug = REGEXP_PATH_SLUG.test(file_name) ? 2 : 0; + file_name = file_name.replaceAll(REGEXP_PATH_SLUG, ":$1"); + routes[has_method | has_slug].push({ + method, + path: [ + ...regexp_parts, + file_name + ].join(import_node_path.default.sep), + module_path: entry_path + }); + } } else { - throw new TypeError("Argument 0 must be an instance of HyperAPIError or be an object or an array."); + scanDirectory(router, entry_path, [ + ...regexp_parts, + entry.name.replaceAll(REGEXP_PATH_SLUG, ":$1") + ]); } } - /** - * @returns {boolean} Whether the response is successful. - * @readonly - */ - get is_success() { - return this.error === void 0; - } - /** - * Returns response as an object. For example, that can be used as the body of a HTTP response. - * @returns {{[key: string]: *}?} The response. - */ - getResponse() { - if (this.error) { - return this.error.getResponse(); - } - return this.data; + for (const route of [ + ...routes[1], + ...routes[3], + ...routes[0], + ...routes[2] + ]) { + router[route.method](route.path, (r) => { + const response = { + module_path: route.module_path, + args: r.params + }; + return response; + }); } -}; +} -// src/driver.js -var HyperAPIDriver = class extends EventTarget { +// dist/esm/main.js +var ENTRYPOINT_PATH = import_node_path2.default.dirname(process.argv[1]); +var HyperAPI = class { + router; + driver; /** - * @param {HyperAPIRequest} request - - * @returns {Promise} - + * Creates a HyperAPI instance. + * @param options The options. + * @param options.driver The driver. + * @param [options.root] The root directory for API methods modules. Default: `hyper-api` directory alongside the entrypoint script. */ - async processRequest(request) { - const promise = new Promise((resolve) => { - this.addEventListener( - request.response_event_name, - (response) => { - if (response instanceof HyperAPIResponse) { - resolve(response); + constructor({ driver, root = import_node_path2.default.join(ENTRYPOINT_PATH, "hyper-api") }) { + this.driver = driver; + this.router = createRouter(root); + this.driver.start(async (driver_request) => { + const [request, module_, response] = await this.processRequest(driver_request); + if (request && module_) { + for (const hook of this.handlers.response) { + try { + await hook(request, module_, response); + } catch (error) { + console.error('Error in "response" hook:'); + console.error(error); } - }, - { - once: true } - ); + } + return response; }); - this.dispatchEvent(request); - return promise; - } -}; - -// src/utils/extract-module-not-found-path.js -var import_node_path = require("node:path"); -var REGEXP_MODULE_SPECIFIER = /Cannot find module ["'](.+)["'] (?:imported\s)?from/; -var REGEXP_MODULE_REQUESTER = /\s(?:imported\s)?from ["'](.+)["']/; -function extractPath(error) { - if (typeof error.specifier === "string") { - return error.specifier; - } - if (error.url instanceof URL) { - return error.url.pathname; - } - if (typeof error.url === "string") { - return new URL(error.url).pathname; - } - const match = error.message.match(REGEXP_MODULE_SPECIFIER); - if (match !== null) { - return match[1]; } - throw error; -} -function extractModuleNotFoundPath(error) { - const path = extractPath(error); - if (path.startsWith("/")) { - return path; - } - const match = error.message.match(REGEXP_MODULE_REQUESTER); - if (match !== null) { - const specifier_from = match[1]; - return (0, import_node_path.join)( - (0, import_node_path.dirname)(specifier_from), - path - ); - } - throw error; -} - -// src/main.js -var ENTRYPOINT_PATH = (0, import_node_path2.dirname)(process.argv[1]); -var HyperAPI = class { - /** @type {HyperAPIDriver} The HyperAPI driver. */ - #driver; - /** @type {string} The root directory for API methods modules. */ - #root; - /** @type {function(HyperAPIRequest): void} Handles a request. */ - #requestHandler; + handlers = { + transformer: void 0, + module: [], + response: [] + }; /** - * Creates a HyperAPI instance. - * @param {object} options The options. - * @param {HyperAPIDriver} options.driver The HyperAPI driver. - * @param {string} [options.root] The root directory for API methods modules. Default: `hyper-api` directory alongside the entrypoint script. + * Use this hook add properties to the request before it is send to the API module. + * + * This hook can be set only once. + * @param transformer The callback function. */ - constructor({ - driver, - root = (0, import_node_path2.join)( - ENTRYPOINT_PATH, - "hyper-api" - ) - }) { - if (driver instanceof HyperAPIDriver !== true) { - throw new TypeError('Property "driver" must be an instance of HyperAPIDriver.'); + setTransformer(transformer) { + if (this.handlers.transformer) { + throw new Error("Transformer has already been set."); } - this.#driver = driver; - this.#requestHandler = async (request) => { - try { - const response = await this.#handleRequest(request); - this.#driver.dispatchEvent(response); - } catch (error) { - console.error("Unexpected error happened:"); - console.error(error); - console.error("This error should not have reached this point."); - console.error("This is probably a bug in the HyperAPI driver you are using or in the HyperAPI itself."); - console.error("Now exiting the process."); - process.exit(1); - } - }; - this.#driver.addEventListener( - "request", - this.#requestHandler - ); - this.#root = root; + this.handlers.transformer = transformer; } /** - * Removes the request event listener from the driver. + * Adds a hook to be called when the API module is imported. + * @param callback - */ - #turnDriverOff() { - this.#driver.removeEventListener( - "request", - this.#requestHandler - ); + onModule(callback) { + this.handlers.module.push(callback); } /** - * Processes a request and returns the response. - * @param {HyperAPIRequest} request The HyperAPI request. - * @returns {Promise} The HyperAPI response. + * Adds a hook to be called right before the response is sent back. + * + * This hook called only if the request was processed by the API module. If unknown method was requested, this hook is not called. + * @param callback - */ - async #handleRequest(request) { + onResponse(callback) { + this.handlers.response.push(callback); + } + async processRequest(driver_request) { + let request = null; + let module_ = null; try { - const response_data = await this.#useModule(request); - return new HyperAPIResponse( + if (driver_request.path.startsWith("/") !== true) { + driver_request.path = `/${driver_request.path}`; + } + const router_response = await useRouter(this.router, driver_request.method, driver_request.path); + if (!router_response) { + return [ + request, + module_, + new HyperAPIUnknownMethodError() + ]; + } + driver_request.args = { + ...driver_request.args, + ...router_response.args + }; + request = this.handlers.transformer ? await this.handlers.transformer(driver_request) : driver_request; + module_ = await import(router_response.module_path); + if (module_.argsValidator) { + request.args = module_.argsValidator(request.args); + } + for (const hook of this.handlers.module) { + await hook(request, module_); + } + const response = await module_.default(request); + return [ request, - response_data - ); + module_, + response + ]; } catch (error) { - if (error instanceof HyperAPIError !== true) { - console.error(error); - error = new HyperAPIInternalError(); + if (error instanceof HyperAPIError) { + return [ + request, + module_, + error + ]; } - return new HyperAPIResponse( + console.error(error); + return [ request, - error - ); + module_, + new HyperAPIInternalError() + ]; } + throw new Error("Unreachable"); } - /** - * Processes a request and returns the response. - * @param {HyperAPIRequest} request The HyperAPI request. - * @returns {Promise} The HyperAPI response. - */ - async #getModule(request) { - const filenames = [ - request.module_path, - `${request.module_path}.js`, - `${request.module_path}.mjs`, - `${request.module_path}.cjs`, - (0, import_node_path2.join)(request.module_path, "index.js") - ]; - for (const filename of filenames) { - const path = (0, import_node_path2.join)( - this.#root, - filename - ); - try { - return await import(path); - } catch (error) { - if (error.code === "ERR_MODULE_NOT_FOUND") { - const path_not_found = extractModuleNotFoundPath(error); - if (path === path_not_found) { - continue; - } - } - if (error instanceof Error && error.message.startsWith(`Failed to load url ${path} `)) { - continue; - } - throw error; - } - } - throw new HyperAPIUnknownMethodError(); - } - /** - * Processes a request and returns the response. - * @param {HyperAPIRequest} request The HyperAPI request. - * @returns {Promise} The HyperAPI response. - */ - async #useModule(request) { - const module2 = await this.#getModule(request); - if (typeof module2.argsValidator === "function") { - request.args = await module2.argsValidator(request.args); - } - return module2.default(request); - } - /** - * Destroys the HyperAPI instance. - */ + /** Destroys the HyperAPI instance. */ destroy() { - this.#turnDriverOff(); + this.handlers.transformer = void 0; + this.handlers.module.splice(0); + this.handlers.response.splice(0); } }; // Annotate the CommonJS export names for ESM import in node: @@ -442,7 +371,6 @@ var HyperAPI = class { HyperAPIBusyError, HyperAPICaptchaError, HyperAPIConfirmationError, - HyperAPIDriver, HyperAPIError, HyperAPIForbiddenError, HyperAPIInternalError, @@ -451,7 +379,5 @@ var HyperAPI = class { HyperAPIOTPError, HyperAPIObjectsLimitError, HyperAPIRateLimitError, - HyperAPIRequest, - HyperAPIResponse, HyperAPIUnknownMethodError }); diff --git a/eslint.config.js b/eslint.config.js new file mode 100644 index 0000000..59ec8dc --- /dev/null +++ b/eslint.config.js @@ -0,0 +1 @@ +export { config as default } from '@kirick/eslint-config'; diff --git a/package.json b/package.json index cc4ca7a..b556569 100644 --- a/package.json +++ b/package.json @@ -1,42 +1,42 @@ { "name": "@hyperapi/core", - "version": "0.2.0-beta.3", + "version": "0.3.0-beta.1", "description": "Core package of the HyperAPI project.", "publishConfig": { "access": "public" }, "type": "module", - "main": "src/main.js", - "types": "types/main.d.ts", + "main": "dist/esm/main.js", + "types": "dist/esm/main.d.ts", "exports": { ".": { - "import": "./src/main.js", + "import": "./dist/esm/main.js", "require": "./dist/main.cjs" } }, "engines": { - "node": ">=10.0.0" + "node": ">=15.4.0" + }, + "dependencies": { + "itty-router": "^5.0.18" }, "devDependencies": { - "@babel/eslint-parser": "7.21.8", - "@types/node": "^20.14.8", - "eslint": "8.41.0", - "eslint-config-xo": "0.43.1", - "eslint-plugin-import": "2.27.5", - "eslint-plugin-jsdoc": "46.5.0", - "eslint-plugin-node": "11.1.0", - "eslint-plugin-promise": "6.1.1", - "eslint-plugin-unicorn": "47.0.0", - "valibot": "^0.35", - "vitest": "^1.6" + "@kirick/eslint-config": "latest", + "@types/bun": "^1.1.9", + "@types/node": "^22.5.5", + "eslint": "9.10.0", + "typescript": "5.5.4", + "valibot": "^0.42.0", + "vitest": "^2.1.1" }, "scripts": { + "build": "bun run build:ts && bun run build:cjs", + "build:cjs": "bunx esbuild --bundle --platform=node --format=cjs --packages=external --outfile=dist/main.cjs dist/esm/main.js", + "build:ts": "rm -r dist/esm ; tsc && (mv dist/esm/src dist/.esm && rm -r dist/esm && mv dist/.esm dist/esm)", + "lint": "eslint . && tsc --skipLibCheck --noemit", + "publish:npm": "bun run build && bun run lint && bun run test && npm publish", "test": "npm run test:vitest && bun test --coverage", - "test:vitest": "vitest run --no-file-parallelism --exclude '**/extract-*'", - "build": "bun run build:types && bun run build:cjs", - "build:cjs": "bunx esbuild --bundle --platform=node --format=cjs --packages=external --outfile=dist/main.cjs src/main.js", - "build:types": "bunx tsc --skipLibCheck --declaration --emitDeclarationOnly --outDir types", - "publish:npm": "pnpm i && bun run build && eslint . && bunx tsc --skipLibCheck --noemit && bun run test && npm publish" + "test:vitest": "vitest run --no-file-parallelism" }, "repository": { "type": "git", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml deleted file mode 100644 index 22aab0c..0000000 --- a/pnpm-lock.yaml +++ /dev/null @@ -1,3444 +0,0 @@ -lockfileVersion: '9.0' - -settings: - autoInstallPeers: true - excludeLinksFromLockfile: false - -importers: - - .: - devDependencies: - '@babel/eslint-parser': - specifier: 7.21.8 - version: 7.21.8(@babel/core@7.24.7)(eslint@8.41.0) - '@types/node': - specifier: ^20.14.8 - version: 20.14.8 - eslint: - specifier: 8.41.0 - version: 8.41.0 - eslint-config-xo: - specifier: 0.43.1 - version: 0.43.1(eslint@8.41.0) - eslint-plugin-import: - specifier: 2.27.5 - version: 2.27.5(eslint@8.41.0) - eslint-plugin-jsdoc: - specifier: 46.5.0 - version: 46.5.0(eslint@8.41.0) - eslint-plugin-node: - specifier: 11.1.0 - version: 11.1.0(eslint@8.41.0) - eslint-plugin-promise: - specifier: 6.1.1 - version: 6.1.1(eslint@8.41.0) - eslint-plugin-unicorn: - specifier: 47.0.0 - version: 47.0.0(eslint@8.41.0) - valibot: - specifier: ^0.35 - version: 0.35.0 - vitest: - specifier: ^1.6 - version: 1.6.0(@types/node@20.14.8) - -packages: - - '@ampproject/remapping@2.3.0': - resolution: {integrity: sha512-30iZtAPgz+LTIYoeivqYo853f02jBYSd5uGnGpkFV0M3xOt9aN73erkgYAmZU43x4VfqcnLxW9Kpg3R5LC4YYw==} - engines: {node: '>=6.0.0'} - - '@babel/code-frame@7.24.7': - resolution: {integrity: sha512-BcYH1CVJBO9tvyIZ2jVeXgSIMvGZ2FDRvDdOIVQyuklNKSsx+eppDEBq/g47Ayw+RqNFE+URvOShmf+f/qwAlA==} - engines: {node: '>=6.9.0'} - - '@babel/compat-data@7.24.7': - resolution: {integrity: sha512-qJzAIcv03PyaWqxRgO4mSU3lihncDT296vnyuE2O8uA4w3UHWI4S3hgeZd1L8W1Bft40w9JxJ2b412iDUFFRhw==} - engines: {node: '>=6.9.0'} - - '@babel/core@7.24.7': - resolution: {integrity: sha512-nykK+LEK86ahTkX/3TgauT0ikKoNCfKHEaZYTUVupJdTLzGNvrblu4u6fa7DhZONAltdf8e662t/abY8idrd/g==} - engines: {node: '>=6.9.0'} - - '@babel/eslint-parser@7.21.8': - resolution: {integrity: sha512-HLhI+2q+BP3sf78mFUZNCGc10KEmoUqtUT1OCdMZsN+qr4qFeLUod62/zAnF3jNQstwyasDkZnVXwfK2Bml7MQ==} - engines: {node: ^10.13.0 || ^12.13.0 || >=14.0.0} - peerDependencies: - '@babel/core': '>=7.11.0' - eslint: ^7.5.0 || ^8.0.0 - - '@babel/generator@7.24.7': - resolution: {integrity: sha512-oipXieGC3i45Y1A41t4tAqpnEZWgB/lC6Ehh6+rOviR5XWpTtMmLN+fGjz9vOiNRt0p6RtO6DtD0pdU3vpqdSA==} - engines: {node: '>=6.9.0'} - - '@babel/helper-compilation-targets@7.24.7': - resolution: {integrity: sha512-ctSdRHBi20qWOfy27RUb4Fhp07KSJ3sXcuSvTrXrc4aG8NSYDo1ici3Vhg9bg69y5bj0Mr1lh0aeEgTvc12rMg==} - engines: {node: '>=6.9.0'} - - '@babel/helper-environment-visitor@7.24.7': - resolution: {integrity: sha512-DoiN84+4Gnd0ncbBOM9AZENV4a5ZiL39HYMyZJGZ/AZEykHYdJw0wW3kdcsh9/Kn+BRXHLkkklZ51ecPKmI1CQ==} - engines: {node: '>=6.9.0'} - - '@babel/helper-function-name@7.24.7': - resolution: {integrity: sha512-FyoJTsj/PEUWu1/TYRiXTIHc8lbw+TDYkZuoE43opPS5TrI7MyONBE1oNvfguEXAD9yhQRrVBnXdXzSLQl9XnA==} - engines: {node: '>=6.9.0'} - - '@babel/helper-hoist-variables@7.24.7': - resolution: {integrity: sha512-MJJwhkoGy5c4ehfoRyrJ/owKeMl19U54h27YYftT0o2teQ3FJ3nQUf/I3LlJsX4l3qlw7WRXUmiyajvHXoTubQ==} - engines: {node: '>=6.9.0'} - - '@babel/helper-module-imports@7.24.7': - resolution: {integrity: sha512-8AyH3C+74cgCVVXow/myrynrAGv+nTVg5vKu2nZph9x7RcRwzmh0VFallJuFTZ9mx6u4eSdXZfcOzSqTUm0HCA==} - engines: {node: '>=6.9.0'} - - '@babel/helper-module-transforms@7.24.7': - resolution: {integrity: sha512-1fuJEwIrp+97rM4RWdO+qrRsZlAeL1lQJoPqtCYWv0NL115XM93hIH4CSRln2w52SqvmY5hqdtauB6QFCDiZNQ==} - engines: {node: '>=6.9.0'} - peerDependencies: - '@babel/core': ^7.0.0 - - '@babel/helper-simple-access@7.24.7': - resolution: {integrity: sha512-zBAIvbCMh5Ts+b86r/CjU+4XGYIs+R1j951gxI3KmmxBMhCg4oQMsv6ZXQ64XOm/cvzfU1FmoCyt6+owc5QMYg==} - engines: {node: '>=6.9.0'} - - '@babel/helper-split-export-declaration@7.24.7': - resolution: {integrity: sha512-oy5V7pD+UvfkEATUKvIjvIAH/xCzfsFVw7ygW2SI6NClZzquT+mwdTfgfdbUiceh6iQO0CHtCPsyze/MZ2YbAA==} - engines: {node: '>=6.9.0'} - - '@babel/helper-string-parser@7.24.7': - resolution: {integrity: sha512-7MbVt6xrwFQbunH2DNQsAP5sTGxfqQtErvBIvIMi6EQnbgUOuVYanvREcmFrOPhoXBrTtjhhP+lW+o5UfK+tDg==} - engines: {node: '>=6.9.0'} - - '@babel/helper-validator-identifier@7.24.7': - resolution: {integrity: sha512-rR+PBcQ1SMQDDyF6X0wxtG8QyLCgUB0eRAGguqRLfkCA87l7yAP7ehq8SNj96OOGTO8OBV70KhuFYcIkHXOg0w==} - engines: {node: '>=6.9.0'} - - '@babel/helper-validator-option@7.24.7': - resolution: {integrity: sha512-yy1/KvjhV/ZCL+SM7hBrvnZJ3ZuT9OuZgIJAGpPEToANvc3iM6iDvBnRjtElWibHU6n8/LPR/EjX9EtIEYO3pw==} - engines: {node: '>=6.9.0'} - - '@babel/helpers@7.24.7': - resolution: {integrity: sha512-NlmJJtvcw72yRJRcnCmGvSi+3jDEg8qFu3z0AFoymmzLx5ERVWyzd9kVXr7Th9/8yIJi2Zc6av4Tqz3wFs8QWg==} - engines: {node: '>=6.9.0'} - - '@babel/highlight@7.24.7': - resolution: {integrity: sha512-EStJpq4OuY8xYfhGVXngigBJRWxftKX9ksiGDnmlY3o7B/V7KIAc9X4oiK87uPJSc/vs5L869bem5fhZa8caZw==} - engines: {node: '>=6.9.0'} - - '@babel/parser@7.24.7': - resolution: {integrity: sha512-9uUYRm6OqQrCqQdG1iCBwBPZgN8ciDBro2nIOFaiRz1/BCxaI7CNvQbDHvsArAC7Tw9Hda/B3U+6ui9u4HWXPw==} - engines: {node: '>=6.0.0'} - hasBin: true - - '@babel/template@7.24.7': - resolution: {integrity: sha512-jYqfPrU9JTF0PmPy1tLYHW4Mp4KlgxJD9l2nP9fD6yT/ICi554DmrWBAEYpIelzjHf1msDP3PxJIRt/nFNfBig==} - engines: {node: '>=6.9.0'} - - '@babel/traverse@7.24.7': - resolution: {integrity: sha512-yb65Ed5S/QAcewNPh0nZczy9JdYXkkAbIsEo+P7BE7yO3txAY30Y/oPa3QkQ5It3xVG2kpKMg9MsdxZaO31uKA==} - engines: {node: '>=6.9.0'} - - '@babel/types@7.24.7': - resolution: {integrity: sha512-XEFXSlxiG5td2EJRe8vOmRbaXVgfcBlszKujvVmWIK/UpywWljQCfzAv3RQCGujWQ1RD4YYWEAqDXfuJiy8f5Q==} - engines: {node: '>=6.9.0'} - - '@es-joy/jsdoccomment@0.40.1': - resolution: {integrity: sha512-YORCdZSusAlBrFpZ77pJjc5r1bQs5caPWtAu+WWmiSo+8XaUzseapVrfAtiRFbQWnrBxxLLEwF6f6ZG/UgCQCg==} - engines: {node: '>=16'} - - '@esbuild/aix-ppc64@0.21.5': - resolution: {integrity: sha512-1SDgH6ZSPTlggy1yI6+Dbkiz8xzpHJEVAlF/AM1tHPLsf5STom9rwtjE4hKAF20FfXXNTFqEYXyJNWh1GiZedQ==} - engines: {node: '>=12'} - cpu: [ppc64] - os: [aix] - - '@esbuild/android-arm64@0.21.5': - resolution: {integrity: sha512-c0uX9VAUBQ7dTDCjq+wdyGLowMdtR/GoC2U5IYk/7D1H1JYC0qseD7+11iMP2mRLN9RcCMRcjC4YMclCzGwS/A==} - engines: {node: '>=12'} - cpu: [arm64] - os: [android] - - '@esbuild/android-arm@0.21.5': - resolution: {integrity: sha512-vCPvzSjpPHEi1siZdlvAlsPxXl7WbOVUBBAowWug4rJHb68Ox8KualB+1ocNvT5fjv6wpkX6o/iEpbDrf68zcg==} - engines: {node: '>=12'} - cpu: [arm] - os: [android] - - '@esbuild/android-x64@0.21.5': - resolution: {integrity: sha512-D7aPRUUNHRBwHxzxRvp856rjUHRFW1SdQATKXH2hqA0kAZb1hKmi02OpYRacl0TxIGz/ZmXWlbZgjwWYaCakTA==} - engines: {node: '>=12'} - cpu: [x64] - os: [android] - - '@esbuild/darwin-arm64@0.21.5': - resolution: {integrity: sha512-DwqXqZyuk5AiWWf3UfLiRDJ5EDd49zg6O9wclZ7kUMv2WRFr4HKjXp/5t8JZ11QbQfUS6/cRCKGwYhtNAY88kQ==} - engines: {node: '>=12'} - cpu: [arm64] - os: [darwin] - - '@esbuild/darwin-x64@0.21.5': - resolution: {integrity: sha512-se/JjF8NlmKVG4kNIuyWMV/22ZaerB+qaSi5MdrXtd6R08kvs2qCN4C09miupktDitvh8jRFflwGFBQcxZRjbw==} - engines: {node: '>=12'} - cpu: [x64] - os: [darwin] - - '@esbuild/freebsd-arm64@0.21.5': - resolution: {integrity: sha512-5JcRxxRDUJLX8JXp/wcBCy3pENnCgBR9bN6JsY4OmhfUtIHe3ZW0mawA7+RDAcMLrMIZaf03NlQiX9DGyB8h4g==} - engines: {node: '>=12'} - cpu: [arm64] - os: [freebsd] - - '@esbuild/freebsd-x64@0.21.5': - resolution: {integrity: sha512-J95kNBj1zkbMXtHVH29bBriQygMXqoVQOQYA+ISs0/2l3T9/kj42ow2mpqerRBxDJnmkUDCaQT/dfNXWX/ZZCQ==} - engines: {node: '>=12'} - cpu: [x64] - os: [freebsd] - - '@esbuild/linux-arm64@0.21.5': - resolution: {integrity: sha512-ibKvmyYzKsBeX8d8I7MH/TMfWDXBF3db4qM6sy+7re0YXya+K1cem3on9XgdT2EQGMu4hQyZhan7TeQ8XkGp4Q==} - engines: {node: '>=12'} - cpu: [arm64] - os: [linux] - - '@esbuild/linux-arm@0.21.5': - resolution: {integrity: sha512-bPb5AHZtbeNGjCKVZ9UGqGwo8EUu4cLq68E95A53KlxAPRmUyYv2D6F0uUI65XisGOL1hBP5mTronbgo+0bFcA==} - engines: {node: '>=12'} - cpu: [arm] - os: [linux] - - '@esbuild/linux-ia32@0.21.5': - resolution: {integrity: sha512-YvjXDqLRqPDl2dvRODYmmhz4rPeVKYvppfGYKSNGdyZkA01046pLWyRKKI3ax8fbJoK5QbxblURkwK/MWY18Tg==} - engines: {node: '>=12'} - cpu: [ia32] - os: [linux] - - '@esbuild/linux-loong64@0.21.5': - resolution: {integrity: sha512-uHf1BmMG8qEvzdrzAqg2SIG/02+4/DHB6a9Kbya0XDvwDEKCoC8ZRWI5JJvNdUjtciBGFQ5PuBlpEOXQj+JQSg==} - engines: {node: '>=12'} - cpu: [loong64] - os: [linux] - - '@esbuild/linux-mips64el@0.21.5': - resolution: {integrity: sha512-IajOmO+KJK23bj52dFSNCMsz1QP1DqM6cwLUv3W1QwyxkyIWecfafnI555fvSGqEKwjMXVLokcV5ygHW5b3Jbg==} - engines: {node: '>=12'} - cpu: [mips64el] - os: [linux] - - '@esbuild/linux-ppc64@0.21.5': - resolution: {integrity: sha512-1hHV/Z4OEfMwpLO8rp7CvlhBDnjsC3CttJXIhBi+5Aj5r+MBvy4egg7wCbe//hSsT+RvDAG7s81tAvpL2XAE4w==} - engines: {node: '>=12'} - cpu: [ppc64] - os: [linux] - - '@esbuild/linux-riscv64@0.21.5': - resolution: {integrity: sha512-2HdXDMd9GMgTGrPWnJzP2ALSokE/0O5HhTUvWIbD3YdjME8JwvSCnNGBnTThKGEB91OZhzrJ4qIIxk/SBmyDDA==} - engines: {node: '>=12'} - cpu: [riscv64] - os: [linux] - - '@esbuild/linux-s390x@0.21.5': - resolution: {integrity: sha512-zus5sxzqBJD3eXxwvjN1yQkRepANgxE9lgOW2qLnmr8ikMTphkjgXu1HR01K4FJg8h1kEEDAqDcZQtbrRnB41A==} - engines: {node: '>=12'} - cpu: [s390x] - os: [linux] - - '@esbuild/linux-x64@0.21.5': - resolution: {integrity: sha512-1rYdTpyv03iycF1+BhzrzQJCdOuAOtaqHTWJZCWvijKD2N5Xu0TtVC8/+1faWqcP9iBCWOmjmhoH94dH82BxPQ==} - engines: {node: '>=12'} - cpu: [x64] - os: [linux] - - '@esbuild/netbsd-x64@0.21.5': - resolution: {integrity: sha512-Woi2MXzXjMULccIwMnLciyZH4nCIMpWQAs049KEeMvOcNADVxo0UBIQPfSmxB3CWKedngg7sWZdLvLczpe0tLg==} - engines: {node: '>=12'} - cpu: [x64] - os: [netbsd] - - '@esbuild/openbsd-x64@0.21.5': - resolution: {integrity: sha512-HLNNw99xsvx12lFBUwoT8EVCsSvRNDVxNpjZ7bPn947b8gJPzeHWyNVhFsaerc0n3TsbOINvRP2byTZ5LKezow==} - engines: {node: '>=12'} - cpu: [x64] - os: [openbsd] - - '@esbuild/sunos-x64@0.21.5': - resolution: {integrity: sha512-6+gjmFpfy0BHU5Tpptkuh8+uw3mnrvgs+dSPQXQOv3ekbordwnzTVEb4qnIvQcYXq6gzkyTnoZ9dZG+D4garKg==} - engines: {node: '>=12'} - cpu: [x64] - os: [sunos] - - '@esbuild/win32-arm64@0.21.5': - resolution: {integrity: sha512-Z0gOTd75VvXqyq7nsl93zwahcTROgqvuAcYDUr+vOv8uHhNSKROyU961kgtCD1e95IqPKSQKH7tBTslnS3tA8A==} - engines: {node: '>=12'} - cpu: [arm64] - os: [win32] - - '@esbuild/win32-ia32@0.21.5': - resolution: {integrity: sha512-SWXFF1CL2RVNMaVs+BBClwtfZSvDgtL//G/smwAc5oVK/UPu2Gu9tIaRgFmYFFKrmg3SyAjSrElf0TiJ1v8fYA==} - engines: {node: '>=12'} - cpu: [ia32] - os: [win32] - - '@esbuild/win32-x64@0.21.5': - resolution: {integrity: sha512-tQd/1efJuzPC6rCFwEvLtci/xNFcTZknmXs98FYDfGE4wP9ClFV98nyKrzJKVPMhdDnjzLhdUyMX4PsQAPjwIw==} - engines: {node: '>=12'} - cpu: [x64] - os: [win32] - - '@eslint-community/eslint-utils@4.4.0': - resolution: {integrity: sha512-1/sA4dwrzBAyeUoQ6oxahHKmrZvsnLCg4RfxW3ZFGGmQkSNQPFNLV9CUEFQP1x9EYXHTo5p6xdhZM1Ne9p/AfA==} - engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} - peerDependencies: - eslint: ^6.0.0 || ^7.0.0 || >=8.0.0 - - '@eslint-community/regexpp@4.10.1': - resolution: {integrity: sha512-Zm2NGpWELsQAD1xsJzGQpYfvICSsFkEpU0jxBjfdC6uNEWXcHnfs9hScFWtXVDVl+rBQJGrl4g1vcKIejpH9dA==} - engines: {node: ^12.0.0 || ^14.0.0 || >=16.0.0} - - '@eslint/eslintrc@2.1.4': - resolution: {integrity: sha512-269Z39MS6wVJtsoUl10L60WdkhJVdPG24Q4eZTH3nnF6lpvSShEK3wQjDX9JRWAUPvPh7COouPpU9IrqaZFvtQ==} - engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} - - '@eslint/js@8.41.0': - resolution: {integrity: sha512-LxcyMGxwmTh2lY9FwHPGWOHmYFCZvbrFCBZL4FzSSsxsRPuhrYUg/49/0KDfW8tnIEaEHtfmn6+NPN+1DqaNmA==} - engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} - - '@humanwhocodes/config-array@0.11.14': - resolution: {integrity: sha512-3T8LkOmg45BV5FICb15QQMsyUSWrQ8AygVfC7ZG32zOalnqrilm018ZVCw0eapXux8FtA33q8PSRSstjee3jSg==} - engines: {node: '>=10.10.0'} - deprecated: Use @eslint/config-array instead - - '@humanwhocodes/module-importer@1.0.1': - resolution: {integrity: sha512-bxveV4V8v5Yb4ncFTT3rPSgZBOpCkjfK0y4oVVVJwIuDVBRMDXrPyXRL988i5ap9m9bnyEEjWfm5WkBmtffLfA==} - engines: {node: '>=12.22'} - - '@humanwhocodes/object-schema@2.0.3': - resolution: {integrity: sha512-93zYdMES/c1D69yZiKDBj0V24vqNzB/koF26KPaagAfd3P/4gUlh3Dys5ogAK+Exi9QyzlD8x/08Zt7wIKcDcA==} - deprecated: Use @eslint/object-schema instead - - '@jest/schemas@29.6.3': - resolution: {integrity: sha512-mo5j5X+jIZmJQveBKeS/clAueipV7KgiX1vMgCxam1RNYiqE1w62n0/tJJnHtjW8ZHcQco5gY85jA3mi0L+nSA==} - engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} - - '@jridgewell/gen-mapping@0.3.5': - resolution: {integrity: sha512-IzL8ZoEDIBRWEzlCcRhOaCupYyN5gdIK+Q6fbFdPDg6HqX6jpkItn7DFIpW9LQzXG6Df9sA7+OKnq0qlz/GaQg==} - engines: {node: '>=6.0.0'} - - '@jridgewell/resolve-uri@3.1.2': - resolution: {integrity: sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw==} - engines: {node: '>=6.0.0'} - - '@jridgewell/set-array@1.2.1': - resolution: {integrity: sha512-R8gLRTZeyp03ymzP/6Lil/28tGeGEzhx1q2k703KGWRAI1VdvPIXdG70VJc2pAMw3NA6JKL5hhFu1sJX0Mnn/A==} - engines: {node: '>=6.0.0'} - - '@jridgewell/sourcemap-codec@1.4.15': - resolution: {integrity: sha512-eF2rxCRulEKXHTRiDrDy6erMYWqNw4LPdQ8UQA4huuxaQsVeRPFl2oM8oDGxMFhJUWZf9McpLtJasDDZb/Bpeg==} - - '@jridgewell/trace-mapping@0.3.25': - resolution: {integrity: sha512-vNk6aEwybGtawWmy/PzwnGDOjCkLWSD2wqvjGGAgOAwCGWySYXfYoxt00IJkTF+8Lb57DwOb3Aa0o9CApepiYQ==} - - '@nicolo-ribaudo/eslint-scope-5-internals@5.1.1-v1': - resolution: {integrity: sha512-54/JRvkLIzzDWshCWfuhadfrfZVPiElY8Fcgmg1HroEly/EDSszzhBAsarCux+D/kOslTRquNzuyGSmUSTTHGg==} - - '@nodelib/fs.scandir@2.1.5': - resolution: {integrity: sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==} - engines: {node: '>= 8'} - - '@nodelib/fs.stat@2.0.5': - resolution: {integrity: sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==} - engines: {node: '>= 8'} - - '@nodelib/fs.walk@1.2.8': - resolution: {integrity: sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==} - engines: {node: '>= 8'} - - '@rollup/rollup-android-arm-eabi@4.18.0': - resolution: {integrity: sha512-Tya6xypR10giZV1XzxmH5wr25VcZSncG0pZIjfePT0OVBvqNEurzValetGNarVrGiq66EBVAFn15iYX4w6FKgQ==} - cpu: [arm] - os: [android] - - '@rollup/rollup-android-arm64@4.18.0': - resolution: {integrity: sha512-avCea0RAP03lTsDhEyfy+hpfr85KfyTctMADqHVhLAF3MlIkq83CP8UfAHUssgXTYd+6er6PaAhx/QGv4L1EiA==} - cpu: [arm64] - os: [android] - - '@rollup/rollup-darwin-arm64@4.18.0': - resolution: {integrity: sha512-IWfdwU7KDSm07Ty0PuA/W2JYoZ4iTj3TUQjkVsO/6U+4I1jN5lcR71ZEvRh52sDOERdnNhhHU57UITXz5jC1/w==} - cpu: [arm64] - os: [darwin] - - '@rollup/rollup-darwin-x64@4.18.0': - resolution: {integrity: sha512-n2LMsUz7Ynu7DoQrSQkBf8iNrjOGyPLrdSg802vk6XT3FtsgX6JbE8IHRvposskFm9SNxzkLYGSq9QdpLYpRNA==} - cpu: [x64] - os: [darwin] - - '@rollup/rollup-linux-arm-gnueabihf@4.18.0': - resolution: {integrity: sha512-C/zbRYRXFjWvz9Z4haRxcTdnkPt1BtCkz+7RtBSuNmKzMzp3ZxdM28Mpccn6pt28/UWUCTXa+b0Mx1k3g6NOMA==} - cpu: [arm] - os: [linux] - - '@rollup/rollup-linux-arm-musleabihf@4.18.0': - resolution: {integrity: sha512-l3m9ewPgjQSXrUMHg93vt0hYCGnrMOcUpTz6FLtbwljo2HluS4zTXFy2571YQbisTnfTKPZ01u/ukJdQTLGh9A==} - cpu: [arm] - os: [linux] - - '@rollup/rollup-linux-arm64-gnu@4.18.0': - resolution: {integrity: sha512-rJ5D47d8WD7J+7STKdCUAgmQk49xuFrRi9pZkWoRD1UeSMakbcepWXPF8ycChBoAqs1pb2wzvbY6Q33WmN2ftw==} - cpu: [arm64] - os: [linux] - - '@rollup/rollup-linux-arm64-musl@4.18.0': - resolution: {integrity: sha512-be6Yx37b24ZwxQ+wOQXXLZqpq4jTckJhtGlWGZs68TgdKXJgw54lUUoFYrg6Zs/kjzAQwEwYbp8JxZVzZLRepQ==} - cpu: [arm64] - os: [linux] - - '@rollup/rollup-linux-powerpc64le-gnu@4.18.0': - resolution: {integrity: sha512-hNVMQK+qrA9Todu9+wqrXOHxFiD5YmdEi3paj6vP02Kx1hjd2LLYR2eaN7DsEshg09+9uzWi2W18MJDlG0cxJA==} - cpu: [ppc64] - os: [linux] - - '@rollup/rollup-linux-riscv64-gnu@4.18.0': - resolution: {integrity: sha512-ROCM7i+m1NfdrsmvwSzoxp9HFtmKGHEqu5NNDiZWQtXLA8S5HBCkVvKAxJ8U+CVctHwV2Gb5VUaK7UAkzhDjlg==} - cpu: [riscv64] - os: [linux] - - '@rollup/rollup-linux-s390x-gnu@4.18.0': - resolution: {integrity: sha512-0UyyRHyDN42QL+NbqevXIIUnKA47A+45WyasO+y2bGJ1mhQrfrtXUpTxCOrfxCR4esV3/RLYyucGVPiUsO8xjg==} - cpu: [s390x] - os: [linux] - - '@rollup/rollup-linux-x64-gnu@4.18.0': - resolution: {integrity: sha512-xuglR2rBVHA5UsI8h8UbX4VJ470PtGCf5Vpswh7p2ukaqBGFTnsfzxUBetoWBWymHMxbIG0Cmx7Y9qDZzr648w==} - cpu: [x64] - os: [linux] - - '@rollup/rollup-linux-x64-musl@4.18.0': - resolution: {integrity: sha512-LKaqQL9osY/ir2geuLVvRRs+utWUNilzdE90TpyoX0eNqPzWjRm14oMEE+YLve4k/NAqCdPkGYDaDF5Sw+xBfg==} - cpu: [x64] - os: [linux] - - '@rollup/rollup-win32-arm64-msvc@4.18.0': - resolution: {integrity: sha512-7J6TkZQFGo9qBKH0pk2cEVSRhJbL6MtfWxth7Y5YmZs57Pi+4x6c2dStAUvaQkHQLnEQv1jzBUW43GvZW8OFqA==} - cpu: [arm64] - os: [win32] - - '@rollup/rollup-win32-ia32-msvc@4.18.0': - resolution: {integrity: sha512-Txjh+IxBPbkUB9+SXZMpv+b/vnTEtFyfWZgJ6iyCmt2tdx0OF5WhFowLmnh8ENGNpfUlUZkdI//4IEmhwPieNg==} - cpu: [ia32] - os: [win32] - - '@rollup/rollup-win32-x64-msvc@4.18.0': - resolution: {integrity: sha512-UOo5FdvOL0+eIVTgS4tIdbW+TtnBLWg1YBCcU2KWM7nuNwRz9bksDX1bekJJCpu25N1DVWaCwnT39dVQxzqS8g==} - cpu: [x64] - os: [win32] - - '@sinclair/typebox@0.27.8': - resolution: {integrity: sha512-+Fj43pSMwJs4KRrH/938Uf+uAELIgVBmQzg/q1YG10djyfA3TnrU8N8XzqCh/okZdszqBQTZf96idMfE5lnwTA==} - - '@types/estree@1.0.5': - resolution: {integrity: sha512-/kYRxGDLWzHOB7q+wtSUQlFrtcdUccpfy+X+9iMBpHK8QLLhx2wIPYuS5DYtR9Wa/YlZAbIovy7qVdB1Aq6Lyw==} - - '@types/json5@0.0.29': - resolution: {integrity: sha512-dRLjCWHYg4oaA77cxO64oO+7JwCwnIzkZPdrrC71jQmQtlhM556pwKo5bUzqvZndkVbeFLIIi+9TC40JNF5hNQ==} - - '@types/node@20.14.8': - resolution: {integrity: sha512-DO+2/jZinXfROG7j7WKFn/3C6nFwxy2lLpgLjEXJz+0XKphZlTLJ14mo8Vfg8X5BWN6XjyESXq+LcYdT7tR3bA==} - - '@types/normalize-package-data@2.4.4': - resolution: {integrity: sha512-37i+OaWTh9qeK4LSHPsyRC7NahnGotNuZvjLSgcPzblpHB3rrCJxAOgI5gCdKm7coonsaX1Of0ILiTcnZjbfxA==} - - '@vitest/expect@1.6.0': - resolution: {integrity: sha512-ixEvFVQjycy/oNgHjqsL6AZCDduC+tflRluaHIzKIsdbzkLn2U/iBnVeJwB6HsIjQBdfMR8Z0tRxKUsvFJEeWQ==} - - '@vitest/runner@1.6.0': - resolution: {integrity: sha512-P4xgwPjwesuBiHisAVz/LSSZtDjOTPYZVmNAnpHHSR6ONrf8eCJOFRvUwdHn30F5M1fxhqtl7QZQUk2dprIXAg==} - - '@vitest/snapshot@1.6.0': - resolution: {integrity: sha512-+Hx43f8Chus+DCmygqqfetcAZrDJwvTj0ymqjQq4CvmpKFSTVteEOBzCusu1x2tt4OJcvBflyHUE0DZSLgEMtQ==} - - '@vitest/spy@1.6.0': - resolution: {integrity: sha512-leUTap6B/cqi/bQkXUu6bQV5TZPx7pmMBKBQiI0rJA8c3pB56ZsaTbREnF7CJfmvAS4V2cXIBAh/3rVwrrCYgw==} - - '@vitest/utils@1.6.0': - resolution: {integrity: sha512-21cPiuGMoMZwiOHa2i4LXkMkMkCGzA+MVFV70jRwHo95dL4x/ts5GZhML1QWuy7yfp3WzK3lRvZi3JnXTYqrBw==} - - acorn-jsx@5.3.2: - resolution: {integrity: sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==} - peerDependencies: - acorn: ^6.0.0 || ^7.0.0 || ^8.0.0 - - acorn-walk@8.3.3: - resolution: {integrity: sha512-MxXdReSRhGO7VlFe1bRG/oI7/mdLV9B9JJT0N8vZOhF7gFRR5l3M8W9G8JxmKV+JC5mGqJ0QvqfSOLsCPa4nUw==} - engines: {node: '>=0.4.0'} - - acorn@8.12.0: - resolution: {integrity: sha512-RTvkC4w+KNXrM39/lWCUaG0IbRkWdCv7W/IOW9oU6SawyxulvkQy5HQPVTKxEjczcUvapcrw3cFx/60VN/NRNw==} - engines: {node: '>=0.4.0'} - hasBin: true - - ajv@6.12.6: - resolution: {integrity: sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==} - - ansi-regex@5.0.1: - resolution: {integrity: sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==} - engines: {node: '>=8'} - - ansi-styles@3.2.1: - resolution: {integrity: sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==} - engines: {node: '>=4'} - - ansi-styles@4.3.0: - resolution: {integrity: sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==} - engines: {node: '>=8'} - - ansi-styles@5.2.0: - resolution: {integrity: sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA==} - engines: {node: '>=10'} - - are-docs-informative@0.0.2: - resolution: {integrity: sha512-ixiS0nLNNG5jNQzgZJNoUpBKdo9yTYZMGJ+QgT2jmjR7G7+QHRCc4v6LQ3NgE7EBJq+o0ams3waJwkrlBom8Ig==} - engines: {node: '>=14'} - - argparse@2.0.1: - resolution: {integrity: sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==} - - array-buffer-byte-length@1.0.1: - resolution: {integrity: sha512-ahC5W1xgou+KTXix4sAO8Ki12Q+jf4i0+tmk3sC+zgcynshkHxzpXdImBehiUYKKKDwvfFiJl1tZt6ewscS1Mg==} - engines: {node: '>= 0.4'} - - array-includes@3.1.8: - resolution: {integrity: sha512-itaWrbYbqpGXkGhZPGUulwnhVf5Hpy1xiCFsGqyIGglbBxmG5vSjxQen3/WGOjPpNEv1RtBLKxbmVXm8HpJStQ==} - engines: {node: '>= 0.4'} - - array.prototype.flat@1.3.2: - resolution: {integrity: sha512-djYB+Zx2vLewY8RWlNCUdHjDXs2XOgm602S9E7P/UpHgfeHL00cRiIF+IN/G/aUJ7kGPb6yO/ErDI5V2s8iycA==} - engines: {node: '>= 0.4'} - - array.prototype.flatmap@1.3.2: - resolution: {integrity: sha512-Ewyx0c9PmpcsByhSW4r+9zDU7sGjFc86qf/kKtuSCRdhfbk0SNLLkaT5qvcHnRGgc5NP/ly/y+qkXkqONX54CQ==} - engines: {node: '>= 0.4'} - - arraybuffer.prototype.slice@1.0.3: - resolution: {integrity: sha512-bMxMKAjg13EBSVscxTaYA4mRc5t1UAXa2kXiGTNfZ079HIWXEkKmkgFrh/nJqamaLSrXO5H4WFFkPEaLJWbs3A==} - engines: {node: '>= 0.4'} - - assertion-error@1.1.0: - resolution: {integrity: sha512-jgsaNduz+ndvGyFt3uSuWqvy4lCnIJiovtouQN5JZHOKCS2QuhEdbcQHFhVksz2N2U9hXJo8odG7ETyWlEeuDw==} - - available-typed-arrays@1.0.7: - resolution: {integrity: sha512-wvUjBtSGN7+7SjNpq/9M2Tg350UZD3q62IFZLbRAR1bSMlCo1ZaeW+BJ+D090e4hIIZLBcTDWe4Mh4jvUDajzQ==} - engines: {node: '>= 0.4'} - - balanced-match@1.0.2: - resolution: {integrity: sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==} - - brace-expansion@1.1.11: - resolution: {integrity: sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==} - - browserslist@4.23.1: - resolution: {integrity: sha512-TUfofFo/KsK/bWZ9TWQ5O26tsWW4Uhmt8IYklbnUa70udB6P2wA7w7o4PY4muaEPBQaAX+CEnmmIA41NVHtPVw==} - engines: {node: ^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7} - hasBin: true - - builtin-modules@3.3.0: - resolution: {integrity: sha512-zhaCDicdLuWN5UbN5IMnFqNMhNfo919sH85y2/ea+5Yg9TsTkeZxpL+JLbp6cgYFS4sRLp3YV4S6yDuqVWHYOw==} - engines: {node: '>=6'} - - cac@6.7.14: - resolution: {integrity: sha512-b6Ilus+c3RrdDk+JhLKUAQfzzgLEPy6wcXqS7f/xe1EETvsDP6GORG7SFuOs6cID5YkqchW/LXZbX5bc8j7ZcQ==} - engines: {node: '>=8'} - - call-bind@1.0.7: - resolution: {integrity: sha512-GHTSNSYICQ7scH7sZ+M2rFopRoLh8t2bLSW6BbgrtLsahOIB5iyAVJf9GjWK3cYTDaMj4XdBpM1cA6pIS0Kv2w==} - engines: {node: '>= 0.4'} - - callsites@3.1.0: - resolution: {integrity: sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==} - engines: {node: '>=6'} - - caniuse-lite@1.0.30001636: - resolution: {integrity: sha512-bMg2vmr8XBsbL6Lr0UHXy/21m84FTxDLWn2FSqMd5PrlbMxwJlQnC2YWYxVgp66PZE+BBNF2jYQUBKCo1FDeZg==} - - chai@4.4.1: - resolution: {integrity: sha512-13sOfMv2+DWduEU+/xbun3LScLoqN17nBeTLUsmDfKdoiC1fr0n9PU4guu4AhRcOVFk/sW8LyZWHuhWtQZiF+g==} - engines: {node: '>=4'} - - chalk@2.4.2: - resolution: {integrity: sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==} - engines: {node: '>=4'} - - chalk@4.1.2: - resolution: {integrity: sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==} - engines: {node: '>=10'} - - check-error@1.0.3: - resolution: {integrity: sha512-iKEoDYaRmd1mxM90a2OEfWhjsjPpYPuQ+lMYsoxB126+t8fw7ySEO48nmDg5COTjxDI65/Y2OWpeEHk3ZOe8zg==} - - ci-info@3.9.0: - resolution: {integrity: sha512-NIxF55hv4nSqQswkAeiOi1r83xy8JldOFDTWiug55KBu9Jnblncd2U6ViHmYgHf01TPZS77NJBhBMKdWj9HQMQ==} - engines: {node: '>=8'} - - clean-regexp@1.0.0: - resolution: {integrity: sha512-GfisEZEJvzKrmGWkvfhgzcz/BllN1USeqD2V6tg14OAOgaCD2Z/PUEuxnAZ/nPvmaHRG7a8y77p1T/IRQ4D1Hw==} - engines: {node: '>=4'} - - color-convert@1.9.3: - resolution: {integrity: sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==} - - color-convert@2.0.1: - resolution: {integrity: sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==} - engines: {node: '>=7.0.0'} - - color-name@1.1.3: - resolution: {integrity: sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==} - - color-name@1.1.4: - resolution: {integrity: sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==} - - comment-parser@1.4.0: - resolution: {integrity: sha512-QLyTNiZ2KDOibvFPlZ6ZngVsZ/0gYnE6uTXi5aoDg8ed3AkJAz4sEje3Y8a29hQ1s6A99MZXe47fLAXQ1rTqaw==} - engines: {node: '>= 12.0.0'} - - concat-map@0.0.1: - resolution: {integrity: sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==} - - confbox@0.1.7: - resolution: {integrity: sha512-uJcB/FKZtBMCJpK8MQji6bJHgu1tixKPxRLeGkNzBoOZzpnZUJm0jm2/sBDWcuBx1dYgxV4JU+g5hmNxCyAmdA==} - - confusing-browser-globals@1.0.11: - resolution: {integrity: sha512-JsPKdmh8ZkmnHxDk55FZ1TqVLvEQTvoByJZRN9jzI0UjxK/QgAmsphz7PGtqgPieQZ/CQcHWXCR7ATDNhGe+YA==} - - convert-source-map@2.0.0: - resolution: {integrity: sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg==} - - cross-spawn@7.0.3: - resolution: {integrity: sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==} - engines: {node: '>= 8'} - - data-view-buffer@1.0.1: - resolution: {integrity: sha512-0lht7OugA5x3iJLOWFhWK/5ehONdprk0ISXqVFn/NFrDu+cuc8iADFrGQz5BnRK7LLU3JmkbXSxaqX+/mXYtUA==} - engines: {node: '>= 0.4'} - - data-view-byte-length@1.0.1: - resolution: {integrity: sha512-4J7wRJD3ABAzr8wP+OcIcqq2dlUKp4DVflx++hs5h5ZKydWMI6/D/fAot+yh6g2tHh8fLFTvNOaVN357NvSrOQ==} - engines: {node: '>= 0.4'} - - data-view-byte-offset@1.0.0: - resolution: {integrity: sha512-t/Ygsytq+R995EJ5PZlD4Cu56sWa8InXySaViRzw9apusqsOO2bQP+SbYzAhR0pFKoB+43lYy8rWban9JSuXnA==} - engines: {node: '>= 0.4'} - - debug@3.2.7: - resolution: {integrity: sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==} - peerDependencies: - supports-color: '*' - peerDependenciesMeta: - supports-color: - optional: true - - debug@4.3.4: - resolution: {integrity: sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==} - engines: {node: '>=6.0'} - peerDependencies: - supports-color: '*' - peerDependenciesMeta: - supports-color: - optional: true - - deep-eql@4.1.4: - resolution: {integrity: sha512-SUwdGfqdKOwxCPeVYjwSyRpJ7Z+fhpwIAtmCUdZIWZ/YP5R9WAsyuSgpLVDi9bjWoN2LXHNss/dk3urXtdQxGg==} - engines: {node: '>=6'} - - deep-is@0.1.4: - resolution: {integrity: sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==} - - define-data-property@1.1.4: - resolution: {integrity: sha512-rBMvIzlpA8v6E+SJZoo++HAYqsLrkg7MSfIinMPFhmkorw7X+dOXVJQs+QT69zGkzMyfDnIMN2Wid1+NbL3T+A==} - engines: {node: '>= 0.4'} - - define-properties@1.2.1: - resolution: {integrity: sha512-8QmQKqEASLd5nx0U1B1okLElbUuuttJ/AnYmRXbbbGDWh6uS208EjD4Xqq/I9wK7u0v6O08XhTWnt5XtEbR6Dg==} - engines: {node: '>= 0.4'} - - diff-sequences@29.6.3: - resolution: {integrity: sha512-EjePK1srD3P08o2j4f0ExnylqRs5B9tJjcp9t1krH2qRi8CCdsYfwe9JgSLurFBWwq4uOlipzfk5fHNvwFKr8Q==} - engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} - - doctrine@2.1.0: - resolution: {integrity: sha512-35mSku4ZXK0vfCuHEDAwt55dg2jNajHZ1odvF+8SSr82EsZY4QmXfuWso8oEd8zRhVObSN18aM0CjSdoBX7zIw==} - engines: {node: '>=0.10.0'} - - doctrine@3.0.0: - resolution: {integrity: sha512-yS+Q5i3hBf7GBkd4KG8a7eBNNWNGLTaEwwYWUijIYM7zrlYDM0BFXHjjPWlWZ1Rg7UaddZeIDmi9jF3HmqiQ2w==} - engines: {node: '>=6.0.0'} - - electron-to-chromium@1.4.811: - resolution: {integrity: sha512-CDyzcJ5XW78SHzsIOdn27z8J4ist8eaFLhdto2hSMSJQgsiwvbv2fbizcKUICryw1Wii1TI/FEkvzvJsR3awrA==} - - error-ex@1.3.2: - resolution: {integrity: sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g==} - - es-abstract@1.23.3: - resolution: {integrity: sha512-e+HfNH61Bj1X9/jLc5v1owaLYuHdeHHSQlkhCBiTK8rBvKaULl/beGMxwrMXjpYrv4pz22BlY570vVePA2ho4A==} - engines: {node: '>= 0.4'} - - es-define-property@1.0.0: - resolution: {integrity: sha512-jxayLKShrEqqzJ0eumQbVhTYQM27CfT1T35+gCgDFoL82JLsXqTJ76zv6A0YLOgEnLUMvLzsDsGIrl8NFpT2gQ==} - engines: {node: '>= 0.4'} - - es-errors@1.3.0: - resolution: {integrity: sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==} - engines: {node: '>= 0.4'} - - es-object-atoms@1.0.0: - resolution: {integrity: sha512-MZ4iQ6JwHOBQjahnjwaC1ZtIBH+2ohjamzAO3oaHcXYup7qxjF2fixyH+Q71voWHeOkI2q/TnJao/KfXYIZWbw==} - engines: {node: '>= 0.4'} - - es-set-tostringtag@2.0.3: - resolution: {integrity: sha512-3T8uNMC3OQTHkFUsFq8r/BwAXLHvU/9O9mE0fBc/MY5iq/8H7ncvO947LmYA6ldWw9Uh8Yhf25zu6n7nML5QWQ==} - engines: {node: '>= 0.4'} - - es-shim-unscopables@1.0.2: - resolution: {integrity: sha512-J3yBRXCzDu4ULnQwxyToo/OjdMx6akgVC7K6few0a7F/0wLtmKKN7I73AH5T2836UuXRqN7Qg+IIUw/+YJksRw==} - - es-to-primitive@1.2.1: - resolution: {integrity: sha512-QCOllgZJtaUo9miYBcLChTUaHNjJF3PYs1VidD7AwiEj1kYxKeQTctLAezAOH5ZKRH0g2IgPn6KwB4IT8iRpvA==} - engines: {node: '>= 0.4'} - - esbuild@0.21.5: - resolution: {integrity: sha512-mg3OPMV4hXywwpoDxu3Qda5xCKQi+vCTZq8S9J/EpkhB2HzKXq4SNFZE3+NK93JYxc8VMSep+lOUSC/RVKaBqw==} - engines: {node: '>=12'} - hasBin: true - - escalade@3.1.2: - resolution: {integrity: sha512-ErCHMCae19vR8vQGe50xIsVomy19rg6gFu3+r3jkEO46suLMWBksvVyoGgQV+jOfl84ZSOSlmv6Gxa89PmTGmA==} - engines: {node: '>=6'} - - escape-string-regexp@1.0.5: - resolution: {integrity: sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==} - engines: {node: '>=0.8.0'} - - escape-string-regexp@4.0.0: - resolution: {integrity: sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==} - engines: {node: '>=10'} - - eslint-config-xo@0.43.1: - resolution: {integrity: sha512-azv1L2PysRA0NkZOgbndUpN+581L7wPqkgJOgxxw3hxwXAbJgD6Hqb/SjHRiACifXt/AvxCzE/jIKFAlI7XjvQ==} - engines: {node: '>=12'} - peerDependencies: - eslint: '>=8.27.0' - - eslint-import-resolver-node@0.3.9: - resolution: {integrity: sha512-WFj2isz22JahUv+B788TlO3N6zL3nNJGU8CcZbPZvVEkBPaJdCV4vy5wyghty5ROFbCRnm132v8BScu5/1BQ8g==} - - eslint-module-utils@2.8.1: - resolution: {integrity: sha512-rXDXR3h7cs7dy9RNpUlQf80nX31XWJEyGq1tRMo+6GsO5VmTe4UTwtmonAD4ZkAsrfMVDA2wlGJ3790Ys+D49Q==} - engines: {node: '>=4'} - peerDependencies: - '@typescript-eslint/parser': '*' - eslint: '*' - eslint-import-resolver-node: '*' - eslint-import-resolver-typescript: '*' - eslint-import-resolver-webpack: '*' - peerDependenciesMeta: - '@typescript-eslint/parser': - optional: true - eslint: - optional: true - eslint-import-resolver-node: - optional: true - eslint-import-resolver-typescript: - optional: true - eslint-import-resolver-webpack: - optional: true - - eslint-plugin-es@3.0.1: - resolution: {integrity: sha512-GUmAsJaN4Fc7Gbtl8uOBlayo2DqhwWvEzykMHSCZHU3XdJ+NSzzZcVhXh3VxX5icqQ+oQdIEawXX8xkR3mIFmQ==} - engines: {node: '>=8.10.0'} - peerDependencies: - eslint: '>=4.19.1' - - eslint-plugin-import@2.27.5: - resolution: {integrity: sha512-LmEt3GVofgiGuiE+ORpnvP+kAm3h6MLZJ4Q5HCyHADofsb4VzXFsRiWj3c0OFiV+3DWFh0qg3v9gcPlfc3zRow==} - engines: {node: '>=4'} - peerDependencies: - '@typescript-eslint/parser': '*' - eslint: ^2 || ^3 || ^4 || ^5 || ^6 || ^7.2.0 || ^8 - peerDependenciesMeta: - '@typescript-eslint/parser': - optional: true - - eslint-plugin-jsdoc@46.5.0: - resolution: {integrity: sha512-aulXdA4I1dyWpzyS1Nh/GNoS6PavzeucxEapnMR4JUERowWvaEk2Y4A5irpHAcdXtBBHLVe8WIhdXNjoAlGQgA==} - engines: {node: '>=16'} - peerDependencies: - eslint: ^7.0.0 || ^8.0.0 - - eslint-plugin-node@11.1.0: - resolution: {integrity: sha512-oUwtPJ1W0SKD0Tr+wqu92c5xuCeQqB3hSCHasn/ZgjFdA9iDGNkNf2Zi9ztY7X+hNuMib23LNGRm6+uN+KLE3g==} - engines: {node: '>=8.10.0'} - peerDependencies: - eslint: '>=5.16.0' - - eslint-plugin-promise@6.1.1: - resolution: {integrity: sha512-tjqWDwVZQo7UIPMeDReOpUgHCmCiH+ePnVT+5zVapL0uuHnegBUs2smM13CzOs2Xb5+MHMRFTs9v24yjba4Oig==} - engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} - peerDependencies: - eslint: ^7.0.0 || ^8.0.0 - - eslint-plugin-unicorn@47.0.0: - resolution: {integrity: sha512-ivB3bKk7fDIeWOUmmMm9o3Ax9zbMz1Bsza/R2qm46ufw4T6VBFBaJIR1uN3pCKSmSXm8/9Nri8V+iUut1NhQGA==} - engines: {node: '>=16'} - peerDependencies: - eslint: '>=8.38.0' - - eslint-scope@5.1.1: - resolution: {integrity: sha512-2NxwbF/hZ0KpepYN0cNbo+FN6XoK7GaHlQhgx/hIZl6Va0bF45RQOOwhLIy8lQDbuCiadSLCBnH2CFYquit5bw==} - engines: {node: '>=8.0.0'} - - eslint-scope@7.2.2: - resolution: {integrity: sha512-dOt21O7lTMhDM+X9mB4GX+DZrZtCUJPL/wlcTqxyrx5IvO0IYtILdtrQGQp+8n5S0gwSVmOf9NQrjMOgfQZlIg==} - engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} - - eslint-utils@2.1.0: - resolution: {integrity: sha512-w94dQYoauyvlDc43XnGB8lU3Zt713vNChgt4EWwhXAP2XkBvndfxF0AgIqKOOasjPIPzj9JqgwkwbCYD0/V3Zg==} - engines: {node: '>=6'} - - eslint-visitor-keys@1.3.0: - resolution: {integrity: sha512-6J72N8UNa462wa/KFODt/PJ3IU60SDpC3QXC1Hjc1BXXpfL2C9R5+AU7jhe0F6GREqVMh4Juu+NY7xn+6dipUQ==} - engines: {node: '>=4'} - - eslint-visitor-keys@2.1.0: - resolution: {integrity: sha512-0rSmRBzXgDzIsD6mGdJgevzgezI534Cer5L/vyMX0kHzT/jiB43jRhd9YUlMGYLQy2zprNmoT8qasCGtY+QaKw==} - engines: {node: '>=10'} - - eslint-visitor-keys@3.4.3: - resolution: {integrity: sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag==} - engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} - - eslint@8.41.0: - resolution: {integrity: sha512-WQDQpzGBOP5IrXPo4Hc0814r4/v2rrIsB0rhT7jtunIalgg6gYXWhRMOejVO8yH21T/FGaxjmFjBMNqcIlmH1Q==} - engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} - hasBin: true - - espree@9.6.1: - resolution: {integrity: sha512-oruZaFkjorTpF32kDSI5/75ViwGeZginGGy2NoOSg3Q9bnwlnmDm4HLnkl0RE3n+njDXR037aY1+x58Z/zFdwQ==} - engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} - - esquery@1.5.0: - resolution: {integrity: sha512-YQLXUplAwJgCydQ78IMJywZCceoqk1oH01OERdSAJc/7U2AylwjhSCLDEtqwg811idIS/9fIU5GjG73IgjKMVg==} - engines: {node: '>=0.10'} - - esrecurse@4.3.0: - resolution: {integrity: sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==} - engines: {node: '>=4.0'} - - estraverse@4.3.0: - resolution: {integrity: sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw==} - engines: {node: '>=4.0'} - - estraverse@5.3.0: - resolution: {integrity: sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==} - engines: {node: '>=4.0'} - - estree-walker@3.0.3: - resolution: {integrity: sha512-7RUKfXgSMMkzt6ZuXmqapOurLGPPfgj6l9uRZ7lRGolvk0y2yocc35LdcxKC5PQZdn2DMqioAQ2NoWcrTKmm6g==} - - esutils@2.0.3: - resolution: {integrity: sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==} - engines: {node: '>=0.10.0'} - - execa@8.0.1: - resolution: {integrity: sha512-VyhnebXciFV2DESc+p6B+y0LjSm0krU4OgJN44qFAhBY0TJ+1V61tYD2+wHusZ6F9n5K+vl8k0sTy7PEfV4qpg==} - engines: {node: '>=16.17'} - - fast-deep-equal@3.1.3: - resolution: {integrity: sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==} - - fast-json-stable-stringify@2.1.0: - resolution: {integrity: sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==} - - fast-levenshtein@2.0.6: - resolution: {integrity: sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==} - - fastq@1.17.1: - resolution: {integrity: sha512-sRVD3lWVIXWg6By68ZN7vho9a1pQcN/WBFaAAsDDFzlJjvoGx0P8z7V1t72grFJfJhu3YPZBuu25f7Kaw2jN1w==} - - file-entry-cache@6.0.1: - resolution: {integrity: sha512-7Gps/XWymbLk2QLYK4NzpMOrYjMhdIxXuIvy2QBsLE6ljuodKvdkWs/cpyJJ3CVIVpH0Oi1Hvg1ovbMzLdFBBg==} - engines: {node: ^10.12.0 || >=12.0.0} - - find-up@4.1.0: - resolution: {integrity: sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==} - engines: {node: '>=8'} - - find-up@5.0.0: - resolution: {integrity: sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==} - engines: {node: '>=10'} - - flat-cache@3.2.0: - resolution: {integrity: sha512-CYcENa+FtcUKLmhhqyctpclsq7QF38pKjZHsGNiSQF5r4FtoKDWabFDl3hzaEQMvT1LHEysw5twgLvpYYb4vbw==} - engines: {node: ^10.12.0 || >=12.0.0} - - flatted@3.3.1: - resolution: {integrity: sha512-X8cqMLLie7KsNUDSdzeN8FYK9rEt4Dt67OsG/DNGnYTSDBG4uFAJFBnUeiV+zCVAvwFy56IjM9sH51jVaEhNxw==} - - for-each@0.3.3: - resolution: {integrity: sha512-jqYfLp7mo9vIyQf8ykW2v7A+2N4QjeCeI5+Dz9XraiO1ign81wjiH7Fb9vSOWvQfNtmSa4H2RoQTrrXivdUZmw==} - - fs.realpath@1.0.0: - resolution: {integrity: sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==} - - fsevents@2.3.3: - resolution: {integrity: sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==} - engines: {node: ^8.16.0 || ^10.6.0 || >=11.0.0} - os: [darwin] - - function-bind@1.1.2: - resolution: {integrity: sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==} - - function.prototype.name@1.1.6: - resolution: {integrity: sha512-Z5kx79swU5P27WEayXM1tBi5Ze/lbIyiNgU3qyXUOf9b2rgXYyF9Dy9Cx+IQv/Lc8WCG6L82zwUPpSS9hGehIg==} - engines: {node: '>= 0.4'} - - functions-have-names@1.2.3: - resolution: {integrity: sha512-xckBUXyTIqT97tq2x2AMb+g163b5JFysYk0x4qxNFwbfQkmNZoiRHb6sPzI9/QV33WeuvVYBUIiD4NzNIyqaRQ==} - - gensync@1.0.0-beta.2: - resolution: {integrity: sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg==} - engines: {node: '>=6.9.0'} - - get-func-name@2.0.2: - resolution: {integrity: sha512-8vXOvuE167CtIc3OyItco7N/dpRtBbYOsPsXCz7X/PMnlGjYjSGuZJgM1Y7mmew7BKf9BqvLX2tnOVy1BBUsxQ==} - - get-intrinsic@1.2.4: - resolution: {integrity: sha512-5uYhsJH8VJBTv7oslg4BznJYhDoRI6waYCxMmCdnTrcCrHA/fCFKoTFz2JKKE0HdDFUF7/oQuhzumXJK7paBRQ==} - engines: {node: '>= 0.4'} - - get-stream@8.0.1: - resolution: {integrity: sha512-VaUJspBffn/LMCJVoMvSAdmscJyS1auj5Zulnn5UoYcY531UWmdwhRWkcGKnGU93m5HSXP9LP2usOryrBtQowA==} - engines: {node: '>=16'} - - get-symbol-description@1.0.2: - resolution: {integrity: sha512-g0QYk1dZBxGwk+Ngc+ltRH2IBp2f7zBkBMBJZCDerh6EhlhSR6+9irMCuT/09zD6qkarHUSn529sK/yL4S27mg==} - engines: {node: '>= 0.4'} - - glob-parent@6.0.2: - resolution: {integrity: sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==} - engines: {node: '>=10.13.0'} - - glob@7.2.3: - resolution: {integrity: sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==} - deprecated: Glob versions prior to v9 are no longer supported - - globals@11.12.0: - resolution: {integrity: sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA==} - engines: {node: '>=4'} - - globals@13.24.0: - resolution: {integrity: sha512-AhO5QUcj8llrbG09iWhPU2B204J1xnPeL8kQmVorSsy+Sjj1sk8gIyh6cUocGmH4L0UuhAJy+hJMRA4mgA4mFQ==} - engines: {node: '>=8'} - - globalthis@1.0.4: - resolution: {integrity: sha512-DpLKbNU4WylpxJykQujfCcwYWiV/Jhm50Goo0wrVILAv5jOr9d+H+UR3PhSCD2rCCEIg0uc+G+muBTwD54JhDQ==} - engines: {node: '>= 0.4'} - - gopd@1.0.1: - resolution: {integrity: sha512-d65bNlIadxvpb/A2abVdlqKqV563juRnZ1Wtk6s1sIR8uNsXR70xqIzVqxVf1eTqDunwT2MkczEeaezCKTZhwA==} - - graphemer@1.4.0: - resolution: {integrity: sha512-EtKwoO6kxCL9WO5xipiHTZlSzBm7WLT627TqC/uVRd0HKmq8NXyebnNYxDoBi7wt8eTWrUrKXCOVaFq9x1kgag==} - - has-bigints@1.0.2: - resolution: {integrity: sha512-tSvCKtBr9lkF0Ex0aQiP9N+OpV4zi2r/Nee5VkRDbaqv35RLYMzbwQfFSZZH0kR+Rd6302UJZ2p/bJCEoR3VoQ==} - - has-flag@3.0.0: - resolution: {integrity: sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==} - engines: {node: '>=4'} - - has-flag@4.0.0: - resolution: {integrity: sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==} - engines: {node: '>=8'} - - has-property-descriptors@1.0.2: - resolution: {integrity: sha512-55JNKuIW+vq4Ke1BjOTjM2YctQIvCT7GFzHwmfZPGo5wnrgkid0YQtnAleFSqumZm4az3n2BS+erby5ipJdgrg==} - - has-proto@1.0.3: - resolution: {integrity: sha512-SJ1amZAJUiZS+PhsVLf5tGydlaVB8EdFpaSO4gmiUKUOxk8qzn5AIy4ZeJUmh22znIdk/uMAUT2pl3FxzVUH+Q==} - engines: {node: '>= 0.4'} - - has-symbols@1.0.3: - resolution: {integrity: sha512-l3LCuF6MgDNwTDKkdYGEihYjt5pRPbEg46rtlmnSPlUbgmB8LOIrKJbYYFBSbnPaJexMKtiPO8hmeRjRz2Td+A==} - engines: {node: '>= 0.4'} - - has-tostringtag@1.0.2: - resolution: {integrity: sha512-NqADB8VjPFLM2V0VvHUewwwsw0ZWBaIdgo+ieHtK3hasLz4qeCRjYcqfB6AQrBggRKppKF8L52/VqdVsO47Dlw==} - engines: {node: '>= 0.4'} - - has@1.0.4: - resolution: {integrity: sha512-qdSAmqLF6209RFj4VVItywPMbm3vWylknmB3nvNiUIs72xAimcM8nVYxYr7ncvZq5qzk9MKIZR8ijqD/1QuYjQ==} - engines: {node: '>= 0.4.0'} - - hasown@2.0.2: - resolution: {integrity: sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==} - engines: {node: '>= 0.4'} - - hosted-git-info@2.8.9: - resolution: {integrity: sha512-mxIDAb9Lsm6DoOJ7xH+5+X4y1LU/4Hi50L9C5sIswK3JzULS4bwk1FvjdBgvYR4bzT4tuUQiC15FE2f5HbLvYw==} - - human-signals@5.0.0: - resolution: {integrity: sha512-AXcZb6vzzrFAUE61HnN4mpLqd/cSIwNQjtNWR0euPm6y0iqx3G4gOXaIDdtdDwZmhwe82LA6+zinmW4UBWVePQ==} - engines: {node: '>=16.17.0'} - - ignore@5.3.1: - resolution: {integrity: sha512-5Fytz/IraMjqpwfd34ke28PTVMjZjJG2MPn5t7OE4eUCUNf8BAa7b5WUS9/Qvr6mwOQS7Mk6vdsMno5he+T8Xw==} - engines: {node: '>= 4'} - - import-fresh@3.3.0: - resolution: {integrity: sha512-veYYhQa+D1QBKznvhUHxb8faxlrwUnxseDAbAp457E0wLNio2bOSKnjYDhMj+YiAq61xrMGhQk9iXVk5FzgQMw==} - engines: {node: '>=6'} - - imurmurhash@0.1.4: - resolution: {integrity: sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==} - engines: {node: '>=0.8.19'} - - indent-string@4.0.0: - resolution: {integrity: sha512-EdDDZu4A2OyIK7Lr/2zG+w5jmbuk1DVBnEwREQvBzspBJkCEbRa8GxU1lghYcaGJCnRWibjDXlq779X1/y5xwg==} - engines: {node: '>=8'} - - inflight@1.0.6: - resolution: {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. - - inherits@2.0.4: - resolution: {integrity: sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==} - - internal-slot@1.0.7: - resolution: {integrity: sha512-NGnrKwXzSms2qUUih/ILZ5JBqNTSa1+ZmP6flaIp6KmSElgE9qdndzS3cqjrDovwFdmwsGsLdeFgB6suw+1e9g==} - engines: {node: '>= 0.4'} - - is-array-buffer@3.0.4: - resolution: {integrity: sha512-wcjaerHw0ydZwfhiKbXJWLDY8A7yV7KhjQOpb83hGgGfId/aQa4TOvwyzn2PuswW2gPCYEL/nEAiSVpdOj1lXw==} - engines: {node: '>= 0.4'} - - is-arrayish@0.2.1: - resolution: {integrity: sha512-zz06S8t0ozoDXMG+ube26zeCTNXcKIPJZJi8hBrF4idCLms4CG9QtK7qBl1boi5ODzFpjswb5JPmHCbMpjaYzg==} - - is-bigint@1.0.4: - resolution: {integrity: sha512-zB9CruMamjym81i2JZ3UMn54PKGsQzsJeo6xvN3HJJ4CAsQNB6iRutp2To77OfCNuoxspsIhzaPoO1zyCEhFOg==} - - is-boolean-object@1.1.2: - resolution: {integrity: sha512-gDYaKHJmnj4aWxyj6YHyXVpdQawtVLHU5cb+eztPGczf6cjuTdwve5ZIEfgXqH4e57An1D1AKf8CZ3kYrQRqYA==} - engines: {node: '>= 0.4'} - - is-builtin-module@3.2.1: - resolution: {integrity: sha512-BSLE3HnV2syZ0FK0iMA/yUGplUeMmNz4AW5fnTunbCIqZi4vG3WjJT9FHMy5D69xmAYBHXQhJdALdpwVxV501A==} - engines: {node: '>=6'} - - is-callable@1.2.7: - resolution: {integrity: sha512-1BC0BVFhS/p0qtw6enp8e+8OD0UrK0oFLztSjNzhcKA3WDuJxxAPXzPuPtKkjEY9UUoEWlX/8fgKeu2S8i9JTA==} - engines: {node: '>= 0.4'} - - is-core-module@2.14.0: - resolution: {integrity: sha512-a5dFJih5ZLYlRtDc0dZWP7RiKr6xIKzmn/oAYCDvdLThadVgyJwlaoQPmRtMSpz+rk0OGAgIu+TcM9HUF0fk1A==} - engines: {node: '>= 0.4'} - - is-data-view@1.0.1: - resolution: {integrity: sha512-AHkaJrsUVW6wq6JS8y3JnM/GJF/9cf+k20+iDzlSaJrinEo5+7vRiteOSwBhHRiAyQATN1AmY4hwzxJKPmYf+w==} - engines: {node: '>= 0.4'} - - is-date-object@1.0.5: - resolution: {integrity: sha512-9YQaSxsAiSwcvS33MBk3wTCVnWK+HhF8VZR2jRxehM16QcVOdHqPn4VPHmRK4lSr38n9JriurInLcP90xsYNfQ==} - engines: {node: '>= 0.4'} - - is-extglob@2.1.1: - resolution: {integrity: sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==} - engines: {node: '>=0.10.0'} - - is-glob@4.0.3: - resolution: {integrity: sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==} - engines: {node: '>=0.10.0'} - - is-negative-zero@2.0.3: - resolution: {integrity: sha512-5KoIu2Ngpyek75jXodFvnafB6DJgr3u8uuK0LEZJjrU19DrMD3EVERaR8sjz8CCGgpZvxPl9SuE1GMVPFHx1mw==} - engines: {node: '>= 0.4'} - - is-number-object@1.0.7: - resolution: {integrity: sha512-k1U0IRzLMo7ZlYIfzRu23Oh6MiIFasgpb9X76eqfFZAqwH44UI4KTBvBYIZ1dSL9ZzChTB9ShHfLkR4pdW5krQ==} - engines: {node: '>= 0.4'} - - is-path-inside@3.0.3: - resolution: {integrity: sha512-Fd4gABb+ycGAmKou8eMftCupSir5lRxqf4aD/vd0cD2qc4HL07OjCeuHMr8Ro4CoMaeCKDB0/ECBOVWjTwUvPQ==} - engines: {node: '>=8'} - - is-regex@1.1.4: - resolution: {integrity: sha512-kvRdxDsxZjhzUX07ZnLydzS1TU/TJlTUHHY4YLL87e37oUA49DfkLqgy+VjFocowy29cKvcSiu+kIv728jTTVg==} - engines: {node: '>= 0.4'} - - is-shared-array-buffer@1.0.3: - resolution: {integrity: sha512-nA2hv5XIhLR3uVzDDfCIknerhx8XUKnstuOERPNNIinXG7v9u+ohXF67vxm4TPTEPU6lm61ZkwP3c9PCB97rhg==} - engines: {node: '>= 0.4'} - - is-stream@3.0.0: - resolution: {integrity: sha512-LnQR4bZ9IADDRSkvpqMGvt/tEJWclzklNgSw48V5EAaAeDd6qGvN8ei6k5p0tvxSR171VmGyHuTiAOfxAbr8kA==} - engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} - - is-string@1.0.7: - resolution: {integrity: sha512-tE2UXzivje6ofPW7l23cjDOMa09gb7xlAqG6jG5ej6uPV32TlWP3NKPigtaGeHNu9fohccRYvIiZMfOOnOYUtg==} - engines: {node: '>= 0.4'} - - is-symbol@1.0.4: - resolution: {integrity: sha512-C/CPBqKWnvdcxqIARxyOh4v1UUEOCHpgDa0WYgpKDFMszcrPcffg5uhwSgPCLD2WWxmq6isisz87tzT01tuGhg==} - engines: {node: '>= 0.4'} - - is-typed-array@1.1.13: - resolution: {integrity: sha512-uZ25/bUAlUY5fR4OKT4rZQEBrzQWYV9ZJYGGsUmEJ6thodVJ1HX64ePQ6Z0qPWP+m+Uq6e9UugrE38jeYsDSMw==} - engines: {node: '>= 0.4'} - - is-weakref@1.0.2: - resolution: {integrity: sha512-qctsuLZmIQ0+vSSMfoVvyFe2+GSEvnmZ2ezTup1SBse9+twCCeial6EEi3Nc2KFcf6+qz2FBPnjXsk8xhKSaPQ==} - - isarray@2.0.5: - resolution: {integrity: sha512-xHjhDr3cNBK0BzdUJSPXZntQUx/mwMS5Rw4A7lPJ90XGAO6ISP/ePDNuo0vhqOZU+UD5JoodwCAAoZQd3FeAKw==} - - isexe@2.0.0: - resolution: {integrity: sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==} - - js-tokens@4.0.0: - resolution: {integrity: sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==} - - js-tokens@9.0.0: - resolution: {integrity: sha512-WriZw1luRMlmV3LGJaR6QOJjWwgLUTf89OwT2lUOyjX2dJGBwgmIkbcz+7WFZjrZM635JOIR517++e/67CP9dQ==} - - js-yaml@4.1.0: - resolution: {integrity: sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==} - hasBin: true - - jsdoc-type-pratt-parser@4.0.0: - resolution: {integrity: sha512-YtOli5Cmzy3q4dP26GraSOeAhqecewG04hoO8DY56CH4KJ9Fvv5qKWUCCo3HZob7esJQHCv6/+bnTy72xZZaVQ==} - engines: {node: '>=12.0.0'} - - jsesc@0.5.0: - resolution: {integrity: sha512-uZz5UnB7u4T9LvwmFqXii7pZSouaRPorGs5who1Ip7VO0wxanFvBL7GkM6dTHlgX+jhBApRetaWpnDabOeTcnA==} - hasBin: true - - jsesc@2.5.2: - resolution: {integrity: sha512-OYu7XEzjkCQ3C5Ps3QIZsQfNpqoJyZZA99wd9aWd05NCtC5pWOkShK2mkL6HXQR6/Cy2lbNdPlZBpuQHXE63gA==} - engines: {node: '>=4'} - hasBin: true - - jsesc@3.0.2: - resolution: {integrity: sha512-xKqzzWXDttJuOcawBt4KnKHHIf5oQ/Cxax+0PWFG+DFDgHNAdi+TXECADI+RYiFUMmx8792xsMbbgXj4CwnP4g==} - engines: {node: '>=6'} - hasBin: true - - json-buffer@3.0.1: - resolution: {integrity: sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ==} - - json-parse-even-better-errors@2.3.1: - resolution: {integrity: sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w==} - - json-schema-traverse@0.4.1: - resolution: {integrity: sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==} - - json-stable-stringify-without-jsonify@1.0.1: - resolution: {integrity: sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw==} - - json5@1.0.2: - resolution: {integrity: sha512-g1MWMLBiz8FKi1e4w0UyVL3w+iJceWAFBAaBnnGKOpNa5f8TLktkbre1+s6oICydWAm+HRUGTmI+//xv2hvXYA==} - hasBin: true - - json5@2.2.3: - resolution: {integrity: sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg==} - engines: {node: '>=6'} - hasBin: true - - keyv@4.5.4: - resolution: {integrity: sha512-oxVHkHR/EJf2CNXnWxRLW6mg7JyCCUcG0DtEGmL2ctUo1PNTin1PUil+r/+4r5MpVgC/fn1kjsx7mjSujKqIpw==} - - levn@0.4.1: - resolution: {integrity: sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==} - engines: {node: '>= 0.8.0'} - - lines-and-columns@1.2.4: - resolution: {integrity: sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg==} - - local-pkg@0.5.0: - resolution: {integrity: sha512-ok6z3qlYyCDS4ZEU27HaU6x/xZa9Whf8jD4ptH5UZTQYZVYeb9bnZ3ojVhiJNLiXK1Hfc0GNbLXcmZ5plLDDBg==} - engines: {node: '>=14'} - - locate-path@5.0.0: - resolution: {integrity: sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==} - engines: {node: '>=8'} - - locate-path@6.0.0: - resolution: {integrity: sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==} - engines: {node: '>=10'} - - lodash.merge@4.6.2: - resolution: {integrity: sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==} - - lodash@4.17.21: - resolution: {integrity: sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==} - - loupe@2.3.7: - resolution: {integrity: sha512-zSMINGVYkdpYSOBmLi0D1Uo7JU9nVdQKrHxC8eYlV+9YKK9WePqAlL7lSlorG/U2Fw1w0hTBmaa/jrQ3UbPHtA==} - - lru-cache@5.1.1: - resolution: {integrity: sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==} - - magic-string@0.30.10: - resolution: {integrity: sha512-iIRwTIf0QKV3UAnYK4PU8uiEc4SRh5jX0mwpIwETPpHdhVM4f53RSwS/vXvN1JhGX+Cs7B8qIq3d6AH49O5fAQ==} - - merge-stream@2.0.0: - resolution: {integrity: sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w==} - - mimic-fn@4.0.0: - resolution: {integrity: sha512-vqiC06CuhBTUdZH+RYl8sFrL096vA45Ok5ISO6sE/Mr1jRbGH4Csnhi8f3wKVl7x8mO4Au7Ir9D3Oyv1VYMFJw==} - engines: {node: '>=12'} - - min-indent@1.0.1: - resolution: {integrity: sha512-I9jwMn07Sy/IwOj3zVkVik2JTvgpaykDZEigL6Rx6N9LbMywwUSMtxET+7lVoDLLd3O3IXwJwvuuns8UB/HeAg==} - engines: {node: '>=4'} - - minimatch@3.1.2: - resolution: {integrity: sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==} - - minimist@1.2.8: - resolution: {integrity: sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==} - - mlly@1.7.1: - resolution: {integrity: sha512-rrVRZRELyQzrIUAVMHxP97kv+G786pHmOKzuFII8zDYahFBS7qnHh2AlYSl1GAHhaMPCz6/oHjVMcfFYgFYHgA==} - - ms@2.1.2: - resolution: {integrity: sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==} - - nanoid@3.3.7: - resolution: {integrity: sha512-eSRppjcPIatRIMC1U6UngP8XFcz8MQWGQdt1MTBQ7NaAmvXDfvNxbvWV3x2y6CdEUciCSsDHDQZbhYaB8QEo2g==} - engines: {node: ^10 || ^12 || ^13.7 || ^14 || >=15.0.1} - hasBin: true - - natural-compare@1.4.0: - resolution: {integrity: sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==} - - node-releases@2.0.14: - resolution: {integrity: sha512-y10wOWt8yZpqXmOgRo77WaHEmhYQYGNA6y421PKsKYWEK8aW+cqAphborZDhqfyKrbZEN92CN1X2KbafY2s7Yw==} - - normalize-package-data@2.5.0: - resolution: {integrity: sha512-/5CMN3T0R4XTj4DcGaexo+roZSdSFW/0AOOTROrjxzCG1wrWXEsGbRKevjlIL+ZDE4sZlJr5ED4YW0yqmkK+eA==} - - npm-run-path@5.3.0: - resolution: {integrity: sha512-ppwTtiJZq0O/ai0z7yfudtBpWIoxM8yE6nHi1X47eFR2EWORqfbu6CnPlNsjeN683eT0qG6H/Pyf9fCcvjnnnQ==} - engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} - - object-inspect@1.13.2: - resolution: {integrity: sha512-IRZSRuzJiynemAXPYtPe5BoI/RESNYR7TYm50MC5Mqbd3Jmw5y790sErYw3V6SryFJD64b74qQQs9wn5Bg/k3g==} - engines: {node: '>= 0.4'} - - object-keys@1.1.1: - resolution: {integrity: sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==} - engines: {node: '>= 0.4'} - - object.assign@4.1.5: - resolution: {integrity: sha512-byy+U7gp+FVwmyzKPYhW2h5l3crpmGsxl7X2s8y43IgxvG4g3QZ6CffDtsNQy1WsmZpQbO+ybo0AlW7TY6DcBQ==} - engines: {node: '>= 0.4'} - - object.values@1.2.0: - resolution: {integrity: sha512-yBYjY9QX2hnRmZHAjG/f13MzmBzxzYgQhFrke06TTyKY5zSTEqkOeukBzIdVA3j3ulu8Qa3MbVFShV7T2RmGtQ==} - engines: {node: '>= 0.4'} - - once@1.4.0: - resolution: {integrity: sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==} - - onetime@6.0.0: - resolution: {integrity: sha512-1FlR+gjXK7X+AsAHso35MnyN5KqGwJRi/31ft6x0M194ht7S+rWAvd7PHss9xSKMzE0asv1pyIHaJYq+BbacAQ==} - engines: {node: '>=12'} - - optionator@0.9.4: - resolution: {integrity: sha512-6IpQ7mKUxRcZNLIObR0hz7lxsapSSIYNZJwXPGeF0mTVqGKFIXj1DQcMoT22S3ROcLyY/rz0PWaWZ9ayWmad9g==} - engines: {node: '>= 0.8.0'} - - p-limit@2.3.0: - resolution: {integrity: sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==} - engines: {node: '>=6'} - - p-limit@3.1.0: - resolution: {integrity: sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==} - engines: {node: '>=10'} - - p-limit@5.0.0: - resolution: {integrity: sha512-/Eaoq+QyLSiXQ4lyYV23f14mZRQcXnxfHrN0vCai+ak9G0pp9iEQukIIZq5NccEvwRB8PUnZT0KsOoDCINS1qQ==} - engines: {node: '>=18'} - - p-locate@4.1.0: - resolution: {integrity: sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==} - engines: {node: '>=8'} - - p-locate@5.0.0: - resolution: {integrity: sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==} - engines: {node: '>=10'} - - p-try@2.2.0: - resolution: {integrity: sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==} - engines: {node: '>=6'} - - parent-module@1.0.1: - resolution: {integrity: sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==} - engines: {node: '>=6'} - - parse-json@5.2.0: - resolution: {integrity: sha512-ayCKvm/phCGxOkYRSCM82iDwct8/EonSEgCSxWxD7ve6jHggsFl4fZVQBPRNgQoKiuV/odhFrGzQXZwbifC8Rg==} - engines: {node: '>=8'} - - path-exists@4.0.0: - resolution: {integrity: sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==} - engines: {node: '>=8'} - - path-is-absolute@1.0.1: - resolution: {integrity: sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==} - engines: {node: '>=0.10.0'} - - path-key@3.1.1: - resolution: {integrity: sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==} - engines: {node: '>=8'} - - path-key@4.0.0: - resolution: {integrity: sha512-haREypq7xkM7ErfgIyA0z+Bj4AGKlMSdlQE2jvJo6huWD1EdkKYV+G/T4nq0YEF2vgTT8kqMFKo1uHn950r4SQ==} - engines: {node: '>=12'} - - path-parse@1.0.7: - resolution: {integrity: sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==} - - pathe@1.1.2: - resolution: {integrity: sha512-whLdWMYL2TwI08hn8/ZqAbrVemu0LNaNNJZX73O6qaIdCTfXutsLhMkjdENX0qhsQ9uIimo4/aQOmXkoon2nDQ==} - - pathval@1.1.1: - resolution: {integrity: sha512-Dp6zGqpTdETdR63lehJYPeIOqpiNBNtc7BpWSLrOje7UaIsE5aY92r/AunQA7rsXvet3lrJ3JnZX29UPTKXyKQ==} - - picocolors@1.0.0: - resolution: {integrity: sha512-1fygroTLlHu66zi26VoTDv8yRgm0Fccecssto+MhsZ0D/DGW2sm8E8AjW7NU5VVTRt5GxbeZ5qBuJr+HyLYkjQ==} - - picocolors@1.0.1: - resolution: {integrity: sha512-anP1Z8qwhkbmu7MFP5iTt+wQKXgwzf7zTyGlcdzabySa9vd0Xt392U0rVmz9poOaBj0uHJKyyo9/upk0HrEQew==} - - pkg-types@1.1.1: - resolution: {integrity: sha512-ko14TjmDuQJ14zsotODv7dBlwxKhUKQEhuhmbqo1uCi9BB0Z2alo/wAXg6q1dTR5TyuqYyWhjtfe/Tsh+X28jQ==} - - pluralize@8.0.0: - resolution: {integrity: sha512-Nc3IT5yHzflTfbjgqWcCPpo7DaKy4FnpB0l/zCAW0Tc7jxAiuqSxHasntB3D7887LSrA93kDJ9IXovxJYxyLCA==} - engines: {node: '>=4'} - - possible-typed-array-names@1.0.0: - resolution: {integrity: sha512-d7Uw+eZoloe0EHDIYoe+bQ5WXnGMOpmiZFTuMWCwpjzzkL2nTjcKiAk4hh8TjnGye2TwWOk3UXucZ+3rbmBa8Q==} - engines: {node: '>= 0.4'} - - postcss@8.4.38: - resolution: {integrity: sha512-Wglpdk03BSfXkHoQa3b/oulrotAkwrlLDRSOb9D0bN86FdRyE9lppSp33aHNPgBa0JKCoB+drFLZkQoRRYae5A==} - engines: {node: ^10 || ^12 || >=14} - - prelude-ls@1.2.1: - resolution: {integrity: sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==} - engines: {node: '>= 0.8.0'} - - pretty-format@29.7.0: - resolution: {integrity: sha512-Pdlw/oPxN+aXdmM9R00JVC9WVFoCLTKJvDVLgmJ+qAffBMxsV85l/Lu7sNx4zSzPyoL2euImuEwHhOXdEgNFZQ==} - engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} - - punycode@2.3.1: - resolution: {integrity: sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==} - engines: {node: '>=6'} - - queue-microtask@1.2.3: - resolution: {integrity: sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==} - - react-is@18.2.0: - resolution: {integrity: sha512-xWGDIW6x921xtzPkhiULtthJHoJvBbF3q26fzloPCK0hsvxtPVelvftw3zjbHWSkR2km9Z+4uxbDDK/6Zw9B8w==} - - read-pkg-up@7.0.1: - resolution: {integrity: sha512-zK0TB7Xd6JpCLmlLmufqykGE+/TlOePD6qKClNW7hHDKFh/J7/7gCWGR7joEQEW1bKq3a3yUZSObOoWLFQ4ohg==} - engines: {node: '>=8'} - - read-pkg@5.2.0: - resolution: {integrity: sha512-Ug69mNOpfvKDAc2Q8DRpMjjzdtrnv9HcSMX+4VsZxD1aZ6ZzrIE7rlzXBtWTyhULSMKg076AW6WR5iZpD0JiOg==} - engines: {node: '>=8'} - - regexp-tree@0.1.27: - resolution: {integrity: sha512-iETxpjK6YoRWJG5o6hXLwvjYAoW+FEZn9os0PD/b6AP6xQwsa/Y7lCVgIixBbUPMfhu+i2LtdeAqVTgGlQarfA==} - hasBin: true - - regexp.prototype.flags@1.5.2: - resolution: {integrity: sha512-NcDiDkTLuPR+++OCKB0nWafEmhg/Da8aUPLPMQbK+bxKKCm1/S5he+AqYa4PlMCVBalb4/yxIRub6qkEx5yJbw==} - engines: {node: '>= 0.4'} - - regexpp@3.2.0: - resolution: {integrity: sha512-pq2bWo9mVD43nbts2wGv17XLiNLya+GklZ8kaDLV2Z08gDCsGpnKn9BFMepvWuHCbyVvY7J5o5+BVvoQbmlJLg==} - engines: {node: '>=8'} - - regjsparser@0.10.0: - resolution: {integrity: sha512-qx+xQGZVsy55CH0a1hiVwHmqjLryfh7wQyF5HO07XJ9f7dQMY/gPQHhlyDkIzJKC+x2fUCpCcUODUUUFrm7SHA==} - hasBin: true - - resolve-from@4.0.0: - resolution: {integrity: sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==} - engines: {node: '>=4'} - - resolve@1.22.8: - resolution: {integrity: sha512-oKWePCxqpd6FlLvGV1VU0x7bkPmmCNolxzjMf4NczoDnQcIWrAF+cPtZn5i6n+RfD2d9i0tzpKnG6Yk168yIyw==} - hasBin: true - - reusify@1.0.4: - resolution: {integrity: sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw==} - engines: {iojs: '>=1.0.0', node: '>=0.10.0'} - - rimraf@3.0.2: - resolution: {integrity: sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==} - deprecated: Rimraf versions prior to v4 are no longer supported - hasBin: true - - rollup@4.18.0: - resolution: {integrity: sha512-QmJz14PX3rzbJCN1SG4Xe/bAAX2a6NpCP8ab2vfu2GiUr8AQcr2nCV/oEO3yneFarB67zk8ShlIyWb2LGTb3Sg==} - engines: {node: '>=18.0.0', npm: '>=8.0.0'} - hasBin: true - - run-parallel@1.2.0: - resolution: {integrity: sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==} - - safe-array-concat@1.1.2: - resolution: {integrity: sha512-vj6RsCsWBCf19jIeHEfkRMw8DPiBb+DMXklQ/1SGDHOMlHdPUkZXFQ2YdplS23zESTijAcurb1aSgJA3AgMu1Q==} - engines: {node: '>=0.4'} - - safe-regex-test@1.0.3: - resolution: {integrity: sha512-CdASjNJPvRa7roO6Ra/gLYBTzYzzPyyBXxIMdGW3USQLyjWEls2RgW5UBTXaQVp+OrpeCK3bLem8smtmheoRuw==} - engines: {node: '>= 0.4'} - - safe-regex@2.1.1: - resolution: {integrity: sha512-rx+x8AMzKb5Q5lQ95Zoi6ZbJqwCLkqi3XuJXp5P3rT8OEc6sZCJG5AE5dU3lsgRr/F4Bs31jSlVN+j5KrsGu9A==} - - semver@5.7.2: - resolution: {integrity: sha512-cBznnQ9KjJqU67B52RMC65CMarK2600WFnbkcaiwWq3xy/5haFJlshgnpjovMVJ+Hff49d8GEn0b87C5pDQ10g==} - hasBin: true - - semver@6.3.1: - resolution: {integrity: sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==} - hasBin: true - - semver@7.6.2: - resolution: {integrity: sha512-FNAIBWCx9qcRhoHcgcJ0gvU7SN1lYU2ZXuSfl04bSC5OpvDHFyJCjdNHomPXxjQlCBU67YW64PzY7/VIEH7F2w==} - engines: {node: '>=10'} - hasBin: true - - set-function-length@1.2.2: - resolution: {integrity: sha512-pgRc4hJ4/sNjWCSS9AmnS40x3bNMDTknHgL5UaMBTMyJnU90EgWh1Rz+MC9eFu4BuN/UwZjKQuY/1v3rM7HMfg==} - engines: {node: '>= 0.4'} - - set-function-name@2.0.2: - resolution: {integrity: sha512-7PGFlmtwsEADb0WYyvCMa1t+yke6daIG4Wirafur5kcf+MhUnPms1UeR0CKQdTZD81yESwMHbtn+TR+dMviakQ==} - engines: {node: '>= 0.4'} - - shebang-command@2.0.0: - resolution: {integrity: sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==} - engines: {node: '>=8'} - - shebang-regex@3.0.0: - resolution: {integrity: sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==} - engines: {node: '>=8'} - - side-channel@1.0.6: - resolution: {integrity: sha512-fDW/EZ6Q9RiO8eFG8Hj+7u/oW+XrPTIChwCOM2+th2A6OblDtYYIpve9m+KvI9Z4C9qSEXlaGR6bTEYHReuglA==} - engines: {node: '>= 0.4'} - - siginfo@2.0.0: - resolution: {integrity: sha512-ybx0WO1/8bSBLEWXZvEd7gMW3Sn3JFlW3TvX1nREbDLRNQNaeNN8WK0meBwPdAaOI7TtRRRJn/Es1zhrrCHu7g==} - - signal-exit@4.1.0: - resolution: {integrity: sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==} - engines: {node: '>=14'} - - source-map-js@1.2.0: - resolution: {integrity: sha512-itJW8lvSA0TXEphiRoawsCksnlf8SyvmFzIhltqAHluXd88pkCd+cXJVHTDwdCr0IzwptSm035IHQktUu1QUMg==} - engines: {node: '>=0.10.0'} - - spdx-correct@3.2.0: - resolution: {integrity: sha512-kN9dJbvnySHULIluDHy32WHRUu3Og7B9sbY7tsFLctQkIqnMh3hErYgdMjTYuqmcXX+lK5T1lnUt3G7zNswmZA==} - - spdx-exceptions@2.5.0: - resolution: {integrity: sha512-PiU42r+xO4UbUS1buo3LPJkjlO7430Xn5SVAhdpzzsPHsjbYVflnnFdATgabnLude+Cqu25p6N+g2lw/PFsa4w==} - - spdx-expression-parse@3.0.1: - resolution: {integrity: sha512-cbqHunsQWnJNE6KhVSMsMeH5H/L9EpymbzqTQ3uLwNCLZ1Q481oWaofqH7nO6V07xlXwY6PhQdQ2IedWx/ZK4Q==} - - spdx-license-ids@3.0.18: - resolution: {integrity: sha512-xxRs31BqRYHwiMzudOrpSiHtZ8i/GeionCBDSilhYRj+9gIcI8wCZTlXZKu9vZIVqViP3dcp9qE5G6AlIaD+TQ==} - - stackback@0.0.2: - resolution: {integrity: sha512-1XMJE5fQo1jGH6Y/7ebnwPOBEkIEnT4QF32d5R1+VXdXveM0IBMJt8zfaxX1P3QhVwrYe+576+jkANtSS2mBbw==} - - std-env@3.7.0: - resolution: {integrity: sha512-JPbdCEQLj1w5GilpiHAx3qJvFndqybBysA3qUOnznweH4QbNYUsW/ea8QzSrnh0vNsezMMw5bcVool8lM0gwzg==} - - string.prototype.trim@1.2.9: - resolution: {integrity: sha512-klHuCNxiMZ8MlsOihJhJEBJAiMVqU3Z2nEXWfWnIqjN0gEFS9J9+IxKozWWtQGcgoa1WUZzLjKPTr4ZHNFTFxw==} - engines: {node: '>= 0.4'} - - string.prototype.trimend@1.0.8: - resolution: {integrity: sha512-p73uL5VCHCO2BZZ6krwwQE3kCzM7NKmis8S//xEC6fQonchbum4eP6kR4DLEjQFO3Wnj3Fuo8NM0kOSjVdHjZQ==} - - string.prototype.trimstart@1.0.8: - resolution: {integrity: sha512-UXSH262CSZY1tfu3G3Secr6uGLCFVPMhIqHjlgCUtCCcgihYc/xKs9djMTMUOb2j1mVSeU8EU6NWc/iQKU6Gfg==} - engines: {node: '>= 0.4'} - - strip-ansi@6.0.1: - resolution: {integrity: sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==} - engines: {node: '>=8'} - - strip-bom@3.0.0: - resolution: {integrity: sha512-vavAMRXOgBVNF6nyEEmL3DBK19iRpDcoIwW+swQ+CbGiu7lju6t+JklA1MHweoWtadgt4ISVUsXLyDq34ddcwA==} - engines: {node: '>=4'} - - strip-final-newline@3.0.0: - resolution: {integrity: sha512-dOESqjYr96iWYylGObzd39EuNTa5VJxyvVAEm5Jnh7KGo75V43Hk1odPQkNDyXNmUR6k+gEiDVXnjB8HJ3crXw==} - engines: {node: '>=12'} - - strip-indent@3.0.0: - resolution: {integrity: sha512-laJTa3Jb+VQpaC6DseHhF7dXVqHTfJPCRDaEbid/drOhgitgYku/letMUqOXFoWV0zIIUbjpdH2t+tYj4bQMRQ==} - engines: {node: '>=8'} - - strip-json-comments@3.1.1: - resolution: {integrity: sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==} - engines: {node: '>=8'} - - strip-literal@2.1.0: - resolution: {integrity: sha512-Op+UycaUt/8FbN/Z2TWPBLge3jWrP3xj10f3fnYxf052bKuS3EKs1ZQcVGjnEMdsNVAM+plXRdmjrZ/KgG3Skw==} - - supports-color@5.5.0: - resolution: {integrity: sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==} - engines: {node: '>=4'} - - supports-color@7.2.0: - resolution: {integrity: sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==} - engines: {node: '>=8'} - - supports-preserve-symlinks-flag@1.0.0: - resolution: {integrity: sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==} - engines: {node: '>= 0.4'} - - text-table@0.2.0: - resolution: {integrity: sha512-N+8UisAXDGk8PFXP4HAzVR9nbfmVJ3zYLAWiTIoqC5v5isinhr+r5uaO8+7r3BMfuNIufIsA7RdpVgacC2cSpw==} - - tinybench@2.8.0: - resolution: {integrity: sha512-1/eK7zUnIklz4JUUlL+658n58XO2hHLQfSk1Zf2LKieUjxidN16eKFEoDEfjHc3ohofSSqK3X5yO6VGb6iW8Lw==} - - tinypool@0.8.4: - resolution: {integrity: sha512-i11VH5gS6IFeLY3gMBQ00/MmLncVP7JLXOw1vlgkytLmJK7QnEr7NXf0LBdxfmNPAeyetukOk0bOYrJrFGjYJQ==} - engines: {node: '>=14.0.0'} - - tinyspy@2.2.1: - resolution: {integrity: sha512-KYad6Vy5VDWV4GH3fjpseMQ/XU2BhIYP7Vzd0LG44qRWm/Yt2WCOTicFdvmgo6gWaqooMQCawTtILVQJupKu7A==} - engines: {node: '>=14.0.0'} - - to-fast-properties@2.0.0: - resolution: {integrity: sha512-/OaKK0xYrs3DmxRYqL/yDc+FxFUVYhDlXMhRmv3z915w2HF1tnN1omB354j8VUGO/hbRzyD6Y3sA7v7GS/ceog==} - engines: {node: '>=4'} - - tsconfig-paths@3.15.0: - resolution: {integrity: sha512-2Ac2RgzDe/cn48GvOe3M+o82pEFewD3UPbyoUHHdKasHwJKjds4fLXWf/Ux5kATBKN20oaFGu+jbElp1pos0mg==} - - type-check@0.4.0: - resolution: {integrity: sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==} - engines: {node: '>= 0.8.0'} - - type-detect@4.0.8: - resolution: {integrity: sha512-0fr/mIH1dlO+x7TlcMy+bIDqKPsw/70tVyeHW787goQjhmqaZe10uwLujubK9q9Lg6Fiho1KUKDYz0Z7k7g5/g==} - engines: {node: '>=4'} - - type-fest@0.20.2: - resolution: {integrity: sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ==} - engines: {node: '>=10'} - - type-fest@0.6.0: - resolution: {integrity: sha512-q+MB8nYR1KDLrgr4G5yemftpMC7/QLqVndBmEEdqzmNj5dcFOO4Oo8qlwZE3ULT3+Zim1F8Kq4cBnikNhlCMlg==} - engines: {node: '>=8'} - - type-fest@0.8.1: - resolution: {integrity: sha512-4dbzIzqvjtgiM5rw1k5rEHtBANKmdudhGyBEajN01fEyhaAIhsoKNy6y7+IN93IfpFtwY9iqi7kD+xwKhQsNJA==} - engines: {node: '>=8'} - - typed-array-buffer@1.0.2: - resolution: {integrity: sha512-gEymJYKZtKXzzBzM4jqa9w6Q1Jjm7x2d+sh19AdsD4wqnMPDYyvwpsIc2Q/835kHuo3BEQ7CjelGhfTsoBb2MQ==} - engines: {node: '>= 0.4'} - - typed-array-byte-length@1.0.1: - resolution: {integrity: sha512-3iMJ9q0ao7WE9tWcaYKIptkNBuOIcZCCT0d4MRvuuH88fEoEH62IuQe0OtraD3ebQEoTRk8XCBoknUNc1Y67pw==} - engines: {node: '>= 0.4'} - - typed-array-byte-offset@1.0.2: - resolution: {integrity: sha512-Ous0vodHa56FviZucS2E63zkgtgrACj7omjwd/8lTEMEPFFyjfixMZ1ZXenpgCFBBt4EC1J2XsyVS2gkG0eTFA==} - engines: {node: '>= 0.4'} - - typed-array-length@1.0.6: - resolution: {integrity: sha512-/OxDN6OtAk5KBpGb28T+HZc2M+ADtvRxXrKKbUwtsLgdoxgX13hyy7ek6bFRl5+aBs2yZzB0c4CnQfAtVypW/g==} - engines: {node: '>= 0.4'} - - ufo@1.5.3: - resolution: {integrity: sha512-Y7HYmWaFwPUmkoQCUIAYpKqkOf+SbVj/2fJJZ4RJMCfZp0rTGwRbzQD+HghfnhKOjL9E01okqz+ncJskGYfBNw==} - - unbox-primitive@1.0.2: - resolution: {integrity: sha512-61pPlCD9h51VoreyJ0BReideM3MDKMKnh6+V9L08331ipq6Q8OFXZYiqP6n/tbHx4s5I9uRhcye6BrbkizkBDw==} - - undici-types@5.26.5: - resolution: {integrity: sha512-JlCMO+ehdEIKqlFxk6IfVoAUVmgz7cU7zD/h9XZ0qzeosSHmUJVOzSQvvYSYWXkFXC+IfLKSIffhv0sVZup6pA==} - - update-browserslist-db@1.0.16: - resolution: {integrity: sha512-KVbTxlBYlckhF5wgfyZXTWnMn7MMZjMu9XG8bPlliUOP9ThaF4QnhP8qrjrH7DRzHfSk0oQv1wToW+iA5GajEQ==} - hasBin: true - peerDependencies: - browserslist: '>= 4.21.0' - - uri-js@4.4.1: - resolution: {integrity: sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==} - - valibot@0.35.0: - resolution: {integrity: sha512-+i2aCRkReTrd5KBN/dW2BrPOvFnU5LXTV2xjZnjnqUIO8YUx6P2+MgRrkwF2FhkexgyKq/NIZdPdknhHf5A/Ww==} - - validate-npm-package-license@3.0.4: - resolution: {integrity: sha512-DpKm2Ui/xN7/HQKCtpZxoRWBhZ9Z0kqtygG8XCgNQ8ZlDnxuQmWhj566j8fN4Cu3/JmbhsDo7fcAJq4s9h27Ew==} - - vite-node@1.6.0: - resolution: {integrity: sha512-de6HJgzC+TFzOu0NTC4RAIsyf/DY/ibWDYQUcuEA84EMHhcefTUGkjFHKKEJhQN4A+6I0u++kr3l36ZF2d7XRw==} - engines: {node: ^18.0.0 || >=20.0.0} - hasBin: true - - vite@5.3.1: - resolution: {integrity: sha512-XBmSKRLXLxiaPYamLv3/hnP/KXDai1NDexN0FpkTaZXTfycHvkRHoenpgl/fvuK/kPbB6xAgoyiryAhQNxYmAQ==} - engines: {node: ^18.0.0 || >=20.0.0} - hasBin: true - peerDependencies: - '@types/node': ^18.0.0 || >=20.0.0 - less: '*' - lightningcss: ^1.21.0 - sass: '*' - stylus: '*' - sugarss: '*' - terser: ^5.4.0 - peerDependenciesMeta: - '@types/node': - optional: true - less: - optional: true - lightningcss: - optional: true - sass: - optional: true - stylus: - optional: true - sugarss: - optional: true - terser: - optional: true - - vitest@1.6.0: - resolution: {integrity: sha512-H5r/dN06swuFnzNFhq/dnz37bPXnq8xB2xB5JOVk8K09rUtoeNN+LHWkoQ0A/i3hvbUKKcCei9KpbxqHMLhLLA==} - engines: {node: ^18.0.0 || >=20.0.0} - hasBin: true - peerDependencies: - '@edge-runtime/vm': '*' - '@types/node': ^18.0.0 || >=20.0.0 - '@vitest/browser': 1.6.0 - '@vitest/ui': 1.6.0 - happy-dom: '*' - jsdom: '*' - peerDependenciesMeta: - '@edge-runtime/vm': - optional: true - '@types/node': - optional: true - '@vitest/browser': - optional: true - '@vitest/ui': - optional: true - happy-dom: - optional: true - jsdom: - optional: true - - which-boxed-primitive@1.0.2: - resolution: {integrity: sha512-bwZdv0AKLpplFY2KZRX6TvyuN7ojjr7lwkg6ml0roIy9YeuSr7JS372qlNW18UQYzgYK9ziGcerWqZOmEn9VNg==} - - which-typed-array@1.1.15: - resolution: {integrity: sha512-oV0jmFtUky6CXfkqehVvBP/LSWJ2sy4vWMioiENyJLePrBO/yKyV9OyJySfAKosh+RYkIl5zJCNZ8/4JncrpdA==} - engines: {node: '>= 0.4'} - - which@2.0.2: - resolution: {integrity: sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==} - engines: {node: '>= 8'} - hasBin: true - - why-is-node-running@2.2.2: - resolution: {integrity: sha512-6tSwToZxTOcotxHeA+qGCq1mVzKR3CwcJGmVcY+QE8SHy6TnpFnh8PAvPNHYr7EcuVeG0QSMxtYCuO1ta/G/oA==} - engines: {node: '>=8'} - hasBin: true - - word-wrap@1.2.5: - resolution: {integrity: sha512-BN22B5eaMMI9UMtjrGd5g5eCYPpCPDUy0FJXbYsaT5zYxjFOckS53SQDE3pWkVoWpHXVb3BrYcEN4Twa55B5cA==} - engines: {node: '>=0.10.0'} - - wrappy@1.0.2: - resolution: {integrity: sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==} - - yallist@3.1.1: - resolution: {integrity: sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==} - - yocto-queue@0.1.0: - resolution: {integrity: sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==} - engines: {node: '>=10'} - - yocto-queue@1.0.0: - resolution: {integrity: sha512-9bnSc/HEW2uRy67wc+T8UwauLuPJVn28jb+GtJY16iiKWyvmYJRXVT4UamsAEGQfPohgr2q4Tq0sQbQlxTfi1g==} - engines: {node: '>=12.20'} - -snapshots: - - '@ampproject/remapping@2.3.0': - dependencies: - '@jridgewell/gen-mapping': 0.3.5 - '@jridgewell/trace-mapping': 0.3.25 - - '@babel/code-frame@7.24.7': - dependencies: - '@babel/highlight': 7.24.7 - picocolors: 1.0.0 - - '@babel/compat-data@7.24.7': {} - - '@babel/core@7.24.7': - dependencies: - '@ampproject/remapping': 2.3.0 - '@babel/code-frame': 7.24.7 - '@babel/generator': 7.24.7 - '@babel/helper-compilation-targets': 7.24.7 - '@babel/helper-module-transforms': 7.24.7(@babel/core@7.24.7) - '@babel/helpers': 7.24.7 - '@babel/parser': 7.24.7 - '@babel/template': 7.24.7 - '@babel/traverse': 7.24.7 - '@babel/types': 7.24.7 - convert-source-map: 2.0.0 - debug: 4.3.4 - gensync: 1.0.0-beta.2 - json5: 2.2.3 - semver: 6.3.1 - transitivePeerDependencies: - - supports-color - - '@babel/eslint-parser@7.21.8(@babel/core@7.24.7)(eslint@8.41.0)': - dependencies: - '@babel/core': 7.24.7 - '@nicolo-ribaudo/eslint-scope-5-internals': 5.1.1-v1 - eslint: 8.41.0 - eslint-visitor-keys: 2.1.0 - semver: 6.3.1 - - '@babel/generator@7.24.7': - dependencies: - '@babel/types': 7.24.7 - '@jridgewell/gen-mapping': 0.3.5 - '@jridgewell/trace-mapping': 0.3.25 - jsesc: 2.5.2 - - '@babel/helper-compilation-targets@7.24.7': - dependencies: - '@babel/compat-data': 7.24.7 - '@babel/helper-validator-option': 7.24.7 - browserslist: 4.23.1 - lru-cache: 5.1.1 - semver: 6.3.1 - - '@babel/helper-environment-visitor@7.24.7': - dependencies: - '@babel/types': 7.24.7 - - '@babel/helper-function-name@7.24.7': - dependencies: - '@babel/template': 7.24.7 - '@babel/types': 7.24.7 - - '@babel/helper-hoist-variables@7.24.7': - dependencies: - '@babel/types': 7.24.7 - - '@babel/helper-module-imports@7.24.7': - dependencies: - '@babel/traverse': 7.24.7 - '@babel/types': 7.24.7 - transitivePeerDependencies: - - supports-color - - '@babel/helper-module-transforms@7.24.7(@babel/core@7.24.7)': - dependencies: - '@babel/core': 7.24.7 - '@babel/helper-environment-visitor': 7.24.7 - '@babel/helper-module-imports': 7.24.7 - '@babel/helper-simple-access': 7.24.7 - '@babel/helper-split-export-declaration': 7.24.7 - '@babel/helper-validator-identifier': 7.24.7 - transitivePeerDependencies: - - supports-color - - '@babel/helper-simple-access@7.24.7': - dependencies: - '@babel/traverse': 7.24.7 - '@babel/types': 7.24.7 - transitivePeerDependencies: - - supports-color - - '@babel/helper-split-export-declaration@7.24.7': - dependencies: - '@babel/types': 7.24.7 - - '@babel/helper-string-parser@7.24.7': {} - - '@babel/helper-validator-identifier@7.24.7': {} - - '@babel/helper-validator-option@7.24.7': {} - - '@babel/helpers@7.24.7': - dependencies: - '@babel/template': 7.24.7 - '@babel/types': 7.24.7 - - '@babel/highlight@7.24.7': - dependencies: - '@babel/helper-validator-identifier': 7.24.7 - chalk: 2.4.2 - js-tokens: 4.0.0 - picocolors: 1.0.0 - - '@babel/parser@7.24.7': - dependencies: - '@babel/types': 7.24.7 - - '@babel/template@7.24.7': - dependencies: - '@babel/code-frame': 7.24.7 - '@babel/parser': 7.24.7 - '@babel/types': 7.24.7 - - '@babel/traverse@7.24.7': - dependencies: - '@babel/code-frame': 7.24.7 - '@babel/generator': 7.24.7 - '@babel/helper-environment-visitor': 7.24.7 - '@babel/helper-function-name': 7.24.7 - '@babel/helper-hoist-variables': 7.24.7 - '@babel/helper-split-export-declaration': 7.24.7 - '@babel/parser': 7.24.7 - '@babel/types': 7.24.7 - debug: 4.3.4 - globals: 11.12.0 - transitivePeerDependencies: - - supports-color - - '@babel/types@7.24.7': - dependencies: - '@babel/helper-string-parser': 7.24.7 - '@babel/helper-validator-identifier': 7.24.7 - to-fast-properties: 2.0.0 - - '@es-joy/jsdoccomment@0.40.1': - dependencies: - comment-parser: 1.4.0 - esquery: 1.5.0 - jsdoc-type-pratt-parser: 4.0.0 - - '@esbuild/aix-ppc64@0.21.5': - optional: true - - '@esbuild/android-arm64@0.21.5': - optional: true - - '@esbuild/android-arm@0.21.5': - optional: true - - '@esbuild/android-x64@0.21.5': - optional: true - - '@esbuild/darwin-arm64@0.21.5': - optional: true - - '@esbuild/darwin-x64@0.21.5': - optional: true - - '@esbuild/freebsd-arm64@0.21.5': - optional: true - - '@esbuild/freebsd-x64@0.21.5': - optional: true - - '@esbuild/linux-arm64@0.21.5': - optional: true - - '@esbuild/linux-arm@0.21.5': - optional: true - - '@esbuild/linux-ia32@0.21.5': - optional: true - - '@esbuild/linux-loong64@0.21.5': - optional: true - - '@esbuild/linux-mips64el@0.21.5': - optional: true - - '@esbuild/linux-ppc64@0.21.5': - optional: true - - '@esbuild/linux-riscv64@0.21.5': - optional: true - - '@esbuild/linux-s390x@0.21.5': - optional: true - - '@esbuild/linux-x64@0.21.5': - optional: true - - '@esbuild/netbsd-x64@0.21.5': - optional: true - - '@esbuild/openbsd-x64@0.21.5': - optional: true - - '@esbuild/sunos-x64@0.21.5': - optional: true - - '@esbuild/win32-arm64@0.21.5': - optional: true - - '@esbuild/win32-ia32@0.21.5': - optional: true - - '@esbuild/win32-x64@0.21.5': - optional: true - - '@eslint-community/eslint-utils@4.4.0(eslint@8.41.0)': - dependencies: - eslint: 8.41.0 - eslint-visitor-keys: 3.4.3 - - '@eslint-community/regexpp@4.10.1': {} - - '@eslint/eslintrc@2.1.4': - dependencies: - ajv: 6.12.6 - debug: 4.3.4 - espree: 9.6.1 - globals: 13.24.0 - ignore: 5.3.1 - import-fresh: 3.3.0 - js-yaml: 4.1.0 - minimatch: 3.1.2 - strip-json-comments: 3.1.1 - transitivePeerDependencies: - - supports-color - - '@eslint/js@8.41.0': {} - - '@humanwhocodes/config-array@0.11.14': - dependencies: - '@humanwhocodes/object-schema': 2.0.3 - debug: 4.3.4 - minimatch: 3.1.2 - transitivePeerDependencies: - - supports-color - - '@humanwhocodes/module-importer@1.0.1': {} - - '@humanwhocodes/object-schema@2.0.3': {} - - '@jest/schemas@29.6.3': - dependencies: - '@sinclair/typebox': 0.27.8 - - '@jridgewell/gen-mapping@0.3.5': - dependencies: - '@jridgewell/set-array': 1.2.1 - '@jridgewell/sourcemap-codec': 1.4.15 - '@jridgewell/trace-mapping': 0.3.25 - - '@jridgewell/resolve-uri@3.1.2': {} - - '@jridgewell/set-array@1.2.1': {} - - '@jridgewell/sourcemap-codec@1.4.15': {} - - '@jridgewell/trace-mapping@0.3.25': - dependencies: - '@jridgewell/resolve-uri': 3.1.2 - '@jridgewell/sourcemap-codec': 1.4.15 - - '@nicolo-ribaudo/eslint-scope-5-internals@5.1.1-v1': - dependencies: - eslint-scope: 5.1.1 - - '@nodelib/fs.scandir@2.1.5': - dependencies: - '@nodelib/fs.stat': 2.0.5 - run-parallel: 1.2.0 - - '@nodelib/fs.stat@2.0.5': {} - - '@nodelib/fs.walk@1.2.8': - dependencies: - '@nodelib/fs.scandir': 2.1.5 - fastq: 1.17.1 - - '@rollup/rollup-android-arm-eabi@4.18.0': - optional: true - - '@rollup/rollup-android-arm64@4.18.0': - optional: true - - '@rollup/rollup-darwin-arm64@4.18.0': - optional: true - - '@rollup/rollup-darwin-x64@4.18.0': - optional: true - - '@rollup/rollup-linux-arm-gnueabihf@4.18.0': - optional: true - - '@rollup/rollup-linux-arm-musleabihf@4.18.0': - optional: true - - '@rollup/rollup-linux-arm64-gnu@4.18.0': - optional: true - - '@rollup/rollup-linux-arm64-musl@4.18.0': - optional: true - - '@rollup/rollup-linux-powerpc64le-gnu@4.18.0': - optional: true - - '@rollup/rollup-linux-riscv64-gnu@4.18.0': - optional: true - - '@rollup/rollup-linux-s390x-gnu@4.18.0': - optional: true - - '@rollup/rollup-linux-x64-gnu@4.18.0': - optional: true - - '@rollup/rollup-linux-x64-musl@4.18.0': - optional: true - - '@rollup/rollup-win32-arm64-msvc@4.18.0': - optional: true - - '@rollup/rollup-win32-ia32-msvc@4.18.0': - optional: true - - '@rollup/rollup-win32-x64-msvc@4.18.0': - optional: true - - '@sinclair/typebox@0.27.8': {} - - '@types/estree@1.0.5': {} - - '@types/json5@0.0.29': {} - - '@types/node@20.14.8': - dependencies: - undici-types: 5.26.5 - - '@types/normalize-package-data@2.4.4': {} - - '@vitest/expect@1.6.0': - dependencies: - '@vitest/spy': 1.6.0 - '@vitest/utils': 1.6.0 - chai: 4.4.1 - - '@vitest/runner@1.6.0': - dependencies: - '@vitest/utils': 1.6.0 - p-limit: 5.0.0 - pathe: 1.1.2 - - '@vitest/snapshot@1.6.0': - dependencies: - magic-string: 0.30.10 - pathe: 1.1.2 - pretty-format: 29.7.0 - - '@vitest/spy@1.6.0': - dependencies: - tinyspy: 2.2.1 - - '@vitest/utils@1.6.0': - dependencies: - diff-sequences: 29.6.3 - estree-walker: 3.0.3 - loupe: 2.3.7 - pretty-format: 29.7.0 - - acorn-jsx@5.3.2(acorn@8.12.0): - dependencies: - acorn: 8.12.0 - - acorn-walk@8.3.3: - dependencies: - acorn: 8.12.0 - - acorn@8.12.0: {} - - ajv@6.12.6: - dependencies: - fast-deep-equal: 3.1.3 - fast-json-stable-stringify: 2.1.0 - json-schema-traverse: 0.4.1 - uri-js: 4.4.1 - - ansi-regex@5.0.1: {} - - ansi-styles@3.2.1: - dependencies: - color-convert: 1.9.3 - - ansi-styles@4.3.0: - dependencies: - color-convert: 2.0.1 - - ansi-styles@5.2.0: {} - - are-docs-informative@0.0.2: {} - - argparse@2.0.1: {} - - array-buffer-byte-length@1.0.1: - dependencies: - call-bind: 1.0.7 - is-array-buffer: 3.0.4 - - array-includes@3.1.8: - dependencies: - call-bind: 1.0.7 - define-properties: 1.2.1 - es-abstract: 1.23.3 - es-object-atoms: 1.0.0 - get-intrinsic: 1.2.4 - is-string: 1.0.7 - - array.prototype.flat@1.3.2: - dependencies: - call-bind: 1.0.7 - define-properties: 1.2.1 - es-abstract: 1.23.3 - es-shim-unscopables: 1.0.2 - - array.prototype.flatmap@1.3.2: - dependencies: - call-bind: 1.0.7 - define-properties: 1.2.1 - es-abstract: 1.23.3 - es-shim-unscopables: 1.0.2 - - arraybuffer.prototype.slice@1.0.3: - dependencies: - array-buffer-byte-length: 1.0.1 - call-bind: 1.0.7 - define-properties: 1.2.1 - es-abstract: 1.23.3 - es-errors: 1.3.0 - get-intrinsic: 1.2.4 - is-array-buffer: 3.0.4 - is-shared-array-buffer: 1.0.3 - - assertion-error@1.1.0: {} - - available-typed-arrays@1.0.7: - dependencies: - possible-typed-array-names: 1.0.0 - - balanced-match@1.0.2: {} - - brace-expansion@1.1.11: - dependencies: - balanced-match: 1.0.2 - concat-map: 0.0.1 - - browserslist@4.23.1: - dependencies: - caniuse-lite: 1.0.30001636 - electron-to-chromium: 1.4.811 - node-releases: 2.0.14 - update-browserslist-db: 1.0.16(browserslist@4.23.1) - - builtin-modules@3.3.0: {} - - cac@6.7.14: {} - - call-bind@1.0.7: - 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.2 - - callsites@3.1.0: {} - - caniuse-lite@1.0.30001636: {} - - chai@4.4.1: - dependencies: - assertion-error: 1.1.0 - check-error: 1.0.3 - deep-eql: 4.1.4 - get-func-name: 2.0.2 - loupe: 2.3.7 - pathval: 1.1.1 - type-detect: 4.0.8 - - chalk@2.4.2: - dependencies: - ansi-styles: 3.2.1 - escape-string-regexp: 1.0.5 - supports-color: 5.5.0 - - chalk@4.1.2: - dependencies: - ansi-styles: 4.3.0 - supports-color: 7.2.0 - - check-error@1.0.3: - dependencies: - get-func-name: 2.0.2 - - ci-info@3.9.0: {} - - clean-regexp@1.0.0: - dependencies: - escape-string-regexp: 1.0.5 - - color-convert@1.9.3: - dependencies: - color-name: 1.1.3 - - color-convert@2.0.1: - dependencies: - color-name: 1.1.4 - - color-name@1.1.3: {} - - color-name@1.1.4: {} - - comment-parser@1.4.0: {} - - concat-map@0.0.1: {} - - confbox@0.1.7: {} - - confusing-browser-globals@1.0.11: {} - - convert-source-map@2.0.0: {} - - cross-spawn@7.0.3: - dependencies: - path-key: 3.1.1 - shebang-command: 2.0.0 - which: 2.0.2 - - data-view-buffer@1.0.1: - dependencies: - call-bind: 1.0.7 - es-errors: 1.3.0 - is-data-view: 1.0.1 - - data-view-byte-length@1.0.1: - dependencies: - call-bind: 1.0.7 - es-errors: 1.3.0 - is-data-view: 1.0.1 - - data-view-byte-offset@1.0.0: - dependencies: - call-bind: 1.0.7 - es-errors: 1.3.0 - is-data-view: 1.0.1 - - debug@3.2.7: - dependencies: - ms: 2.1.2 - - debug@4.3.4: - dependencies: - ms: 2.1.2 - - deep-eql@4.1.4: - dependencies: - type-detect: 4.0.8 - - deep-is@0.1.4: {} - - define-data-property@1.1.4: - dependencies: - es-define-property: 1.0.0 - es-errors: 1.3.0 - gopd: 1.0.1 - - define-properties@1.2.1: - dependencies: - define-data-property: 1.1.4 - has-property-descriptors: 1.0.2 - object-keys: 1.1.1 - - diff-sequences@29.6.3: {} - - doctrine@2.1.0: - dependencies: - esutils: 2.0.3 - - doctrine@3.0.0: - dependencies: - esutils: 2.0.3 - - electron-to-chromium@1.4.811: {} - - error-ex@1.3.2: - dependencies: - is-arrayish: 0.2.1 - - es-abstract@1.23.3: - 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.4 - 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.2 - 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 - - es-define-property@1.0.0: - dependencies: - get-intrinsic: 1.2.4 - - es-errors@1.3.0: {} - - es-object-atoms@1.0.0: - dependencies: - es-errors: 1.3.0 - - es-set-tostringtag@2.0.3: - dependencies: - get-intrinsic: 1.2.4 - has-tostringtag: 1.0.2 - hasown: 2.0.2 - - es-shim-unscopables@1.0.2: - dependencies: - hasown: 2.0.2 - - es-to-primitive@1.2.1: - dependencies: - is-callable: 1.2.7 - is-date-object: 1.0.5 - is-symbol: 1.0.4 - - esbuild@0.21.5: - optionalDependencies: - '@esbuild/aix-ppc64': 0.21.5 - '@esbuild/android-arm': 0.21.5 - '@esbuild/android-arm64': 0.21.5 - '@esbuild/android-x64': 0.21.5 - '@esbuild/darwin-arm64': 0.21.5 - '@esbuild/darwin-x64': 0.21.5 - '@esbuild/freebsd-arm64': 0.21.5 - '@esbuild/freebsd-x64': 0.21.5 - '@esbuild/linux-arm': 0.21.5 - '@esbuild/linux-arm64': 0.21.5 - '@esbuild/linux-ia32': 0.21.5 - '@esbuild/linux-loong64': 0.21.5 - '@esbuild/linux-mips64el': 0.21.5 - '@esbuild/linux-ppc64': 0.21.5 - '@esbuild/linux-riscv64': 0.21.5 - '@esbuild/linux-s390x': 0.21.5 - '@esbuild/linux-x64': 0.21.5 - '@esbuild/netbsd-x64': 0.21.5 - '@esbuild/openbsd-x64': 0.21.5 - '@esbuild/sunos-x64': 0.21.5 - '@esbuild/win32-arm64': 0.21.5 - '@esbuild/win32-ia32': 0.21.5 - '@esbuild/win32-x64': 0.21.5 - - escalade@3.1.2: {} - - escape-string-regexp@1.0.5: {} - - escape-string-regexp@4.0.0: {} - - eslint-config-xo@0.43.1(eslint@8.41.0): - dependencies: - confusing-browser-globals: 1.0.11 - eslint: 8.41.0 - - eslint-import-resolver-node@0.3.9: - dependencies: - debug: 3.2.7 - is-core-module: 2.14.0 - resolve: 1.22.8 - transitivePeerDependencies: - - supports-color - - eslint-module-utils@2.8.1(eslint-import-resolver-node@0.3.9)(eslint@8.41.0): - dependencies: - debug: 3.2.7 - optionalDependencies: - eslint: 8.41.0 - eslint-import-resolver-node: 0.3.9 - transitivePeerDependencies: - - supports-color - - eslint-plugin-es@3.0.1(eslint@8.41.0): - dependencies: - eslint: 8.41.0 - eslint-utils: 2.1.0 - regexpp: 3.2.0 - - eslint-plugin-import@2.27.5(eslint@8.41.0): - dependencies: - array-includes: 3.1.8 - array.prototype.flat: 1.3.2 - array.prototype.flatmap: 1.3.2 - debug: 3.2.7 - doctrine: 2.1.0 - eslint: 8.41.0 - eslint-import-resolver-node: 0.3.9 - eslint-module-utils: 2.8.1(eslint-import-resolver-node@0.3.9)(eslint@8.41.0) - has: 1.0.4 - is-core-module: 2.14.0 - is-glob: 4.0.3 - minimatch: 3.1.2 - object.values: 1.2.0 - resolve: 1.22.8 - semver: 6.3.1 - tsconfig-paths: 3.15.0 - transitivePeerDependencies: - - eslint-import-resolver-typescript - - eslint-import-resolver-webpack - - supports-color - - eslint-plugin-jsdoc@46.5.0(eslint@8.41.0): - dependencies: - '@es-joy/jsdoccomment': 0.40.1 - are-docs-informative: 0.0.2 - comment-parser: 1.4.0 - debug: 4.3.4 - escape-string-regexp: 4.0.0 - eslint: 8.41.0 - esquery: 1.5.0 - is-builtin-module: 3.2.1 - semver: 7.6.2 - spdx-expression-parse: 3.0.1 - transitivePeerDependencies: - - supports-color - - eslint-plugin-node@11.1.0(eslint@8.41.0): - dependencies: - eslint: 8.41.0 - eslint-plugin-es: 3.0.1(eslint@8.41.0) - eslint-utils: 2.1.0 - ignore: 5.3.1 - minimatch: 3.1.2 - resolve: 1.22.8 - semver: 6.3.1 - - eslint-plugin-promise@6.1.1(eslint@8.41.0): - dependencies: - eslint: 8.41.0 - - eslint-plugin-unicorn@47.0.0(eslint@8.41.0): - dependencies: - '@babel/helper-validator-identifier': 7.24.7 - '@eslint-community/eslint-utils': 4.4.0(eslint@8.41.0) - ci-info: 3.9.0 - clean-regexp: 1.0.0 - eslint: 8.41.0 - esquery: 1.5.0 - indent-string: 4.0.0 - is-builtin-module: 3.2.1 - jsesc: 3.0.2 - lodash: 4.17.21 - pluralize: 8.0.0 - read-pkg-up: 7.0.1 - regexp-tree: 0.1.27 - regjsparser: 0.10.0 - safe-regex: 2.1.1 - semver: 7.6.2 - strip-indent: 3.0.0 - - eslint-scope@5.1.1: - dependencies: - esrecurse: 4.3.0 - estraverse: 4.3.0 - - eslint-scope@7.2.2: - dependencies: - esrecurse: 4.3.0 - estraverse: 5.3.0 - - eslint-utils@2.1.0: - dependencies: - eslint-visitor-keys: 1.3.0 - - eslint-visitor-keys@1.3.0: {} - - eslint-visitor-keys@2.1.0: {} - - eslint-visitor-keys@3.4.3: {} - - eslint@8.41.0: - dependencies: - '@eslint-community/eslint-utils': 4.4.0(eslint@8.41.0) - '@eslint-community/regexpp': 4.10.1 - '@eslint/eslintrc': 2.1.4 - '@eslint/js': 8.41.0 - '@humanwhocodes/config-array': 0.11.14 - '@humanwhocodes/module-importer': 1.0.1 - '@nodelib/fs.walk': 1.2.8 - ajv: 6.12.6 - chalk: 4.1.2 - cross-spawn: 7.0.3 - debug: 4.3.4 - 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.5.0 - esutils: 2.0.3 - fast-deep-equal: 3.1.3 - file-entry-cache: 6.0.1 - find-up: 5.0.0 - glob-parent: 6.0.2 - globals: 13.24.0 - graphemer: 1.4.0 - ignore: 5.3.1 - import-fresh: 3.3.0 - imurmurhash: 0.1.4 - is-glob: 4.0.3 - 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.4 - strip-ansi: 6.0.1 - strip-json-comments: 3.1.1 - text-table: 0.2.0 - transitivePeerDependencies: - - supports-color - - espree@9.6.1: - dependencies: - acorn: 8.12.0 - acorn-jsx: 5.3.2(acorn@8.12.0) - eslint-visitor-keys: 3.4.3 - - esquery@1.5.0: - dependencies: - estraverse: 5.3.0 - - esrecurse@4.3.0: - dependencies: - estraverse: 5.3.0 - - estraverse@4.3.0: {} - - estraverse@5.3.0: {} - - estree-walker@3.0.3: - dependencies: - '@types/estree': 1.0.5 - - esutils@2.0.3: {} - - execa@8.0.1: - dependencies: - cross-spawn: 7.0.3 - get-stream: 8.0.1 - human-signals: 5.0.0 - is-stream: 3.0.0 - merge-stream: 2.0.0 - npm-run-path: 5.3.0 - onetime: 6.0.0 - signal-exit: 4.1.0 - strip-final-newline: 3.0.0 - - fast-deep-equal@3.1.3: {} - - fast-json-stable-stringify@2.1.0: {} - - fast-levenshtein@2.0.6: {} - - fastq@1.17.1: - dependencies: - reusify: 1.0.4 - - file-entry-cache@6.0.1: - dependencies: - flat-cache: 3.2.0 - - find-up@4.1.0: - dependencies: - locate-path: 5.0.0 - path-exists: 4.0.0 - - find-up@5.0.0: - dependencies: - locate-path: 6.0.0 - path-exists: 4.0.0 - - flat-cache@3.2.0: - dependencies: - flatted: 3.3.1 - keyv: 4.5.4 - rimraf: 3.0.2 - - flatted@3.3.1: {} - - for-each@0.3.3: - dependencies: - is-callable: 1.2.7 - - fs.realpath@1.0.0: {} - - fsevents@2.3.3: - optional: true - - function-bind@1.1.2: {} - - function.prototype.name@1.1.6: - dependencies: - call-bind: 1.0.7 - define-properties: 1.2.1 - es-abstract: 1.23.3 - functions-have-names: 1.2.3 - - functions-have-names@1.2.3: {} - - gensync@1.0.0-beta.2: {} - - get-func-name@2.0.2: {} - - get-intrinsic@1.2.4: - dependencies: - es-errors: 1.3.0 - function-bind: 1.1.2 - has-proto: 1.0.3 - has-symbols: 1.0.3 - hasown: 2.0.2 - - get-stream@8.0.1: {} - - get-symbol-description@1.0.2: - dependencies: - call-bind: 1.0.7 - es-errors: 1.3.0 - get-intrinsic: 1.2.4 - - glob-parent@6.0.2: - dependencies: - is-glob: 4.0.3 - - glob@7.2.3: - dependencies: - fs.realpath: 1.0.0 - inflight: 1.0.6 - inherits: 2.0.4 - minimatch: 3.1.2 - once: 1.4.0 - path-is-absolute: 1.0.1 - - globals@11.12.0: {} - - globals@13.24.0: - dependencies: - type-fest: 0.20.2 - - globalthis@1.0.4: - dependencies: - define-properties: 1.2.1 - gopd: 1.0.1 - - gopd@1.0.1: - dependencies: - get-intrinsic: 1.2.4 - - graphemer@1.4.0: {} - - has-bigints@1.0.2: {} - - has-flag@3.0.0: {} - - has-flag@4.0.0: {} - - has-property-descriptors@1.0.2: - dependencies: - es-define-property: 1.0.0 - - has-proto@1.0.3: {} - - has-symbols@1.0.3: {} - - has-tostringtag@1.0.2: - dependencies: - has-symbols: 1.0.3 - - has@1.0.4: {} - - hasown@2.0.2: - dependencies: - function-bind: 1.1.2 - - hosted-git-info@2.8.9: {} - - human-signals@5.0.0: {} - - ignore@5.3.1: {} - - import-fresh@3.3.0: - dependencies: - parent-module: 1.0.1 - resolve-from: 4.0.0 - - imurmurhash@0.1.4: {} - - indent-string@4.0.0: {} - - inflight@1.0.6: - dependencies: - once: 1.4.0 - wrappy: 1.0.2 - - inherits@2.0.4: {} - - internal-slot@1.0.7: - dependencies: - es-errors: 1.3.0 - hasown: 2.0.2 - side-channel: 1.0.6 - - is-array-buffer@3.0.4: - dependencies: - call-bind: 1.0.7 - get-intrinsic: 1.2.4 - - is-arrayish@0.2.1: {} - - is-bigint@1.0.4: - dependencies: - has-bigints: 1.0.2 - - is-boolean-object@1.1.2: - dependencies: - call-bind: 1.0.7 - has-tostringtag: 1.0.2 - - is-builtin-module@3.2.1: - dependencies: - builtin-modules: 3.3.0 - - is-callable@1.2.7: {} - - is-core-module@2.14.0: - dependencies: - hasown: 2.0.2 - - is-data-view@1.0.1: - dependencies: - is-typed-array: 1.1.13 - - is-date-object@1.0.5: - dependencies: - has-tostringtag: 1.0.2 - - is-extglob@2.1.1: {} - - is-glob@4.0.3: - dependencies: - is-extglob: 2.1.1 - - is-negative-zero@2.0.3: {} - - is-number-object@1.0.7: - dependencies: - has-tostringtag: 1.0.2 - - is-path-inside@3.0.3: {} - - is-regex@1.1.4: - dependencies: - call-bind: 1.0.7 - has-tostringtag: 1.0.2 - - is-shared-array-buffer@1.0.3: - dependencies: - call-bind: 1.0.7 - - is-stream@3.0.0: {} - - is-string@1.0.7: - dependencies: - has-tostringtag: 1.0.2 - - is-symbol@1.0.4: - dependencies: - has-symbols: 1.0.3 - - is-typed-array@1.1.13: - dependencies: - which-typed-array: 1.1.15 - - is-weakref@1.0.2: - dependencies: - call-bind: 1.0.7 - - isarray@2.0.5: {} - - isexe@2.0.0: {} - - js-tokens@4.0.0: {} - - js-tokens@9.0.0: {} - - js-yaml@4.1.0: - dependencies: - argparse: 2.0.1 - - jsdoc-type-pratt-parser@4.0.0: {} - - jsesc@0.5.0: {} - - jsesc@2.5.2: {} - - jsesc@3.0.2: {} - - json-buffer@3.0.1: {} - - json-parse-even-better-errors@2.3.1: {} - - json-schema-traverse@0.4.1: {} - - json-stable-stringify-without-jsonify@1.0.1: {} - - json5@1.0.2: - dependencies: - minimist: 1.2.8 - - json5@2.2.3: {} - - keyv@4.5.4: - dependencies: - json-buffer: 3.0.1 - - levn@0.4.1: - dependencies: - prelude-ls: 1.2.1 - type-check: 0.4.0 - - lines-and-columns@1.2.4: {} - - local-pkg@0.5.0: - dependencies: - mlly: 1.7.1 - pkg-types: 1.1.1 - - locate-path@5.0.0: - dependencies: - p-locate: 4.1.0 - - locate-path@6.0.0: - dependencies: - p-locate: 5.0.0 - - lodash.merge@4.6.2: {} - - lodash@4.17.21: {} - - loupe@2.3.7: - dependencies: - get-func-name: 2.0.2 - - lru-cache@5.1.1: - dependencies: - yallist: 3.1.1 - - magic-string@0.30.10: - dependencies: - '@jridgewell/sourcemap-codec': 1.4.15 - - merge-stream@2.0.0: {} - - mimic-fn@4.0.0: {} - - min-indent@1.0.1: {} - - minimatch@3.1.2: - dependencies: - brace-expansion: 1.1.11 - - minimist@1.2.8: {} - - mlly@1.7.1: - dependencies: - acorn: 8.12.0 - pathe: 1.1.2 - pkg-types: 1.1.1 - ufo: 1.5.3 - - ms@2.1.2: {} - - nanoid@3.3.7: {} - - natural-compare@1.4.0: {} - - node-releases@2.0.14: {} - - normalize-package-data@2.5.0: - dependencies: - hosted-git-info: 2.8.9 - resolve: 1.22.8 - semver: 5.7.2 - validate-npm-package-license: 3.0.4 - - npm-run-path@5.3.0: - dependencies: - path-key: 4.0.0 - - object-inspect@1.13.2: {} - - object-keys@1.1.1: {} - - object.assign@4.1.5: - dependencies: - call-bind: 1.0.7 - define-properties: 1.2.1 - has-symbols: 1.0.3 - object-keys: 1.1.1 - - object.values@1.2.0: - dependencies: - call-bind: 1.0.7 - define-properties: 1.2.1 - es-object-atoms: 1.0.0 - - once@1.4.0: - dependencies: - wrappy: 1.0.2 - - onetime@6.0.0: - dependencies: - mimic-fn: 4.0.0 - - optionator@0.9.4: - dependencies: - deep-is: 0.1.4 - fast-levenshtein: 2.0.6 - levn: 0.4.1 - prelude-ls: 1.2.1 - type-check: 0.4.0 - word-wrap: 1.2.5 - - p-limit@2.3.0: - dependencies: - p-try: 2.2.0 - - p-limit@3.1.0: - dependencies: - yocto-queue: 0.1.0 - - p-limit@5.0.0: - dependencies: - yocto-queue: 1.0.0 - - p-locate@4.1.0: - dependencies: - p-limit: 2.3.0 - - p-locate@5.0.0: - dependencies: - p-limit: 3.1.0 - - p-try@2.2.0: {} - - parent-module@1.0.1: - dependencies: - callsites: 3.1.0 - - parse-json@5.2.0: - dependencies: - '@babel/code-frame': 7.24.7 - error-ex: 1.3.2 - json-parse-even-better-errors: 2.3.1 - lines-and-columns: 1.2.4 - - path-exists@4.0.0: {} - - path-is-absolute@1.0.1: {} - - path-key@3.1.1: {} - - path-key@4.0.0: {} - - path-parse@1.0.7: {} - - pathe@1.1.2: {} - - pathval@1.1.1: {} - - picocolors@1.0.0: {} - - picocolors@1.0.1: {} - - pkg-types@1.1.1: - dependencies: - confbox: 0.1.7 - mlly: 1.7.1 - pathe: 1.1.2 - - pluralize@8.0.0: {} - - possible-typed-array-names@1.0.0: {} - - postcss@8.4.38: - dependencies: - nanoid: 3.3.7 - picocolors: 1.0.1 - source-map-js: 1.2.0 - - prelude-ls@1.2.1: {} - - pretty-format@29.7.0: - dependencies: - '@jest/schemas': 29.6.3 - ansi-styles: 5.2.0 - react-is: 18.2.0 - - punycode@2.3.1: {} - - queue-microtask@1.2.3: {} - - react-is@18.2.0: {} - - read-pkg-up@7.0.1: - dependencies: - find-up: 4.1.0 - read-pkg: 5.2.0 - type-fest: 0.8.1 - - read-pkg@5.2.0: - dependencies: - '@types/normalize-package-data': 2.4.4 - normalize-package-data: 2.5.0 - parse-json: 5.2.0 - type-fest: 0.6.0 - - regexp-tree@0.1.27: {} - - regexp.prototype.flags@1.5.2: - dependencies: - call-bind: 1.0.7 - define-properties: 1.2.1 - es-errors: 1.3.0 - set-function-name: 2.0.2 - - regexpp@3.2.0: {} - - regjsparser@0.10.0: - dependencies: - jsesc: 0.5.0 - - resolve-from@4.0.0: {} - - resolve@1.22.8: - dependencies: - is-core-module: 2.14.0 - path-parse: 1.0.7 - supports-preserve-symlinks-flag: 1.0.0 - - reusify@1.0.4: {} - - rimraf@3.0.2: - dependencies: - glob: 7.2.3 - - rollup@4.18.0: - dependencies: - '@types/estree': 1.0.5 - optionalDependencies: - '@rollup/rollup-android-arm-eabi': 4.18.0 - '@rollup/rollup-android-arm64': 4.18.0 - '@rollup/rollup-darwin-arm64': 4.18.0 - '@rollup/rollup-darwin-x64': 4.18.0 - '@rollup/rollup-linux-arm-gnueabihf': 4.18.0 - '@rollup/rollup-linux-arm-musleabihf': 4.18.0 - '@rollup/rollup-linux-arm64-gnu': 4.18.0 - '@rollup/rollup-linux-arm64-musl': 4.18.0 - '@rollup/rollup-linux-powerpc64le-gnu': 4.18.0 - '@rollup/rollup-linux-riscv64-gnu': 4.18.0 - '@rollup/rollup-linux-s390x-gnu': 4.18.0 - '@rollup/rollup-linux-x64-gnu': 4.18.0 - '@rollup/rollup-linux-x64-musl': 4.18.0 - '@rollup/rollup-win32-arm64-msvc': 4.18.0 - '@rollup/rollup-win32-ia32-msvc': 4.18.0 - '@rollup/rollup-win32-x64-msvc': 4.18.0 - fsevents: 2.3.3 - - run-parallel@1.2.0: - dependencies: - queue-microtask: 1.2.3 - - safe-array-concat@1.1.2: - dependencies: - call-bind: 1.0.7 - get-intrinsic: 1.2.4 - has-symbols: 1.0.3 - isarray: 2.0.5 - - safe-regex-test@1.0.3: - dependencies: - call-bind: 1.0.7 - es-errors: 1.3.0 - is-regex: 1.1.4 - - safe-regex@2.1.1: - dependencies: - regexp-tree: 0.1.27 - - semver@5.7.2: {} - - semver@6.3.1: {} - - semver@7.6.2: {} - - set-function-length@1.2.2: - 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 - - set-function-name@2.0.2: - dependencies: - define-data-property: 1.1.4 - es-errors: 1.3.0 - functions-have-names: 1.2.3 - has-property-descriptors: 1.0.2 - - shebang-command@2.0.0: - dependencies: - shebang-regex: 3.0.0 - - shebang-regex@3.0.0: {} - - side-channel@1.0.6: - dependencies: - call-bind: 1.0.7 - es-errors: 1.3.0 - get-intrinsic: 1.2.4 - object-inspect: 1.13.2 - - siginfo@2.0.0: {} - - signal-exit@4.1.0: {} - - source-map-js@1.2.0: {} - - spdx-correct@3.2.0: - dependencies: - spdx-expression-parse: 3.0.1 - spdx-license-ids: 3.0.18 - - spdx-exceptions@2.5.0: {} - - spdx-expression-parse@3.0.1: - dependencies: - spdx-exceptions: 2.5.0 - spdx-license-ids: 3.0.18 - - spdx-license-ids@3.0.18: {} - - stackback@0.0.2: {} - - std-env@3.7.0: {} - - string.prototype.trim@1.2.9: - dependencies: - call-bind: 1.0.7 - define-properties: 1.2.1 - es-abstract: 1.23.3 - es-object-atoms: 1.0.0 - - string.prototype.trimend@1.0.8: - dependencies: - call-bind: 1.0.7 - define-properties: 1.2.1 - es-object-atoms: 1.0.0 - - string.prototype.trimstart@1.0.8: - dependencies: - call-bind: 1.0.7 - define-properties: 1.2.1 - es-object-atoms: 1.0.0 - - strip-ansi@6.0.1: - dependencies: - ansi-regex: 5.0.1 - - strip-bom@3.0.0: {} - - strip-final-newline@3.0.0: {} - - strip-indent@3.0.0: - dependencies: - min-indent: 1.0.1 - - strip-json-comments@3.1.1: {} - - strip-literal@2.1.0: - dependencies: - js-tokens: 9.0.0 - - supports-color@5.5.0: - dependencies: - has-flag: 3.0.0 - - supports-color@7.2.0: - dependencies: - has-flag: 4.0.0 - - supports-preserve-symlinks-flag@1.0.0: {} - - text-table@0.2.0: {} - - tinybench@2.8.0: {} - - tinypool@0.8.4: {} - - tinyspy@2.2.1: {} - - to-fast-properties@2.0.0: {} - - tsconfig-paths@3.15.0: - dependencies: - '@types/json5': 0.0.29 - json5: 1.0.2 - minimist: 1.2.8 - strip-bom: 3.0.0 - - type-check@0.4.0: - dependencies: - prelude-ls: 1.2.1 - - type-detect@4.0.8: {} - - type-fest@0.20.2: {} - - type-fest@0.6.0: {} - - type-fest@0.8.1: {} - - typed-array-buffer@1.0.2: - dependencies: - call-bind: 1.0.7 - es-errors: 1.3.0 - is-typed-array: 1.1.13 - - typed-array-byte-length@1.0.1: - 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 - - typed-array-byte-offset@1.0.2: - 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 - - typed-array-length@1.0.6: - 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 - - ufo@1.5.3: {} - - unbox-primitive@1.0.2: - dependencies: - call-bind: 1.0.7 - has-bigints: 1.0.2 - has-symbols: 1.0.3 - which-boxed-primitive: 1.0.2 - - undici-types@5.26.5: {} - - update-browserslist-db@1.0.16(browserslist@4.23.1): - dependencies: - browserslist: 4.23.1 - escalade: 3.1.2 - picocolors: 1.0.1 - - uri-js@4.4.1: - dependencies: - punycode: 2.3.1 - - valibot@0.35.0: {} - - validate-npm-package-license@3.0.4: - dependencies: - spdx-correct: 3.2.0 - spdx-expression-parse: 3.0.1 - - vite-node@1.6.0(@types/node@20.14.8): - dependencies: - cac: 6.7.14 - debug: 4.3.4 - pathe: 1.1.2 - picocolors: 1.0.1 - vite: 5.3.1(@types/node@20.14.8) - transitivePeerDependencies: - - '@types/node' - - less - - lightningcss - - sass - - stylus - - sugarss - - supports-color - - terser - - vite@5.3.1(@types/node@20.14.8): - dependencies: - esbuild: 0.21.5 - postcss: 8.4.38 - rollup: 4.18.0 - optionalDependencies: - '@types/node': 20.14.8 - fsevents: 2.3.3 - - vitest@1.6.0(@types/node@20.14.8): - dependencies: - '@vitest/expect': 1.6.0 - '@vitest/runner': 1.6.0 - '@vitest/snapshot': 1.6.0 - '@vitest/spy': 1.6.0 - '@vitest/utils': 1.6.0 - acorn-walk: 8.3.3 - chai: 4.4.1 - debug: 4.3.4 - execa: 8.0.1 - local-pkg: 0.5.0 - magic-string: 0.30.10 - pathe: 1.1.2 - picocolors: 1.0.1 - std-env: 3.7.0 - strip-literal: 2.1.0 - tinybench: 2.8.0 - tinypool: 0.8.4 - vite: 5.3.1(@types/node@20.14.8) - vite-node: 1.6.0(@types/node@20.14.8) - why-is-node-running: 2.2.2 - optionalDependencies: - '@types/node': 20.14.8 - transitivePeerDependencies: - - less - - lightningcss - - sass - - stylus - - sugarss - - supports-color - - terser - - which-boxed-primitive@1.0.2: - dependencies: - is-bigint: 1.0.4 - is-boolean-object: 1.1.2 - is-number-object: 1.0.7 - is-string: 1.0.7 - is-symbol: 1.0.4 - - which-typed-array@1.1.15: - 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 - - which@2.0.2: - dependencies: - isexe: 2.0.0 - - why-is-node-running@2.2.2: - dependencies: - siginfo: 2.0.0 - stackback: 0.0.2 - - word-wrap@1.2.5: {} - - wrappy@1.0.2: {} - - yallist@3.1.1: {} - - yocto-queue@0.1.0: {} - - yocto-queue@1.0.0: {} diff --git a/src/api-errors.js b/src/api-errors.ts similarity index 51% rename from src/api-errors.js rename to src/api-errors.ts index 1e6dac1..b92140f 100644 --- a/src/api-errors.js +++ b/src/api-errors.ts @@ -1,73 +1,75 @@ +import { + type ErrorData, + HyperAPIError, +} from './error'; -import { HyperAPIError } from './error.js'; - -export class HyperAPIAuthorizationError extends HyperAPIError { +export class HyperAPIAuthorizationError extends HyperAPIError { code = 1; description = 'Authorization error'; httpStatus = 401; // Unauthorized } -export class HyperAPIInvalidParametersError extends HyperAPIError { +export class HyperAPIInvalidParametersError extends HyperAPIError { code = 2; description = 'One of the parameters specified was missing or invalid'; httpStatus = 400; // Bad Request } -export class HyperAPIInternalError extends HyperAPIError { +export class HyperAPIInternalError extends HyperAPIError { code = 3; description = 'Internal error'; httpStatus = 500; // Internal Server Error } -export class HyperAPIForbiddenError extends HyperAPIError { +export class HyperAPIForbiddenError extends HyperAPIError { code = 4; description = 'You do not have permission to perform this action'; httpStatus = 403; // Forbidden } -export class HyperAPIUnknownMethodError extends HyperAPIError { +export class HyperAPIUnknownMethodError extends HyperAPIError { code = 5; description = 'Unknown method called'; httpStatus = 404; // Not Found } -export class HyperAPIObjectsLimitError extends HyperAPIError { +export class HyperAPIObjectsLimitError extends HyperAPIError { code = 6; description = 'Too many objects requested'; httpStatus = 400; // Bad Request } -export class HyperAPIRateLimitError extends HyperAPIError { +export class HyperAPIRateLimitError extends HyperAPIError { code = 7; description = 'Rate limit exceeded'; httpStatus = 429; // Too Many Requests } -export class HyperAPICaptchaError extends HyperAPIError { +export class HyperAPICaptchaError extends HyperAPIError { code = 8; description = 'Captcha required'; httpStatus = 428; // Precondition Required } -export class HyperAPIBusyError extends HyperAPIError { +export class HyperAPIBusyError extends HyperAPIError { code = 10; description = 'Endpoint is busy'; httpStatus = 503; // Service Unavailable } -export class HyperAPIConfirmationError extends HyperAPIError { +export class HyperAPIConfirmationError extends HyperAPIError { code = 11; description = 'Confirmation required'; httpStatus = 409; // Conflict } -export class HyperAPIOTPError extends HyperAPIError { +export class HyperAPIOTPError extends HyperAPIError { code = 12; description = 'One-time password required'; httpStatus = 401; // Unauthorized } -export class HyperAPIMaintenanceError extends HyperAPIError { +export class HyperAPIMaintenanceError extends HyperAPIError { code = 13; description = 'Endpoint is in maintenance mode'; httpStatus = 503; // Service Unavailable diff --git a/src/driver.js b/src/driver.js deleted file mode 100644 index e4db53b..0000000 --- a/src/driver.js +++ /dev/null @@ -1,29 +0,0 @@ - -import { HyperAPIRequest } from './request.js'; -import { HyperAPIResponse } from './response.js'; - -export class HyperAPIDriver extends EventTarget { - /** - * @param {HyperAPIRequest} request - - * @returns {Promise} - - */ - async processRequest(request) { - const promise = new Promise((resolve) => { - this.addEventListener( - request.response_event_name, - (response) => { - if (response instanceof HyperAPIResponse) { - resolve(response); - } - }, - { - once: true, - }, - ); - }); - - this.dispatchEvent(request); - - return promise; - } -} diff --git a/src/driver.ts b/src/driver.ts new file mode 100644 index 0000000..f9fd077 --- /dev/null +++ b/src/driver.ts @@ -0,0 +1,16 @@ +import type { + HyperAPIRequest, +} from './request'; +import type { HyperAPIResponse } from './response'; +import { + MaybePromise, +} from './utils/types'; + +export type HyperAPIDriverHandler = (request: R) => MaybePromise; + +export interface HyperAPIDriver { + start(handler: HyperAPIDriverHandler): void; + stop(): void; +} + +export type InferDriverRequest = D extends HyperAPIDriver ? R : never; diff --git a/src/error.js b/src/error.js deleted file mode 100644 index 24b0691..0000000 --- a/src/error.js +++ /dev/null @@ -1,78 +0,0 @@ - -/** - * @typedef {object} HyperAPIErrorResponse - * @property {number} code - The error code. - * @property {string} [description] - The error description. - * @property {{[key: string]: any}} [data] - The error data. - */ - -export class HyperAPIError extends Error { - /** - * The error code. - * @type {number} - * @readonly - */ - code; - - /** - * The error description. - * @type {string?} - * @readonly - */ - description = null; - - /** - * The error data. - * @type {{[key: string]: any}} - * @readonly - */ - data; - - /** @type {number?} */ - httpStatus; - - /** @type {Record?} */ - httpHeaders; - - /** - * @param {{[key: string]: any}} [data] The error data. - */ - constructor(data) { - super(); - - if (data !== null && typeof data === 'object') { - this.data = data; - } - else if (data !== undefined) { - throw new TypeError('Argument 0 must be an object or not be provided'); - } - } - - /** - * @returns {string} - - */ - get message() { - return `${this.description ?? ''} (code ${this.code})`; - } - - /** - * Creates response object. - * @returns {HyperAPIErrorResponse} - - */ - getResponse() { - /** @type {HyperAPIErrorResponse} */ - const result = { - code: this.code, - }; - - if (typeof this.description === 'string') { - result.description = this.description; - } - - if (this.data) { - result.data = this.data; - } - - return result; - } -} diff --git a/src/error.test.ts b/src/error.test.ts new file mode 100644 index 0000000..f334213 --- /dev/null +++ b/src/error.test.ts @@ -0,0 +1,17 @@ +/* eslint-disable @typescript-eslint/no-explicit-any */ + +import { + test, + expect, +} from 'vitest'; +import { HyperAPIError } from './error'; + +class HyperAPICustomError extends HyperAPIError { + code = 1001; + description = 'This is a custom error'; +} + +test('custom error', () => { + const error = new HyperAPICustomError(); + expect(error.message).toBe('This is a custom error (code 1001).'); +}); diff --git a/src/error.ts b/src/error.ts new file mode 100644 index 0000000..059a80f --- /dev/null +++ b/src/error.ts @@ -0,0 +1,56 @@ +import { isRecord } from './utils/is-record'; + +interface HyperAPIErrorResponse { + code: number; + description?: string; + data?: Record; +} + +export type ErrorData = Record | undefined; + +export class HyperAPIError< + D extends Record | undefined, +> extends Error { + /** The error code. */ + readonly code: number = 0; + /** The error description. */ + readonly description: string = 'HyperAPI error'; + /** The error data. */ + readonly data?: D; + /** HTTP status code. */ + readonly httpStatus?: number; + /** HTTP headers to return. */ + readonly httpHeaders?: Record; + + constructor(data?: D) { + super(); + + if (isRecord(data)) { + this.data = data; + } + } + + get message() { + return `${this.description} (code ${this.code}).`; + } + + /** + * Creates response object. + * @returns - + */ + getResponse() { + const response: HyperAPIErrorResponse = { + code: this.code, + }; + + if (typeof this.description === 'string') { + response.description = this.description; + } + + if (this.data) { + response.data = this.data; + } + + return response; + } +} diff --git a/src/main.js b/src/main.js deleted file mode 100644 index 38fa077..0000000 --- a/src/main.js +++ /dev/null @@ -1,193 +0,0 @@ - -/** - * @typedef {object} HyperAPIModule - * @property {function(HyperAPIRequest): HyperAPIModuleResponse | Promise} default Core function of the API method. - * @property {function({ [key: string]: any }): { [key: string]: any } | Promise<{ [key: string]: any }>} [argsValidator] - Function that validates `args` property of the HyperAPIRequest. Should return validated args or throw an error. - * @typedef {Record | any[] | undefined} HyperAPIModuleResponse - */ - -import { - dirname, - join as joinPath } from 'node:path'; -import { - HyperAPIInternalError, - HyperAPIUnknownMethodError } from './api-errors.js'; -import { HyperAPIDriver } from './driver.js'; -import { HyperAPIError } from './error.js'; -import { HyperAPIRequest } from './request.js'; -import { HyperAPIResponse } from './response.js'; -import { extractModuleNotFoundPath } from './utils/extract-module-not-found-path.js'; - -const ENTRYPOINT_PATH = dirname(process.argv[1]); - -export class HyperAPI { - /** @type {HyperAPIDriver} The HyperAPI driver. */ - #driver; - - /** @type {string} The root directory for API methods modules. */ - #root; - - /** @type {function(HyperAPIRequest): void} Handles a request. */ - #requestHandler; - - /** - * Creates a HyperAPI instance. - * @param {object} options The options. - * @param {HyperAPIDriver} options.driver The HyperAPI driver. - * @param {string} [options.root] The root directory for API methods modules. Default: `hyper-api` directory alongside the entrypoint script. - */ - constructor({ - driver, - root = joinPath( - ENTRYPOINT_PATH, - 'hyper-api', - ), - }) { - if (driver instanceof HyperAPIDriver !== true) { - throw new TypeError('Property "driver" must be an instance of HyperAPIDriver.'); - } - this.#driver = driver; - - this.#requestHandler = async (request) => { - try { - const response = await this.#handleRequest(request); - - this.#driver.dispatchEvent(response); - } - catch (error) { - // should never happen - console.error('Unexpected error happened:'); - console.error(error); - console.error('This error should not have reached this point.'); - console.error('This is probably a bug in the HyperAPI driver you are using or in the HyperAPI itself.'); - console.error('Now exiting the process.'); - - // eslint-disable-next-line no-process-exit, unicorn/no-process-exit - process.exit(1); - } - }; - - this.#driver.addEventListener( - 'request', - this.#requestHandler, - ); - - this.#root = root; - } - - /** - * Removes the request event listener from the driver. - */ - #turnDriverOff() { - this.#driver.removeEventListener( - 'request', - this.#requestHandler, - ); - } - - /** - * Processes a request and returns the response. - * @param {HyperAPIRequest} request The HyperAPI request. - * @returns {Promise} The HyperAPI response. - */ - async #handleRequest(request) { - try { - const response_data = await this.#useModule(request); - return new HyperAPIResponse( - request, - response_data, - ); - } - catch (error) { - // error must be an instance of HyperAPIError - if (error instanceof HyperAPIError !== true) { - console.error(error); - // eslint-disable-next-line no-ex-assign - error = new HyperAPIInternalError(); - } - - return new HyperAPIResponse( - request, - error, - ); - } - } - - /** - * Processes a request and returns the response. - * @param {HyperAPIRequest} request The HyperAPI request. - * @returns {Promise} The HyperAPI response. - */ - async #getModule(request) { - const filenames = [ - request.module_path, - `${request.module_path}.js`, - `${request.module_path}.mjs`, - `${request.module_path}.cjs`, - joinPath(request.module_path, 'index.js'), - ]; - - for (const filename of filenames) { - const path = joinPath( - this.#root, - filename, - ); - - try { - // eslint-disable-next-line no-await-in-loop - return await import(path); - } - catch (error) { - if (error.code === 'ERR_MODULE_NOT_FOUND') { - const path_not_found = extractModuleNotFoundPath(error); - // skip error only if we cannot found the module itself - if (path === path_not_found) { - continue; - } - } - - // vitest - if ( - error instanceof Error - && error.message.startsWith(`Failed to load url ${path} `) - ) { - continue; - } - - throw error; - } - } - - throw new HyperAPIUnknownMethodError(); - } - - /** - * Processes a request and returns the response. - * @param {HyperAPIRequest} request The HyperAPI request. - * @returns {Promise} The HyperAPI response. - */ - async #useModule(request) { - const module = await this.#getModule(request); - - if (typeof module.argsValidator === 'function') { - // We assign to the readonly property "args" only internally, so we can safely ignore the TS error. - // @ts-ignore - request.args = await module.argsValidator(request.args); - } - - return module.default(request); - } - - /** - * Destroys the HyperAPI instance. - */ - destroy() { - this.#turnDriverOff(); - } -} - -export * from './api-errors.js'; -export { HyperAPIDriver } from './driver.js'; -export { HyperAPIError } from './error.js'; -export { HyperAPIRequest } from './request.js'; -export { HyperAPIResponse } from './response.js'; diff --git a/src/main.test.js b/src/main.test.js deleted file mode 100644 index fe61af5..0000000 --- a/src/main.test.js +++ /dev/null @@ -1,183 +0,0 @@ - -/* eslint-disable jsdoc/require-jsdoc */ - -import { - afterAll, - describe, - test, - expect } from 'vitest'; -import { HyperAPIDriver } from './driver.js'; -import { HyperAPI } from './main.js'; -import { HyperAPIRequest } from './request.js'; - -const driver = new HyperAPIDriver(); -const api = new HyperAPI({ - driver, - root: new URL('../test/api', import.meta.url).pathname, -}); - -async function request(method, args = {}) { - const response = await driver.processRequest( - new HyperAPIRequest( - method, - args, - ), - ); - - return [ - response.is_success, - response.getResponse(), - ]; -} - -afterAll(() => { - api.destroy(); -}); - -describe('HyperAPI', () => { - test('correct request (sync)', async () => { - const result = await request( - 'echo', - { - name: 'world', - }, - ); - - expect(result).toStrictEqual([ - true, - { - message: 'Hello, world!', - }, - ]); - }); - - test('method in directory', async () => { - const result = await request( - 'dir/nested', - ); - - expect(result).toStrictEqual([ - true, - { - ok: true, - }, - ]); - }); - - test('correct request (async)', async () => { - const result = await request( - 'echo.async', - { - name: 'user', - }, - ); - - expect(result).toStrictEqual([ - true, - { - message: 'Hello, user!', - }, - ]); - }); - - test('invalid arguments', async () => { - const result = await request( - 'echo', - { - name: 123, - }, - ); - - expect(result).toStrictEqual([ - false, - { - code: 2, - description: 'One of the parameters specified was missing or invalid', - }, - ]); - }); - - test('missing arguments', async () => { - const result = await request('echo'); - - expect(result).toStrictEqual([ - false, - { - code: 2, - description: 'One of the parameters specified was missing or invalid', - }, - ]); - }); - - test('api error', async () => { - const result = await request('error.api'); - - expect(result).toStrictEqual([ - false, - { - code: 10, - description: 'Endpoint is busy', - }, - ]); - }); - - test('internal error', async () => { - const result = await request('error.internal'); - - expect(result).toStrictEqual([ - false, - { - code: 3, - description: 'Internal error', - }, - ]); - }); - - test('invalid return type', async () => { - const result = await request('error.type'); - - expect(result).toStrictEqual([ - false, - { - code: 3, - description: 'Internal error', - }, - ]); - }); - - test('unknown method', async () => { - const result = await request('error.unknown-method'); - - expect(result).toStrictEqual([ - false, - { - code: 5, - description: 'Unknown method called', - }, - ]); - }); - - test('invalid import path inside module', async () => { - const result = await request('error.import.path'); - - expect(result).toStrictEqual([ - false, - { - code: 3, - description: 'Internal error', - }, - ]); - }); - - test('invalid import field inside module', async () => { - const result = await request('error.import.field'); - - expect(result).toStrictEqual([ - false, - { - code: 3, - description: 'Internal error', - }, - ]); - }); -}); diff --git a/src/main.test.ts b/src/main.test.ts new file mode 100644 index 0000000..79380e5 --- /dev/null +++ b/src/main.test.ts @@ -0,0 +1,184 @@ +import { + afterAll, + describe, + test, + expect, +} from 'vitest'; +import { + driver, + hyperApi, +} from '../test/setup'; + +afterAll(() => { + hyperApi.destroy(); +}); + +describe('routing', () => { + describe('methods', () => { + test('ALL', async () => { + const result = await driver.trigger( + 'GET', + 'echo', + { + name: 'world', + }, + ); + + expect(result).toStrictEqual([ + true, + { + method: 'ALL', + message: 'Hello, world!', + }, + ]); + }); + + test('POST', async () => { + const result = await driver.trigger( + 'POST', + 'echo', + { + name: 'deadbeef', + }, + ); + + expect(result).toStrictEqual([ + true, + { + method: 'POST', + message: 'Hello, deadbeef!', + }, + ]); + }); + }); + + // test('method in directory', async () => { + // const result = await request( + // 'dir/nested', + // ); + + // expect(result).toStrictEqual([ + // true, + // { + // ok: true, + // }, + // ]); + // }); + + // test('correct request (async)', async () => { + // const result = await request( + // 'echo.async', + // { + // name: 'user', + // }, + // ); + + // expect(result).toStrictEqual([ + // true, + // { + // message: 'Hello, user!', + // }, + // ]); + // }); + + // test('invalid arguments', async () => { + // const result = await request( + // 'echo', + // { + // name: 123, + // }, + // ); + + // expect(result).toStrictEqual([ + // false, + // { + // code: 2, + // description: 'One of the parameters specified was missing or invalid', + // }, + // ]); + // }); + + // test('missing arguments', async () => { + // const result = await request('echo'); + + // expect(result).toStrictEqual([ + // false, + // { + // code: 2, + // description: 'One of the parameters specified was missing or invalid', + // }, + // ]); + // }); + + // test('api error', async () => { + // const result = await request('error.api'); + + // expect(result).toStrictEqual([ + // false, + // { + // code: 10, + // description: 'Endpoint is busy', + // }, + // ]); + // }); + + // test('internal error', async () => { + // const result = await request('error.internal'); + + // expect(result).toStrictEqual([ + // false, + // { + // code: 3, + // description: 'Internal error', + // }, + // ]); + // }); + + // test('invalid return type', async () => { + // const result = await request('error.type'); + + // expect(result).toStrictEqual([ + // false, + // { + // code: 3, + // description: 'Internal error', + // }, + // ]); + // }); + + // test('unknown method', async () => { + // const result = await request('error.unknown-method'); + + // expect(result).toStrictEqual([ + // false, + // { + // code: 5, + // description: 'Unknown method called', + // }, + // ]); + // }); + + // test('invalid import path inside module', async () => { + // const result = await request('error.import.path'); + + // expect(result).toStrictEqual([ + // false, + // { + // code: 3, + // description: 'Internal error', + // }, + // ]); + // }); + + // test('invalid import field inside module', async () => { + // const result = await request('error.import.field'); + + // expect(result).toStrictEqual([ + // false, + // { + // code: 3, + // description: 'Internal error', + // }, + // ]); + // }); +}); diff --git a/src/main.ts b/src/main.ts new file mode 100644 index 0000000..8621df0 --- /dev/null +++ b/src/main.ts @@ -0,0 +1,227 @@ + +import nodePath from 'node:path'; +import { + HyperAPIInternalError, + HyperAPIUnknownMethodError, +} from './api-errors'; +import type { + HyperAPIDriver, + InferDriverRequest, +} from './driver'; +import { HyperAPIError } from './error'; +import type { HyperAPIModule } from './module'; +import type { HyperAPIRequest } from './request'; +import type { HyperAPIResponse } from './response'; +import { + createRouter, + useRouter, +} from './router'; +import type { MaybePromise } from './utils/types'; + +interface HyperAPIHandlers< + D extends HyperAPIDriver, + R extends InferDriverRequest, + M extends HyperAPIModule, +> { + transformer: ((driver_request: Readonly>) => MaybePromise) | void; + module: ((request: Readonly, module_: M) => MaybePromise)[]; + response: ((request: R, module_: M, response: HyperAPIResponse) => MaybePromise)[]; +} + +const ENTRYPOINT_PATH = nodePath.dirname(process.argv[1]); + +export class HyperAPI< + D extends HyperAPIDriver, + R extends InferDriverRequest, + M extends HyperAPIModule = HyperAPIModule, +> { + private router: ReturnType; + private driver: D; + + /** + * Creates a HyperAPI instance. + * @param options The options. + * @param options.driver The driver. + * @param [options.root] The root directory for API methods modules. Default: `hyper-api` directory alongside the entrypoint script. + */ + constructor({ + driver, + root = nodePath.join( + ENTRYPOINT_PATH, + 'hyper-api', + ), + }: { + driver: D, + root?: string, + }) { + this.driver = driver; + this.router = createRouter(root); + + this.driver.start(async (driver_request) => { + const [ + request, + module_, + response, + ] = await this.processRequest(driver_request as InferDriverRequest); + + if (request && module_) { + for (const hook of this.handlers.response) { + try { + // eslint-disable-next-line no-await-in-loop + await hook(request, module_, response); + } + catch (error) { + /* eslint-disable no-console */ + console.error('Error in "response" hook:'); + console.error(error); + /* eslint-enable no-console */ + } + } + } + + return response; + }); + } + + private handlers: HyperAPIHandlers = { + transformer: undefined, + module: [], + response: [], + }; + + /** + * Use this hook add properties to the request before it is send to the API module. + * + * This hook can be set only once. + * @param transformer The callback function. + */ + setTransformer(transformer: typeof this.handlers['transformer']) { + if (this.handlers.transformer) { + throw new Error('Transformer has already been set.'); + } + + this.handlers.transformer = transformer; + } + + /** + * Adds a hook to be called when the API module is imported. + * @param callback - + */ + onModule(callback: typeof this.handlers['module'][number]) { + this.handlers.module.push(callback); + } + + /** + * Adds a hook to be called right before the response is sent back. + * + * This hook called only if the request was processed by the API module. If unknown method was requested, this hook is not called. + * @param callback - + */ + onResponse(callback: typeof this.handlers['response'][number]) { + this.handlers.response.push(callback); + } + + private async processRequest(driver_request: InferDriverRequest): Promise<[ R | null, M | null, HyperAPIResponse ]> { + let request: R | null = null; + let module_: M | null = null; + + try { + if (driver_request.path.startsWith('/') !== true) { + driver_request.path = `/${driver_request.path}`; + } + + const router_response = await useRouter( + this.router, + driver_request.method, + driver_request.path, + ); + + if (!router_response) { + return [ + request, + module_, + new HyperAPIUnknownMethodError(), + ]; + } + + driver_request.args = { + ...driver_request.args, + ...router_response.args, + }; + + // Send request to the outside user + request = this.handlers.transformer + ? await this.handlers.transformer(driver_request) + : driver_request as R; + + // IDEA: "onBeforeModule" hook? + + module_ = (await import(router_response.module_path)) as M; + if (module_.argsValidator) { + request.args = module_.argsValidator(request.args); + } + + for (const hook of this.handlers.module) { + // eslint-disable-next-line no-await-in-loop + await hook(request, module_); + } + + // IDEA: "onBeforeExecute" hook? + + const response = await module_.default(request); + + // IDEA: "onExecute" hook? + + return [ + request, + module_, + response, + ]; + } + catch (error) { + if (error instanceof HyperAPIError) { + return [ + request, + module_, + error, + ]; + } + + // eslint-disable-next-line no-console + console.error(error); + + return [ + request, + module_, + new HyperAPIInternalError(), + ]; + } + + throw new Error('Unreachable'); + } + + /** Destroys the HyperAPI instance. */ + destroy() { + this.handlers.transformer = undefined; + this.handlers.module.splice(0); + this.handlers.response.splice(0); + } +} + +export * from './api-errors'; +export type { + HyperAPIDriver, + HyperAPIDriverHandler, +} from './driver'; +export { HyperAPIError } from './error'; +export type { + HyperAPIModule, + // HyperAPIModuleRequest, + // HyperAPIModuleResponse, + InferModule, +} from './module'; +export type { + HyperAPIRequest, + HyperAPIRequestArgs, +} from './request'; +export type { HyperAPIResponse } from './response'; diff --git a/src/module.ts b/src/module.ts new file mode 100644 index 0000000..23b2f0e --- /dev/null +++ b/src/module.ts @@ -0,0 +1,20 @@ +import { HyperAPI } from './main'; +import type { + HyperAPIRequest, + HyperAPIRequestArgs, +} from './request'; +import type { + MaybePromise, +} from './utils/types'; + +export type HyperAPIModuleResponse = Record | unknown[] | undefined; + +export interface HyperAPIModule> { + readonly default: (request: R) => MaybePromise; + readonly argsValidator: (args: unknown) => R extends HyperAPIRequest ? A : never; +} + +// export type HyperAPIModuleRequest> = Parameters[0]; + +// eslint-disable-next-line @typescript-eslint/no-explicit-any +export type InferModule> = H extends HyperAPI ? M : never; diff --git a/src/request.js b/src/request.js deleted file mode 100644 index 9173558..0000000 --- a/src/request.js +++ /dev/null @@ -1,40 +0,0 @@ - -import { randomUUID } from 'node:crypto'; - -/** - * @class HyperAPIRequest - * @template {Record} [HyperAPIRequestArgs={}] - */ -export class HyperAPIRequest extends Event { - /** - * The unique identifier for this request. - * @type {string} - * @readonly - */ - response_event_name = 'response:' + randomUUID(); - - /** - * The relative path to the JavaScript module that contains requested API method. - * @type {string} - * @readonly - */ - module_path; - - /** - * Request arguments to pass to the API method. - * @type {HyperAPIRequestArgs} - * @readonly - */ - args; - - /** - * @param {string} module_path The relative path to the API method module. - * @param {HyperAPIRequestArgs} args The arguments to pass to the API method. - */ - constructor(module_path, args) { - super('request'); - - this.module_path = module_path; - this.args = args; - } -} diff --git a/src/request.ts b/src/request.ts new file mode 100644 index 0000000..0a67ebd --- /dev/null +++ b/src/request.ts @@ -0,0 +1,14 @@ +import type { + EmptyObject, + HTTPMethod, +} from './utils/types'; + +export type HyperAPIRequestArgs = Record; + +export interface HyperAPIRequest< + A extends HyperAPIRequestArgs = EmptyObject, +> { + method: HTTPMethod; + path: string; + args: A; +} diff --git a/src/response.js b/src/response.js deleted file mode 100644 index ed64ae3..0000000 --- a/src/response.js +++ /dev/null @@ -1,50 +0,0 @@ - -import { HyperAPIError } from './error.js'; -import { HyperAPIRequest } from './request.js'; - -export class HyperAPIResponse extends Event { - /** - * Creates a HyperAPI response. - * @param {HyperAPIRequest} request The request. - * @param {HyperAPIError | Record | any[]} value The error or the response value. - */ - constructor(request, value) { - super(request.response_event_name); - - if (value instanceof HyperAPIError) { - this.error = value; - } - else if (value === undefined) { - this.data = {}; - } - else if ( - (value !== null && typeof value === 'object') // object - || Array.isArray(value) // array - ) { - this.data = value; - } - else { - throw new TypeError('Argument 0 must be an instance of HyperAPIError or be an object or an array.'); - } - } - - /** - * @returns {boolean} Whether the response is successful. - * @readonly - */ - get is_success() { - return this.error === undefined; - } - - /** - * Returns response as an object. For example, that can be used as the body of a HTTP response. - * @returns {{[key: string]: *}?} The response. - */ - getResponse() { - if (this.error) { - return this.error.getResponse(); - } - - return this.data; - } -} diff --git a/src/response.ts b/src/response.ts new file mode 100644 index 0000000..e9c75ef --- /dev/null +++ b/src/response.ts @@ -0,0 +1,5 @@ +import { HyperAPIError } from './error'; +import { HyperAPIModuleResponse } from './module'; + +// eslint-disable-next-line @typescript-eslint/no-explicit-any +export type HyperAPIResponse = HyperAPIModuleResponse | HyperAPIError; diff --git a/src/router.ts b/src/router.ts new file mode 100644 index 0000000..9fe18db --- /dev/null +++ b/src/router.ts @@ -0,0 +1,171 @@ +/* eslint-disable n/no-sync */ + +import { + IttyRouter, + type IRequest, + type IttyRouterType, +} from 'itty-router'; +import { readdirSync } from 'node:fs'; +import nodePath from 'node:path'; +import { HTTPMethod } from './utils/types'; + +/** + * Creates new IttyRouter from filesystem. + * @param path The path to scan. + * @returns The new IttyRouter. + */ +export function createRouter(path: string) { + // eslint-disable-next-line new-cap + const router = IttyRouter(); + + scanDirectory(router, path); + + return router; +} + +interface RouterResponse { + module_path: string; + args: Record; +} + +/** + * Fetches data from router. + * @param router The router to fetch data from. + * @param method The HTTP method. + * @param path The path to fetch data from. + * @returns The response. + */ +export function useRouter( + router: IttyRouterType, + method: HTTPMethod, + path: string, +) { + return router.fetch({ + method, + url: `file://${path}`, + }) as Promise; +} + +const REGEXP_FILE_EXTENSION = /\.(js|mjs|cjs|ts)$/; +const REGEXP_HTTP_METHOD = /\.\[(delete|get|head|options|patch|post|put)]$/; +const REGEXP_PATH_SLUG = /\[(\w+)]/g; + +interface Route { + method: Lowercase> | 'all'; + path: string; + module_path: string; +} + +/** + * Scans directory for routes. + * @param router The router to add routes to. + * @param path The path to scan. + * @param [regexp_parts] The parts of the regular expression. + */ +function scanDirectory( + router: IttyRouterType, + path: string, + regexp_parts: string[] = [ '' ], +) { + const result = readdirSync( + path, + { + withFileTypes: true, + }, + ); + + const routes: Record = { + 0: [], // routes with no method and no slug + 1: [], // routes with method and no slug + 2: [], // routes with no method and slug + 3: [], // routes with method and slug + }; + + for (const entry of result) { + const entry_path = nodePath.join( + path, + entry.name, + ); + + if (entry.isFile()) { + let file_name = entry.name; + if (REGEXP_FILE_EXTENSION.test(file_name)) { + file_name = file_name.replace( + REGEXP_FILE_EXTENSION, + '', + ); + + let method: Route['method'] = 'all'; + const method_match = file_name.match(REGEXP_HTTP_METHOD); + const has_method = method_match ? 1 : 0; + if (method_match) { + method = method_match[1] as Exclude; + + file_name = file_name.replace( + REGEXP_HTTP_METHOD, + '', + ); + } + + const has_slug = REGEXP_PATH_SLUG.test(file_name) ? 2 : 0; + file_name = file_name.replaceAll( + REGEXP_PATH_SLUG, + ':$1', + ); + + // console.log( + // entry_path, + // method, + // [ + // ...regexp_parts, + // file_name, + // ].join(nodePath.sep), + // ); + + // eslint-disable-next-line no-bitwise + routes[has_method | has_slug].push({ + method, + path: [ + ...regexp_parts, + file_name, + ].join(nodePath.sep), + module_path: entry_path, + }); + } + } + else { + scanDirectory( + router, + entry_path, + [ + ...regexp_parts, + entry.name.replaceAll( + REGEXP_PATH_SLUG, + ':$1', + ), + ], + ); + } + } + + for ( + const route of [ + ...routes[1], + ...routes[3], + ...routes[0], + ...routes[2], + ] + ) { + router[route.method]( + route.path, + (r) => { + const response: RouterResponse = { + module_path: route.module_path, + args: r.params, + }; + + return response; + }, + ); + } +} diff --git a/src/utils/extract-module-not-found-path.js b/src/utils/extract-module-not-found-path.js deleted file mode 100644 index 41a2ad6..0000000 --- a/src/utils/extract-module-not-found-path.js +++ /dev/null @@ -1,78 +0,0 @@ - -import { - dirname, - join as joinPath } from 'node:path'; - -// typedef does not work for some reason. - -// /** -// * @typedef {Error} ModuleNotFoundError -// * @property {'ERR_MODULE_NOT_FOUND'} code The error code. -// * @property {string} [specifier] - Path to the module that was not found. -// */ -class ModuleNotFoundError extends Error { - /** @type {string} */ - code = 'ERR_MODULE_NOT_FOUND'; - /** @type {string | undefined} */ - specifier; - /** @type {string | URL | undefined} */ - url; -} - -const REGEXP_MODULE_SPECIFIER = /Cannot find module ["'](.+)["'] (?:imported\s)?from/; -const REGEXP_MODULE_REQUESTER = /\s(?:imported\s)?from ["'](.+)["']/; - -/** - * Extracts path from error as is. - * @param {ModuleNotFoundError} error The error. - * @returns {string} The path to the module that was not found. - */ -function extractPath(error) { - // Bun - if (typeof error.specifier === 'string') { - return error.specifier; - } - - // Node 20.6 ... 20.7 - if (error.url instanceof URL) { - return error.url.pathname; - } - - // Node 20.8+ - if (typeof error.url === 'string') { - return new URL(error.url).pathname; - } - - const match = error.message.match(REGEXP_MODULE_SPECIFIER); - if (match !== null) { - return match[1]; - } - - throw error; -} - -/** - * Extracts the path to module-not-found from an ERR_MODULE_NOT_FOUND error. - * @param {ModuleNotFoundError} error The error. - * @returns {string} The path to the module that was not found. - */ -export function extractModuleNotFoundPath(error) { - const path = extractPath(error); - - if (path.startsWith('/')) { - return path; - } - - // Bun returns relative paths, so we have to extract path to the module that requested the missing module from the error message. - const match = error.message.match(REGEXP_MODULE_REQUESTER); - if (match !== null) { - const specifier_from = match[1]; - - return joinPath( - dirname(specifier_from), - path, - ); - } - - throw error; -} diff --git a/src/utils/extract-module-not-found-path.test.js b/src/utils/extract-module-not-found-path.test.js deleted file mode 100644 index 03bd90a..0000000 --- a/src/utils/extract-module-not-found-path.test.js +++ /dev/null @@ -1,93 +0,0 @@ -/* global Bun */ - -import { - beforeAll, - describe, - test, - expect } from 'vitest'; - -const IMAGES = [ - // no fields, extracting path from message - 'node:14-slim', - 'node:16-slim', - 'node:18-slim', - 'node:20.0-slim', - 'node:20.4-slim', - // field "url" as an instance of URL - 'node:20.6-slim', - // field "url" as string - 'node:20.8-slim', - 'node:22-slim', - // bun - 'oven/bun:1.0', - 'oven/bun:1.1.0-slim', - 'oven/bun:1.1.17-slim', -]; - -beforeAll(async () => { - let count = 0; - - await Promise.all( - IMAGES.map((image) => (async () => { - const proc = Bun.spawn([ - 'docker', - 'pull', - image, - ]); - - await proc.exited; - - console.log('pulled', image, `(${++count} of ${IMAGES.length})`); - })()), - ); -}); - -const PATHS = [ - { - title: 'existing module imports non-existing module', - path: './dependency.mjs', - path_expect: '/app/test/err_module_not_found/test.js', - }, - { - title: 'requested module itself does not exist', - path: './not-exists.mjs', - path_expect: '/app/test/err_module_not_found/not-exists.mjs', - }, -]; - -// const ROOT_DIRECTORY = process.cwd(); -// console.log('ROOT_DIRECTORY', ROOT_DIRECTORY); - -for (const { title, path, path_expect } of PATHS) { - describe(title, () => { - for (const image of IMAGES) { - const args = [ - 'docker', - 'run', - '--rm', - '-v', - `${process.cwd()}:/app`, - '-w', - '/app', - image, - 'test/err_module_not_found/main.mjs', - ]; - - test(image, async () => { - const proc = Bun.spawn([ - ...args, - path, - ]); - - await proc.exited; - - expect(proc.exitCode).toBe(0); - - const stdout = await new Response(proc.stdout).text(); - const path_received = stdout.trim(); - - expect(path_received).toBe(path_expect); - }); - } - }); -} diff --git a/src/utils/is-record.ts b/src/utils/is-record.ts new file mode 100644 index 0000000..a7e9ae0 --- /dev/null +++ b/src/utils/is-record.ts @@ -0,0 +1,12 @@ +/** + * Check if a value is a record. + * @param value - + * @returns - + */ +export function isRecord(value: unknown): value is Record { + return typeof value === 'object' + && value !== null + && !Array.isArray(value) + && value.constructor === Object + && Object.prototype.toString.call(value) === '[object Object]'; +} diff --git a/src/utils/types.ts b/src/utils/types.ts new file mode 100644 index 0000000..fd4b055 --- /dev/null +++ b/src/utils/types.ts @@ -0,0 +1,4 @@ +export type EmptyObject = Omit<{ p: never }, 'p'>; +export type MaybePromise = T | Promise; + +export type HTTPMethod = 'DELETE' | 'GET' | 'HEAD' | 'OPTIONS' | 'PATCH' | 'POST' | 'PUT' | 'UNKNOWN'; diff --git a/test/api/dir/nested.js b/test/api/dir/nested.js deleted file mode 100644 index f3f3acf..0000000 --- a/test/api/dir/nested.js +++ /dev/null @@ -1,8 +0,0 @@ - -/* eslint-disable jsdoc/require-jsdoc */ - -export default function () { - return { - ok: true, - }; -} diff --git a/test/api/echo.async.js b/test/api/echo.async.js deleted file mode 100644 index cbbf1f3..0000000 --- a/test/api/echo.async.js +++ /dev/null @@ -1,24 +0,0 @@ - -/* eslint-disable jsdoc/require-jsdoc */ - -export default async function (request) { - await new Promise((resolve) => { - setTimeout( - resolve, - 10, - ); - }); - - return { - message: `Hello, ${request.args.name}!`, - }; -} - -import * as v from 'valibot'; -import { valibot } from '../validator.js'; - -export const argsValidator = valibot.bind( - v.strictObject({ - name: v.string(), - }), -); diff --git a/test/api/echo.js b/test/api/echo.js deleted file mode 100644 index 45a46a6..0000000 --- a/test/api/echo.js +++ /dev/null @@ -1,17 +0,0 @@ - -/* eslint-disable jsdoc/require-jsdoc */ - -export default function (request) { - return { - message: `Hello, ${request.args.name}!`, - }; -} - -import * as v from 'valibot'; -import { valibot } from '../validator.js'; - -export const argsValidator = valibot.bind( - v.strictObject({ - name: v.string(), - }), -); diff --git a/test/api/error.api.js b/test/api/error.api.js deleted file mode 100644 index 97cd4bd..0000000 --- a/test/api/error.api.js +++ /dev/null @@ -1,7 +0,0 @@ -/* eslint-disable jsdoc/require-jsdoc */ - -import { HyperAPIBusyError } from '../../src/api-errors.js'; - -export default function () { - throw new HyperAPIBusyError(); -} diff --git a/test/api/error.import.field.js b/test/api/error.import.field.js deleted file mode 100644 index 35a970d..0000000 --- a/test/api/error.import.field.js +++ /dev/null @@ -1,12 +0,0 @@ -/* eslint-disable jsdoc/require-jsdoc */ - -// eslint-disable-next-line import/named -import { deadbeef } from '../validator.js'; - -export default function () { - return true; -} - -export function _() { - return deadbeef; -} diff --git a/test/api/error.import.path.js b/test/api/error.import.path.js deleted file mode 100644 index 3854034..0000000 --- a/test/api/error.import.path.js +++ /dev/null @@ -1,8 +0,0 @@ -/* eslint-disable jsdoc/require-jsdoc */ - -// eslint-disable-next-line import/no-unresolved -import { foo } from '../invalid.js'; - -export default function () { - return foo; -} diff --git a/test/api/error.type.js b/test/api/error.type.js deleted file mode 100644 index 1b124e9..0000000 --- a/test/api/error.type.js +++ /dev/null @@ -1,5 +0,0 @@ -/* eslint-disable jsdoc/require-jsdoc */ - -export default function () { - return true; -} diff --git a/test/err_module_not_found/dependency.mjs b/test/err_module_not_found/dependency.mjs deleted file mode 100644 index 186ad66..0000000 --- a/test/err_module_not_found/dependency.mjs +++ /dev/null @@ -1,3 +0,0 @@ - -// eslint-disable-next-line import/no-unresolved, no-unused-vars -import * as v from './test.js'; diff --git a/test/err_module_not_found/main.mjs b/test/err_module_not_found/main.mjs deleted file mode 100644 index e227079..0000000 --- a/test/err_module_not_found/main.mjs +++ /dev/null @@ -1,14 +0,0 @@ - -import { extractModuleNotFoundPath } from '../../src/utils/extract-module-not-found-path.js'; - -try { - await import(process.argv[2]); - - // eslint-disable-next-line no-process-exit, unicorn/no-process-exit - process.exit(128); -} -catch (error) { - console.log( - extractModuleNotFoundPath(error), - ); -} diff --git a/test/hyper-api/echo.[post].ts b/test/hyper-api/echo.[post].ts new file mode 100644 index 0000000..1013f02 --- /dev/null +++ b/test/hyper-api/echo.[post].ts @@ -0,0 +1,26 @@ +/* eslint-disable jsdoc/require-jsdoc */ + +import * as v from 'valibot'; +import type { + HyperAPIRequest, + HyperAPIResponse, + InferModule, +} from '../../src/main'; +import { hyperApi } from '../setup'; + +type Module = InferModule; + +export default function (request: HyperAPIRequest>): HyperAPIResponse { + return { + method: 'POST', + message: `Hello, ${request.args.name}!`, + }; +} + +export const argsValidator = v.parser( + v.strictObject({ + name: v.string(), + }), +); + +export const auth: Module['auth'] = true; diff --git a/test/hyper-api/echo.ts b/test/hyper-api/echo.ts new file mode 100644 index 0000000..2066b16 --- /dev/null +++ b/test/hyper-api/echo.ts @@ -0,0 +1,18 @@ +/* eslint-disable jsdoc/require-jsdoc */ + +import * as v from 'valibot'; +import { type HyperAPIResponse } from '../../src/main'; +import { type LocalRequest } from '../setup'; + +export default function (request: LocalRequest>): HyperAPIResponse { + return { + method: 'ALL', + message: `Hello, ${request.args.name}!`, + }; +} + +export const argsValidator = v.parser( + v.strictObject({ + name: v.string(), + }), +); diff --git a/test/hyper-api/errors/api.test.ts b/test/hyper-api/errors/api.test.ts new file mode 100644 index 0000000..890778c --- /dev/null +++ b/test/hyper-api/errors/api.test.ts @@ -0,0 +1,44 @@ + +import { + expect, + test, +} from 'vitest'; +import { driver } from '../../setup'; + +test('error', async () => { + const result = await driver.trigger( + 'GET', + 'errors/api', + ); + + expect(result).toStrictEqual([ + false, + { + code: 10, + description: 'Endpoint is busy', + }, + ]); +}); + +test('error with data', async () => { + const result = await driver.trigger( + 'GET', + 'errors/api', + { + error_data: { + foo: 'bar', + }, + }, + ); + + expect(result).toStrictEqual([ + false, + { + code: 10, + description: 'Endpoint is busy', + data: { + foo: 'bar', + }, + }, + ]); +}); diff --git a/test/hyper-api/errors/api.ts b/test/hyper-api/errors/api.ts new file mode 100644 index 0000000..6356165 --- /dev/null +++ b/test/hyper-api/errors/api.ts @@ -0,0 +1,27 @@ +/* eslint-disable jsdoc/require-jsdoc */ + +import * as v from 'valibot'; +import { HyperAPIBusyError } from '../../../src/api-errors'; +import { type LocalRequest } from '../../setup'; + +export default function (request: LocalRequest>) { + throw new HyperAPIBusyError( + Object.keys(request.args.error_data).length > 0 + ? request.args.error_data + : undefined, + ); +} + +export const argsValidator = v.parser( + v.strictObject({ + error_data: v.optional( + v.record( + v.string(), + v.any(), + ), + () => { + return {}; + }, + ), + }), +); diff --git a/test/hyper-api/errors/internal.test.ts b/test/hyper-api/errors/internal.test.ts new file mode 100644 index 0000000..6c75021 --- /dev/null +++ b/test/hyper-api/errors/internal.test.ts @@ -0,0 +1,21 @@ + +import { + expect, + test, +} from 'vitest'; +import { driver } from '../../setup'; + +test('internal error', async () => { + const result = await driver.trigger( + 'GET', + 'errors/internal', + ); + + expect(result).toStrictEqual([ + false, + { + code: 3, + description: 'Internal error', + }, + ]); +}); diff --git a/test/api/error.internal.js b/test/hyper-api/errors/internal.ts similarity index 100% rename from test/api/error.internal.js rename to test/hyper-api/errors/internal.ts diff --git a/test/setup.ts b/test/setup.ts new file mode 100644 index 0000000..4e29ce0 --- /dev/null +++ b/test/setup.ts @@ -0,0 +1,125 @@ +import { + HyperAPI, + HyperAPIDriver, + HyperAPIDriverHandler, + HyperAPIError, + HyperAPIModule, + HyperAPIRequest, + HyperAPIRequestArgs, +} from '../src/main'; +import type { + EmptyObject, + HTTPMethod, +} from '../src/utils/types'; + +interface DriverRequest extends HyperAPIRequest { + foo: string; +} + +class HyperAPITestDriver implements HyperAPIDriver { + private handler: HyperAPIDriverHandler | null = null; + + start(handler: HyperAPIDriverHandler): void { + this.handler = handler; + } + + stop(): void { + this.handler = null; + } + + async trigger( + method: HTTPMethod, + path: string, + args: Record = {}, + ): Promise<[ boolean, unknown ]> { + if (!this.handler) { + throw new Error('No handler available.'); + } + + const response = await this.handler({ + method, + path, + args, + foo: 'bar', + }); + + if (response instanceof HyperAPIError) { + return [ + false, + response.getResponse(), + ]; + } + + return [ + true, + response, + ]; + } +} + +export const driver = new HyperAPITestDriver(); + +export interface LocalRequest extends DriverRequest { + bar: number; +} + +export interface LocalModule extends HyperAPIModule { + auth: boolean; +} + +export const hyperApi_simple = new HyperAPI({ + driver, + root: new URL('../test/hyper-api', import.meta.url).pathname, +}); + +export const hyperApi = new HyperAPI< + typeof driver, + LocalRequest, + LocalModule +>({ + driver, + root: new URL('../test/hyper-api', import.meta.url).pathname, +}); + +/* eslint-disable @typescript-eslint/no-unused-vars */ + +hyperApi.setTransformer((request) => { + const { + foo, + // @ts-expect-error Accessing property that does not exist on DriverRequest + bar, + } = request; + + return { + ...request, + bar: 10, + }; +}); + +hyperApi.onModule((request, module) => { + const { + foo, + bar, + } = request; + + const { + default: default_, + argsValidator, + auth, + } = module; +}); + +hyperApi.onResponse((request, module) => { + const { + foo, + bar, + } = request; + + const { + default: default_, + argsValidator, + auth, + } = module; +}); + +/* eslint-enable @typescript-eslint/no-unused-vars */ diff --git a/test/validator.js b/test/validator.js deleted file mode 100644 index e539afe..0000000 --- a/test/validator.js +++ /dev/null @@ -1,24 +0,0 @@ - -import { - parse, - ValiError } from 'valibot'; -import { HyperAPIInvalidParametersError } from '../src/api-errors.js'; - -/** - * Validates the given value using Valibot schema. - * @param {any} value The value to validate. - * @returns {any} The validated value. - */ -export function valibot(value) { - try { - return parse(this, value); - } - catch (error) { - if (error instanceof ValiError) { - // console.error(error); - throw new HyperAPIInvalidParametersError(); - } - - throw error; - } -} diff --git a/tsconfig.json b/tsconfig.json index 79c8b45..c00281e 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -1,18 +1,27 @@ { - "compilerOptions": { - "target": "es2022", - "noImplicitAny": true, - "checkJs": true, - "allowJs": true, - "module": "ESNext", - "moduleResolution": "node" - }, + "compileOnSave": false, "include": [ - "src/**/*" + "src/", + "test/" ], "exclude": [ - "node_modules/", "dist/", - "**/*.test.*" - ] + "node_modules/" + ], + "compilerOptions": { + "outDir": "dist/esm", + "declaration": true, + "declarationDir": "dist/esm", + "target": "esnext", + "module": "esnext", + "lib": [ + "ESNext", + "ES2021.String" + ], + "moduleResolution": "node", + "allowSyntheticDefaultImports": true, + "skipLibCheck": true, + "strict": true, + "removeComments": false + } } diff --git a/types/api-errors.d.ts b/types/api-errors.d.ts deleted file mode 100644 index d9f64ad..0000000 --- a/types/api-errors.d.ts +++ /dev/null @@ -1,49 +0,0 @@ -export class HyperAPIAuthorizationError extends HyperAPIError { - code: number; - description: string; -} -export class HyperAPIInvalidParametersError extends HyperAPIError { - code: number; - description: string; -} -export class HyperAPIInternalError extends HyperAPIError { - code: number; - description: string; -} -export class HyperAPIForbiddenError extends HyperAPIError { - code: number; - description: string; -} -export class HyperAPIUnknownMethodError extends HyperAPIError { - code: number; - description: string; -} -export class HyperAPIObjectsLimitError extends HyperAPIError { - code: number; - description: string; -} -export class HyperAPIRateLimitError extends HyperAPIError { - code: number; - description: string; -} -export class HyperAPICaptchaError extends HyperAPIError { - code: number; - description: string; -} -export class HyperAPIBusyError extends HyperAPIError { - code: number; - description: string; -} -export class HyperAPIConfirmationError extends HyperAPIError { - code: number; - description: string; -} -export class HyperAPIOTPError extends HyperAPIError { - code: number; - description: string; -} -export class HyperAPIMaintenanceError extends HyperAPIError { - code: number; - description: string; -} -import { HyperAPIError } from './error.js'; diff --git a/types/driver.d.ts b/types/driver.d.ts deleted file mode 100644 index d0689aa..0000000 --- a/types/driver.d.ts +++ /dev/null @@ -1,9 +0,0 @@ -export class HyperAPIDriver extends EventTarget { - /** - * @param {HyperAPIRequest} request - - * @returns {Promise} - - */ - processRequest(request: HyperAPIRequest): Promise; -} -import { HyperAPIRequest } from './request.js'; -import { HyperAPIResponse } from './response.js'; diff --git a/types/error.d.ts b/types/error.d.ts deleted file mode 100644 index ab22e20..0000000 --- a/types/error.d.ts +++ /dev/null @@ -1,63 +0,0 @@ -/** - * @typedef {object} HyperAPIErrorResponse - * @property {number} code - The error code. - * @property {string} [description] - The error description. - * @property {{[key: string]: any}} [data] - The error data. - */ -export class HyperAPIError extends Error { - /** - * @param {{[key: string]: any}} [data] The error data. - */ - constructor(data?: { - [key: string]: any; - }); - /** - * The error code. - * @type {number} - * @readonly - */ - readonly code: number; - /** - * The error description. - * @type {string?} - * @readonly - */ - readonly description: string | null; - /** - * The error data. - * @type {{[key: string]: any}} - * @readonly - */ - readonly data: { - [key: string]: any; - }; - /** @type {number?} */ - httpStatus: number | null; - /** @type {Record?} */ - httpHeaders: Record | null; - /** - * @returns {string} - - */ - get message(): string; - /** - * Creates response object. - * @returns {HyperAPIErrorResponse} - - */ - getResponse(): HyperAPIErrorResponse; -} -export type HyperAPIErrorResponse = { - /** - * - The error code. - */ - code: number; - /** - * - The error description. - */ - description?: string; - /** - * - The error data. - */ - data?: { - [key: string]: any; - }; -}; diff --git a/types/main.d.ts b/types/main.d.ts deleted file mode 100644 index 7e6d90e..0000000 --- a/types/main.d.ts +++ /dev/null @@ -1,41 +0,0 @@ -export class HyperAPI { - /** - * Creates a HyperAPI instance. - * @param {object} options The options. - * @param {HyperAPIDriver} options.driver The HyperAPI driver. - * @param {string} [options.root] The root directory for API methods modules. Default: `hyper-api` directory alongside the entrypoint script. - */ - constructor({ driver, root, }: { - driver: HyperAPIDriver; - root?: string; - }); - /** - * Destroys the HyperAPI instance. - */ - destroy(): void; - #private; -} -export * from "./api-errors.js"; -export { HyperAPIDriver } from "./driver.js"; -export { HyperAPIError } from "./error.js"; -export { HyperAPIRequest } from "./request.js"; -export { HyperAPIResponse } from "./response.js"; -export type HyperAPIModule = { - /** - * Core function of the API method. - */ - default: (arg0: HyperAPIRequest) => HyperAPIModuleResponse | Promise; - /** - * - Function that validates `args` property of the HyperAPIRequest. Should return validated args or throw an error. - */ - argsValidator?: (arg0: { - [key: string]: any; - }) => { - [key: string]: any; - } | Promise<{ - [key: string]: any; - }>; -}; -export type HyperAPIModuleResponse = Record | any[] | undefined; -import { HyperAPIDriver } from './driver.js'; -import { HyperAPIRequest } from './request.js'; diff --git a/types/request.d.ts b/types/request.d.ts deleted file mode 100644 index 2966b59..0000000 --- a/types/request.d.ts +++ /dev/null @@ -1,29 +0,0 @@ -/** - * @class HyperAPIRequest - * @template {Record} [HyperAPIRequestArgs={}] - */ -export class HyperAPIRequest = {}> extends Event { - /** - * @param {string} module_path The relative path to the API method module. - * @param {HyperAPIRequestArgs} args The arguments to pass to the API method. - */ - constructor(module_path: string, args: HyperAPIRequestArgs); - /** - * The unique identifier for this request. - * @type {string} - * @readonly - */ - readonly response_event_name: string; - /** - * The relative path to the JavaScript module that contains requested API method. - * @type {string} - * @readonly - */ - readonly module_path: string; - /** - * Request arguments to pass to the API method. - * @type {HyperAPIRequestArgs} - * @readonly - */ - readonly args: HyperAPIRequestArgs; -} diff --git a/types/response.d.ts b/types/response.d.ts deleted file mode 100644 index f5d17f1..0000000 --- a/types/response.d.ts +++ /dev/null @@ -1,24 +0,0 @@ -export class HyperAPIResponse extends Event { - /** - * Creates a HyperAPI response. - * @param {HyperAPIRequest} request The request. - * @param {HyperAPIError | Record | any[]} value The error or the response value. - */ - constructor(request: HyperAPIRequest, value: HyperAPIError | Record | any[]); - error: HyperAPIError; - data: any[] | Record; - /** - * @returns {boolean} Whether the response is successful. - * @readonly - */ - readonly get is_success(): boolean; - /** - * Returns response as an object. For example, that can be used as the body of a HTTP response. - * @returns {{[key: string]: *}?} The response. - */ - getResponse(): { - [key: string]: any; - } | null; -} -import { HyperAPIError } from './error.js'; -import { HyperAPIRequest } from './request.js'; diff --git a/types/utils/extract-module-not-found-path.d.ts b/types/utils/extract-module-not-found-path.d.ts deleted file mode 100644 index d6afbf3..0000000 --- a/types/utils/extract-module-not-found-path.d.ts +++ /dev/null @@ -1,15 +0,0 @@ -/** - * Extracts the path to module-not-found from an ERR_MODULE_NOT_FOUND error. - * @param {ModuleNotFoundError} error The error. - * @returns {string} The path to the module that was not found. - */ -export function extractModuleNotFoundPath(error: ModuleNotFoundError): string; -declare class ModuleNotFoundError extends Error { - /** @type {string} */ - code: string; - /** @type {string | undefined} */ - specifier: string | undefined; - /** @type {string | URL | undefined} */ - url: string | URL | undefined; -} -export {}; From be706f2e54937fbe2ce3c3626493349f2f6b309b Mon Sep 17 00:00:00 2001 From: Daniil Kirichenko Date: Tue, 17 Sep 2024 13:19:35 +0300 Subject: [PATCH 16/57] Create npm-publish.yml --- .github/workflows/npm-publish.yml | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) create mode 100644 .github/workflows/npm-publish.yml diff --git a/.github/workflows/npm-publish.yml b/.github/workflows/npm-publish.yml new file mode 100644 index 0000000..1027d77 --- /dev/null +++ b/.github/workflows/npm-publish.yml @@ -0,0 +1,20 @@ +name: Publish NPM Package + +on: + - push + +jobs: + build: + runs-on: ubuntu-latest + permissions: + contents: read + id-token: write + steps: + - uses: actions/checkout@v4 + - uses: kirick13/build-npm-package-action@v1 + with: + npm-token: ${{ secrets.NPM_TOKEN }} + - uses: kirick13/notify-action@v1 + with: + telegram-bot-token: ${{ secrets.TELEGRAM_BOT_TOKEN }} + telegram-chat-id: ${{ secrets.TELEGRAM_CHAT_ID }} From b20b483e1d2134c5c8c251b21bc2e45f5e108745 Mon Sep 17 00:00:00 2001 From: Daniil Kirichenko Date: Tue, 17 Sep 2024 13:30:07 +0300 Subject: [PATCH 17/57] Removed `dist` from repo --- dist/esm/api-errors.d.ts | 61 ------ dist/esm/api-errors.js | 61 ------ dist/esm/driver.d.ts | 9 - dist/esm/driver.js | 1 - dist/esm/error.d.ts | 26 --- dist/esm/error.js | 38 ---- dist/esm/error.test.d.ts | 1 - dist/esm/error.test.js | 11 - dist/esm/main.d.ts | 46 ---- dist/esm/main.js | 137 ------------ dist/esm/main.test.d.ts | 1 - dist/esm/main.test.js | 143 ------------- dist/esm/module.d.ts | 9 - dist/esm/module.js | 1 - dist/esm/request.d.ts | 7 - dist/esm/request.js | 1 - dist/esm/response.d.ts | 3 - dist/esm/response.js | 1 - dist/esm/router.d.ts | 21 -- dist/esm/router.js | 103 --------- dist/esm/utils/is-record.d.ts | 6 - dist/esm/utils/is-record.js | 12 -- dist/esm/utils/types.d.ts | 5 - dist/esm/utils/types.js | 1 - dist/main.cjs | 383 ---------------------------------- package.json | 4 +- 26 files changed, 2 insertions(+), 1090 deletions(-) delete mode 100644 dist/esm/api-errors.d.ts delete mode 100644 dist/esm/api-errors.js delete mode 100644 dist/esm/driver.d.ts delete mode 100644 dist/esm/driver.js delete mode 100644 dist/esm/error.d.ts delete mode 100644 dist/esm/error.js delete mode 100644 dist/esm/error.test.d.ts delete mode 100644 dist/esm/error.test.js delete mode 100644 dist/esm/main.d.ts delete mode 100644 dist/esm/main.js delete mode 100644 dist/esm/main.test.d.ts delete mode 100644 dist/esm/main.test.js delete mode 100644 dist/esm/module.d.ts delete mode 100644 dist/esm/module.js delete mode 100644 dist/esm/request.d.ts delete mode 100644 dist/esm/request.js delete mode 100644 dist/esm/response.d.ts delete mode 100644 dist/esm/response.js delete mode 100644 dist/esm/router.d.ts delete mode 100644 dist/esm/router.js delete mode 100644 dist/esm/utils/is-record.d.ts delete mode 100644 dist/esm/utils/is-record.js delete mode 100644 dist/esm/utils/types.d.ts delete mode 100644 dist/esm/utils/types.js delete mode 100644 dist/main.cjs diff --git a/dist/esm/api-errors.d.ts b/dist/esm/api-errors.d.ts deleted file mode 100644 index 2c5289c..0000000 --- a/dist/esm/api-errors.d.ts +++ /dev/null @@ -1,61 +0,0 @@ -import { type ErrorData, HyperAPIError } from './error'; -export declare class HyperAPIAuthorizationError extends HyperAPIError { - code: number; - description: string; - httpStatus: number; -} -export declare class HyperAPIInvalidParametersError extends HyperAPIError { - code: number; - description: string; - httpStatus: number; -} -export declare class HyperAPIInternalError extends HyperAPIError { - code: number; - description: string; - httpStatus: number; -} -export declare class HyperAPIForbiddenError extends HyperAPIError { - code: number; - description: string; - httpStatus: number; -} -export declare class HyperAPIUnknownMethodError extends HyperAPIError { - code: number; - description: string; - httpStatus: number; -} -export declare class HyperAPIObjectsLimitError extends HyperAPIError { - code: number; - description: string; - httpStatus: number; -} -export declare class HyperAPIRateLimitError extends HyperAPIError { - code: number; - description: string; - httpStatus: number; -} -export declare class HyperAPICaptchaError extends HyperAPIError { - code: number; - description: string; - httpStatus: number; -} -export declare class HyperAPIBusyError extends HyperAPIError { - code: number; - description: string; - httpStatus: number; -} -export declare class HyperAPIConfirmationError extends HyperAPIError { - code: number; - description: string; - httpStatus: number; -} -export declare class HyperAPIOTPError extends HyperAPIError { - code: number; - description: string; - httpStatus: number; -} -export declare class HyperAPIMaintenanceError extends HyperAPIError { - code: number; - description: string; - httpStatus: number; -} diff --git a/dist/esm/api-errors.js b/dist/esm/api-errors.js deleted file mode 100644 index 0d92728..0000000 --- a/dist/esm/api-errors.js +++ /dev/null @@ -1,61 +0,0 @@ -import { HyperAPIError, } from './error'; -export class HyperAPIAuthorizationError extends HyperAPIError { - code = 1; - description = 'Authorization error'; - httpStatus = 401; // Unauthorized -} -export class HyperAPIInvalidParametersError extends HyperAPIError { - code = 2; - description = 'One of the parameters specified was missing or invalid'; - httpStatus = 400; // Bad Request -} -export class HyperAPIInternalError extends HyperAPIError { - code = 3; - description = 'Internal error'; - httpStatus = 500; // Internal Server Error -} -export class HyperAPIForbiddenError extends HyperAPIError { - code = 4; - description = 'You do not have permission to perform this action'; - httpStatus = 403; // Forbidden -} -export class HyperAPIUnknownMethodError extends HyperAPIError { - code = 5; - description = 'Unknown method called'; - httpStatus = 404; // Not Found -} -export class HyperAPIObjectsLimitError extends HyperAPIError { - code = 6; - description = 'Too many objects requested'; - httpStatus = 400; // Bad Request -} -export class HyperAPIRateLimitError extends HyperAPIError { - code = 7; - description = 'Rate limit exceeded'; - httpStatus = 429; // Too Many Requests -} -export class HyperAPICaptchaError extends HyperAPIError { - code = 8; - description = 'Captcha required'; - httpStatus = 428; // Precondition Required -} -export class HyperAPIBusyError extends HyperAPIError { - code = 10; - description = 'Endpoint is busy'; - httpStatus = 503; // Service Unavailable -} -export class HyperAPIConfirmationError extends HyperAPIError { - code = 11; - description = 'Confirmation required'; - httpStatus = 409; // Conflict -} -export class HyperAPIOTPError extends HyperAPIError { - code = 12; - description = 'One-time password required'; - httpStatus = 401; // Unauthorized -} -export class HyperAPIMaintenanceError extends HyperAPIError { - code = 13; - description = 'Endpoint is in maintenance mode'; - httpStatus = 503; // Service Unavailable -} diff --git a/dist/esm/driver.d.ts b/dist/esm/driver.d.ts deleted file mode 100644 index 9360e63..0000000 --- a/dist/esm/driver.d.ts +++ /dev/null @@ -1,9 +0,0 @@ -import type { HyperAPIRequest } from './request'; -import type { HyperAPIResponse } from './response'; -import { MaybePromise } from './utils/types'; -export type HyperAPIDriverHandler = (request: R) => MaybePromise; -export interface HyperAPIDriver { - start(handler: HyperAPIDriverHandler): void; - stop(): void; -} -export type InferDriverRequest = D extends HyperAPIDriver ? R : never; diff --git a/dist/esm/driver.js b/dist/esm/driver.js deleted file mode 100644 index cb0ff5c..0000000 --- a/dist/esm/driver.js +++ /dev/null @@ -1 +0,0 @@ -export {}; diff --git a/dist/esm/error.d.ts b/dist/esm/error.d.ts deleted file mode 100644 index 279e608..0000000 --- a/dist/esm/error.d.ts +++ /dev/null @@ -1,26 +0,0 @@ -interface HyperAPIErrorResponse { - code: number; - description?: string; - data?: Record; -} -export type ErrorData = Record | undefined; -export declare class HyperAPIError | undefined> extends Error { - /** The error code. */ - readonly code: number; - /** The error description. */ - readonly description: string; - /** The error data. */ - readonly data?: D; - /** HTTP status code. */ - readonly httpStatus?: number; - /** HTTP headers to return. */ - readonly httpHeaders?: Record; - constructor(data?: D); - get message(): string; - /** - * Creates response object. - * @returns - - */ - getResponse(): HyperAPIErrorResponse; -} -export {}; diff --git a/dist/esm/error.js b/dist/esm/error.js deleted file mode 100644 index 353bfa6..0000000 --- a/dist/esm/error.js +++ /dev/null @@ -1,38 +0,0 @@ -import { isRecord } from './utils/is-record'; -export class HyperAPIError extends Error { - /** The error code. */ - code = 0; - /** The error description. */ - description = 'HyperAPI error'; - /** The error data. */ - data; - /** HTTP status code. */ - httpStatus; - /** HTTP headers to return. */ - httpHeaders; - constructor(data) { - super(); - if (isRecord(data)) { - this.data = data; - } - } - get message() { - return `${this.description} (code ${this.code}).`; - } - /** - * Creates response object. - * @returns - - */ - getResponse() { - const response = { - code: this.code, - }; - if (typeof this.description === 'string') { - response.description = this.description; - } - if (this.data) { - response.data = this.data; - } - return response; - } -} diff --git a/dist/esm/error.test.d.ts b/dist/esm/error.test.d.ts deleted file mode 100644 index cb0ff5c..0000000 --- a/dist/esm/error.test.d.ts +++ /dev/null @@ -1 +0,0 @@ -export {}; diff --git a/dist/esm/error.test.js b/dist/esm/error.test.js deleted file mode 100644 index 8dbb23b..0000000 --- a/dist/esm/error.test.js +++ /dev/null @@ -1,11 +0,0 @@ -/* eslint-disable @typescript-eslint/no-explicit-any */ -import { test, expect, } from 'vitest'; -import { HyperAPIError } from './error'; -class HyperAPICustomError extends HyperAPIError { - code = 1001; - description = 'This is a custom error'; -} -test('custom error', () => { - const error = new HyperAPICustomError(); - expect(error.message).toBe('This is a custom error (code 1001).'); -}); diff --git a/dist/esm/main.d.ts b/dist/esm/main.d.ts deleted file mode 100644 index c6d48d4..0000000 --- a/dist/esm/main.d.ts +++ /dev/null @@ -1,46 +0,0 @@ -import type { HyperAPIDriver, InferDriverRequest } from './driver'; -import type { HyperAPIModule } from './module'; -import type { HyperAPIRequest } from './request'; -export declare class HyperAPI, R extends InferDriverRequest, M extends HyperAPIModule = HyperAPIModule> { - private router; - private driver; - /** - * Creates a HyperAPI instance. - * @param options The options. - * @param options.driver The driver. - * @param [options.root] The root directory for API methods modules. Default: `hyper-api` directory alongside the entrypoint script. - */ - constructor({ driver, root, }: { - driver: D; - root?: string; - }); - private handlers; - /** - * Use this hook add properties to the request before it is send to the API module. - * - * This hook can be set only once. - * @param transformer The callback function. - */ - setTransformer(transformer: typeof this.handlers['transformer']): void; - /** - * Adds a hook to be called when the API module is imported. - * @param callback - - */ - onModule(callback: typeof this.handlers['module'][number]): void; - /** - * Adds a hook to be called right before the response is sent back. - * - * This hook called only if the request was processed by the API module. If unknown method was requested, this hook is not called. - * @param callback - - */ - onResponse(callback: typeof this.handlers['response'][number]): void; - private processRequest; - /** Destroys the HyperAPI instance. */ - destroy(): void; -} -export * from './api-errors'; -export type { HyperAPIDriver, HyperAPIDriverHandler, } from './driver'; -export { HyperAPIError } from './error'; -export type { HyperAPIModule, InferModule, } from './module'; -export type { HyperAPIRequest, HyperAPIRequestArgs, } from './request'; -export type { HyperAPIResponse } from './response'; diff --git a/dist/esm/main.js b/dist/esm/main.js deleted file mode 100644 index 48660b9..0000000 --- a/dist/esm/main.js +++ /dev/null @@ -1,137 +0,0 @@ -import nodePath from 'node:path'; -import { HyperAPIInternalError, HyperAPIUnknownMethodError, } from './api-errors'; -import { HyperAPIError } from './error'; -import { createRouter, useRouter, } from './router'; -const ENTRYPOINT_PATH = nodePath.dirname(process.argv[1]); -export class HyperAPI { - router; - driver; - /** - * Creates a HyperAPI instance. - * @param options The options. - * @param options.driver The driver. - * @param [options.root] The root directory for API methods modules. Default: `hyper-api` directory alongside the entrypoint script. - */ - constructor({ driver, root = nodePath.join(ENTRYPOINT_PATH, 'hyper-api'), }) { - this.driver = driver; - this.router = createRouter(root); - this.driver.start(async (driver_request) => { - const [request, module_, response,] = await this.processRequest(driver_request); - if (request && module_) { - for (const hook of this.handlers.response) { - try { - // eslint-disable-next-line no-await-in-loop - await hook(request, module_, response); - } - catch (error) { - /* eslint-disable no-console */ - console.error('Error in "response" hook:'); - console.error(error); - /* eslint-enable no-console */ - } - } - } - return response; - }); - } - handlers = { - transformer: undefined, - module: [], - response: [], - }; - /** - * Use this hook add properties to the request before it is send to the API module. - * - * This hook can be set only once. - * @param transformer The callback function. - */ - setTransformer(transformer) { - if (this.handlers.transformer) { - throw new Error('Transformer has already been set.'); - } - this.handlers.transformer = transformer; - } - /** - * Adds a hook to be called when the API module is imported. - * @param callback - - */ - onModule(callback) { - this.handlers.module.push(callback); - } - /** - * Adds a hook to be called right before the response is sent back. - * - * This hook called only if the request was processed by the API module. If unknown method was requested, this hook is not called. - * @param callback - - */ - onResponse(callback) { - this.handlers.response.push(callback); - } - async processRequest(driver_request) { - let request = null; - let module_ = null; - try { - if (driver_request.path.startsWith('/') !== true) { - driver_request.path = `/${driver_request.path}`; - } - const router_response = await useRouter(this.router, driver_request.method, driver_request.path); - if (!router_response) { - return [ - request, - module_, - new HyperAPIUnknownMethodError(), - ]; - } - driver_request.args = { - ...driver_request.args, - ...router_response.args, - }; - // Send request to the outside user - request = this.handlers.transformer - ? await this.handlers.transformer(driver_request) - : driver_request; - // IDEA: "onBeforeModule" hook? - module_ = (await import(router_response.module_path)); - if (module_.argsValidator) { - request.args = module_.argsValidator(request.args); - } - for (const hook of this.handlers.module) { - // eslint-disable-next-line no-await-in-loop - await hook(request, module_); - } - // IDEA: "onBeforeExecute" hook? - const response = await module_.default(request); - // IDEA: "onExecute" hook? - return [ - request, - module_, - response, - ]; - } - catch (error) { - if (error instanceof HyperAPIError) { - return [ - request, - module_, - error, - ]; - } - // eslint-disable-next-line no-console - console.error(error); - return [ - request, - module_, - new HyperAPIInternalError(), - ]; - } - throw new Error('Unreachable'); - } - /** Destroys the HyperAPI instance. */ - destroy() { - this.handlers.transformer = undefined; - this.handlers.module.splice(0); - this.handlers.response.splice(0); - } -} -export * from './api-errors'; -export { HyperAPIError } from './error'; diff --git a/dist/esm/main.test.d.ts b/dist/esm/main.test.d.ts deleted file mode 100644 index cb0ff5c..0000000 --- a/dist/esm/main.test.d.ts +++ /dev/null @@ -1 +0,0 @@ -export {}; diff --git a/dist/esm/main.test.js b/dist/esm/main.test.js deleted file mode 100644 index 516ab4d..0000000 --- a/dist/esm/main.test.js +++ /dev/null @@ -1,143 +0,0 @@ -import { afterAll, describe, test, expect, } from 'vitest'; -import { driver, hyperApi, } from '../test/setup'; -afterAll(() => { - hyperApi.destroy(); -}); -describe('routing', () => { - describe('methods', () => { - test('ALL', async () => { - const result = await driver.trigger('GET', 'echo', { - name: 'world', - }); - expect(result).toStrictEqual([ - true, - { - method: 'ALL', - message: 'Hello, world!', - }, - ]); - }); - test('POST', async () => { - const result = await driver.trigger('POST', 'echo', { - name: 'deadbeef', - }); - expect(result).toStrictEqual([ - true, - { - method: 'POST', - message: 'Hello, deadbeef!', - }, - ]); - }); - }); - // test('method in directory', async () => { - // const result = await request( - // 'dir/nested', - // ); - // expect(result).toStrictEqual([ - // true, - // { - // ok: true, - // }, - // ]); - // }); - // test('correct request (async)', async () => { - // const result = await request( - // 'echo.async', - // { - // name: 'user', - // }, - // ); - // expect(result).toStrictEqual([ - // true, - // { - // message: 'Hello, user!', - // }, - // ]); - // }); - // test('invalid arguments', async () => { - // const result = await request( - // 'echo', - // { - // name: 123, - // }, - // ); - // expect(result).toStrictEqual([ - // false, - // { - // code: 2, - // description: 'One of the parameters specified was missing or invalid', - // }, - // ]); - // }); - // test('missing arguments', async () => { - // const result = await request('echo'); - // expect(result).toStrictEqual([ - // false, - // { - // code: 2, - // description: 'One of the parameters specified was missing or invalid', - // }, - // ]); - // }); - // test('api error', async () => { - // const result = await request('error.api'); - // expect(result).toStrictEqual([ - // false, - // { - // code: 10, - // description: 'Endpoint is busy', - // }, - // ]); - // }); - // test('internal error', async () => { - // const result = await request('error.internal'); - // expect(result).toStrictEqual([ - // false, - // { - // code: 3, - // description: 'Internal error', - // }, - // ]); - // }); - // test('invalid return type', async () => { - // const result = await request('error.type'); - // expect(result).toStrictEqual([ - // false, - // { - // code: 3, - // description: 'Internal error', - // }, - // ]); - // }); - // test('unknown method', async () => { - // const result = await request('error.unknown-method'); - // expect(result).toStrictEqual([ - // false, - // { - // code: 5, - // description: 'Unknown method called', - // }, - // ]); - // }); - // test('invalid import path inside module', async () => { - // const result = await request('error.import.path'); - // expect(result).toStrictEqual([ - // false, - // { - // code: 3, - // description: 'Internal error', - // }, - // ]); - // }); - // test('invalid import field inside module', async () => { - // const result = await request('error.import.field'); - // expect(result).toStrictEqual([ - // false, - // { - // code: 3, - // description: 'Internal error', - // }, - // ]); - // }); -}); diff --git a/dist/esm/module.d.ts b/dist/esm/module.d.ts deleted file mode 100644 index ca33951..0000000 --- a/dist/esm/module.d.ts +++ /dev/null @@ -1,9 +0,0 @@ -import { HyperAPI } from './main'; -import type { HyperAPIRequest, HyperAPIRequestArgs } from './request'; -import type { MaybePromise } from './utils/types'; -export type HyperAPIModuleResponse = Record | unknown[] | undefined; -export interface HyperAPIModule> { - readonly default: (request: R) => MaybePromise; - readonly argsValidator: (args: unknown) => R extends HyperAPIRequest ? A : never; -} -export type InferModule> = H extends HyperAPI ? M : never; diff --git a/dist/esm/module.js b/dist/esm/module.js deleted file mode 100644 index cb0ff5c..0000000 --- a/dist/esm/module.js +++ /dev/null @@ -1 +0,0 @@ -export {}; diff --git a/dist/esm/request.d.ts b/dist/esm/request.d.ts deleted file mode 100644 index 4ead616..0000000 --- a/dist/esm/request.d.ts +++ /dev/null @@ -1,7 +0,0 @@ -import type { EmptyObject, HTTPMethod } from './utils/types'; -export type HyperAPIRequestArgs = Record; -export interface HyperAPIRequest { - method: HTTPMethod; - path: string; - args: A; -} diff --git a/dist/esm/request.js b/dist/esm/request.js deleted file mode 100644 index cb0ff5c..0000000 --- a/dist/esm/request.js +++ /dev/null @@ -1 +0,0 @@ -export {}; diff --git a/dist/esm/response.d.ts b/dist/esm/response.d.ts deleted file mode 100644 index 9b61a74..0000000 --- a/dist/esm/response.d.ts +++ /dev/null @@ -1,3 +0,0 @@ -import { HyperAPIError } from './error'; -import { HyperAPIModuleResponse } from './module'; -export type HyperAPIResponse = HyperAPIModuleResponse | HyperAPIError; diff --git a/dist/esm/response.js b/dist/esm/response.js deleted file mode 100644 index cb0ff5c..0000000 --- a/dist/esm/response.js +++ /dev/null @@ -1 +0,0 @@ -export {}; diff --git a/dist/esm/router.d.ts b/dist/esm/router.d.ts deleted file mode 100644 index 1c3f152..0000000 --- a/dist/esm/router.d.ts +++ /dev/null @@ -1,21 +0,0 @@ -import { type IRequest, type IttyRouterType } from 'itty-router'; -import { HTTPMethod } from './utils/types'; -/** - * Creates new IttyRouter from filesystem. - * @param path The path to scan. - * @returns The new IttyRouter. - */ -export declare function createRouter(path: string): IttyRouterType; -interface RouterResponse { - module_path: string; - args: Record; -} -/** - * Fetches data from router. - * @param router The router to fetch data from. - * @param method The HTTP method. - * @param path The path to fetch data from. - * @returns The response. - */ -export declare function useRouter(router: IttyRouterType, method: HTTPMethod, path: string): Promise; -export {}; diff --git a/dist/esm/router.js b/dist/esm/router.js deleted file mode 100644 index f1bdd75..0000000 --- a/dist/esm/router.js +++ /dev/null @@ -1,103 +0,0 @@ -/* eslint-disable n/no-sync */ -import { IttyRouter, } from 'itty-router'; -import { readdirSync } from 'node:fs'; -import nodePath from 'node:path'; -/** - * Creates new IttyRouter from filesystem. - * @param path The path to scan. - * @returns The new IttyRouter. - */ -export function createRouter(path) { - // eslint-disable-next-line new-cap - const router = IttyRouter(); - scanDirectory(router, path); - return router; -} -/** - * Fetches data from router. - * @param router The router to fetch data from. - * @param method The HTTP method. - * @param path The path to fetch data from. - * @returns The response. - */ -export function useRouter(router, method, path) { - return router.fetch({ - method, - url: `file://${path}`, - }); -} -const REGEXP_FILE_EXTENSION = /\.(js|mjs|cjs|ts)$/; -const REGEXP_HTTP_METHOD = /\.\[(delete|get|head|options|patch|post|put)]$/; -const REGEXP_PATH_SLUG = /\[(\w+)]/g; -/** - * Scans directory for routes. - * @param router The router to add routes to. - * @param path The path to scan. - * @param [regexp_parts] The parts of the regular expression. - */ -function scanDirectory(router, path, regexp_parts = ['']) { - const result = readdirSync(path, { - withFileTypes: true, - }); - const routes = { - 0: [], // routes with no method and no slug - 1: [], // routes with method and no slug - 2: [], // routes with no method and slug - 3: [], // routes with method and slug - }; - for (const entry of result) { - const entry_path = nodePath.join(path, entry.name); - if (entry.isFile()) { - let file_name = entry.name; - if (REGEXP_FILE_EXTENSION.test(file_name)) { - file_name = file_name.replace(REGEXP_FILE_EXTENSION, ''); - let method = 'all'; - const method_match = file_name.match(REGEXP_HTTP_METHOD); - const has_method = method_match ? 1 : 0; - if (method_match) { - method = method_match[1]; - file_name = file_name.replace(REGEXP_HTTP_METHOD, ''); - } - const has_slug = REGEXP_PATH_SLUG.test(file_name) ? 2 : 0; - file_name = file_name.replaceAll(REGEXP_PATH_SLUG, ':$1'); - // console.log( - // entry_path, - // method, - // [ - // ...regexp_parts, - // file_name, - // ].join(nodePath.sep), - // ); - // eslint-disable-next-line no-bitwise - routes[has_method | has_slug].push({ - method, - path: [ - ...regexp_parts, - file_name, - ].join(nodePath.sep), - module_path: entry_path, - }); - } - } - else { - scanDirectory(router, entry_path, [ - ...regexp_parts, - entry.name.replaceAll(REGEXP_PATH_SLUG, ':$1'), - ]); - } - } - for (const route of [ - ...routes[1], - ...routes[3], - ...routes[0], - ...routes[2], - ]) { - router[route.method](route.path, (r) => { - const response = { - module_path: route.module_path, - args: r.params, - }; - return response; - }); - } -} diff --git a/dist/esm/utils/is-record.d.ts b/dist/esm/utils/is-record.d.ts deleted file mode 100644 index b3e9d51..0000000 --- a/dist/esm/utils/is-record.d.ts +++ /dev/null @@ -1,6 +0,0 @@ -/** - * Check if a value is a record. - * @param value - - * @returns - - */ -export declare function isRecord(value: unknown): value is Record; diff --git a/dist/esm/utils/is-record.js b/dist/esm/utils/is-record.js deleted file mode 100644 index 350e9df..0000000 --- a/dist/esm/utils/is-record.js +++ /dev/null @@ -1,12 +0,0 @@ -/** - * Check if a value is a record. - * @param value - - * @returns - - */ -export function isRecord(value) { - return typeof value === 'object' - && value !== null - && !Array.isArray(value) - && value.constructor === Object - && Object.prototype.toString.call(value) === '[object Object]'; -} diff --git a/dist/esm/utils/types.d.ts b/dist/esm/utils/types.d.ts deleted file mode 100644 index d050ecd..0000000 --- a/dist/esm/utils/types.d.ts +++ /dev/null @@ -1,5 +0,0 @@ -export type EmptyObject = Omit<{ - p: never; -}, 'p'>; -export type MaybePromise = T | Promise; -export type HTTPMethod = 'DELETE' | 'GET' | 'HEAD' | 'OPTIONS' | 'PATCH' | 'POST' | 'PUT' | 'UNKNOWN'; diff --git a/dist/esm/utils/types.js b/dist/esm/utils/types.js deleted file mode 100644 index cb0ff5c..0000000 --- a/dist/esm/utils/types.js +++ /dev/null @@ -1 +0,0 @@ -export {}; diff --git a/dist/main.cjs b/dist/main.cjs deleted file mode 100644 index 41ed216..0000000 --- a/dist/main.cjs +++ /dev/null @@ -1,383 +0,0 @@ -"use strict"; -var __create = Object.create; -var __defProp = Object.defineProperty; -var __getOwnPropDesc = Object.getOwnPropertyDescriptor; -var __getOwnPropNames = Object.getOwnPropertyNames; -var __getProtoOf = Object.getPrototypeOf; -var __hasOwnProp = Object.prototype.hasOwnProperty; -var __export = (target, all) => { - for (var name in all) - __defProp(target, name, { get: all[name], enumerable: true }); -}; -var __copyProps = (to, from, except, desc) => { - if (from && typeof from === "object" || typeof from === "function") { - for (let key of __getOwnPropNames(from)) - if (!__hasOwnProp.call(to, key) && key !== except) - __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable }); - } - return to; -}; -var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps( - // If the importer is in node compatibility mode or this is not an ESM - // file that has been converted to a CommonJS file using a Babel- - // compatible transform (i.e. "__esModule" has not been set), then set - // "default" to the CommonJS "module.exports" for node compatibility. - isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target, - mod -)); -var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod); - -// dist/esm/main.js -var main_exports = {}; -__export(main_exports, { - HyperAPI: () => HyperAPI, - HyperAPIAuthorizationError: () => HyperAPIAuthorizationError, - HyperAPIBusyError: () => HyperAPIBusyError, - HyperAPICaptchaError: () => HyperAPICaptchaError, - HyperAPIConfirmationError: () => HyperAPIConfirmationError, - HyperAPIError: () => HyperAPIError, - HyperAPIForbiddenError: () => HyperAPIForbiddenError, - HyperAPIInternalError: () => HyperAPIInternalError, - HyperAPIInvalidParametersError: () => HyperAPIInvalidParametersError, - HyperAPIMaintenanceError: () => HyperAPIMaintenanceError, - HyperAPIOTPError: () => HyperAPIOTPError, - HyperAPIObjectsLimitError: () => HyperAPIObjectsLimitError, - HyperAPIRateLimitError: () => HyperAPIRateLimitError, - HyperAPIUnknownMethodError: () => HyperAPIUnknownMethodError -}); -module.exports = __toCommonJS(main_exports); -var import_node_path2 = __toESM(require("node:path"), 1); - -// dist/esm/utils/is-record.js -function isRecord(value) { - return typeof value === "object" && value !== null && !Array.isArray(value) && value.constructor === Object && Object.prototype.toString.call(value) === "[object Object]"; -} - -// dist/esm/error.js -var HyperAPIError = class extends Error { - /** The error code. */ - code = 0; - /** The error description. */ - description = "HyperAPI error"; - /** The error data. */ - data; - /** HTTP status code. */ - httpStatus; - /** HTTP headers to return. */ - httpHeaders; - constructor(data) { - super(); - if (isRecord(data)) { - this.data = data; - } - } - get message() { - return `${this.description} (code ${this.code}).`; - } - /** - * Creates response object. - * @returns - - */ - getResponse() { - const response = { - code: this.code - }; - if (typeof this.description === "string") { - response.description = this.description; - } - if (this.data) { - response.data = this.data; - } - return response; - } -}; - -// dist/esm/api-errors.js -var HyperAPIAuthorizationError = class extends HyperAPIError { - code = 1; - description = "Authorization error"; - httpStatus = 401; - // Unauthorized -}; -var HyperAPIInvalidParametersError = class extends HyperAPIError { - code = 2; - description = "One of the parameters specified was missing or invalid"; - httpStatus = 400; - // Bad Request -}; -var HyperAPIInternalError = class extends HyperAPIError { - code = 3; - description = "Internal error"; - httpStatus = 500; - // Internal Server Error -}; -var HyperAPIForbiddenError = class extends HyperAPIError { - code = 4; - description = "You do not have permission to perform this action"; - httpStatus = 403; - // Forbidden -}; -var HyperAPIUnknownMethodError = class extends HyperAPIError { - code = 5; - description = "Unknown method called"; - httpStatus = 404; - // Not Found -}; -var HyperAPIObjectsLimitError = class extends HyperAPIError { - code = 6; - description = "Too many objects requested"; - httpStatus = 400; - // Bad Request -}; -var HyperAPIRateLimitError = class extends HyperAPIError { - code = 7; - description = "Rate limit exceeded"; - httpStatus = 429; - // Too Many Requests -}; -var HyperAPICaptchaError = class extends HyperAPIError { - code = 8; - description = "Captcha required"; - httpStatus = 428; - // Precondition Required -}; -var HyperAPIBusyError = class extends HyperAPIError { - code = 10; - description = "Endpoint is busy"; - httpStatus = 503; - // Service Unavailable -}; -var HyperAPIConfirmationError = class extends HyperAPIError { - code = 11; - description = "Confirmation required"; - httpStatus = 409; - // Conflict -}; -var HyperAPIOTPError = class extends HyperAPIError { - code = 12; - description = "One-time password required"; - httpStatus = 401; - // Unauthorized -}; -var HyperAPIMaintenanceError = class extends HyperAPIError { - code = 13; - description = "Endpoint is in maintenance mode"; - httpStatus = 503; - // Service Unavailable -}; - -// dist/esm/router.js -var import_itty_router = require("itty-router"); -var import_node_fs = require("node:fs"); -var import_node_path = __toESM(require("node:path"), 1); -function createRouter(path) { - const router = (0, import_itty_router.IttyRouter)(); - scanDirectory(router, path); - return router; -} -function useRouter(router, method, path) { - return router.fetch({ - method, - url: `file://${path}` - }); -} -var REGEXP_FILE_EXTENSION = /\.(js|mjs|cjs|ts)$/; -var REGEXP_HTTP_METHOD = /\.\[(delete|get|head|options|patch|post|put)]$/; -var REGEXP_PATH_SLUG = /\[(\w+)]/g; -function scanDirectory(router, path, regexp_parts = [""]) { - const result = (0, import_node_fs.readdirSync)(path, { - withFileTypes: true - }); - const routes = { - 0: [], - // routes with no method and no slug - 1: [], - // routes with method and no slug - 2: [], - // routes with no method and slug - 3: [] - // routes with method and slug - }; - for (const entry of result) { - const entry_path = import_node_path.default.join(path, entry.name); - if (entry.isFile()) { - let file_name = entry.name; - if (REGEXP_FILE_EXTENSION.test(file_name)) { - file_name = file_name.replace(REGEXP_FILE_EXTENSION, ""); - let method = "all"; - const method_match = file_name.match(REGEXP_HTTP_METHOD); - const has_method = method_match ? 1 : 0; - if (method_match) { - method = method_match[1]; - file_name = file_name.replace(REGEXP_HTTP_METHOD, ""); - } - const has_slug = REGEXP_PATH_SLUG.test(file_name) ? 2 : 0; - file_name = file_name.replaceAll(REGEXP_PATH_SLUG, ":$1"); - routes[has_method | has_slug].push({ - method, - path: [ - ...regexp_parts, - file_name - ].join(import_node_path.default.sep), - module_path: entry_path - }); - } - } else { - scanDirectory(router, entry_path, [ - ...regexp_parts, - entry.name.replaceAll(REGEXP_PATH_SLUG, ":$1") - ]); - } - } - for (const route of [ - ...routes[1], - ...routes[3], - ...routes[0], - ...routes[2] - ]) { - router[route.method](route.path, (r) => { - const response = { - module_path: route.module_path, - args: r.params - }; - return response; - }); - } -} - -// dist/esm/main.js -var ENTRYPOINT_PATH = import_node_path2.default.dirname(process.argv[1]); -var HyperAPI = class { - router; - driver; - /** - * Creates a HyperAPI instance. - * @param options The options. - * @param options.driver The driver. - * @param [options.root] The root directory for API methods modules. Default: `hyper-api` directory alongside the entrypoint script. - */ - constructor({ driver, root = import_node_path2.default.join(ENTRYPOINT_PATH, "hyper-api") }) { - this.driver = driver; - this.router = createRouter(root); - this.driver.start(async (driver_request) => { - const [request, module_, response] = await this.processRequest(driver_request); - if (request && module_) { - for (const hook of this.handlers.response) { - try { - await hook(request, module_, response); - } catch (error) { - console.error('Error in "response" hook:'); - console.error(error); - } - } - } - return response; - }); - } - handlers = { - transformer: void 0, - module: [], - response: [] - }; - /** - * Use this hook add properties to the request before it is send to the API module. - * - * This hook can be set only once. - * @param transformer The callback function. - */ - setTransformer(transformer) { - if (this.handlers.transformer) { - throw new Error("Transformer has already been set."); - } - this.handlers.transformer = transformer; - } - /** - * Adds a hook to be called when the API module is imported. - * @param callback - - */ - onModule(callback) { - this.handlers.module.push(callback); - } - /** - * Adds a hook to be called right before the response is sent back. - * - * This hook called only if the request was processed by the API module. If unknown method was requested, this hook is not called. - * @param callback - - */ - onResponse(callback) { - this.handlers.response.push(callback); - } - async processRequest(driver_request) { - let request = null; - let module_ = null; - try { - if (driver_request.path.startsWith("/") !== true) { - driver_request.path = `/${driver_request.path}`; - } - const router_response = await useRouter(this.router, driver_request.method, driver_request.path); - if (!router_response) { - return [ - request, - module_, - new HyperAPIUnknownMethodError() - ]; - } - driver_request.args = { - ...driver_request.args, - ...router_response.args - }; - request = this.handlers.transformer ? await this.handlers.transformer(driver_request) : driver_request; - module_ = await import(router_response.module_path); - if (module_.argsValidator) { - request.args = module_.argsValidator(request.args); - } - for (const hook of this.handlers.module) { - await hook(request, module_); - } - const response = await module_.default(request); - return [ - request, - module_, - response - ]; - } catch (error) { - if (error instanceof HyperAPIError) { - return [ - request, - module_, - error - ]; - } - console.error(error); - return [ - request, - module_, - new HyperAPIInternalError() - ]; - } - throw new Error("Unreachable"); - } - /** Destroys the HyperAPI instance. */ - destroy() { - this.handlers.transformer = void 0; - this.handlers.module.splice(0); - this.handlers.response.splice(0); - } -}; -// Annotate the CommonJS export names for ESM import in node: -0 && (module.exports = { - HyperAPI, - HyperAPIAuthorizationError, - HyperAPIBusyError, - HyperAPICaptchaError, - HyperAPIConfirmationError, - HyperAPIError, - HyperAPIForbiddenError, - HyperAPIInternalError, - HyperAPIInvalidParametersError, - HyperAPIMaintenanceError, - HyperAPIOTPError, - HyperAPIObjectsLimitError, - HyperAPIRateLimitError, - HyperAPIUnknownMethodError -}); diff --git a/package.json b/package.json index b556569..a4c4091 100644 --- a/package.json +++ b/package.json @@ -30,12 +30,12 @@ "vitest": "^2.1.1" }, "scripts": { - "build": "bun run build:ts && bun run build:cjs", + "build": "rm -r dist ; bun run build:ts && bun run build:cjs", "build:cjs": "bunx esbuild --bundle --platform=node --format=cjs --packages=external --outfile=dist/main.cjs dist/esm/main.js", "build:ts": "rm -r dist/esm ; tsc && (mv dist/esm/src dist/.esm && rm -r dist/esm && mv dist/.esm dist/esm)", "lint": "eslint . && tsc --skipLibCheck --noemit", "publish:npm": "bun run build && bun run lint && bun run test && npm publish", - "test": "npm run test:vitest && bun test --coverage", + "test": "rm -r dist ; npm run test:vitest && bun test --coverage", "test:vitest": "vitest run --no-file-parallelism" }, "repository": { From 4e375ad2b64e0776795450b81188a4669f5e2d62 Mon Sep 17 00:00:00 2001 From: Daniil Kirichenko Date: Tue, 17 Sep 2024 13:36:48 +0300 Subject: [PATCH 18/57] Fix for Bun test runner --- dist/esm/api-errors.d.ts | 61 ++++++ dist/esm/api-errors.js | 61 ++++++ dist/esm/driver.d.ts | 9 + dist/esm/driver.js | 1 + dist/esm/error.d.ts | 26 +++ dist/esm/error.js | 38 ++++ dist/esm/error.test.d.ts | 1 + dist/esm/error.test.js | 11 + dist/esm/main.d.ts | 46 ++++ dist/esm/main.js | 137 ++++++++++++ dist/esm/main.test.d.ts | 1 + dist/esm/main.test.js | 143 +++++++++++++ dist/esm/module.d.ts | 9 + dist/esm/module.js | 1 + dist/esm/request.d.ts | 7 + dist/esm/request.js | 1 + dist/esm/response.d.ts | 3 + dist/esm/response.js | 1 + dist/esm/router.d.ts | 21 ++ dist/esm/router.js | 103 +++++++++ dist/esm/utils/is-record.d.ts | 6 + dist/esm/utils/is-record.js | 12 ++ dist/esm/utils/types.d.ts | 5 + dist/esm/utils/types.js | 1 + dist/main.cjs | 383 ++++++++++++++++++++++++++++++++++ package.json | 2 +- 26 files changed, 1089 insertions(+), 1 deletion(-) create mode 100644 dist/esm/api-errors.d.ts create mode 100644 dist/esm/api-errors.js create mode 100644 dist/esm/driver.d.ts create mode 100644 dist/esm/driver.js create mode 100644 dist/esm/error.d.ts create mode 100644 dist/esm/error.js create mode 100644 dist/esm/error.test.d.ts create mode 100644 dist/esm/error.test.js create mode 100644 dist/esm/main.d.ts create mode 100644 dist/esm/main.js create mode 100644 dist/esm/main.test.d.ts create mode 100644 dist/esm/main.test.js create mode 100644 dist/esm/module.d.ts create mode 100644 dist/esm/module.js create mode 100644 dist/esm/request.d.ts create mode 100644 dist/esm/request.js create mode 100644 dist/esm/response.d.ts create mode 100644 dist/esm/response.js create mode 100644 dist/esm/router.d.ts create mode 100644 dist/esm/router.js create mode 100644 dist/esm/utils/is-record.d.ts create mode 100644 dist/esm/utils/is-record.js create mode 100644 dist/esm/utils/types.d.ts create mode 100644 dist/esm/utils/types.js create mode 100644 dist/main.cjs diff --git a/dist/esm/api-errors.d.ts b/dist/esm/api-errors.d.ts new file mode 100644 index 0000000..2c5289c --- /dev/null +++ b/dist/esm/api-errors.d.ts @@ -0,0 +1,61 @@ +import { type ErrorData, HyperAPIError } from './error'; +export declare class HyperAPIAuthorizationError extends HyperAPIError { + code: number; + description: string; + httpStatus: number; +} +export declare class HyperAPIInvalidParametersError extends HyperAPIError { + code: number; + description: string; + httpStatus: number; +} +export declare class HyperAPIInternalError extends HyperAPIError { + code: number; + description: string; + httpStatus: number; +} +export declare class HyperAPIForbiddenError extends HyperAPIError { + code: number; + description: string; + httpStatus: number; +} +export declare class HyperAPIUnknownMethodError extends HyperAPIError { + code: number; + description: string; + httpStatus: number; +} +export declare class HyperAPIObjectsLimitError extends HyperAPIError { + code: number; + description: string; + httpStatus: number; +} +export declare class HyperAPIRateLimitError extends HyperAPIError { + code: number; + description: string; + httpStatus: number; +} +export declare class HyperAPICaptchaError extends HyperAPIError { + code: number; + description: string; + httpStatus: number; +} +export declare class HyperAPIBusyError extends HyperAPIError { + code: number; + description: string; + httpStatus: number; +} +export declare class HyperAPIConfirmationError extends HyperAPIError { + code: number; + description: string; + httpStatus: number; +} +export declare class HyperAPIOTPError extends HyperAPIError { + code: number; + description: string; + httpStatus: number; +} +export declare class HyperAPIMaintenanceError extends HyperAPIError { + code: number; + description: string; + httpStatus: number; +} diff --git a/dist/esm/api-errors.js b/dist/esm/api-errors.js new file mode 100644 index 0000000..0d92728 --- /dev/null +++ b/dist/esm/api-errors.js @@ -0,0 +1,61 @@ +import { HyperAPIError, } from './error'; +export class HyperAPIAuthorizationError extends HyperAPIError { + code = 1; + description = 'Authorization error'; + httpStatus = 401; // Unauthorized +} +export class HyperAPIInvalidParametersError extends HyperAPIError { + code = 2; + description = 'One of the parameters specified was missing or invalid'; + httpStatus = 400; // Bad Request +} +export class HyperAPIInternalError extends HyperAPIError { + code = 3; + description = 'Internal error'; + httpStatus = 500; // Internal Server Error +} +export class HyperAPIForbiddenError extends HyperAPIError { + code = 4; + description = 'You do not have permission to perform this action'; + httpStatus = 403; // Forbidden +} +export class HyperAPIUnknownMethodError extends HyperAPIError { + code = 5; + description = 'Unknown method called'; + httpStatus = 404; // Not Found +} +export class HyperAPIObjectsLimitError extends HyperAPIError { + code = 6; + description = 'Too many objects requested'; + httpStatus = 400; // Bad Request +} +export class HyperAPIRateLimitError extends HyperAPIError { + code = 7; + description = 'Rate limit exceeded'; + httpStatus = 429; // Too Many Requests +} +export class HyperAPICaptchaError extends HyperAPIError { + code = 8; + description = 'Captcha required'; + httpStatus = 428; // Precondition Required +} +export class HyperAPIBusyError extends HyperAPIError { + code = 10; + description = 'Endpoint is busy'; + httpStatus = 503; // Service Unavailable +} +export class HyperAPIConfirmationError extends HyperAPIError { + code = 11; + description = 'Confirmation required'; + httpStatus = 409; // Conflict +} +export class HyperAPIOTPError extends HyperAPIError { + code = 12; + description = 'One-time password required'; + httpStatus = 401; // Unauthorized +} +export class HyperAPIMaintenanceError extends HyperAPIError { + code = 13; + description = 'Endpoint is in maintenance mode'; + httpStatus = 503; // Service Unavailable +} diff --git a/dist/esm/driver.d.ts b/dist/esm/driver.d.ts new file mode 100644 index 0000000..9360e63 --- /dev/null +++ b/dist/esm/driver.d.ts @@ -0,0 +1,9 @@ +import type { HyperAPIRequest } from './request'; +import type { HyperAPIResponse } from './response'; +import { MaybePromise } from './utils/types'; +export type HyperAPIDriverHandler = (request: R) => MaybePromise; +export interface HyperAPIDriver { + start(handler: HyperAPIDriverHandler): void; + stop(): void; +} +export type InferDriverRequest = D extends HyperAPIDriver ? R : never; diff --git a/dist/esm/driver.js b/dist/esm/driver.js new file mode 100644 index 0000000..cb0ff5c --- /dev/null +++ b/dist/esm/driver.js @@ -0,0 +1 @@ +export {}; diff --git a/dist/esm/error.d.ts b/dist/esm/error.d.ts new file mode 100644 index 0000000..279e608 --- /dev/null +++ b/dist/esm/error.d.ts @@ -0,0 +1,26 @@ +interface HyperAPIErrorResponse { + code: number; + description?: string; + data?: Record; +} +export type ErrorData = Record | undefined; +export declare class HyperAPIError | undefined> extends Error { + /** The error code. */ + readonly code: number; + /** The error description. */ + readonly description: string; + /** The error data. */ + readonly data?: D; + /** HTTP status code. */ + readonly httpStatus?: number; + /** HTTP headers to return. */ + readonly httpHeaders?: Record; + constructor(data?: D); + get message(): string; + /** + * Creates response object. + * @returns - + */ + getResponse(): HyperAPIErrorResponse; +} +export {}; diff --git a/dist/esm/error.js b/dist/esm/error.js new file mode 100644 index 0000000..353bfa6 --- /dev/null +++ b/dist/esm/error.js @@ -0,0 +1,38 @@ +import { isRecord } from './utils/is-record'; +export class HyperAPIError extends Error { + /** The error code. */ + code = 0; + /** The error description. */ + description = 'HyperAPI error'; + /** The error data. */ + data; + /** HTTP status code. */ + httpStatus; + /** HTTP headers to return. */ + httpHeaders; + constructor(data) { + super(); + if (isRecord(data)) { + this.data = data; + } + } + get message() { + return `${this.description} (code ${this.code}).`; + } + /** + * Creates response object. + * @returns - + */ + getResponse() { + const response = { + code: this.code, + }; + if (typeof this.description === 'string') { + response.description = this.description; + } + if (this.data) { + response.data = this.data; + } + return response; + } +} diff --git a/dist/esm/error.test.d.ts b/dist/esm/error.test.d.ts new file mode 100644 index 0000000..cb0ff5c --- /dev/null +++ b/dist/esm/error.test.d.ts @@ -0,0 +1 @@ +export {}; diff --git a/dist/esm/error.test.js b/dist/esm/error.test.js new file mode 100644 index 0000000..8dbb23b --- /dev/null +++ b/dist/esm/error.test.js @@ -0,0 +1,11 @@ +/* eslint-disable @typescript-eslint/no-explicit-any */ +import { test, expect, } from 'vitest'; +import { HyperAPIError } from './error'; +class HyperAPICustomError extends HyperAPIError { + code = 1001; + description = 'This is a custom error'; +} +test('custom error', () => { + const error = new HyperAPICustomError(); + expect(error.message).toBe('This is a custom error (code 1001).'); +}); diff --git a/dist/esm/main.d.ts b/dist/esm/main.d.ts new file mode 100644 index 0000000..c6d48d4 --- /dev/null +++ b/dist/esm/main.d.ts @@ -0,0 +1,46 @@ +import type { HyperAPIDriver, InferDriverRequest } from './driver'; +import type { HyperAPIModule } from './module'; +import type { HyperAPIRequest } from './request'; +export declare class HyperAPI, R extends InferDriverRequest, M extends HyperAPIModule = HyperAPIModule> { + private router; + private driver; + /** + * Creates a HyperAPI instance. + * @param options The options. + * @param options.driver The driver. + * @param [options.root] The root directory for API methods modules. Default: `hyper-api` directory alongside the entrypoint script. + */ + constructor({ driver, root, }: { + driver: D; + root?: string; + }); + private handlers; + /** + * Use this hook add properties to the request before it is send to the API module. + * + * This hook can be set only once. + * @param transformer The callback function. + */ + setTransformer(transformer: typeof this.handlers['transformer']): void; + /** + * Adds a hook to be called when the API module is imported. + * @param callback - + */ + onModule(callback: typeof this.handlers['module'][number]): void; + /** + * Adds a hook to be called right before the response is sent back. + * + * This hook called only if the request was processed by the API module. If unknown method was requested, this hook is not called. + * @param callback - + */ + onResponse(callback: typeof this.handlers['response'][number]): void; + private processRequest; + /** Destroys the HyperAPI instance. */ + destroy(): void; +} +export * from './api-errors'; +export type { HyperAPIDriver, HyperAPIDriverHandler, } from './driver'; +export { HyperAPIError } from './error'; +export type { HyperAPIModule, InferModule, } from './module'; +export type { HyperAPIRequest, HyperAPIRequestArgs, } from './request'; +export type { HyperAPIResponse } from './response'; diff --git a/dist/esm/main.js b/dist/esm/main.js new file mode 100644 index 0000000..48660b9 --- /dev/null +++ b/dist/esm/main.js @@ -0,0 +1,137 @@ +import nodePath from 'node:path'; +import { HyperAPIInternalError, HyperAPIUnknownMethodError, } from './api-errors'; +import { HyperAPIError } from './error'; +import { createRouter, useRouter, } from './router'; +const ENTRYPOINT_PATH = nodePath.dirname(process.argv[1]); +export class HyperAPI { + router; + driver; + /** + * Creates a HyperAPI instance. + * @param options The options. + * @param options.driver The driver. + * @param [options.root] The root directory for API methods modules. Default: `hyper-api` directory alongside the entrypoint script. + */ + constructor({ driver, root = nodePath.join(ENTRYPOINT_PATH, 'hyper-api'), }) { + this.driver = driver; + this.router = createRouter(root); + this.driver.start(async (driver_request) => { + const [request, module_, response,] = await this.processRequest(driver_request); + if (request && module_) { + for (const hook of this.handlers.response) { + try { + // eslint-disable-next-line no-await-in-loop + await hook(request, module_, response); + } + catch (error) { + /* eslint-disable no-console */ + console.error('Error in "response" hook:'); + console.error(error); + /* eslint-enable no-console */ + } + } + } + return response; + }); + } + handlers = { + transformer: undefined, + module: [], + response: [], + }; + /** + * Use this hook add properties to the request before it is send to the API module. + * + * This hook can be set only once. + * @param transformer The callback function. + */ + setTransformer(transformer) { + if (this.handlers.transformer) { + throw new Error('Transformer has already been set.'); + } + this.handlers.transformer = transformer; + } + /** + * Adds a hook to be called when the API module is imported. + * @param callback - + */ + onModule(callback) { + this.handlers.module.push(callback); + } + /** + * Adds a hook to be called right before the response is sent back. + * + * This hook called only if the request was processed by the API module. If unknown method was requested, this hook is not called. + * @param callback - + */ + onResponse(callback) { + this.handlers.response.push(callback); + } + async processRequest(driver_request) { + let request = null; + let module_ = null; + try { + if (driver_request.path.startsWith('/') !== true) { + driver_request.path = `/${driver_request.path}`; + } + const router_response = await useRouter(this.router, driver_request.method, driver_request.path); + if (!router_response) { + return [ + request, + module_, + new HyperAPIUnknownMethodError(), + ]; + } + driver_request.args = { + ...driver_request.args, + ...router_response.args, + }; + // Send request to the outside user + request = this.handlers.transformer + ? await this.handlers.transformer(driver_request) + : driver_request; + // IDEA: "onBeforeModule" hook? + module_ = (await import(router_response.module_path)); + if (module_.argsValidator) { + request.args = module_.argsValidator(request.args); + } + for (const hook of this.handlers.module) { + // eslint-disable-next-line no-await-in-loop + await hook(request, module_); + } + // IDEA: "onBeforeExecute" hook? + const response = await module_.default(request); + // IDEA: "onExecute" hook? + return [ + request, + module_, + response, + ]; + } + catch (error) { + if (error instanceof HyperAPIError) { + return [ + request, + module_, + error, + ]; + } + // eslint-disable-next-line no-console + console.error(error); + return [ + request, + module_, + new HyperAPIInternalError(), + ]; + } + throw new Error('Unreachable'); + } + /** Destroys the HyperAPI instance. */ + destroy() { + this.handlers.transformer = undefined; + this.handlers.module.splice(0); + this.handlers.response.splice(0); + } +} +export * from './api-errors'; +export { HyperAPIError } from './error'; diff --git a/dist/esm/main.test.d.ts b/dist/esm/main.test.d.ts new file mode 100644 index 0000000..cb0ff5c --- /dev/null +++ b/dist/esm/main.test.d.ts @@ -0,0 +1 @@ +export {}; diff --git a/dist/esm/main.test.js b/dist/esm/main.test.js new file mode 100644 index 0000000..516ab4d --- /dev/null +++ b/dist/esm/main.test.js @@ -0,0 +1,143 @@ +import { afterAll, describe, test, expect, } from 'vitest'; +import { driver, hyperApi, } from '../test/setup'; +afterAll(() => { + hyperApi.destroy(); +}); +describe('routing', () => { + describe('methods', () => { + test('ALL', async () => { + const result = await driver.trigger('GET', 'echo', { + name: 'world', + }); + expect(result).toStrictEqual([ + true, + { + method: 'ALL', + message: 'Hello, world!', + }, + ]); + }); + test('POST', async () => { + const result = await driver.trigger('POST', 'echo', { + name: 'deadbeef', + }); + expect(result).toStrictEqual([ + true, + { + method: 'POST', + message: 'Hello, deadbeef!', + }, + ]); + }); + }); + // test('method in directory', async () => { + // const result = await request( + // 'dir/nested', + // ); + // expect(result).toStrictEqual([ + // true, + // { + // ok: true, + // }, + // ]); + // }); + // test('correct request (async)', async () => { + // const result = await request( + // 'echo.async', + // { + // name: 'user', + // }, + // ); + // expect(result).toStrictEqual([ + // true, + // { + // message: 'Hello, user!', + // }, + // ]); + // }); + // test('invalid arguments', async () => { + // const result = await request( + // 'echo', + // { + // name: 123, + // }, + // ); + // expect(result).toStrictEqual([ + // false, + // { + // code: 2, + // description: 'One of the parameters specified was missing or invalid', + // }, + // ]); + // }); + // test('missing arguments', async () => { + // const result = await request('echo'); + // expect(result).toStrictEqual([ + // false, + // { + // code: 2, + // description: 'One of the parameters specified was missing or invalid', + // }, + // ]); + // }); + // test('api error', async () => { + // const result = await request('error.api'); + // expect(result).toStrictEqual([ + // false, + // { + // code: 10, + // description: 'Endpoint is busy', + // }, + // ]); + // }); + // test('internal error', async () => { + // const result = await request('error.internal'); + // expect(result).toStrictEqual([ + // false, + // { + // code: 3, + // description: 'Internal error', + // }, + // ]); + // }); + // test('invalid return type', async () => { + // const result = await request('error.type'); + // expect(result).toStrictEqual([ + // false, + // { + // code: 3, + // description: 'Internal error', + // }, + // ]); + // }); + // test('unknown method', async () => { + // const result = await request('error.unknown-method'); + // expect(result).toStrictEqual([ + // false, + // { + // code: 5, + // description: 'Unknown method called', + // }, + // ]); + // }); + // test('invalid import path inside module', async () => { + // const result = await request('error.import.path'); + // expect(result).toStrictEqual([ + // false, + // { + // code: 3, + // description: 'Internal error', + // }, + // ]); + // }); + // test('invalid import field inside module', async () => { + // const result = await request('error.import.field'); + // expect(result).toStrictEqual([ + // false, + // { + // code: 3, + // description: 'Internal error', + // }, + // ]); + // }); +}); diff --git a/dist/esm/module.d.ts b/dist/esm/module.d.ts new file mode 100644 index 0000000..ca33951 --- /dev/null +++ b/dist/esm/module.d.ts @@ -0,0 +1,9 @@ +import { HyperAPI } from './main'; +import type { HyperAPIRequest, HyperAPIRequestArgs } from './request'; +import type { MaybePromise } from './utils/types'; +export type HyperAPIModuleResponse = Record | unknown[] | undefined; +export interface HyperAPIModule> { + readonly default: (request: R) => MaybePromise; + readonly argsValidator: (args: unknown) => R extends HyperAPIRequest ? A : never; +} +export type InferModule> = H extends HyperAPI ? M : never; diff --git a/dist/esm/module.js b/dist/esm/module.js new file mode 100644 index 0000000..cb0ff5c --- /dev/null +++ b/dist/esm/module.js @@ -0,0 +1 @@ +export {}; diff --git a/dist/esm/request.d.ts b/dist/esm/request.d.ts new file mode 100644 index 0000000..4ead616 --- /dev/null +++ b/dist/esm/request.d.ts @@ -0,0 +1,7 @@ +import type { EmptyObject, HTTPMethod } from './utils/types'; +export type HyperAPIRequestArgs = Record; +export interface HyperAPIRequest { + method: HTTPMethod; + path: string; + args: A; +} diff --git a/dist/esm/request.js b/dist/esm/request.js new file mode 100644 index 0000000..cb0ff5c --- /dev/null +++ b/dist/esm/request.js @@ -0,0 +1 @@ +export {}; diff --git a/dist/esm/response.d.ts b/dist/esm/response.d.ts new file mode 100644 index 0000000..9b61a74 --- /dev/null +++ b/dist/esm/response.d.ts @@ -0,0 +1,3 @@ +import { HyperAPIError } from './error'; +import { HyperAPIModuleResponse } from './module'; +export type HyperAPIResponse = HyperAPIModuleResponse | HyperAPIError; diff --git a/dist/esm/response.js b/dist/esm/response.js new file mode 100644 index 0000000..cb0ff5c --- /dev/null +++ b/dist/esm/response.js @@ -0,0 +1 @@ +export {}; diff --git a/dist/esm/router.d.ts b/dist/esm/router.d.ts new file mode 100644 index 0000000..1c3f152 --- /dev/null +++ b/dist/esm/router.d.ts @@ -0,0 +1,21 @@ +import { type IRequest, type IttyRouterType } from 'itty-router'; +import { HTTPMethod } from './utils/types'; +/** + * Creates new IttyRouter from filesystem. + * @param path The path to scan. + * @returns The new IttyRouter. + */ +export declare function createRouter(path: string): IttyRouterType; +interface RouterResponse { + module_path: string; + args: Record; +} +/** + * Fetches data from router. + * @param router The router to fetch data from. + * @param method The HTTP method. + * @param path The path to fetch data from. + * @returns The response. + */ +export declare function useRouter(router: IttyRouterType, method: HTTPMethod, path: string): Promise; +export {}; diff --git a/dist/esm/router.js b/dist/esm/router.js new file mode 100644 index 0000000..f1bdd75 --- /dev/null +++ b/dist/esm/router.js @@ -0,0 +1,103 @@ +/* eslint-disable n/no-sync */ +import { IttyRouter, } from 'itty-router'; +import { readdirSync } from 'node:fs'; +import nodePath from 'node:path'; +/** + * Creates new IttyRouter from filesystem. + * @param path The path to scan. + * @returns The new IttyRouter. + */ +export function createRouter(path) { + // eslint-disable-next-line new-cap + const router = IttyRouter(); + scanDirectory(router, path); + return router; +} +/** + * Fetches data from router. + * @param router The router to fetch data from. + * @param method The HTTP method. + * @param path The path to fetch data from. + * @returns The response. + */ +export function useRouter(router, method, path) { + return router.fetch({ + method, + url: `file://${path}`, + }); +} +const REGEXP_FILE_EXTENSION = /\.(js|mjs|cjs|ts)$/; +const REGEXP_HTTP_METHOD = /\.\[(delete|get|head|options|patch|post|put)]$/; +const REGEXP_PATH_SLUG = /\[(\w+)]/g; +/** + * Scans directory for routes. + * @param router The router to add routes to. + * @param path The path to scan. + * @param [regexp_parts] The parts of the regular expression. + */ +function scanDirectory(router, path, regexp_parts = ['']) { + const result = readdirSync(path, { + withFileTypes: true, + }); + const routes = { + 0: [], // routes with no method and no slug + 1: [], // routes with method and no slug + 2: [], // routes with no method and slug + 3: [], // routes with method and slug + }; + for (const entry of result) { + const entry_path = nodePath.join(path, entry.name); + if (entry.isFile()) { + let file_name = entry.name; + if (REGEXP_FILE_EXTENSION.test(file_name)) { + file_name = file_name.replace(REGEXP_FILE_EXTENSION, ''); + let method = 'all'; + const method_match = file_name.match(REGEXP_HTTP_METHOD); + const has_method = method_match ? 1 : 0; + if (method_match) { + method = method_match[1]; + file_name = file_name.replace(REGEXP_HTTP_METHOD, ''); + } + const has_slug = REGEXP_PATH_SLUG.test(file_name) ? 2 : 0; + file_name = file_name.replaceAll(REGEXP_PATH_SLUG, ':$1'); + // console.log( + // entry_path, + // method, + // [ + // ...regexp_parts, + // file_name, + // ].join(nodePath.sep), + // ); + // eslint-disable-next-line no-bitwise + routes[has_method | has_slug].push({ + method, + path: [ + ...regexp_parts, + file_name, + ].join(nodePath.sep), + module_path: entry_path, + }); + } + } + else { + scanDirectory(router, entry_path, [ + ...regexp_parts, + entry.name.replaceAll(REGEXP_PATH_SLUG, ':$1'), + ]); + } + } + for (const route of [ + ...routes[1], + ...routes[3], + ...routes[0], + ...routes[2], + ]) { + router[route.method](route.path, (r) => { + const response = { + module_path: route.module_path, + args: r.params, + }; + return response; + }); + } +} diff --git a/dist/esm/utils/is-record.d.ts b/dist/esm/utils/is-record.d.ts new file mode 100644 index 0000000..b3e9d51 --- /dev/null +++ b/dist/esm/utils/is-record.d.ts @@ -0,0 +1,6 @@ +/** + * Check if a value is a record. + * @param value - + * @returns - + */ +export declare function isRecord(value: unknown): value is Record; diff --git a/dist/esm/utils/is-record.js b/dist/esm/utils/is-record.js new file mode 100644 index 0000000..350e9df --- /dev/null +++ b/dist/esm/utils/is-record.js @@ -0,0 +1,12 @@ +/** + * Check if a value is a record. + * @param value - + * @returns - + */ +export function isRecord(value) { + return typeof value === 'object' + && value !== null + && !Array.isArray(value) + && value.constructor === Object + && Object.prototype.toString.call(value) === '[object Object]'; +} diff --git a/dist/esm/utils/types.d.ts b/dist/esm/utils/types.d.ts new file mode 100644 index 0000000..d050ecd --- /dev/null +++ b/dist/esm/utils/types.d.ts @@ -0,0 +1,5 @@ +export type EmptyObject = Omit<{ + p: never; +}, 'p'>; +export type MaybePromise = T | Promise; +export type HTTPMethod = 'DELETE' | 'GET' | 'HEAD' | 'OPTIONS' | 'PATCH' | 'POST' | 'PUT' | 'UNKNOWN'; diff --git a/dist/esm/utils/types.js b/dist/esm/utils/types.js new file mode 100644 index 0000000..cb0ff5c --- /dev/null +++ b/dist/esm/utils/types.js @@ -0,0 +1 @@ +export {}; diff --git a/dist/main.cjs b/dist/main.cjs new file mode 100644 index 0000000..41ed216 --- /dev/null +++ b/dist/main.cjs @@ -0,0 +1,383 @@ +"use strict"; +var __create = Object.create; +var __defProp = Object.defineProperty; +var __getOwnPropDesc = Object.getOwnPropertyDescriptor; +var __getOwnPropNames = Object.getOwnPropertyNames; +var __getProtoOf = Object.getPrototypeOf; +var __hasOwnProp = Object.prototype.hasOwnProperty; +var __export = (target, all) => { + for (var name in all) + __defProp(target, name, { get: all[name], enumerable: true }); +}; +var __copyProps = (to, from, except, desc) => { + if (from && typeof from === "object" || typeof from === "function") { + for (let key of __getOwnPropNames(from)) + if (!__hasOwnProp.call(to, key) && key !== except) + __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable }); + } + return to; +}; +var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps( + // If the importer is in node compatibility mode or this is not an ESM + // file that has been converted to a CommonJS file using a Babel- + // compatible transform (i.e. "__esModule" has not been set), then set + // "default" to the CommonJS "module.exports" for node compatibility. + isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target, + mod +)); +var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod); + +// dist/esm/main.js +var main_exports = {}; +__export(main_exports, { + HyperAPI: () => HyperAPI, + HyperAPIAuthorizationError: () => HyperAPIAuthorizationError, + HyperAPIBusyError: () => HyperAPIBusyError, + HyperAPICaptchaError: () => HyperAPICaptchaError, + HyperAPIConfirmationError: () => HyperAPIConfirmationError, + HyperAPIError: () => HyperAPIError, + HyperAPIForbiddenError: () => HyperAPIForbiddenError, + HyperAPIInternalError: () => HyperAPIInternalError, + HyperAPIInvalidParametersError: () => HyperAPIInvalidParametersError, + HyperAPIMaintenanceError: () => HyperAPIMaintenanceError, + HyperAPIOTPError: () => HyperAPIOTPError, + HyperAPIObjectsLimitError: () => HyperAPIObjectsLimitError, + HyperAPIRateLimitError: () => HyperAPIRateLimitError, + HyperAPIUnknownMethodError: () => HyperAPIUnknownMethodError +}); +module.exports = __toCommonJS(main_exports); +var import_node_path2 = __toESM(require("node:path"), 1); + +// dist/esm/utils/is-record.js +function isRecord(value) { + return typeof value === "object" && value !== null && !Array.isArray(value) && value.constructor === Object && Object.prototype.toString.call(value) === "[object Object]"; +} + +// dist/esm/error.js +var HyperAPIError = class extends Error { + /** The error code. */ + code = 0; + /** The error description. */ + description = "HyperAPI error"; + /** The error data. */ + data; + /** HTTP status code. */ + httpStatus; + /** HTTP headers to return. */ + httpHeaders; + constructor(data) { + super(); + if (isRecord(data)) { + this.data = data; + } + } + get message() { + return `${this.description} (code ${this.code}).`; + } + /** + * Creates response object. + * @returns - + */ + getResponse() { + const response = { + code: this.code + }; + if (typeof this.description === "string") { + response.description = this.description; + } + if (this.data) { + response.data = this.data; + } + return response; + } +}; + +// dist/esm/api-errors.js +var HyperAPIAuthorizationError = class extends HyperAPIError { + code = 1; + description = "Authorization error"; + httpStatus = 401; + // Unauthorized +}; +var HyperAPIInvalidParametersError = class extends HyperAPIError { + code = 2; + description = "One of the parameters specified was missing or invalid"; + httpStatus = 400; + // Bad Request +}; +var HyperAPIInternalError = class extends HyperAPIError { + code = 3; + description = "Internal error"; + httpStatus = 500; + // Internal Server Error +}; +var HyperAPIForbiddenError = class extends HyperAPIError { + code = 4; + description = "You do not have permission to perform this action"; + httpStatus = 403; + // Forbidden +}; +var HyperAPIUnknownMethodError = class extends HyperAPIError { + code = 5; + description = "Unknown method called"; + httpStatus = 404; + // Not Found +}; +var HyperAPIObjectsLimitError = class extends HyperAPIError { + code = 6; + description = "Too many objects requested"; + httpStatus = 400; + // Bad Request +}; +var HyperAPIRateLimitError = class extends HyperAPIError { + code = 7; + description = "Rate limit exceeded"; + httpStatus = 429; + // Too Many Requests +}; +var HyperAPICaptchaError = class extends HyperAPIError { + code = 8; + description = "Captcha required"; + httpStatus = 428; + // Precondition Required +}; +var HyperAPIBusyError = class extends HyperAPIError { + code = 10; + description = "Endpoint is busy"; + httpStatus = 503; + // Service Unavailable +}; +var HyperAPIConfirmationError = class extends HyperAPIError { + code = 11; + description = "Confirmation required"; + httpStatus = 409; + // Conflict +}; +var HyperAPIOTPError = class extends HyperAPIError { + code = 12; + description = "One-time password required"; + httpStatus = 401; + // Unauthorized +}; +var HyperAPIMaintenanceError = class extends HyperAPIError { + code = 13; + description = "Endpoint is in maintenance mode"; + httpStatus = 503; + // Service Unavailable +}; + +// dist/esm/router.js +var import_itty_router = require("itty-router"); +var import_node_fs = require("node:fs"); +var import_node_path = __toESM(require("node:path"), 1); +function createRouter(path) { + const router = (0, import_itty_router.IttyRouter)(); + scanDirectory(router, path); + return router; +} +function useRouter(router, method, path) { + return router.fetch({ + method, + url: `file://${path}` + }); +} +var REGEXP_FILE_EXTENSION = /\.(js|mjs|cjs|ts)$/; +var REGEXP_HTTP_METHOD = /\.\[(delete|get|head|options|patch|post|put)]$/; +var REGEXP_PATH_SLUG = /\[(\w+)]/g; +function scanDirectory(router, path, regexp_parts = [""]) { + const result = (0, import_node_fs.readdirSync)(path, { + withFileTypes: true + }); + const routes = { + 0: [], + // routes with no method and no slug + 1: [], + // routes with method and no slug + 2: [], + // routes with no method and slug + 3: [] + // routes with method and slug + }; + for (const entry of result) { + const entry_path = import_node_path.default.join(path, entry.name); + if (entry.isFile()) { + let file_name = entry.name; + if (REGEXP_FILE_EXTENSION.test(file_name)) { + file_name = file_name.replace(REGEXP_FILE_EXTENSION, ""); + let method = "all"; + const method_match = file_name.match(REGEXP_HTTP_METHOD); + const has_method = method_match ? 1 : 0; + if (method_match) { + method = method_match[1]; + file_name = file_name.replace(REGEXP_HTTP_METHOD, ""); + } + const has_slug = REGEXP_PATH_SLUG.test(file_name) ? 2 : 0; + file_name = file_name.replaceAll(REGEXP_PATH_SLUG, ":$1"); + routes[has_method | has_slug].push({ + method, + path: [ + ...regexp_parts, + file_name + ].join(import_node_path.default.sep), + module_path: entry_path + }); + } + } else { + scanDirectory(router, entry_path, [ + ...regexp_parts, + entry.name.replaceAll(REGEXP_PATH_SLUG, ":$1") + ]); + } + } + for (const route of [ + ...routes[1], + ...routes[3], + ...routes[0], + ...routes[2] + ]) { + router[route.method](route.path, (r) => { + const response = { + module_path: route.module_path, + args: r.params + }; + return response; + }); + } +} + +// dist/esm/main.js +var ENTRYPOINT_PATH = import_node_path2.default.dirname(process.argv[1]); +var HyperAPI = class { + router; + driver; + /** + * Creates a HyperAPI instance. + * @param options The options. + * @param options.driver The driver. + * @param [options.root] The root directory for API methods modules. Default: `hyper-api` directory alongside the entrypoint script. + */ + constructor({ driver, root = import_node_path2.default.join(ENTRYPOINT_PATH, "hyper-api") }) { + this.driver = driver; + this.router = createRouter(root); + this.driver.start(async (driver_request) => { + const [request, module_, response] = await this.processRequest(driver_request); + if (request && module_) { + for (const hook of this.handlers.response) { + try { + await hook(request, module_, response); + } catch (error) { + console.error('Error in "response" hook:'); + console.error(error); + } + } + } + return response; + }); + } + handlers = { + transformer: void 0, + module: [], + response: [] + }; + /** + * Use this hook add properties to the request before it is send to the API module. + * + * This hook can be set only once. + * @param transformer The callback function. + */ + setTransformer(transformer) { + if (this.handlers.transformer) { + throw new Error("Transformer has already been set."); + } + this.handlers.transformer = transformer; + } + /** + * Adds a hook to be called when the API module is imported. + * @param callback - + */ + onModule(callback) { + this.handlers.module.push(callback); + } + /** + * Adds a hook to be called right before the response is sent back. + * + * This hook called only if the request was processed by the API module. If unknown method was requested, this hook is not called. + * @param callback - + */ + onResponse(callback) { + this.handlers.response.push(callback); + } + async processRequest(driver_request) { + let request = null; + let module_ = null; + try { + if (driver_request.path.startsWith("/") !== true) { + driver_request.path = `/${driver_request.path}`; + } + const router_response = await useRouter(this.router, driver_request.method, driver_request.path); + if (!router_response) { + return [ + request, + module_, + new HyperAPIUnknownMethodError() + ]; + } + driver_request.args = { + ...driver_request.args, + ...router_response.args + }; + request = this.handlers.transformer ? await this.handlers.transformer(driver_request) : driver_request; + module_ = await import(router_response.module_path); + if (module_.argsValidator) { + request.args = module_.argsValidator(request.args); + } + for (const hook of this.handlers.module) { + await hook(request, module_); + } + const response = await module_.default(request); + return [ + request, + module_, + response + ]; + } catch (error) { + if (error instanceof HyperAPIError) { + return [ + request, + module_, + error + ]; + } + console.error(error); + return [ + request, + module_, + new HyperAPIInternalError() + ]; + } + throw new Error("Unreachable"); + } + /** Destroys the HyperAPI instance. */ + destroy() { + this.handlers.transformer = void 0; + this.handlers.module.splice(0); + this.handlers.response.splice(0); + } +}; +// Annotate the CommonJS export names for ESM import in node: +0 && (module.exports = { + HyperAPI, + HyperAPIAuthorizationError, + HyperAPIBusyError, + HyperAPICaptchaError, + HyperAPIConfirmationError, + HyperAPIError, + HyperAPIForbiddenError, + HyperAPIInternalError, + HyperAPIInvalidParametersError, + HyperAPIMaintenanceError, + HyperAPIOTPError, + HyperAPIObjectsLimitError, + HyperAPIRateLimitError, + HyperAPIUnknownMethodError +}); diff --git a/package.json b/package.json index a4c4091..1cc9776 100644 --- a/package.json +++ b/package.json @@ -35,7 +35,7 @@ "build:ts": "rm -r dist/esm ; tsc && (mv dist/esm/src dist/.esm && rm -r dist/esm && mv dist/.esm dist/esm)", "lint": "eslint . && tsc --skipLibCheck --noemit", "publish:npm": "bun run build && bun run lint && bun run test && npm publish", - "test": "rm -r dist ; npm run test:vitest && bun test --coverage", + "test": "npm run test:vitest && bun test --coverage src/ test/", "test:vitest": "vitest run --no-file-parallelism" }, "repository": { From 073d17fb4a4de4c305248e1ffecb9f5309df1fb8 Mon Sep 17 00:00:00 2001 From: Daniil Kirichenko Date: Tue, 17 Sep 2024 13:39:09 +0300 Subject: [PATCH 19/57] [v0.3.0-beta.2] Fixed publishing config --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 1cc9776..89f5d2e 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@hyperapi/core", - "version": "0.3.0-beta.1", + "version": "0.3.0-beta.2", "description": "Core package of the HyperAPI project.", "publishConfig": { "access": "public" From 2bebc0c0ad0771b1ed4c08df7800d8798307cc3e Mon Sep 17 00:00:00 2001 From: Daniil Kirichenko Date: Wed, 18 Sep 2024 16:55:42 +0300 Subject: [PATCH 20/57] [v0.3.0-beta.3] Fixed import extensions --- bun.lockb | Bin 118712 -> 118712 bytes dist/esm/api-errors.d.ts | 2 +- dist/esm/api-errors.js | 2 +- dist/esm/driver.d.ts | 6 +- dist/esm/error.js | 2 +- dist/esm/error.test.d.ts | 1 - dist/esm/error.test.js | 11 -- dist/esm/main.d.ts | 18 ++-- dist/esm/main.js | 10 +- dist/esm/main.test.d.ts | 1 - dist/esm/main.test.js | 143 ------------------------- dist/esm/module.d.ts | 6 +- dist/esm/request.d.ts | 2 +- dist/esm/response.d.ts | 4 +- dist/esm/router.d.ts | 2 +- package.json | 6 +- src/api-errors.ts | 2 +- src/driver.ts | 6 +- src/error.test.ts | 2 +- src/error.ts | 2 +- src/main.test.ts | 2 +- src/main.ts | 29 +++-- src/module.ts | 6 +- src/request.ts | 2 +- src/response.ts | 4 +- src/router.ts | 8 +- test/hyper-api/echo.[post].ts | 4 +- test/hyper-api/echo.ts | 4 +- test/hyper-api/errors/api.test.ts | 2 +- test/hyper-api/errors/api.ts | 4 +- test/hyper-api/errors/internal.test.ts | 2 +- test/setup.ts | 4 +- test/tsconfig.json | 18 ++++ tsconfig.json | 11 +- 34 files changed, 95 insertions(+), 233 deletions(-) delete mode 100644 dist/esm/error.test.d.ts delete mode 100644 dist/esm/error.test.js delete mode 100644 dist/esm/main.test.d.ts delete mode 100644 dist/esm/main.test.js create mode 100644 test/tsconfig.json diff --git a/bun.lockb b/bun.lockb index 18657feda4544e43d3bea60c3c82c2267ecacf77..167dc82f0d486ab35eef61a2cb65b956cde11a14 100755 GIT binary patch delta 135 zcmV;20C@knp9i>~2aqlxZC&wcYy*n3{`x^tx;Bbx%sPh1mBMfz_tO4NeP2pqu}&&M z0Unca+$*!BL78wsMmdrjZT!%bzc46#(izL8Qh_5ydHM(jx&+r$ueKTeEKaU?N0PH& p+RBhkMHGsjbZ*&@Y=gQgNprlzVNg)wvwgCy_5w37w=Agvj3ynOKpg-8 delta 135 zcmV;20C@knp9i>~2aqlxpYtyyKvVa;ojC~ORJM=c+iAaRG!1>s7BJ%EnOu)!u}&&M z0UeWZ+$*!BL78wsNvoq4AjUe3zcDJlCOt@}V|g;wd>ImjOq*txPX1KuFUg14w&Sgm pg9c|doS>fRKrRC9U1wO)|2w79A{b5mvwgCy_5w0Fw=Agvj3%dhKPUhI diff --git a/dist/esm/api-errors.d.ts b/dist/esm/api-errors.d.ts index 2c5289c..62ed9c4 100644 --- a/dist/esm/api-errors.d.ts +++ b/dist/esm/api-errors.d.ts @@ -1,4 +1,4 @@ -import { type ErrorData, HyperAPIError } from './error'; +import { type ErrorData, HyperAPIError } from './error.js'; export declare class HyperAPIAuthorizationError extends HyperAPIError { code: number; description: string; diff --git a/dist/esm/api-errors.js b/dist/esm/api-errors.js index 0d92728..d8f3ab2 100644 --- a/dist/esm/api-errors.js +++ b/dist/esm/api-errors.js @@ -1,4 +1,4 @@ -import { HyperAPIError, } from './error'; +import { HyperAPIError, } from './error.js'; export class HyperAPIAuthorizationError extends HyperAPIError { code = 1; description = 'Authorization error'; diff --git a/dist/esm/driver.d.ts b/dist/esm/driver.d.ts index 9360e63..b7131cf 100644 --- a/dist/esm/driver.d.ts +++ b/dist/esm/driver.d.ts @@ -1,6 +1,6 @@ -import type { HyperAPIRequest } from './request'; -import type { HyperAPIResponse } from './response'; -import { MaybePromise } from './utils/types'; +import type { HyperAPIRequest } from './request.js'; +import type { HyperAPIResponse } from './response.js'; +import { MaybePromise } from './utils/types.js'; export type HyperAPIDriverHandler = (request: R) => MaybePromise; export interface HyperAPIDriver { start(handler: HyperAPIDriverHandler): void; diff --git a/dist/esm/error.js b/dist/esm/error.js index 353bfa6..74c0f51 100644 --- a/dist/esm/error.js +++ b/dist/esm/error.js @@ -1,4 +1,4 @@ -import { isRecord } from './utils/is-record'; +import { isRecord } from './utils/is-record.js'; export class HyperAPIError extends Error { /** The error code. */ code = 0; diff --git a/dist/esm/error.test.d.ts b/dist/esm/error.test.d.ts deleted file mode 100644 index cb0ff5c..0000000 --- a/dist/esm/error.test.d.ts +++ /dev/null @@ -1 +0,0 @@ -export {}; diff --git a/dist/esm/error.test.js b/dist/esm/error.test.js deleted file mode 100644 index 8dbb23b..0000000 --- a/dist/esm/error.test.js +++ /dev/null @@ -1,11 +0,0 @@ -/* eslint-disable @typescript-eslint/no-explicit-any */ -import { test, expect, } from 'vitest'; -import { HyperAPIError } from './error'; -class HyperAPICustomError extends HyperAPIError { - code = 1001; - description = 'This is a custom error'; -} -test('custom error', () => { - const error = new HyperAPICustomError(); - expect(error.message).toBe('This is a custom error (code 1001).'); -}); diff --git a/dist/esm/main.d.ts b/dist/esm/main.d.ts index c6d48d4..57ccbc3 100644 --- a/dist/esm/main.d.ts +++ b/dist/esm/main.d.ts @@ -1,6 +1,6 @@ -import type { HyperAPIDriver, InferDriverRequest } from './driver'; -import type { HyperAPIModule } from './module'; -import type { HyperAPIRequest } from './request'; +import type { HyperAPIDriver, InferDriverRequest } from './driver.js'; +import type { HyperAPIModule } from './module.js'; +import type { HyperAPIRequest } from './request.js'; export declare class HyperAPI, R extends InferDriverRequest, M extends HyperAPIModule = HyperAPIModule> { private router; private driver; @@ -38,9 +38,9 @@ export declare class HyperAPI, R exten /** Destroys the HyperAPI instance. */ destroy(): void; } -export * from './api-errors'; -export type { HyperAPIDriver, HyperAPIDriverHandler, } from './driver'; -export { HyperAPIError } from './error'; -export type { HyperAPIModule, InferModule, } from './module'; -export type { HyperAPIRequest, HyperAPIRequestArgs, } from './request'; -export type { HyperAPIResponse } from './response'; +export * from './api-errors.js'; +export type { HyperAPIDriver, HyperAPIDriverHandler, } from './driver.js'; +export { HyperAPIError } from './error.js'; +export type { HyperAPIModule, InferModule, } from './module.js'; +export type { HyperAPIRequest, HyperAPIRequestArgs, } from './request.js'; +export type { HyperAPIResponse } from './response.js'; diff --git a/dist/esm/main.js b/dist/esm/main.js index 48660b9..75cc88b 100644 --- a/dist/esm/main.js +++ b/dist/esm/main.js @@ -1,7 +1,7 @@ import nodePath from 'node:path'; -import { HyperAPIInternalError, HyperAPIUnknownMethodError, } from './api-errors'; -import { HyperAPIError } from './error'; -import { createRouter, useRouter, } from './router'; +import { HyperAPIInternalError, HyperAPIUnknownMethodError, } from './api-errors.js'; +import { HyperAPIError } from './error.js'; +import { createRouter, useRouter, } from './router.js'; const ENTRYPOINT_PATH = nodePath.dirname(process.argv[1]); export class HyperAPI { router; @@ -133,5 +133,5 @@ export class HyperAPI { this.handlers.response.splice(0); } } -export * from './api-errors'; -export { HyperAPIError } from './error'; +export * from './api-errors.js'; +export { HyperAPIError } from './error.js'; diff --git a/dist/esm/main.test.d.ts b/dist/esm/main.test.d.ts deleted file mode 100644 index cb0ff5c..0000000 --- a/dist/esm/main.test.d.ts +++ /dev/null @@ -1 +0,0 @@ -export {}; diff --git a/dist/esm/main.test.js b/dist/esm/main.test.js deleted file mode 100644 index 516ab4d..0000000 --- a/dist/esm/main.test.js +++ /dev/null @@ -1,143 +0,0 @@ -import { afterAll, describe, test, expect, } from 'vitest'; -import { driver, hyperApi, } from '../test/setup'; -afterAll(() => { - hyperApi.destroy(); -}); -describe('routing', () => { - describe('methods', () => { - test('ALL', async () => { - const result = await driver.trigger('GET', 'echo', { - name: 'world', - }); - expect(result).toStrictEqual([ - true, - { - method: 'ALL', - message: 'Hello, world!', - }, - ]); - }); - test('POST', async () => { - const result = await driver.trigger('POST', 'echo', { - name: 'deadbeef', - }); - expect(result).toStrictEqual([ - true, - { - method: 'POST', - message: 'Hello, deadbeef!', - }, - ]); - }); - }); - // test('method in directory', async () => { - // const result = await request( - // 'dir/nested', - // ); - // expect(result).toStrictEqual([ - // true, - // { - // ok: true, - // }, - // ]); - // }); - // test('correct request (async)', async () => { - // const result = await request( - // 'echo.async', - // { - // name: 'user', - // }, - // ); - // expect(result).toStrictEqual([ - // true, - // { - // message: 'Hello, user!', - // }, - // ]); - // }); - // test('invalid arguments', async () => { - // const result = await request( - // 'echo', - // { - // name: 123, - // }, - // ); - // expect(result).toStrictEqual([ - // false, - // { - // code: 2, - // description: 'One of the parameters specified was missing or invalid', - // }, - // ]); - // }); - // test('missing arguments', async () => { - // const result = await request('echo'); - // expect(result).toStrictEqual([ - // false, - // { - // code: 2, - // description: 'One of the parameters specified was missing or invalid', - // }, - // ]); - // }); - // test('api error', async () => { - // const result = await request('error.api'); - // expect(result).toStrictEqual([ - // false, - // { - // code: 10, - // description: 'Endpoint is busy', - // }, - // ]); - // }); - // test('internal error', async () => { - // const result = await request('error.internal'); - // expect(result).toStrictEqual([ - // false, - // { - // code: 3, - // description: 'Internal error', - // }, - // ]); - // }); - // test('invalid return type', async () => { - // const result = await request('error.type'); - // expect(result).toStrictEqual([ - // false, - // { - // code: 3, - // description: 'Internal error', - // }, - // ]); - // }); - // test('unknown method', async () => { - // const result = await request('error.unknown-method'); - // expect(result).toStrictEqual([ - // false, - // { - // code: 5, - // description: 'Unknown method called', - // }, - // ]); - // }); - // test('invalid import path inside module', async () => { - // const result = await request('error.import.path'); - // expect(result).toStrictEqual([ - // false, - // { - // code: 3, - // description: 'Internal error', - // }, - // ]); - // }); - // test('invalid import field inside module', async () => { - // const result = await request('error.import.field'); - // expect(result).toStrictEqual([ - // false, - // { - // code: 3, - // description: 'Internal error', - // }, - // ]); - // }); -}); diff --git a/dist/esm/module.d.ts b/dist/esm/module.d.ts index ca33951..53c3d43 100644 --- a/dist/esm/module.d.ts +++ b/dist/esm/module.d.ts @@ -1,6 +1,6 @@ -import { HyperAPI } from './main'; -import type { HyperAPIRequest, HyperAPIRequestArgs } from './request'; -import type { MaybePromise } from './utils/types'; +import { HyperAPI } from './main.js'; +import type { HyperAPIRequest, HyperAPIRequestArgs } from './request.js'; +import type { MaybePromise } from './utils/types.js'; export type HyperAPIModuleResponse = Record | unknown[] | undefined; export interface HyperAPIModule> { readonly default: (request: R) => MaybePromise; diff --git a/dist/esm/request.d.ts b/dist/esm/request.d.ts index 4ead616..826789a 100644 --- a/dist/esm/request.d.ts +++ b/dist/esm/request.d.ts @@ -1,4 +1,4 @@ -import type { EmptyObject, HTTPMethod } from './utils/types'; +import type { EmptyObject, HTTPMethod } from './utils/types.js'; export type HyperAPIRequestArgs = Record; export interface HyperAPIRequest { method: HTTPMethod; diff --git a/dist/esm/response.d.ts b/dist/esm/response.d.ts index 9b61a74..4954640 100644 --- a/dist/esm/response.d.ts +++ b/dist/esm/response.d.ts @@ -1,3 +1,3 @@ -import { HyperAPIError } from './error'; -import { HyperAPIModuleResponse } from './module'; +import { HyperAPIError } from './error.js'; +import { HyperAPIModuleResponse } from './module.js'; export type HyperAPIResponse = HyperAPIModuleResponse | HyperAPIError; diff --git a/dist/esm/router.d.ts b/dist/esm/router.d.ts index 1c3f152..5e30242 100644 --- a/dist/esm/router.d.ts +++ b/dist/esm/router.d.ts @@ -1,5 +1,5 @@ import { type IRequest, type IttyRouterType } from 'itty-router'; -import { HTTPMethod } from './utils/types'; +import { HTTPMethod } from './utils/types.js'; /** * Creates new IttyRouter from filesystem. * @param path The path to scan. diff --git a/package.json b/package.json index 89f5d2e..33983bc 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@hyperapi/core", - "version": "0.3.0-beta.2", + "version": "0.3.0-beta.3", "description": "Core package of the HyperAPI project.", "publishConfig": { "access": "public" @@ -21,7 +21,7 @@ "itty-router": "^5.0.18" }, "devDependencies": { - "@kirick/eslint-config": "latest", + "@kirick/eslint-config": "^0.1.30", "@types/bun": "^1.1.9", "@types/node": "^22.5.5", "eslint": "9.10.0", @@ -32,7 +32,7 @@ "scripts": { "build": "rm -r dist ; bun run build:ts && bun run build:cjs", "build:cjs": "bunx esbuild --bundle --platform=node --format=cjs --packages=external --outfile=dist/main.cjs dist/esm/main.js", - "build:ts": "rm -r dist/esm ; tsc && (mv dist/esm/src dist/.esm && rm -r dist/esm && mv dist/.esm dist/esm)", + "build:ts": "rm -r dist/esm ; tsc", "lint": "eslint . && tsc --skipLibCheck --noemit", "publish:npm": "bun run build && bun run lint && bun run test && npm publish", "test": "npm run test:vitest && bun test --coverage src/ test/", diff --git a/src/api-errors.ts b/src/api-errors.ts index b92140f..99f3375 100644 --- a/src/api-errors.ts +++ b/src/api-errors.ts @@ -1,7 +1,7 @@ import { type ErrorData, HyperAPIError, -} from './error'; +} from './error.js'; export class HyperAPIAuthorizationError extends HyperAPIError { code = 1; diff --git a/src/driver.ts b/src/driver.ts index f9fd077..31fe25e 100644 --- a/src/driver.ts +++ b/src/driver.ts @@ -1,10 +1,10 @@ import type { HyperAPIRequest, -} from './request'; -import type { HyperAPIResponse } from './response'; +} from './request.js'; +import type { HyperAPIResponse } from './response.js'; import { MaybePromise, -} from './utils/types'; +} from './utils/types.js'; export type HyperAPIDriverHandler = (request: R) => MaybePromise; diff --git a/src/error.test.ts b/src/error.test.ts index f334213..07745bf 100644 --- a/src/error.test.ts +++ b/src/error.test.ts @@ -4,7 +4,7 @@ import { test, expect, } from 'vitest'; -import { HyperAPIError } from './error'; +import { HyperAPIError } from './error.js'; class HyperAPICustomError extends HyperAPIError { code = 1001; diff --git a/src/error.ts b/src/error.ts index 059a80f..87f673f 100644 --- a/src/error.ts +++ b/src/error.ts @@ -1,4 +1,4 @@ -import { isRecord } from './utils/is-record'; +import { isRecord } from './utils/is-record.js'; interface HyperAPIErrorResponse { code: number; diff --git a/src/main.test.ts b/src/main.test.ts index 79380e5..bafc939 100644 --- a/src/main.test.ts +++ b/src/main.test.ts @@ -7,7 +7,7 @@ import { import { driver, hyperApi, -} from '../test/setup'; +} from '../test/setup.js'; afterAll(() => { hyperApi.destroy(); diff --git a/src/main.ts b/src/main.ts index 8621df0..be85de3 100644 --- a/src/main.ts +++ b/src/main.ts @@ -1,22 +1,21 @@ - import nodePath from 'node:path'; import { HyperAPIInternalError, HyperAPIUnknownMethodError, -} from './api-errors'; +} from './api-errors.js'; import type { HyperAPIDriver, InferDriverRequest, -} from './driver'; -import { HyperAPIError } from './error'; -import type { HyperAPIModule } from './module'; -import type { HyperAPIRequest } from './request'; -import type { HyperAPIResponse } from './response'; +} from './driver.js'; +import { HyperAPIError } from './error.js'; +import type { HyperAPIModule } from './module.js'; +import type { HyperAPIRequest } from './request.js'; +import type { HyperAPIResponse } from './response.js'; import { createRouter, useRouter, -} from './router'; -import type { MaybePromise } from './utils/types'; +} from './router.js'; +import type { MaybePromise } from './utils/types.js'; interface HyperAPIHandlers< D extends HyperAPIDriver, @@ -208,20 +207,20 @@ export class HyperAPI< } } -export * from './api-errors'; +export * from './api-errors.js'; export type { HyperAPIDriver, HyperAPIDriverHandler, -} from './driver'; -export { HyperAPIError } from './error'; +} from './driver.js'; +export { HyperAPIError } from './error.js'; export type { HyperAPIModule, // HyperAPIModuleRequest, // HyperAPIModuleResponse, InferModule, -} from './module'; +} from './module.js'; export type { HyperAPIRequest, HyperAPIRequestArgs, -} from './request'; -export type { HyperAPIResponse } from './response'; +} from './request.js'; +export type { HyperAPIResponse } from './response.js'; diff --git a/src/module.ts b/src/module.ts index 23b2f0e..de31c7f 100644 --- a/src/module.ts +++ b/src/module.ts @@ -1,11 +1,11 @@ -import { HyperAPI } from './main'; +import { HyperAPI } from './main.js'; import type { HyperAPIRequest, HyperAPIRequestArgs, -} from './request'; +} from './request.js'; import type { MaybePromise, -} from './utils/types'; +} from './utils/types.js'; export type HyperAPIModuleResponse = Record | unknown[] | undefined; diff --git a/src/request.ts b/src/request.ts index 0a67ebd..a592eed 100644 --- a/src/request.ts +++ b/src/request.ts @@ -1,7 +1,7 @@ import type { EmptyObject, HTTPMethod, -} from './utils/types'; +} from './utils/types.js'; export type HyperAPIRequestArgs = Record; diff --git a/src/response.ts b/src/response.ts index e9c75ef..4168fdc 100644 --- a/src/response.ts +++ b/src/response.ts @@ -1,5 +1,5 @@ -import { HyperAPIError } from './error'; -import { HyperAPIModuleResponse } from './module'; +import { HyperAPIError } from './error.js'; +import { HyperAPIModuleResponse } from './module.js'; // eslint-disable-next-line @typescript-eslint/no-explicit-any export type HyperAPIResponse = HyperAPIModuleResponse | HyperAPIError; diff --git a/src/router.ts b/src/router.ts index 9fe18db..6c51807 100644 --- a/src/router.ts +++ b/src/router.ts @@ -4,10 +4,10 @@ import { IttyRouter, type IRequest, type IttyRouterType, -} from 'itty-router'; -import { readdirSync } from 'node:fs'; -import nodePath from 'node:path'; -import { HTTPMethod } from './utils/types'; +} from 'itty-router'; +import { readdirSync } from 'node:fs'; +import nodePath from 'node:path'; +import { HTTPMethod } from './utils/types.js'; /** * Creates new IttyRouter from filesystem. diff --git a/test/hyper-api/echo.[post].ts b/test/hyper-api/echo.[post].ts index 1013f02..3598d04 100644 --- a/test/hyper-api/echo.[post].ts +++ b/test/hyper-api/echo.[post].ts @@ -5,8 +5,8 @@ import type { HyperAPIRequest, HyperAPIResponse, InferModule, -} from '../../src/main'; -import { hyperApi } from '../setup'; +} from '../../src/main.js'; +import { hyperApi } from '../setup.js'; type Module = InferModule; diff --git a/test/hyper-api/echo.ts b/test/hyper-api/echo.ts index 2066b16..ede38c3 100644 --- a/test/hyper-api/echo.ts +++ b/test/hyper-api/echo.ts @@ -1,8 +1,8 @@ /* eslint-disable jsdoc/require-jsdoc */ import * as v from 'valibot'; -import { type HyperAPIResponse } from '../../src/main'; -import { type LocalRequest } from '../setup'; +import { type HyperAPIResponse } from '../../src/main.js'; +import { type LocalRequest } from '../setup.js'; export default function (request: LocalRequest>): HyperAPIResponse { return { diff --git a/test/hyper-api/errors/api.test.ts b/test/hyper-api/errors/api.test.ts index 890778c..5e1886b 100644 --- a/test/hyper-api/errors/api.test.ts +++ b/test/hyper-api/errors/api.test.ts @@ -3,7 +3,7 @@ import { expect, test, } from 'vitest'; -import { driver } from '../../setup'; +import { driver } from '../../setup.js'; test('error', async () => { const result = await driver.trigger( diff --git a/test/hyper-api/errors/api.ts b/test/hyper-api/errors/api.ts index 6356165..3c3a4e7 100644 --- a/test/hyper-api/errors/api.ts +++ b/test/hyper-api/errors/api.ts @@ -1,8 +1,8 @@ /* eslint-disable jsdoc/require-jsdoc */ import * as v from 'valibot'; -import { HyperAPIBusyError } from '../../../src/api-errors'; -import { type LocalRequest } from '../../setup'; +import { HyperAPIBusyError } from '../../../src/api-errors.js'; +import { type LocalRequest } from '../../setup.js'; export default function (request: LocalRequest>) { throw new HyperAPIBusyError( diff --git a/test/hyper-api/errors/internal.test.ts b/test/hyper-api/errors/internal.test.ts index 6c75021..664b216 100644 --- a/test/hyper-api/errors/internal.test.ts +++ b/test/hyper-api/errors/internal.test.ts @@ -3,7 +3,7 @@ import { expect, test, } from 'vitest'; -import { driver } from '../../setup'; +import { driver } from '../../setup.js'; test('internal error', async () => { const result = await driver.trigger( diff --git a/test/setup.ts b/test/setup.ts index 4e29ce0..5200720 100644 --- a/test/setup.ts +++ b/test/setup.ts @@ -6,11 +6,11 @@ import { HyperAPIModule, HyperAPIRequest, HyperAPIRequestArgs, -} from '../src/main'; +} from '../src/main.js'; import type { EmptyObject, HTTPMethod, -} from '../src/utils/types'; +} from '../src/utils/types.js'; interface DriverRequest extends HyperAPIRequest { foo: string; diff --git a/test/tsconfig.json b/test/tsconfig.json new file mode 100644 index 0000000..4efefea --- /dev/null +++ b/test/tsconfig.json @@ -0,0 +1,18 @@ +{ + "compileOnSave": false, + "compilerOptions": { + "outDir": "/dev/null", + "declaration": false, + "target": "esnext", + "module": "esnext", + "lib": [ + "ESNext", + "ES2021.String" + ], + "moduleResolution": "node", + "allowSyntheticDefaultImports": true, + "skipLibCheck": true, + "strict": true, + "removeComments": false + } +} diff --git a/tsconfig.json b/tsconfig.json index c00281e..5b2b5b4 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -1,24 +1,25 @@ { "compileOnSave": false, "include": [ - "src/", - "test/" + "src/" ], "exclude": [ "dist/", - "node_modules/" + "node_modules/", + "test/", + "**/*.test.*" ], "compilerOptions": { "outDir": "dist/esm", "declaration": true, "declarationDir": "dist/esm", "target": "esnext", - "module": "esnext", + "module": "nodenext", "lib": [ "ESNext", "ES2021.String" ], - "moduleResolution": "node", + "esModuleInterop": true, "allowSyntheticDefaultImports": true, "skipLibCheck": true, "strict": true, From 5a97bfe689eb5aefb5f235a59b1b5e492badb21e Mon Sep 17 00:00:00 2001 From: Daniil Kirichenko Date: Thu, 19 Sep 2024 01:20:54 +0300 Subject: [PATCH 21/57] Updated `package.json` --- bun.lockb | Bin 118712 -> 118320 bytes package.json | 3 +-- tsconfig.json | 4 ++-- 3 files changed, 3 insertions(+), 4 deletions(-) diff --git a/bun.lockb b/bun.lockb index 167dc82f0d486ab35eef61a2cb65b956cde11a14..49623977e8b5daf22f23a534f0c972afe9248045 100755 GIT binary patch delta 12801 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 Date: Thu, 19 Sep 2024 16:22:05 +0300 Subject: [PATCH 22/57] [v0.3.0-beta.4] exported HyperAPI methods allowed to use --- package.json | 2 +- src/main.ts | 4 ++++ src/request.ts | 6 ++++-- src/router.ts | 6 +++--- src/utils/methods.ts | 17 +++++++++++++++++ src/utils/types.ts | 2 -- 6 files changed, 29 insertions(+), 8 deletions(-) create mode 100644 src/utils/methods.ts diff --git a/package.json b/package.json index 6157e2c..6822f32 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@hyperapi/core", - "version": "0.3.0-beta.3", + "version": "0.3.0-beta.4", "description": "Core package of the HyperAPI project.", "publishConfig": { "access": "public" diff --git a/src/main.ts b/src/main.ts index be85de3..f8ae7eb 100644 --- a/src/main.ts +++ b/src/main.ts @@ -224,3 +224,7 @@ export type { HyperAPIRequestArgs, } from './request.js'; export type { HyperAPIResponse } from './response.js'; +export { + isHyperApiMethod, + type HyperAPIMethod, +} from './utils/methods.js'; diff --git a/src/request.ts b/src/request.ts index a592eed..6b169db 100644 --- a/src/request.ts +++ b/src/request.ts @@ -1,6 +1,8 @@ +import type { + HyperAPIMethod, +} from './utils/methods.js'; import type { EmptyObject, - HTTPMethod, } from './utils/types.js'; export type HyperAPIRequestArgs = Record; @@ -8,7 +10,7 @@ export type HyperAPIRequestArgs = Record; export interface HyperAPIRequest< A extends HyperAPIRequestArgs = EmptyObject, > { - method: HTTPMethod; + method: HyperAPIMethod; path: string; args: A; } diff --git a/src/router.ts b/src/router.ts index 6c51807..599ba88 100644 --- a/src/router.ts +++ b/src/router.ts @@ -7,7 +7,7 @@ import { } from 'itty-router'; import { readdirSync } from 'node:fs'; import nodePath from 'node:path'; -import { HTTPMethod } from './utils/types.js'; +import { HyperAPIMethod } from './utils/methods.js'; /** * Creates new IttyRouter from filesystem. @@ -37,7 +37,7 @@ interface RouterResponse { */ export function useRouter( router: IttyRouterType, - method: HTTPMethod, + method: HyperAPIMethod, path: string, ) { return router.fetch({ @@ -51,7 +51,7 @@ const REGEXP_HTTP_METHOD = /\.\[(delete|get|head|options|patch|post|put)]$/; const REGEXP_PATH_SLUG = /\[(\w+)]/g; interface Route { - method: Lowercase> | 'all'; + method: Lowercase> | 'all'; path: string; module_path: string; } diff --git a/src/utils/methods.ts b/src/utils/methods.ts new file mode 100644 index 0000000..7f1c371 --- /dev/null +++ b/src/utils/methods.ts @@ -0,0 +1,17 @@ +export type HyperAPIMethod = 'DELETE' | 'GET' | 'HEAD' | 'OPTIONS' | 'PATCH' | 'POST' | 'PUT' | 'UNKNOWN'; + +/** + * Checks if the given value is a valid HyperAPI method. + * @param method The HTTP method to check. + * @returns - + */ +export function isHyperApiMethod(method: unknown): method is HyperAPIMethod { + return method === 'DELETE' + || method === 'GET' + || method === 'HEAD' + || method === 'OPTIONS' + || method === 'PATCH' + || method === 'POST' + || method === 'PUT' + || method === 'UNKNOWN'; +} diff --git a/src/utils/types.ts b/src/utils/types.ts index fd4b055..ed6ddd3 100644 --- a/src/utils/types.ts +++ b/src/utils/types.ts @@ -1,4 +1,2 @@ export type EmptyObject = Omit<{ p: never }, 'p'>; export type MaybePromise = T | Promise; - -export type HTTPMethod = 'DELETE' | 'GET' | 'HEAD' | 'OPTIONS' | 'PATCH' | 'POST' | 'PUT' | 'UNKNOWN'; From b044a3296fdaa96f77b682b8336759c7f528e23f Mon Sep 17 00:00:00 2001 From: Eronary Date: Fri, 28 Feb 2025 15:27:07 +0300 Subject: [PATCH 23/57] Add type Response for Response, up Node version --- package.json | 2 +- src/module.ts | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/package.json b/package.json index 6822f32..0d93146 100644 --- a/package.json +++ b/package.json @@ -15,7 +15,7 @@ } }, "engines": { - "node": ">=15.4.0" + "node": ">=21.0.0" }, "dependencies": { "itty-router": "^5.0.18" diff --git a/src/module.ts b/src/module.ts index de31c7f..ca6a0b9 100644 --- a/src/module.ts +++ b/src/module.ts @@ -7,7 +7,7 @@ import type { MaybePromise, } from './utils/types.js'; -export type HyperAPIModuleResponse = Record | unknown[] | undefined; +export type HyperAPIModuleResponse = Record | Response | unknown[] | undefined; export interface HyperAPIModule> { readonly default: (request: R) => MaybePromise; From c7ef7fbfe41463086a03a87c16c46b1e78e4e4bb Mon Sep 17 00:00:00 2001 From: Daniil Kirichenko Date: Fri, 28 Feb 2025 15:38:19 +0300 Subject: [PATCH 24/57] Update npm-publish.yml --- .github/workflows/npm-publish.yml | 108 ++++++++++++++++++++++++++++-- 1 file changed, 104 insertions(+), 4 deletions(-) diff --git a/.github/workflows/npm-publish.yml b/.github/workflows/npm-publish.yml index 1027d77..f23335f 100644 --- a/.github/workflows/npm-publish.yml +++ b/.github/workflows/npm-publish.yml @@ -1,19 +1,119 @@ name: Publish NPM Package on: - - push + push: + branches: + - main + - beta + - 'dev-*' + pull_request: + branches: + - main + - beta + - 'dev-*' + +env: + BUN_VERSION: 1.2.2 + NODE_VERSION: 22 jobs: - build: + version: + runs-on: ubuntu-latest + outputs: + npm_tag: ${{ steps.set-tag.outputs.npm_tag }} + steps: + - uses: actions/checkout@v4 + + - name: Determine NPM tag + id: set-tag + run: | + VERSION=$(node -p "require('./package.json').version") + + if [[ $VERSION == *"-beta."* ]]; then + NPM_TAG="beta" + elif [[ $VERSION =~ ^[0-9]+\.[0-9]+\.[0-9]+$ ]]; then + NPM_TAG="latest" + else + NPM_TAG="dev" + fi + + echo "Detected version: $VERSION" + echo "NPM tag: $NPM_TAG" + echo "npm_tag=$NPM_TAG" >> $GITHUB_OUTPUT + + - name: Validate branch and tag + if: | + (github.event_name == 'push' && (github.ref == 'refs/heads/main' || github.ref == 'refs/heads/beta')) + || (github.event_name == 'pull_request' && (github.base_ref == 'main' || github.base_ref == 'beta')) + run: | + if [[ "${{ github.event_name }}" == "push" ]]; then + BRANCH=${GITHUB_REF#refs/heads/} + else + BRANCH=${{ github.base_ref }} + fi + + NPM_TAG=${{ steps.set-tag.outputs.npm_tag }} + + if [[ $BRANCH == "main" && $NPM_TAG != "latest" ]] || \ + [[ $BRANCH == "beta" && $NPM_TAG != "beta" ]]; then + echo "Error: Version tag $NPM_TAG doesn't match branch $BRANCH" + exit 1 + fi + + check: + needs: [version] runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + + - name: Set up Bun + uses: oven-sh/setup-bun@v2 + with: + bun-version: ${{ env.BUN_VERSION }} + + - name: Install dependencies + run: bun install --frozen-lockfile + + - name: Lint code + run: bun run lint + + - name: Test code + run: bun run test + + publish: + needs: [version, check] + if: | + github.event_name == 'push' && + (github.ref == 'refs/heads/main' || github.ref == 'refs/heads/beta') permissions: contents: read id-token: write + runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 - - uses: kirick13/build-npm-package-action@v1 + + - name: Set up Node.js + uses: actions/setup-node@v4 with: - npm-token: ${{ secrets.NPM_TOKEN }} + node-version: ${{ env.NODE_VERSION }} + registry-url: https://registry.npmjs.org/ + + - name: Set up Bun + uses: oven-sh/setup-bun@v2 + with: + bun-version: ${{ env.BUN_VERSION }} + + - name: Install dependencies + run: bun install --frozen-lockfile + + - name: Build code + run: bun run build + + - name: Publish to NPM + run: npm publish --access public --provenance --tag ${{ needs.version.outputs.npm_tag }} + env: + NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }} + - uses: kirick13/notify-action@v1 with: telegram-bot-token: ${{ secrets.TELEGRAM_BOT_TOKEN }} From bf5d1ce6857b026fdda5ad219d232acac8008e7d Mon Sep 17 00:00:00 2001 From: Daniil Kirichenko Date: Fri, 28 Feb 2025 15:39:45 +0300 Subject: [PATCH 25/57] New action --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 0d93146..7a1d1eb 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@hyperapi/core", - "version": "0.3.0-beta.4", + "version": "0.3.0-dev", "description": "Core package of the HyperAPI project.", "publishConfig": { "access": "public" From 56fed457ae60751024729c8b690441d95a10e589 Mon Sep 17 00:00:00 2001 From: Daniil Kirichenko Date: Fri, 28 Feb 2025 16:41:38 +0300 Subject: [PATCH 26/57] dist :) --- dist/esm/main.d.ts | 1 + dist/esm/main.js | 1 + dist/esm/module.d.ts | 2 +- dist/esm/request.d.ts | 5 +++-- dist/esm/router.d.ts | 4 ++-- dist/esm/utils/methods.d.ts | 7 +++++++ dist/esm/utils/methods.js | 15 +++++++++++++++ dist/esm/utils/types.d.ts | 1 - dist/main.cjs | 11 +++++++++-- 9 files changed, 39 insertions(+), 8 deletions(-) create mode 100644 dist/esm/utils/methods.d.ts create mode 100644 dist/esm/utils/methods.js diff --git a/dist/esm/main.d.ts b/dist/esm/main.d.ts index 57ccbc3..0f5e51d 100644 --- a/dist/esm/main.d.ts +++ b/dist/esm/main.d.ts @@ -44,3 +44,4 @@ export { HyperAPIError } from './error.js'; export type { HyperAPIModule, InferModule, } from './module.js'; export type { HyperAPIRequest, HyperAPIRequestArgs, } from './request.js'; export type { HyperAPIResponse } from './response.js'; +export { isHyperApiMethod, type HyperAPIMethod, } from './utils/methods.js'; diff --git a/dist/esm/main.js b/dist/esm/main.js index 75cc88b..5a8519f 100644 --- a/dist/esm/main.js +++ b/dist/esm/main.js @@ -135,3 +135,4 @@ export class HyperAPI { } export * from './api-errors.js'; export { HyperAPIError } from './error.js'; +export { isHyperApiMethod, } from './utils/methods.js'; diff --git a/dist/esm/module.d.ts b/dist/esm/module.d.ts index 53c3d43..f0e1dde 100644 --- a/dist/esm/module.d.ts +++ b/dist/esm/module.d.ts @@ -1,7 +1,7 @@ import { HyperAPI } from './main.js'; import type { HyperAPIRequest, HyperAPIRequestArgs } from './request.js'; import type { MaybePromise } from './utils/types.js'; -export type HyperAPIModuleResponse = Record | unknown[] | undefined; +export type HyperAPIModuleResponse = Record | Response | unknown[] | undefined; export interface HyperAPIModule> { readonly default: (request: R) => MaybePromise; readonly argsValidator: (args: unknown) => R extends HyperAPIRequest ? A : never; diff --git a/dist/esm/request.d.ts b/dist/esm/request.d.ts index 826789a..1456c0a 100644 --- a/dist/esm/request.d.ts +++ b/dist/esm/request.d.ts @@ -1,7 +1,8 @@ -import type { EmptyObject, HTTPMethod } from './utils/types.js'; +import type { HyperAPIMethod } from './utils/methods.js'; +import type { EmptyObject } from './utils/types.js'; export type HyperAPIRequestArgs = Record; export interface HyperAPIRequest { - method: HTTPMethod; + method: HyperAPIMethod; path: string; args: A; } diff --git a/dist/esm/router.d.ts b/dist/esm/router.d.ts index 5e30242..dc22873 100644 --- a/dist/esm/router.d.ts +++ b/dist/esm/router.d.ts @@ -1,5 +1,5 @@ import { type IRequest, type IttyRouterType } from 'itty-router'; -import { HTTPMethod } from './utils/types.js'; +import { HyperAPIMethod } from './utils/methods.js'; /** * Creates new IttyRouter from filesystem. * @param path The path to scan. @@ -17,5 +17,5 @@ interface RouterResponse { * @param path The path to fetch data from. * @returns The response. */ -export declare function useRouter(router: IttyRouterType, method: HTTPMethod, path: string): Promise; +export declare function useRouter(router: IttyRouterType, method: HyperAPIMethod, path: string): Promise; export {}; diff --git a/dist/esm/utils/methods.d.ts b/dist/esm/utils/methods.d.ts new file mode 100644 index 0000000..27e89a3 --- /dev/null +++ b/dist/esm/utils/methods.d.ts @@ -0,0 +1,7 @@ +export type HyperAPIMethod = 'DELETE' | 'GET' | 'HEAD' | 'OPTIONS' | 'PATCH' | 'POST' | 'PUT' | 'UNKNOWN'; +/** + * Checks if the given value is a valid HyperAPI method. + * @param method The HTTP method to check. + * @returns - + */ +export declare function isHyperApiMethod(method: unknown): method is HyperAPIMethod; diff --git a/dist/esm/utils/methods.js b/dist/esm/utils/methods.js new file mode 100644 index 0000000..3266c72 --- /dev/null +++ b/dist/esm/utils/methods.js @@ -0,0 +1,15 @@ +/** + * Checks if the given value is a valid HyperAPI method. + * @param method The HTTP method to check. + * @returns - + */ +export function isHyperApiMethod(method) { + return method === 'DELETE' + || method === 'GET' + || method === 'HEAD' + || method === 'OPTIONS' + || method === 'PATCH' + || method === 'POST' + || method === 'PUT' + || method === 'UNKNOWN'; +} diff --git a/dist/esm/utils/types.d.ts b/dist/esm/utils/types.d.ts index d050ecd..a6078fe 100644 --- a/dist/esm/utils/types.d.ts +++ b/dist/esm/utils/types.d.ts @@ -2,4 +2,3 @@ export type EmptyObject = Omit<{ p: never; }, 'p'>; export type MaybePromise = T | Promise; -export type HTTPMethod = 'DELETE' | 'GET' | 'HEAD' | 'OPTIONS' | 'PATCH' | 'POST' | 'PUT' | 'UNKNOWN'; diff --git a/dist/main.cjs b/dist/main.cjs index 41ed216..681e6be 100644 --- a/dist/main.cjs +++ b/dist/main.cjs @@ -43,7 +43,8 @@ __export(main_exports, { HyperAPIOTPError: () => HyperAPIOTPError, HyperAPIObjectsLimitError: () => HyperAPIObjectsLimitError, HyperAPIRateLimitError: () => HyperAPIRateLimitError, - HyperAPIUnknownMethodError: () => HyperAPIUnknownMethodError + HyperAPIUnknownMethodError: () => HyperAPIUnknownMethodError, + isHyperApiMethod: () => isHyperApiMethod }); module.exports = __toCommonJS(main_exports); var import_node_path2 = __toESM(require("node:path"), 1); @@ -245,6 +246,11 @@ function scanDirectory(router, path, regexp_parts = [""]) { } } +// dist/esm/utils/methods.js +function isHyperApiMethod(method) { + return method === "DELETE" || method === "GET" || method === "HEAD" || method === "OPTIONS" || method === "PATCH" || method === "POST" || method === "PUT" || method === "UNKNOWN"; +} + // dist/esm/main.js var ENTRYPOINT_PATH = import_node_path2.default.dirname(process.argv[1]); var HyperAPI = class { @@ -379,5 +385,6 @@ var HyperAPI = class { HyperAPIOTPError, HyperAPIObjectsLimitError, HyperAPIRateLimitError, - HyperAPIUnknownMethodError + HyperAPIUnknownMethodError, + isHyperApiMethod }); From d8b753edc246919be9b2f026a78013335c71d310 Mon Sep 17 00:00:00 2001 From: Daniil Kirichenko Date: Fri, 28 Feb 2025 16:44:44 +0300 Subject: [PATCH 27/57] bun build --- dist/main.cjs | 239 +++++++++++++++++++++----------------------------- package.json | 3 +- 2 files changed, 100 insertions(+), 142 deletions(-) diff --git a/dist/main.cjs b/dist/main.cjs index 681e6be..268b22b 100644 --- a/dist/main.cjs +++ b/dist/main.cjs @@ -1,53 +1,65 @@ -"use strict"; var __create = Object.create; +var __getProtoOf = Object.getPrototypeOf; var __defProp = Object.defineProperty; -var __getOwnPropDesc = Object.getOwnPropertyDescriptor; var __getOwnPropNames = Object.getOwnPropertyNames; -var __getProtoOf = Object.getPrototypeOf; +var __getOwnPropDesc = Object.getOwnPropertyDescriptor; var __hasOwnProp = Object.prototype.hasOwnProperty; +var __toESM = (mod, isNodeMode, target) => { + target = mod != null ? __create(__getProtoOf(mod)) : {}; + const to = isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target; + for (let key of __getOwnPropNames(mod)) + if (!__hasOwnProp.call(to, key)) + __defProp(to, key, { + get: () => mod[key], + enumerable: true + }); + return to; +}; +var __moduleCache = /* @__PURE__ */ new WeakMap; +var __toCommonJS = (from) => { + var entry = __moduleCache.get(from), desc; + if (entry) + return entry; + entry = __defProp({}, "__esModule", { value: true }); + if (from && typeof from === "object" || typeof from === "function") + __getOwnPropNames(from).map((key) => !__hasOwnProp.call(entry, key) && __defProp(entry, key, { + get: () => from[key], + enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable + })); + __moduleCache.set(from, entry); + return entry; +}; var __export = (target, all) => { for (var name in all) - __defProp(target, name, { get: all[name], enumerable: true }); -}; -var __copyProps = (to, from, except, desc) => { - if (from && typeof from === "object" || typeof from === "function") { - for (let key of __getOwnPropNames(from)) - if (!__hasOwnProp.call(to, key) && key !== except) - __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable }); - } - return to; + __defProp(target, name, { + get: all[name], + enumerable: true, + configurable: true, + set: (newValue) => all[name] = () => newValue + }); }; -var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps( - // If the importer is in node compatibility mode or this is not an ESM - // file that has been converted to a CommonJS file using a Babel- - // compatible transform (i.e. "__esModule" has not been set), then set - // "default" to the CommonJS "module.exports" for node compatibility. - isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target, - mod -)); -var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod); // dist/esm/main.js -var main_exports = {}; -__export(main_exports, { - HyperAPI: () => HyperAPI, - HyperAPIAuthorizationError: () => HyperAPIAuthorizationError, - HyperAPIBusyError: () => HyperAPIBusyError, - HyperAPICaptchaError: () => HyperAPICaptchaError, - HyperAPIConfirmationError: () => HyperAPIConfirmationError, - HyperAPIError: () => HyperAPIError, - HyperAPIForbiddenError: () => HyperAPIForbiddenError, - HyperAPIInternalError: () => HyperAPIInternalError, - HyperAPIInvalidParametersError: () => HyperAPIInvalidParametersError, - HyperAPIMaintenanceError: () => HyperAPIMaintenanceError, - HyperAPIOTPError: () => HyperAPIOTPError, - HyperAPIObjectsLimitError: () => HyperAPIObjectsLimitError, - HyperAPIRateLimitError: () => HyperAPIRateLimitError, +var exports_main = {}; +__export(exports_main, { + isHyperApiMethod: () => isHyperApiMethod, HyperAPIUnknownMethodError: () => HyperAPIUnknownMethodError, - isHyperApiMethod: () => isHyperApiMethod + HyperAPIRateLimitError: () => HyperAPIRateLimitError, + HyperAPIObjectsLimitError: () => HyperAPIObjectsLimitError, + HyperAPIOTPError: () => HyperAPIOTPError, + HyperAPIMaintenanceError: () => HyperAPIMaintenanceError, + HyperAPIInvalidParametersError: () => HyperAPIInvalidParametersError, + HyperAPIInternalError: () => HyperAPIInternalError, + HyperAPIForbiddenError: () => HyperAPIForbiddenError, + HyperAPIError: () => HyperAPIError, + HyperAPIConfirmationError: () => HyperAPIConfirmationError, + HyperAPICaptchaError: () => HyperAPICaptchaError, + HyperAPIBusyError: () => HyperAPIBusyError, + HyperAPIAuthorizationError: () => HyperAPIAuthorizationError, + HyperAPI: () => HyperAPI }); -module.exports = __toCommonJS(main_exports); -var import_node_path2 = __toESM(require("node:path"), 1); +module.exports = __toCommonJS(exports_main); +var import_node_path2 = __toESM(require("node:path")); // dist/esm/utils/is-record.js function isRecord(value) { @@ -55,16 +67,11 @@ function isRecord(value) { } // dist/esm/error.js -var HyperAPIError = class extends Error { - /** The error code. */ +class HyperAPIError extends Error { code = 0; - /** The error description. */ description = "HyperAPI error"; - /** The error data. */ data; - /** HTTP status code. */ httpStatus; - /** HTTP headers to return. */ httpHeaders; constructor(data) { super(); @@ -75,10 +82,6 @@ var HyperAPIError = class extends Error { get message() { return `${this.description} (code ${this.code}).`; } - /** - * Creates response object. - * @returns - - */ getResponse() { const response = { code: this.code @@ -91,88 +94,87 @@ var HyperAPIError = class extends Error { } return response; } -}; +} // dist/esm/api-errors.js -var HyperAPIAuthorizationError = class extends HyperAPIError { +class HyperAPIAuthorizationError extends HyperAPIError { code = 1; description = "Authorization error"; httpStatus = 401; - // Unauthorized -}; -var HyperAPIInvalidParametersError = class extends HyperAPIError { +} + +class HyperAPIInvalidParametersError extends HyperAPIError { code = 2; description = "One of the parameters specified was missing or invalid"; httpStatus = 400; - // Bad Request -}; -var HyperAPIInternalError = class extends HyperAPIError { +} + +class HyperAPIInternalError extends HyperAPIError { code = 3; description = "Internal error"; httpStatus = 500; - // Internal Server Error -}; -var HyperAPIForbiddenError = class extends HyperAPIError { +} + +class HyperAPIForbiddenError extends HyperAPIError { code = 4; description = "You do not have permission to perform this action"; httpStatus = 403; - // Forbidden -}; -var HyperAPIUnknownMethodError = class extends HyperAPIError { +} + +class HyperAPIUnknownMethodError extends HyperAPIError { code = 5; description = "Unknown method called"; httpStatus = 404; - // Not Found -}; -var HyperAPIObjectsLimitError = class extends HyperAPIError { +} + +class HyperAPIObjectsLimitError extends HyperAPIError { code = 6; description = "Too many objects requested"; httpStatus = 400; - // Bad Request -}; -var HyperAPIRateLimitError = class extends HyperAPIError { +} + +class HyperAPIRateLimitError extends HyperAPIError { code = 7; description = "Rate limit exceeded"; httpStatus = 429; - // Too Many Requests -}; -var HyperAPICaptchaError = class extends HyperAPIError { +} + +class HyperAPICaptchaError extends HyperAPIError { code = 8; description = "Captcha required"; httpStatus = 428; - // Precondition Required -}; -var HyperAPIBusyError = class extends HyperAPIError { +} + +class HyperAPIBusyError extends HyperAPIError { code = 10; description = "Endpoint is busy"; httpStatus = 503; - // Service Unavailable -}; -var HyperAPIConfirmationError = class extends HyperAPIError { +} + +class HyperAPIConfirmationError extends HyperAPIError { code = 11; description = "Confirmation required"; httpStatus = 409; - // Conflict -}; -var HyperAPIOTPError = class extends HyperAPIError { +} + +class HyperAPIOTPError extends HyperAPIError { code = 12; description = "One-time password required"; httpStatus = 401; - // Unauthorized -}; -var HyperAPIMaintenanceError = class extends HyperAPIError { +} + +class HyperAPIMaintenanceError extends HyperAPIError { code = 13; description = "Endpoint is in maintenance mode"; httpStatus = 503; - // Service Unavailable -}; +} // dist/esm/router.js var import_itty_router = require("itty-router"); var import_node_fs = require("node:fs"); -var import_node_path = __toESM(require("node:path"), 1); +var import_node_path = __toESM(require("node:path")); function createRouter(path) { - const router = (0, import_itty_router.IttyRouter)(); + const router = import_itty_router.IttyRouter(); scanDirectory(router, path); return router; } @@ -186,18 +188,14 @@ var REGEXP_FILE_EXTENSION = /\.(js|mjs|cjs|ts)$/; var REGEXP_HTTP_METHOD = /\.\[(delete|get|head|options|patch|post|put)]$/; var REGEXP_PATH_SLUG = /\[(\w+)]/g; function scanDirectory(router, path, regexp_parts = [""]) { - const result = (0, import_node_fs.readdirSync)(path, { + const result = import_node_fs.readdirSync(path, { withFileTypes: true }); const routes = { 0: [], - // routes with no method and no slug 1: [], - // routes with method and no slug 2: [], - // routes with no method and slug 3: [] - // routes with method and slug }; for (const entry of result) { const entry_path = import_node_path.default.join(path, entry.name); @@ -245,7 +243,6 @@ function scanDirectory(router, path, regexp_parts = [""]) { }); } } - // dist/esm/utils/methods.js function isHyperApiMethod(method) { return method === "DELETE" || method === "GET" || method === "HEAD" || method === "OPTIONS" || method === "PATCH" || method === "POST" || method === "PUT" || method === "UNKNOWN"; @@ -253,15 +250,10 @@ function isHyperApiMethod(method) { // dist/esm/main.js var ENTRYPOINT_PATH = import_node_path2.default.dirname(process.argv[1]); -var HyperAPI = class { + +class HyperAPI { router; driver; - /** - * Creates a HyperAPI instance. - * @param options The options. - * @param options.driver The driver. - * @param [options.root] The root directory for API methods modules. Default: `hyper-api` directory alongside the entrypoint script. - */ constructor({ driver, root = import_node_path2.default.join(ENTRYPOINT_PATH, "hyper-api") }) { this.driver = driver; this.router = createRouter(root); @@ -281,35 +273,19 @@ var HyperAPI = class { }); } handlers = { - transformer: void 0, + transformer: undefined, module: [], response: [] }; - /** - * Use this hook add properties to the request before it is send to the API module. - * - * This hook can be set only once. - * @param transformer The callback function. - */ setTransformer(transformer) { if (this.handlers.transformer) { throw new Error("Transformer has already been set."); } this.handlers.transformer = transformer; } - /** - * Adds a hook to be called when the API module is imported. - * @param callback - - */ onModule(callback) { this.handlers.module.push(callback); } - /** - * Adds a hook to be called right before the response is sent back. - * - * This hook called only if the request was processed by the API module. If unknown method was requested, this hook is not called. - * @param callback - - */ onResponse(callback) { this.handlers.response.push(callback); } @@ -325,7 +301,7 @@ var HyperAPI = class { return [ request, module_, - new HyperAPIUnknownMethodError() + new HyperAPIUnknownMethodError ]; } driver_request.args = { @@ -358,33 +334,14 @@ var HyperAPI = class { return [ request, module_, - new HyperAPIInternalError() + new HyperAPIInternalError ]; } throw new Error("Unreachable"); } - /** Destroys the HyperAPI instance. */ destroy() { - this.handlers.transformer = void 0; + this.handlers.transformer = undefined; this.handlers.module.splice(0); this.handlers.response.splice(0); } -}; -// Annotate the CommonJS export names for ESM import in node: -0 && (module.exports = { - HyperAPI, - HyperAPIAuthorizationError, - HyperAPIBusyError, - HyperAPICaptchaError, - HyperAPIConfirmationError, - HyperAPIError, - HyperAPIForbiddenError, - HyperAPIInternalError, - HyperAPIInvalidParametersError, - HyperAPIMaintenanceError, - HyperAPIOTPError, - HyperAPIObjectsLimitError, - HyperAPIRateLimitError, - HyperAPIUnknownMethodError, - isHyperApiMethod -}); +} diff --git a/package.json b/package.json index 7a1d1eb..2995ea8 100644 --- a/package.json +++ b/package.json @@ -30,7 +30,8 @@ }, "scripts": { "build": "rm -r dist ; bun run build:ts && bun run build:cjs", - "build:cjs": "bunx esbuild --bundle --platform=node --format=cjs --packages=external --outfile=dist/main.cjs dist/esm/main.js", + "build:cjs": "bun build dist/esm/main.js --platform=node --format=cjs --packages=external --outfile=dist/main.cjs", + "# build:cjs": "bunx esbuild --bundle --platform=node --format=cjs --packages=external --outfile=dist/main.cjs dist/esm/main.js", "build:ts": "rm -r dist/esm ; tsc", "lint": "eslint . && tsc --skipLibCheck --noemit", "publish:npm": "bun run build && bun run lint && bun run test && npm publish", From 1cfb6973df539136b31467c5c2fc5cc85c94ae38 Mon Sep 17 00:00:00 2001 From: Daniil Kirichenko Date: Thu, 17 Apr 2025 10:38:30 +0200 Subject: [PATCH 28/57] Small fixes --- dist/esm/api-errors.d.ts | 31 +++++++++++--------- dist/esm/api-errors.js | 5 ++++ dist/esm/error.d.ts | 6 ++-- dist/esm/main.d.ts | 2 +- dist/esm/main.js | 18 +++++++----- dist/esm/router.js | 4 ++- dist/main.cjs | 23 ++++++++++----- package.json | 2 +- src/api-errors.ts | 32 ++++++++++++--------- src/error.ts | 8 +++--- src/main.test.ts | 33 +++++++++++++++++++-- src/main.ts | 23 +++++++++------ src/router.ts | 6 +++- test/hyper-api/echo.[post].ts | 5 +++- test/hyper-api/echo.ts | 5 +++- test/hyper-api/errors/api.test.ts | 1 - test/hyper-api/errors/internal.test.ts | 1 - test/hyper-api/only-get.[get].ts | 9 ++++++ test/hyper-api/only-get.test.ts | 40 ++++++++++++++++++++++++++ test/setup.ts | 38 +++++++++++++++++------- 20 files changed, 215 insertions(+), 77 deletions(-) create mode 100644 test/hyper-api/only-get.[get].ts create mode 100644 test/hyper-api/only-get.test.ts diff --git a/dist/esm/api-errors.d.ts b/dist/esm/api-errors.d.ts index 62ed9c4..d1a3ad2 100644 --- a/dist/esm/api-errors.d.ts +++ b/dist/esm/api-errors.d.ts @@ -1,60 +1,65 @@ -import { type ErrorData, HyperAPIError } from './error.js'; -export declare class HyperAPIAuthorizationError extends HyperAPIError { +import { type HyperAPIErrorData, HyperAPIError } from './error.js'; +export declare class HyperAPIAuthorizationError extends HyperAPIError { code: number; description: string; httpStatus: number; } -export declare class HyperAPIInvalidParametersError extends HyperAPIError { +export declare class HyperAPIInvalidParametersError extends HyperAPIError { code: number; description: string; httpStatus: number; } -export declare class HyperAPIInternalError extends HyperAPIError { +export declare class HyperAPIInternalError extends HyperAPIError { code: number; description: string; httpStatus: number; } -export declare class HyperAPIForbiddenError extends HyperAPIError { +export declare class HyperAPIForbiddenError extends HyperAPIError { code: number; description: string; httpStatus: number; } -export declare class HyperAPIUnknownMethodError extends HyperAPIError { +export declare class HyperAPIUnknownMethodError extends HyperAPIError { code: number; description: string; httpStatus: number; } -export declare class HyperAPIObjectsLimitError extends HyperAPIError { +export declare class HyperAPIObjectsLimitError extends HyperAPIError { code: number; description: string; httpStatus: number; } -export declare class HyperAPIRateLimitError extends HyperAPIError { +export declare class HyperAPIRateLimitError extends HyperAPIError { code: number; description: string; httpStatus: number; } -export declare class HyperAPICaptchaError extends HyperAPIError { +export declare class HyperAPICaptchaError extends HyperAPIError { code: number; description: string; httpStatus: number; } -export declare class HyperAPIBusyError extends HyperAPIError { +export declare class HyperAPIBusyError extends HyperAPIError { code: number; description: string; httpStatus: number; } -export declare class HyperAPIConfirmationError extends HyperAPIError { +export declare class HyperAPIConfirmationError extends HyperAPIError { code: number; description: string; httpStatus: number; } -export declare class HyperAPIOTPError extends HyperAPIError { +export declare class HyperAPIOTPError extends HyperAPIError { code: number; description: string; httpStatus: number; } -export declare class HyperAPIMaintenanceError extends HyperAPIError { +export declare class HyperAPIMaintenanceError extends HyperAPIError { + code: number; + description: string; + httpStatus: number; +} +export declare class HyperAPIMethodNotAllowedError extends HyperAPIError { code: number; description: string; httpStatus: number; diff --git a/dist/esm/api-errors.js b/dist/esm/api-errors.js index d8f3ab2..7e5b288 100644 --- a/dist/esm/api-errors.js +++ b/dist/esm/api-errors.js @@ -59,3 +59,8 @@ export class HyperAPIMaintenanceError extends HyperAPIError { description = 'Endpoint is in maintenance mode'; httpStatus = 503; // Service Unavailable } +export class HyperAPIMethodNotAllowedError extends HyperAPIError { + code = 14; + description = 'HTTP method not allowed'; + httpStatus = 405; // Method Not Allowed +} diff --git a/dist/esm/error.d.ts b/dist/esm/error.d.ts index 279e608..aebb759 100644 --- a/dist/esm/error.d.ts +++ b/dist/esm/error.d.ts @@ -1,10 +1,10 @@ +export type HyperAPIErrorData = Record | undefined; interface HyperAPIErrorResponse { code: number; description?: string; - data?: Record; + data?: HyperAPIErrorData; } -export type ErrorData = Record | undefined; -export declare class HyperAPIError | undefined> extends Error { +export declare class HyperAPIError extends Error { /** The error code. */ readonly code: number; /** The error description. */ diff --git a/dist/esm/main.d.ts b/dist/esm/main.d.ts index 0f5e51d..976effb 100644 --- a/dist/esm/main.d.ts +++ b/dist/esm/main.d.ts @@ -41,7 +41,7 @@ export declare class HyperAPI, R exten export * from './api-errors.js'; export type { HyperAPIDriver, HyperAPIDriverHandler, } from './driver.js'; export { HyperAPIError } from './error.js'; -export type { HyperAPIModule, InferModule, } from './module.js'; +export type { HyperAPIModule, HyperAPIModuleResponse, InferModule, } from './module.js'; export type { HyperAPIRequest, HyperAPIRequestArgs, } from './request.js'; export type { HyperAPIResponse } from './response.js'; export { isHyperApiMethod, type HyperAPIMethod, } from './utils/methods.js'; diff --git a/dist/esm/main.js b/dist/esm/main.js index 5a8519f..38334b6 100644 --- a/dist/esm/main.js +++ b/dist/esm/main.js @@ -1,5 +1,5 @@ import nodePath from 'node:path'; -import { HyperAPIInternalError, HyperAPIUnknownMethodError, } from './api-errors.js'; +import { HyperAPIInternalError, HyperAPIInvalidParametersError, HyperAPIUnknownMethodError, } from './api-errors.js'; import { HyperAPIError } from './error.js'; import { createRouter, useRouter, } from './router.js'; const ENTRYPOINT_PATH = nodePath.dirname(process.argv[1]); @@ -76,11 +76,8 @@ export class HyperAPI { } const router_response = await useRouter(this.router, driver_request.method, driver_request.path); if (!router_response) { - return [ - request, - module_, - new HyperAPIUnknownMethodError(), - ]; + // TODO throw HyperAPIMethodNotAllowedError when path exists but HTTP method does not match + throw new HyperAPIUnknownMethodError(); } driver_request.args = { ...driver_request.args, @@ -93,7 +90,14 @@ export class HyperAPI { // IDEA: "onBeforeModule" hook? module_ = (await import(router_response.module_path)); if (module_.argsValidator) { - request.args = module_.argsValidator(request.args); + try { + request.args = module_.argsValidator(request.args); + } + catch (error) { + // eslint-disable-next-line no-console + console.error(error); + throw new HyperAPIInvalidParametersError(); + } } for (const hook of this.handlers.module) { // eslint-disable-next-line no-await-in-loop diff --git a/dist/esm/router.js b/dist/esm/router.js index f1bdd75..a245173 100644 --- a/dist/esm/router.js +++ b/dist/esm/router.js @@ -27,6 +27,7 @@ export function useRouter(router, method, path) { }); } const REGEXP_FILE_EXTENSION = /\.(js|mjs|cjs|ts)$/; +const REGEXP_TEST_FILE_EXTENSION = /\.test\.(js|mjs|cjs|ts)$/; const REGEXP_HTTP_METHOD = /\.\[(delete|get|head|options|patch|post|put)]$/; const REGEXP_PATH_SLUG = /\[(\w+)]/g; /** @@ -49,7 +50,8 @@ function scanDirectory(router, path, regexp_parts = ['']) { const entry_path = nodePath.join(path, entry.name); if (entry.isFile()) { let file_name = entry.name; - if (REGEXP_FILE_EXTENSION.test(file_name)) { + if (REGEXP_FILE_EXTENSION.test(file_name) + && REGEXP_TEST_FILE_EXTENSION.test(file_name) !== true) { file_name = file_name.replace(REGEXP_FILE_EXTENSION, ''); let method = 'all'; const method_match = file_name.match(REGEXP_HTTP_METHOD); diff --git a/dist/main.cjs b/dist/main.cjs index 268b22b..d66ef7a 100644 --- a/dist/main.cjs +++ b/dist/main.cjs @@ -47,6 +47,7 @@ __export(exports_main, { HyperAPIRateLimitError: () => HyperAPIRateLimitError, HyperAPIObjectsLimitError: () => HyperAPIObjectsLimitError, HyperAPIOTPError: () => HyperAPIOTPError, + HyperAPIMethodNotAllowedError: () => HyperAPIMethodNotAllowedError, HyperAPIMaintenanceError: () => HyperAPIMaintenanceError, HyperAPIInvalidParametersError: () => HyperAPIInvalidParametersError, HyperAPIInternalError: () => HyperAPIInternalError, @@ -169,6 +170,12 @@ class HyperAPIMaintenanceError extends HyperAPIError { httpStatus = 503; } +class HyperAPIMethodNotAllowedError extends HyperAPIError { + code = 14; + description = "HTTP method not allowed"; + httpStatus = 405; +} + // dist/esm/router.js var import_itty_router = require("itty-router"); var import_node_fs = require("node:fs"); @@ -185,6 +192,7 @@ function useRouter(router, method, path) { }); } var REGEXP_FILE_EXTENSION = /\.(js|mjs|cjs|ts)$/; +var REGEXP_TEST_FILE_EXTENSION = /\.test\.(js|mjs|cjs|ts)$/; var REGEXP_HTTP_METHOD = /\.\[(delete|get|head|options|patch|post|put)]$/; var REGEXP_PATH_SLUG = /\[(\w+)]/g; function scanDirectory(router, path, regexp_parts = [""]) { @@ -201,7 +209,7 @@ function scanDirectory(router, path, regexp_parts = [""]) { const entry_path = import_node_path.default.join(path, entry.name); if (entry.isFile()) { let file_name = entry.name; - if (REGEXP_FILE_EXTENSION.test(file_name)) { + if (REGEXP_FILE_EXTENSION.test(file_name) && REGEXP_TEST_FILE_EXTENSION.test(file_name) !== true) { file_name = file_name.replace(REGEXP_FILE_EXTENSION, ""); let method = "all"; const method_match = file_name.match(REGEXP_HTTP_METHOD); @@ -298,11 +306,7 @@ class HyperAPI { } const router_response = await useRouter(this.router, driver_request.method, driver_request.path); if (!router_response) { - return [ - request, - module_, - new HyperAPIUnknownMethodError - ]; + throw new HyperAPIUnknownMethodError; } driver_request.args = { ...driver_request.args, @@ -311,7 +315,12 @@ class HyperAPI { request = this.handlers.transformer ? await this.handlers.transformer(driver_request) : driver_request; module_ = await import(router_response.module_path); if (module_.argsValidator) { - request.args = module_.argsValidator(request.args); + try { + request.args = module_.argsValidator(request.args); + } catch (error) { + console.error(error); + throw new HyperAPIInvalidParametersError; + } } for (const hook of this.handlers.module) { await hook(request, module_); diff --git a/package.json b/package.json index 2995ea8..9de2468 100644 --- a/package.json +++ b/package.json @@ -33,8 +33,8 @@ "build:cjs": "bun build dist/esm/main.js --platform=node --format=cjs --packages=external --outfile=dist/main.cjs", "# build:cjs": "bunx esbuild --bundle --platform=node --format=cjs --packages=external --outfile=dist/main.cjs dist/esm/main.js", "build:ts": "rm -r dist/esm ; tsc", + "check": "bun run build && bun run lint && bun run test", "lint": "eslint . && tsc --skipLibCheck --noemit", - "publish:npm": "bun run build && bun run lint && bun run test && npm publish", "test": "npm run test:vitest && bun test --coverage src/ test/", "test:vitest": "vitest run --no-file-parallelism" }, diff --git a/src/api-errors.ts b/src/api-errors.ts index 99f3375..a084e13 100644 --- a/src/api-errors.ts +++ b/src/api-errors.ts @@ -1,76 +1,82 @@ import { - type ErrorData, + type HyperAPIErrorData, HyperAPIError, } from './error.js'; -export class HyperAPIAuthorizationError extends HyperAPIError { +export class HyperAPIAuthorizationError extends HyperAPIError { code = 1; description = 'Authorization error'; httpStatus = 401; // Unauthorized } -export class HyperAPIInvalidParametersError extends HyperAPIError { +export class HyperAPIInvalidParametersError extends HyperAPIError { code = 2; description = 'One of the parameters specified was missing or invalid'; httpStatus = 400; // Bad Request } -export class HyperAPIInternalError extends HyperAPIError { +export class HyperAPIInternalError extends HyperAPIError { code = 3; description = 'Internal error'; httpStatus = 500; // Internal Server Error } -export class HyperAPIForbiddenError extends HyperAPIError { +export class HyperAPIForbiddenError extends HyperAPIError { code = 4; description = 'You do not have permission to perform this action'; httpStatus = 403; // Forbidden } -export class HyperAPIUnknownMethodError extends HyperAPIError { +export class HyperAPIUnknownMethodError extends HyperAPIError { code = 5; description = 'Unknown method called'; httpStatus = 404; // Not Found } -export class HyperAPIObjectsLimitError extends HyperAPIError { +export class HyperAPIObjectsLimitError extends HyperAPIError { code = 6; description = 'Too many objects requested'; httpStatus = 400; // Bad Request } -export class HyperAPIRateLimitError extends HyperAPIError { +export class HyperAPIRateLimitError extends HyperAPIError { code = 7; description = 'Rate limit exceeded'; httpStatus = 429; // Too Many Requests } -export class HyperAPICaptchaError extends HyperAPIError { +export class HyperAPICaptchaError extends HyperAPIError { code = 8; description = 'Captcha required'; httpStatus = 428; // Precondition Required } -export class HyperAPIBusyError extends HyperAPIError { +export class HyperAPIBusyError extends HyperAPIError { code = 10; description = 'Endpoint is busy'; httpStatus = 503; // Service Unavailable } -export class HyperAPIConfirmationError extends HyperAPIError { +export class HyperAPIConfirmationError extends HyperAPIError { code = 11; description = 'Confirmation required'; httpStatus = 409; // Conflict } -export class HyperAPIOTPError extends HyperAPIError { +export class HyperAPIOTPError extends HyperAPIError { code = 12; description = 'One-time password required'; httpStatus = 401; // Unauthorized } -export class HyperAPIMaintenanceError extends HyperAPIError { +export class HyperAPIMaintenanceError extends HyperAPIError { code = 13; description = 'Endpoint is in maintenance mode'; httpStatus = 503; // Service Unavailable } + +export class HyperAPIMethodNotAllowedError extends HyperAPIError { + code = 14; + description = 'HTTP method not allowed'; + httpStatus = 405; // Method Not Allowed +} diff --git a/src/error.ts b/src/error.ts index 87f673f..854db50 100644 --- a/src/error.ts +++ b/src/error.ts @@ -1,15 +1,15 @@ import { isRecord } from './utils/is-record.js'; +export type HyperAPIErrorData = Record | undefined; + interface HyperAPIErrorResponse { code: number; description?: string; - data?: Record; + data?: HyperAPIErrorData; } -export type ErrorData = Record | undefined; - export class HyperAPIError< - D extends Record | undefined, + D extends HyperAPIErrorData = undefined, > extends Error { /** The error code. */ readonly code: number = 0; diff --git a/src/main.test.ts b/src/main.test.ts index bafc939..d74da8e 100644 --- a/src/main.test.ts +++ b/src/main.test.ts @@ -15,7 +15,7 @@ afterAll(() => { describe('routing', () => { describe('methods', () => { - test('ALL', async () => { + test('ALL with GET', async () => { const result = await driver.trigger( 'GET', 'echo', @@ -27,7 +27,31 @@ describe('routing', () => { expect(result).toStrictEqual([ true, { - method: 'ALL', + method: { + expected: 'ALL', + received: 'GET', + }, + message: 'Hello, world!', + }, + ]); + }); + + test('ALL with DELETE', async () => { + const result = await driver.trigger( + 'DELETE', + 'echo', + { + name: 'world', + }, + ); + + expect(result).toStrictEqual([ + true, + { + method: { + expected: 'ALL', + received: 'DELETE', + }, message: 'Hello, world!', }, ]); @@ -45,7 +69,10 @@ describe('routing', () => { expect(result).toStrictEqual([ true, { - method: 'POST', + method: { + expected: 'POST', + received: 'POST', + }, message: 'Hello, deadbeef!', }, ]); diff --git a/src/main.ts b/src/main.ts index f8ae7eb..943de93 100644 --- a/src/main.ts +++ b/src/main.ts @@ -1,6 +1,7 @@ -import nodePath from 'node:path'; +import nodePath from 'node:path'; import { HyperAPIInternalError, + HyperAPIInvalidParametersError, HyperAPIUnknownMethodError, } from './api-errors.js'; import type { @@ -136,11 +137,8 @@ export class HyperAPI< ); if (!router_response) { - return [ - request, - module_, - new HyperAPIUnknownMethodError(), - ]; + // TODO throw HyperAPIMethodNotAllowedError when path exists but HTTP method does not match + throw new HyperAPIUnknownMethodError(); } driver_request.args = { @@ -157,7 +155,15 @@ export class HyperAPI< module_ = (await import(router_response.module_path)) as M; if (module_.argsValidator) { - request.args = module_.argsValidator(request.args); + try { + request.args = module_.argsValidator(request.args); + } + catch (error) { + // eslint-disable-next-line no-console + console.error(error); + + throw new HyperAPIInvalidParametersError(); + } } for (const hook of this.handlers.module) { @@ -215,8 +221,7 @@ export type { export { HyperAPIError } from './error.js'; export type { HyperAPIModule, - // HyperAPIModuleRequest, - // HyperAPIModuleResponse, + HyperAPIModuleResponse, InferModule, } from './module.js'; export type { diff --git a/src/router.ts b/src/router.ts index 599ba88..e93443c 100644 --- a/src/router.ts +++ b/src/router.ts @@ -47,6 +47,7 @@ export function useRouter( } const REGEXP_FILE_EXTENSION = /\.(js|mjs|cjs|ts)$/; +const REGEXP_TEST_FILE_EXTENSION = /\.test\.(js|mjs|cjs|ts)$/; const REGEXP_HTTP_METHOD = /\.\[(delete|get|head|options|patch|post|put)]$/; const REGEXP_PATH_SLUG = /\[(\w+)]/g; @@ -89,7 +90,10 @@ function scanDirectory( if (entry.isFile()) { let file_name = entry.name; - if (REGEXP_FILE_EXTENSION.test(file_name)) { + if ( + REGEXP_FILE_EXTENSION.test(file_name) + && REGEXP_TEST_FILE_EXTENSION.test(file_name) !== true + ) { file_name = file_name.replace( REGEXP_FILE_EXTENSION, '', diff --git a/test/hyper-api/echo.[post].ts b/test/hyper-api/echo.[post].ts index 3598d04..c13883f 100644 --- a/test/hyper-api/echo.[post].ts +++ b/test/hyper-api/echo.[post].ts @@ -12,7 +12,10 @@ type Module = InferModule; export default function (request: HyperAPIRequest>): HyperAPIResponse { return { - method: 'POST', + method: { + expected: 'POST', + received: request.method, + }, message: `Hello, ${request.args.name}!`, }; } diff --git a/test/hyper-api/echo.ts b/test/hyper-api/echo.ts index ede38c3..a600866 100644 --- a/test/hyper-api/echo.ts +++ b/test/hyper-api/echo.ts @@ -6,7 +6,10 @@ import { type LocalRequest } from '../setup.js'; export default function (request: LocalRequest>): HyperAPIResponse { return { - method: 'ALL', + method: { + expected: 'ALL', + received: request.method, + }, message: `Hello, ${request.args.name}!`, }; } diff --git a/test/hyper-api/errors/api.test.ts b/test/hyper-api/errors/api.test.ts index 5e1886b..2d4cd6c 100644 --- a/test/hyper-api/errors/api.test.ts +++ b/test/hyper-api/errors/api.test.ts @@ -1,4 +1,3 @@ - import { expect, test, diff --git a/test/hyper-api/errors/internal.test.ts b/test/hyper-api/errors/internal.test.ts index 664b216..a1b3668 100644 --- a/test/hyper-api/errors/internal.test.ts +++ b/test/hyper-api/errors/internal.test.ts @@ -1,4 +1,3 @@ - import { expect, test, diff --git a/test/hyper-api/only-get.[get].ts b/test/hyper-api/only-get.[get].ts new file mode 100644 index 0000000..05dd31d --- /dev/null +++ b/test/hyper-api/only-get.[get].ts @@ -0,0 +1,9 @@ +/* eslint-disable jsdoc/require-jsdoc */ + +import type { HyperAPIModuleResponse } from '../../src/main.js'; + +export default function (): HyperAPIModuleResponse { + return { + foo: 'bar', + }; +} diff --git a/test/hyper-api/only-get.test.ts b/test/hyper-api/only-get.test.ts new file mode 100644 index 0000000..e064b71 --- /dev/null +++ b/test/hyper-api/only-get.test.ts @@ -0,0 +1,40 @@ +import { + expect, + test, +} from 'vitest'; +import { driver } from '../setup.js'; + +test('GET', async () => { + const result = await driver.trigger( + 'GET', + 'only-get', + ); + + expect(result).toStrictEqual([ + true, + { + foo: 'bar', + }, + ]); +}); + +// TODO uncomment this test when HyperAPIMethodNotAllowedError supported +// test('POST', async () => { +// const result = await driver.trigger( +// 'POST', +// 'only-get', +// {}, +// true, +// ); + +// expect(result).toStrictEqual([ +// false, +// { +// code: 5, +// description: 'Unknown method called', +// }, +// { +// status: 405, +// }, +// ]); +// }); diff --git a/test/setup.ts b/test/setup.ts index 5200720..0ecaf58 100644 --- a/test/setup.ts +++ b/test/setup.ts @@ -7,10 +7,8 @@ import { HyperAPIRequest, HyperAPIRequestArgs, } from '../src/main.js'; -import type { - EmptyObject, - HTTPMethod, -} from '../src/utils/types.js'; +import type { HyperAPIMethod } from '../src/utils/methods.js'; +import type { EmptyObject } from '../src/utils/types.js'; interface DriverRequest extends HyperAPIRequest { foo: string; @@ -28,10 +26,22 @@ class HyperAPITestDriver implements HyperAPIDriver { } async trigger( - method: HTTPMethod, + method: HyperAPIMethod, + path: string, + args?: Record, + ): Promise<[ boolean, unknown ]>; + async trigger( + method: HyperAPIMethod, + path: string, + args: Record, + use_http: true, + ): Promise<[ boolean, unknown, { status: number | undefined } ]>; + async trigger( + method: HyperAPIMethod, path: string, args: Record = {}, - ): Promise<[ boolean, unknown ]> { + use_http: boolean = false, + ): Promise<[ boolean, unknown ] | [ boolean, unknown, { status: number | undefined }]> { if (!this.handler) { throw new Error('No handler available.'); } @@ -44,10 +54,18 @@ class HyperAPITestDriver implements HyperAPIDriver { }); if (response instanceof HyperAPIError) { - return [ - false, - response.getResponse(), - ]; + return use_http === true + ? [ + false, + response.getResponse(), + { + status: response.httpStatus, + }, + ] + : [ + false, + response.getResponse(), + ]; } return [ From ca15b2c93608f45161267612ddc473dbe55d61f0 Mon Sep 17 00:00:00 2001 From: Daniil Kirichenko Date: Thu, 17 Apr 2025 10:50:04 +0200 Subject: [PATCH 29/57] Exported type `HyperAPIErrorData` --- dist/esm/main.d.ts | 2 +- dist/esm/main.js | 2 +- src/main.ts | 5 ++++- 3 files changed, 6 insertions(+), 3 deletions(-) diff --git a/dist/esm/main.d.ts b/dist/esm/main.d.ts index 976effb..5150ae3 100644 --- a/dist/esm/main.d.ts +++ b/dist/esm/main.d.ts @@ -40,7 +40,7 @@ export declare class HyperAPI, R exten } export * from './api-errors.js'; export type { HyperAPIDriver, HyperAPIDriverHandler, } from './driver.js'; -export { HyperAPIError } from './error.js'; +export { type HyperAPIErrorData, HyperAPIError, } from './error.js'; export type { HyperAPIModule, HyperAPIModuleResponse, InferModule, } from './module.js'; export type { HyperAPIRequest, HyperAPIRequestArgs, } from './request.js'; export type { HyperAPIResponse } from './response.js'; diff --git a/dist/esm/main.js b/dist/esm/main.js index 38334b6..fa8e929 100644 --- a/dist/esm/main.js +++ b/dist/esm/main.js @@ -138,5 +138,5 @@ export class HyperAPI { } } export * from './api-errors.js'; -export { HyperAPIError } from './error.js'; +export { HyperAPIError, } from './error.js'; export { isHyperApiMethod, } from './utils/methods.js'; diff --git a/src/main.ts b/src/main.ts index 943de93..24f8151 100644 --- a/src/main.ts +++ b/src/main.ts @@ -218,7 +218,10 @@ export type { HyperAPIDriver, HyperAPIDriverHandler, } from './driver.js'; -export { HyperAPIError } from './error.js'; +export { + type HyperAPIErrorData, + HyperAPIError, +} from './error.js'; export type { HyperAPIModule, HyperAPIModuleResponse, From 8894dcfe65392c9a4111c4494945817bff9f1f52 Mon Sep 17 00:00:00 2001 From: Daniil Kirichenko Date: Fri, 23 May 2025 22:16:34 +0200 Subject: [PATCH 30/57] New configs, new build --- .gitignore | 5 +- .npmignore | 21 +- bun.lockb | Bin 118320 -> 156451 bytes dist/esm/api-errors.d.ts | 66 ---- dist/esm/api-errors.js | 66 ---- dist/esm/driver.d.ts | 9 - dist/esm/driver.js | 1 - dist/esm/error.d.ts | 26 -- dist/esm/error.js | 38 -- dist/esm/main.d.ts | 47 --- dist/esm/main.js | 142 -------- dist/esm/module.d.ts | 9 - dist/esm/module.js | 1 - dist/esm/request.d.ts | 8 - dist/esm/request.js | 1 - dist/esm/response.d.ts | 3 - dist/esm/response.js | 1 - dist/esm/router.d.ts | 21 -- dist/esm/router.js | 105 ------ dist/esm/utils/is-record.d.ts | 6 - dist/esm/utils/is-record.js | 12 - dist/esm/utils/methods.d.ts | 7 - dist/esm/utils/methods.js | 15 - dist/esm/utils/types.d.ts | 4 - dist/esm/utils/types.js | 1 - dist/main.cjs | 662 +++++++++++++++++----------------- dist/main.d.ts | 191 ++++++++++ dist/main.js | 312 ++++++++++++++++ package.json | 28 +- src/api-errors.ts | 78 ++-- src/driver.ts | 6 +- src/error.ts | 4 +- src/main.ts | 27 +- src/module.ts | 6 +- src/request.ts | 8 +- src/response.ts | 2 +- src/router.ts | 18 +- src/utils/types.ts | 2 - test/setup.ts | 16 +- test/tsconfig.json | 24 +- tsconfig.json | 44 ++- 41 files changed, 972 insertions(+), 1071 deletions(-) delete mode 100644 dist/esm/api-errors.d.ts delete mode 100644 dist/esm/api-errors.js delete mode 100644 dist/esm/driver.d.ts delete mode 100644 dist/esm/driver.js delete mode 100644 dist/esm/error.d.ts delete mode 100644 dist/esm/error.js delete mode 100644 dist/esm/main.d.ts delete mode 100644 dist/esm/main.js delete mode 100644 dist/esm/module.d.ts delete mode 100644 dist/esm/module.js delete mode 100644 dist/esm/request.d.ts delete mode 100644 dist/esm/request.js delete mode 100644 dist/esm/response.d.ts delete mode 100644 dist/esm/response.js delete mode 100644 dist/esm/router.d.ts delete mode 100644 dist/esm/router.js delete mode 100644 dist/esm/utils/is-record.d.ts delete mode 100644 dist/esm/utils/is-record.js delete mode 100644 dist/esm/utils/methods.d.ts delete mode 100644 dist/esm/utils/methods.js delete mode 100644 dist/esm/utils/types.d.ts delete mode 100644 dist/esm/utils/types.js create mode 100644 dist/main.d.ts create mode 100644 dist/main.js delete mode 100644 src/utils/types.ts diff --git a/.gitignore b/.gitignore index 6675c5d..2e217a0 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,4 @@ - .DS_Store -node_modules +.env +*.env +node_modules \ No newline at end of file diff --git a/.npmignore b/.npmignore index ee2885d..83f941b 100644 --- a/.npmignore +++ b/.npmignore @@ -1,20 +1,31 @@ +# ignore source files of the Typescript project +src/ + # ignore tests **/*.test.* **/*.test.d.ts test/ - -# ignore source files of the Typescript project -src/ +test-d/ # ignore configs .luarc.json biome.json # these names cannot be declared using {js,mjs,cjs} syntax -# is this case rule n/no-unpublished-import screams at me +# is this case rule n/no-unpublished-import yells at me eslint.config.js eslint.config.mjs eslint.config.cjs tsconfig.json +tsconfig.*.json +vitest.config.js +vitest.config.ts + +# ignore lockfiles +bun.lock +bun.lockb +package-lock.json +pnpm-lock.yaml +yarn.lock # ignore repo configs .github/ @@ -22,4 +33,4 @@ tsconfig.json # ignore IDE files .idea -.nova +.nova \ No newline at end of file diff --git a/bun.lockb b/bun.lockb index 49623977e8b5daf22f23a534f0c972afe9248045..44335b2c6cec6b0a423976909a61f47bdd2379ed 100755 GIT binary patch delta 50189 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

c|x1Oq2@R?W|#Mn;ug0$s)J7J%emF|m>SfL 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 diff --git a/dist/esm/api-errors.d.ts b/dist/esm/api-errors.d.ts deleted file mode 100644 index d1a3ad2..0000000 --- a/dist/esm/api-errors.d.ts +++ /dev/null @@ -1,66 +0,0 @@ -import { type HyperAPIErrorData, HyperAPIError } from './error.js'; -export declare class HyperAPIAuthorizationError extends HyperAPIError { - code: number; - description: string; - httpStatus: number; -} -export declare class HyperAPIInvalidParametersError extends HyperAPIError { - code: number; - description: string; - httpStatus: number; -} -export declare class HyperAPIInternalError extends HyperAPIError { - code: number; - description: string; - httpStatus: number; -} -export declare class HyperAPIForbiddenError extends HyperAPIError { - code: number; - description: string; - httpStatus: number; -} -export declare class HyperAPIUnknownMethodError extends HyperAPIError { - code: number; - description: string; - httpStatus: number; -} -export declare class HyperAPIObjectsLimitError extends HyperAPIError { - code: number; - description: string; - httpStatus: number; -} -export declare class HyperAPIRateLimitError extends HyperAPIError { - code: number; - description: string; - httpStatus: number; -} -export declare class HyperAPICaptchaError extends HyperAPIError { - code: number; - description: string; - httpStatus: number; -} -export declare class HyperAPIBusyError extends HyperAPIError { - code: number; - description: string; - httpStatus: number; -} -export declare class HyperAPIConfirmationError extends HyperAPIError { - code: number; - description: string; - httpStatus: number; -} -export declare class HyperAPIOTPError extends HyperAPIError { - code: number; - description: string; - httpStatus: number; -} -export declare class HyperAPIMaintenanceError extends HyperAPIError { - code: number; - description: string; - httpStatus: number; -} -export declare class HyperAPIMethodNotAllowedError extends HyperAPIError { - code: number; - description: string; - httpStatus: number; -} diff --git a/dist/esm/api-errors.js b/dist/esm/api-errors.js deleted file mode 100644 index 7e5b288..0000000 --- a/dist/esm/api-errors.js +++ /dev/null @@ -1,66 +0,0 @@ -import { HyperAPIError, } from './error.js'; -export class HyperAPIAuthorizationError extends HyperAPIError { - code = 1; - description = 'Authorization error'; - httpStatus = 401; // Unauthorized -} -export class HyperAPIInvalidParametersError extends HyperAPIError { - code = 2; - description = 'One of the parameters specified was missing or invalid'; - httpStatus = 400; // Bad Request -} -export class HyperAPIInternalError extends HyperAPIError { - code = 3; - description = 'Internal error'; - httpStatus = 500; // Internal Server Error -} -export class HyperAPIForbiddenError extends HyperAPIError { - code = 4; - description = 'You do not have permission to perform this action'; - httpStatus = 403; // Forbidden -} -export class HyperAPIUnknownMethodError extends HyperAPIError { - code = 5; - description = 'Unknown method called'; - httpStatus = 404; // Not Found -} -export class HyperAPIObjectsLimitError extends HyperAPIError { - code = 6; - description = 'Too many objects requested'; - httpStatus = 400; // Bad Request -} -export class HyperAPIRateLimitError extends HyperAPIError { - code = 7; - description = 'Rate limit exceeded'; - httpStatus = 429; // Too Many Requests -} -export class HyperAPICaptchaError extends HyperAPIError { - code = 8; - description = 'Captcha required'; - httpStatus = 428; // Precondition Required -} -export class HyperAPIBusyError extends HyperAPIError { - code = 10; - description = 'Endpoint is busy'; - httpStatus = 503; // Service Unavailable -} -export class HyperAPIConfirmationError extends HyperAPIError { - code = 11; - description = 'Confirmation required'; - httpStatus = 409; // Conflict -} -export class HyperAPIOTPError extends HyperAPIError { - code = 12; - description = 'One-time password required'; - httpStatus = 401; // Unauthorized -} -export class HyperAPIMaintenanceError extends HyperAPIError { - code = 13; - description = 'Endpoint is in maintenance mode'; - httpStatus = 503; // Service Unavailable -} -export class HyperAPIMethodNotAllowedError extends HyperAPIError { - code = 14; - description = 'HTTP method not allowed'; - httpStatus = 405; // Method Not Allowed -} diff --git a/dist/esm/driver.d.ts b/dist/esm/driver.d.ts deleted file mode 100644 index b7131cf..0000000 --- a/dist/esm/driver.d.ts +++ /dev/null @@ -1,9 +0,0 @@ -import type { HyperAPIRequest } from './request.js'; -import type { HyperAPIResponse } from './response.js'; -import { MaybePromise } from './utils/types.js'; -export type HyperAPIDriverHandler = (request: R) => MaybePromise; -export interface HyperAPIDriver { - start(handler: HyperAPIDriverHandler): void; - stop(): void; -} -export type InferDriverRequest = D extends HyperAPIDriver ? R : never; diff --git a/dist/esm/driver.js b/dist/esm/driver.js deleted file mode 100644 index cb0ff5c..0000000 --- a/dist/esm/driver.js +++ /dev/null @@ -1 +0,0 @@ -export {}; diff --git a/dist/esm/error.d.ts b/dist/esm/error.d.ts deleted file mode 100644 index aebb759..0000000 --- a/dist/esm/error.d.ts +++ /dev/null @@ -1,26 +0,0 @@ -export type HyperAPIErrorData = Record | undefined; -interface HyperAPIErrorResponse { - code: number; - description?: string; - data?: HyperAPIErrorData; -} -export declare class HyperAPIError extends Error { - /** The error code. */ - readonly code: number; - /** The error description. */ - readonly description: string; - /** The error data. */ - readonly data?: D; - /** HTTP status code. */ - readonly httpStatus?: number; - /** HTTP headers to return. */ - readonly httpHeaders?: Record; - constructor(data?: D); - get message(): string; - /** - * Creates response object. - * @returns - - */ - getResponse(): HyperAPIErrorResponse; -} -export {}; diff --git a/dist/esm/error.js b/dist/esm/error.js deleted file mode 100644 index 74c0f51..0000000 --- a/dist/esm/error.js +++ /dev/null @@ -1,38 +0,0 @@ -import { isRecord } from './utils/is-record.js'; -export class HyperAPIError extends Error { - /** The error code. */ - code = 0; - /** The error description. */ - description = 'HyperAPI error'; - /** The error data. */ - data; - /** HTTP status code. */ - httpStatus; - /** HTTP headers to return. */ - httpHeaders; - constructor(data) { - super(); - if (isRecord(data)) { - this.data = data; - } - } - get message() { - return `${this.description} (code ${this.code}).`; - } - /** - * Creates response object. - * @returns - - */ - getResponse() { - const response = { - code: this.code, - }; - if (typeof this.description === 'string') { - response.description = this.description; - } - if (this.data) { - response.data = this.data; - } - return response; - } -} diff --git a/dist/esm/main.d.ts b/dist/esm/main.d.ts deleted file mode 100644 index 5150ae3..0000000 --- a/dist/esm/main.d.ts +++ /dev/null @@ -1,47 +0,0 @@ -import type { HyperAPIDriver, InferDriverRequest } from './driver.js'; -import type { HyperAPIModule } from './module.js'; -import type { HyperAPIRequest } from './request.js'; -export declare class HyperAPI, R extends InferDriverRequest, M extends HyperAPIModule = HyperAPIModule> { - private router; - private driver; - /** - * Creates a HyperAPI instance. - * @param options The options. - * @param options.driver The driver. - * @param [options.root] The root directory for API methods modules. Default: `hyper-api` directory alongside the entrypoint script. - */ - constructor({ driver, root, }: { - driver: D; - root?: string; - }); - private handlers; - /** - * Use this hook add properties to the request before it is send to the API module. - * - * This hook can be set only once. - * @param transformer The callback function. - */ - setTransformer(transformer: typeof this.handlers['transformer']): void; - /** - * Adds a hook to be called when the API module is imported. - * @param callback - - */ - onModule(callback: typeof this.handlers['module'][number]): void; - /** - * Adds a hook to be called right before the response is sent back. - * - * This hook called only if the request was processed by the API module. If unknown method was requested, this hook is not called. - * @param callback - - */ - onResponse(callback: typeof this.handlers['response'][number]): void; - private processRequest; - /** Destroys the HyperAPI instance. */ - destroy(): void; -} -export * from './api-errors.js'; -export type { HyperAPIDriver, HyperAPIDriverHandler, } from './driver.js'; -export { type HyperAPIErrorData, HyperAPIError, } from './error.js'; -export type { HyperAPIModule, HyperAPIModuleResponse, InferModule, } from './module.js'; -export type { HyperAPIRequest, HyperAPIRequestArgs, } from './request.js'; -export type { HyperAPIResponse } from './response.js'; -export { isHyperApiMethod, type HyperAPIMethod, } from './utils/methods.js'; diff --git a/dist/esm/main.js b/dist/esm/main.js deleted file mode 100644 index fa8e929..0000000 --- a/dist/esm/main.js +++ /dev/null @@ -1,142 +0,0 @@ -import nodePath from 'node:path'; -import { HyperAPIInternalError, HyperAPIInvalidParametersError, HyperAPIUnknownMethodError, } from './api-errors.js'; -import { HyperAPIError } from './error.js'; -import { createRouter, useRouter, } from './router.js'; -const ENTRYPOINT_PATH = nodePath.dirname(process.argv[1]); -export class HyperAPI { - router; - driver; - /** - * Creates a HyperAPI instance. - * @param options The options. - * @param options.driver The driver. - * @param [options.root] The root directory for API methods modules. Default: `hyper-api` directory alongside the entrypoint script. - */ - constructor({ driver, root = nodePath.join(ENTRYPOINT_PATH, 'hyper-api'), }) { - this.driver = driver; - this.router = createRouter(root); - this.driver.start(async (driver_request) => { - const [request, module_, response,] = await this.processRequest(driver_request); - if (request && module_) { - for (const hook of this.handlers.response) { - try { - // eslint-disable-next-line no-await-in-loop - await hook(request, module_, response); - } - catch (error) { - /* eslint-disable no-console */ - console.error('Error in "response" hook:'); - console.error(error); - /* eslint-enable no-console */ - } - } - } - return response; - }); - } - handlers = { - transformer: undefined, - module: [], - response: [], - }; - /** - * Use this hook add properties to the request before it is send to the API module. - * - * This hook can be set only once. - * @param transformer The callback function. - */ - setTransformer(transformer) { - if (this.handlers.transformer) { - throw new Error('Transformer has already been set.'); - } - this.handlers.transformer = transformer; - } - /** - * Adds a hook to be called when the API module is imported. - * @param callback - - */ - onModule(callback) { - this.handlers.module.push(callback); - } - /** - * Adds a hook to be called right before the response is sent back. - * - * This hook called only if the request was processed by the API module. If unknown method was requested, this hook is not called. - * @param callback - - */ - onResponse(callback) { - this.handlers.response.push(callback); - } - async processRequest(driver_request) { - let request = null; - let module_ = null; - try { - if (driver_request.path.startsWith('/') !== true) { - driver_request.path = `/${driver_request.path}`; - } - const router_response = await useRouter(this.router, driver_request.method, driver_request.path); - if (!router_response) { - // TODO throw HyperAPIMethodNotAllowedError when path exists but HTTP method does not match - throw new HyperAPIUnknownMethodError(); - } - driver_request.args = { - ...driver_request.args, - ...router_response.args, - }; - // Send request to the outside user - request = this.handlers.transformer - ? await this.handlers.transformer(driver_request) - : driver_request; - // IDEA: "onBeforeModule" hook? - module_ = (await import(router_response.module_path)); - if (module_.argsValidator) { - try { - request.args = module_.argsValidator(request.args); - } - catch (error) { - // eslint-disable-next-line no-console - console.error(error); - throw new HyperAPIInvalidParametersError(); - } - } - for (const hook of this.handlers.module) { - // eslint-disable-next-line no-await-in-loop - await hook(request, module_); - } - // IDEA: "onBeforeExecute" hook? - const response = await module_.default(request); - // IDEA: "onExecute" hook? - return [ - request, - module_, - response, - ]; - } - catch (error) { - if (error instanceof HyperAPIError) { - return [ - request, - module_, - error, - ]; - } - // eslint-disable-next-line no-console - console.error(error); - return [ - request, - module_, - new HyperAPIInternalError(), - ]; - } - throw new Error('Unreachable'); - } - /** Destroys the HyperAPI instance. */ - destroy() { - this.handlers.transformer = undefined; - this.handlers.module.splice(0); - this.handlers.response.splice(0); - } -} -export * from './api-errors.js'; -export { HyperAPIError, } from './error.js'; -export { isHyperApiMethod, } from './utils/methods.js'; diff --git a/dist/esm/module.d.ts b/dist/esm/module.d.ts deleted file mode 100644 index f0e1dde..0000000 --- a/dist/esm/module.d.ts +++ /dev/null @@ -1,9 +0,0 @@ -import { HyperAPI } from './main.js'; -import type { HyperAPIRequest, HyperAPIRequestArgs } from './request.js'; -import type { MaybePromise } from './utils/types.js'; -export type HyperAPIModuleResponse = Record | Response | unknown[] | undefined; -export interface HyperAPIModule> { - readonly default: (request: R) => MaybePromise; - readonly argsValidator: (args: unknown) => R extends HyperAPIRequest ? A : never; -} -export type InferModule> = H extends HyperAPI ? M : never; diff --git a/dist/esm/module.js b/dist/esm/module.js deleted file mode 100644 index cb0ff5c..0000000 --- a/dist/esm/module.js +++ /dev/null @@ -1 +0,0 @@ -export {}; diff --git a/dist/esm/request.d.ts b/dist/esm/request.d.ts deleted file mode 100644 index 1456c0a..0000000 --- a/dist/esm/request.d.ts +++ /dev/null @@ -1,8 +0,0 @@ -import type { HyperAPIMethod } from './utils/methods.js'; -import type { EmptyObject } from './utils/types.js'; -export type HyperAPIRequestArgs = Record; -export interface HyperAPIRequest { - method: HyperAPIMethod; - path: string; - args: A; -} diff --git a/dist/esm/request.js b/dist/esm/request.js deleted file mode 100644 index cb0ff5c..0000000 --- a/dist/esm/request.js +++ /dev/null @@ -1 +0,0 @@ -export {}; diff --git a/dist/esm/response.d.ts b/dist/esm/response.d.ts deleted file mode 100644 index 4954640..0000000 --- a/dist/esm/response.d.ts +++ /dev/null @@ -1,3 +0,0 @@ -import { HyperAPIError } from './error.js'; -import { HyperAPIModuleResponse } from './module.js'; -export type HyperAPIResponse = HyperAPIModuleResponse | HyperAPIError; diff --git a/dist/esm/response.js b/dist/esm/response.js deleted file mode 100644 index cb0ff5c..0000000 --- a/dist/esm/response.js +++ /dev/null @@ -1 +0,0 @@ -export {}; diff --git a/dist/esm/router.d.ts b/dist/esm/router.d.ts deleted file mode 100644 index dc22873..0000000 --- a/dist/esm/router.d.ts +++ /dev/null @@ -1,21 +0,0 @@ -import { type IRequest, type IttyRouterType } from 'itty-router'; -import { HyperAPIMethod } from './utils/methods.js'; -/** - * Creates new IttyRouter from filesystem. - * @param path The path to scan. - * @returns The new IttyRouter. - */ -export declare function createRouter(path: string): IttyRouterType; -interface RouterResponse { - module_path: string; - args: Record; -} -/** - * Fetches data from router. - * @param router The router to fetch data from. - * @param method The HTTP method. - * @param path The path to fetch data from. - * @returns The response. - */ -export declare function useRouter(router: IttyRouterType, method: HyperAPIMethod, path: string): Promise; -export {}; diff --git a/dist/esm/router.js b/dist/esm/router.js deleted file mode 100644 index a245173..0000000 --- a/dist/esm/router.js +++ /dev/null @@ -1,105 +0,0 @@ -/* eslint-disable n/no-sync */ -import { IttyRouter, } from 'itty-router'; -import { readdirSync } from 'node:fs'; -import nodePath from 'node:path'; -/** - * Creates new IttyRouter from filesystem. - * @param path The path to scan. - * @returns The new IttyRouter. - */ -export function createRouter(path) { - // eslint-disable-next-line new-cap - const router = IttyRouter(); - scanDirectory(router, path); - return router; -} -/** - * Fetches data from router. - * @param router The router to fetch data from. - * @param method The HTTP method. - * @param path The path to fetch data from. - * @returns The response. - */ -export function useRouter(router, method, path) { - return router.fetch({ - method, - url: `file://${path}`, - }); -} -const REGEXP_FILE_EXTENSION = /\.(js|mjs|cjs|ts)$/; -const REGEXP_TEST_FILE_EXTENSION = /\.test\.(js|mjs|cjs|ts)$/; -const REGEXP_HTTP_METHOD = /\.\[(delete|get|head|options|patch|post|put)]$/; -const REGEXP_PATH_SLUG = /\[(\w+)]/g; -/** - * Scans directory for routes. - * @param router The router to add routes to. - * @param path The path to scan. - * @param [regexp_parts] The parts of the regular expression. - */ -function scanDirectory(router, path, regexp_parts = ['']) { - const result = readdirSync(path, { - withFileTypes: true, - }); - const routes = { - 0: [], // routes with no method and no slug - 1: [], // routes with method and no slug - 2: [], // routes with no method and slug - 3: [], // routes with method and slug - }; - for (const entry of result) { - const entry_path = nodePath.join(path, entry.name); - if (entry.isFile()) { - let file_name = entry.name; - if (REGEXP_FILE_EXTENSION.test(file_name) - && REGEXP_TEST_FILE_EXTENSION.test(file_name) !== true) { - file_name = file_name.replace(REGEXP_FILE_EXTENSION, ''); - let method = 'all'; - const method_match = file_name.match(REGEXP_HTTP_METHOD); - const has_method = method_match ? 1 : 0; - if (method_match) { - method = method_match[1]; - file_name = file_name.replace(REGEXP_HTTP_METHOD, ''); - } - const has_slug = REGEXP_PATH_SLUG.test(file_name) ? 2 : 0; - file_name = file_name.replaceAll(REGEXP_PATH_SLUG, ':$1'); - // console.log( - // entry_path, - // method, - // [ - // ...regexp_parts, - // file_name, - // ].join(nodePath.sep), - // ); - // eslint-disable-next-line no-bitwise - routes[has_method | has_slug].push({ - method, - path: [ - ...regexp_parts, - file_name, - ].join(nodePath.sep), - module_path: entry_path, - }); - } - } - else { - scanDirectory(router, entry_path, [ - ...regexp_parts, - entry.name.replaceAll(REGEXP_PATH_SLUG, ':$1'), - ]); - } - } - for (const route of [ - ...routes[1], - ...routes[3], - ...routes[0], - ...routes[2], - ]) { - router[route.method](route.path, (r) => { - const response = { - module_path: route.module_path, - args: r.params, - }; - return response; - }); - } -} diff --git a/dist/esm/utils/is-record.d.ts b/dist/esm/utils/is-record.d.ts deleted file mode 100644 index b3e9d51..0000000 --- a/dist/esm/utils/is-record.d.ts +++ /dev/null @@ -1,6 +0,0 @@ -/** - * Check if a value is a record. - * @param value - - * @returns - - */ -export declare function isRecord(value: unknown): value is Record; diff --git a/dist/esm/utils/is-record.js b/dist/esm/utils/is-record.js deleted file mode 100644 index 350e9df..0000000 --- a/dist/esm/utils/is-record.js +++ /dev/null @@ -1,12 +0,0 @@ -/** - * Check if a value is a record. - * @param value - - * @returns - - */ -export function isRecord(value) { - return typeof value === 'object' - && value !== null - && !Array.isArray(value) - && value.constructor === Object - && Object.prototype.toString.call(value) === '[object Object]'; -} diff --git a/dist/esm/utils/methods.d.ts b/dist/esm/utils/methods.d.ts deleted file mode 100644 index 27e89a3..0000000 --- a/dist/esm/utils/methods.d.ts +++ /dev/null @@ -1,7 +0,0 @@ -export type HyperAPIMethod = 'DELETE' | 'GET' | 'HEAD' | 'OPTIONS' | 'PATCH' | 'POST' | 'PUT' | 'UNKNOWN'; -/** - * Checks if the given value is a valid HyperAPI method. - * @param method The HTTP method to check. - * @returns - - */ -export declare function isHyperApiMethod(method: unknown): method is HyperAPIMethod; diff --git a/dist/esm/utils/methods.js b/dist/esm/utils/methods.js deleted file mode 100644 index 3266c72..0000000 --- a/dist/esm/utils/methods.js +++ /dev/null @@ -1,15 +0,0 @@ -/** - * Checks if the given value is a valid HyperAPI method. - * @param method The HTTP method to check. - * @returns - - */ -export function isHyperApiMethod(method) { - return method === 'DELETE' - || method === 'GET' - || method === 'HEAD' - || method === 'OPTIONS' - || method === 'PATCH' - || method === 'POST' - || method === 'PUT' - || method === 'UNKNOWN'; -} diff --git a/dist/esm/utils/types.d.ts b/dist/esm/utils/types.d.ts deleted file mode 100644 index a6078fe..0000000 --- a/dist/esm/utils/types.d.ts +++ /dev/null @@ -1,4 +0,0 @@ -export type EmptyObject = Omit<{ - p: never; -}, 'p'>; -export type MaybePromise = T | Promise; diff --git a/dist/esm/utils/types.js b/dist/esm/utils/types.js deleted file mode 100644 index cb0ff5c..0000000 --- a/dist/esm/utils/types.js +++ /dev/null @@ -1 +0,0 @@ -export {}; diff --git a/dist/main.cjs b/dist/main.cjs index d66ef7a..4fa6254 100644 --- a/dist/main.cjs +++ b/dist/main.cjs @@ -1,356 +1,350 @@ +//#region rolldown:runtime var __create = Object.create; -var __getProtoOf = Object.getPrototypeOf; var __defProp = Object.defineProperty; -var __getOwnPropNames = Object.getOwnPropertyNames; var __getOwnPropDesc = Object.getOwnPropertyDescriptor; +var __getOwnPropNames = Object.getOwnPropertyNames; +var __getProtoOf = Object.getPrototypeOf; var __hasOwnProp = Object.prototype.hasOwnProperty; -var __toESM = (mod, isNodeMode, target) => { - target = mod != null ? __create(__getProtoOf(mod)) : {}; - const to = isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target; - for (let key of __getOwnPropNames(mod)) - if (!__hasOwnProp.call(to, key)) - __defProp(to, key, { - get: () => mod[key], - enumerable: true - }); - return to; -}; -var __moduleCache = /* @__PURE__ */ new WeakMap; -var __toCommonJS = (from) => { - var entry = __moduleCache.get(from), desc; - if (entry) - return entry; - entry = __defProp({}, "__esModule", { value: true }); - if (from && typeof from === "object" || typeof from === "function") - __getOwnPropNames(from).map((key) => !__hasOwnProp.call(entry, key) && __defProp(entry, key, { - get: () => from[key], - enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable - })); - __moduleCache.set(from, entry); - return entry; -}; -var __export = (target, all) => { - for (var name in all) - __defProp(target, name, { - get: all[name], - enumerable: true, - configurable: true, - set: (newValue) => all[name] = () => newValue - }); +var __copyProps = (to, from, except, desc) => { + if (from && typeof from === "object" || typeof from === "function") for (var keys = __getOwnPropNames(from), i = 0, n = keys.length, key; i < n; i++) { + key = keys[i]; + if (!__hasOwnProp.call(to, key) && key !== except) __defProp(to, key, { + get: ((k) => from[k]).bind(null, key), + enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable + }); + } + return to; }; +var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { + value: mod, + enumerable: true +}) : target, mod)); -// dist/esm/main.js -var exports_main = {}; -__export(exports_main, { - isHyperApiMethod: () => isHyperApiMethod, - HyperAPIUnknownMethodError: () => HyperAPIUnknownMethodError, - HyperAPIRateLimitError: () => HyperAPIRateLimitError, - HyperAPIObjectsLimitError: () => HyperAPIObjectsLimitError, - HyperAPIOTPError: () => HyperAPIOTPError, - HyperAPIMethodNotAllowedError: () => HyperAPIMethodNotAllowedError, - HyperAPIMaintenanceError: () => HyperAPIMaintenanceError, - HyperAPIInvalidParametersError: () => HyperAPIInvalidParametersError, - HyperAPIInternalError: () => HyperAPIInternalError, - HyperAPIForbiddenError: () => HyperAPIForbiddenError, - HyperAPIError: () => HyperAPIError, - HyperAPIConfirmationError: () => HyperAPIConfirmationError, - HyperAPICaptchaError: () => HyperAPICaptchaError, - HyperAPIBusyError: () => HyperAPIBusyError, - HyperAPIAuthorizationError: () => HyperAPIAuthorizationError, - HyperAPI: () => HyperAPI -}); -module.exports = __toCommonJS(exports_main); -var import_node_path2 = __toESM(require("node:path")); +//#endregion +const node_path = __toESM(require("node:path")); +const itty_router = __toESM(require("itty-router")); +const node_fs = __toESM(require("node:fs")); -// dist/esm/utils/is-record.js +//#region src/utils/is-record.ts +/** +* Check if a value is a record. +* @param value - +* @returns - +*/ function isRecord(value) { - return typeof value === "object" && value !== null && !Array.isArray(value) && value.constructor === Object && Object.prototype.toString.call(value) === "[object Object]"; + return typeof value === "object" && value !== null && !Array.isArray(value) && value.constructor === Object && Object.prototype.toString.call(value) === "[object Object]"; } -// dist/esm/error.js -class HyperAPIError extends Error { - code = 0; - description = "HyperAPI error"; - data; - httpStatus; - httpHeaders; - constructor(data) { - super(); - if (isRecord(data)) { - this.data = data; - } - } - get message() { - return `${this.description} (code ${this.code}).`; - } - getResponse() { - const response = { - code: this.code - }; - if (typeof this.description === "string") { - response.description = this.description; - } - if (this.data) { - response.data = this.data; - } - return response; - } -} - -// dist/esm/api-errors.js -class HyperAPIAuthorizationError extends HyperAPIError { - code = 1; - description = "Authorization error"; - httpStatus = 401; -} - -class HyperAPIInvalidParametersError extends HyperAPIError { - code = 2; - description = "One of the parameters specified was missing or invalid"; - httpStatus = 400; -} - -class HyperAPIInternalError extends HyperAPIError { - code = 3; - description = "Internal error"; - httpStatus = 500; -} - -class HyperAPIForbiddenError extends HyperAPIError { - code = 4; - description = "You do not have permission to perform this action"; - httpStatus = 403; -} - -class HyperAPIUnknownMethodError extends HyperAPIError { - code = 5; - description = "Unknown method called"; - httpStatus = 404; -} - -class HyperAPIObjectsLimitError extends HyperAPIError { - code = 6; - description = "Too many objects requested"; - httpStatus = 400; -} - -class HyperAPIRateLimitError extends HyperAPIError { - code = 7; - description = "Rate limit exceeded"; - httpStatus = 429; -} - -class HyperAPICaptchaError extends HyperAPIError { - code = 8; - description = "Captcha required"; - httpStatus = 428; -} - -class HyperAPIBusyError extends HyperAPIError { - code = 10; - description = "Endpoint is busy"; - httpStatus = 503; -} - -class HyperAPIConfirmationError extends HyperAPIError { - code = 11; - description = "Confirmation required"; - httpStatus = 409; -} - -class HyperAPIOTPError extends HyperAPIError { - code = 12; - description = "One-time password required"; - httpStatus = 401; -} - -class HyperAPIMaintenanceError extends HyperAPIError { - code = 13; - description = "Endpoint is in maintenance mode"; - httpStatus = 503; -} +//#endregion +//#region src/error.ts +var HyperAPIError = class extends Error { + /** The error code. */ + code = 0; + /** The error description. */ + description = "HyperAPI error"; + /** The error data. */ + data; + /** HTTP status code. */ + httpStatus; + /** HTTP headers to return. */ + httpHeaders; + constructor(data) { + super(); + if (isRecord(data)) this.data = data; + } + get message() { + return `${this.description} (code ${this.code}).`; + } + /** + * Creates response object. + * @returns - + */ + getResponse() { + const response = { code: this.code }; + if (typeof this.description === "string") response.description = this.description; + if (this.data) response.data = this.data; + return response; + } +}; -class HyperAPIMethodNotAllowedError extends HyperAPIError { - code = 14; - description = "HTTP method not allowed"; - httpStatus = 405; -} +//#endregion +//#region src/api-errors.ts +var HyperAPIAuthorizationError = class extends HyperAPIError { + code = 1; + description = "Authorization error"; + httpStatus = 401; +}; +var HyperAPIInvalidParametersError = class extends HyperAPIError { + code = 2; + description = "One of the parameters specified was missing or invalid"; + httpStatus = 400; +}; +var HyperAPIInternalError = class extends HyperAPIError { + code = 3; + description = "Internal error"; + httpStatus = 500; +}; +var HyperAPIForbiddenError = class extends HyperAPIError { + code = 4; + description = "You do not have permission to perform this action"; + httpStatus = 403; +}; +var HyperAPIUnknownMethodError = class extends HyperAPIError { + code = 5; + description = "Unknown method called"; + httpStatus = 404; +}; +var HyperAPIObjectsLimitError = class extends HyperAPIError { + code = 6; + description = "Too many objects requested"; + httpStatus = 400; +}; +var HyperAPIRateLimitError = class extends HyperAPIError { + code = 7; + description = "Rate limit exceeded"; + httpStatus = 429; +}; +var HyperAPICaptchaError = class extends HyperAPIError { + code = 8; + description = "Captcha required"; + httpStatus = 428; +}; +var HyperAPIBusyError = class extends HyperAPIError { + code = 10; + description = "Endpoint is busy"; + httpStatus = 503; +}; +var HyperAPIConfirmationError = class extends HyperAPIError { + code = 11; + description = "Confirmation required"; + httpStatus = 409; +}; +var HyperAPIOTPError = class extends HyperAPIError { + code = 12; + description = "One-time password required"; + httpStatus = 401; +}; +var HyperAPIMaintenanceError = class extends HyperAPIError { + code = 13; + description = "Endpoint is in maintenance mode"; + httpStatus = 503; +}; +var HyperAPIMethodNotAllowedError = class extends HyperAPIError { + code = 14; + description = "HTTP method not allowed"; + httpStatus = 405; +}; -// dist/esm/router.js -var import_itty_router = require("itty-router"); -var import_node_fs = require("node:fs"); -var import_node_path = __toESM(require("node:path")); +//#endregion +//#region src/router.ts +/** +* Creates new IttyRouter from filesystem. +* @param path The path to scan. +* @returns The new IttyRouter. +*/ function createRouter(path) { - const router = import_itty_router.IttyRouter(); - scanDirectory(router, path); - return router; + const router = (0, itty_router.IttyRouter)(); + scanDirectory(router, path); + return router; } +/** +* Fetches data from router. +* @param router The router to fetch data from. +* @param method The HTTP method. +* @param path The path to fetch data from. +* @returns The response. +*/ function useRouter(router, method, path) { - return router.fetch({ - method, - url: `file://${path}` - }); + return router.fetch({ + method, + url: `file://${path}` + }); } -var REGEXP_FILE_EXTENSION = /\.(js|mjs|cjs|ts)$/; -var REGEXP_TEST_FILE_EXTENSION = /\.test\.(js|mjs|cjs|ts)$/; -var REGEXP_HTTP_METHOD = /\.\[(delete|get|head|options|patch|post|put)]$/; -var REGEXP_PATH_SLUG = /\[(\w+)]/g; +const REGEXP_FILE_EXTENSION = /\.(js|mjs|cjs|ts)$/; +const REGEXP_TEST_FILE_EXTENSION = /\.test\.(js|mjs|cjs|ts)$/; +const REGEXP_HTTP_METHOD = /\.\[(delete|get|head|options|patch|post|put)]$/; +const REGEXP_PATH_SLUG = /\[(\w+)]/g; +/** +* Scans directory for routes. +* @param router The router to add routes to. +* @param path The path to scan. +* @param [regexp_parts] The parts of the regular expression. +*/ function scanDirectory(router, path, regexp_parts = [""]) { - const result = import_node_fs.readdirSync(path, { - withFileTypes: true - }); - const routes = { - 0: [], - 1: [], - 2: [], - 3: [] - }; - for (const entry of result) { - const entry_path = import_node_path.default.join(path, entry.name); - if (entry.isFile()) { - let file_name = entry.name; - if (REGEXP_FILE_EXTENSION.test(file_name) && REGEXP_TEST_FILE_EXTENSION.test(file_name) !== true) { - file_name = file_name.replace(REGEXP_FILE_EXTENSION, ""); - let method = "all"; - const method_match = file_name.match(REGEXP_HTTP_METHOD); - const has_method = method_match ? 1 : 0; - if (method_match) { - method = method_match[1]; - file_name = file_name.replace(REGEXP_HTTP_METHOD, ""); - } - const has_slug = REGEXP_PATH_SLUG.test(file_name) ? 2 : 0; - file_name = file_name.replaceAll(REGEXP_PATH_SLUG, ":$1"); - routes[has_method | has_slug].push({ - method, - path: [ - ...regexp_parts, - file_name - ].join(import_node_path.default.sep), - module_path: entry_path - }); - } - } else { - scanDirectory(router, entry_path, [ - ...regexp_parts, - entry.name.replaceAll(REGEXP_PATH_SLUG, ":$1") - ]); - } - } - for (const route of [ - ...routes[1], - ...routes[3], - ...routes[0], - ...routes[2] - ]) { - router[route.method](route.path, (r) => { - const response = { - module_path: route.module_path, - args: r.params - }; - return response; - }); - } + const result = (0, node_fs.readdirSync)(path, { withFileTypes: true }); + const routes = { + 0: [], + 1: [], + 2: [], + 3: [] + }; + for (const entry of result) { + const entry_path = node_path.default.join(path, entry.name); + if (entry.isFile()) { + let file_name = entry.name; + if (REGEXP_FILE_EXTENSION.test(file_name) && REGEXP_TEST_FILE_EXTENSION.test(file_name) !== true) { + file_name = file_name.replace(REGEXP_FILE_EXTENSION, ""); + let method = "all"; + const method_match = file_name.match(REGEXP_HTTP_METHOD); + const has_method = method_match ? 1 : 0; + if (method_match) { + method = method_match[1]; + file_name = file_name.replace(REGEXP_HTTP_METHOD, ""); + } + const has_slug = REGEXP_PATH_SLUG.test(file_name) ? 2 : 0; + file_name = file_name.replaceAll(REGEXP_PATH_SLUG, ":$1"); + routes[has_method | has_slug]?.push({ + method, + path: [...regexp_parts, file_name].join(node_path.default.sep), + module_path: entry_path + }); + } + } else scanDirectory(router, entry_path, [...regexp_parts, entry.name.replaceAll(REGEXP_PATH_SLUG, ":$1")]); + } + for (const route of [ + ...routes[1], + ...routes[3], + ...routes[0], + ...routes[2] + ]) router[route.method](route.path, (r) => { + const response = { + module_path: route.module_path, + args: r.params + }; + return response; + }); } -// dist/esm/utils/methods.js + +//#endregion +//#region src/utils/methods.ts +/** +* Checks if the given value is a valid HyperAPI method. +* @param method The HTTP method to check. +* @returns - +*/ function isHyperApiMethod(method) { - return method === "DELETE" || method === "GET" || method === "HEAD" || method === "OPTIONS" || method === "PATCH" || method === "POST" || method === "PUT" || method === "UNKNOWN"; + return method === "DELETE" || method === "GET" || method === "HEAD" || method === "OPTIONS" || method === "PATCH" || method === "POST" || method === "PUT" || method === "UNKNOWN"; } -// dist/esm/main.js -var ENTRYPOINT_PATH = import_node_path2.default.dirname(process.argv[1]); +//#endregion +//#region src/main.ts +const ENTRYPOINT_PATH = node_path.default.dirname(process.argv[1]); +var HyperAPI = class { + router; + driver; + /** + * Creates a HyperAPI instance. + * @param options The options. + * @param options.driver The driver. + * @param [options.root] The root directory for API methods modules. Default: `hyper-api` directory alongside the entrypoint script. + */ + constructor({ driver, root = node_path.default.join(ENTRYPOINT_PATH, "hyper-api") }) { + this.driver = driver; + this.router = createRouter(root); + this.driver.start(async (driver_request) => { + const [request, module_, response] = await this.processRequest(driver_request); + if (request && module_) for (const hook of this.handlers.response) try { + await hook(request, module_, response); + } catch (error) { + console.error("Error in \"response\" hook:"); + console.error(error); + } + return response; + }); + } + handlers = { + transformer: void 0, + module: [], + response: [] + }; + /** + * Use this hook add properties to the request before it is send to the API module. + * + * This hook can be set only once. + * @param transformer The callback function. + */ + setTransformer(transformer) { + if (this.handlers.transformer) throw new Error("Transformer has already been set."); + this.handlers.transformer = transformer; + } + /** + * Adds a hook to be called when the API module is imported. + * @param callback - + */ + onModule(callback) { + this.handlers.module.push(callback); + } + /** + * Adds a hook to be called right before the response is sent back. + * + * This hook called only if the request was processed by the API module. If unknown method was requested, this hook is not called. + * @param callback - + */ + onResponse(callback) { + this.handlers.response.push(callback); + } + async processRequest(driver_request) { + let request = null; + let module_ = null; + try { + if (driver_request.path.startsWith("/") !== true) driver_request.path = `/${driver_request.path}`; + const router_response = await useRouter(this.router, driver_request.method, driver_request.path); + if (!router_response) throw new HyperAPIUnknownMethodError(); + driver_request.args = { + ...driver_request.args, + ...router_response.args + }; + request = this.handlers.transformer ? await this.handlers.transformer(driver_request) : driver_request; + module_ = await import(router_response.module_path); + if (module_.argsValidator) try { + request.args = module_.argsValidator(request.args); + } catch (error) { + console.error(error); + throw new HyperAPIInvalidParametersError(); + } + for (const hook of this.handlers.module) await hook(request, module_); + const response = await module_.default(request); + return [ + request, + module_, + response + ]; + } catch (error) { + if (error instanceof HyperAPIError) return [ + request, + module_, + error + ]; + console.error(error); + return [ + request, + module_, + new HyperAPIInternalError() + ]; + } + } + /** Destroys the HyperAPI instance. */ + destroy() { + this.handlers.transformer = void 0; + this.handlers.module.splice(0); + this.handlers.response.splice(0); + } +}; -class HyperAPI { - router; - driver; - constructor({ driver, root = import_node_path2.default.join(ENTRYPOINT_PATH, "hyper-api") }) { - this.driver = driver; - this.router = createRouter(root); - this.driver.start(async (driver_request) => { - const [request, module_, response] = await this.processRequest(driver_request); - if (request && module_) { - for (const hook of this.handlers.response) { - try { - await hook(request, module_, response); - } catch (error) { - console.error('Error in "response" hook:'); - console.error(error); - } - } - } - return response; - }); - } - handlers = { - transformer: undefined, - module: [], - response: [] - }; - setTransformer(transformer) { - if (this.handlers.transformer) { - throw new Error("Transformer has already been set."); - } - this.handlers.transformer = transformer; - } - onModule(callback) { - this.handlers.module.push(callback); - } - onResponse(callback) { - this.handlers.response.push(callback); - } - async processRequest(driver_request) { - let request = null; - let module_ = null; - try { - if (driver_request.path.startsWith("/") !== true) { - driver_request.path = `/${driver_request.path}`; - } - const router_response = await useRouter(this.router, driver_request.method, driver_request.path); - if (!router_response) { - throw new HyperAPIUnknownMethodError; - } - driver_request.args = { - ...driver_request.args, - ...router_response.args - }; - request = this.handlers.transformer ? await this.handlers.transformer(driver_request) : driver_request; - module_ = await import(router_response.module_path); - if (module_.argsValidator) { - try { - request.args = module_.argsValidator(request.args); - } catch (error) { - console.error(error); - throw new HyperAPIInvalidParametersError; - } - } - for (const hook of this.handlers.module) { - await hook(request, module_); - } - const response = await module_.default(request); - return [ - request, - module_, - response - ]; - } catch (error) { - if (error instanceof HyperAPIError) { - return [ - request, - module_, - error - ]; - } - console.error(error); - return [ - request, - module_, - new HyperAPIInternalError - ]; - } - throw new Error("Unreachable"); - } - destroy() { - this.handlers.transformer = undefined; - this.handlers.module.splice(0); - this.handlers.response.splice(0); - } -} +//#endregion +exports.HyperAPI = HyperAPI; +exports.HyperAPIAuthorizationError = HyperAPIAuthorizationError; +exports.HyperAPIBusyError = HyperAPIBusyError; +exports.HyperAPICaptchaError = HyperAPICaptchaError; +exports.HyperAPIConfirmationError = HyperAPIConfirmationError; +exports.HyperAPIError = HyperAPIError; +exports.HyperAPIForbiddenError = HyperAPIForbiddenError; +exports.HyperAPIInternalError = HyperAPIInternalError; +exports.HyperAPIInvalidParametersError = HyperAPIInvalidParametersError; +exports.HyperAPIMaintenanceError = HyperAPIMaintenanceError; +exports.HyperAPIMethodNotAllowedError = HyperAPIMethodNotAllowedError; +exports.HyperAPIOTPError = HyperAPIOTPError; +exports.HyperAPIObjectsLimitError = HyperAPIObjectsLimitError; +exports.HyperAPIRateLimitError = HyperAPIRateLimitError; +exports.HyperAPIUnknownMethodError = HyperAPIUnknownMethodError; +exports.isHyperApiMethod = isHyperApiMethod; \ No newline at end of file diff --git a/dist/main.d.ts b/dist/main.d.ts new file mode 100644 index 0000000..1a8ddef --- /dev/null +++ b/dist/main.d.ts @@ -0,0 +1,191 @@ +import { EmptyObject, Promisable } from "type-fest"; + +//#region src/utils/methods.d.ts +type HyperAPIMethod = "DELETE" | "GET" | "HEAD" | "OPTIONS" | "PATCH" | "POST" | "PUT" | "UNKNOWN"; +/** +* Checks if the given value is a valid HyperAPI method. +* @param method The HTTP method to check. +* @returns - +*/ +declare function isHyperApiMethod(method: unknown): method is HyperAPIMethod; + +//#endregion +//#region src/request.d.ts +type HyperAPIRequestArgs = Record; +interface HyperAPIRequest { + method: HyperAPIMethod; + path: string; + args: A; +} + +//#endregion +//#region src/error.d.ts +type HyperAPIErrorData = Record | undefined; +interface HyperAPIErrorResponse { + code: number; + description?: string; + data?: HyperAPIErrorData; +} +declare class HyperAPIError extends Error { + /** The error code. */ + readonly code: number; + /** The error description. */ + readonly description: string; + /** The error data. */ + readonly data?: D; + /** HTTP status code. */ + readonly httpStatus?: number; + /** HTTP headers to return. */ + readonly httpHeaders?: Record; + constructor(data?: D); + get message(): string; + /** + * Creates response object. + * @returns - + */ + getResponse(): HyperAPIErrorResponse; +} + +//#endregion +//#region src/module.d.ts +type HyperAPIModuleResponse = Record | Response | unknown[] | undefined; +interface HyperAPIModule> { + readonly default: (request: R) => Promisable; + readonly argsValidator: (args: unknown) => R extends HyperAPIRequest ? A : never; +} +// export type HyperAPIModuleRequest> = Parameters[0]; +// eslint-disable-next-line @typescript-eslint/no-explicit-any +type InferModule> = H extends HyperAPI ? M : never; + +//#endregion +//#region src/response.d.ts +// eslint-disable-next-line @typescript-eslint/no-explicit-any +type HyperAPIResponse = HyperAPIModuleResponse | HyperAPIError; + +//#endregion +//#region src/driver.d.ts +type HyperAPIDriverHandler = (request: R) => Promisable; +interface HyperAPIDriver { + start(handler: HyperAPIDriverHandler): void; + stop(): void; +} +type InferDriverRequest = D extends HyperAPIDriver ? R : never; + +//#endregion +//#region src/api-errors.d.ts +declare class HyperAPIAuthorizationError extends HyperAPIError { + code: number; + description: string; + httpStatus: number; +} +declare class HyperAPIInvalidParametersError extends HyperAPIError { + code: number; + description: string; + httpStatus: number; +} +declare class HyperAPIInternalError extends HyperAPIError { + code: number; + description: string; + httpStatus: number; +} +declare class HyperAPIForbiddenError extends HyperAPIError { + code: number; + description: string; + httpStatus: number; +} +declare class HyperAPIUnknownMethodError extends HyperAPIError { + code: number; + description: string; + httpStatus: number; +} +declare class HyperAPIObjectsLimitError extends HyperAPIError { + code: number; + description: string; + httpStatus: number; +} +declare class HyperAPIRateLimitError extends HyperAPIError { + code: number; + description: string; + httpStatus: number; +} +declare class HyperAPICaptchaError extends HyperAPIError { + code: number; + description: string; + httpStatus: number; +} +declare class HyperAPIBusyError extends HyperAPIError { + code: number; + description: string; + httpStatus: number; +} +declare class HyperAPIConfirmationError extends HyperAPIError { + code: number; + description: string; + httpStatus: number; +} +declare class HyperAPIOTPError extends HyperAPIError { + code: number; + description: string; + httpStatus: number; +} +declare class HyperAPIMaintenanceError extends HyperAPIError { + code: number; + description: string; + httpStatus: number; +} +declare class HyperAPIMethodNotAllowedError extends HyperAPIError { + code: number; + description: string; + httpStatus: number; +} + +//#endregion +//#region src/main.d.ts +interface HyperAPIHandlers, M extends HyperAPIModule> { + transformer: ((driver_request: Readonly>) => Promisable) | void; + module: ((request: Readonly, module_: M) => Promisable)[]; + response: ((request: R, module_: M, response: HyperAPIResponse) => Promisable)[]; +} +declare class HyperAPI, R extends InferDriverRequest, M extends HyperAPIModule = HyperAPIModule> { + private router; + private driver; + /** + * Creates a HyperAPI instance. + * @param options The options. + * @param options.driver The driver. + * @param [options.root] The root directory for API methods modules. Default: `hyper-api` directory alongside the entrypoint script. + */ + constructor({ + driver, + root + }: { + driver: D; + root?: string; + }); + private handlers; + /** + * Use this hook add properties to the request before it is send to the API module. + * + * This hook can be set only once. + * @param transformer The callback function. + */ + setTransformer(transformer: HyperAPIHandlers["transformer"]): void; + /** + * Adds a hook to be called when the API module is imported. + * @param callback - + */ + onModule(callback: HyperAPIHandlers["module"][number]): void; + /** + * Adds a hook to be called right before the response is sent back. + * + * This hook called only if the request was processed by the API module. If unknown method was requested, this hook is not called. + * @param callback - + */ + onResponse(callback: HyperAPIHandlers["response"][number]): void; + private processRequest; + /** Destroys the HyperAPI instance. */ + destroy(): void; +} + +//#endregion +export { HyperAPI, HyperAPIAuthorizationError, HyperAPIBusyError, HyperAPICaptchaError, HyperAPIConfirmationError, HyperAPIDriver, HyperAPIDriverHandler, HyperAPIError, HyperAPIErrorData, HyperAPIForbiddenError, HyperAPIInternalError, HyperAPIInvalidParametersError, HyperAPIMaintenanceError, HyperAPIMethod, HyperAPIMethodNotAllowedError, HyperAPIModule, HyperAPIModuleResponse, HyperAPIOTPError, HyperAPIObjectsLimitError, HyperAPIRateLimitError, HyperAPIRequest, HyperAPIRequestArgs, HyperAPIResponse, HyperAPIUnknownMethodError, InferModule, isHyperApiMethod }; \ No newline at end of file diff --git a/dist/main.js b/dist/main.js new file mode 100644 index 0000000..a210ccc --- /dev/null +++ b/dist/main.js @@ -0,0 +1,312 @@ +import nodePath from "node:path"; +import { IttyRouter } from "itty-router"; +import { readdirSync } from "node:fs"; + +//#region src/utils/is-record.ts +/** +* Check if a value is a record. +* @param value - +* @returns - +*/ +function isRecord(value) { + return typeof value === "object" && value !== null && !Array.isArray(value) && value.constructor === Object && Object.prototype.toString.call(value) === "[object Object]"; +} + +//#endregion +//#region src/error.ts +var HyperAPIError = class extends Error { + /** The error code. */ + code = 0; + /** The error description. */ + description = "HyperAPI error"; + /** The error data. */ + data; + /** HTTP status code. */ + httpStatus; + /** HTTP headers to return. */ + httpHeaders; + constructor(data) { + super(); + if (isRecord(data)) this.data = data; + } + get message() { + return `${this.description} (code ${this.code}).`; + } + /** + * Creates response object. + * @returns - + */ + getResponse() { + const response = { code: this.code }; + if (typeof this.description === "string") response.description = this.description; + if (this.data) response.data = this.data; + return response; + } +}; + +//#endregion +//#region src/api-errors.ts +var HyperAPIAuthorizationError = class extends HyperAPIError { + code = 1; + description = "Authorization error"; + httpStatus = 401; +}; +var HyperAPIInvalidParametersError = class extends HyperAPIError { + code = 2; + description = "One of the parameters specified was missing or invalid"; + httpStatus = 400; +}; +var HyperAPIInternalError = class extends HyperAPIError { + code = 3; + description = "Internal error"; + httpStatus = 500; +}; +var HyperAPIForbiddenError = class extends HyperAPIError { + code = 4; + description = "You do not have permission to perform this action"; + httpStatus = 403; +}; +var HyperAPIUnknownMethodError = class extends HyperAPIError { + code = 5; + description = "Unknown method called"; + httpStatus = 404; +}; +var HyperAPIObjectsLimitError = class extends HyperAPIError { + code = 6; + description = "Too many objects requested"; + httpStatus = 400; +}; +var HyperAPIRateLimitError = class extends HyperAPIError { + code = 7; + description = "Rate limit exceeded"; + httpStatus = 429; +}; +var HyperAPICaptchaError = class extends HyperAPIError { + code = 8; + description = "Captcha required"; + httpStatus = 428; +}; +var HyperAPIBusyError = class extends HyperAPIError { + code = 10; + description = "Endpoint is busy"; + httpStatus = 503; +}; +var HyperAPIConfirmationError = class extends HyperAPIError { + code = 11; + description = "Confirmation required"; + httpStatus = 409; +}; +var HyperAPIOTPError = class extends HyperAPIError { + code = 12; + description = "One-time password required"; + httpStatus = 401; +}; +var HyperAPIMaintenanceError = class extends HyperAPIError { + code = 13; + description = "Endpoint is in maintenance mode"; + httpStatus = 503; +}; +var HyperAPIMethodNotAllowedError = class extends HyperAPIError { + code = 14; + description = "HTTP method not allowed"; + httpStatus = 405; +}; + +//#endregion +//#region src/router.ts +/** +* Creates new IttyRouter from filesystem. +* @param path The path to scan. +* @returns The new IttyRouter. +*/ +function createRouter(path) { + const router = IttyRouter(); + scanDirectory(router, path); + return router; +} +/** +* Fetches data from router. +* @param router The router to fetch data from. +* @param method The HTTP method. +* @param path The path to fetch data from. +* @returns The response. +*/ +function useRouter(router, method, path) { + return router.fetch({ + method, + url: `file://${path}` + }); +} +const REGEXP_FILE_EXTENSION = /\.(js|mjs|cjs|ts)$/; +const REGEXP_TEST_FILE_EXTENSION = /\.test\.(js|mjs|cjs|ts)$/; +const REGEXP_HTTP_METHOD = /\.\[(delete|get|head|options|patch|post|put)]$/; +const REGEXP_PATH_SLUG = /\[(\w+)]/g; +/** +* Scans directory for routes. +* @param router The router to add routes to. +* @param path The path to scan. +* @param [regexp_parts] The parts of the regular expression. +*/ +function scanDirectory(router, path, regexp_parts = [""]) { + const result = readdirSync(path, { withFileTypes: true }); + const routes = { + 0: [], + 1: [], + 2: [], + 3: [] + }; + for (const entry of result) { + const entry_path = nodePath.join(path, entry.name); + if (entry.isFile()) { + let file_name = entry.name; + if (REGEXP_FILE_EXTENSION.test(file_name) && REGEXP_TEST_FILE_EXTENSION.test(file_name) !== true) { + file_name = file_name.replace(REGEXP_FILE_EXTENSION, ""); + let method = "all"; + const method_match = file_name.match(REGEXP_HTTP_METHOD); + const has_method = method_match ? 1 : 0; + if (method_match) { + method = method_match[1]; + file_name = file_name.replace(REGEXP_HTTP_METHOD, ""); + } + const has_slug = REGEXP_PATH_SLUG.test(file_name) ? 2 : 0; + file_name = file_name.replaceAll(REGEXP_PATH_SLUG, ":$1"); + routes[has_method | has_slug]?.push({ + method, + path: [...regexp_parts, file_name].join(nodePath.sep), + module_path: entry_path + }); + } + } else scanDirectory(router, entry_path, [...regexp_parts, entry.name.replaceAll(REGEXP_PATH_SLUG, ":$1")]); + } + for (const route of [ + ...routes[1], + ...routes[3], + ...routes[0], + ...routes[2] + ]) router[route.method](route.path, (r) => { + const response = { + module_path: route.module_path, + args: r.params + }; + return response; + }); +} + +//#endregion +//#region src/utils/methods.ts +/** +* Checks if the given value is a valid HyperAPI method. +* @param method The HTTP method to check. +* @returns - +*/ +function isHyperApiMethod(method) { + return method === "DELETE" || method === "GET" || method === "HEAD" || method === "OPTIONS" || method === "PATCH" || method === "POST" || method === "PUT" || method === "UNKNOWN"; +} + +//#endregion +//#region src/main.ts +const ENTRYPOINT_PATH = nodePath.dirname(process.argv[1]); +var HyperAPI = class { + router; + driver; + /** + * Creates a HyperAPI instance. + * @param options The options. + * @param options.driver The driver. + * @param [options.root] The root directory for API methods modules. Default: `hyper-api` directory alongside the entrypoint script. + */ + constructor({ driver, root = nodePath.join(ENTRYPOINT_PATH, "hyper-api") }) { + this.driver = driver; + this.router = createRouter(root); + this.driver.start(async (driver_request) => { + const [request, module_, response] = await this.processRequest(driver_request); + if (request && module_) for (const hook of this.handlers.response) try { + await hook(request, module_, response); + } catch (error) { + console.error("Error in \"response\" hook:"); + console.error(error); + } + return response; + }); + } + handlers = { + transformer: void 0, + module: [], + response: [] + }; + /** + * Use this hook add properties to the request before it is send to the API module. + * + * This hook can be set only once. + * @param transformer The callback function. + */ + setTransformer(transformer) { + if (this.handlers.transformer) throw new Error("Transformer has already been set."); + this.handlers.transformer = transformer; + } + /** + * Adds a hook to be called when the API module is imported. + * @param callback - + */ + onModule(callback) { + this.handlers.module.push(callback); + } + /** + * Adds a hook to be called right before the response is sent back. + * + * This hook called only if the request was processed by the API module. If unknown method was requested, this hook is not called. + * @param callback - + */ + onResponse(callback) { + this.handlers.response.push(callback); + } + async processRequest(driver_request) { + let request = null; + let module_ = null; + try { + if (driver_request.path.startsWith("/") !== true) driver_request.path = `/${driver_request.path}`; + const router_response = await useRouter(this.router, driver_request.method, driver_request.path); + if (!router_response) throw new HyperAPIUnknownMethodError(); + driver_request.args = { + ...driver_request.args, + ...router_response.args + }; + request = this.handlers.transformer ? await this.handlers.transformer(driver_request) : driver_request; + module_ = await import(router_response.module_path); + if (module_.argsValidator) try { + request.args = module_.argsValidator(request.args); + } catch (error) { + console.error(error); + throw new HyperAPIInvalidParametersError(); + } + for (const hook of this.handlers.module) await hook(request, module_); + const response = await module_.default(request); + return [ + request, + module_, + response + ]; + } catch (error) { + if (error instanceof HyperAPIError) return [ + request, + module_, + error + ]; + console.error(error); + return [ + request, + module_, + new HyperAPIInternalError() + ]; + } + } + /** Destroys the HyperAPI instance. */ + destroy() { + this.handlers.transformer = void 0; + this.handlers.module.splice(0); + this.handlers.response.splice(0); + } +}; + +//#endregion +export { HyperAPI, HyperAPIAuthorizationError, HyperAPIBusyError, HyperAPICaptchaError, HyperAPIConfirmationError, HyperAPIError, HyperAPIForbiddenError, HyperAPIInternalError, HyperAPIInvalidParametersError, HyperAPIMaintenanceError, HyperAPIMethodNotAllowedError, HyperAPIOTPError, HyperAPIObjectsLimitError, HyperAPIRateLimitError, HyperAPIUnknownMethodError, isHyperApiMethod }; \ No newline at end of file diff --git a/package.json b/package.json index 9de2468..127e890 100644 --- a/package.json +++ b/package.json @@ -6,11 +6,11 @@ "access": "public" }, "type": "module", - "main": "dist/esm/main.js", - "types": "dist/esm/main.d.ts", + "main": "dist/main.js", + "types": "dist/main.d.ts", "exports": { ".": { - "import": "./dist/esm/main.js", + "import": "./dist/main.js", "require": "./dist/main.cjs" } }, @@ -22,20 +22,22 @@ }, "devDependencies": { "@kirick/eslint-config": "^0.1.30", - "@types/bun": "^1.1.9", + "@types/bun": "^1.2.13", "eslint": "9.10.0", - "typescript": "5.5.4", - "valibot": "^0.42.0", - "vitest": "2.1.1" + "oxc-parser": "0.71.0", + "publint": "0.3.12", + "tsdown": "0.12.2", + "type-fest": "^4.41.0", + "typescript": "5.8.3", + "unplugin-unused": "0.5.0", + "valibot": "1.1.0", + "vitest": "3.1.4" }, "scripts": { - "build": "rm -r dist ; bun run build:ts && bun run build:cjs", - "build:cjs": "bun build dist/esm/main.js --platform=node --format=cjs --packages=external --outfile=dist/main.cjs", - "# build:cjs": "bunx esbuild --bundle --platform=node --format=cjs --packages=external --outfile=dist/main.cjs dist/esm/main.js", - "build:ts": "rm -r dist/esm ; tsc", + "build": "tsdown src/main.ts --publint --unused --dts --format esm --format cjs && rm dist/main.d.cts", "check": "bun run build && bun run lint && bun run test", - "lint": "eslint . && tsc --skipLibCheck --noemit", - "test": "npm run test:vitest && bun test --coverage src/ test/", + "lint": "eslint . && tsc && (cd test && tsc)", + "test": "npm run test:vitest && bun test --coverage", "test:vitest": "vitest run --no-file-parallelism" }, "repository": { diff --git a/src/api-errors.ts b/src/api-errors.ts index a084e13..b5ddf85 100644 --- a/src/api-errors.ts +++ b/src/api-errors.ts @@ -4,79 +4,79 @@ import { } from './error.js'; export class HyperAPIAuthorizationError extends HyperAPIError { - code = 1; - description = 'Authorization error'; - httpStatus = 401; // Unauthorized + override code = 1; + override description = 'Authorization error'; + override httpStatus = 401; // Unauthorized } export class HyperAPIInvalidParametersError extends HyperAPIError { - code = 2; - description = 'One of the parameters specified was missing or invalid'; - httpStatus = 400; // Bad Request + override code = 2; + override description = 'One of the parameters specified was missing or invalid'; + override httpStatus = 400; // Bad Request } export class HyperAPIInternalError extends HyperAPIError { - code = 3; - description = 'Internal error'; - httpStatus = 500; // Internal Server Error + override code = 3; + override description = 'Internal error'; + override httpStatus = 500; // Internal Server Error } export class HyperAPIForbiddenError extends HyperAPIError { - code = 4; - description = 'You do not have permission to perform this action'; - httpStatus = 403; // Forbidden + override code = 4; + override description = 'You do not have permission to perform this action'; + override httpStatus = 403; // Forbidden } export class HyperAPIUnknownMethodError extends HyperAPIError { - code = 5; - description = 'Unknown method called'; - httpStatus = 404; // Not Found + override code = 5; + override description = 'Unknown method called'; + override httpStatus = 404; // Not Found } export class HyperAPIObjectsLimitError extends HyperAPIError { - code = 6; - description = 'Too many objects requested'; - httpStatus = 400; // Bad Request + override code = 6; + override description = 'Too many objects requested'; + override httpStatus = 400; // Bad Request } export class HyperAPIRateLimitError extends HyperAPIError { - code = 7; - description = 'Rate limit exceeded'; - httpStatus = 429; // Too Many Requests + override code = 7; + override description = 'Rate limit exceeded'; + override httpStatus = 429; // Too Many Requests } export class HyperAPICaptchaError extends HyperAPIError { - code = 8; - description = 'Captcha required'; - httpStatus = 428; // Precondition Required + override code = 8; + override description = 'Captcha required'; + override httpStatus = 428; // Precondition Required } export class HyperAPIBusyError extends HyperAPIError { - code = 10; - description = 'Endpoint is busy'; - httpStatus = 503; // Service Unavailable + override code = 10; + override description = 'Endpoint is busy'; + override httpStatus = 503; // Service Unavailable } export class HyperAPIConfirmationError extends HyperAPIError { - code = 11; - description = 'Confirmation required'; - httpStatus = 409; // Conflict + override code = 11; + override description = 'Confirmation required'; + override httpStatus = 409; // Conflict } export class HyperAPIOTPError extends HyperAPIError { - code = 12; - description = 'One-time password required'; - httpStatus = 401; // Unauthorized + override code = 12; + override description = 'One-time password required'; + override httpStatus = 401; // Unauthorized } export class HyperAPIMaintenanceError extends HyperAPIError { - code = 13; - description = 'Endpoint is in maintenance mode'; - httpStatus = 503; // Service Unavailable + override code = 13; + override description = 'Endpoint is in maintenance mode'; + override httpStatus = 503; // Service Unavailable } export class HyperAPIMethodNotAllowedError extends HyperAPIError { - code = 14; - description = 'HTTP method not allowed'; - httpStatus = 405; // Method Not Allowed + override code = 14; + override description = 'HTTP method not allowed'; + override httpStatus = 405; // Method Not Allowed } diff --git a/src/driver.ts b/src/driver.ts index 31fe25e..57abf74 100644 --- a/src/driver.ts +++ b/src/driver.ts @@ -1,12 +1,10 @@ +import type { Promisable } from 'type-fest'; import type { HyperAPIRequest, } from './request.js'; import type { HyperAPIResponse } from './response.js'; -import { - MaybePromise, -} from './utils/types.js'; -export type HyperAPIDriverHandler = (request: R) => MaybePromise; +export type HyperAPIDriverHandler = (request: R) => Promisable; export interface HyperAPIDriver { start(handler: HyperAPIDriverHandler): void; diff --git a/src/error.ts b/src/error.ts index 854db50..46dfdfc 100644 --- a/src/error.ts +++ b/src/error.ts @@ -30,7 +30,7 @@ export class HyperAPIError< } } - get message() { + override get message() { return `${this.description} (code ${this.code}).`; } @@ -38,7 +38,7 @@ export class HyperAPIError< * Creates response object. * @returns - */ - getResponse() { + getResponse(): HyperAPIErrorResponse { const response: HyperAPIErrorResponse = { code: this.code, }; diff --git a/src/main.ts b/src/main.ts index 24f8151..2b1be11 100644 --- a/src/main.ts +++ b/src/main.ts @@ -1,4 +1,5 @@ import nodePath from 'node:path'; +import type { Promisable } from 'type-fest'; import { HyperAPIInternalError, HyperAPIInvalidParametersError, @@ -16,19 +17,18 @@ import { createRouter, useRouter, } from './router.js'; -import type { MaybePromise } from './utils/types.js'; interface HyperAPIHandlers< D extends HyperAPIDriver, R extends InferDriverRequest, M extends HyperAPIModule, > { - transformer: ((driver_request: Readonly>) => MaybePromise) | void; - module: ((request: Readonly, module_: M) => MaybePromise)[]; - response: ((request: R, module_: M, response: HyperAPIResponse) => MaybePromise)[]; + transformer: ((driver_request: Readonly>) => Promisable) | void; + module: ((request: Readonly, module_: M) => Promisable)[]; + response: ((request: R, module_: M, response: HyperAPIResponse) => Promisable)[]; } -const ENTRYPOINT_PATH = nodePath.dirname(process.argv[1]); +const ENTRYPOINT_PATH = nodePath.dirname(process.argv[1]!); export class HyperAPI< D extends HyperAPIDriver, @@ -46,10 +46,7 @@ export class HyperAPI< */ constructor({ driver, - root = nodePath.join( - ENTRYPOINT_PATH, - 'hyper-api', - ), + root = nodePath.join(ENTRYPOINT_PATH, 'hyper-api'), }: { driver: D, root?: string, @@ -95,7 +92,7 @@ export class HyperAPI< * This hook can be set only once. * @param transformer The callback function. */ - setTransformer(transformer: typeof this.handlers['transformer']) { + setTransformer(transformer: HyperAPIHandlers['transformer']): void { if (this.handlers.transformer) { throw new Error('Transformer has already been set.'); } @@ -107,7 +104,7 @@ export class HyperAPI< * Adds a hook to be called when the API module is imported. * @param callback - */ - onModule(callback: typeof this.handlers['module'][number]) { + onModule(callback: HyperAPIHandlers['module'][number]): void { this.handlers.module.push(callback); } @@ -117,7 +114,7 @@ export class HyperAPI< * This hook called only if the request was processed by the API module. If unknown method was requested, this hook is not called. * @param callback - */ - onResponse(callback: typeof this.handlers['response'][number]) { + onResponse(callback: HyperAPIHandlers['response'][number]): void { this.handlers.response.push(callback); } @@ -201,12 +198,10 @@ export class HyperAPI< new HyperAPIInternalError(), ]; } - - throw new Error('Unreachable'); } /** Destroys the HyperAPI instance. */ - destroy() { + destroy(): void { this.handlers.transformer = undefined; this.handlers.module.splice(0); this.handlers.response.splice(0); @@ -233,6 +228,6 @@ export type { } from './request.js'; export type { HyperAPIResponse } from './response.js'; export { - isHyperApiMethod, type HyperAPIMethod, + isHyperApiMethod, } from './utils/methods.js'; diff --git a/src/module.ts b/src/module.ts index ca6a0b9..ca5d30c 100644 --- a/src/module.ts +++ b/src/module.ts @@ -1,16 +1,14 @@ +import type { Promisable } from 'type-fest'; import { HyperAPI } from './main.js'; import type { HyperAPIRequest, HyperAPIRequestArgs, } from './request.js'; -import type { - MaybePromise, -} from './utils/types.js'; export type HyperAPIModuleResponse = Record | Response | unknown[] | undefined; export interface HyperAPIModule> { - readonly default: (request: R) => MaybePromise; + readonly default: (request: R) => Promisable; readonly argsValidator: (args: unknown) => R extends HyperAPIRequest ? A : never; } diff --git a/src/request.ts b/src/request.ts index 6b169db..030c02d 100644 --- a/src/request.ts +++ b/src/request.ts @@ -1,9 +1,5 @@ -import type { - HyperAPIMethod, -} from './utils/methods.js'; -import type { - EmptyObject, -} from './utils/types.js'; +import type { EmptyObject } from 'type-fest'; +import type { HyperAPIMethod } from './utils/methods.js'; export type HyperAPIRequestArgs = Record; diff --git a/src/response.ts b/src/response.ts index 4168fdc..6d0c16d 100644 --- a/src/response.ts +++ b/src/response.ts @@ -1,5 +1,5 @@ import { HyperAPIError } from './error.js'; -import { HyperAPIModuleResponse } from './module.js'; +import type { HyperAPIModuleResponse } from './module.js'; // eslint-disable-next-line @typescript-eslint/no-explicit-any export type HyperAPIResponse = HyperAPIModuleResponse | HyperAPIError; diff --git a/src/router.ts b/src/router.ts index e93443c..0815912 100644 --- a/src/router.ts +++ b/src/router.ts @@ -7,14 +7,15 @@ import { } from 'itty-router'; import { readdirSync } from 'node:fs'; import nodePath from 'node:path'; -import { HyperAPIMethod } from './utils/methods.js'; +import type { HyperAPIMethod } from './utils/methods.js'; /** * Creates new IttyRouter from filesystem. * @param path The path to scan. * @returns The new IttyRouter. */ -export function createRouter(path: string) { +// eslint-disable-next-line @typescript-eslint/no-explicit-any +export function createRouter(path: string): IttyRouterType { // eslint-disable-next-line new-cap const router = IttyRouter(); @@ -75,7 +76,7 @@ function scanDirectory( }, ); - const routes: Record = { + const routes: Record = { 0: [], // routes with no method and no slug 1: [], // routes with method and no slug 2: [], // routes with no method and slug @@ -127,7 +128,7 @@ function scanDirectory( // ); // eslint-disable-next-line no-bitwise - routes[has_method | has_slug].push({ + routes[has_method | has_slug]?.push({ method, path: [ ...regexp_parts, @@ -154,10 +155,11 @@ function scanDirectory( for ( const route of [ - ...routes[1], - ...routes[3], - ...routes[0], - ...routes[2], + // suppress indexed access to fail + ...routes[1]!, + ...routes[3]!, + ...routes[0]!, + ...routes[2]!, ] ) { router[route.method]( diff --git a/src/utils/types.ts b/src/utils/types.ts deleted file mode 100644 index ed6ddd3..0000000 --- a/src/utils/types.ts +++ /dev/null @@ -1,2 +0,0 @@ -export type EmptyObject = Omit<{ p: never }, 'p'>; -export type MaybePromise = T | Promise; diff --git a/test/setup.ts b/test/setup.ts index 0ecaf58..ac76f07 100644 --- a/test/setup.ts +++ b/test/setup.ts @@ -1,14 +1,14 @@ +import type { EmptyObject } from 'type-fest'; import { + type HyperAPIDriver, + type HyperAPIDriverHandler, + type HyperAPIModule, + type HyperAPIRequest, + type HyperAPIRequestArgs, HyperAPI, - HyperAPIDriver, - HyperAPIDriverHandler, HyperAPIError, - HyperAPIModule, - HyperAPIRequest, - HyperAPIRequestArgs, } from '../src/main.js'; import type { HyperAPIMethod } from '../src/utils/methods.js'; -import type { EmptyObject } from '../src/utils/types.js'; interface DriverRequest extends HyperAPIRequest { foo: string; @@ -127,7 +127,7 @@ hyperApi.onModule((request, module) => { } = module; }); -hyperApi.onResponse((request, module) => { +hyperApi.onResponse((request, module, response) => { const { foo, bar, @@ -138,6 +138,8 @@ hyperApi.onResponse((request, module) => { argsValidator, auth, } = module; + + // response; }); /* eslint-enable @typescript-eslint/no-unused-vars */ diff --git a/test/tsconfig.json b/test/tsconfig.json index 4efefea..059d1f5 100644 --- a/test/tsconfig.json +++ b/test/tsconfig.json @@ -1,18 +1,10 @@ { - "compileOnSave": false, + "extends": "../tsconfig.json", "compilerOptions": { - "outDir": "/dev/null", - "declaration": false, - "target": "esnext", - "module": "esnext", - "lib": [ - "ESNext", - "ES2021.String" - ], - "moduleResolution": "node", - "allowSyntheticDefaultImports": true, - "skipLibCheck": true, - "strict": true, - "removeComments": false - } -} + "isolatedDeclarations": false + }, + "include": [ + "./**/*.ts", + "../src/**/*.test.ts" + ] +} \ No newline at end of file diff --git a/tsconfig.json b/tsconfig.json index 83cd553..6efe70c 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -1,28 +1,26 @@ { - "compileOnSave": false, - "include": [ - "src/" - ], - "exclude": [ - "dist/", - "node_modules/", - "test/", - "**/*.test.*" - ], "compilerOptions": { - "outDir": "dist/esm", - "declaration": true, - "declarationDir": "dist/esm", - "target": "esnext", - "module": "nodenext", "esModuleInterop": true, - "allowSyntheticDefaultImports": true, - "lib": [ - "ESNext", - "ES2021.String" - ], "skipLibCheck": true, + "target": "es2022", + "moduleDetection": "force", + "isolatedModules": true, + "verbatimModuleSyntax": true, "strict": true, - "removeComments": false - } -} + "noUncheckedIndexedAccess": true, + "noImplicitOverride": true, + "module": "preserve", + "noEmit": true, + "lib": [ + "es2022" + ], + "declaration": true, + "isolatedDeclarations": true + }, + "include": [ + "src/" + ], + "exclude": [ + "**/*.test.ts" + ] +} \ No newline at end of file From 361a0e89a9307bd5d6bb3145e9683c7c8b9923ef Mon Sep 17 00:00:00 2001 From: Daniil Kirichenko Date: Sat, 24 May 2025 13:39:17 +0200 Subject: [PATCH 31/57] Update package.json --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 127e890..8ced098 100644 --- a/package.json +++ b/package.json @@ -15,7 +15,7 @@ } }, "engines": { - "node": ">=21.0.0" + "node": ">=21" }, "dependencies": { "itty-router": "^5.0.18" From c8d28db654df8adf96449d739c40942d326dc6e5 Mon Sep 17 00:00:00 2001 From: Daniil Kirichenko Date: Sat, 24 May 2025 16:41:16 +0200 Subject: [PATCH 32/57] Update hooks, add README.md --- README.md | 291 ++++++++++++++++++++++++++++++++++++++++++++++++- dist/main.cjs | 69 +++++++++--- dist/main.d.ts | 36 ++++-- dist/main.js | 69 +++++++++--- package.json | 2 +- src/main.ts | 142 ++++++++++++++++-------- test/setup.ts | 42 +++++-- 7 files changed, 546 insertions(+), 105 deletions(-) diff --git a/README.md b/README.md index d1ade38..4564f1e 100644 --- a/README.md +++ b/README.md @@ -1 +1,290 @@ -# @hyperapi/core +# HyperAPI Core + +[![npm version](https://img.shields.io/npm/v/@hyperapi/core.svg)](https://www.npmjs.com/package/@hyperapi/core) +[![License: MIT](https://img.shields.io/badge/License-MIT-blue.svg)](https://opensource.org/licenses/MIT) + +A powerful, type-safe foundation framework for building APIs with minimal boilerplate. HyperAPI Core provides routing, standardized API method modules, validation, and hooks, while leaving the connection to the outside world to be handled by drivers. + +## Features + +- 🔒 **Type-safe API development** - Get full TypeScript support and inference +- 🧩 **File-based routing** - Automatically generate API endpoints from your file structure +- 🚀 **Driver-based architecture** - Easily adapt to different environments (HTTP, WebSockets, etc.) +- 🔍 **Input validation** - Built-in support for request validation +- 🪝 **Middleware hooks** - Extensible system for authentication, logging, and more + +## Installation + +```bash +bun i @hyperapi/core +# with pnpm +pnpm add @hyperapi/core +# with npm +npm install @hyperapi/core +``` + +## Quick Start + +> **NOTE:** HyperAPI Core by itself cannot create a server. You must use a driver package to connect with the outside world. HyperAPI can work with any protocol through its driver system: HTTP, WebSocket, [TASQ](https://github.com/kirick-ts/tasq), [IPC](https://github.com/hyperapi/driver-ipc), or any custom protocol you create a driver for. + +### 1. Set up your API structure + +Create a directory to hold your API methods (default: `hyper-api` in your project root): + +``` +my-project/ +├── hyper-api/ +│ ├── users.[get].ts +│ ├── users.[post].ts +│ └── products/ +│ ├── [id].[get].ts +│ └── search.[get].ts +├── index.ts +└── package.json +``` + +HyperAPI uses file names to determine routes and HTTP methods: + +- `users.ts` → `GET /users` +- `users.[post].ts` → `POST /users` +- `users/[id].ts` → `GET /users/:id` +- `users/[id].[delete].ts` → `DELETE /users/:id` + +### 2. Create your API handlers + +Example of a basic endpoint (`hyper-api/hello.[get].ts`): + +```typescript +import type { HyperAPIRequest, HyperAPIResponse } from '@hyperapi/core'; +import * as v from 'valibot'; + +// Define your handler function +export default function(request: HyperAPIRequest>): HyperAPIResponse { + return { + message: `Hello, ${request.args.name}!`, + timestamp: new Date().toISOString() + }; +} + +// Define input validation +export const argsValidator = v.parser( + v.strictObject({ + name: v.string('Name is required'), + }) +); +``` + +### 3. Initialize HyperAPI + +```typescript +import { HyperAPI } from '@hyperapi/core'; +import { SomeHttpDriver } from '@hyperapi/some-http-driver'; // functional driver + +// Create a driver instance +const driver = new SomeHttpDriver({ port: 3000 }); + +// Initialize HyperAPI with the driver +const api = new HyperAPI({ + driver, + // Optional: custom root path for API methods + // root: path.join(import.meta.dir, 'api') +}); + +// Add middleware hooks +api.onBeforeRouter((driver_request) => { + console.log(`Incoming request: ${driver_request.method} ${driver_request.path}`); +}); + +api.setTransformer((driver_request, module) => { + return { + ...driver_request, + user: getCurrentUser(driver_request), + startTime: Date.now() + }; +}); + +api.onBeforeExecute((request, module) => { + // Auth check right before execution + if (module.auth && !isAuthenticated(request)) { + throw new UnauthorizedError(); + } +}); + +api.onResponse((driver_request, request, module, response) => { + if (request) { + console.log(`Completed: ${request.method} ${request.path}`); + } +}); + +console.log('API server running on http://localhost:3000'); +``` + +## Request Pipeline + +HyperAPI Core processes requests through a well-defined sequence of steps: + +1. *Driver* creates a [request](src/request.ts#L6) and passes it to the *Core* +2. *Core* executes all registered `onBeforeRouter` hooks with request it received from the *Driver* +3. *Core* uses a file router to match the request path and method to a module file + - If no match is found, a [`HyperAPIUnknownMethodError`](src/api-errors.ts#L30) is thrown +4. *Core* merges arguments received from the driver with arguments extracted from the request path by the file router +5. *Core* imports the matched module file dynamically +6. If `argsValidator` is defined, *Core* calls it to validate the request arguments. Returned value is set as new request arguments value + - If `argsValidator` throws, a [`HyperAPIInvalidParametersError`](src/api-errors.ts#L12) is thrown +7. *Core* calls registered `setRequestTransformer` hook to update request with developer-defined transformations. + - This is a single point where developer can modify the request *type-safely* before it reaches the module +8. *Core* executes all registered `onModule` hooks with request and module +9. *Core* calls the module's `export default function` with the request object +10. *Core* executes all registered `onResponse` hooks with request it received from the *Driver*, modified request, module, and response received from the module +11. Finally, *Core* passes the response back to the *Driver*, which sends it to the client. + +If an error occurs at any steps from 2 to 9, the pipeline short-circuits to the step 10. Before executing step 10, *Core* sets [`HyperAPIInternalError`](src/api-errors.ts#L18) as a response, if error occurred before is not instance of `HyperAPIError`. + +## Input Validation + +HyperAPI has built-in support for input validation using libraries like [valibot](https://github.com/fabian-hiller/valibot): + +```typescript +import * as v from 'valibot'; + +export const argsValidator = v.parser( + v.strictObject({ + id: v.number('ID must be a number'), + email: v.string([v.email('Invalid email format')]), + tags: v.optional(v.array(v.string())), + }) +); +``` + +In general, you define `argsValidator` function that throws if validation fails and returns a valid object if the input is correct. But validation library is your choice. + +## Hooks and Middleware + +HyperAPI provides several hooks for extending functionality at different stages of the request pipeline: + +### Process request before routing + +Executed after path normalization but before route matching. Use for logging, request inspection, or early validation. + +```typescript +api.onBeforeRouter((driver_request) => { + console.log(`Incoming request: ${driver_request.method} ${driver_request.path}`); + + // Verify request integrity, implement rate limiting, etc. + if (isRateLimited(driver_request)) { + throw new HyperAPIRateLimitError(); + } +}); +``` + +### Transform request with module context + +Executed after module loading and argument validation, but before module execution. Can access both driver request and module. + +> [!TIP] +> This is the only hook that can change the request type, allowing you to add custom properties or modify existing ones. +> +> For example, if module exports `auth = true` property, you can validate token and add user information to the request object. + +```typescript +api.setRequestTransformer((driver_request, module) => { + return { + ...driver_request, + user: module.auth + ? getCurrentUser(driver_request) + : null, + }; +}); +``` + +### Execute code before module function + +Last hook before the module's default export function runs. + +```typescript +api.onBeforeExecute((request, module) => { + // Runs after transformation, with the final request object + // Perfect for authorization checks based on both request and module + if (module.auth && !isAuthorized(request, module.auth)) { + throw new HyperAPIUnauthorizedError(); + } +}); +``` + +### Process response before delivery + +Final hook executed before returning response to driver. Receives all context from the request lifecycle. + +This hook has access to both the original driver request and the transformed request. Also, errors thrown from this hook will not change the response. + +```typescript +api.onResponse((driver_request, request, module, response) => { + // Has access to both original driver request and transformed request + // Useful for metrics, logging, and response modification + if (request) { + const duration = Date.now() - request.startTime; + console.log(`${request.method} ${request.path} completed in ${duration}ms`); + } +}); +``` + +## Error Handling + +HyperAPI provides built-in error type [`HyperAPIError`](src/error.ts) for standardized error handling. If you want to return an error from your module, you can throw an instance of `HyperAPIError` or its subclasses. This will automatically convert it to a proper response by the driver. + +```typescript +import { HyperAPIError } from '@hyperapi/core'; + +// for example, you create custom error for limiting access to some API methods +class HyperAPIAccessDeniedError extends HyperAPIError { + // mandatory: specify numeric API code greater than 100 + override code = 101; + // mandatory: specify text description + override description = 'Access to this API method is denied'; + // optional: specify object with additional information to return + override data: { foo: 'bar' }; + // optional: specify HTTP status code + override httpStatus = 403; // Forbidden + // optional: specify HTTP headers + override httpHeaders = { + 'X-Access-Denied': '1', + }; +} +``` + +Now you can throw this error from your module or hooks. Drivers will automatically convert it to a proper response based on their protocols. + +HyperAPI provides several [built-in error classes](src/api-errors.ts) for common scenarios like unauthorized access, invalid parameters, and internal errors. You can import them right from the package. + +## Custom Drivers + +HyperAPI is designed to work with any transport layer or protocol through drivers. This separation of concerns allows you to implement your API once and use it across multiple protocols without changing your business logic. + +## TypeScript Support + +HyperAPI is built with TypeScript and provides excellent type inference: + +```typescript +// Define custom request type +interface MyRequest extends HyperAPIRequest { + user: { + id: string; + roles: string[]; + } +} + +// Define custom module interface +interface MyModule extends HyperAPIModule { + auth: boolean; + roles?: string[]; +} + +// Initialize with type parameters +const api = new HyperAPI< + typeof myDriver, + MyRequest, + MyModule +>({ + driver: myDriver +}); +``` diff --git a/dist/main.cjs b/dist/main.cjs index 4fa6254..0284cfa 100644 --- a/dist/main.cjs +++ b/dist/main.cjs @@ -241,10 +241,16 @@ var HyperAPI = class { constructor({ driver, root = node_path.default.join(ENTRYPOINT_PATH, "hyper-api") }) { this.driver = driver; this.router = createRouter(root); - this.driver.start(async (driver_request) => { + this.driver.start(async (arg0) => { + const driver_request = arg0; const [request, module_, response] = await this.processRequest(driver_request); - if (request && module_) for (const hook of this.handlers.response) try { - await hook(request, module_, response); + try { + await this.useHooks(this.handlers.response, [ + driver_request, + request, + module_, + response + ]); } catch (error) { console.error("Error in \"response\" hook:"); console.error(error); @@ -253,56 +259,82 @@ var HyperAPI = class { }); } handlers = { - transformer: void 0, - module: [], + beforeRouter: [], + requestTransformer: void 0, + beforeExecute: [], response: [] }; /** + * Adds a hook to be called before request is matched against the file router. + * + * This hook can be set multiple times. Every hook is executed simultaneously. + * + * If error is thrown in this hook, it will abort the request processing and return an error response. + * @param callback The callback function. + */ + onBeforeRouter(callback) { + this.handlers.beforeRouter.push(callback); + } + /** * Use this hook add properties to the request before it is send to the API module. * * This hook can be set only once. + * + * If error is thrown in this hook, it will abort the request processing and return an error response. * @param transformer The callback function. */ - setTransformer(transformer) { - if (this.handlers.transformer) throw new Error("Transformer has already been set."); - this.handlers.transformer = transformer; + setRequestTransformer(transformer) { + if (this.handlers.requestTransformer) throw new Error("Transformer has already been set."); + this.handlers.requestTransformer = transformer; } /** - * Adds a hook to be called when the API module is imported. + * Adds a hook to be called right before the API module is executed. + * + * This hook can be set multiple times. Every hook is executed simultaneously. + * + * If error is thrown in this hook, it will abort the request processing and return an error response. * @param callback - */ - onModule(callback) { - this.handlers.module.push(callback); + onBeforeExecute(callback) { + this.handlers.beforeExecute.push(callback); } /** - * Adds a hook to be called right before the response is sent back. + * Adds a hook to be called right before the response is sent back to the driver. * - * This hook called only if the request was processed by the API module. If unknown method was requested, this hook is not called. + * This hook can be set multiple times. Every hook is executed simultaneously. + * + * If error is thrown in this hook, it will be printed to the console, but will not prevent response from being sent to the driver. * @param callback - */ onResponse(callback) { this.handlers.response.push(callback); } + async useHooks(hooks, args) { + const promises = []; + for (const hook of hooks) promises.push(hook(...args)); + await Promise.all(promises); + } async processRequest(driver_request) { let request = null; let module_ = null; try { if (driver_request.path.startsWith("/") !== true) driver_request.path = `/${driver_request.path}`; + await this.useHooks(this.handlers.beforeRouter, [driver_request]); const router_response = await useRouter(this.router, driver_request.method, driver_request.path); if (!router_response) throw new HyperAPIUnknownMethodError(); driver_request.args = { ...driver_request.args, ...router_response.args }; - request = this.handlers.transformer ? await this.handlers.transformer(driver_request) : driver_request; module_ = await import(router_response.module_path); if (module_.argsValidator) try { - request.args = module_.argsValidator(request.args); + driver_request.args = module_.argsValidator(driver_request.args); } catch (error) { console.error(error); throw new HyperAPIInvalidParametersError(); } - for (const hook of this.handlers.module) await hook(request, module_); + request = this.handlers.requestTransformer ? await this.handlers.requestTransformer(driver_request, module_) : driver_request; + await this.useHooks(this.handlers.beforeExecute, [request, module_]); const response = await module_.default(request); return [ request, @@ -325,8 +357,9 @@ var HyperAPI = class { } /** Destroys the HyperAPI instance. */ destroy() { - this.handlers.transformer = void 0; - this.handlers.module.splice(0); + this.handlers.beforeRouter.splice(0); + this.handlers.requestTransformer = void 0; + this.handlers.beforeExecute.splice(0); this.handlers.response.splice(0); } }; diff --git a/dist/main.d.ts b/dist/main.d.ts index 1a8ddef..73fddd6 100644 --- a/dist/main.d.ts +++ b/dist/main.d.ts @@ -142,9 +142,10 @@ declare class HyperAPIMethodNotAllowedError extends //#endregion //#region src/main.d.ts interface HyperAPIHandlers, M extends HyperAPIModule> { - transformer: ((driver_request: Readonly>) => Promisable) | void; - module: ((request: Readonly, module_: M) => Promisable)[]; - response: ((request: R, module_: M, response: HyperAPIResponse) => Promisable)[]; + beforeRouter: ((driver_request: Readonly>) => Promisable)[]; + requestTransformer: ((driver_request: Readonly>, module_: M) => Promisable) | void; + beforeExecute: ((request: Readonly, module_: M) => Promisable)[]; + response: ((driver_request: Readonly>, request: R | null, module_: M | null, response: HyperAPIResponse) => Promisable)[]; } declare class HyperAPI, R extends InferDriverRequest, M extends HyperAPIModule = HyperAPIModule> { private router; @@ -164,24 +165,43 @@ declare class HyperAPI, R extends Infe }); private handlers; /** + * Adds a hook to be called before request is matched against the file router. + * + * This hook can be set multiple times. Every hook is executed simultaneously. + * + * If error is thrown in this hook, it will abort the request processing and return an error response. + * @param callback The callback function. + */ + onBeforeRouter(callback: HyperAPIHandlers["beforeRouter"][number]): void; + /** * Use this hook add properties to the request before it is send to the API module. * * This hook can be set only once. + * + * If error is thrown in this hook, it will abort the request processing and return an error response. * @param transformer The callback function. */ - setTransformer(transformer: HyperAPIHandlers["transformer"]): void; + setRequestTransformer(transformer: HyperAPIHandlers["requestTransformer"]): void; /** - * Adds a hook to be called when the API module is imported. + * Adds a hook to be called right before the API module is executed. + * + * This hook can be set multiple times. Every hook is executed simultaneously. + * + * If error is thrown in this hook, it will abort the request processing and return an error response. * @param callback - */ - onModule(callback: HyperAPIHandlers["module"][number]): void; + onBeforeExecute(callback: HyperAPIHandlers["beforeExecute"][number]): void; /** - * Adds a hook to be called right before the response is sent back. + * Adds a hook to be called right before the response is sent back to the driver. + * + * This hook can be set multiple times. Every hook is executed simultaneously. * - * This hook called only if the request was processed by the API module. If unknown method was requested, this hook is not called. + * If error is thrown in this hook, it will be printed to the console, but will not prevent response from being sent to the driver. * @param callback - */ onResponse(callback: HyperAPIHandlers["response"][number]): void; + // eslint-disable-next-line class-methods-use-this, @typescript-eslint/no-explicit-any + private useHooks; private processRequest; /** Destroys the HyperAPI instance. */ destroy(): void; diff --git a/dist/main.js b/dist/main.js index a210ccc..99c5173 100644 --- a/dist/main.js +++ b/dist/main.js @@ -218,10 +218,16 @@ var HyperAPI = class { constructor({ driver, root = nodePath.join(ENTRYPOINT_PATH, "hyper-api") }) { this.driver = driver; this.router = createRouter(root); - this.driver.start(async (driver_request) => { + this.driver.start(async (arg0) => { + const driver_request = arg0; const [request, module_, response] = await this.processRequest(driver_request); - if (request && module_) for (const hook of this.handlers.response) try { - await hook(request, module_, response); + try { + await this.useHooks(this.handlers.response, [ + driver_request, + request, + module_, + response + ]); } catch (error) { console.error("Error in \"response\" hook:"); console.error(error); @@ -230,56 +236,82 @@ var HyperAPI = class { }); } handlers = { - transformer: void 0, - module: [], + beforeRouter: [], + requestTransformer: void 0, + beforeExecute: [], response: [] }; /** + * Adds a hook to be called before request is matched against the file router. + * + * This hook can be set multiple times. Every hook is executed simultaneously. + * + * If error is thrown in this hook, it will abort the request processing and return an error response. + * @param callback The callback function. + */ + onBeforeRouter(callback) { + this.handlers.beforeRouter.push(callback); + } + /** * Use this hook add properties to the request before it is send to the API module. * * This hook can be set only once. + * + * If error is thrown in this hook, it will abort the request processing and return an error response. * @param transformer The callback function. */ - setTransformer(transformer) { - if (this.handlers.transformer) throw new Error("Transformer has already been set."); - this.handlers.transformer = transformer; + setRequestTransformer(transformer) { + if (this.handlers.requestTransformer) throw new Error("Transformer has already been set."); + this.handlers.requestTransformer = transformer; } /** - * Adds a hook to be called when the API module is imported. + * Adds a hook to be called right before the API module is executed. + * + * This hook can be set multiple times. Every hook is executed simultaneously. + * + * If error is thrown in this hook, it will abort the request processing and return an error response. * @param callback - */ - onModule(callback) { - this.handlers.module.push(callback); + onBeforeExecute(callback) { + this.handlers.beforeExecute.push(callback); } /** - * Adds a hook to be called right before the response is sent back. + * Adds a hook to be called right before the response is sent back to the driver. * - * This hook called only if the request was processed by the API module. If unknown method was requested, this hook is not called. + * This hook can be set multiple times. Every hook is executed simultaneously. + * + * If error is thrown in this hook, it will be printed to the console, but will not prevent response from being sent to the driver. * @param callback - */ onResponse(callback) { this.handlers.response.push(callback); } + async useHooks(hooks, args) { + const promises = []; + for (const hook of hooks) promises.push(hook(...args)); + await Promise.all(promises); + } async processRequest(driver_request) { let request = null; let module_ = null; try { if (driver_request.path.startsWith("/") !== true) driver_request.path = `/${driver_request.path}`; + await this.useHooks(this.handlers.beforeRouter, [driver_request]); const router_response = await useRouter(this.router, driver_request.method, driver_request.path); if (!router_response) throw new HyperAPIUnknownMethodError(); driver_request.args = { ...driver_request.args, ...router_response.args }; - request = this.handlers.transformer ? await this.handlers.transformer(driver_request) : driver_request; module_ = await import(router_response.module_path); if (module_.argsValidator) try { - request.args = module_.argsValidator(request.args); + driver_request.args = module_.argsValidator(driver_request.args); } catch (error) { console.error(error); throw new HyperAPIInvalidParametersError(); } - for (const hook of this.handlers.module) await hook(request, module_); + request = this.handlers.requestTransformer ? await this.handlers.requestTransformer(driver_request, module_) : driver_request; + await this.useHooks(this.handlers.beforeExecute, [request, module_]); const response = await module_.default(request); return [ request, @@ -302,8 +334,9 @@ var HyperAPI = class { } /** Destroys the HyperAPI instance. */ destroy() { - this.handlers.transformer = void 0; - this.handlers.module.splice(0); + this.handlers.beforeRouter.splice(0); + this.handlers.requestTransformer = void 0; + this.handlers.beforeExecute.splice(0); this.handlers.response.splice(0); } }; diff --git a/package.json b/package.json index 8ced098..9a4d30e 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@hyperapi/core", - "version": "0.3.0-dev", + "version": "0.4.0-dev", "description": "Core package of the HyperAPI project.", "publishConfig": { "access": "public" diff --git a/src/main.ts b/src/main.ts index 2b1be11..ea5f73c 100644 --- a/src/main.ts +++ b/src/main.ts @@ -23,9 +23,10 @@ interface HyperAPIHandlers< R extends InferDriverRequest, M extends HyperAPIModule, > { - transformer: ((driver_request: Readonly>) => Promisable) | void; - module: ((request: Readonly, module_: M) => Promisable)[]; - response: ((request: R, module_: M, response: HyperAPIResponse) => Promisable)[]; + beforeRouter: ((driver_request: Readonly>) => Promisable)[]; + requestTransformer: ((driver_request: Readonly>, module_: M) => Promisable) | void; + beforeExecute: ((request: Readonly, module_: M) => Promisable)[]; + response: ((driver_request: Readonly>, request: R | null, module_: M | null, response: HyperAPIResponse) => Promisable)[]; } const ENTRYPOINT_PATH = nodePath.dirname(process.argv[1]!); @@ -54,71 +55,111 @@ export class HyperAPI< this.driver = driver; this.router = createRouter(root); - this.driver.start(async (driver_request) => { + this.driver.start(async (arg0) => { + const driver_request = arg0 as InferDriverRequest; + const [ request, module_, response, - ] = await this.processRequest(driver_request as InferDriverRequest); - - if (request && module_) { - for (const hook of this.handlers.response) { - try { - // eslint-disable-next-line no-await-in-loop - await hook(request, module_, response); - } - catch (error) { - /* eslint-disable no-console */ - console.error('Error in "response" hook:'); - console.error(error); - /* eslint-enable no-console */ - } - } + ] = await this.processRequest(driver_request); + + // 10. *Core* executes all registered `onResponse` hooks... + try { + await this.useHooks( + this.handlers.response, + [ + driver_request, + request, + module_, + response, + ], + ); + } + catch (error) { + /* eslint-disable no-console */ + console.error('Error in "response" hook:'); + console.error(error); + /* eslint-enable no-console */ } + // 11. Finally, *Core* passes the response back to the *Driver*... return response; }); } private handlers: HyperAPIHandlers = { - transformer: undefined, - module: [], + beforeRouter: [], + requestTransformer: undefined, + beforeExecute: [], response: [], }; + /** + * Adds a hook to be called before request is matched against the file router. + * + * This hook can be set multiple times. Every hook is executed simultaneously. + * + * If error is thrown in this hook, it will abort the request processing and return an error response. + * @param callback The callback function. + */ + onBeforeRouter(callback: HyperAPIHandlers['beforeRouter'][number]): void { + this.handlers.beforeRouter.push(callback); + } + /** * Use this hook add properties to the request before it is send to the API module. * * This hook can be set only once. + * + * If error is thrown in this hook, it will abort the request processing and return an error response. * @param transformer The callback function. */ - setTransformer(transformer: HyperAPIHandlers['transformer']): void { - if (this.handlers.transformer) { + setRequestTransformer(transformer: HyperAPIHandlers['requestTransformer']): void { + if (this.handlers.requestTransformer) { throw new Error('Transformer has already been set.'); } - this.handlers.transformer = transformer; + this.handlers.requestTransformer = transformer; } /** - * Adds a hook to be called when the API module is imported. + * Adds a hook to be called right before the API module is executed. + * + * This hook can be set multiple times. Every hook is executed simultaneously. + * + * If error is thrown in this hook, it will abort the request processing and return an error response. * @param callback - */ - onModule(callback: HyperAPIHandlers['module'][number]): void { - this.handlers.module.push(callback); + onBeforeExecute(callback: HyperAPIHandlers['beforeExecute'][number]): void { + this.handlers.beforeExecute.push(callback); } /** - * Adds a hook to be called right before the response is sent back. + * Adds a hook to be called right before the response is sent back to the driver. + * + * This hook can be set multiple times. Every hook is executed simultaneously. * - * This hook called only if the request was processed by the API module. If unknown method was requested, this hook is not called. + * If error is thrown in this hook, it will be printed to the console, but will not prevent response from being sent to the driver. * @param callback - */ onResponse(callback: HyperAPIHandlers['response'][number]): void { this.handlers.response.push(callback); } + // eslint-disable-next-line class-methods-use-this, @typescript-eslint/no-explicit-any + private async useHooks void>(hooks: H[], args: Parameters) { + const promises: Promisable[] = []; + for (const hook of hooks) { + promises.push(hook(...args)); + } + + await Promise.all(promises); + } + private async processRequest(driver_request: InferDriverRequest): Promise<[ R | null, M | null, HyperAPIResponse ]> { + // 1. *Driver* creates a request and passes it to the *Core* + let request: R | null = null; let module_: M | null = null; @@ -127,33 +168,36 @@ export class HyperAPI< driver_request.path = `/${driver_request.path}`; } + // 2. *Core* executes all registered `onBeforeRouter` hooks... + await this.useHooks( + this.handlers.beforeRouter, + [ driver_request ], + ); + + // 3. *Core* uses a file router... const router_response = await useRouter( this.router, driver_request.method, driver_request.path, ); - if (!router_response) { // TODO throw HyperAPIMethodNotAllowedError when path exists but HTTP method does not match throw new HyperAPIUnknownMethodError(); } + // 4. *Core* merges arguments received from the driver with arguments extracted from the request path by the file router driver_request.args = { ...driver_request.args, ...router_response.args, }; - // Send request to the outside user - request = this.handlers.transformer - ? await this.handlers.transformer(driver_request) - : driver_request as R; - - // IDEA: "onBeforeModule" hook? - + // 5. *Core* imports the matched module file... module_ = (await import(router_response.module_path)) as M; + + // 6. If `argsValidator` is defined, *Core* calls it to validate the request arguments... if (module_.argsValidator) { try { - request.args = module_.argsValidator(request.args); + driver_request.args = module_.argsValidator(driver_request.args); } catch (error) { // eslint-disable-next-line no-console @@ -163,17 +207,20 @@ export class HyperAPI< } } - for (const hook of this.handlers.module) { - // eslint-disable-next-line no-await-in-loop - await hook(request, module_); - } + // 7. *Core* calls registered `setRequestTransformer` hook + request = this.handlers.requestTransformer + ? await this.handlers.requestTransformer(driver_request, module_) + : driver_request as R; - // IDEA: "onBeforeExecute" hook? + // 8. *Core* executes all registered `onBeforeExecute` hooks... + await this.useHooks( + this.handlers.beforeExecute, + [ request, module_ ], + ); + // 9. *Core* calls the module's `export default function`... const response = await module_.default(request); - // IDEA: "onExecute" hook? - return [ request, module_, @@ -202,8 +249,9 @@ export class HyperAPI< /** Destroys the HyperAPI instance. */ destroy(): void { - this.handlers.transformer = undefined; - this.handlers.module.splice(0); + this.handlers.beforeRouter.splice(0); + this.handlers.requestTransformer = undefined; + this.handlers.beforeExecute.splice(0); this.handlers.response.splice(0); } } diff --git a/test/setup.ts b/test/setup.ts index ac76f07..0ed1e80 100644 --- a/test/setup.ts +++ b/test/setup.ts @@ -101,20 +101,28 @@ export const hyperApi = new HyperAPI< /* eslint-disable @typescript-eslint/no-unused-vars */ -hyperApi.setTransformer((request) => { +hyperApi.onBeforeRouter((driver_request) => { const { foo, // @ts-expect-error Accessing property that does not exist on DriverRequest bar, - } = request; + } = driver_request; +}); + +hyperApi.setRequestTransformer((driver_request) => { + const { + foo, + // @ts-expect-error Accessing property that does not exist on DriverRequest + bar, + } = driver_request; return { - ...request, + ...driver_request, bar: 10, }; }); -hyperApi.onModule((request, module) => { +hyperApi.onBeforeExecute((request, module) => { const { foo, bar, @@ -127,19 +135,29 @@ hyperApi.onModule((request, module) => { } = module; }); -hyperApi.onResponse((request, module, response) => { +hyperApi.onResponse((driver_request, request, module, response) => { const { foo, + // @ts-expect-error Accessing property that does not exist on DriverRequest bar, - } = request; + } = driver_request; - const { - default: default_, - argsValidator, - auth, - } = module; + if (request) { + const { + foo, + bar, + } = request; + } + + if (module) { + const { + default: default_, + argsValidator, + auth, + } = module; + } - // response; + console.log(response); }); /* eslint-enable @typescript-eslint/no-unused-vars */ From 694e007fc8868c8bd87a58942dc89a771925a0ed Mon Sep 17 00:00:00 2001 From: Daniil Kirichenko Date: Sat, 24 May 2025 16:42:39 +0200 Subject: [PATCH 33/57] Update README.md --- README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 4564f1e..deac6cd 100644 --- a/README.md +++ b/README.md @@ -25,7 +25,7 @@ npm install @hyperapi/core ## Quick Start -> **NOTE:** HyperAPI Core by itself cannot create a server. You must use a driver package to connect with the outside world. HyperAPI can work with any protocol through its driver system: HTTP, WebSocket, [TASQ](https://github.com/kirick-ts/tasq), [IPC](https://github.com/hyperapi/driver-ipc), or any custom protocol you create a driver for. +> **NOTE:** HyperAPI Core by itself cannot create a server. You must use a driver package to connect with the outside world. HyperAPI can work with any protocol through its driver system: HTTP, WebSocket, [tasq](https://github.com/kirick-ts/tasq), [IPC](https://github.com/hyperapi/driver-ipc), or any custom protocol you create a driver for. ### 1. Set up your API structure @@ -133,7 +133,7 @@ HyperAPI Core processes requests through a well-defined sequence of steps: - If `argsValidator` throws, a [`HyperAPIInvalidParametersError`](src/api-errors.ts#L12) is thrown 7. *Core* calls registered `setRequestTransformer` hook to update request with developer-defined transformations. - This is a single point where developer can modify the request *type-safely* before it reaches the module -8. *Core* executes all registered `onModule` hooks with request and module +8. *Core* executes all registered `onBeforeExecute` hooks with request and module 9. *Core* calls the module's `export default function` with the request object 10. *Core* executes all registered `onResponse` hooks with request it received from the *Driver*, modified request, module, and response received from the module 11. Finally, *Core* passes the response back to the *Driver*, which sends it to the client. From 4b243d75fc2fc7bd6f4318b727d08cd39abeac9b Mon Sep 17 00:00:00 2001 From: Daniil Kirichenko Date: Sat, 24 May 2025 17:00:13 +0200 Subject: [PATCH 34/57] Update README.md --- README.md | 38 ++++++-------------------------------- 1 file changed, 6 insertions(+), 32 deletions(-) diff --git a/README.md b/README.md index deac6cd..30864be 100644 --- a/README.md +++ b/README.md @@ -84,38 +84,12 @@ import { SomeHttpDriver } from '@hyperapi/some-http-driver'; // functional drive const driver = new SomeHttpDriver({ port: 3000 }); // Initialize HyperAPI with the driver -const api = new HyperAPI({ +const hyperApiCore = new HyperAPI({ driver, // Optional: custom root path for API methods // root: path.join(import.meta.dir, 'api') }); -// Add middleware hooks -api.onBeforeRouter((driver_request) => { - console.log(`Incoming request: ${driver_request.method} ${driver_request.path}`); -}); - -api.setTransformer((driver_request, module) => { - return { - ...driver_request, - user: getCurrentUser(driver_request), - startTime: Date.now() - }; -}); - -api.onBeforeExecute((request, module) => { - // Auth check right before execution - if (module.auth && !isAuthenticated(request)) { - throw new UnauthorizedError(); - } -}); - -api.onResponse((driver_request, request, module, response) => { - if (request) { - console.log(`Completed: ${request.method} ${request.path}`); - } -}); - console.log('API server running on http://localhost:3000'); ``` @@ -167,7 +141,7 @@ HyperAPI provides several hooks for extending functionality at different stages Executed after path normalization but before route matching. Use for logging, request inspection, or early validation. ```typescript -api.onBeforeRouter((driver_request) => { +hyperApiCore.onBeforeRouter((driver_request) => { console.log(`Incoming request: ${driver_request.method} ${driver_request.path}`); // Verify request integrity, implement rate limiting, etc. @@ -187,7 +161,7 @@ Executed after module loading and argument validation, but before module executi > For example, if module exports `auth = true` property, you can validate token and add user information to the request object. ```typescript -api.setRequestTransformer((driver_request, module) => { +hyperApiCore.setRequestTransformer((driver_request, module) => { return { ...driver_request, user: module.auth @@ -202,7 +176,7 @@ api.setRequestTransformer((driver_request, module) => { Last hook before the module's default export function runs. ```typescript -api.onBeforeExecute((request, module) => { +hyperApiCore.onBeforeExecute((request, module) => { // Runs after transformation, with the final request object // Perfect for authorization checks based on both request and module if (module.auth && !isAuthorized(request, module.auth)) { @@ -218,7 +192,7 @@ Final hook executed before returning response to driver. Receives all context fr This hook has access to both the original driver request and the transformed request. Also, errors thrown from this hook will not change the response. ```typescript -api.onResponse((driver_request, request, module, response) => { +hyperApiCore.onResponse((driver_request, request, module, response) => { // Has access to both original driver request and transformed request // Useful for metrics, logging, and response modification if (request) { @@ -280,7 +254,7 @@ interface MyModule extends HyperAPIModule { } // Initialize with type parameters -const api = new HyperAPI< +const hyperApiCore = new HyperAPI< typeof myDriver, MyRequest, MyModule From 200cfe5c666ee72caad8208a4c954de6cc83de19 Mon Sep 17 00:00:00 2001 From: Daniil Kirichenko Date: Sat, 24 May 2025 17:01:30 +0200 Subject: [PATCH 35/57] Update README.md --- README.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 30864be..2260439 100644 --- a/README.md +++ b/README.md @@ -25,7 +25,8 @@ npm install @hyperapi/core ## Quick Start -> **NOTE:** HyperAPI Core by itself cannot create a server. You must use a driver package to connect with the outside world. HyperAPI can work with any protocol through its driver system: HTTP, WebSocket, [tasq](https://github.com/kirick-ts/tasq), [IPC](https://github.com/hyperapi/driver-ipc), or any custom protocol you create a driver for. +> [!NOTE] +> HyperAPI Core by itself cannot serve requests: you must use a driver package to connect with the outside world. HyperAPI can work with any protocol through its driver system: HTTP, WebSocket, [tasq](https://github.com/kirick-ts/tasq), [IPC](https://github.com/hyperapi/driver-ipc), or any custom protocol you create a driver for. ### 1. Set up your API structure From 3cc8a2a0c488414a8105ded5201235e4da8ec181 Mon Sep 17 00:00:00 2001 From: Daniil Kirichenko Date: Sun, 25 May 2025 00:48:38 +0200 Subject: [PATCH 36/57] Update README.md --- README.md | 25 +++++++++++++------------ 1 file changed, 13 insertions(+), 12 deletions(-) diff --git a/README.md b/README.md index 2260439..daecbc9 100644 --- a/README.md +++ b/README.md @@ -1,7 +1,7 @@ # HyperAPI Core [![npm version](https://img.shields.io/npm/v/@hyperapi/core.svg)](https://www.npmjs.com/package/@hyperapi/core) -[![License: MIT](https://img.shields.io/badge/License-MIT-blue.svg)](https://opensource.org/licenses/MIT) +[![license](https://img.shields.io/npm/l/@hyperapi/core.svg)](https://github.com/hyperapi/core/blob/main/LICENSE) A powerful, type-safe foundation framework for building APIs with minimal boilerplate. HyperAPI Core provides routing, standardized API method modules, validation, and hooks, while leaving the connection to the outside world to be handled by drivers. @@ -17,9 +17,9 @@ A powerful, type-safe foundation framework for building APIs with minimal boiler ```bash bun i @hyperapi/core -# with pnpm +# or with pnpm pnpm add @hyperapi/core -# with npm +# or with npm npm install @hyperapi/core ``` @@ -107,7 +107,6 @@ HyperAPI Core processes requests through a well-defined sequence of steps: 6. If `argsValidator` is defined, *Core* calls it to validate the request arguments. Returned value is set as new request arguments value - If `argsValidator` throws, a [`HyperAPIInvalidParametersError`](src/api-errors.ts#L12) is thrown 7. *Core* calls registered `setRequestTransformer` hook to update request with developer-defined transformations. - - This is a single point where developer can modify the request *type-safely* before it reaches the module 8. *Core* executes all registered `onBeforeExecute` hooks with request and module 9. *Core* calls the module's `export default function` with the request object 10. *Core* executes all registered `onResponse` hooks with request it received from the *Driver*, modified request, module, and response received from the module @@ -135,9 +134,9 @@ In general, you define `argsValidator` function that throws if validation fails ## Hooks and Middleware -HyperAPI provides several hooks for extending functionality at different stages of the request pipeline: +HyperAPI provides several hooks for extending functionality at different stages of the request pipeline. Every type of hook executed in parallel, so be careful when changing request object there and avoid race conditions. -### Process request before routing +### `beforeRouter` hook Executed after path normalization but before route matching. Use for logging, request inspection, or early validation. @@ -152,10 +151,12 @@ hyperApiCore.onBeforeRouter((driver_request) => { }); ``` -### Transform request with module context +### `requestTransformer` hook Executed after module loading and argument validation, but before module execution. Can access both driver request and module. +This hook can be set only once. + > [!TIP] > This is the only hook that can change the request type, allowing you to add custom properties or modify existing ones. > @@ -172,9 +173,9 @@ hyperApiCore.setRequestTransformer((driver_request, module) => { }); ``` -### Execute code before module function +### `beforeExecute` hook -Last hook before the module's default export function runs. +Executed before the module's default export function runs. ```typescript hyperApiCore.onBeforeExecute((request, module) => { @@ -186,9 +187,9 @@ hyperApiCore.onBeforeExecute((request, module) => { }); ``` -### Process response before delivery +### `onResponse` hook -Final hook executed before returning response to driver. Receives all context from the request lifecycle. +Executed before returning response to driver. Receives all context from the request lifecycle. This hook has access to both the original driver request and the transformed request. Also, errors thrown from this hook will not change the response. @@ -205,7 +206,7 @@ hyperApiCore.onResponse((driver_request, request, module, response) => { ## Error Handling -HyperAPI provides built-in error type [`HyperAPIError`](src/error.ts) for standardized error handling. If you want to return an error from your module, you can throw an instance of `HyperAPIError` or its subclasses. This will automatically convert it to a proper response by the driver. +HyperAPI provides built-in error type [`HyperAPIError`](src/error.ts) for standardized error handling. If you want to return an error from your module, you can throw an instance of `HyperAPIError` or its subclasses. ```typescript import { HyperAPIError } from '@hyperapi/core'; From 20bbcc398a13ad5e4676db045c0d403de1452a19 Mon Sep 17 00:00:00 2001 From: Daniil Kirichenko Date: Sun, 25 May 2025 00:54:42 +0200 Subject: [PATCH 37/57] Update README.md --- README.md | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index daecbc9..2bdb85e 100644 --- a/README.md +++ b/README.md @@ -1,7 +1,7 @@ # HyperAPI Core [![npm version](https://img.shields.io/npm/v/@hyperapi/core.svg)](https://www.npmjs.com/package/@hyperapi/core) -[![license](https://img.shields.io/npm/l/@hyperapi/core.svg)](https://github.com/hyperapi/core/blob/main/LICENSE) +[![license](https://img.shields.io/npm/l/@hyperapi/core.svg?color=blue)](https://github.com/hyperapi/core/blob/main/LICENSE) A powerful, type-safe foundation framework for building APIs with minimal boilerplate. HyperAPI Core provides routing, standardized API method modules, validation, and hooks, while leaving the connection to the outside world to be handled by drivers. @@ -264,3 +264,7 @@ const hyperApiCore = new HyperAPI< driver: myDriver }); ``` + +## Contributing + +Issues and pull requests are welcome at [our GitHub repository](https://github.com/hyperapi/core). From 30dc86f06f4960f43a17b5cb63b6bd57740ad8be Mon Sep 17 00:00:00 2001 From: Daniil Kirichenko Date: Sun, 25 May 2025 18:14:03 +0200 Subject: [PATCH 38/57] Update README.md, package.json --- README.md | 2 +- bun.lock | 798 +++++++++++++++++++++++++++++++++++++++++++++++++++ bun.lockb | Bin 156451 -> 0 bytes package.json | 1 - 4 files changed, 799 insertions(+), 2 deletions(-) create mode 100644 bun.lock delete mode 100755 bun.lockb diff --git a/README.md b/README.md index 2bdb85e..66ef31f 100644 --- a/README.md +++ b/README.md @@ -26,7 +26,7 @@ npm install @hyperapi/core ## Quick Start > [!NOTE] -> HyperAPI Core by itself cannot serve requests: you must use a driver package to connect with the outside world. HyperAPI can work with any protocol through its driver system: HTTP, WebSocket, [tasq](https://github.com/kirick-ts/tasq), [IPC](https://github.com/hyperapi/driver-ipc), or any custom protocol you create a driver for. +> HyperAPI Core by itself cannot serve requests: you must use a driver package to connect with the outside world. HyperAPI can work with any protocol through its driver system: [HTTP](https://github.com/hyperapi/driver-http-bun), WebSocket, [Tasq](https://github.com/kirick-ts/tasq), [IPC](https://github.com/hyperapi/driver-ipc), or any custom protocol you create a driver for. ### 1. Set up your API structure diff --git a/bun.lock b/bun.lock new file mode 100644 index 0000000..0973ab3 --- /dev/null +++ b/bun.lock @@ -0,0 +1,798 @@ +{ + "lockfileVersion": 1, + "workspaces": { + "": { + "name": "@hyperapi/core", + "dependencies": { + "itty-router": "^5.0.18", + }, + "devDependencies": { + "@kirick/eslint-config": "^0.1.30", + "@types/bun": "^1.2.13", + "eslint": "9.10.0", + "publint": "0.3.12", + "tsdown": "0.12.2", + "type-fest": "^4.41.0", + "typescript": "5.8.3", + "unplugin-unused": "0.5.0", + "valibot": "1.1.0", + "vitest": "3.1.4", + }, + }, + }, + "packages": { + "@babel/code-frame": ["@babel/code-frame@7.24.7", "", { "dependencies": { "@babel/highlight": "^7.24.7", "picocolors": "^1.0.0" } }, "sha512-BcYH1CVJBO9tvyIZ2jVeXgSIMvGZ2FDRvDdOIVQyuklNKSsx+eppDEBq/g47Ayw+RqNFE+URvOShmf+f/qwAlA=="], + + "@babel/generator": ["@babel/generator@7.27.1", "", { "dependencies": { "@babel/parser": "^7.27.1", "@babel/types": "^7.27.1", "@jridgewell/gen-mapping": "^0.3.5", "@jridgewell/trace-mapping": "^0.3.25", "jsesc": "^3.0.2" } }, "sha512-UnJfnIpc/+JO0/+KRVQNGU+y5taA5vCbwN8+azkX6beii/ZF+enZJSOKo11ZSzGJjlNfJHfQtmQT8H+9TXPG2w=="], + + "@babel/helper-string-parser": ["@babel/helper-string-parser@7.27.1", "", {}, "sha512-qMlSxKbpRlAridDExk92nSobyDdpPijUq2DW6oDnUqd0iOGxmQjyqhMIihI9+zv4LPyZdRje2cavWPbCbWm3eA=="], + + "@babel/helper-validator-identifier": ["@babel/helper-validator-identifier@7.24.7", "", {}, "sha512-rR+PBcQ1SMQDDyF6X0wxtG8QyLCgUB0eRAGguqRLfkCA87l7yAP7ehq8SNj96OOGTO8OBV70KhuFYcIkHXOg0w=="], + + "@babel/highlight": ["@babel/highlight@7.24.7", "", { "dependencies": { "@babel/helper-validator-identifier": "^7.24.7", "chalk": "^2.4.2", "js-tokens": "^4.0.0", "picocolors": "^1.0.0" } }, "sha512-EStJpq4OuY8xYfhGVXngigBJRWxftKX9ksiGDnmlY3o7B/V7KIAc9X4oiK87uPJSc/vs5L869bem5fhZa8caZw=="], + + "@babel/parser": ["@babel/parser@7.27.2", "", { "dependencies": { "@babel/types": "^7.27.1" }, "bin": "./bin/babel-parser.js" }, "sha512-QYLs8299NA7WM/bZAdp+CviYYkVoYXlDW2rzliy3chxd1PQjej7JORuMJDJXJUb9g0TT+B99EwaVLKmX+sPXWw=="], + + "@babel/types": ["@babel/types@7.27.1", "", { "dependencies": { "@babel/helper-string-parser": "^7.27.1", "@babel/helper-validator-identifier": "^7.27.1" } }, "sha512-+EzkxvLNfiUeKMgy/3luqfsCWFRXLb7U6wNQTk60tovuckwB15B191tJWvpp4HjiQWdJkCxO3Wbvc6jlk3Xb2Q=="], + + "@emnapi/core": ["@emnapi/core@1.4.3", "", { "dependencies": { "@emnapi/wasi-threads": "1.0.2", "tslib": "^2.4.0" } }, "sha512-4m62DuCE07lw01soJwPiBGC0nAww0Q+RY70VZ+n49yDIO13yyinhbWCeNnaob0lakDtWQzSdtNWzJeOJt2ma+g=="], + + "@emnapi/runtime": ["@emnapi/runtime@1.4.3", "", { "dependencies": { "tslib": "^2.4.0" } }, "sha512-pBPWdu6MLKROBX05wSNKcNb++m5Er+KQ9QkB+WVM+pW2Kx9hoSrVTnu3BdkI5eBLZoKu/J6mW/B6i6bJB2ytXQ=="], + + "@emnapi/wasi-threads": ["@emnapi/wasi-threads@1.0.2", "", { "dependencies": { "tslib": "^2.4.0" } }, "sha512-5n3nTJblwRi8LlXkJ9eBzu+kZR8Yxcc7ubakyQTFzPMtIhFpUBRbsnc2Dv88IZDIbCDlBiWrknhB4Lsz7mg6BA=="], + + "@es-joy/jsdoccomment": ["@es-joy/jsdoccomment@0.46.0", "", { "dependencies": { "comment-parser": "1.4.1", "esquery": "^1.6.0", "jsdoc-type-pratt-parser": "~4.0.0" } }, "sha512-C3Axuq1xd/9VqFZpW4YAzOx5O9q/LP46uIQy/iNDpHG3fmPa6TBtvfglMCs3RBiBxAIi0Go97r8+jvTt55XMyQ=="], + + "@esbuild/aix-ppc64": ["@esbuild/aix-ppc64@0.21.5", "", { "os": "aix", "cpu": "ppc64" }, "sha512-1SDgH6ZSPTlggy1yI6+Dbkiz8xzpHJEVAlF/AM1tHPLsf5STom9rwtjE4hKAF20FfXXNTFqEYXyJNWh1GiZedQ=="], + + "@esbuild/android-arm": ["@esbuild/android-arm@0.21.5", "", { "os": "android", "cpu": "arm" }, "sha512-vCPvzSjpPHEi1siZdlvAlsPxXl7WbOVUBBAowWug4rJHb68Ox8KualB+1ocNvT5fjv6wpkX6o/iEpbDrf68zcg=="], + + "@esbuild/android-arm64": ["@esbuild/android-arm64@0.21.5", "", { "os": "android", "cpu": "arm64" }, "sha512-c0uX9VAUBQ7dTDCjq+wdyGLowMdtR/GoC2U5IYk/7D1H1JYC0qseD7+11iMP2mRLN9RcCMRcjC4YMclCzGwS/A=="], + + "@esbuild/android-x64": ["@esbuild/android-x64@0.21.5", "", { "os": "android", "cpu": "x64" }, "sha512-D7aPRUUNHRBwHxzxRvp856rjUHRFW1SdQATKXH2hqA0kAZb1hKmi02OpYRacl0TxIGz/ZmXWlbZgjwWYaCakTA=="], + + "@esbuild/darwin-arm64": ["@esbuild/darwin-arm64@0.21.5", "", { "os": "darwin", "cpu": "arm64" }, "sha512-DwqXqZyuk5AiWWf3UfLiRDJ5EDd49zg6O9wclZ7kUMv2WRFr4HKjXp/5t8JZ11QbQfUS6/cRCKGwYhtNAY88kQ=="], + + "@esbuild/darwin-x64": ["@esbuild/darwin-x64@0.21.5", "", { "os": "darwin", "cpu": "x64" }, "sha512-se/JjF8NlmKVG4kNIuyWMV/22ZaerB+qaSi5MdrXtd6R08kvs2qCN4C09miupktDitvh8jRFflwGFBQcxZRjbw=="], + + "@esbuild/freebsd-arm64": ["@esbuild/freebsd-arm64@0.21.5", "", { "os": "freebsd", "cpu": "arm64" }, "sha512-5JcRxxRDUJLX8JXp/wcBCy3pENnCgBR9bN6JsY4OmhfUtIHe3ZW0mawA7+RDAcMLrMIZaf03NlQiX9DGyB8h4g=="], + + "@esbuild/freebsd-x64": ["@esbuild/freebsd-x64@0.21.5", "", { "os": "freebsd", "cpu": "x64" }, "sha512-J95kNBj1zkbMXtHVH29bBriQygMXqoVQOQYA+ISs0/2l3T9/kj42ow2mpqerRBxDJnmkUDCaQT/dfNXWX/ZZCQ=="], + + "@esbuild/linux-arm": ["@esbuild/linux-arm@0.21.5", "", { "os": "linux", "cpu": "arm" }, "sha512-bPb5AHZtbeNGjCKVZ9UGqGwo8EUu4cLq68E95A53KlxAPRmUyYv2D6F0uUI65XisGOL1hBP5mTronbgo+0bFcA=="], + + "@esbuild/linux-arm64": ["@esbuild/linux-arm64@0.21.5", "", { "os": "linux", "cpu": "arm64" }, "sha512-ibKvmyYzKsBeX8d8I7MH/TMfWDXBF3db4qM6sy+7re0YXya+K1cem3on9XgdT2EQGMu4hQyZhan7TeQ8XkGp4Q=="], + + "@esbuild/linux-ia32": ["@esbuild/linux-ia32@0.21.5", "", { "os": "linux", "cpu": "ia32" }, "sha512-YvjXDqLRqPDl2dvRODYmmhz4rPeVKYvppfGYKSNGdyZkA01046pLWyRKKI3ax8fbJoK5QbxblURkwK/MWY18Tg=="], + + "@esbuild/linux-loong64": ["@esbuild/linux-loong64@0.21.5", "", { "os": "linux", "cpu": "none" }, "sha512-uHf1BmMG8qEvzdrzAqg2SIG/02+4/DHB6a9Kbya0XDvwDEKCoC8ZRWI5JJvNdUjtciBGFQ5PuBlpEOXQj+JQSg=="], + + "@esbuild/linux-mips64el": ["@esbuild/linux-mips64el@0.21.5", "", { "os": "linux", "cpu": "none" }, "sha512-IajOmO+KJK23bj52dFSNCMsz1QP1DqM6cwLUv3W1QwyxkyIWecfafnI555fvSGqEKwjMXVLokcV5ygHW5b3Jbg=="], + + "@esbuild/linux-ppc64": ["@esbuild/linux-ppc64@0.21.5", "", { "os": "linux", "cpu": "ppc64" }, "sha512-1hHV/Z4OEfMwpLO8rp7CvlhBDnjsC3CttJXIhBi+5Aj5r+MBvy4egg7wCbe//hSsT+RvDAG7s81tAvpL2XAE4w=="], + + "@esbuild/linux-riscv64": ["@esbuild/linux-riscv64@0.21.5", "", { "os": "linux", "cpu": "none" }, "sha512-2HdXDMd9GMgTGrPWnJzP2ALSokE/0O5HhTUvWIbD3YdjME8JwvSCnNGBnTThKGEB91OZhzrJ4qIIxk/SBmyDDA=="], + + "@esbuild/linux-s390x": ["@esbuild/linux-s390x@0.21.5", "", { "os": "linux", "cpu": "s390x" }, "sha512-zus5sxzqBJD3eXxwvjN1yQkRepANgxE9lgOW2qLnmr8ikMTphkjgXu1HR01K4FJg8h1kEEDAqDcZQtbrRnB41A=="], + + "@esbuild/linux-x64": ["@esbuild/linux-x64@0.21.5", "", { "os": "linux", "cpu": "x64" }, "sha512-1rYdTpyv03iycF1+BhzrzQJCdOuAOtaqHTWJZCWvijKD2N5Xu0TtVC8/+1faWqcP9iBCWOmjmhoH94dH82BxPQ=="], + + "@esbuild/netbsd-x64": ["@esbuild/netbsd-x64@0.21.5", "", { "os": "none", "cpu": "x64" }, "sha512-Woi2MXzXjMULccIwMnLciyZH4nCIMpWQAs049KEeMvOcNADVxo0UBIQPfSmxB3CWKedngg7sWZdLvLczpe0tLg=="], + + "@esbuild/openbsd-x64": ["@esbuild/openbsd-x64@0.21.5", "", { "os": "openbsd", "cpu": "x64" }, "sha512-HLNNw99xsvx12lFBUwoT8EVCsSvRNDVxNpjZ7bPn947b8gJPzeHWyNVhFsaerc0n3TsbOINvRP2byTZ5LKezow=="], + + "@esbuild/sunos-x64": ["@esbuild/sunos-x64@0.21.5", "", { "os": "sunos", "cpu": "x64" }, "sha512-6+gjmFpfy0BHU5Tpptkuh8+uw3mnrvgs+dSPQXQOv3ekbordwnzTVEb4qnIvQcYXq6gzkyTnoZ9dZG+D4garKg=="], + + "@esbuild/win32-arm64": ["@esbuild/win32-arm64@0.21.5", "", { "os": "win32", "cpu": "arm64" }, "sha512-Z0gOTd75VvXqyq7nsl93zwahcTROgqvuAcYDUr+vOv8uHhNSKROyU961kgtCD1e95IqPKSQKH7tBTslnS3tA8A=="], + + "@esbuild/win32-ia32": ["@esbuild/win32-ia32@0.21.5", "", { "os": "win32", "cpu": "ia32" }, "sha512-SWXFF1CL2RVNMaVs+BBClwtfZSvDgtL//G/smwAc5oVK/UPu2Gu9tIaRgFmYFFKrmg3SyAjSrElf0TiJ1v8fYA=="], + + "@esbuild/win32-x64": ["@esbuild/win32-x64@0.21.5", "", { "os": "win32", "cpu": "x64" }, "sha512-tQd/1efJuzPC6rCFwEvLtci/xNFcTZknmXs98FYDfGE4wP9ClFV98nyKrzJKVPMhdDnjzLhdUyMX4PsQAPjwIw=="], + + "@eslint-community/eslint-utils": ["@eslint-community/eslint-utils@4.4.0", "", { "dependencies": { "eslint-visitor-keys": "^3.3.0" }, "peerDependencies": { "eslint": "^6.0.0 || ^7.0.0 || >=8.0.0" } }, "sha512-1/sA4dwrzBAyeUoQ6oxahHKmrZvsnLCg4RfxW3ZFGGmQkSNQPFNLV9CUEFQP1x9EYXHTo5p6xdhZM1Ne9p/AfA=="], + + "@eslint-community/regexpp": ["@eslint-community/regexpp@4.11.0", "", {}, "sha512-G/M/tIiMrTAxEWRfLfQJMmGNX28IxBg4PBz8XqQhqUHLFI6TL2htpIB1iQCj144V5ee/JaKyT9/WZ0MGZWfA7A=="], + + "@eslint/config-array": ["@eslint/config-array@0.18.0", "", { "dependencies": { "@eslint/object-schema": "^2.1.4", "debug": "^4.3.1", "minimatch": "^3.1.2" } }, "sha512-fTxvnS1sRMu3+JjXwJG0j/i4RT9u4qJ+lqS/yCGap4lH4zZGzQ7tu+xZqQmcMZq5OBZDL4QRxQzRjkWcGt8IVw=="], + + "@eslint/eslintrc": ["@eslint/eslintrc@3.1.0", "", { "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" } }, "sha512-4Bfj15dVJdoy3RfZmmo86RK1Fwzn6SstsvK9JS+BaVKqC6QQQQyXekNaC+g+LKNgkQ+2VhGAzm6hO40AhMR3zQ=="], + + "@eslint/js": ["@eslint/js@9.10.0", "", {}, "sha512-fuXtbiP5GWIn8Fz+LWoOMVf/Jxm+aajZYkhi6CuEm4SxymFM+eUWzbO9qXT+L0iCkL5+KGYMCSGxo686H19S1g=="], + + "@eslint/object-schema": ["@eslint/object-schema@2.1.4", "", {}, "sha512-BsWiH1yFGjXXS2yvrf5LyuoSIIbPrGUWob917o+BTKuZ7qJdxX8aJLRxs1fS9n6r7vESrq1OUqb68dANcFXuQQ=="], + + "@eslint/plugin-kit": ["@eslint/plugin-kit@0.1.0", "", { "dependencies": { "levn": "^0.4.1" } }, "sha512-autAXT203ixhqei9xt+qkYOvY8l6LAFIdT2UXc/RPNeUVfqRF1BV94GTJyVPFKT8nFM6MyVJhjLj9E8JWvf5zQ=="], + + "@humanwhocodes/module-importer": ["@humanwhocodes/module-importer@1.0.1", "", {}, "sha512-bxveV4V8v5Yb4ncFTT3rPSgZBOpCkjfK0y4oVVVJwIuDVBRMDXrPyXRL988i5ap9m9bnyEEjWfm5WkBmtffLfA=="], + + "@humanwhocodes/retry": ["@humanwhocodes/retry@0.3.0", "", {}, "sha512-d2CGZR2o7fS6sWB7DG/3a95bGKQyHMACZ5aW8qGkkqQpUoZV6C0X7Pc7l4ZNMZkfNBf4VWNe9E1jRsf0G146Ew=="], + + "@jridgewell/gen-mapping": ["@jridgewell/gen-mapping@0.3.8", "", { "dependencies": { "@jridgewell/set-array": "^1.2.1", "@jridgewell/sourcemap-codec": "^1.4.10", "@jridgewell/trace-mapping": "^0.3.24" } }, "sha512-imAbBGkb+ebQyxKgzv5Hu2nmROxoDOXHh80evxdoXNOrvAnVx7zimzc1Oo5h9RlfV4vPXaE2iM5pOFbvOCClWA=="], + + "@jridgewell/resolve-uri": ["@jridgewell/resolve-uri@3.1.2", "", {}, "sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw=="], + + "@jridgewell/set-array": ["@jridgewell/set-array@1.2.1", "", {}, "sha512-R8gLRTZeyp03ymzP/6Lil/28tGeGEzhx1q2k703KGWRAI1VdvPIXdG70VJc2pAMw3NA6JKL5hhFu1sJX0Mnn/A=="], + + "@jridgewell/sourcemap-codec": ["@jridgewell/sourcemap-codec@1.5.0", "", {}, "sha512-gv3ZRaISU3fjPAgNsriBRqGWQL6quFx04YMPW/zD8XMLsU32mhCCbfbO6KZFLjvYpCZ8zyDEgqsgf+PwPaM7GQ=="], + + "@jridgewell/trace-mapping": ["@jridgewell/trace-mapping@0.3.25", "", { "dependencies": { "@jridgewell/resolve-uri": "^3.1.0", "@jridgewell/sourcemap-codec": "^1.4.14" } }, "sha512-vNk6aEwybGtawWmy/PzwnGDOjCkLWSD2wqvjGGAgOAwCGWySYXfYoxt00IJkTF+8Lb57DwOb3Aa0o9CApepiYQ=="], + + "@kirick/eslint-config": ["@kirick/eslint-config@0.1.30", "", { "dependencies": { "@stylistic/eslint-plugin": "^2.6.1", "eslint-plugin-jsdoc": "^48.11.0", "eslint-plugin-n": "^17.10.2", "eslint-plugin-promise": "^7.1.0", "eslint-plugin-unicorn": "^55.0.0", "eslint-plugin-vue": "^9.27.0", "globals": "^15.9.0", "typescript-eslint": "^8.0.0" } }, "sha512-RjmSG2380JS/MCh80hnLpVKBI0V5+ggGugTXVK+2Gf0sTq54R5KzX9rKkE1FFIqedG7ZkGyDuipJc7zDYVBQ4g=="], + + "@napi-rs/wasm-runtime": ["@napi-rs/wasm-runtime@0.2.10", "", { "dependencies": { "@emnapi/core": "^1.4.3", "@emnapi/runtime": "^1.4.3", "@tybys/wasm-util": "^0.9.0" } }, "sha512-bCsCyeZEwVErsGmyPNSzwfwFn4OdxBj0mmv6hOFucB/k81Ojdu68RbZdxYsRQUPc9l6SU5F/cG+bXgWs3oUgsQ=="], + + "@nodelib/fs.scandir": ["@nodelib/fs.scandir@2.1.5", "", { "dependencies": { "@nodelib/fs.stat": "2.0.5", "run-parallel": "^1.1.9" } }, "sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g=="], + + "@nodelib/fs.stat": ["@nodelib/fs.stat@2.0.5", "", {}, "sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A=="], + + "@nodelib/fs.walk": ["@nodelib/fs.walk@1.2.8", "", { "dependencies": { "@nodelib/fs.scandir": "2.1.5", "fastq": "^1.6.0" } }, "sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg=="], + + "@oxc-project/types": ["@oxc-project/types@0.71.0", "", {}, "sha512-5CwQ4MI+P4MQbjLWXgNurA+igGwu/opNetIE13LBs9+V93R64MLvDKOOLZIXSzEfovU3Zef3q3GjPnMTgJTn2w=="], + + "@pkgr/core": ["@pkgr/core@0.1.1", "", {}, "sha512-cq8o4cWH0ibXh9VGi5P20Tu9XF/0fFXl9EUinr9QfTM7a7p0oTA4iJRCQWppXR1Pg8dSM0UCItCkPwsk9qWWYA=="], + + "@publint/pack": ["@publint/pack@0.1.2", "", {}, "sha512-S+9ANAvUmjutrshV4jZjaiG8XQyuJIZ8a4utWmN/vW1sgQ9IfBnPndwkmQYw53QmouOIytT874u65HEmu6H5jw=="], + + "@quansync/fs": ["@quansync/fs@0.1.3", "", { "dependencies": { "quansync": "^0.2.10" } }, "sha512-G0OnZbMWEs5LhDyqy2UL17vGhSVHkQIfVojMtEWVenvj0V5S84VBgy86kJIuNsGDp2p7sTKlpSIpBUWdC35OKg=="], + + "@rolldown/binding-darwin-arm64": ["@rolldown/binding-darwin-arm64@1.0.0-beta.9-commit.51df2b7", "", { "os": "darwin", "cpu": "arm64" }, "sha512-ho2xtXwIXiSIlI0C4G9TKxeRC0BOlML1JMNILpxvdjJiN/M6zV/MYIys6ZyqIlIlLzilr0Wu4KIpb+mnR2E7tQ=="], + + "@rolldown/binding-darwin-x64": ["@rolldown/binding-darwin-x64@1.0.0-beta.9-commit.51df2b7", "", { "os": "darwin", "cpu": "x64" }, "sha512-f9llkFu7gAL/uvbU9JQtMgrPXE70HZ8VXHMD6ENvdzmM+Z/Bh8WnquwbgpSSnj9M111Tg4gyZe3R31CTYlcQow=="], + + "@rolldown/binding-freebsd-x64": ["@rolldown/binding-freebsd-x64@1.0.0-beta.9-commit.51df2b7", "", { "os": "freebsd", "cpu": "x64" }, "sha512-ZP3+8qmcUkxzXMvGVyaPKKUswhyRfBo4EGEo4FOxQ6+D+XjTaL4rSGOs979CBpfk7f3HIxyKEXvWokv6fsdTdw=="], + + "@rolldown/binding-linux-arm-gnueabihf": ["@rolldown/binding-linux-arm-gnueabihf@1.0.0-beta.9-commit.51df2b7", "", { "os": "linux", "cpu": "arm" }, "sha512-lb4TCuCGimXdImS1fiZqfZBObgxZr32P8u1T8FeifdwGCieXnz5CjoywDyrhZuZMoLU3UU3PJV7WcD8721jK/g=="], + + "@rolldown/binding-linux-arm64-gnu": ["@rolldown/binding-linux-arm64-gnu@1.0.0-beta.9-commit.51df2b7", "", { "os": "linux", "cpu": "arm64" }, "sha512-07FhoEJsku912alIEfTf1QmEMWxjuQxkPD6ewWtyyhEZHDF5XhpKpat/GFEDic/doXVRggRvxIZccyS5Kyu45A=="], + + "@rolldown/binding-linux-arm64-musl": ["@rolldown/binding-linux-arm64-musl@1.0.0-beta.9-commit.51df2b7", "", { "os": "linux", "cpu": "arm64" }, "sha512-QUHSOXq6F+Z4eBud86nGq2C/KhdNs980LLQcAFDIr6tPw5fN8Z2Zqy61XeWGB01Y30G5esiMzsJqsHHQDqSvsg=="], + + "@rolldown/binding-linux-x64-gnu": ["@rolldown/binding-linux-x64-gnu@1.0.0-beta.9-commit.51df2b7", "", { "os": "linux", "cpu": "x64" }, "sha512-VdsjRgP2VlAJqbuHdY3Xh37+yU7H+KYy3fA2+falRGlhko20/Ch8V7+7SizTu2LfKgvd1LVhQek8InnmojX0tA=="], + + "@rolldown/binding-linux-x64-musl": ["@rolldown/binding-linux-x64-musl@1.0.0-beta.9-commit.51df2b7", "", { "os": "linux", "cpu": "x64" }, "sha512-zbilaXq6n+FerHarckH20bh5QgSPO9dCC4BfAzXidaji/eMRO0gfjFjKJpVx0gxwc+LVBjdHDKB0DplGZiPMEw=="], + + "@rolldown/binding-wasm32-wasi": ["@rolldown/binding-wasm32-wasi@1.0.0-beta.9-commit.51df2b7", "", { "dependencies": { "@napi-rs/wasm-runtime": "^0.2.4" }, "cpu": "none" }, "sha512-iqvvLmCl9n3TzE6QLZ1ZRYigavEoOVr33Q6qoLbDHnnXZqp1V9APLckbv8E9qaukDmbVP3dOCr/dD7AT+GsE3w=="], + + "@rolldown/binding-win32-arm64-msvc": ["@rolldown/binding-win32-arm64-msvc@1.0.0-beta.9-commit.51df2b7", "", { "os": "win32", "cpu": "arm64" }, "sha512-ey1jfhd5BFn4bIJjQAVNclkDCl9mg9b96LyDHVETkZZrmAV8zSaE0kazXe5eWn8n7p0RH2t1cOiQWVcXrFVh0g=="], + + "@rolldown/binding-win32-ia32-msvc": ["@rolldown/binding-win32-ia32-msvc@1.0.0-beta.9-commit.51df2b7", "", { "os": "win32", "cpu": "ia32" }, "sha512-RBWTjyturLAPInDJH+945twk31bkEw4t0wcWZFXzGFGN6fjeF0Jlj9fPQ3+TO3GhqAgeLymraFztJJdLVc7hSg=="], + + "@rolldown/binding-win32-x64-msvc": ["@rolldown/binding-win32-x64-msvc@1.0.0-beta.9-commit.51df2b7", "", { "os": "win32", "cpu": "x64" }, "sha512-umDrroMuEfK3xYcRvr6p7u1AUwv3IoY2Sl6LlBZ5ncOAZ/OQo/41wHwUHtN+PRE02/BI8f84HMZrMR+rJgkmog=="], + + "@rolldown/pluginutils": ["@rolldown/pluginutils@1.0.0-beta.9-commit.51df2b7", "", {}, "sha512-A+2WuD4O5309iooTWXMS0vMfb44bKJUOCwJj2oBYvOpaNT3VHFmgLdx++NTlKh/3hJ8Xa+Zy8c34z0EBQSU+mw=="], + + "@rollup/rollup-android-arm-eabi": ["@rollup/rollup-android-arm-eabi@4.21.2", "", { "os": "android", "cpu": "arm" }, "sha512-fSuPrt0ZO8uXeS+xP3b+yYTCBUd05MoSp2N/MFOgjhhUhMmchXlpTQrTpI8T+YAwAQuK7MafsCOxW7VrPMrJcg=="], + + "@rollup/rollup-android-arm64": ["@rollup/rollup-android-arm64@4.21.2", "", { "os": "android", "cpu": "arm64" }, "sha512-xGU5ZQmPlsjQS6tzTTGwMsnKUtu0WVbl0hYpTPauvbRAnmIvpInhJtgjj3mcuJpEiuUw4v1s4BimkdfDWlh7gA=="], + + "@rollup/rollup-darwin-arm64": ["@rollup/rollup-darwin-arm64@4.21.2", "", { "os": "darwin", "cpu": "arm64" }, "sha512-99AhQ3/ZMxU7jw34Sq8brzXqWH/bMnf7ZVhvLk9QU2cOepbQSVTns6qoErJmSiAvU3InRqC2RRZ5ovh1KN0d0Q=="], + + "@rollup/rollup-darwin-x64": ["@rollup/rollup-darwin-x64@4.21.2", "", { "os": "darwin", "cpu": "x64" }, "sha512-ZbRaUvw2iN/y37x6dY50D8m2BnDbBjlnMPotDi/qITMJ4sIxNY33HArjikDyakhSv0+ybdUxhWxE6kTI4oX26w=="], + + "@rollup/rollup-linux-arm-gnueabihf": ["@rollup/rollup-linux-arm-gnueabihf@4.21.2", "", { "os": "linux", "cpu": "arm" }, "sha512-ztRJJMiE8nnU1YFcdbd9BcH6bGWG1z+jP+IPW2oDUAPxPjo9dverIOyXz76m6IPA6udEL12reYeLojzW2cYL7w=="], + + "@rollup/rollup-linux-arm-musleabihf": ["@rollup/rollup-linux-arm-musleabihf@4.21.2", "", { "os": "linux", "cpu": "arm" }, "sha512-flOcGHDZajGKYpLV0JNc0VFH361M7rnV1ee+NTeC/BQQ1/0pllYcFmxpagltANYt8FYf9+kL6RSk80Ziwyhr7w=="], + + "@rollup/rollup-linux-arm64-gnu": ["@rollup/rollup-linux-arm64-gnu@4.21.2", "", { "os": "linux", "cpu": "arm64" }, "sha512-69CF19Kp3TdMopyteO/LJbWufOzqqXzkrv4L2sP8kfMaAQ6iwky7NoXTp7bD6/irKgknDKM0P9E/1l5XxVQAhw=="], + + "@rollup/rollup-linux-arm64-musl": ["@rollup/rollup-linux-arm64-musl@4.21.2", "", { "os": "linux", "cpu": "arm64" }, "sha512-48pD/fJkTiHAZTnZwR0VzHrao70/4MlzJrq0ZsILjLW/Ab/1XlVUStYyGt7tdyIiVSlGZbnliqmult/QGA2O2w=="], + + "@rollup/rollup-linux-powerpc64le-gnu": ["@rollup/rollup-linux-powerpc64le-gnu@4.21.2", "", { "os": "linux", "cpu": "ppc64" }, "sha512-cZdyuInj0ofc7mAQpKcPR2a2iu4YM4FQfuUzCVA2u4HI95lCwzjoPtdWjdpDKyHxI0UO82bLDoOaLfpZ/wviyQ=="], + + "@rollup/rollup-linux-riscv64-gnu": ["@rollup/rollup-linux-riscv64-gnu@4.21.2", "", { "os": "linux", "cpu": "none" }, "sha512-RL56JMT6NwQ0lXIQmMIWr1SW28z4E4pOhRRNqwWZeXpRlykRIlEpSWdsgNWJbYBEWD84eocjSGDu/XxbYeCmwg=="], + + "@rollup/rollup-linux-s390x-gnu": ["@rollup/rollup-linux-s390x-gnu@4.21.2", "", { "os": "linux", "cpu": "s390x" }, "sha512-PMxkrWS9z38bCr3rWvDFVGD6sFeZJw4iQlhrup7ReGmfn7Oukrr/zweLhYX6v2/8J6Cep9IEA/SmjXjCmSbrMQ=="], + + "@rollup/rollup-linux-x64-gnu": ["@rollup/rollup-linux-x64-gnu@4.21.2", "", { "os": "linux", "cpu": "x64" }, "sha512-B90tYAUoLhU22olrafY3JQCFLnT3NglazdwkHyxNDYF/zAxJt5fJUB/yBoWFoIQ7SQj+KLe3iL4BhOMa9fzgpw=="], + + "@rollup/rollup-linux-x64-musl": ["@rollup/rollup-linux-x64-musl@4.21.2", "", { "os": "linux", "cpu": "x64" }, "sha512-7twFizNXudESmC9oneLGIUmoHiiLppz/Xs5uJQ4ShvE6234K0VB1/aJYU3f/4g7PhssLGKBVCC37uRkkOi8wjg=="], + + "@rollup/rollup-win32-arm64-msvc": ["@rollup/rollup-win32-arm64-msvc@4.21.2", "", { "os": "win32", "cpu": "arm64" }, "sha512-9rRero0E7qTeYf6+rFh3AErTNU1VCQg2mn7CQcI44vNUWM9Ze7MSRS/9RFuSsox+vstRt97+x3sOhEey024FRQ=="], + + "@rollup/rollup-win32-ia32-msvc": ["@rollup/rollup-win32-ia32-msvc@4.21.2", "", { "os": "win32", "cpu": "ia32" }, "sha512-5rA4vjlqgrpbFVVHX3qkrCo/fZTj1q0Xxpg+Z7yIo3J2AilW7t2+n6Q8Jrx+4MrYpAnjttTYF8rr7bP46BPzRw=="], + + "@rollup/rollup-win32-x64-msvc": ["@rollup/rollup-win32-x64-msvc@4.21.2", "", { "os": "win32", "cpu": "x64" }, "sha512-6UUxd0+SKomjdzuAcp+HAmxw1FlGBnl1v2yEPSabtx4lBfdXHDVsW7+lQkgz9cNFJGY3AWR7+V8P5BqkD9L9nA=="], + + "@stylistic/eslint-plugin": ["@stylistic/eslint-plugin@2.7.2", "", { "dependencies": { "@types/eslint": "^9.6.1", "@typescript-eslint/utils": "^8.3.0", "eslint-visitor-keys": "^4.0.0", "espree": "^10.1.0", "estraverse": "^5.3.0", "picomatch": "^4.0.2" }, "peerDependencies": { "eslint": ">=8.40.0" } }, "sha512-3DVLU5HEuk2pQoBmXJlzvrxbKNpu2mJ0SRqz5O/CJjyNCr12ZiPcYMEtuArTyPOk5i7bsAU44nywh1rGfe3gKQ=="], + + "@tybys/wasm-util": ["@tybys/wasm-util@0.9.0", "", { "dependencies": { "tslib": "^2.4.0" } }, "sha512-6+7nlbMVX/PVDCwaIQ8nTOPveOcFLSt8GcXdx8hD0bt39uWxYT88uXzqTd4fTvqta7oeUJqudepapKNt2DYJFw=="], + + "@types/bun": ["@types/bun@1.2.14", "", { "dependencies": { "bun-types": "1.2.14" } }, "sha512-VsFZKs8oKHzI7zwvECiAJ5oSorWndIWEVhfbYqZd4HI/45kzW7PN2Rr5biAzvGvRuNmYLSANY+H59ubHq8xw7Q=="], + + "@types/eslint": ["@types/eslint@9.6.1", "", { "dependencies": { "@types/estree": "*", "@types/json-schema": "*" } }, "sha512-FXx2pKgId/WyYo2jXw63kk7/+TY7u7AziEJxJAnSFzHlqTAS3Ync6SvgYAN/k4/PQpnnVuzoMuVnByKK2qp0ag=="], + + "@types/estree": ["@types/estree@1.0.5", "", {}, "sha512-/kYRxGDLWzHOB7q+wtSUQlFrtcdUccpfy+X+9iMBpHK8QLLhx2wIPYuS5DYtR9Wa/YlZAbIovy7qVdB1Aq6Lyw=="], + + "@types/json-schema": ["@types/json-schema@7.0.15", "", {}, "sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA=="], + + "@types/node": ["@types/node@20.16.5", "", { "dependencies": { "undici-types": "~6.19.2" } }, "sha512-VwYCweNo3ERajwy0IUlqqcyZ8/A7Zwa9ZP3MnENWcB11AejO+tLy3pu850goUW2FC/IJMdZUfKpX/yxL1gymCA=="], + + "@types/normalize-package-data": ["@types/normalize-package-data@2.4.4", "", {}, "sha512-37i+OaWTh9qeK4LSHPsyRC7NahnGotNuZvjLSgcPzblpHB3rrCJxAOgI5gCdKm7coonsaX1Of0ILiTcnZjbfxA=="], + + "@typescript-eslint/eslint-plugin": ["@typescript-eslint/eslint-plugin@8.4.0", "", { "dependencies": { "@eslint-community/regexpp": "^4.10.0", "@typescript-eslint/scope-manager": "8.4.0", "@typescript-eslint/type-utils": "8.4.0", "@typescript-eslint/utils": "8.4.0", "@typescript-eslint/visitor-keys": "8.4.0", "graphemer": "^1.4.0", "ignore": "^5.3.1", "natural-compare": "^1.4.0", "ts-api-utils": "^1.3.0" }, "peerDependencies": { "@typescript-eslint/parser": "^8.0.0 || ^8.0.0-alpha.0", "eslint": "^8.57.0 || ^9.0.0" } }, "sha512-rg8LGdv7ri3oAlenMACk9e+AR4wUV0yrrG+XKsGKOK0EVgeEDqurkXMPILG2836fW4ibokTB5v4b6Z9+GYQDEw=="], + + "@typescript-eslint/parser": ["@typescript-eslint/parser@8.4.0", "", { "dependencies": { "@typescript-eslint/scope-manager": "8.4.0", "@typescript-eslint/types": "8.4.0", "@typescript-eslint/typescript-estree": "8.4.0", "@typescript-eslint/visitor-keys": "8.4.0", "debug": "^4.3.4" }, "peerDependencies": { "eslint": "^8.57.0 || ^9.0.0" } }, "sha512-NHgWmKSgJk5K9N16GIhQ4jSobBoJwrmURaLErad0qlLjrpP5bECYg+wxVTGlGZmJbU03jj/dfnb6V9bw+5icsA=="], + + "@typescript-eslint/scope-manager": ["@typescript-eslint/scope-manager@8.4.0", "", { "dependencies": { "@typescript-eslint/types": "8.4.0", "@typescript-eslint/visitor-keys": "8.4.0" } }, "sha512-n2jFxLeY0JmKfUqy3P70rs6vdoPjHK8P/w+zJcV3fk0b0BwRXC/zxRTEnAsgYT7MwdQDt/ZEbtdzdVC+hcpF0A=="], + + "@typescript-eslint/type-utils": ["@typescript-eslint/type-utils@8.4.0", "", { "dependencies": { "@typescript-eslint/typescript-estree": "8.4.0", "@typescript-eslint/utils": "8.4.0", "debug": "^4.3.4", "ts-api-utils": "^1.3.0" } }, "sha512-pu2PAmNrl9KX6TtirVOrbLPLwDmASpZhK/XU7WvoKoCUkdtq9zF7qQ7gna0GBZFN0hci0vHaSusiL2WpsQk37A=="], + + "@typescript-eslint/types": ["@typescript-eslint/types@8.4.0", "", {}, "sha512-T1RB3KQdskh9t3v/qv7niK6P8yvn7ja1mS7QK7XfRVL6wtZ8/mFs/FHf4fKvTA0rKnqnYxl/uHFNbnEt0phgbw=="], + + "@typescript-eslint/typescript-estree": ["@typescript-eslint/typescript-estree@8.4.0", "", { "dependencies": { "@typescript-eslint/types": "8.4.0", "@typescript-eslint/visitor-keys": "8.4.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" } }, "sha512-kJ2OIP4dQw5gdI4uXsaxUZHRwWAGpREJ9Zq6D5L0BweyOrWsL6Sz0YcAZGWhvKnH7fm1J5YFE1JrQL0c9dd53A=="], + + "@typescript-eslint/utils": ["@typescript-eslint/utils@8.4.0", "", { "dependencies": { "@eslint-community/eslint-utils": "^4.4.0", "@typescript-eslint/scope-manager": "8.4.0", "@typescript-eslint/types": "8.4.0", "@typescript-eslint/typescript-estree": "8.4.0" }, "peerDependencies": { "eslint": "^8.57.0 || ^9.0.0" } }, "sha512-swULW8n1IKLjRAgciCkTCafyTHHfwVQFt8DovmaF69sKbOxTSFMmIZaSHjqO9i/RV0wIblaawhzvtva8Nmm7lQ=="], + + "@typescript-eslint/visitor-keys": ["@typescript-eslint/visitor-keys@8.4.0", "", { "dependencies": { "@typescript-eslint/types": "8.4.0", "eslint-visitor-keys": "^3.4.3" } }, "sha512-zTQD6WLNTre1hj5wp09nBIDiOc2U5r/qmzo7wxPn4ZgAjHql09EofqhF9WF+fZHzL5aCyaIpPcT2hyxl73kr9A=="], + + "@vitest/expect": ["@vitest/expect@3.1.4", "", { "dependencies": { "@vitest/spy": "3.1.4", "@vitest/utils": "3.1.4", "chai": "^5.2.0", "tinyrainbow": "^2.0.0" } }, "sha512-xkD/ljeliyaClDYqHPNCiJ0plY5YIcM0OlRiZizLhlPmpXWpxnGMyTZXOHFhFeG7w9P5PBeL4IdtJ/HeQwTbQA=="], + + "@vitest/mocker": ["@vitest/mocker@3.1.4", "", { "dependencies": { "@vitest/spy": "3.1.4", "estree-walker": "^3.0.3", "magic-string": "^0.30.17" }, "peerDependencies": { "msw": "^2.4.9", "vite": "^5.0.0 || ^6.0.0" }, "optionalPeers": ["msw", "vite"] }, "sha512-8IJ3CvwtSw/EFXqWFL8aCMu+YyYXG2WUSrQbViOZkWTKTVicVwZ/YiEZDSqD00kX+v/+W+OnxhNWoeVKorHygA=="], + + "@vitest/pretty-format": ["@vitest/pretty-format@3.1.4", "", { "dependencies": { "tinyrainbow": "^2.0.0" } }, "sha512-cqv9H9GvAEoTaoq+cYqUTCGscUjKqlJZC7PRwY5FMySVj5J+xOm1KQcCiYHJOEzOKRUhLH4R2pTwvFlWCEScsg=="], + + "@vitest/runner": ["@vitest/runner@3.1.4", "", { "dependencies": { "@vitest/utils": "3.1.4", "pathe": "^2.0.3" } }, "sha512-djTeF1/vt985I/wpKVFBMWUlk/I7mb5hmD5oP8K9ACRmVXgKTae3TUOtXAEBfslNKPzUQvnKhNd34nnRSYgLNQ=="], + + "@vitest/snapshot": ["@vitest/snapshot@3.1.4", "", { "dependencies": { "@vitest/pretty-format": "3.1.4", "magic-string": "^0.30.17", "pathe": "^2.0.3" } }, "sha512-JPHf68DvuO7vilmvwdPr9TS0SuuIzHvxeaCkxYcCD4jTk67XwL45ZhEHFKIuCm8CYstgI6LZ4XbwD6ANrwMpFg=="], + + "@vitest/spy": ["@vitest/spy@3.1.4", "", { "dependencies": { "tinyspy": "^3.0.2" } }, "sha512-Xg1bXhu+vtPXIodYN369M86K8shGLouNjoVI78g8iAq2rFoHFdajNvJJ5A/9bPMFcfQqdaCpOgWKEoMQg/s0Yg=="], + + "@vitest/utils": ["@vitest/utils@3.1.4", "", { "dependencies": { "@vitest/pretty-format": "3.1.4", "loupe": "^3.1.3", "tinyrainbow": "^2.0.0" } }, "sha512-yriMuO1cfFhmiGc8ataN51+9ooHRuURdfAZfwFd3usWynjzpLslZdYnRegTv32qdgtJTsj15FoeZe2g15fY1gg=="], + + "acorn": ["acorn@8.12.1", "", { "bin": { "acorn": "bin/acorn" } }, "sha512-tcpGyI9zbizT9JbV6oYE477V6mTlXvvi0T0G3SNIYE2apm/G5huBa1+K89VGeovbg+jycCrfhl3ADxErOuO6Jg=="], + + "acorn-jsx": ["acorn-jsx@5.3.2", "", { "peerDependencies": { "acorn": "^6.0.0 || ^7.0.0 || ^8.0.0" } }, "sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ=="], + + "ajv": ["ajv@6.12.6", "", { "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" } }, "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g=="], + + "ansi-regex": ["ansi-regex@5.0.1", "", {}, "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ=="], + + "ansi-styles": ["ansi-styles@4.3.0", "", { "dependencies": { "color-convert": "^2.0.1" } }, "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg=="], + + "ansis": ["ansis@4.0.0", "", {}, "sha512-P8nrHI1EyW9OfBt1X7hMSwGN2vwRuqHSKJAT1gbLWZRzDa24oHjYwGHvEgHeBepupzk878yS/HBZ0NMPYtbolw=="], + + "are-docs-informative": ["are-docs-informative@0.0.2", "", {}, "sha512-ixiS0nLNNG5jNQzgZJNoUpBKdo9yTYZMGJ+QgT2jmjR7G7+QHRCc4v6LQ3NgE7EBJq+o0ams3waJwkrlBom8Ig=="], + + "argparse": ["argparse@2.0.1", "", {}, "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q=="], + + "assertion-error": ["assertion-error@2.0.1", "", {}, "sha512-Izi8RQcffqCeNVgFigKli1ssklIbpHnCYc6AknXGYoB6grJqyeby7jv12JUQgmTAnIDnbck1uxksT4dzN3PWBA=="], + + "ast-kit": ["ast-kit@2.0.0", "", { "dependencies": { "@babel/parser": "^7.27.2", "pathe": "^2.0.3" } }, "sha512-P63jzlYNz96MF9mCcprU+a7I5/ZQ5QAn3y+mZcPWEcGV3CHF/GWnkFPj3oCrWLUjL47+PD9PNiCUdXxw0cWdsg=="], + + "balanced-match": ["balanced-match@1.0.2", "", {}, "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw=="], + + "birpc": ["birpc@2.3.0", "", {}, "sha512-ijbtkn/F3Pvzb6jHypHRyve2QApOCZDR25D/VnkY2G/lBNcXCTsnsCxgY4k4PkVB7zfwzYbY3O9Lcqe3xufS5g=="], + + "boolbase": ["boolbase@1.0.0", "", {}, "sha512-JZOSA7Mo9sNGB8+UjSgzdLtokWAky1zbztM3WRLCbZ70/3cTANmQmOdR7y2g+J0e2WXywy1yS468tY+IruqEww=="], + + "brace-expansion": ["brace-expansion@1.1.11", "", { "dependencies": { "balanced-match": "^1.0.0", "concat-map": "0.0.1" } }, "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA=="], + + "braces": ["braces@3.0.3", "", { "dependencies": { "fill-range": "^7.1.1" } }, "sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA=="], + + "browserslist": ["browserslist@4.23.3", "", { "dependencies": { "caniuse-lite": "^1.0.30001646", "electron-to-chromium": "^1.5.4", "node-releases": "^2.0.18", "update-browserslist-db": "^1.1.0" }, "bin": { "browserslist": "cli.js" } }, "sha512-btwCFJVjI4YWDNfau8RhZ+B1Q/VLoUITrm3RlP6y1tYGWIOa+InuYiRGXUBXo8nA1qKmHMyLB/iVQg5TT4eFoA=="], + + "builtin-modules": ["builtin-modules@3.3.0", "", {}, "sha512-zhaCDicdLuWN5UbN5IMnFqNMhNfo919sH85y2/ea+5Yg9TsTkeZxpL+JLbp6cgYFS4sRLp3YV4S6yDuqVWHYOw=="], + + "bun-types": ["bun-types@1.2.14", "", { "dependencies": { "@types/node": "*" } }, "sha512-Kuh4Ub28ucMRWeiUUWMHsT9Wcbr4H3kLIO72RZZElSDxSu7vpetRvxIUDUaW6QtaIeixIpm7OXtNnZPf82EzwA=="], + + "cac": ["cac@6.7.14", "", {}, "sha512-b6Ilus+c3RrdDk+JhLKUAQfzzgLEPy6wcXqS7f/xe1EETvsDP6GORG7SFuOs6cID5YkqchW/LXZbX5bc8j7ZcQ=="], + + "callsites": ["callsites@3.1.0", "", {}, "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ=="], + + "caniuse-lite": ["caniuse-lite@1.0.30001657", "", {}, "sha512-DPbJAlP8/BAXy3IgiWmZKItubb3TYGP0WscQQlVGIfT4s/YlFYVuJgyOsQNP7rJRChx/qdMeLJQJP0Sgg2yjNA=="], + + "chai": ["chai@5.2.0", "", { "dependencies": { "assertion-error": "^2.0.1", "check-error": "^2.1.1", "deep-eql": "^5.0.1", "loupe": "^3.1.0", "pathval": "^2.0.0" } }, "sha512-mCuXncKXk5iCLhfhwTc0izo0gtEmpz5CtG2y8GiOINBlMVS6v8TMRc5TaLWKS6692m9+dVVfzgeVxR5UxWHTYw=="], + + "chalk": ["chalk@4.1.2", "", { "dependencies": { "ansi-styles": "^4.1.0", "supports-color": "^7.1.0" } }, "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA=="], + + "check-error": ["check-error@2.1.1", "", {}, "sha512-OAlb+T7V4Op9OwdkjmguYRqncdlx5JiofwOAUkmTF+jNdHwzTaTs4sRAGpzLF3oOz5xAyDGrPgeIDFQmDOTiJw=="], + + "chokidar": ["chokidar@4.0.3", "", { "dependencies": { "readdirp": "^4.0.1" } }, "sha512-Qgzu8kfBvo+cA4962jnP1KkS6Dop5NS6g7R5LFYJr4b8Ub94PPQXUksCw9PvXoeXPRRddRNC5C1JQUR2SMGtnA=="], + + "ci-info": ["ci-info@4.0.0", "", {}, "sha512-TdHqgGf9odd8SXNuxtUBVx8Nv+qZOejE6qyqiy5NtbYYQOeFa6zmHkxlPzmaLxWWHsU6nJmB7AETdVPi+2NBUg=="], + + "clean-regexp": ["clean-regexp@1.0.0", "", { "dependencies": { "escape-string-regexp": "^1.0.5" } }, "sha512-GfisEZEJvzKrmGWkvfhgzcz/BllN1USeqD2V6tg14OAOgaCD2Z/PUEuxnAZ/nPvmaHRG7a8y77p1T/IRQ4D1Hw=="], + + "color-convert": ["color-convert@2.0.1", "", { "dependencies": { "color-name": "~1.1.4" } }, "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ=="], + + "color-name": ["color-name@1.1.4", "", {}, "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA=="], + + "comment-parser": ["comment-parser@1.4.1", "", {}, "sha512-buhp5kePrmda3vhc5B9t7pUQXAb2Tnd0qgpkIhPhkHXxJpiPJ11H0ZEU0oBpJ2QztSbzG/ZxMj/CHsYJqRHmyg=="], + + "concat-map": ["concat-map@0.0.1", "", {}, "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg=="], + + "confbox": ["confbox@0.2.2", "", {}, "sha512-1NB+BKqhtNipMsov4xI/NnhCKp9XG9NamYp5PVm9klAT0fsrNPjaFICsCFhNhwZJKNh7zB/3q8qXz0E9oaMNtQ=="], + + "core-js-compat": ["core-js-compat@3.38.1", "", { "dependencies": { "browserslist": "^4.23.3" } }, "sha512-JRH6gfXxGmrzF3tZ57lFx97YARxCXPaMzPo6jELZhv88pBH5VXpQ+y0znKGlFnzuaihqhLbefxSJxWJMPtfDzw=="], + + "cross-spawn": ["cross-spawn@7.0.3", "", { "dependencies": { "path-key": "^3.1.0", "shebang-command": "^2.0.0", "which": "^2.0.1" } }, "sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w=="], + + "cssesc": ["cssesc@3.0.0", "", { "bin": { "cssesc": "bin/cssesc" } }, "sha512-/Tb/JcjK111nNScGob5MNtsntNM1aCNUDipB/TkwZFhyDrrE47SOx/18wF2bbjgc3ZzCSKW1T5nt5EbFoAz/Vg=="], + + "debug": ["debug@4.3.6", "", { "dependencies": { "ms": "2.1.2" } }, "sha512-O/09Bd4Z1fBrU4VzkhFqVgpPzaGbw6Sm9FEkBT1A/YBXQFGuuSxa1dN2nxgxS34JmKXqYx8CZAwEVoJFImUXIg=="], + + "deep-eql": ["deep-eql@5.0.2", "", {}, "sha512-h5k/5U50IJJFpzfL6nO9jaaumfjO/f2NjK/oYB2Djzm4p9L+3T9qWpZqZ2hAbLPuuYq9wrU08WQyBTL5GbPk5Q=="], + + "deep-is": ["deep-is@0.1.4", "", {}, "sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ=="], + + "defu": ["defu@6.1.4", "", {}, "sha512-mEQCMmwJu317oSz8CwdIOdwf3xMif1ttiM8LTufzc3g6kR+9Pe236twL8j3IYT1F7GfRgGcW6MWxzZjLIkuHIg=="], + + "diff": ["diff@8.0.2", "", {}, "sha512-sSuxWU5j5SR9QQji/o2qMvqRNYRDOcBTgsJ/DeCf4iSN4gW+gNMXM7wFIP+fdXZxoNiAnHUTGjCr+TSWXdRDKg=="], + + "dts-resolver": ["dts-resolver@2.0.1", "", { "peerDependencies": { "oxc-resolver": "^9.0.2" }, "optionalPeers": ["oxc-resolver"] }, "sha512-Pe2kqaQTNVxleYpt9Q9658fn6rEpoZbMbDpEBbcU6pnuGM3Q0IdM+Rv67kN6qcyp8Bv2Uv9NYy5Y1rG1LSgfoQ=="], + + "electron-to-chromium": ["electron-to-chromium@1.5.14", "", {}, "sha512-bEfPECb3fJ15eaDnu9LEJ2vPGD6W1vt7vZleSVyFhYuMIKm3vz/g9lt7IvEzgdwj58RjbPKUF2rXTCN/UW47tQ=="], + + "empathic": ["empathic@1.1.0", "", {}, "sha512-rsPft6CK3eHtrlp9Y5ALBb+hfK+DWnA4WFebbazxjWyx8vSm3rZeoM3z9irsjcqO3PYRzlfv27XIB4tz2DV7RA=="], + + "enhanced-resolve": ["enhanced-resolve@5.17.1", "", { "dependencies": { "graceful-fs": "^4.2.4", "tapable": "^2.2.0" } }, "sha512-LMHl3dXhTcfv8gM4kEzIUeTQ+7fpdA0l2tUf34BddXPkz2A5xJ5L/Pchd5BL6rdccM9QGvu0sWZzK1Z1t4wwyg=="], + + "error-ex": ["error-ex@1.3.2", "", { "dependencies": { "is-arrayish": "^0.2.1" } }, "sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g=="], + + "es-module-lexer": ["es-module-lexer@1.7.0", "", {}, "sha512-jEQoCwk8hyb2AZziIOLhDqpm5+2ww5uIE6lkO/6jcOCusfk6LhMHpXXfBLXTZ7Ydyt0j4VoUQv6uGNYbdW+kBA=="], + + "esbuild": ["esbuild@0.21.5", "", { "optionalDependencies": { "@esbuild/aix-ppc64": "0.21.5", "@esbuild/android-arm": "0.21.5", "@esbuild/android-arm64": "0.21.5", "@esbuild/android-x64": "0.21.5", "@esbuild/darwin-arm64": "0.21.5", "@esbuild/darwin-x64": "0.21.5", "@esbuild/freebsd-arm64": "0.21.5", "@esbuild/freebsd-x64": "0.21.5", "@esbuild/linux-arm": "0.21.5", "@esbuild/linux-arm64": "0.21.5", "@esbuild/linux-ia32": "0.21.5", "@esbuild/linux-loong64": "0.21.5", "@esbuild/linux-mips64el": "0.21.5", "@esbuild/linux-ppc64": "0.21.5", "@esbuild/linux-riscv64": "0.21.5", "@esbuild/linux-s390x": "0.21.5", "@esbuild/linux-x64": "0.21.5", "@esbuild/netbsd-x64": "0.21.5", "@esbuild/openbsd-x64": "0.21.5", "@esbuild/sunos-x64": "0.21.5", "@esbuild/win32-arm64": "0.21.5", "@esbuild/win32-ia32": "0.21.5", "@esbuild/win32-x64": "0.21.5" }, "bin": { "esbuild": "bin/esbuild" } }, "sha512-mg3OPMV4hXywwpoDxu3Qda5xCKQi+vCTZq8S9J/EpkhB2HzKXq4SNFZE3+NK93JYxc8VMSep+lOUSC/RVKaBqw=="], + + "escalade": ["escalade@3.2.0", "", {}, "sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA=="], + + "escape-string-regexp": ["escape-string-regexp@4.0.0", "", {}, "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA=="], + + "eslint": ["eslint@9.10.0", "", { "dependencies": { "@eslint-community/eslint-utils": "^4.2.0", "@eslint-community/regexpp": "^4.11.0", "@eslint/config-array": "^0.18.0", "@eslint/eslintrc": "^3.1.0", "@eslint/js": "9.10.0", "@eslint/plugin-kit": "^0.1.0", "@humanwhocodes/module-importer": "^1.0.1", "@humanwhocodes/retry": "^0.3.0", "@nodelib/fs.walk": "^1.2.8", "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.0.2", "eslint-visitor-keys": "^4.0.0", "espree": "^10.1.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", "is-path-inside": "^3.0.3", "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", "strip-ansi": "^6.0.1", "text-table": "^0.2.0" }, "peerDependencies": { "jiti": "*" }, "optionalPeers": ["jiti"], "bin": { "eslint": "bin/eslint.js" } }, "sha512-Y4D0IgtBZfOcOUAIQTSXBKoNGfY0REGqHJG6+Q81vNippW5YlKjHFj4soMxamKK1NXHUWuBZTLdU3Km+L/pcHw=="], + + "eslint-compat-utils": ["eslint-compat-utils@0.5.1", "", { "dependencies": { "semver": "^7.5.4" }, "peerDependencies": { "eslint": ">=6.0.0" } }, "sha512-3z3vFexKIEnjHE3zCMRo6fn/e44U7T1khUjg+Hp0ZQMCigh28rALD0nPFBcGZuiLC5rLZa2ubQHDRln09JfU2Q=="], + + "eslint-plugin-es-x": ["eslint-plugin-es-x@7.8.0", "", { "dependencies": { "@eslint-community/eslint-utils": "^4.1.2", "@eslint-community/regexpp": "^4.11.0", "eslint-compat-utils": "^0.5.1" }, "peerDependencies": { "eslint": ">=8" } }, "sha512-7Ds8+wAAoV3T+LAKeu39Y5BzXCrGKrcISfgKEqTS4BDN8SFEDQd0S43jiQ8vIa3wUKD07qitZdfzlenSi8/0qQ=="], + + "eslint-plugin-jsdoc": ["eslint-plugin-jsdoc@48.11.0", "", { "dependencies": { "@es-joy/jsdoccomment": "~0.46.0", "are-docs-informative": "^0.0.2", "comment-parser": "1.4.1", "debug": "^4.3.5", "escape-string-regexp": "^4.0.0", "espree": "^10.1.0", "esquery": "^1.6.0", "parse-imports": "^2.1.1", "semver": "^7.6.3", "spdx-expression-parse": "^4.0.0", "synckit": "^0.9.1" }, "peerDependencies": { "eslint": "^7.0.0 || ^8.0.0 || ^9.0.0" } }, "sha512-d12JHJDPNo7IFwTOAItCeJY1hcqoIxE0lHA8infQByLilQ9xkqrRa6laWCnsuCrf+8rUnvxXY1XuTbibRBNylA=="], + + "eslint-plugin-n": ["eslint-plugin-n@17.10.2", "", { "dependencies": { "@eslint-community/eslint-utils": "^4.4.0", "enhanced-resolve": "^5.17.0", "eslint-plugin-es-x": "^7.5.0", "get-tsconfig": "^4.7.0", "globals": "^15.8.0", "ignore": "^5.2.4", "minimatch": "^9.0.5", "semver": "^7.5.3" }, "peerDependencies": { "eslint": ">=8.23.0" } }, "sha512-e+s4eAf5NtJaxPhTNu3qMO0Iz40WANS93w9LQgYcvuljgvDmWi/a3rh+OrNyMHeng6aOWGJO0rCg5lH4zi8yTw=="], + + "eslint-plugin-promise": ["eslint-plugin-promise@7.1.0", "", { "peerDependencies": { "eslint": "^7.0.0 || ^8.0.0 || ^9.0.0" } }, "sha512-8trNmPxdAy3W620WKDpaS65NlM5yAumod6XeC4LOb+jxlkG4IVcp68c6dXY2ev+uT4U1PtG57YDV6EGAXN0GbQ=="], + + "eslint-plugin-unicorn": ["eslint-plugin-unicorn@55.0.0", "", { "dependencies": { "@babel/helper-validator-identifier": "^7.24.5", "@eslint-community/eslint-utils": "^4.4.0", "ci-info": "^4.0.0", "clean-regexp": "^1.0.0", "core-js-compat": "^3.37.0", "esquery": "^1.5.0", "globals": "^15.7.0", "indent-string": "^4.0.0", "is-builtin-module": "^3.2.1", "jsesc": "^3.0.2", "pluralize": "^8.0.0", "read-pkg-up": "^7.0.1", "regexp-tree": "^0.1.27", "regjsparser": "^0.10.0", "semver": "^7.6.1", "strip-indent": "^3.0.0" }, "peerDependencies": { "eslint": ">=8.56.0" } }, "sha512-n3AKiVpY2/uDcGrS3+QsYDkjPfaOrNrsfQxU9nt5nitd9KuvVXrfAvgCO9DYPSfap+Gqjw9EOrXIsBp5tlHZjA=="], + + "eslint-plugin-vue": ["eslint-plugin-vue@9.28.0", "", { "dependencies": { "@eslint-community/eslint-utils": "^4.4.0", "globals": "^13.24.0", "natural-compare": "^1.4.0", "nth-check": "^2.1.1", "postcss-selector-parser": "^6.0.15", "semver": "^7.6.3", "vue-eslint-parser": "^9.4.3", "xml-name-validator": "^4.0.0" }, "peerDependencies": { "eslint": "^6.2.0 || ^7.0.0 || ^8.0.0 || ^9.0.0" } }, "sha512-ShrihdjIhOTxs+MfWun6oJWuk+g/LAhN+CiuOl/jjkG3l0F2AuK5NMTaWqyvBgkFtpYmyks6P4603mLmhNJW8g=="], + + "eslint-scope": ["eslint-scope@8.0.2", "", { "dependencies": { "esrecurse": "^4.3.0", "estraverse": "^5.2.0" } }, "sha512-6E4xmrTw5wtxnLA5wYL3WDfhZ/1bUBGOXV0zQvVRDOtrR8D0p6W7fs3JweNYhwRYeGvd/1CKX2se0/2s7Q/nJA=="], + + "eslint-visitor-keys": ["eslint-visitor-keys@4.0.0", "", {}, "sha512-OtIRv/2GyiF6o/d8K7MYKKbXrOUBIK6SfkIRM4Z0dY3w+LiQ0vy3F57m0Z71bjbyeiWFiHJ8brqnmE6H6/jEuw=="], + + "espree": ["espree@10.1.0", "", { "dependencies": { "acorn": "^8.12.0", "acorn-jsx": "^5.3.2", "eslint-visitor-keys": "^4.0.0" } }, "sha512-M1M6CpiE6ffoigIOWYO9UDP8TMUw9kqb21tf+08IgDYjCsOvCuDt4jQcZmoYxx+w7zlKw9/N0KXfto+I8/FrXA=="], + + "esquery": ["esquery@1.6.0", "", { "dependencies": { "estraverse": "^5.1.0" } }, "sha512-ca9pw9fomFcKPvFLXhBKUK90ZvGibiGOvRJNbjljY7s7uq/5YO4BOzcYtJqExdx99rF6aAcnRxHmcUHcz6sQsg=="], + + "esrecurse": ["esrecurse@4.3.0", "", { "dependencies": { "estraverse": "^5.2.0" } }, "sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag=="], + + "estraverse": ["estraverse@5.3.0", "", {}, "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA=="], + + "estree-walker": ["estree-walker@3.0.3", "", { "dependencies": { "@types/estree": "^1.0.0" } }, "sha512-7RUKfXgSMMkzt6ZuXmqapOurLGPPfgj6l9uRZ7lRGolvk0y2yocc35LdcxKC5PQZdn2DMqioAQ2NoWcrTKmm6g=="], + + "esutils": ["esutils@2.0.3", "", {}, "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g=="], + + "expect-type": ["expect-type@1.2.1", "", {}, "sha512-/kP8CAwxzLVEeFrMm4kMmy4CCDlpipyA7MYLVrdJIkV0fYF0UaigQHRsxHiuY/GEea+bh4KSv3TIlgr+2UL6bw=="], + + "exsolve": ["exsolve@1.0.5", "", {}, "sha512-pz5dvkYYKQ1AHVrgOzBKWeP4u4FRb3a6DNK2ucr0OoNwYIU4QWsJ+NM36LLzORT+z845MzKHHhpXiUF5nvQoJg=="], + + "fast-deep-equal": ["fast-deep-equal@3.1.3", "", {}, "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q=="], + + "fast-glob": ["fast-glob@3.3.2", "", { "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" } }, "sha512-oX2ruAFQwf/Orj8m737Y5adxDQO0LAB7/S5MnxCdTNDd4p6BsyIVsv9JQsATbTSq8KHRpLwIHbVlUNatxd+1Ow=="], + + "fast-json-stable-stringify": ["fast-json-stable-stringify@2.1.0", "", {}, "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw=="], + + "fast-levenshtein": ["fast-levenshtein@2.0.6", "", {}, "sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw=="], + + "fastq": ["fastq@1.17.1", "", { "dependencies": { "reusify": "^1.0.4" } }, "sha512-sRVD3lWVIXWg6By68ZN7vho9a1pQcN/WBFaAAsDDFzlJjvoGx0P8z7V1t72grFJfJhu3YPZBuu25f7Kaw2jN1w=="], + + "fdir": ["fdir@6.4.4", "", { "peerDependencies": { "picomatch": "^3 || ^4" }, "optionalPeers": ["picomatch"] }, "sha512-1NZP+GK4GfuAv3PqKvxQRDMjdSRZjnkq7KfhlNrCNNlZ0ygQFpebfrnfnq/W7fpUnAv9aGWmY1zKx7FYL3gwhg=="], + + "file-entry-cache": ["file-entry-cache@8.0.0", "", { "dependencies": { "flat-cache": "^4.0.0" } }, "sha512-XXTUwCvisa5oacNGRP9SfNtYBNAMi+RPwBFmblZEF7N7swHYQS6/Zfk7SRwx4D5j3CH211YNRco1DEMNVfZCnQ=="], + + "fill-range": ["fill-range@7.1.1", "", { "dependencies": { "to-regex-range": "^5.0.1" } }, "sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg=="], + + "find-up": ["find-up@5.0.0", "", { "dependencies": { "locate-path": "^6.0.0", "path-exists": "^4.0.0" } }, "sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng=="], + + "flat-cache": ["flat-cache@4.0.1", "", { "dependencies": { "flatted": "^3.2.9", "keyv": "^4.5.4" } }, "sha512-f7ccFPK3SXFHpx15UIGyRJ/FJQctuKZ0zVuN3frBo4HnK3cay9VEW0R6yPYFHC0AgqhukPzKjq22t5DmAyqGyw=="], + + "flatted": ["flatted@3.3.1", "", {}, "sha512-X8cqMLLie7KsNUDSdzeN8FYK9rEt4Dt67OsG/DNGnYTSDBG4uFAJFBnUeiV+zCVAvwFy56IjM9sH51jVaEhNxw=="], + + "fsevents": ["fsevents@2.3.3", "", { "os": "darwin" }, "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw=="], + + "function-bind": ["function-bind@1.1.2", "", {}, "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA=="], + + "get-tsconfig": ["get-tsconfig@4.8.0", "", { "dependencies": { "resolve-pkg-maps": "^1.0.0" } }, "sha512-Pgba6TExTZ0FJAn1qkJAjIeKoDJ3CsI2ChuLohJnZl/tTU8MVrq3b+2t5UOPfRa4RMsorClBjJALkJUMjG1PAw=="], + + "glob-parent": ["glob-parent@6.0.2", "", { "dependencies": { "is-glob": "^4.0.3" } }, "sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A=="], + + "globals": ["globals@15.9.0", "", {}, "sha512-SmSKyLLKFbSr6rptvP8izbyxJL4ILwqO9Jg23UA0sDlGlu58V59D1//I3vlc0KJphVdUR7vMjHIplYnzBxorQA=="], + + "graceful-fs": ["graceful-fs@4.2.11", "", {}, "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ=="], + + "graphemer": ["graphemer@1.4.0", "", {}, "sha512-EtKwoO6kxCL9WO5xipiHTZlSzBm7WLT627TqC/uVRd0HKmq8NXyebnNYxDoBi7wt8eTWrUrKXCOVaFq9x1kgag=="], + + "has-flag": ["has-flag@4.0.0", "", {}, "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ=="], + + "hasown": ["hasown@2.0.2", "", { "dependencies": { "function-bind": "^1.1.2" } }, "sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ=="], + + "hookable": ["hookable@5.5.3", "", {}, "sha512-Yc+BQe8SvoXH1643Qez1zqLRmbA5rCL+sSmk6TVos0LWVfNIB7PGncdlId77WzLGSIB5KaWgTaNTs2lNVEI6VQ=="], + + "hosted-git-info": ["hosted-git-info@2.8.9", "", {}, "sha512-mxIDAb9Lsm6DoOJ7xH+5+X4y1LU/4Hi50L9C5sIswK3JzULS4bwk1FvjdBgvYR4bzT4tuUQiC15FE2f5HbLvYw=="], + + "ignore": ["ignore@5.3.2", "", {}, "sha512-hsBTNUqQTDwkWtcdYI2i06Y/nUBEsNEDJKjWdigLvegy8kDuJAS8uRlpkkcQpyEXL0Z/pjDy5HBmMjRCJ2gq+g=="], + + "import-fresh": ["import-fresh@3.3.0", "", { "dependencies": { "parent-module": "^1.0.0", "resolve-from": "^4.0.0" } }, "sha512-veYYhQa+D1QBKznvhUHxb8faxlrwUnxseDAbAp457E0wLNio2bOSKnjYDhMj+YiAq61xrMGhQk9iXVk5FzgQMw=="], + + "imurmurhash": ["imurmurhash@0.1.4", "", {}, "sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA=="], + + "indent-string": ["indent-string@4.0.0", "", {}, "sha512-EdDDZu4A2OyIK7Lr/2zG+w5jmbuk1DVBnEwREQvBzspBJkCEbRa8GxU1lghYcaGJCnRWibjDXlq779X1/y5xwg=="], + + "is-arrayish": ["is-arrayish@0.2.1", "", {}, "sha512-zz06S8t0ozoDXMG+ube26zeCTNXcKIPJZJi8hBrF4idCLms4CG9QtK7qBl1boi5ODzFpjswb5JPmHCbMpjaYzg=="], + + "is-builtin-module": ["is-builtin-module@3.2.1", "", { "dependencies": { "builtin-modules": "^3.3.0" } }, "sha512-BSLE3HnV2syZ0FK0iMA/yUGplUeMmNz4AW5fnTunbCIqZi4vG3WjJT9FHMy5D69xmAYBHXQhJdALdpwVxV501A=="], + + "is-core-module": ["is-core-module@2.15.1", "", { "dependencies": { "hasown": "^2.0.2" } }, "sha512-z0vtXSwucUJtANQWldhbtbt7BnL0vxiFjIdDLAatwhDYty2bad6s+rijD6Ri4YuYJubLzIJLUidCh09e1djEVQ=="], + + "is-extglob": ["is-extglob@2.1.1", "", {}, "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ=="], + + "is-glob": ["is-glob@4.0.3", "", { "dependencies": { "is-extglob": "^2.1.1" } }, "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg=="], + + "is-number": ["is-number@7.0.0", "", {}, "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng=="], + + "is-path-inside": ["is-path-inside@3.0.3", "", {}, "sha512-Fd4gABb+ycGAmKou8eMftCupSir5lRxqf4aD/vd0cD2qc4HL07OjCeuHMr8Ro4CoMaeCKDB0/ECBOVWjTwUvPQ=="], + + "isexe": ["isexe@2.0.0", "", {}, "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw=="], + + "itty-router": ["itty-router@5.0.18", "", {}, "sha512-mK3ReOt4ARAGy0V0J7uHmArG2USN2x0zprZ+u+YgmeRjXTDbaowDy3kPcsmQY6tH+uHhDgpWit9Vqmv/4rTXwA=="], + + "jiti": ["jiti@2.4.2", "", { "bin": { "jiti": "lib/jiti-cli.mjs" } }, "sha512-rg9zJN+G4n2nfJl5MW3BMygZX56zKPNVEYYqq7adpmMh4Jn2QNEwhvQlFy6jPVdcod7txZtKHWnyZiA3a0zP7A=="], + + "js-tokens": ["js-tokens@9.0.1", "", {}, "sha512-mxa9E9ITFOt0ban3j6L5MpjwegGz6lBQmM1IJkWeBZGcMxto50+eWdjC/52xDbS2vy0k7vIMK0Fe2wfL9OQSpQ=="], + + "js-yaml": ["js-yaml@4.1.0", "", { "dependencies": { "argparse": "^2.0.1" }, "bin": { "js-yaml": "bin/js-yaml.js" } }, "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA=="], + + "jsdoc-type-pratt-parser": ["jsdoc-type-pratt-parser@4.0.0", "", {}, "sha512-YtOli5Cmzy3q4dP26GraSOeAhqecewG04hoO8DY56CH4KJ9Fvv5qKWUCCo3HZob7esJQHCv6/+bnTy72xZZaVQ=="], + + "jsesc": ["jsesc@3.0.2", "", { "bin": { "jsesc": "bin/jsesc" } }, "sha512-xKqzzWXDttJuOcawBt4KnKHHIf5oQ/Cxax+0PWFG+DFDgHNAdi+TXECADI+RYiFUMmx8792xsMbbgXj4CwnP4g=="], + + "json-buffer": ["json-buffer@3.0.1", "", {}, "sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ=="], + + "json-parse-even-better-errors": ["json-parse-even-better-errors@2.3.1", "", {}, "sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w=="], + + "json-schema-traverse": ["json-schema-traverse@0.4.1", "", {}, "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg=="], + + "json-stable-stringify-without-jsonify": ["json-stable-stringify-without-jsonify@1.0.1", "", {}, "sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw=="], + + "keyv": ["keyv@4.5.4", "", { "dependencies": { "json-buffer": "3.0.1" } }, "sha512-oxVHkHR/EJf2CNXnWxRLW6mg7JyCCUcG0DtEGmL2ctUo1PNTin1PUil+r/+4r5MpVgC/fn1kjsx7mjSujKqIpw=="], + + "levn": ["levn@0.4.1", "", { "dependencies": { "prelude-ls": "^1.2.1", "type-check": "~0.4.0" } }, "sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ=="], + + "lines-and-columns": ["lines-and-columns@1.2.4", "", {}, "sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg=="], + + "locate-path": ["locate-path@6.0.0", "", { "dependencies": { "p-locate": "^5.0.0" } }, "sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw=="], + + "lodash": ["lodash@4.17.21", "", {}, "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg=="], + + "lodash.merge": ["lodash.merge@4.6.2", "", {}, "sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ=="], + + "loupe": ["loupe@3.1.3", "", {}, "sha512-kkIp7XSkP78ZxJEsSxW3712C6teJVoeHHwgo9zJ380de7IYyJ2ISlxojcH2pC5OFLewESmnRi/+XCDIEEVyoug=="], + + "magic-string": ["magic-string@0.30.17", "", { "dependencies": { "@jridgewell/sourcemap-codec": "^1.5.0" } }, "sha512-sNPKHvyjVf7gyjwS4xGTaW/mCnF8wnjtifKBEhxfZ7E/S8tQ0rssrwGNn6q8JH/ohItJfSQp9mBtQYuTlH5QnA=="], + + "merge2": ["merge2@1.4.1", "", {}, "sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg=="], + + "micromatch": ["micromatch@4.0.8", "", { "dependencies": { "braces": "^3.0.3", "picomatch": "^2.3.1" } }, "sha512-PXwfBhYu0hBCPw8Dn0E+WDYb7af3dSLVWKi3HGv84IdF4TyFoC0ysxFd0Goxw7nSv4T/PzEJQxsYsEiFCKo2BA=="], + + "min-indent": ["min-indent@1.0.1", "", {}, "sha512-I9jwMn07Sy/IwOj3zVkVik2JTvgpaykDZEigL6Rx6N9LbMywwUSMtxET+7lVoDLLd3O3IXwJwvuuns8UB/HeAg=="], + + "minimatch": ["minimatch@3.1.2", "", { "dependencies": { "brace-expansion": "^1.1.7" } }, "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw=="], + + "mri": ["mri@1.2.0", "", {}, "sha512-tzzskb3bG8LvYGFF/mDTpq3jpI6Q9wc3LEmBaghu+DdCssd1FakN7Bc0hVNmEyGq1bq3RgfkCb3cmQLpNPOroA=="], + + "ms": ["ms@2.1.2", "", {}, "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w=="], + + "nanoid": ["nanoid@3.3.7", "", { "bin": { "nanoid": "bin/nanoid.cjs" } }, "sha512-eSRppjcPIatRIMC1U6UngP8XFcz8MQWGQdt1MTBQ7NaAmvXDfvNxbvWV3x2y6CdEUciCSsDHDQZbhYaB8QEo2g=="], + + "natural-compare": ["natural-compare@1.4.0", "", {}, "sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw=="], + + "node-releases": ["node-releases@2.0.18", "", {}, "sha512-d9VeXT4SJ7ZeOqGX6R5EM022wpL+eWPooLI+5UpWn2jCT1aosUQEhQP214x33Wkwx3JQMvIm+tIoVOdodFS40g=="], + + "normalize-package-data": ["normalize-package-data@2.5.0", "", { "dependencies": { "hosted-git-info": "^2.1.4", "resolve": "^1.10.0", "semver": "2 || 3 || 4 || 5", "validate-npm-package-license": "^3.0.1" } }, "sha512-/5CMN3T0R4XTj4DcGaexo+roZSdSFW/0AOOTROrjxzCG1wrWXEsGbRKevjlIL+ZDE4sZlJr5ED4YW0yqmkK+eA=="], + + "nth-check": ["nth-check@2.1.1", "", { "dependencies": { "boolbase": "^1.0.0" } }, "sha512-lqjrjmaOoAnWfMmBPL+XNnynZh2+swxiX3WUE0s4yEHI6m+AwrK2UZOimIRl3X/4QctVqS8AiZjFqyOGrMXb/w=="], + + "optionator": ["optionator@0.9.4", "", { "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" } }, "sha512-6IpQ7mKUxRcZNLIObR0hz7lxsapSSIYNZJwXPGeF0mTVqGKFIXj1DQcMoT22S3ROcLyY/rz0PWaWZ9ayWmad9g=="], + + "p-limit": ["p-limit@3.1.0", "", { "dependencies": { "yocto-queue": "^0.1.0" } }, "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ=="], + + "p-locate": ["p-locate@5.0.0", "", { "dependencies": { "p-limit": "^3.0.2" } }, "sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw=="], + + "p-try": ["p-try@2.2.0", "", {}, "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ=="], + + "package-manager-detector": ["package-manager-detector@1.3.0", "", {}, "sha512-ZsEbbZORsyHuO00lY1kV3/t72yp6Ysay6Pd17ZAlNGuGwmWDLCJxFpRs0IzfXfj1o4icJOkUEioexFHzyPurSQ=="], + + "parent-module": ["parent-module@1.0.1", "", { "dependencies": { "callsites": "^3.0.0" } }, "sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g=="], + + "parse-imports": ["parse-imports@2.1.1", "", { "dependencies": { "es-module-lexer": "^1.5.3", "slashes": "^3.0.12" } }, "sha512-TDT4HqzUiTMO1wJRwg/t/hYk8Wdp3iF/ToMIlAoVQfL1Xs/sTxq1dKWSMjMbQmIarfWKymOyly40+zmPHXMqCA=="], + + "parse-json": ["parse-json@5.2.0", "", { "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" } }, "sha512-ayCKvm/phCGxOkYRSCM82iDwct8/EonSEgCSxWxD7ve6jHggsFl4fZVQBPRNgQoKiuV/odhFrGzQXZwbifC8Rg=="], + + "path-exists": ["path-exists@4.0.0", "", {}, "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w=="], + + "path-key": ["path-key@3.1.1", "", {}, "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q=="], + + "path-parse": ["path-parse@1.0.7", "", {}, "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw=="], + + "pathe": ["pathe@2.0.3", "", {}, "sha512-WUjGcAqP1gQacoQe+OBJsFA7Ld4DyXuUIjZ5cc75cLHvJ7dtNsTugphxIADwspS+AraAUePCKrSVtPLFj/F88w=="], + + "pathval": ["pathval@2.0.0", "", {}, "sha512-vE7JKRyES09KiunauX7nd2Q9/L7lhok4smP9RZTDeD4MVs72Dp2qNFVz39Nz5a0FVEW0BJR6C0DYrq6unoziZA=="], + + "picocolors": ["picocolors@1.1.1", "", {}, "sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA=="], + + "picomatch": ["picomatch@4.0.2", "", {}, "sha512-M7BAV6Rlcy5u+m6oPhAPFgJTzAioX/6B0DxyvDlo9l8+T3nLKbrczg2WLUyzd45L8RqfUMyGPzekbMvX2Ldkwg=="], + + "pkg-types": ["pkg-types@2.1.0", "", { "dependencies": { "confbox": "^0.2.1", "exsolve": "^1.0.1", "pathe": "^2.0.3" } }, "sha512-wmJwA+8ihJixSoHKxZJRBQG1oY8Yr9pGLzRmSsNms0iNWyHHAlZCa7mmKiFR10YPZuz/2k169JiS/inOjBCZ2A=="], + + "pluralize": ["pluralize@8.0.0", "", {}, "sha512-Nc3IT5yHzflTfbjgqWcCPpo7DaKy4FnpB0l/zCAW0Tc7jxAiuqSxHasntB3D7887LSrA93kDJ9IXovxJYxyLCA=="], + + "postcss": ["postcss@8.4.45", "", { "dependencies": { "nanoid": "^3.3.7", "picocolors": "^1.0.1", "source-map-js": "^1.2.0" } }, "sha512-7KTLTdzdZZYscUc65XmjFiB73vBhBfbPztCYdUNvlaso9PrzjzcmjqBPR0lNGkcVlcO4BjiO5rK/qNz+XAen1Q=="], + + "postcss-selector-parser": ["postcss-selector-parser@6.1.2", "", { "dependencies": { "cssesc": "^3.0.0", "util-deprecate": "^1.0.2" } }, "sha512-Q8qQfPiZ+THO/3ZrOrO0cJJKfpYCagtMUkXbnEfmgUjwXg6z/WBeOyS9APBBPCTSiDV+s4SwQGu8yFsiMRIudg=="], + + "prelude-ls": ["prelude-ls@1.2.1", "", {}, "sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g=="], + + "publint": ["publint@0.3.12", "", { "dependencies": { "@publint/pack": "^0.1.2", "package-manager-detector": "^1.1.0", "picocolors": "^1.1.1", "sade": "^1.8.1" }, "bin": { "publint": "src/cli.js" } }, "sha512-1w3MMtL9iotBjm1mmXtG3Nk06wnq9UhGNRpQ2j6n1Zq7YAD6gnxMMZMIxlRPAydVjVbjSm+n0lhwqsD1m4LD5w=="], + + "punycode": ["punycode@2.3.1", "", {}, "sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg=="], + + "quansync": ["quansync@0.2.10", "", {}, "sha512-t41VRkMYbkHyCYmOvx/6URnN80H7k4X0lLdBMGsz+maAwrJQYB1djpV6vHrQIBE0WBSGqhtEHrK9U3DWWH8v7A=="], + + "queue-microtask": ["queue-microtask@1.2.3", "", {}, "sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A=="], + + "read-pkg": ["read-pkg@5.2.0", "", { "dependencies": { "@types/normalize-package-data": "^2.4.0", "normalize-package-data": "^2.5.0", "parse-json": "^5.0.0", "type-fest": "^0.6.0" } }, "sha512-Ug69mNOpfvKDAc2Q8DRpMjjzdtrnv9HcSMX+4VsZxD1aZ6ZzrIE7rlzXBtWTyhULSMKg076AW6WR5iZpD0JiOg=="], + + "read-pkg-up": ["read-pkg-up@7.0.1", "", { "dependencies": { "find-up": "^4.1.0", "read-pkg": "^5.2.0", "type-fest": "^0.8.1" } }, "sha512-zK0TB7Xd6JpCLmlLmufqykGE+/TlOePD6qKClNW7hHDKFh/J7/7gCWGR7joEQEW1bKq3a3yUZSObOoWLFQ4ohg=="], + + "readdirp": ["readdirp@4.1.2", "", {}, "sha512-GDhwkLfywWL2s6vEjyhri+eXmfH6j1L7JE27WhqLeYzoh/A3DBaYGEj2H/HFZCn/kMfim73FXxEJTw06WtxQwg=="], + + "regexp-tree": ["regexp-tree@0.1.27", "", { "bin": { "regexp-tree": "bin/regexp-tree" } }, "sha512-iETxpjK6YoRWJG5o6hXLwvjYAoW+FEZn9os0PD/b6AP6xQwsa/Y7lCVgIixBbUPMfhu+i2LtdeAqVTgGlQarfA=="], + + "regjsparser": ["regjsparser@0.10.0", "", { "dependencies": { "jsesc": "~0.5.0" }, "bin": { "regjsparser": "bin/parser" } }, "sha512-qx+xQGZVsy55CH0a1hiVwHmqjLryfh7wQyF5HO07XJ9f7dQMY/gPQHhlyDkIzJKC+x2fUCpCcUODUUUFrm7SHA=="], + + "resolve": ["resolve@1.22.8", "", { "dependencies": { "is-core-module": "^2.13.0", "path-parse": "^1.0.7", "supports-preserve-symlinks-flag": "^1.0.0" }, "bin": { "resolve": "bin/resolve" } }, "sha512-oKWePCxqpd6FlLvGV1VU0x7bkPmmCNolxzjMf4NczoDnQcIWrAF+cPtZn5i6n+RfD2d9i0tzpKnG6Yk168yIyw=="], + + "resolve-from": ["resolve-from@4.0.0", "", {}, "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g=="], + + "resolve-pkg-maps": ["resolve-pkg-maps@1.0.0", "", {}, "sha512-seS2Tj26TBVOC2NIc2rOe2y2ZO7efxITtLZcGSOnHHNOQ7CkiUBfw0Iw2ck6xkIhPwLhKNLS8BO+hEpngQlqzw=="], + + "reusify": ["reusify@1.0.4", "", {}, "sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw=="], + + "rolldown": ["rolldown@1.0.0-beta.9-commit.51df2b7", "", { "dependencies": { "@oxc-project/types": "0.71.0", "@rolldown/pluginutils": "1.0.0-beta.9-commit.51df2b7", "ansis": "^4.0.0" }, "optionalDependencies": { "@rolldown/binding-darwin-arm64": "1.0.0-beta.9-commit.51df2b7", "@rolldown/binding-darwin-x64": "1.0.0-beta.9-commit.51df2b7", "@rolldown/binding-freebsd-x64": "1.0.0-beta.9-commit.51df2b7", "@rolldown/binding-linux-arm-gnueabihf": "1.0.0-beta.9-commit.51df2b7", "@rolldown/binding-linux-arm64-gnu": "1.0.0-beta.9-commit.51df2b7", "@rolldown/binding-linux-arm64-musl": "1.0.0-beta.9-commit.51df2b7", "@rolldown/binding-linux-x64-gnu": "1.0.0-beta.9-commit.51df2b7", "@rolldown/binding-linux-x64-musl": "1.0.0-beta.9-commit.51df2b7", "@rolldown/binding-wasm32-wasi": "1.0.0-beta.9-commit.51df2b7", "@rolldown/binding-win32-arm64-msvc": "1.0.0-beta.9-commit.51df2b7", "@rolldown/binding-win32-ia32-msvc": "1.0.0-beta.9-commit.51df2b7", "@rolldown/binding-win32-x64-msvc": "1.0.0-beta.9-commit.51df2b7" }, "peerDependencies": { "@oxc-project/runtime": "0.71.0" }, "optionalPeers": ["@oxc-project/runtime"], "bin": { "rolldown": "bin/cli.mjs" } }, "sha512-jsHj8vikf9qezv+Ct2sL1gHgIXVq+3NATCcY24lnJNdHvmc2t9aRjuMp5nUCzZ4aFTpRFJmucSOgqfvruo4/ew=="], + + "rolldown-plugin-dts": ["rolldown-plugin-dts@0.13.4", "", { "dependencies": { "@babel/generator": "^7.27.1", "@babel/parser": "^7.27.2", "@babel/types": "^7.27.1", "ast-kit": "^2.0.0", "birpc": "^2.3.0", "debug": "^4.4.1", "dts-resolver": "^2.0.1", "get-tsconfig": "^4.10.1" }, "peerDependencies": { "rolldown": "^1.0.0-beta.9", "typescript": "^5.0.0", "vue-tsc": "~2.2.0" }, "optionalPeers": ["typescript", "vue-tsc"] }, "sha512-2+3GnKj6A3wKfyomUKfONRHjgKE85X4PcgW1b84KkHvuN3mUuUiOMseLKafFLMF6NkqQPAJ3FErwtC4HuwIswg=="], + + "rollup": ["rollup@4.21.2", "", { "dependencies": { "@types/estree": "1.0.5" }, "optionalDependencies": { "@rollup/rollup-android-arm-eabi": "4.21.2", "@rollup/rollup-android-arm64": "4.21.2", "@rollup/rollup-darwin-arm64": "4.21.2", "@rollup/rollup-darwin-x64": "4.21.2", "@rollup/rollup-linux-arm-gnueabihf": "4.21.2", "@rollup/rollup-linux-arm-musleabihf": "4.21.2", "@rollup/rollup-linux-arm64-gnu": "4.21.2", "@rollup/rollup-linux-arm64-musl": "4.21.2", "@rollup/rollup-linux-powerpc64le-gnu": "4.21.2", "@rollup/rollup-linux-riscv64-gnu": "4.21.2", "@rollup/rollup-linux-s390x-gnu": "4.21.2", "@rollup/rollup-linux-x64-gnu": "4.21.2", "@rollup/rollup-linux-x64-musl": "4.21.2", "@rollup/rollup-win32-arm64-msvc": "4.21.2", "@rollup/rollup-win32-ia32-msvc": "4.21.2", "@rollup/rollup-win32-x64-msvc": "4.21.2", "fsevents": "~2.3.2" }, "bin": { "rollup": "dist/bin/rollup" } }, "sha512-e3TapAgYf9xjdLvKQCkQTnbTKd4a6jwlpQSJJFokHGaX2IVjoEqkIIhiQfqsi0cdwlOD+tQGuOd5AJkc5RngBw=="], + + "run-parallel": ["run-parallel@1.2.0", "", { "dependencies": { "queue-microtask": "^1.2.2" } }, "sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA=="], + + "sade": ["sade@1.8.1", "", { "dependencies": { "mri": "^1.1.0" } }, "sha512-xal3CZX1Xlo/k4ApwCFrHVACi9fBqJ7V+mwhBsuf/1IOKbBy098Fex+Wa/5QMubw09pSZ/u8EY8PWgevJsXp1A=="], + + "semver": ["semver@7.7.2", "", { "bin": { "semver": "bin/semver.js" } }, "sha512-RF0Fw+rO5AMf9MAyaRXI4AV0Ulj5lMHqVxxdSgiVbixSCXoEmmX/jk0CuJw4+3SqroYO9VoUh+HcuJivvtJemA=="], + + "shebang-command": ["shebang-command@2.0.0", "", { "dependencies": { "shebang-regex": "^3.0.0" } }, "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA=="], + + "shebang-regex": ["shebang-regex@3.0.0", "", {}, "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A=="], + + "siginfo": ["siginfo@2.0.0", "", {}, "sha512-ybx0WO1/8bSBLEWXZvEd7gMW3Sn3JFlW3TvX1nREbDLRNQNaeNN8WK0meBwPdAaOI7TtRRRJn/Es1zhrrCHu7g=="], + + "slashes": ["slashes@3.0.12", "", {}, "sha512-Q9VME8WyGkc7pJf6QEkj3wE+2CnvZMI+XJhwdTPR8Z/kWQRXi7boAWLDibRPyHRTUTPx5FaU7MsyrjI3yLB4HA=="], + + "source-map-js": ["source-map-js@1.2.0", "", {}, "sha512-itJW8lvSA0TXEphiRoawsCksnlf8SyvmFzIhltqAHluXd88pkCd+cXJVHTDwdCr0IzwptSm035IHQktUu1QUMg=="], + + "spdx-correct": ["spdx-correct@3.2.0", "", { "dependencies": { "spdx-expression-parse": "^3.0.0", "spdx-license-ids": "^3.0.0" } }, "sha512-kN9dJbvnySHULIluDHy32WHRUu3Og7B9sbY7tsFLctQkIqnMh3hErYgdMjTYuqmcXX+lK5T1lnUt3G7zNswmZA=="], + + "spdx-exceptions": ["spdx-exceptions@2.5.0", "", {}, "sha512-PiU42r+xO4UbUS1buo3LPJkjlO7430Xn5SVAhdpzzsPHsjbYVflnnFdATgabnLude+Cqu25p6N+g2lw/PFsa4w=="], + + "spdx-expression-parse": ["spdx-expression-parse@4.0.0", "", { "dependencies": { "spdx-exceptions": "^2.1.0", "spdx-license-ids": "^3.0.0" } }, "sha512-Clya5JIij/7C6bRR22+tnGXbc4VKlibKSVj2iHvVeX5iMW7s1SIQlqu699JkODJJIhh/pUu8L0/VLh8xflD+LQ=="], + + "spdx-license-ids": ["spdx-license-ids@3.0.20", "", {}, "sha512-jg25NiDV/1fLtSgEgyvVyDunvaNHbuwF9lfNV17gSmPFAlYzdfNBlLtLzXTevwkPj7DhGbmN9VnmJIgLnhvaBw=="], + + "stackback": ["stackback@0.0.2", "", {}, "sha512-1XMJE5fQo1jGH6Y/7ebnwPOBEkIEnT4QF32d5R1+VXdXveM0IBMJt8zfaxX1P3QhVwrYe+576+jkANtSS2mBbw=="], + + "std-env": ["std-env@3.9.0", "", {}, "sha512-UGvjygr6F6tpH7o2qyqR6QYpwraIjKSdtzyBdyytFOHmPZY917kwdwLG0RbOjWOnKmnm3PeHjaoLLMie7kPLQw=="], + + "strip-ansi": ["strip-ansi@6.0.1", "", { "dependencies": { "ansi-regex": "^5.0.1" } }, "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A=="], + + "strip-indent": ["strip-indent@3.0.0", "", { "dependencies": { "min-indent": "^1.0.0" } }, "sha512-laJTa3Jb+VQpaC6DseHhF7dXVqHTfJPCRDaEbid/drOhgitgYku/letMUqOXFoWV0zIIUbjpdH2t+tYj4bQMRQ=="], + + "strip-json-comments": ["strip-json-comments@3.1.1", "", {}, "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig=="], + + "supports-color": ["supports-color@7.2.0", "", { "dependencies": { "has-flag": "^4.0.0" } }, "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw=="], + + "supports-preserve-symlinks-flag": ["supports-preserve-symlinks-flag@1.0.0", "", {}, "sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w=="], + + "synckit": ["synckit@0.9.1", "", { "dependencies": { "@pkgr/core": "^0.1.0", "tslib": "^2.6.2" } }, "sha512-7gr8p9TQP6RAHusBOSLs46F4564ZrjV8xFmw5zCmgmhGUcw2hxsShhJ6CEiHQMgPDwAQ1fWHPM0ypc4RMAig4A=="], + + "tapable": ["tapable@2.2.1", "", {}, "sha512-GNzQvQTOIP6RyTfE2Qxb8ZVlNmw0n88vp1szwWRimP02mnTsx3Wtn5qRdqY9w2XduFNUgvOwhNnQsjwCp+kqaQ=="], + + "text-table": ["text-table@0.2.0", "", {}, "sha512-N+8UisAXDGk8PFXP4HAzVR9nbfmVJ3zYLAWiTIoqC5v5isinhr+r5uaO8+7r3BMfuNIufIsA7RdpVgacC2cSpw=="], + + "tinybench": ["tinybench@2.9.0", "", {}, "sha512-0+DUvqWMValLmha6lr4kD8iAMK1HzV0/aKnCtWb9v9641TnP/MFb7Pc2bxoxQjTXAErryXVgUOfv2YqNllqGeg=="], + + "tinyexec": ["tinyexec@1.0.1", "", {}, "sha512-5uC6DDlmeqiOwCPmK9jMSdOuZTh8bU39Ys6yidB+UTt5hfZUPGAypSgFRiEp+jbi9qH40BLDvy85jIU88wKSqw=="], + + "tinyglobby": ["tinyglobby@0.2.13", "", { "dependencies": { "fdir": "^6.4.4", "picomatch": "^4.0.2" } }, "sha512-mEwzpUgrLySlveBwEVDMKk5B57bhLPYovRfPAXD5gA/98Opn0rCDj3GtLwFvCvH5RK9uPCExUROW5NjDwvqkxw=="], + + "tinypool": ["tinypool@1.0.2", "", {}, "sha512-al6n+QEANGFOMf/dmUMsuS5/r9B06uwlyNjZZql/zv8J7ybHCgoihBNORZCY2mzUuAnomQa2JdhyHKzZxPCrFA=="], + + "tinyrainbow": ["tinyrainbow@2.0.0", "", {}, "sha512-op4nsTR47R6p0vMUUoYl/a+ljLFVtlfaXkLQmqfLR1qHma1h/ysYk4hEXZ880bf2CYgTskvTa/e196Vd5dDQXw=="], + + "tinyspy": ["tinyspy@3.0.2", "", {}, "sha512-n1cw8k1k0x4pgA2+9XrOkFydTerNcJ1zWCO5Nn9scWHTD+5tp8dghT2x1uduQePZTZgd3Tupf+x9BxJjeJi77Q=="], + + "to-regex-range": ["to-regex-range@5.0.1", "", { "dependencies": { "is-number": "^7.0.0" } }, "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ=="], + + "ts-api-utils": ["ts-api-utils@1.3.0", "", { "peerDependencies": { "typescript": ">=4.2.0" } }, "sha512-UQMIo7pb8WRomKR1/+MFVLTroIvDVtMX3K6OUir8ynLyzB8Jeriont2bTAtmNPa1ekAgN7YPDyf6V+ygrdU+eQ=="], + + "tsdown": ["tsdown@0.12.2", "", { "dependencies": { "ansis": "^4.0.0", "cac": "^6.7.14", "chokidar": "^4.0.3", "debug": "^4.4.1", "diff": "^8.0.1", "empathic": "^1.1.0", "hookable": "^5.5.3", "rolldown": "1.0.0-beta.9-commit.51df2b7", "rolldown-plugin-dts": "^0.13.4", "semver": "^7.7.2", "tinyexec": "^1.0.1", "tinyglobby": "^0.2.13", "unconfig": "^7.3.2" }, "peerDependencies": { "publint": "^0.3.0", "typescript": "^5.0.0", "unplugin-lightningcss": "^0.4.0", "unplugin-unused": "^0.5.0" }, "optionalPeers": ["publint", "typescript", "unplugin-lightningcss", "unplugin-unused"], "bin": { "tsdown": "dist/run.js" } }, "sha512-JbBhVW799a1aOt1g8tNw5MGRuYm+xZWBkj9jMOdJJ6zSFT/pAewdQytgtgBemz4Wv3pmRLZNPK9YqUu1IVuIqA=="], + + "tslib": ["tslib@2.7.0", "", {}, "sha512-gLXCKdN1/j47AiHiOkJN69hJmcbGTHI0ImLmbYLHykhgeN0jVGola9yVjFgzCUklsZQMW55o+dW7IXv3RCXDzA=="], + + "type-check": ["type-check@0.4.0", "", { "dependencies": { "prelude-ls": "^1.2.1" } }, "sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew=="], + + "type-fest": ["type-fest@4.41.0", "", {}, "sha512-TeTSQ6H5YHvpqVwBRcnLDCBnDOHWYu7IvGbHT6N8AOymcr9PJGjc1GTtiWZTYg0NCgYwvnYWEkVChQAr9bjfwA=="], + + "typescript": ["typescript@5.8.3", "", { "bin": { "tsc": "bin/tsc", "tsserver": "bin/tsserver" } }, "sha512-p1diW6TqL9L07nNxvRMM7hMMw4c5XOo/1ibL4aAIGmSAt9slTE1Xgw5KWuof2uTOvCg9BY7ZRi+GaF+7sfgPeQ=="], + + "typescript-eslint": ["typescript-eslint@8.4.0", "", { "dependencies": { "@typescript-eslint/eslint-plugin": "8.4.0", "@typescript-eslint/parser": "8.4.0", "@typescript-eslint/utils": "8.4.0" } }, "sha512-67qoc3zQZe3CAkO0ua17+7aCLI0dU+sSQd1eKPGq06QE4rfQjstVXR6woHO5qQvGUa550NfGckT4tzh3b3c8Pw=="], + + "unconfig": ["unconfig@7.3.2", "", { "dependencies": { "@quansync/fs": "^0.1.1", "defu": "^6.1.4", "jiti": "^2.4.2", "quansync": "^0.2.8" } }, "sha512-nqG5NNL2wFVGZ0NA/aCFw0oJ2pxSf1lwg4Z5ill8wd7K4KX/rQbHlwbh+bjctXL5Ly1xtzHenHGOK0b+lG6JVg=="], + + "undici-types": ["undici-types@6.19.8", "", {}, "sha512-ve2KP6f/JnbPBFyobGHuerC9g1FYGn/F8n1LWTwNxCEzd6IfqTwUQcNXgEtmmQ6DlRrC1hrSrBnCZPokRrDHjw=="], + + "unplugin": ["unplugin@2.3.4", "", { "dependencies": { "acorn": "^8.14.1", "picomatch": "^4.0.2", "webpack-virtual-modules": "^0.6.2" } }, "sha512-m4PjxTurwpWfpMomp8AptjD5yj8qEZN5uQjjGM3TAs9MWWD2tXSSNNj6jGR2FoVGod4293ytyV6SwBbertfyJg=="], + + "unplugin-unused": ["unplugin-unused@0.5.0", "", { "dependencies": { "js-tokens": "^9.0.1", "picocolors": "^1.1.1", "pkg-types": "^2.1.0", "unplugin": "^2.3.2" } }, "sha512-czXny3h/P/Tl5ZOnV5tSf6kswAniHjgJF0slpzBPLkq0zGGKDYa1jgWMAdbWJNu7B1YSmBJY4zf3Q/v9w0+/cg=="], + + "update-browserslist-db": ["update-browserslist-db@1.1.0", "", { "dependencies": { "escalade": "^3.1.2", "picocolors": "^1.0.1" }, "peerDependencies": { "browserslist": ">= 4.21.0" }, "bin": { "update-browserslist-db": "cli.js" } }, "sha512-EdRAaAyk2cUE1wOf2DkEhzxqOQvFOoRJFNS6NeyJ01Gp2beMRpBAINjM2iDXE3KCuKhwnvHIQCJm6ThL2Z+HzQ=="], + + "uri-js": ["uri-js@4.4.1", "", { "dependencies": { "punycode": "^2.1.0" } }, "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg=="], + + "util-deprecate": ["util-deprecate@1.0.2", "", {}, "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw=="], + + "valibot": ["valibot@1.1.0", "", { "peerDependencies": { "typescript": ">=5" }, "optionalPeers": ["typescript"] }, "sha512-Nk8lX30Qhu+9txPYTwM0cFlWLdPFsFr6LblzqIySfbZph9+BFsAHsNvHOymEviUepeIW6KFHzpX8TKhbptBXXw=="], + + "validate-npm-package-license": ["validate-npm-package-license@3.0.4", "", { "dependencies": { "spdx-correct": "^3.0.0", "spdx-expression-parse": "^3.0.0" } }, "sha512-DpKm2Ui/xN7/HQKCtpZxoRWBhZ9Z0kqtygG8XCgNQ8ZlDnxuQmWhj566j8fN4Cu3/JmbhsDo7fcAJq4s9h27Ew=="], + + "vite": ["vite@5.4.3", "", { "dependencies": { "esbuild": "^0.21.3", "postcss": "^8.4.43", "rollup": "^4.20.0" }, "optionalDependencies": { "fsevents": "~2.3.3" }, "peerDependencies": { "@types/node": "^18.0.0 || >=20.0.0", "less": "*", "lightningcss": "^1.21.0", "sass": "*", "sass-embedded": "*", "stylus": "*", "sugarss": "*", "terser": "^5.4.0" }, "optionalPeers": ["@types/node", "less", "lightningcss", "sass", "sass-embedded", "stylus", "sugarss", "terser"], "bin": { "vite": "bin/vite.js" } }, "sha512-IH+nl64eq9lJjFqU+/yrRnrHPVTlgy42/+IzbOdaFDVlyLgI/wDlf+FCobXLX1cT0X5+7LMyH1mIy2xJdLfo8Q=="], + + "vite-node": ["vite-node@3.1.4", "", { "dependencies": { "cac": "^6.7.14", "debug": "^4.4.0", "es-module-lexer": "^1.7.0", "pathe": "^2.0.3", "vite": "^5.0.0 || ^6.0.0" }, "bin": { "vite-node": "vite-node.mjs" } }, "sha512-6enNwYnpyDo4hEgytbmc6mYWHXDHYEn0D1/rw4Q+tnHUGtKTJsn8T1YkX6Q18wI5LCrS8CTYlBaiCqxOy2kvUA=="], + + "vitest": ["vitest@3.1.4", "", { "dependencies": { "@vitest/expect": "3.1.4", "@vitest/mocker": "3.1.4", "@vitest/pretty-format": "^3.1.4", "@vitest/runner": "3.1.4", "@vitest/snapshot": "3.1.4", "@vitest/spy": "3.1.4", "@vitest/utils": "3.1.4", "chai": "^5.2.0", "debug": "^4.4.0", "expect-type": "^1.2.1", "magic-string": "^0.30.17", "pathe": "^2.0.3", "std-env": "^3.9.0", "tinybench": "^2.9.0", "tinyexec": "^0.3.2", "tinyglobby": "^0.2.13", "tinypool": "^1.0.2", "tinyrainbow": "^2.0.0", "vite": "^5.0.0 || ^6.0.0", "vite-node": "3.1.4", "why-is-node-running": "^2.3.0" }, "peerDependencies": { "@edge-runtime/vm": "*", "@types/debug": "^4.1.12", "@types/node": "^18.0.0 || ^20.0.0 || >=22.0.0", "@vitest/browser": "3.1.4", "@vitest/ui": "3.1.4", "happy-dom": "*", "jsdom": "*" }, "optionalPeers": ["@edge-runtime/vm", "@types/debug", "@types/node", "@vitest/browser", "@vitest/ui", "happy-dom", "jsdom"], "bin": { "vitest": "vitest.mjs" } }, "sha512-Ta56rT7uWxCSJXlBtKgIlApJnT6e6IGmTYxYcmxjJ4ujuZDI59GUQgVDObXXJujOmPDBYXHK1qmaGtneu6TNIQ=="], + + "vue-eslint-parser": ["vue-eslint-parser@9.4.3", "", { "dependencies": { "debug": "^4.3.4", "eslint-scope": "^7.1.1", "eslint-visitor-keys": "^3.3.0", "espree": "^9.3.1", "esquery": "^1.4.0", "lodash": "^4.17.21", "semver": "^7.3.6" }, "peerDependencies": { "eslint": ">=6.0.0" } }, "sha512-2rYRLWlIpaiN8xbPiDyXZXRgLGOtWxERV7ND5fFAv5qo1D2N9Fu9MNajBNc6o13lZ+24DAWCkQCvj4klgmcITg=="], + + "webpack-virtual-modules": ["webpack-virtual-modules@0.6.2", "", {}, "sha512-66/V2i5hQanC51vBQKPH4aI8NMAcBW59FVBs+rC7eGHupMyfn34q7rZIE+ETlJ+XTevqfUhVVBgSUNSW2flEUQ=="], + + "which": ["which@2.0.2", "", { "dependencies": { "isexe": "^2.0.0" }, "bin": { "node-which": "./bin/node-which" } }, "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA=="], + + "why-is-node-running": ["why-is-node-running@2.3.0", "", { "dependencies": { "siginfo": "^2.0.0", "stackback": "0.0.2" }, "bin": { "why-is-node-running": "cli.js" } }, "sha512-hUrmaWBdVDcxvYqnyh09zunKzROWjbZTiNy8dBEjkS7ehEDQibXJ7XvlmtbwuTclUiIyN+CyXQD4Vmko8fNm8w=="], + + "word-wrap": ["word-wrap@1.2.5", "", {}, "sha512-BN22B5eaMMI9UMtjrGd5g5eCYPpCPDUy0FJXbYsaT5zYxjFOckS53SQDE3pWkVoWpHXVb3BrYcEN4Twa55B5cA=="], + + "xml-name-validator": ["xml-name-validator@4.0.0", "", {}, "sha512-ICP2e+jsHvAj2E2lIHxa5tjXRlKDJo4IdvPvCXbXQGdzSfmSpNVyIKMvoZHjDY9DP0zV17iI85o90vRFXNccRw=="], + + "yocto-queue": ["yocto-queue@0.1.0", "", {}, "sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q=="], + + "@babel/code-frame/picocolors": ["picocolors@1.1.0", "", {}, "sha512-TQ92mBOW0l3LeMeyLV6mzy/kWr8lkd/hp3mTg7wYK7zJhuBStmGMBG0BdeDZS/dZx1IukaX6Bk11zcln25o1Aw=="], + + "@babel/highlight/chalk": ["chalk@2.4.2", "", { "dependencies": { "ansi-styles": "^3.2.1", "escape-string-regexp": "^1.0.5", "supports-color": "^5.3.0" } }, "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ=="], + + "@babel/highlight/js-tokens": ["js-tokens@4.0.0", "", {}, "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ=="], + + "@babel/highlight/picocolors": ["picocolors@1.1.0", "", {}, "sha512-TQ92mBOW0l3LeMeyLV6mzy/kWr8lkd/hp3mTg7wYK7zJhuBStmGMBG0BdeDZS/dZx1IukaX6Bk11zcln25o1Aw=="], + + "@babel/types/@babel/helper-validator-identifier": ["@babel/helper-validator-identifier@7.27.1", "", {}, "sha512-D2hP9eA+Sqx1kBZgzxZh0y1trbuU+JoDkiEwqhQ36nodYqJwyEIhPSdMNd7lOm/4io72luTPWH20Yda0xOuUow=="], + + "@eslint-community/eslint-utils/eslint-visitor-keys": ["eslint-visitor-keys@3.4.3", "", {}, "sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag=="], + + "@eslint/eslintrc/globals": ["globals@14.0.0", "", {}, "sha512-oahGvuMGQlPw/ivIYBjVSrWAfWLBeku5tpPE2fOPLi+WHffIWbuh2tCjhyQhTBPMf5E9jDEH4FOmTYgYwbKwtQ=="], + + "@typescript-eslint/typescript-estree/minimatch": ["minimatch@9.0.5", "", { "dependencies": { "brace-expansion": "^2.0.1" } }, "sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow=="], + + "@typescript-eslint/typescript-estree/semver": ["semver@7.6.3", "", { "bin": { "semver": "bin/semver.js" } }, "sha512-oVekP1cKtI+CTDvHWYFUcMtsK/00wmAEfyqKfNdARm8u1wNVhSgaX7A8d4UuIlUI5e84iEwOhs7ZPYRmzU9U6A=="], + + "@typescript-eslint/visitor-keys/eslint-visitor-keys": ["eslint-visitor-keys@3.4.3", "", {}, "sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag=="], + + "clean-regexp/escape-string-regexp": ["escape-string-regexp@1.0.5", "", {}, "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg=="], + + "eslint-compat-utils/semver": ["semver@7.6.3", "", { "bin": { "semver": "bin/semver.js" } }, "sha512-oVekP1cKtI+CTDvHWYFUcMtsK/00wmAEfyqKfNdARm8u1wNVhSgaX7A8d4UuIlUI5e84iEwOhs7ZPYRmzU9U6A=="], + + "eslint-plugin-jsdoc/semver": ["semver@7.6.3", "", { "bin": { "semver": "bin/semver.js" } }, "sha512-oVekP1cKtI+CTDvHWYFUcMtsK/00wmAEfyqKfNdARm8u1wNVhSgaX7A8d4UuIlUI5e84iEwOhs7ZPYRmzU9U6A=="], + + "eslint-plugin-n/minimatch": ["minimatch@9.0.5", "", { "dependencies": { "brace-expansion": "^2.0.1" } }, "sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow=="], + + "eslint-plugin-n/semver": ["semver@7.6.3", "", { "bin": { "semver": "bin/semver.js" } }, "sha512-oVekP1cKtI+CTDvHWYFUcMtsK/00wmAEfyqKfNdARm8u1wNVhSgaX7A8d4UuIlUI5e84iEwOhs7ZPYRmzU9U6A=="], + + "eslint-plugin-unicorn/semver": ["semver@7.6.3", "", { "bin": { "semver": "bin/semver.js" } }, "sha512-oVekP1cKtI+CTDvHWYFUcMtsK/00wmAEfyqKfNdARm8u1wNVhSgaX7A8d4UuIlUI5e84iEwOhs7ZPYRmzU9U6A=="], + + "eslint-plugin-vue/globals": ["globals@13.24.0", "", { "dependencies": { "type-fest": "^0.20.2" } }, "sha512-AhO5QUcj8llrbG09iWhPU2B204J1xnPeL8kQmVorSsy+Sjj1sk8gIyh6cUocGmH4L0UuhAJy+hJMRA4mgA4mFQ=="], + + "eslint-plugin-vue/semver": ["semver@7.6.3", "", { "bin": { "semver": "bin/semver.js" } }, "sha512-oVekP1cKtI+CTDvHWYFUcMtsK/00wmAEfyqKfNdARm8u1wNVhSgaX7A8d4UuIlUI5e84iEwOhs7ZPYRmzU9U6A=="], + + "fast-glob/glob-parent": ["glob-parent@5.1.2", "", { "dependencies": { "is-glob": "^4.0.1" } }, "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow=="], + + "micromatch/picomatch": ["picomatch@2.3.1", "", {}, "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA=="], + + "normalize-package-data/semver": ["semver@5.7.2", "", { "bin": { "semver": "bin/semver" } }, "sha512-cBznnQ9KjJqU67B52RMC65CMarK2600WFnbkcaiwWq3xy/5haFJlshgnpjovMVJ+Hff49d8GEn0b87C5pDQ10g=="], + + "parse-imports/es-module-lexer": ["es-module-lexer@1.5.4", "", {}, "sha512-MVNK56NiMrOwitFB7cqDwq0CQutbw+0BvLshJSse0MUNU+y1FC3bUS/AQg7oUng+/wKrrki7JfmwtVHkVfPLlw=="], + + "postcss/picocolors": ["picocolors@1.1.0", "", {}, "sha512-TQ92mBOW0l3LeMeyLV6mzy/kWr8lkd/hp3mTg7wYK7zJhuBStmGMBG0BdeDZS/dZx1IukaX6Bk11zcln25o1Aw=="], + + "read-pkg/type-fest": ["type-fest@0.6.0", "", {}, "sha512-q+MB8nYR1KDLrgr4G5yemftpMC7/QLqVndBmEEdqzmNj5dcFOO4Oo8qlwZE3ULT3+Zim1F8Kq4cBnikNhlCMlg=="], + + "read-pkg-up/find-up": ["find-up@4.1.0", "", { "dependencies": { "locate-path": "^5.0.0", "path-exists": "^4.0.0" } }, "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw=="], + + "read-pkg-up/type-fest": ["type-fest@0.8.1", "", {}, "sha512-4dbzIzqvjtgiM5rw1k5rEHtBANKmdudhGyBEajN01fEyhaAIhsoKNy6y7+IN93IfpFtwY9iqi7kD+xwKhQsNJA=="], + + "regjsparser/jsesc": ["jsesc@0.5.0", "", { "bin": { "jsesc": "bin/jsesc" } }, "sha512-uZz5UnB7u4T9LvwmFqXii7pZSouaRPorGs5who1Ip7VO0wxanFvBL7GkM6dTHlgX+jhBApRetaWpnDabOeTcnA=="], + + "rolldown-plugin-dts/debug": ["debug@4.4.1", "", { "dependencies": { "ms": "^2.1.3" } }, "sha512-KcKCqiftBJcZr++7ykoDIEwSa3XWowTfNPo92BYxjXiyYEVrUQh2aLyhxBCwww+heortUFxEJYcRzosstTEBYQ=="], + + "rolldown-plugin-dts/get-tsconfig": ["get-tsconfig@4.10.1", "", { "dependencies": { "resolve-pkg-maps": "^1.0.0" } }, "sha512-auHyJ4AgMz7vgS8Hp3N6HXSmlMdUyhSUrfBF16w153rxtLIEOE+HGqaBppczZvnHLqQJfiHotCYpNhl0lUROFQ=="], + + "spdx-correct/spdx-expression-parse": ["spdx-expression-parse@3.0.1", "", { "dependencies": { "spdx-exceptions": "^2.1.0", "spdx-license-ids": "^3.0.0" } }, "sha512-cbqHunsQWnJNE6KhVSMsMeH5H/L9EpymbzqTQ3uLwNCLZ1Q481oWaofqH7nO6V07xlXwY6PhQdQ2IedWx/ZK4Q=="], + + "tsdown/debug": ["debug@4.4.1", "", { "dependencies": { "ms": "^2.1.3" } }, "sha512-KcKCqiftBJcZr++7ykoDIEwSa3XWowTfNPo92BYxjXiyYEVrUQh2aLyhxBCwww+heortUFxEJYcRzosstTEBYQ=="], + + "unplugin/acorn": ["acorn@8.14.1", "", { "bin": { "acorn": "bin/acorn" } }, "sha512-OvQ/2pUDKmgfCg++xsTX1wGxfTaszcHVcTctW4UJB4hibJx2HXxxO5UmVgyjMa+ZDsiaf5wWLXYpRWMmBI0QHg=="], + + "update-browserslist-db/picocolors": ["picocolors@1.1.0", "", {}, "sha512-TQ92mBOW0l3LeMeyLV6mzy/kWr8lkd/hp3mTg7wYK7zJhuBStmGMBG0BdeDZS/dZx1IukaX6Bk11zcln25o1Aw=="], + + "validate-npm-package-license/spdx-expression-parse": ["spdx-expression-parse@3.0.1", "", { "dependencies": { "spdx-exceptions": "^2.1.0", "spdx-license-ids": "^3.0.0" } }, "sha512-cbqHunsQWnJNE6KhVSMsMeH5H/L9EpymbzqTQ3uLwNCLZ1Q481oWaofqH7nO6V07xlXwY6PhQdQ2IedWx/ZK4Q=="], + + "vite-node/debug": ["debug@4.4.1", "", { "dependencies": { "ms": "^2.1.3" } }, "sha512-KcKCqiftBJcZr++7ykoDIEwSa3XWowTfNPo92BYxjXiyYEVrUQh2aLyhxBCwww+heortUFxEJYcRzosstTEBYQ=="], + + "vitest/debug": ["debug@4.4.1", "", { "dependencies": { "ms": "^2.1.3" } }, "sha512-KcKCqiftBJcZr++7ykoDIEwSa3XWowTfNPo92BYxjXiyYEVrUQh2aLyhxBCwww+heortUFxEJYcRzosstTEBYQ=="], + + "vitest/tinyexec": ["tinyexec@0.3.2", "", {}, "sha512-KQQR9yN7R5+OSwaK0XQoj22pwHoTlgYqmUscPYoknOoWCWfj/5/ABTMRi69FrKU5ffPVh5QcFikpWJI/P1ocHA=="], + + "vue-eslint-parser/eslint-scope": ["eslint-scope@7.2.2", "", { "dependencies": { "esrecurse": "^4.3.0", "estraverse": "^5.2.0" } }, "sha512-dOt21O7lTMhDM+X9mB4GX+DZrZtCUJPL/wlcTqxyrx5IvO0IYtILdtrQGQp+8n5S0gwSVmOf9NQrjMOgfQZlIg=="], + + "vue-eslint-parser/eslint-visitor-keys": ["eslint-visitor-keys@3.4.3", "", {}, "sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag=="], + + "vue-eslint-parser/espree": ["espree@9.6.1", "", { "dependencies": { "acorn": "^8.9.0", "acorn-jsx": "^5.3.2", "eslint-visitor-keys": "^3.4.1" } }, "sha512-oruZaFkjorTpF32kDSI5/75ViwGeZginGGy2NoOSg3Q9bnwlnmDm4HLnkl0RE3n+njDXR037aY1+x58Z/zFdwQ=="], + + "vue-eslint-parser/semver": ["semver@7.6.3", "", { "bin": { "semver": "bin/semver.js" } }, "sha512-oVekP1cKtI+CTDvHWYFUcMtsK/00wmAEfyqKfNdARm8u1wNVhSgaX7A8d4UuIlUI5e84iEwOhs7ZPYRmzU9U6A=="], + + "@babel/highlight/chalk/ansi-styles": ["ansi-styles@3.2.1", "", { "dependencies": { "color-convert": "^1.9.0" } }, "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA=="], + + "@babel/highlight/chalk/escape-string-regexp": ["escape-string-regexp@1.0.5", "", {}, "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg=="], + + "@babel/highlight/chalk/supports-color": ["supports-color@5.5.0", "", { "dependencies": { "has-flag": "^3.0.0" } }, "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow=="], + + "@typescript-eslint/typescript-estree/minimatch/brace-expansion": ["brace-expansion@2.0.1", "", { "dependencies": { "balanced-match": "^1.0.0" } }, "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA=="], + + "eslint-plugin-n/minimatch/brace-expansion": ["brace-expansion@2.0.1", "", { "dependencies": { "balanced-match": "^1.0.0" } }, "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA=="], + + "eslint-plugin-vue/globals/type-fest": ["type-fest@0.20.2", "", {}, "sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ=="], + + "read-pkg-up/find-up/locate-path": ["locate-path@5.0.0", "", { "dependencies": { "p-locate": "^4.1.0" } }, "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g=="], + + "rolldown-plugin-dts/debug/ms": ["ms@2.1.3", "", {}, "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA=="], + + "tsdown/debug/ms": ["ms@2.1.3", "", {}, "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA=="], + + "vite-node/debug/ms": ["ms@2.1.3", "", {}, "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA=="], + + "vitest/debug/ms": ["ms@2.1.3", "", {}, "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA=="], + + "@babel/highlight/chalk/ansi-styles/color-convert": ["color-convert@1.9.3", "", { "dependencies": { "color-name": "1.1.3" } }, "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg=="], + + "@babel/highlight/chalk/supports-color/has-flag": ["has-flag@3.0.0", "", {}, "sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw=="], + + "read-pkg-up/find-up/locate-path/p-locate": ["p-locate@4.1.0", "", { "dependencies": { "p-limit": "^2.2.0" } }, "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A=="], + + "@babel/highlight/chalk/ansi-styles/color-convert/color-name": ["color-name@1.1.3", "", {}, "sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw=="], + + "read-pkg-up/find-up/locate-path/p-locate/p-limit": ["p-limit@2.3.0", "", { "dependencies": { "p-try": "^2.0.0" } }, "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w=="], + } +} diff --git a/bun.lockb b/bun.lockb deleted file mode 100755 index 44335b2c6cec6b0a423976909a61f47bdd2379ed..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 156451 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 diff --git a/package.json b/package.json index 9a4d30e..5092616 100644 --- a/package.json +++ b/package.json @@ -24,7 +24,6 @@ "@kirick/eslint-config": "^0.1.30", "@types/bun": "^1.2.13", "eslint": "9.10.0", - "oxc-parser": "0.71.0", "publint": "0.3.12", "tsdown": "0.12.2", "type-fest": "^4.41.0", From db67a3835ca465679c93a20c759759ba23535723 Mon Sep 17 00:00:00 2001 From: Daniil Kirichenko Date: Sun, 25 May 2025 18:41:02 +0200 Subject: [PATCH 39/57] Update package.json --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 5092616..cbc85a7 100644 --- a/package.json +++ b/package.json @@ -34,7 +34,7 @@ }, "scripts": { "build": "tsdown src/main.ts --publint --unused --dts --format esm --format cjs && rm dist/main.d.cts", - "check": "bun run build && bun run lint && bun run test", + "check": "bun run lint && bun run build && bun run test", "lint": "eslint . && tsc && (cd test && tsc)", "test": "npm run test:vitest && bun test --coverage", "test:vitest": "vitest run --no-file-parallelism" From 6e65be883355afa7c6d65d4bc55b0bb98b462f47 Mon Sep 17 00:00:00 2001 From: Daniil Kirichenko Date: Wed, 28 May 2025 21:00:34 +0200 Subject: [PATCH 40/57] Adopted biome & oxlint --- .oxlintrc.json | 9 + .zed/settings.json | 12 + biome.json | 28 ++ bun.lock | 362 +++++++++++++------------ dist/main.cjs | 32 ++- dist/main.d.ts | 21 +- dist/main.js | 32 ++- eslint.config.js | 5 +- package.json | 13 +- src/api-errors.ts | 60 ++-- src/driver.ts | 10 +- src/error.test.ts | 5 +- src/main.test.ts | 42 +-- src/main.ts | 129 +++++---- src/module.ts | 29 +- src/request.ts | 4 +- src/response.ts | 2 +- src/router.ts | 113 +++----- src/utils/is-record.ts | 12 +- src/utils/methods.ts | 28 +- test/hyper-api/echo.[post].ts | 6 +- test/hyper-api/echo.ts | 8 +- test/hyper-api/errors/api.test.ts | 22 +- test/hyper-api/errors/api.ts | 18 +- test/hyper-api/errors/internal.test.ts | 10 +- test/hyper-api/only-get.test.ts | 10 +- test/setup.ts | 86 +++--- test/tsconfig.json | 7 +- tsconfig.json | 14 +- 29 files changed, 575 insertions(+), 554 deletions(-) create mode 100644 .oxlintrc.json create mode 100644 .zed/settings.json create mode 100644 biome.json diff --git a/.oxlintrc.json b/.oxlintrc.json new file mode 100644 index 0000000..13b8341 --- /dev/null +++ b/.oxlintrc.json @@ -0,0 +1,9 @@ +{ + "$schema": "./node_modules/oxlint/configuration_schema.json", + "extends": [ + "./node_modules/@kirick/lint/configs/oxlint/correctness.json", + "./node_modules/@kirick/lint/configs/oxlint/perf.json", + "./node_modules/@kirick/lint/configs/oxlint/restriction.json" + ], + "ignorePatterns": ["dist"] +} diff --git a/.zed/settings.json b/.zed/settings.json new file mode 100644 index 0000000..24cc794 --- /dev/null +++ b/.zed/settings.json @@ -0,0 +1,12 @@ +{ + "format_on_save": "on", + "formatter": { + "language_server": { + "name": "biome" + } + }, + "code_actions_on_format": { + "source.fixAll.biome": true, + "source.organizeImports.biome": true + } +} diff --git a/biome.json b/biome.json new file mode 100644 index 0000000..5071149 --- /dev/null +++ b/biome.json @@ -0,0 +1,28 @@ +{ + "$schema": "https://biomejs.dev/schemas/1.9.4/schema.json", + "vcs": { + "enabled": false, + "clientKind": "git", + "useIgnoreFile": false + }, + "files": { + "ignoreUnknown": false, + "ignore": ["dist/"] + }, + "formatter": { + "enabled": true, + "indentStyle": "tab", + "bracketSpacing": true + }, + "organizeImports": { + "enabled": true + }, + "linter": { + "enabled": false + }, + "javascript": { + "formatter": { + "quoteStyle": "single" + } + } +} diff --git a/bun.lock b/bun.lock index 0973ab3..840471c 100644 --- a/bun.lock +++ b/bun.lock @@ -7,9 +7,11 @@ "itty-router": "^5.0.18", }, "devDependencies": { - "@kirick/eslint-config": "^0.1.30", + "@biomejs/biome": "1.9.4", + "@kirick/lint": "0.1.0", "@types/bun": "^1.2.13", - "eslint": "9.10.0", + "eslint": "9.27.0", + "oxlint": "0.16.12", "publint": "0.3.12", "tsdown": "0.12.2", "type-fest": "^4.41.0", @@ -21,27 +23,41 @@ }, }, "packages": { - "@babel/code-frame": ["@babel/code-frame@7.24.7", "", { "dependencies": { "@babel/highlight": "^7.24.7", "picocolors": "^1.0.0" } }, "sha512-BcYH1CVJBO9tvyIZ2jVeXgSIMvGZ2FDRvDdOIVQyuklNKSsx+eppDEBq/g47Ayw+RqNFE+URvOShmf+f/qwAlA=="], - "@babel/generator": ["@babel/generator@7.27.1", "", { "dependencies": { "@babel/parser": "^7.27.1", "@babel/types": "^7.27.1", "@jridgewell/gen-mapping": "^0.3.5", "@jridgewell/trace-mapping": "^0.3.25", "jsesc": "^3.0.2" } }, "sha512-UnJfnIpc/+JO0/+KRVQNGU+y5taA5vCbwN8+azkX6beii/ZF+enZJSOKo11ZSzGJjlNfJHfQtmQT8H+9TXPG2w=="], "@babel/helper-string-parser": ["@babel/helper-string-parser@7.27.1", "", {}, "sha512-qMlSxKbpRlAridDExk92nSobyDdpPijUq2DW6oDnUqd0iOGxmQjyqhMIihI9+zv4LPyZdRje2cavWPbCbWm3eA=="], - "@babel/helper-validator-identifier": ["@babel/helper-validator-identifier@7.24.7", "", {}, "sha512-rR+PBcQ1SMQDDyF6X0wxtG8QyLCgUB0eRAGguqRLfkCA87l7yAP7ehq8SNj96OOGTO8OBV70KhuFYcIkHXOg0w=="], - - "@babel/highlight": ["@babel/highlight@7.24.7", "", { "dependencies": { "@babel/helper-validator-identifier": "^7.24.7", "chalk": "^2.4.2", "js-tokens": "^4.0.0", "picocolors": "^1.0.0" } }, "sha512-EStJpq4OuY8xYfhGVXngigBJRWxftKX9ksiGDnmlY3o7B/V7KIAc9X4oiK87uPJSc/vs5L869bem5fhZa8caZw=="], + "@babel/helper-validator-identifier": ["@babel/helper-validator-identifier@7.27.1", "", {}, "sha512-D2hP9eA+Sqx1kBZgzxZh0y1trbuU+JoDkiEwqhQ36nodYqJwyEIhPSdMNd7lOm/4io72luTPWH20Yda0xOuUow=="], "@babel/parser": ["@babel/parser@7.27.2", "", { "dependencies": { "@babel/types": "^7.27.1" }, "bin": "./bin/babel-parser.js" }, "sha512-QYLs8299NA7WM/bZAdp+CviYYkVoYXlDW2rzliy3chxd1PQjej7JORuMJDJXJUb9g0TT+B99EwaVLKmX+sPXWw=="], "@babel/types": ["@babel/types@7.27.1", "", { "dependencies": { "@babel/helper-string-parser": "^7.27.1", "@babel/helper-validator-identifier": "^7.27.1" } }, "sha512-+EzkxvLNfiUeKMgy/3luqfsCWFRXLb7U6wNQTk60tovuckwB15B191tJWvpp4HjiQWdJkCxO3Wbvc6jlk3Xb2Q=="], + "@biomejs/biome": ["@biomejs/biome@1.9.4", "", { "optionalDependencies": { "@biomejs/cli-darwin-arm64": "1.9.4", "@biomejs/cli-darwin-x64": "1.9.4", "@biomejs/cli-linux-arm64": "1.9.4", "@biomejs/cli-linux-arm64-musl": "1.9.4", "@biomejs/cli-linux-x64": "1.9.4", "@biomejs/cli-linux-x64-musl": "1.9.4", "@biomejs/cli-win32-arm64": "1.9.4", "@biomejs/cli-win32-x64": "1.9.4" }, "bin": { "biome": "bin/biome" } }, "sha512-1rkd7G70+o9KkTn5KLmDYXihGoTaIGO9PIIN2ZB7UJxFrWw04CZHPYiMRjYsaDvVV7hP1dYNRLxSANLaBFGpog=="], + + "@biomejs/cli-darwin-arm64": ["@biomejs/cli-darwin-arm64@1.9.4", "", { "os": "darwin", "cpu": "arm64" }, "sha512-bFBsPWrNvkdKrNCYeAp+xo2HecOGPAy9WyNyB/jKnnedgzl4W4Hb9ZMzYNbf8dMCGmUdSavlYHiR01QaYR58cw=="], + + "@biomejs/cli-darwin-x64": ["@biomejs/cli-darwin-x64@1.9.4", "", { "os": "darwin", "cpu": "x64" }, "sha512-ngYBh/+bEedqkSevPVhLP4QfVPCpb+4BBe2p7Xs32dBgs7rh9nY2AIYUL6BgLw1JVXV8GlpKmb/hNiuIxfPfZg=="], + + "@biomejs/cli-linux-arm64": ["@biomejs/cli-linux-arm64@1.9.4", "", { "os": "linux", "cpu": "arm64" }, "sha512-fJIW0+LYujdjUgJJuwesP4EjIBl/N/TcOX3IvIHJQNsAqvV2CHIogsmA94BPG6jZATS4Hi+xv4SkBBQSt1N4/g=="], + + "@biomejs/cli-linux-arm64-musl": ["@biomejs/cli-linux-arm64-musl@1.9.4", "", { "os": "linux", "cpu": "arm64" }, "sha512-v665Ct9WCRjGa8+kTr0CzApU0+XXtRgwmzIf1SeKSGAv+2scAlW6JR5PMFo6FzqqZ64Po79cKODKf3/AAmECqA=="], + + "@biomejs/cli-linux-x64": ["@biomejs/cli-linux-x64@1.9.4", "", { "os": "linux", "cpu": "x64" }, "sha512-lRCJv/Vi3Vlwmbd6K+oQ0KhLHMAysN8lXoCI7XeHlxaajk06u7G+UsFSO01NAs5iYuWKmVZjmiOzJ0OJmGsMwg=="], + + "@biomejs/cli-linux-x64-musl": ["@biomejs/cli-linux-x64-musl@1.9.4", "", { "os": "linux", "cpu": "x64" }, "sha512-gEhi/jSBhZ2m6wjV530Yy8+fNqG8PAinM3oV7CyO+6c3CEh16Eizm21uHVsyVBEB6RIM8JHIl6AGYCv6Q6Q9Tg=="], + + "@biomejs/cli-win32-arm64": ["@biomejs/cli-win32-arm64@1.9.4", "", { "os": "win32", "cpu": "arm64" }, "sha512-tlbhLk+WXZmgwoIKwHIHEBZUwxml7bRJgk0X2sPyNR3S93cdRq6XulAZRQJ17FYGGzWne0fgrXBKpl7l4M87Hg=="], + + "@biomejs/cli-win32-x64": ["@biomejs/cli-win32-x64@1.9.4", "", { "os": "win32", "cpu": "x64" }, "sha512-8Y5wMhVIPaWe6jw2H+KlEm4wP/f7EW3810ZLmDlrEEy5KvBsb9ECEfu/kMWD484ijfQ8+nIi0giMgu9g1UAuuA=="], + "@emnapi/core": ["@emnapi/core@1.4.3", "", { "dependencies": { "@emnapi/wasi-threads": "1.0.2", "tslib": "^2.4.0" } }, "sha512-4m62DuCE07lw01soJwPiBGC0nAww0Q+RY70VZ+n49yDIO13yyinhbWCeNnaob0lakDtWQzSdtNWzJeOJt2ma+g=="], "@emnapi/runtime": ["@emnapi/runtime@1.4.3", "", { "dependencies": { "tslib": "^2.4.0" } }, "sha512-pBPWdu6MLKROBX05wSNKcNb++m5Er+KQ9QkB+WVM+pW2Kx9hoSrVTnu3BdkI5eBLZoKu/J6mW/B6i6bJB2ytXQ=="], "@emnapi/wasi-threads": ["@emnapi/wasi-threads@1.0.2", "", { "dependencies": { "tslib": "^2.4.0" } }, "sha512-5n3nTJblwRi8LlXkJ9eBzu+kZR8Yxcc7ubakyQTFzPMtIhFpUBRbsnc2Dv88IZDIbCDlBiWrknhB4Lsz7mg6BA=="], - "@es-joy/jsdoccomment": ["@es-joy/jsdoccomment@0.46.0", "", { "dependencies": { "comment-parser": "1.4.1", "esquery": "^1.6.0", "jsdoc-type-pratt-parser": "~4.0.0" } }, "sha512-C3Axuq1xd/9VqFZpW4YAzOx5O9q/LP46uIQy/iNDpHG3fmPa6TBtvfglMCs3RBiBxAIi0Go97r8+jvTt55XMyQ=="], + "@es-joy/jsdoccomment": ["@es-joy/jsdoccomment@0.50.2", "", { "dependencies": { "@types/estree": "^1.0.6", "@typescript-eslint/types": "^8.11.0", "comment-parser": "1.4.1", "esquery": "^1.6.0", "jsdoc-type-pratt-parser": "~4.1.0" } }, "sha512-YAdE/IJSpwbOTiaURNCKECdAwqrJuFiZhylmesBcIRawtYKnBR2wxPhoIewMg+Yu+QuYvHfJNReWpoxGBKOChA=="], "@esbuild/aix-ppc64": ["@esbuild/aix-ppc64@0.21.5", "", { "os": "aix", "cpu": "ppc64" }, "sha512-1SDgH6ZSPTlggy1yI6+Dbkiz8xzpHJEVAlF/AM1tHPLsf5STom9rwtjE4hKAF20FfXXNTFqEYXyJNWh1GiZedQ=="], @@ -89,23 +105,31 @@ "@esbuild/win32-x64": ["@esbuild/win32-x64@0.21.5", "", { "os": "win32", "cpu": "x64" }, "sha512-tQd/1efJuzPC6rCFwEvLtci/xNFcTZknmXs98FYDfGE4wP9ClFV98nyKrzJKVPMhdDnjzLhdUyMX4PsQAPjwIw=="], - "@eslint-community/eslint-utils": ["@eslint-community/eslint-utils@4.4.0", "", { "dependencies": { "eslint-visitor-keys": "^3.3.0" }, "peerDependencies": { "eslint": "^6.0.0 || ^7.0.0 || >=8.0.0" } }, "sha512-1/sA4dwrzBAyeUoQ6oxahHKmrZvsnLCg4RfxW3ZFGGmQkSNQPFNLV9CUEFQP1x9EYXHTo5p6xdhZM1Ne9p/AfA=="], + "@eslint-community/eslint-utils": ["@eslint-community/eslint-utils@4.7.0", "", { "dependencies": { "eslint-visitor-keys": "^3.4.3" }, "peerDependencies": { "eslint": "^6.0.0 || ^7.0.0 || >=8.0.0" } }, "sha512-dyybb3AcajC7uha6CvhdVRJqaKyn7w2YKqKyAN37NKYgZT36w+iRb0Dymmc5qEJ549c/S31cMMSFd75bteCpCw=="], + + "@eslint-community/regexpp": ["@eslint-community/regexpp@4.12.1", "", {}, "sha512-CCZCDJuduB9OUkFkY2IgppNZMi2lBQgD2qzwXkEia16cge2pijY/aXi96CJMquDMn3nJdlPV1A5KrJEXwfLNzQ=="], + + "@eslint/config-array": ["@eslint/config-array@0.20.0", "", { "dependencies": { "@eslint/object-schema": "^2.1.6", "debug": "^4.3.1", "minimatch": "^3.1.2" } }, "sha512-fxlS1kkIjx8+vy2SjuCB94q3htSNrufYTXubwiBFeaQHbH6Ipi43gFJq2zCMt6PHhImH3Xmr0NksKDvchWlpQQ=="], + + "@eslint/config-helpers": ["@eslint/config-helpers@0.2.2", "", {}, "sha512-+GPzk8PlG0sPpzdU5ZvIRMPidzAnZDl/s9L+y13iodqvb8leL53bTannOrQ/Im7UkpsmFU5Ily5U60LWixnmLg=="], - "@eslint-community/regexpp": ["@eslint-community/regexpp@4.11.0", "", {}, "sha512-G/M/tIiMrTAxEWRfLfQJMmGNX28IxBg4PBz8XqQhqUHLFI6TL2htpIB1iQCj144V5ee/JaKyT9/WZ0MGZWfA7A=="], + "@eslint/core": ["@eslint/core@0.14.0", "", { "dependencies": { "@types/json-schema": "^7.0.15" } }, "sha512-qIbV0/JZr7iSDjqAc60IqbLdsj9GDt16xQtWD+B78d/HAlvysGdZZ6rpJHGAc2T0FQx1X6thsSPdnoiGKdNtdg=="], - "@eslint/config-array": ["@eslint/config-array@0.18.0", "", { "dependencies": { "@eslint/object-schema": "^2.1.4", "debug": "^4.3.1", "minimatch": "^3.1.2" } }, "sha512-fTxvnS1sRMu3+JjXwJG0j/i4RT9u4qJ+lqS/yCGap4lH4zZGzQ7tu+xZqQmcMZq5OBZDL4QRxQzRjkWcGt8IVw=="], + "@eslint/eslintrc": ["@eslint/eslintrc@3.3.1", "", { "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" } }, "sha512-gtF186CXhIl1p4pJNGZw8Yc6RlshoePRvE0X91oPGb3vZ8pM3qOS9W9NGPat9LziaBV7XrJWGylNQXkGcnM3IQ=="], - "@eslint/eslintrc": ["@eslint/eslintrc@3.1.0", "", { "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" } }, "sha512-4Bfj15dVJdoy3RfZmmo86RK1Fwzn6SstsvK9JS+BaVKqC6QQQQyXekNaC+g+LKNgkQ+2VhGAzm6hO40AhMR3zQ=="], + "@eslint/js": ["@eslint/js@9.27.0", "", {}, "sha512-G5JD9Tu5HJEu4z2Uo4aHY2sLV64B7CDMXxFzqzjl3NKd6RVzSXNoE80jk7Y0lJkTTkjiIhBAqmlYwjuBY3tvpA=="], - "@eslint/js": ["@eslint/js@9.10.0", "", {}, "sha512-fuXtbiP5GWIn8Fz+LWoOMVf/Jxm+aajZYkhi6CuEm4SxymFM+eUWzbO9qXT+L0iCkL5+KGYMCSGxo686H19S1g=="], + "@eslint/object-schema": ["@eslint/object-schema@2.1.6", "", {}, "sha512-RBMg5FRL0I0gs51M/guSAj5/e14VQ4tpZnQNWwuDT66P14I43ItmPfIZRhO9fUVIPOAQXU47atlywZ/czoqFPA=="], - "@eslint/object-schema": ["@eslint/object-schema@2.1.4", "", {}, "sha512-BsWiH1yFGjXXS2yvrf5LyuoSIIbPrGUWob917o+BTKuZ7qJdxX8aJLRxs1fS9n6r7vESrq1OUqb68dANcFXuQQ=="], + "@eslint/plugin-kit": ["@eslint/plugin-kit@0.3.1", "", { "dependencies": { "@eslint/core": "^0.14.0", "levn": "^0.4.1" } }, "sha512-0J+zgWxHN+xXONWIyPWKFMgVuJoZuGiIFu8yxk7RJjxkzpGmyja5wRFqZIVtjDVOQpV+Rw0iOAjYPE2eQyjr0w=="], - "@eslint/plugin-kit": ["@eslint/plugin-kit@0.1.0", "", { "dependencies": { "levn": "^0.4.1" } }, "sha512-autAXT203ixhqei9xt+qkYOvY8l6LAFIdT2UXc/RPNeUVfqRF1BV94GTJyVPFKT8nFM6MyVJhjLj9E8JWvf5zQ=="], + "@humanfs/core": ["@humanfs/core@0.19.1", "", {}, "sha512-5DyQ4+1JEUzejeK1JGICcideyfUbGixgS9jNgex5nqkW+cY7WZhxBigmieN5Qnw9ZosSNVC9KQKyb+GUaGyKUA=="], + + "@humanfs/node": ["@humanfs/node@0.16.6", "", { "dependencies": { "@humanfs/core": "^0.19.1", "@humanwhocodes/retry": "^0.3.0" } }, "sha512-YuI2ZHQL78Q5HbhDiBA1X4LmYdXCKCMQIfw0pw7piHJwyREFebJUvrQN4cMssyES6x+vfUbx1CIpaQUKYdQZOw=="], "@humanwhocodes/module-importer": ["@humanwhocodes/module-importer@1.0.1", "", {}, "sha512-bxveV4V8v5Yb4ncFTT3rPSgZBOpCkjfK0y4oVVVJwIuDVBRMDXrPyXRL988i5ap9m9bnyEEjWfm5WkBmtffLfA=="], - "@humanwhocodes/retry": ["@humanwhocodes/retry@0.3.0", "", {}, "sha512-d2CGZR2o7fS6sWB7DG/3a95bGKQyHMACZ5aW8qGkkqQpUoZV6C0X7Pc7l4ZNMZkfNBf4VWNe9E1jRsf0G146Ew=="], + "@humanwhocodes/retry": ["@humanwhocodes/retry@0.4.3", "", {}, "sha512-bV0Tgo9K4hfPCek+aMAn81RppFKv2ySDQeMoSZuvTASywNTnVJCArCZE2FWqpvIatKu7VMRLWlR1EazvVhDyhQ=="], "@jridgewell/gen-mapping": ["@jridgewell/gen-mapping@0.3.8", "", { "dependencies": { "@jridgewell/set-array": "^1.2.1", "@jridgewell/sourcemap-codec": "^1.4.10", "@jridgewell/trace-mapping": "^0.3.24" } }, "sha512-imAbBGkb+ebQyxKgzv5Hu2nmROxoDOXHh80evxdoXNOrvAnVx7zimzc1Oo5h9RlfV4vPXaE2iM5pOFbvOCClWA=="], @@ -117,7 +141,7 @@ "@jridgewell/trace-mapping": ["@jridgewell/trace-mapping@0.3.25", "", { "dependencies": { "@jridgewell/resolve-uri": "^3.1.0", "@jridgewell/sourcemap-codec": "^1.4.14" } }, "sha512-vNk6aEwybGtawWmy/PzwnGDOjCkLWSD2wqvjGGAgOAwCGWySYXfYoxt00IJkTF+8Lb57DwOb3Aa0o9CApepiYQ=="], - "@kirick/eslint-config": ["@kirick/eslint-config@0.1.30", "", { "dependencies": { "@stylistic/eslint-plugin": "^2.6.1", "eslint-plugin-jsdoc": "^48.11.0", "eslint-plugin-n": "^17.10.2", "eslint-plugin-promise": "^7.1.0", "eslint-plugin-unicorn": "^55.0.0", "eslint-plugin-vue": "^9.27.0", "globals": "^15.9.0", "typescript-eslint": "^8.0.0" } }, "sha512-RjmSG2380JS/MCh80hnLpVKBI0V5+ggGugTXVK+2Gf0sTq54R5KzX9rKkE1FFIqedG7ZkGyDuipJc7zDYVBQ4g=="], + "@kirick/lint": ["@kirick/lint@0.1.0", "", { "dependencies": { "@stylistic/eslint-plugin": "^4.4.0", "eslint": "9.27.0", "eslint-plugin-jsdoc": "50.6.17", "eslint-plugin-n": "^17.18.0", "eslint-plugin-promise": "^7.2.1", "eslint-plugin-unicorn": "59.0.1", "eslint-plugin-vue": "^10.1.0", "typescript-eslint": "8.32.1" }, "bin": { "lint": "dist/main.js" } }, "sha512-/7TnjAybQvT6oEG7jwaUQegSzDOrxfhxlAE2tojefTfDJxyK/wyxWfPXI7yzMIn/b3u5LxvENYb52OVNg/QAFA=="], "@napi-rs/wasm-runtime": ["@napi-rs/wasm-runtime@0.2.10", "", { "dependencies": { "@emnapi/core": "^1.4.3", "@emnapi/runtime": "^1.4.3", "@tybys/wasm-util": "^0.9.0" } }, "sha512-bCsCyeZEwVErsGmyPNSzwfwFn4OdxBj0mmv6hOFucB/k81Ojdu68RbZdxYsRQUPc9l6SU5F/cG+bXgWs3oUgsQ=="], @@ -129,7 +153,47 @@ "@oxc-project/types": ["@oxc-project/types@0.71.0", "", {}, "sha512-5CwQ4MI+P4MQbjLWXgNurA+igGwu/opNetIE13LBs9+V93R64MLvDKOOLZIXSzEfovU3Zef3q3GjPnMTgJTn2w=="], - "@pkgr/core": ["@pkgr/core@0.1.1", "", {}, "sha512-cq8o4cWH0ibXh9VGi5P20Tu9XF/0fFXl9EUinr9QfTM7a7p0oTA4iJRCQWppXR1Pg8dSM0UCItCkPwsk9qWWYA=="], + "@oxc-resolver/binding-darwin-arm64": ["@oxc-resolver/binding-darwin-arm64@9.0.2", "", { "os": "darwin", "cpu": "arm64" }, "sha512-MVyRgP2gzJJtAowjG/cHN3VQXwNLWnY+FpOEsyvDepJki1SdAX/8XDijM1yN6ESD1kr9uhBKjGelC6h3qtT+rA=="], + + "@oxc-resolver/binding-darwin-x64": ["@oxc-resolver/binding-darwin-x64@9.0.2", "", { "os": "darwin", "cpu": "x64" }, "sha512-7kV0EOFEZ3sk5Hjy4+bfA6XOQpCwbDiDkkHN4BHHyrBHsXxUR05EcEJPPL1WjItefg+9+8hrBmoK0xRoDs41+A=="], + + "@oxc-resolver/binding-freebsd-x64": ["@oxc-resolver/binding-freebsd-x64@9.0.2", "", { "os": "freebsd", "cpu": "x64" }, "sha512-6OvkEtRXrt8sJ4aVfxHRikjain9nV1clIsWtJ1J3J8NG1ZhjyJFgT00SCvqxbK+pzeWJq6XzHyTCN78ML+lY2w=="], + + "@oxc-resolver/binding-linux-arm-gnueabihf": ["@oxc-resolver/binding-linux-arm-gnueabihf@9.0.2", "", { "os": "linux", "cpu": "arm" }, "sha512-aYpNL6o5IRAUIdoweW21TyLt54Hy/ZS9tvzNzF6ya1ckOQ8DLaGVPjGpmzxdNja9j/bbV6aIzBH7lNcBtiOTkQ=="], + + "@oxc-resolver/binding-linux-arm64-gnu": ["@oxc-resolver/binding-linux-arm64-gnu@9.0.2", "", { "os": "linux", "cpu": "arm64" }, "sha512-RGFW4vCfKMFEIzb9VCY0oWyyY9tR1/o+wDdNePhiUXZU4SVniRPQaZ1SJ0sUFI1k25pXZmzQmIP6cBmazi/Dew=="], + + "@oxc-resolver/binding-linux-arm64-musl": ["@oxc-resolver/binding-linux-arm64-musl@9.0.2", "", { "os": "linux", "cpu": "arm64" }, "sha512-lxx/PibBfzqYvut2Y8N2D0Ritg9H8pKO+7NUSJb9YjR/bfk2KRmP8iaUz3zB0JhPtf/W3REs65oKpWxgflGToA=="], + + "@oxc-resolver/binding-linux-riscv64-gnu": ["@oxc-resolver/binding-linux-riscv64-gnu@9.0.2", "", { "os": "linux", "cpu": "none" }, "sha512-yD28ptS/OuNhwkpXRPNf+/FvrO7lwURLsEbRVcL1kIE0GxNJNMtKgIE4xQvtKDzkhk6ZRpLho5VSrkkF+3ARTQ=="], + + "@oxc-resolver/binding-linux-s390x-gnu": ["@oxc-resolver/binding-linux-s390x-gnu@9.0.2", "", { "os": "linux", "cpu": "s390x" }, "sha512-WBwEJdspoga2w+aly6JVZeHnxuPVuztw3fPfWrei2P6rNM5hcKxBGWKKT6zO1fPMCB4sdDkFohGKkMHVV1eryQ=="], + + "@oxc-resolver/binding-linux-x64-gnu": ["@oxc-resolver/binding-linux-x64-gnu@9.0.2", "", { "os": "linux", "cpu": "x64" }, "sha512-a2z3/cbOOTUq0UTBG8f3EO/usFcdwwXnCejfXv42HmV/G8GjrT4fp5+5mVDoMByH3Ce3iVPxj1LmS6OvItKMYQ=="], + + "@oxc-resolver/binding-linux-x64-musl": ["@oxc-resolver/binding-linux-x64-musl@9.0.2", "", { "os": "linux", "cpu": "x64" }, "sha512-bHZF+WShYQWpuswB9fyxcgMIWVk4sZQT0wnwpnZgQuvGTZLkYJ1JTCXJMtaX5mIFHf69ngvawnwPIUA4Feil0g=="], + + "@oxc-resolver/binding-wasm32-wasi": ["@oxc-resolver/binding-wasm32-wasi@9.0.2", "", { "dependencies": { "@napi-rs/wasm-runtime": "^0.2.9" }, "cpu": "none" }, "sha512-I5cSgCCh5nFozGSHz+PjIOfrqW99eUszlxKLgoNNzQ1xQ2ou9ZJGzcZ94BHsM9SpyYHLtgHljmOZxCT9bgxYNA=="], + + "@oxc-resolver/binding-win32-arm64-msvc": ["@oxc-resolver/binding-win32-arm64-msvc@9.0.2", "", { "os": "win32", "cpu": "arm64" }, "sha512-5IhoOpPr38YWDWRCA5kP30xlUxbIJyLAEsAK7EMyUgqygBHEYLkElaKGgS0X5jRXUQ6l5yNxuW73caogb2FYaw=="], + + "@oxc-resolver/binding-win32-x64-msvc": ["@oxc-resolver/binding-win32-x64-msvc@9.0.2", "", { "os": "win32", "cpu": "x64" }, "sha512-Qc40GDkaad9rZksSQr2l/V9UubigIHsW69g94Gswc2sKYB3XfJXfIfyV8WTJ67u6ZMXsZ7BH1msSC6Aen75mCg=="], + + "@oxlint/darwin-arm64": ["@oxlint/darwin-arm64@0.16.12", "", { "os": "darwin", "cpu": "arm64" }, "sha512-G7phYhlIA4ke2nW7tHLl+E5+rvdzgGA6830D+e+y1RGllT0w2ONGdKcVTj+2pXGCw6yPmCC5fDsDEn2+RPTfxg=="], + + "@oxlint/darwin-x64": ["@oxlint/darwin-x64@0.16.12", "", { "os": "darwin", "cpu": "x64" }, "sha512-P/LSOgJ6SzQ3OKEIf3HsebgokZiZ5nDuTgIL4LpNCHlkOLDu/fT8XL9pSkR5y+60v0SOxUF/+aN0Q8EmxblrCw=="], + + "@oxlint/linux-arm64-gnu": ["@oxlint/linux-arm64-gnu@0.16.12", "", { "os": "linux", "cpu": "arm64" }, "sha512-0N/ZsW+cL7ZAUvOHbzMp3iApt5b/Q81q2e9RgEzkI6gUDCJK8/blWg0se/i6y9e24WH0ZC4bcxY1+Qz4ZQ+mFw=="], + + "@oxlint/linux-arm64-musl": ["@oxlint/linux-arm64-musl@0.16.12", "", { "os": "linux", "cpu": "arm64" }, "sha512-MoG1SIw4RGowsOsPjm5HjRWymisRZWBea7ewMoXA5xIVQ3eqECifG0KJW0OZp96Ad8DFBEavdlNuImB2uXsMwg=="], + + "@oxlint/linux-x64-gnu": ["@oxlint/linux-x64-gnu@0.16.12", "", { "os": "linux", "cpu": "x64" }, "sha512-STho8QdMLfn/0lqRU94tGPaYX8lGJccPbqeUcEr3eK5gZ5ZBdXmiHlvkcngXFEXksYC8/5VoJN7Vf3HsmkEskw=="], + + "@oxlint/linux-x64-musl": ["@oxlint/linux-x64-musl@0.16.12", "", { "os": "linux", "cpu": "x64" }, "sha512-i7pzSoj9nCg/ZzOe8dCZeFWyRRWDylR9tIX04xRTq3G6PBLm6i9VrOdEkxbgM9+pCkRzUc0a9D7rbtCF34TQUA=="], + + "@oxlint/win32-arm64": ["@oxlint/win32-arm64@0.16.12", "", { "os": "win32", "cpu": "arm64" }, "sha512-wcxq3IBJ7ZlONlXJxQM+7EMx+LX1nkz3ZS3R0EtDM76EOZaqe8BMkW5cXVhF8jarZTZC18oKAckW4Ng9d8adBg=="], + + "@oxlint/win32-x64": ["@oxlint/win32-x64@0.16.12", "", { "os": "win32", "cpu": "x64" }, "sha512-Ae1fx7wmAcMVqzS8rLINaFRpAdh29QzHh133bEYMHzfWBYyK/hLu9g4GLwC/lEIVQu9884b8qutGfdOk6Qia3w=="], "@publint/pack": ["@publint/pack@0.1.2", "", {}, "sha512-S+9ANAvUmjutrshV4jZjaiG8XQyuJIZ8a4utWmN/vW1sgQ9IfBnPndwkmQYw53QmouOIytT874u65HEmu6H5jw=="], @@ -193,37 +257,33 @@ "@rollup/rollup-win32-x64-msvc": ["@rollup/rollup-win32-x64-msvc@4.21.2", "", { "os": "win32", "cpu": "x64" }, "sha512-6UUxd0+SKomjdzuAcp+HAmxw1FlGBnl1v2yEPSabtx4lBfdXHDVsW7+lQkgz9cNFJGY3AWR7+V8P5BqkD9L9nA=="], - "@stylistic/eslint-plugin": ["@stylistic/eslint-plugin@2.7.2", "", { "dependencies": { "@types/eslint": "^9.6.1", "@typescript-eslint/utils": "^8.3.0", "eslint-visitor-keys": "^4.0.0", "espree": "^10.1.0", "estraverse": "^5.3.0", "picomatch": "^4.0.2" }, "peerDependencies": { "eslint": ">=8.40.0" } }, "sha512-3DVLU5HEuk2pQoBmXJlzvrxbKNpu2mJ0SRqz5O/CJjyNCr12ZiPcYMEtuArTyPOk5i7bsAU44nywh1rGfe3gKQ=="], + "@stylistic/eslint-plugin": ["@stylistic/eslint-plugin@4.4.0", "", { "dependencies": { "@typescript-eslint/utils": "^8.32.1", "eslint-visitor-keys": "^4.2.0", "espree": "^10.3.0", "estraverse": "^5.3.0", "picomatch": "^4.0.2" }, "peerDependencies": { "eslint": ">=9.0.0" } }, "sha512-bIh/d9X+OQLCAMdhHtps+frvyjvAM4B1YlSJzcEEhl7wXLIqPar3ngn9DrHhkBOrTA/z9J0bUMtctAspe0dxdQ=="], "@tybys/wasm-util": ["@tybys/wasm-util@0.9.0", "", { "dependencies": { "tslib": "^2.4.0" } }, "sha512-6+7nlbMVX/PVDCwaIQ8nTOPveOcFLSt8GcXdx8hD0bt39uWxYT88uXzqTd4fTvqta7oeUJqudepapKNt2DYJFw=="], "@types/bun": ["@types/bun@1.2.14", "", { "dependencies": { "bun-types": "1.2.14" } }, "sha512-VsFZKs8oKHzI7zwvECiAJ5oSorWndIWEVhfbYqZd4HI/45kzW7PN2Rr5biAzvGvRuNmYLSANY+H59ubHq8xw7Q=="], - "@types/eslint": ["@types/eslint@9.6.1", "", { "dependencies": { "@types/estree": "*", "@types/json-schema": "*" } }, "sha512-FXx2pKgId/WyYo2jXw63kk7/+TY7u7AziEJxJAnSFzHlqTAS3Ync6SvgYAN/k4/PQpnnVuzoMuVnByKK2qp0ag=="], - - "@types/estree": ["@types/estree@1.0.5", "", {}, "sha512-/kYRxGDLWzHOB7q+wtSUQlFrtcdUccpfy+X+9iMBpHK8QLLhx2wIPYuS5DYtR9Wa/YlZAbIovy7qVdB1Aq6Lyw=="], + "@types/estree": ["@types/estree@1.0.7", "", {}, "sha512-w28IoSUCJpidD/TGviZwwMJckNESJZXFu7NBZ5YJ4mEUnNraUn9Pm8HSZm/jDF1pDWYKspWE7oVphigUPRakIQ=="], "@types/json-schema": ["@types/json-schema@7.0.15", "", {}, "sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA=="], - "@types/node": ["@types/node@20.16.5", "", { "dependencies": { "undici-types": "~6.19.2" } }, "sha512-VwYCweNo3ERajwy0IUlqqcyZ8/A7Zwa9ZP3MnENWcB11AejO+tLy3pu850goUW2FC/IJMdZUfKpX/yxL1gymCA=="], - - "@types/normalize-package-data": ["@types/normalize-package-data@2.4.4", "", {}, "sha512-37i+OaWTh9qeK4LSHPsyRC7NahnGotNuZvjLSgcPzblpHB3rrCJxAOgI5gCdKm7coonsaX1Of0ILiTcnZjbfxA=="], + "@types/node": ["@types/node@22.15.23", "", { "dependencies": { "undici-types": "~6.21.0" } }, "sha512-7Ec1zaFPF4RJ0eXu1YT/xgiebqwqoJz8rYPDi/O2BcZ++Wpt0Kq9cl0eg6NN6bYbPnR67ZLo7St5Q3UK0SnARw=="], - "@typescript-eslint/eslint-plugin": ["@typescript-eslint/eslint-plugin@8.4.0", "", { "dependencies": { "@eslint-community/regexpp": "^4.10.0", "@typescript-eslint/scope-manager": "8.4.0", "@typescript-eslint/type-utils": "8.4.0", "@typescript-eslint/utils": "8.4.0", "@typescript-eslint/visitor-keys": "8.4.0", "graphemer": "^1.4.0", "ignore": "^5.3.1", "natural-compare": "^1.4.0", "ts-api-utils": "^1.3.0" }, "peerDependencies": { "@typescript-eslint/parser": "^8.0.0 || ^8.0.0-alpha.0", "eslint": "^8.57.0 || ^9.0.0" } }, "sha512-rg8LGdv7ri3oAlenMACk9e+AR4wUV0yrrG+XKsGKOK0EVgeEDqurkXMPILG2836fW4ibokTB5v4b6Z9+GYQDEw=="], + "@typescript-eslint/eslint-plugin": ["@typescript-eslint/eslint-plugin@8.32.1", "", { "dependencies": { "@eslint-community/regexpp": "^4.10.0", "@typescript-eslint/scope-manager": "8.32.1", "@typescript-eslint/type-utils": "8.32.1", "@typescript-eslint/utils": "8.32.1", "@typescript-eslint/visitor-keys": "8.32.1", "graphemer": "^1.4.0", "ignore": "^7.0.0", "natural-compare": "^1.4.0", "ts-api-utils": "^2.1.0" }, "peerDependencies": { "@typescript-eslint/parser": "^8.0.0 || ^8.0.0-alpha.0", "eslint": "^8.57.0 || ^9.0.0", "typescript": ">=4.8.4 <5.9.0" } }, "sha512-6u6Plg9nP/J1GRpe/vcjjabo6Uc5YQPAMxsgQyGC/I0RuukiG1wIe3+Vtg3IrSCVJDmqK3j8adrtzXSENRtFgg=="], - "@typescript-eslint/parser": ["@typescript-eslint/parser@8.4.0", "", { "dependencies": { "@typescript-eslint/scope-manager": "8.4.0", "@typescript-eslint/types": "8.4.0", "@typescript-eslint/typescript-estree": "8.4.0", "@typescript-eslint/visitor-keys": "8.4.0", "debug": "^4.3.4" }, "peerDependencies": { "eslint": "^8.57.0 || ^9.0.0" } }, "sha512-NHgWmKSgJk5K9N16GIhQ4jSobBoJwrmURaLErad0qlLjrpP5bECYg+wxVTGlGZmJbU03jj/dfnb6V9bw+5icsA=="], + "@typescript-eslint/parser": ["@typescript-eslint/parser@8.32.1", "", { "dependencies": { "@typescript-eslint/scope-manager": "8.32.1", "@typescript-eslint/types": "8.32.1", "@typescript-eslint/typescript-estree": "8.32.1", "@typescript-eslint/visitor-keys": "8.32.1", "debug": "^4.3.4" }, "peerDependencies": { "eslint": "^8.57.0 || ^9.0.0", "typescript": ">=4.8.4 <5.9.0" } }, "sha512-LKMrmwCPoLhM45Z00O1ulb6jwyVr2kr3XJp+G+tSEZcbauNnScewcQwtJqXDhXeYPDEjZ8C1SjXm015CirEmGg=="], - "@typescript-eslint/scope-manager": ["@typescript-eslint/scope-manager@8.4.0", "", { "dependencies": { "@typescript-eslint/types": "8.4.0", "@typescript-eslint/visitor-keys": "8.4.0" } }, "sha512-n2jFxLeY0JmKfUqy3P70rs6vdoPjHK8P/w+zJcV3fk0b0BwRXC/zxRTEnAsgYT7MwdQDt/ZEbtdzdVC+hcpF0A=="], + "@typescript-eslint/scope-manager": ["@typescript-eslint/scope-manager@8.32.1", "", { "dependencies": { "@typescript-eslint/types": "8.32.1", "@typescript-eslint/visitor-keys": "8.32.1" } }, "sha512-7IsIaIDeZn7kffk7qXC3o6Z4UblZJKV3UBpkvRNpr5NSyLji7tvTcvmnMNYuYLyh26mN8W723xpo3i4MlD33vA=="], - "@typescript-eslint/type-utils": ["@typescript-eslint/type-utils@8.4.0", "", { "dependencies": { "@typescript-eslint/typescript-estree": "8.4.0", "@typescript-eslint/utils": "8.4.0", "debug": "^4.3.4", "ts-api-utils": "^1.3.0" } }, "sha512-pu2PAmNrl9KX6TtirVOrbLPLwDmASpZhK/XU7WvoKoCUkdtq9zF7qQ7gna0GBZFN0hci0vHaSusiL2WpsQk37A=="], + "@typescript-eslint/type-utils": ["@typescript-eslint/type-utils@8.32.1", "", { "dependencies": { "@typescript-eslint/typescript-estree": "8.32.1", "@typescript-eslint/utils": "8.32.1", "debug": "^4.3.4", "ts-api-utils": "^2.1.0" }, "peerDependencies": { "eslint": "^8.57.0 || ^9.0.0", "typescript": ">=4.8.4 <5.9.0" } }, "sha512-mv9YpQGA8iIsl5KyUPi+FGLm7+bA4fgXaeRcFKRDRwDMu4iwrSHeDPipwueNXhdIIZltwCJv+NkxftECbIZWfA=="], - "@typescript-eslint/types": ["@typescript-eslint/types@8.4.0", "", {}, "sha512-T1RB3KQdskh9t3v/qv7niK6P8yvn7ja1mS7QK7XfRVL6wtZ8/mFs/FHf4fKvTA0rKnqnYxl/uHFNbnEt0phgbw=="], + "@typescript-eslint/types": ["@typescript-eslint/types@8.32.1", "", {}, "sha512-YmybwXUJcgGqgAp6bEsgpPXEg6dcCyPyCSr0CAAueacR/CCBi25G3V8gGQ2kRzQRBNol7VQknxMs9HvVa9Rvfg=="], - "@typescript-eslint/typescript-estree": ["@typescript-eslint/typescript-estree@8.4.0", "", { "dependencies": { "@typescript-eslint/types": "8.4.0", "@typescript-eslint/visitor-keys": "8.4.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" } }, "sha512-kJ2OIP4dQw5gdI4uXsaxUZHRwWAGpREJ9Zq6D5L0BweyOrWsL6Sz0YcAZGWhvKnH7fm1J5YFE1JrQL0c9dd53A=="], + "@typescript-eslint/typescript-estree": ["@typescript-eslint/typescript-estree@8.32.1", "", { "dependencies": { "@typescript-eslint/types": "8.32.1", "@typescript-eslint/visitor-keys": "8.32.1", "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": "^2.1.0" }, "peerDependencies": { "typescript": ">=4.8.4 <5.9.0" } }, "sha512-Y3AP9EIfYwBb4kWGb+simvPaqQoT5oJuzzj9m0i6FCY6SPvlomY2Ei4UEMm7+FXtlNJbor80ximyslzaQF6xhg=="], - "@typescript-eslint/utils": ["@typescript-eslint/utils@8.4.0", "", { "dependencies": { "@eslint-community/eslint-utils": "^4.4.0", "@typescript-eslint/scope-manager": "8.4.0", "@typescript-eslint/types": "8.4.0", "@typescript-eslint/typescript-estree": "8.4.0" }, "peerDependencies": { "eslint": "^8.57.0 || ^9.0.0" } }, "sha512-swULW8n1IKLjRAgciCkTCafyTHHfwVQFt8DovmaF69sKbOxTSFMmIZaSHjqO9i/RV0wIblaawhzvtva8Nmm7lQ=="], + "@typescript-eslint/utils": ["@typescript-eslint/utils@8.32.1", "", { "dependencies": { "@eslint-community/eslint-utils": "^4.7.0", "@typescript-eslint/scope-manager": "8.32.1", "@typescript-eslint/types": "8.32.1", "@typescript-eslint/typescript-estree": "8.32.1" }, "peerDependencies": { "eslint": "^8.57.0 || ^9.0.0", "typescript": ">=4.8.4 <5.9.0" } }, "sha512-DsSFNIgLSrc89gpq1LJB7Hm1YpuhK086DRDJSNrewcGvYloWW1vZLHBTIvarKZDcAORIy/uWNx8Gad+4oMpkSA=="], - "@typescript-eslint/visitor-keys": ["@typescript-eslint/visitor-keys@8.4.0", "", { "dependencies": { "@typescript-eslint/types": "8.4.0", "eslint-visitor-keys": "^3.4.3" } }, "sha512-zTQD6WLNTre1hj5wp09nBIDiOc2U5r/qmzo7wxPn4ZgAjHql09EofqhF9WF+fZHzL5aCyaIpPcT2hyxl73kr9A=="], + "@typescript-eslint/visitor-keys": ["@typescript-eslint/visitor-keys@8.32.1", "", { "dependencies": { "@typescript-eslint/types": "8.32.1", "eslint-visitor-keys": "^4.2.0" } }, "sha512-ar0tjQfObzhSaW3C3QNmTc5ofj0hDoNQ5XWrCy6zDyabdr0TWhCkClp+rywGNj/odAFBVzzJrK4tEq5M4Hmu4w=="], "@vitest/expect": ["@vitest/expect@3.1.4", "", { "dependencies": { "@vitest/spy": "3.1.4", "@vitest/utils": "3.1.4", "chai": "^5.2.0", "tinyrainbow": "^2.0.0" } }, "sha512-xkD/ljeliyaClDYqHPNCiJ0plY5YIcM0OlRiZizLhlPmpXWpxnGMyTZXOHFhFeG7w9P5PBeL4IdtJ/HeQwTbQA=="], @@ -239,14 +299,12 @@ "@vitest/utils": ["@vitest/utils@3.1.4", "", { "dependencies": { "@vitest/pretty-format": "3.1.4", "loupe": "^3.1.3", "tinyrainbow": "^2.0.0" } }, "sha512-yriMuO1cfFhmiGc8ataN51+9ooHRuURdfAZfwFd3usWynjzpLslZdYnRegTv32qdgtJTsj15FoeZe2g15fY1gg=="], - "acorn": ["acorn@8.12.1", "", { "bin": { "acorn": "bin/acorn" } }, "sha512-tcpGyI9zbizT9JbV6oYE477V6mTlXvvi0T0G3SNIYE2apm/G5huBa1+K89VGeovbg+jycCrfhl3ADxErOuO6Jg=="], + "acorn": ["acorn@8.14.1", "", { "bin": { "acorn": "bin/acorn" } }, "sha512-OvQ/2pUDKmgfCg++xsTX1wGxfTaszcHVcTctW4UJB4hibJx2HXxxO5UmVgyjMa+ZDsiaf5wWLXYpRWMmBI0QHg=="], "acorn-jsx": ["acorn-jsx@5.3.2", "", { "peerDependencies": { "acorn": "^6.0.0 || ^7.0.0 || ^8.0.0" } }, "sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ=="], "ajv": ["ajv@6.12.6", "", { "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" } }, "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g=="], - "ansi-regex": ["ansi-regex@5.0.1", "", {}, "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ=="], - "ansi-styles": ["ansi-styles@4.3.0", "", { "dependencies": { "color-convert": "^2.0.1" } }, "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg=="], "ansis": ["ansis@4.0.0", "", {}, "sha512-P8nrHI1EyW9OfBt1X7hMSwGN2vwRuqHSKJAT1gbLWZRzDa24oHjYwGHvEgHeBepupzk878yS/HBZ0NMPYtbolw=="], @@ -269,9 +327,9 @@ "braces": ["braces@3.0.3", "", { "dependencies": { "fill-range": "^7.1.1" } }, "sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA=="], - "browserslist": ["browserslist@4.23.3", "", { "dependencies": { "caniuse-lite": "^1.0.30001646", "electron-to-chromium": "^1.5.4", "node-releases": "^2.0.18", "update-browserslist-db": "^1.1.0" }, "bin": { "browserslist": "cli.js" } }, "sha512-btwCFJVjI4YWDNfau8RhZ+B1Q/VLoUITrm3RlP6y1tYGWIOa+InuYiRGXUBXo8nA1qKmHMyLB/iVQg5TT4eFoA=="], + "browserslist": ["browserslist@4.24.5", "", { "dependencies": { "caniuse-lite": "^1.0.30001716", "electron-to-chromium": "^1.5.149", "node-releases": "^2.0.19", "update-browserslist-db": "^1.1.3" }, "bin": { "browserslist": "cli.js" } }, "sha512-FDToo4Wo82hIdgc1CQ+NQD0hEhmpPjrZ3hiUgwgOG6IuTdlpr8jdjyG24P6cNP1yJpTLzS5OcGgSw0xmDU1/Tw=="], - "builtin-modules": ["builtin-modules@3.3.0", "", {}, "sha512-zhaCDicdLuWN5UbN5IMnFqNMhNfo919sH85y2/ea+5Yg9TsTkeZxpL+JLbp6cgYFS4sRLp3YV4S6yDuqVWHYOw=="], + "builtin-modules": ["builtin-modules@5.0.0", "", {}, "sha512-bkXY9WsVpY7CvMhKSR6pZilZu9Ln5WDrKVBUXf2S443etkmEO4V58heTecXcUIsNsi4Rx8JUO4NfX1IcQl4deg=="], "bun-types": ["bun-types@1.2.14", "", { "dependencies": { "@types/node": "*" } }, "sha512-Kuh4Ub28ucMRWeiUUWMHsT9Wcbr4H3kLIO72RZZElSDxSu7vpetRvxIUDUaW6QtaIeixIpm7OXtNnZPf82EzwA=="], @@ -279,7 +337,7 @@ "callsites": ["callsites@3.1.0", "", {}, "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ=="], - "caniuse-lite": ["caniuse-lite@1.0.30001657", "", {}, "sha512-DPbJAlP8/BAXy3IgiWmZKItubb3TYGP0WscQQlVGIfT4s/YlFYVuJgyOsQNP7rJRChx/qdMeLJQJP0Sgg2yjNA=="], + "caniuse-lite": ["caniuse-lite@1.0.30001718", "", {}, "sha512-AflseV1ahcSunK53NfEs9gFWgOEmzr0f+kaMFA4xiLZlr9Hzt7HxcSpIFcnNCUkz6R6dWKa54rUz3HUmI3nVcw=="], "chai": ["chai@5.2.0", "", { "dependencies": { "assertion-error": "^2.0.1", "check-error": "^2.1.1", "deep-eql": "^5.0.1", "loupe": "^3.1.0", "pathval": "^2.0.0" } }, "sha512-mCuXncKXk5iCLhfhwTc0izo0gtEmpz5CtG2y8GiOINBlMVS6v8TMRc5TaLWKS6692m9+dVVfzgeVxR5UxWHTYw=="], @@ -289,7 +347,7 @@ "chokidar": ["chokidar@4.0.3", "", { "dependencies": { "readdirp": "^4.0.1" } }, "sha512-Qgzu8kfBvo+cA4962jnP1KkS6Dop5NS6g7R5LFYJr4b8Ub94PPQXUksCw9PvXoeXPRRddRNC5C1JQUR2SMGtnA=="], - "ci-info": ["ci-info@4.0.0", "", {}, "sha512-TdHqgGf9odd8SXNuxtUBVx8Nv+qZOejE6qyqiy5NtbYYQOeFa6zmHkxlPzmaLxWWHsU6nJmB7AETdVPi+2NBUg=="], + "ci-info": ["ci-info@4.2.0", "", {}, "sha512-cYY9mypksY8NRqgDB1XD1RiJL338v/551niynFTGkZOO2LHuB2OmOYxDIe/ttN9AHwrqdum1360G3ald0W9kCg=="], "clean-regexp": ["clean-regexp@1.0.0", "", { "dependencies": { "escape-string-regexp": "^1.0.5" } }, "sha512-GfisEZEJvzKrmGWkvfhgzcz/BllN1USeqD2V6tg14OAOgaCD2Z/PUEuxnAZ/nPvmaHRG7a8y77p1T/IRQ4D1Hw=="], @@ -303,13 +361,13 @@ "confbox": ["confbox@0.2.2", "", {}, "sha512-1NB+BKqhtNipMsov4xI/NnhCKp9XG9NamYp5PVm9klAT0fsrNPjaFICsCFhNhwZJKNh7zB/3q8qXz0E9oaMNtQ=="], - "core-js-compat": ["core-js-compat@3.38.1", "", { "dependencies": { "browserslist": "^4.23.3" } }, "sha512-JRH6gfXxGmrzF3tZ57lFx97YARxCXPaMzPo6jELZhv88pBH5VXpQ+y0znKGlFnzuaihqhLbefxSJxWJMPtfDzw=="], + "core-js-compat": ["core-js-compat@3.42.0", "", { "dependencies": { "browserslist": "^4.24.4" } }, "sha512-bQasjMfyDGyaeWKBIu33lHh9qlSR0MFE/Nmc6nMjf/iU9b3rSMdAYz1Baxrv4lPdGUsTqZudHA4jIGSJy0SWZQ=="], - "cross-spawn": ["cross-spawn@7.0.3", "", { "dependencies": { "path-key": "^3.1.0", "shebang-command": "^2.0.0", "which": "^2.0.1" } }, "sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w=="], + "cross-spawn": ["cross-spawn@7.0.6", "", { "dependencies": { "path-key": "^3.1.0", "shebang-command": "^2.0.0", "which": "^2.0.1" } }, "sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA=="], "cssesc": ["cssesc@3.0.0", "", { "bin": { "cssesc": "bin/cssesc" } }, "sha512-/Tb/JcjK111nNScGob5MNtsntNM1aCNUDipB/TkwZFhyDrrE47SOx/18wF2bbjgc3ZzCSKW1T5nt5EbFoAz/Vg=="], - "debug": ["debug@4.3.6", "", { "dependencies": { "ms": "2.1.2" } }, "sha512-O/09Bd4Z1fBrU4VzkhFqVgpPzaGbw6Sm9FEkBT1A/YBXQFGuuSxa1dN2nxgxS34JmKXqYx8CZAwEVoJFImUXIg=="], + "debug": ["debug@4.4.1", "", { "dependencies": { "ms": "^2.1.3" } }, "sha512-KcKCqiftBJcZr++7ykoDIEwSa3XWowTfNPo92BYxjXiyYEVrUQh2aLyhxBCwww+heortUFxEJYcRzosstTEBYQ=="], "deep-eql": ["deep-eql@5.0.2", "", {}, "sha512-h5k/5U50IJJFpzfL6nO9jaaumfjO/f2NjK/oYB2Djzm4p9L+3T9qWpZqZ2hAbLPuuYq9wrU08WQyBTL5GbPk5Q=="], @@ -317,18 +375,18 @@ "defu": ["defu@6.1.4", "", {}, "sha512-mEQCMmwJu317oSz8CwdIOdwf3xMif1ttiM8LTufzc3g6kR+9Pe236twL8j3IYT1F7GfRgGcW6MWxzZjLIkuHIg=="], + "detect-libc": ["detect-libc@2.0.4", "", {}, "sha512-3UDv+G9CsCKO1WKMGw9fwq/SWJYbI0c5Y7LU1AXYoDdbhE2AHQ6N6Nb34sG8Fj7T5APy8qXDCKuuIHd1BR0tVA=="], + "diff": ["diff@8.0.2", "", {}, "sha512-sSuxWU5j5SR9QQji/o2qMvqRNYRDOcBTgsJ/DeCf4iSN4gW+gNMXM7wFIP+fdXZxoNiAnHUTGjCr+TSWXdRDKg=="], "dts-resolver": ["dts-resolver@2.0.1", "", { "peerDependencies": { "oxc-resolver": "^9.0.2" }, "optionalPeers": ["oxc-resolver"] }, "sha512-Pe2kqaQTNVxleYpt9Q9658fn6rEpoZbMbDpEBbcU6pnuGM3Q0IdM+Rv67kN6qcyp8Bv2Uv9NYy5Y1rG1LSgfoQ=="], - "electron-to-chromium": ["electron-to-chromium@1.5.14", "", {}, "sha512-bEfPECb3fJ15eaDnu9LEJ2vPGD6W1vt7vZleSVyFhYuMIKm3vz/g9lt7IvEzgdwj58RjbPKUF2rXTCN/UW47tQ=="], + "electron-to-chromium": ["electron-to-chromium@1.5.159", "", {}, "sha512-CEvHptWAMV5p6GJ0Lq8aheyvVbfzVrv5mmidu1D3pidoVNkB3tTBsTMVtPJ+rzRK5oV229mCLz9Zj/hNvU8GBA=="], "empathic": ["empathic@1.1.0", "", {}, "sha512-rsPft6CK3eHtrlp9Y5ALBb+hfK+DWnA4WFebbazxjWyx8vSm3rZeoM3z9irsjcqO3PYRzlfv27XIB4tz2DV7RA=="], "enhanced-resolve": ["enhanced-resolve@5.17.1", "", { "dependencies": { "graceful-fs": "^4.2.4", "tapable": "^2.2.0" } }, "sha512-LMHl3dXhTcfv8gM4kEzIUeTQ+7fpdA0l2tUf34BddXPkz2A5xJ5L/Pchd5BL6rdccM9QGvu0sWZzK1Z1t4wwyg=="], - "error-ex": ["error-ex@1.3.2", "", { "dependencies": { "is-arrayish": "^0.2.1" } }, "sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g=="], - "es-module-lexer": ["es-module-lexer@1.7.0", "", {}, "sha512-jEQoCwk8hyb2AZziIOLhDqpm5+2ww5uIE6lkO/6jcOCusfk6LhMHpXXfBLXTZ7Ydyt0j4VoUQv6uGNYbdW+kBA=="], "esbuild": ["esbuild@0.21.5", "", { "optionalDependencies": { "@esbuild/aix-ppc64": "0.21.5", "@esbuild/android-arm": "0.21.5", "@esbuild/android-arm64": "0.21.5", "@esbuild/android-x64": "0.21.5", "@esbuild/darwin-arm64": "0.21.5", "@esbuild/darwin-x64": "0.21.5", "@esbuild/freebsd-arm64": "0.21.5", "@esbuild/freebsd-x64": "0.21.5", "@esbuild/linux-arm": "0.21.5", "@esbuild/linux-arm64": "0.21.5", "@esbuild/linux-ia32": "0.21.5", "@esbuild/linux-loong64": "0.21.5", "@esbuild/linux-mips64el": "0.21.5", "@esbuild/linux-ppc64": "0.21.5", "@esbuild/linux-riscv64": "0.21.5", "@esbuild/linux-s390x": "0.21.5", "@esbuild/linux-x64": "0.21.5", "@esbuild/netbsd-x64": "0.21.5", "@esbuild/openbsd-x64": "0.21.5", "@esbuild/sunos-x64": "0.21.5", "@esbuild/win32-arm64": "0.21.5", "@esbuild/win32-ia32": "0.21.5", "@esbuild/win32-x64": "0.21.5" }, "bin": { "esbuild": "bin/esbuild" } }, "sha512-mg3OPMV4hXywwpoDxu3Qda5xCKQi+vCTZq8S9J/EpkhB2HzKXq4SNFZE3+NK93JYxc8VMSep+lOUSC/RVKaBqw=="], @@ -337,27 +395,27 @@ "escape-string-regexp": ["escape-string-regexp@4.0.0", "", {}, "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA=="], - "eslint": ["eslint@9.10.0", "", { "dependencies": { "@eslint-community/eslint-utils": "^4.2.0", "@eslint-community/regexpp": "^4.11.0", "@eslint/config-array": "^0.18.0", "@eslint/eslintrc": "^3.1.0", "@eslint/js": "9.10.0", "@eslint/plugin-kit": "^0.1.0", "@humanwhocodes/module-importer": "^1.0.1", "@humanwhocodes/retry": "^0.3.0", "@nodelib/fs.walk": "^1.2.8", "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.0.2", "eslint-visitor-keys": "^4.0.0", "espree": "^10.1.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", "is-path-inside": "^3.0.3", "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", "strip-ansi": "^6.0.1", "text-table": "^0.2.0" }, "peerDependencies": { "jiti": "*" }, "optionalPeers": ["jiti"], "bin": { "eslint": "bin/eslint.js" } }, "sha512-Y4D0IgtBZfOcOUAIQTSXBKoNGfY0REGqHJG6+Q81vNippW5YlKjHFj4soMxamKK1NXHUWuBZTLdU3Km+L/pcHw=="], + "eslint": ["eslint@9.27.0", "", { "dependencies": { "@eslint-community/eslint-utils": "^4.2.0", "@eslint-community/regexpp": "^4.12.1", "@eslint/config-array": "^0.20.0", "@eslint/config-helpers": "^0.2.1", "@eslint/core": "^0.14.0", "@eslint/eslintrc": "^3.3.1", "@eslint/js": "9.27.0", "@eslint/plugin-kit": "^0.3.1", "@humanfs/node": "^0.16.6", "@humanwhocodes/module-importer": "^1.0.1", "@humanwhocodes/retry": "^0.4.2", "@types/estree": "^1.0.6", "@types/json-schema": "^7.0.15", "ajv": "^6.12.4", "chalk": "^4.0.0", "cross-spawn": "^7.0.6", "debug": "^4.3.2", "escape-string-regexp": "^4.0.0", "eslint-scope": "^8.3.0", "eslint-visitor-keys": "^4.2.0", "espree": "^10.3.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" }, "peerDependencies": { "jiti": "*" }, "optionalPeers": ["jiti"], "bin": { "eslint": "bin/eslint.js" } }, "sha512-ixRawFQuMB9DZ7fjU3iGGganFDp3+45bPOdaRurcFHSXO1e/sYwUX/FtQZpLZJR6SjMoJH8hR2pPEAfDyCoU2Q=="], "eslint-compat-utils": ["eslint-compat-utils@0.5.1", "", { "dependencies": { "semver": "^7.5.4" }, "peerDependencies": { "eslint": ">=6.0.0" } }, "sha512-3z3vFexKIEnjHE3zCMRo6fn/e44U7T1khUjg+Hp0ZQMCigh28rALD0nPFBcGZuiLC5rLZa2ubQHDRln09JfU2Q=="], "eslint-plugin-es-x": ["eslint-plugin-es-x@7.8.0", "", { "dependencies": { "@eslint-community/eslint-utils": "^4.1.2", "@eslint-community/regexpp": "^4.11.0", "eslint-compat-utils": "^0.5.1" }, "peerDependencies": { "eslint": ">=8" } }, "sha512-7Ds8+wAAoV3T+LAKeu39Y5BzXCrGKrcISfgKEqTS4BDN8SFEDQd0S43jiQ8vIa3wUKD07qitZdfzlenSi8/0qQ=="], - "eslint-plugin-jsdoc": ["eslint-plugin-jsdoc@48.11.0", "", { "dependencies": { "@es-joy/jsdoccomment": "~0.46.0", "are-docs-informative": "^0.0.2", "comment-parser": "1.4.1", "debug": "^4.3.5", "escape-string-regexp": "^4.0.0", "espree": "^10.1.0", "esquery": "^1.6.0", "parse-imports": "^2.1.1", "semver": "^7.6.3", "spdx-expression-parse": "^4.0.0", "synckit": "^0.9.1" }, "peerDependencies": { "eslint": "^7.0.0 || ^8.0.0 || ^9.0.0" } }, "sha512-d12JHJDPNo7IFwTOAItCeJY1hcqoIxE0lHA8infQByLilQ9xkqrRa6laWCnsuCrf+8rUnvxXY1XuTbibRBNylA=="], + "eslint-plugin-jsdoc": ["eslint-plugin-jsdoc@50.6.17", "", { "dependencies": { "@es-joy/jsdoccomment": "~0.50.1", "are-docs-informative": "^0.0.2", "comment-parser": "1.4.1", "debug": "^4.3.6", "escape-string-regexp": "^4.0.0", "espree": "^10.1.0", "esquery": "^1.6.0", "parse-imports-exports": "^0.2.4", "semver": "^7.6.3", "spdx-expression-parse": "^4.0.0" }, "peerDependencies": { "eslint": "^7.0.0 || ^8.0.0 || ^9.0.0" } }, "sha512-hq+VQylhd12l8qjexyriDsejZhqiP33WgMTy2AmaGZ9+MrMWVqPECsM87GPxgHfQn0zw+YTuhqjUfk1f+q67aQ=="], - "eslint-plugin-n": ["eslint-plugin-n@17.10.2", "", { "dependencies": { "@eslint-community/eslint-utils": "^4.4.0", "enhanced-resolve": "^5.17.0", "eslint-plugin-es-x": "^7.5.0", "get-tsconfig": "^4.7.0", "globals": "^15.8.0", "ignore": "^5.2.4", "minimatch": "^9.0.5", "semver": "^7.5.3" }, "peerDependencies": { "eslint": ">=8.23.0" } }, "sha512-e+s4eAf5NtJaxPhTNu3qMO0Iz40WANS93w9LQgYcvuljgvDmWi/a3rh+OrNyMHeng6aOWGJO0rCg5lH4zi8yTw=="], + "eslint-plugin-n": ["eslint-plugin-n@17.18.0", "", { "dependencies": { "@eslint-community/eslint-utils": "^4.5.0", "enhanced-resolve": "^5.17.1", "eslint-plugin-es-x": "^7.8.0", "get-tsconfig": "^4.8.1", "globals": "^15.11.0", "ignore": "^5.3.2", "minimatch": "^9.0.5", "semver": "^7.6.3" }, "peerDependencies": { "eslint": ">=8.23.0" } }, "sha512-hvZ/HusueqTJ7VDLoCpjN0hx4N4+jHIWTXD4TMLHy9F23XkDagR9v+xQWRWR57yY55GPF8NnD4ox9iGTxirY8A=="], - "eslint-plugin-promise": ["eslint-plugin-promise@7.1.0", "", { "peerDependencies": { "eslint": "^7.0.0 || ^8.0.0 || ^9.0.0" } }, "sha512-8trNmPxdAy3W620WKDpaS65NlM5yAumod6XeC4LOb+jxlkG4IVcp68c6dXY2ev+uT4U1PtG57YDV6EGAXN0GbQ=="], + "eslint-plugin-promise": ["eslint-plugin-promise@7.2.1", "", { "dependencies": { "@eslint-community/eslint-utils": "^4.4.0" }, "peerDependencies": { "eslint": "^7.0.0 || ^8.0.0 || ^9.0.0" } }, "sha512-SWKjd+EuvWkYaS+uN2csvj0KoP43YTu7+phKQ5v+xw6+A0gutVX2yqCeCkC3uLCJFiPfR2dD8Es5L7yUsmvEaA=="], - "eslint-plugin-unicorn": ["eslint-plugin-unicorn@55.0.0", "", { "dependencies": { "@babel/helper-validator-identifier": "^7.24.5", "@eslint-community/eslint-utils": "^4.4.0", "ci-info": "^4.0.0", "clean-regexp": "^1.0.0", "core-js-compat": "^3.37.0", "esquery": "^1.5.0", "globals": "^15.7.0", "indent-string": "^4.0.0", "is-builtin-module": "^3.2.1", "jsesc": "^3.0.2", "pluralize": "^8.0.0", "read-pkg-up": "^7.0.1", "regexp-tree": "^0.1.27", "regjsparser": "^0.10.0", "semver": "^7.6.1", "strip-indent": "^3.0.0" }, "peerDependencies": { "eslint": ">=8.56.0" } }, "sha512-n3AKiVpY2/uDcGrS3+QsYDkjPfaOrNrsfQxU9nt5nitd9KuvVXrfAvgCO9DYPSfap+Gqjw9EOrXIsBp5tlHZjA=="], + "eslint-plugin-unicorn": ["eslint-plugin-unicorn@59.0.1", "", { "dependencies": { "@babel/helper-validator-identifier": "^7.25.9", "@eslint-community/eslint-utils": "^4.5.1", "@eslint/plugin-kit": "^0.2.7", "ci-info": "^4.2.0", "clean-regexp": "^1.0.0", "core-js-compat": "^3.41.0", "esquery": "^1.6.0", "find-up-simple": "^1.0.1", "globals": "^16.0.0", "indent-string": "^5.0.0", "is-builtin-module": "^5.0.0", "jsesc": "^3.1.0", "pluralize": "^8.0.0", "regexp-tree": "^0.1.27", "regjsparser": "^0.12.0", "semver": "^7.7.1", "strip-indent": "^4.0.0" }, "peerDependencies": { "eslint": ">=9.22.0" } }, "sha512-EtNXYuWPUmkgSU2E7Ttn57LbRREQesIP1BiLn7OZLKodopKfDXfBUkC/0j6mpw2JExwf43Uf3qLSvrSvppgy8Q=="], - "eslint-plugin-vue": ["eslint-plugin-vue@9.28.0", "", { "dependencies": { "@eslint-community/eslint-utils": "^4.4.0", "globals": "^13.24.0", "natural-compare": "^1.4.0", "nth-check": "^2.1.1", "postcss-selector-parser": "^6.0.15", "semver": "^7.6.3", "vue-eslint-parser": "^9.4.3", "xml-name-validator": "^4.0.0" }, "peerDependencies": { "eslint": "^6.2.0 || ^7.0.0 || ^8.0.0 || ^9.0.0" } }, "sha512-ShrihdjIhOTxs+MfWun6oJWuk+g/LAhN+CiuOl/jjkG3l0F2AuK5NMTaWqyvBgkFtpYmyks6P4603mLmhNJW8g=="], + "eslint-plugin-vue": ["eslint-plugin-vue@10.1.0", "", { "dependencies": { "@eslint-community/eslint-utils": "^4.4.0", "natural-compare": "^1.4.0", "nth-check": "^2.1.1", "postcss-selector-parser": "^6.0.15", "semver": "^7.6.3", "xml-name-validator": "^4.0.0" }, "peerDependencies": { "eslint": "^8.57.0 || ^9.0.0", "vue-eslint-parser": "^10.0.0" } }, "sha512-/VTiJ1eSfNLw6lvG9ENySbGmcVvz6wZ9nA7ZqXlLBY2RkaF15iViYKxglWiIch12KiLAj0j1iXPYU6W4wTROFA=="], - "eslint-scope": ["eslint-scope@8.0.2", "", { "dependencies": { "esrecurse": "^4.3.0", "estraverse": "^5.2.0" } }, "sha512-6E4xmrTw5wtxnLA5wYL3WDfhZ/1bUBGOXV0zQvVRDOtrR8D0p6W7fs3JweNYhwRYeGvd/1CKX2se0/2s7Q/nJA=="], + "eslint-scope": ["eslint-scope@8.3.0", "", { "dependencies": { "esrecurse": "^4.3.0", "estraverse": "^5.2.0" } }, "sha512-pUNxi75F8MJ/GdeKtVLSbYg4ZI34J6C0C7sbL4YOp2exGwen7ZsuBqKzUhXd0qMQ362yET3z+uPwKeg/0C2XCQ=="], - "eslint-visitor-keys": ["eslint-visitor-keys@4.0.0", "", {}, "sha512-OtIRv/2GyiF6o/d8K7MYKKbXrOUBIK6SfkIRM4Z0dY3w+LiQ0vy3F57m0Z71bjbyeiWFiHJ8brqnmE6H6/jEuw=="], + "eslint-visitor-keys": ["eslint-visitor-keys@4.2.0", "", {}, "sha512-UyLnSehNt62FFhSwjZlHmeokpRK59rcz29j+F1/aDgbkbRTk7wIc9XzdoasMUbRNKDM0qQt/+BJ4BrpFeABemw=="], - "espree": ["espree@10.1.0", "", { "dependencies": { "acorn": "^8.12.0", "acorn-jsx": "^5.3.2", "eslint-visitor-keys": "^4.0.0" } }, "sha512-M1M6CpiE6ffoigIOWYO9UDP8TMUw9kqb21tf+08IgDYjCsOvCuDt4jQcZmoYxx+w7zlKw9/N0KXfto+I8/FrXA=="], + "espree": ["espree@10.3.0", "", { "dependencies": { "acorn": "^8.14.0", "acorn-jsx": "^5.3.2", "eslint-visitor-keys": "^4.2.0" } }, "sha512-0QYC8b24HWY8zjRnDTL6RiHfDbAWn63qb4LMj1Z4b076A4une81+z03Kg7l7mn/48PUTqoLptSXez8oknU8Clg=="], "esquery": ["esquery@1.6.0", "", { "dependencies": { "estraverse": "^5.1.0" } }, "sha512-ca9pw9fomFcKPvFLXhBKUK90ZvGibiGOvRJNbjljY7s7uq/5YO4BOzcYtJqExdx99rF6aAcnRxHmcUHcz6sQsg=="], @@ -391,19 +449,19 @@ "find-up": ["find-up@5.0.0", "", { "dependencies": { "locate-path": "^6.0.0", "path-exists": "^4.0.0" } }, "sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng=="], + "find-up-simple": ["find-up-simple@1.0.1", "", {}, "sha512-afd4O7zpqHeRyg4PfDQsXmlDe2PfdHtJt6Akt8jOWaApLOZk5JXs6VMR29lz03pRe9mpykrRCYIYxaJYcfpncQ=="], + "flat-cache": ["flat-cache@4.0.1", "", { "dependencies": { "flatted": "^3.2.9", "keyv": "^4.5.4" } }, "sha512-f7ccFPK3SXFHpx15UIGyRJ/FJQctuKZ0zVuN3frBo4HnK3cay9VEW0R6yPYFHC0AgqhukPzKjq22t5DmAyqGyw=="], "flatted": ["flatted@3.3.1", "", {}, "sha512-X8cqMLLie7KsNUDSdzeN8FYK9rEt4Dt67OsG/DNGnYTSDBG4uFAJFBnUeiV+zCVAvwFy56IjM9sH51jVaEhNxw=="], "fsevents": ["fsevents@2.3.3", "", { "os": "darwin" }, "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw=="], - "function-bind": ["function-bind@1.1.2", "", {}, "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA=="], - - "get-tsconfig": ["get-tsconfig@4.8.0", "", { "dependencies": { "resolve-pkg-maps": "^1.0.0" } }, "sha512-Pgba6TExTZ0FJAn1qkJAjIeKoDJ3CsI2ChuLohJnZl/tTU8MVrq3b+2t5UOPfRa4RMsorClBjJALkJUMjG1PAw=="], + "get-tsconfig": ["get-tsconfig@4.10.1", "", { "dependencies": { "resolve-pkg-maps": "^1.0.0" } }, "sha512-auHyJ4AgMz7vgS8Hp3N6HXSmlMdUyhSUrfBF16w153rxtLIEOE+HGqaBppczZvnHLqQJfiHotCYpNhl0lUROFQ=="], "glob-parent": ["glob-parent@6.0.2", "", { "dependencies": { "is-glob": "^4.0.3" } }, "sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A=="], - "globals": ["globals@15.9.0", "", {}, "sha512-SmSKyLLKFbSr6rptvP8izbyxJL4ILwqO9Jg23UA0sDlGlu58V59D1//I3vlc0KJphVdUR7vMjHIplYnzBxorQA=="], + "globals": ["globals@15.15.0", "", {}, "sha512-7ACyT3wmyp3I61S4fG682L0VA2RGD9otkqGJIwNUMF1SWUombIIk+af1unuDYgMm082aHYwD+mzJvv9Iu8dsgg=="], "graceful-fs": ["graceful-fs@4.2.11", "", {}, "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ=="], @@ -411,25 +469,17 @@ "has-flag": ["has-flag@4.0.0", "", {}, "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ=="], - "hasown": ["hasown@2.0.2", "", { "dependencies": { "function-bind": "^1.1.2" } }, "sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ=="], - "hookable": ["hookable@5.5.3", "", {}, "sha512-Yc+BQe8SvoXH1643Qez1zqLRmbA5rCL+sSmk6TVos0LWVfNIB7PGncdlId77WzLGSIB5KaWgTaNTs2lNVEI6VQ=="], - "hosted-git-info": ["hosted-git-info@2.8.9", "", {}, "sha512-mxIDAb9Lsm6DoOJ7xH+5+X4y1LU/4Hi50L9C5sIswK3JzULS4bwk1FvjdBgvYR4bzT4tuUQiC15FE2f5HbLvYw=="], - "ignore": ["ignore@5.3.2", "", {}, "sha512-hsBTNUqQTDwkWtcdYI2i06Y/nUBEsNEDJKjWdigLvegy8kDuJAS8uRlpkkcQpyEXL0Z/pjDy5HBmMjRCJ2gq+g=="], "import-fresh": ["import-fresh@3.3.0", "", { "dependencies": { "parent-module": "^1.0.0", "resolve-from": "^4.0.0" } }, "sha512-veYYhQa+D1QBKznvhUHxb8faxlrwUnxseDAbAp457E0wLNio2bOSKnjYDhMj+YiAq61xrMGhQk9iXVk5FzgQMw=="], "imurmurhash": ["imurmurhash@0.1.4", "", {}, "sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA=="], - "indent-string": ["indent-string@4.0.0", "", {}, "sha512-EdDDZu4A2OyIK7Lr/2zG+w5jmbuk1DVBnEwREQvBzspBJkCEbRa8GxU1lghYcaGJCnRWibjDXlq779X1/y5xwg=="], + "indent-string": ["indent-string@5.0.0", "", {}, "sha512-m6FAo/spmsW2Ab2fU35JTYwtOKa2yAwXSwgjSv1TJzh4Mh7mC3lzAOVLBprb72XsTrgkEIsl7YrFNAiDiRhIGg=="], - "is-arrayish": ["is-arrayish@0.2.1", "", {}, "sha512-zz06S8t0ozoDXMG+ube26zeCTNXcKIPJZJi8hBrF4idCLms4CG9QtK7qBl1boi5ODzFpjswb5JPmHCbMpjaYzg=="], - - "is-builtin-module": ["is-builtin-module@3.2.1", "", { "dependencies": { "builtin-modules": "^3.3.0" } }, "sha512-BSLE3HnV2syZ0FK0iMA/yUGplUeMmNz4AW5fnTunbCIqZi4vG3WjJT9FHMy5D69xmAYBHXQhJdALdpwVxV501A=="], - - "is-core-module": ["is-core-module@2.15.1", "", { "dependencies": { "hasown": "^2.0.2" } }, "sha512-z0vtXSwucUJtANQWldhbtbt7BnL0vxiFjIdDLAatwhDYty2bad6s+rijD6Ri4YuYJubLzIJLUidCh09e1djEVQ=="], + "is-builtin-module": ["is-builtin-module@5.0.0", "", { "dependencies": { "builtin-modules": "^5.0.0" } }, "sha512-f4RqJKBUe5rQkJ2eJEJBXSticB3hGbN9j0yxxMQFqIW89Jp9WYFtzfTcRlstDKVUTRzSOTLKRfO9vIztenwtxA=="], "is-extglob": ["is-extglob@2.1.1", "", {}, "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ=="], @@ -437,8 +487,6 @@ "is-number": ["is-number@7.0.0", "", {}, "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng=="], - "is-path-inside": ["is-path-inside@3.0.3", "", {}, "sha512-Fd4gABb+ycGAmKou8eMftCupSir5lRxqf4aD/vd0cD2qc4HL07OjCeuHMr8Ro4CoMaeCKDB0/ECBOVWjTwUvPQ=="], - "isexe": ["isexe@2.0.0", "", {}, "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw=="], "itty-router": ["itty-router@5.0.18", "", {}, "sha512-mK3ReOt4ARAGy0V0J7uHmArG2USN2x0zprZ+u+YgmeRjXTDbaowDy3kPcsmQY6tH+uHhDgpWit9Vqmv/4rTXwA=="], @@ -449,14 +497,12 @@ "js-yaml": ["js-yaml@4.1.0", "", { "dependencies": { "argparse": "^2.0.1" }, "bin": { "js-yaml": "bin/js-yaml.js" } }, "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA=="], - "jsdoc-type-pratt-parser": ["jsdoc-type-pratt-parser@4.0.0", "", {}, "sha512-YtOli5Cmzy3q4dP26GraSOeAhqecewG04hoO8DY56CH4KJ9Fvv5qKWUCCo3HZob7esJQHCv6/+bnTy72xZZaVQ=="], + "jsdoc-type-pratt-parser": ["jsdoc-type-pratt-parser@4.1.0", "", {}, "sha512-Hicd6JK5Njt2QB6XYFS7ok9e37O8AYk3jTcppG4YVQnYjOemymvTcmc7OWsmq/Qqj5TdRFO5/x/tIPmBeRtGHg=="], - "jsesc": ["jsesc@3.0.2", "", { "bin": { "jsesc": "bin/jsesc" } }, "sha512-xKqzzWXDttJuOcawBt4KnKHHIf5oQ/Cxax+0PWFG+DFDgHNAdi+TXECADI+RYiFUMmx8792xsMbbgXj4CwnP4g=="], + "jsesc": ["jsesc@3.1.0", "", { "bin": { "jsesc": "bin/jsesc" } }, "sha512-/sM3dO2FOzXjKQhJuo0Q173wf2KOo8t4I8vHy6lF9poUp7bKT0/NHE8fPX23PwfhnykfqnC2xRxOnVw5XuGIaA=="], "json-buffer": ["json-buffer@3.0.1", "", {}, "sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ=="], - "json-parse-even-better-errors": ["json-parse-even-better-errors@2.3.1", "", {}, "sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w=="], - "json-schema-traverse": ["json-schema-traverse@0.4.1", "", {}, "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg=="], "json-stable-stringify-without-jsonify": ["json-stable-stringify-without-jsonify@1.0.1", "", {}, "sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw=="], @@ -465,7 +511,27 @@ "levn": ["levn@0.4.1", "", { "dependencies": { "prelude-ls": "^1.2.1", "type-check": "~0.4.0" } }, "sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ=="], - "lines-and-columns": ["lines-and-columns@1.2.4", "", {}, "sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg=="], + "lightningcss": ["lightningcss@1.30.1", "", { "dependencies": { "detect-libc": "^2.0.3" }, "optionalDependencies": { "lightningcss-darwin-arm64": "1.30.1", "lightningcss-darwin-x64": "1.30.1", "lightningcss-freebsd-x64": "1.30.1", "lightningcss-linux-arm-gnueabihf": "1.30.1", "lightningcss-linux-arm64-gnu": "1.30.1", "lightningcss-linux-arm64-musl": "1.30.1", "lightningcss-linux-x64-gnu": "1.30.1", "lightningcss-linux-x64-musl": "1.30.1", "lightningcss-win32-arm64-msvc": "1.30.1", "lightningcss-win32-x64-msvc": "1.30.1" } }, "sha512-xi6IyHML+c9+Q3W0S4fCQJOym42pyurFiJUHEcEyHS0CeKzia4yZDEsLlqOFykxOdHpNy0NmvVO31vcSqAxJCg=="], + + "lightningcss-darwin-arm64": ["lightningcss-darwin-arm64@1.30.1", "", { "os": "darwin", "cpu": "arm64" }, "sha512-c8JK7hyE65X1MHMN+Viq9n11RRC7hgin3HhYKhrMyaXflk5GVplZ60IxyoVtzILeKr+xAJwg6zK6sjTBJ0FKYQ=="], + + "lightningcss-darwin-x64": ["lightningcss-darwin-x64@1.30.1", "", { "os": "darwin", "cpu": "x64" }, "sha512-k1EvjakfumAQoTfcXUcHQZhSpLlkAuEkdMBsI/ivWw9hL+7FtilQc0Cy3hrx0AAQrVtQAbMI7YjCgYgvn37PzA=="], + + "lightningcss-freebsd-x64": ["lightningcss-freebsd-x64@1.30.1", "", { "os": "freebsd", "cpu": "x64" }, "sha512-kmW6UGCGg2PcyUE59K5r0kWfKPAVy4SltVeut+umLCFoJ53RdCUWxcRDzO1eTaxf/7Q2H7LTquFHPL5R+Gjyig=="], + + "lightningcss-linux-arm-gnueabihf": ["lightningcss-linux-arm-gnueabihf@1.30.1", "", { "os": "linux", "cpu": "arm" }, "sha512-MjxUShl1v8pit+6D/zSPq9S9dQ2NPFSQwGvxBCYaBYLPlCWuPh9/t1MRS8iUaR8i+a6w7aps+B4N0S1TYP/R+Q=="], + + "lightningcss-linux-arm64-gnu": ["lightningcss-linux-arm64-gnu@1.30.1", "", { "os": "linux", "cpu": "arm64" }, "sha512-gB72maP8rmrKsnKYy8XUuXi/4OctJiuQjcuqWNlJQ6jZiWqtPvqFziskH3hnajfvKB27ynbVCucKSm2rkQp4Bw=="], + + "lightningcss-linux-arm64-musl": ["lightningcss-linux-arm64-musl@1.30.1", "", { "os": "linux", "cpu": "arm64" }, "sha512-jmUQVx4331m6LIX+0wUhBbmMX7TCfjF5FoOH6SD1CttzuYlGNVpA7QnrmLxrsub43ClTINfGSYyHe2HWeLl5CQ=="], + + "lightningcss-linux-x64-gnu": ["lightningcss-linux-x64-gnu@1.30.1", "", { "os": "linux", "cpu": "x64" }, "sha512-piWx3z4wN8J8z3+O5kO74+yr6ze/dKmPnI7vLqfSqI8bccaTGY5xiSGVIJBDd5K5BHlvVLpUB3S2YCfelyJ1bw=="], + + "lightningcss-linux-x64-musl": ["lightningcss-linux-x64-musl@1.30.1", "", { "os": "linux", "cpu": "x64" }, "sha512-rRomAK7eIkL+tHY0YPxbc5Dra2gXlI63HL+v1Pdi1a3sC+tJTcFrHX+E86sulgAXeI7rSzDYhPSeHHjqFhqfeQ=="], + + "lightningcss-win32-arm64-msvc": ["lightningcss-win32-arm64-msvc@1.30.1", "", { "os": "win32", "cpu": "arm64" }, "sha512-mSL4rqPi4iXq5YVqzSsJgMVFENoa4nGTT/GjO2c0Yl9OuQfPsIfncvLrEW6RbbB24WtZ3xP/2CCmI3tNkNV4oA=="], + + "lightningcss-win32-x64-msvc": ["lightningcss-win32-x64-msvc@1.30.1", "", { "os": "win32", "cpu": "x64" }, "sha512-PVqXh48wh4T53F/1CCu8PIPCxLzWyCnn/9T5W1Jpmdy5h9Cwd+0YQS6/LwhHXSafuc61/xg9Lv5OrCby6a++jg=="], "locate-path": ["locate-path@6.0.0", "", { "dependencies": { "p-locate": "^5.0.0" } }, "sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw=="], @@ -487,40 +553,38 @@ "mri": ["mri@1.2.0", "", {}, "sha512-tzzskb3bG8LvYGFF/mDTpq3jpI6Q9wc3LEmBaghu+DdCssd1FakN7Bc0hVNmEyGq1bq3RgfkCb3cmQLpNPOroA=="], - "ms": ["ms@2.1.2", "", {}, "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w=="], + "ms": ["ms@2.1.3", "", {}, "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA=="], "nanoid": ["nanoid@3.3.7", "", { "bin": { "nanoid": "bin/nanoid.cjs" } }, "sha512-eSRppjcPIatRIMC1U6UngP8XFcz8MQWGQdt1MTBQ7NaAmvXDfvNxbvWV3x2y6CdEUciCSsDHDQZbhYaB8QEo2g=="], "natural-compare": ["natural-compare@1.4.0", "", {}, "sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw=="], - "node-releases": ["node-releases@2.0.18", "", {}, "sha512-d9VeXT4SJ7ZeOqGX6R5EM022wpL+eWPooLI+5UpWn2jCT1aosUQEhQP214x33Wkwx3JQMvIm+tIoVOdodFS40g=="], - - "normalize-package-data": ["normalize-package-data@2.5.0", "", { "dependencies": { "hosted-git-info": "^2.1.4", "resolve": "^1.10.0", "semver": "2 || 3 || 4 || 5", "validate-npm-package-license": "^3.0.1" } }, "sha512-/5CMN3T0R4XTj4DcGaexo+roZSdSFW/0AOOTROrjxzCG1wrWXEsGbRKevjlIL+ZDE4sZlJr5ED4YW0yqmkK+eA=="], + "node-releases": ["node-releases@2.0.19", "", {}, "sha512-xxOWJsBKtzAq7DY0J+DTzuz58K8e7sJbdgwkbMWQe8UYB6ekmsQ45q0M/tJDsGaZmbC+l7n57UV8Hl5tHxO9uw=="], "nth-check": ["nth-check@2.1.1", "", { "dependencies": { "boolbase": "^1.0.0" } }, "sha512-lqjrjmaOoAnWfMmBPL+XNnynZh2+swxiX3WUE0s4yEHI6m+AwrK2UZOimIRl3X/4QctVqS8AiZjFqyOGrMXb/w=="], "optionator": ["optionator@0.9.4", "", { "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" } }, "sha512-6IpQ7mKUxRcZNLIObR0hz7lxsapSSIYNZJwXPGeF0mTVqGKFIXj1DQcMoT22S3ROcLyY/rz0PWaWZ9ayWmad9g=="], + "oxc-resolver": ["oxc-resolver@9.0.2", "", { "optionalDependencies": { "@oxc-resolver/binding-darwin-arm64": "9.0.2", "@oxc-resolver/binding-darwin-x64": "9.0.2", "@oxc-resolver/binding-freebsd-x64": "9.0.2", "@oxc-resolver/binding-linux-arm-gnueabihf": "9.0.2", "@oxc-resolver/binding-linux-arm64-gnu": "9.0.2", "@oxc-resolver/binding-linux-arm64-musl": "9.0.2", "@oxc-resolver/binding-linux-riscv64-gnu": "9.0.2", "@oxc-resolver/binding-linux-s390x-gnu": "9.0.2", "@oxc-resolver/binding-linux-x64-gnu": "9.0.2", "@oxc-resolver/binding-linux-x64-musl": "9.0.2", "@oxc-resolver/binding-wasm32-wasi": "9.0.2", "@oxc-resolver/binding-win32-arm64-msvc": "9.0.2", "@oxc-resolver/binding-win32-x64-msvc": "9.0.2" } }, "sha512-w838ygc1p7rF+7+h5vR9A+Y9Fc4imy6C3xPthCMkdFUgFvUWkmABeNB8RBDQ6+afk44Q60/UMMQ+gfDUW99fBA=="], + + "oxlint": ["oxlint@0.16.12", "", { "optionalDependencies": { "@oxlint/darwin-arm64": "0.16.12", "@oxlint/darwin-x64": "0.16.12", "@oxlint/linux-arm64-gnu": "0.16.12", "@oxlint/linux-arm64-musl": "0.16.12", "@oxlint/linux-x64-gnu": "0.16.12", "@oxlint/linux-x64-musl": "0.16.12", "@oxlint/win32-arm64": "0.16.12", "@oxlint/win32-x64": "0.16.12" }, "bin": { "oxlint": "bin/oxlint", "oxc_language_server": "bin/oxc_language_server" } }, "sha512-1oN3P9bzE90zkbjLTc+uICVLwSR+eQaDaYVipS0BtmtmEd3ccQue0y7npCinb35YqKzIv1LZxhoU9nm5fgmQuw=="], + "p-limit": ["p-limit@3.1.0", "", { "dependencies": { "yocto-queue": "^0.1.0" } }, "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ=="], "p-locate": ["p-locate@5.0.0", "", { "dependencies": { "p-limit": "^3.0.2" } }, "sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw=="], - "p-try": ["p-try@2.2.0", "", {}, "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ=="], - "package-manager-detector": ["package-manager-detector@1.3.0", "", {}, "sha512-ZsEbbZORsyHuO00lY1kV3/t72yp6Ysay6Pd17ZAlNGuGwmWDLCJxFpRs0IzfXfj1o4icJOkUEioexFHzyPurSQ=="], "parent-module": ["parent-module@1.0.1", "", { "dependencies": { "callsites": "^3.0.0" } }, "sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g=="], - "parse-imports": ["parse-imports@2.1.1", "", { "dependencies": { "es-module-lexer": "^1.5.3", "slashes": "^3.0.12" } }, "sha512-TDT4HqzUiTMO1wJRwg/t/hYk8Wdp3iF/ToMIlAoVQfL1Xs/sTxq1dKWSMjMbQmIarfWKymOyly40+zmPHXMqCA=="], + "parse-imports-exports": ["parse-imports-exports@0.2.4", "", { "dependencies": { "parse-statements": "1.0.11" } }, "sha512-4s6vd6dx1AotCx/RCI2m7t7GCh5bDRUtGNvRfHSP2wbBQdMi67pPe7mtzmgwcaQ8VKK/6IB7Glfyu3qdZJPybQ=="], - "parse-json": ["parse-json@5.2.0", "", { "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" } }, "sha512-ayCKvm/phCGxOkYRSCM82iDwct8/EonSEgCSxWxD7ve6jHggsFl4fZVQBPRNgQoKiuV/odhFrGzQXZwbifC8Rg=="], + "parse-statements": ["parse-statements@1.0.11", "", {}, "sha512-HlsyYdMBnbPQ9Jr/VgJ1YF4scnldvJpJxCVx6KgqPL4dxppsWrJHCIIxQXMJrqGnsRkNPATbeMJ8Yxu7JMsYcA=="], "path-exists": ["path-exists@4.0.0", "", {}, "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w=="], "path-key": ["path-key@3.1.1", "", {}, "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q=="], - "path-parse": ["path-parse@1.0.7", "", {}, "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw=="], - "pathe": ["pathe@2.0.3", "", {}, "sha512-WUjGcAqP1gQacoQe+OBJsFA7Ld4DyXuUIjZ5cc75cLHvJ7dtNsTugphxIADwspS+AraAUePCKrSVtPLFj/F88w=="], "pathval": ["pathval@2.0.0", "", {}, "sha512-vE7JKRyES09KiunauX7nd2Q9/L7lhok4smP9RZTDeD4MVs72Dp2qNFVz39Nz5a0FVEW0BJR6C0DYrq6unoziZA=="], @@ -547,17 +611,11 @@ "queue-microtask": ["queue-microtask@1.2.3", "", {}, "sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A=="], - "read-pkg": ["read-pkg@5.2.0", "", { "dependencies": { "@types/normalize-package-data": "^2.4.0", "normalize-package-data": "^2.5.0", "parse-json": "^5.0.0", "type-fest": "^0.6.0" } }, "sha512-Ug69mNOpfvKDAc2Q8DRpMjjzdtrnv9HcSMX+4VsZxD1aZ6ZzrIE7rlzXBtWTyhULSMKg076AW6WR5iZpD0JiOg=="], - - "read-pkg-up": ["read-pkg-up@7.0.1", "", { "dependencies": { "find-up": "^4.1.0", "read-pkg": "^5.2.0", "type-fest": "^0.8.1" } }, "sha512-zK0TB7Xd6JpCLmlLmufqykGE+/TlOePD6qKClNW7hHDKFh/J7/7gCWGR7joEQEW1bKq3a3yUZSObOoWLFQ4ohg=="], - "readdirp": ["readdirp@4.1.2", "", {}, "sha512-GDhwkLfywWL2s6vEjyhri+eXmfH6j1L7JE27WhqLeYzoh/A3DBaYGEj2H/HFZCn/kMfim73FXxEJTw06WtxQwg=="], "regexp-tree": ["regexp-tree@0.1.27", "", { "bin": { "regexp-tree": "bin/regexp-tree" } }, "sha512-iETxpjK6YoRWJG5o6hXLwvjYAoW+FEZn9os0PD/b6AP6xQwsa/Y7lCVgIixBbUPMfhu+i2LtdeAqVTgGlQarfA=="], - "regjsparser": ["regjsparser@0.10.0", "", { "dependencies": { "jsesc": "~0.5.0" }, "bin": { "regjsparser": "bin/parser" } }, "sha512-qx+xQGZVsy55CH0a1hiVwHmqjLryfh7wQyF5HO07XJ9f7dQMY/gPQHhlyDkIzJKC+x2fUCpCcUODUUUFrm7SHA=="], - - "resolve": ["resolve@1.22.8", "", { "dependencies": { "is-core-module": "^2.13.0", "path-parse": "^1.0.7", "supports-preserve-symlinks-flag": "^1.0.0" }, "bin": { "resolve": "bin/resolve" } }, "sha512-oKWePCxqpd6FlLvGV1VU0x7bkPmmCNolxzjMf4NczoDnQcIWrAF+cPtZn5i6n+RfD2d9i0tzpKnG6Yk168yIyw=="], + "regjsparser": ["regjsparser@0.12.0", "", { "dependencies": { "jsesc": "~3.0.2" }, "bin": { "regjsparser": "bin/parser" } }, "sha512-cnE+y8bz4NhMjISKbgeVJtqNbtf5QpjZP+Bslo+UqkIt9QPnX9q095eiRRASJG1/tz6dlNr6Z5NsBiWYokp6EQ=="], "resolve-from": ["resolve-from@4.0.0", "", {}, "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g=="], @@ -583,12 +641,8 @@ "siginfo": ["siginfo@2.0.0", "", {}, "sha512-ybx0WO1/8bSBLEWXZvEd7gMW3Sn3JFlW3TvX1nREbDLRNQNaeNN8WK0meBwPdAaOI7TtRRRJn/Es1zhrrCHu7g=="], - "slashes": ["slashes@3.0.12", "", {}, "sha512-Q9VME8WyGkc7pJf6QEkj3wE+2CnvZMI+XJhwdTPR8Z/kWQRXi7boAWLDibRPyHRTUTPx5FaU7MsyrjI3yLB4HA=="], - "source-map-js": ["source-map-js@1.2.0", "", {}, "sha512-itJW8lvSA0TXEphiRoawsCksnlf8SyvmFzIhltqAHluXd88pkCd+cXJVHTDwdCr0IzwptSm035IHQktUu1QUMg=="], - "spdx-correct": ["spdx-correct@3.2.0", "", { "dependencies": { "spdx-expression-parse": "^3.0.0", "spdx-license-ids": "^3.0.0" } }, "sha512-kN9dJbvnySHULIluDHy32WHRUu3Og7B9sbY7tsFLctQkIqnMh3hErYgdMjTYuqmcXX+lK5T1lnUt3G7zNswmZA=="], - "spdx-exceptions": ["spdx-exceptions@2.5.0", "", {}, "sha512-PiU42r+xO4UbUS1buo3LPJkjlO7430Xn5SVAhdpzzsPHsjbYVflnnFdATgabnLude+Cqu25p6N+g2lw/PFsa4w=="], "spdx-expression-parse": ["spdx-expression-parse@4.0.0", "", { "dependencies": { "spdx-exceptions": "^2.1.0", "spdx-license-ids": "^3.0.0" } }, "sha512-Clya5JIij/7C6bRR22+tnGXbc4VKlibKSVj2iHvVeX5iMW7s1SIQlqu699JkODJJIhh/pUu8L0/VLh8xflD+LQ=="], @@ -599,22 +653,14 @@ "std-env": ["std-env@3.9.0", "", {}, "sha512-UGvjygr6F6tpH7o2qyqR6QYpwraIjKSdtzyBdyytFOHmPZY917kwdwLG0RbOjWOnKmnm3PeHjaoLLMie7kPLQw=="], - "strip-ansi": ["strip-ansi@6.0.1", "", { "dependencies": { "ansi-regex": "^5.0.1" } }, "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A=="], - - "strip-indent": ["strip-indent@3.0.0", "", { "dependencies": { "min-indent": "^1.0.0" } }, "sha512-laJTa3Jb+VQpaC6DseHhF7dXVqHTfJPCRDaEbid/drOhgitgYku/letMUqOXFoWV0zIIUbjpdH2t+tYj4bQMRQ=="], + "strip-indent": ["strip-indent@4.0.0", "", { "dependencies": { "min-indent": "^1.0.1" } }, "sha512-mnVSV2l+Zv6BLpSD/8V87CW/y9EmmbYzGCIavsnsI6/nwn26DwffM/yztm30Z/I2DY9wdS3vXVCMnHDgZaVNoA=="], "strip-json-comments": ["strip-json-comments@3.1.1", "", {}, "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig=="], "supports-color": ["supports-color@7.2.0", "", { "dependencies": { "has-flag": "^4.0.0" } }, "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw=="], - "supports-preserve-symlinks-flag": ["supports-preserve-symlinks-flag@1.0.0", "", {}, "sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w=="], - - "synckit": ["synckit@0.9.1", "", { "dependencies": { "@pkgr/core": "^0.1.0", "tslib": "^2.6.2" } }, "sha512-7gr8p9TQP6RAHusBOSLs46F4564ZrjV8xFmw5zCmgmhGUcw2hxsShhJ6CEiHQMgPDwAQ1fWHPM0ypc4RMAig4A=="], - "tapable": ["tapable@2.2.1", "", {}, "sha512-GNzQvQTOIP6RyTfE2Qxb8ZVlNmw0n88vp1szwWRimP02mnTsx3Wtn5qRdqY9w2XduFNUgvOwhNnQsjwCp+kqaQ=="], - "text-table": ["text-table@0.2.0", "", {}, "sha512-N+8UisAXDGk8PFXP4HAzVR9nbfmVJ3zYLAWiTIoqC5v5isinhr+r5uaO8+7r3BMfuNIufIsA7RdpVgacC2cSpw=="], - "tinybench": ["tinybench@2.9.0", "", {}, "sha512-0+DUvqWMValLmha6lr4kD8iAMK1HzV0/aKnCtWb9v9641TnP/MFb7Pc2bxoxQjTXAErryXVgUOfv2YqNllqGeg=="], "tinyexec": ["tinyexec@1.0.1", "", {}, "sha512-5uC6DDlmeqiOwCPmK9jMSdOuZTh8bU39Ys6yidB+UTt5hfZUPGAypSgFRiEp+jbi9qH40BLDvy85jIU88wKSqw=="], @@ -629,7 +675,7 @@ "to-regex-range": ["to-regex-range@5.0.1", "", { "dependencies": { "is-number": "^7.0.0" } }, "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ=="], - "ts-api-utils": ["ts-api-utils@1.3.0", "", { "peerDependencies": { "typescript": ">=4.2.0" } }, "sha512-UQMIo7pb8WRomKR1/+MFVLTroIvDVtMX3K6OUir8ynLyzB8Jeriont2bTAtmNPa1ekAgN7YPDyf6V+ygrdU+eQ=="], + "ts-api-utils": ["ts-api-utils@2.1.0", "", { "peerDependencies": { "typescript": ">=4.8.4" } }, "sha512-CUgTZL1irw8u29bzrOD/nH85jqyc74D6SshFgujOIA7osm2Rz7dYH77agkx7H4FBNxDq7Cjf+IjaX/8zwFW+ZQ=="], "tsdown": ["tsdown@0.12.2", "", { "dependencies": { "ansis": "^4.0.0", "cac": "^6.7.14", "chokidar": "^4.0.3", "debug": "^4.4.1", "diff": "^8.0.1", "empathic": "^1.1.0", "hookable": "^5.5.3", "rolldown": "1.0.0-beta.9-commit.51df2b7", "rolldown-plugin-dts": "^0.13.4", "semver": "^7.7.2", "tinyexec": "^1.0.1", "tinyglobby": "^0.2.13", "unconfig": "^7.3.2" }, "peerDependencies": { "publint": "^0.3.0", "typescript": "^5.0.0", "unplugin-lightningcss": "^0.4.0", "unplugin-unused": "^0.5.0" }, "optionalPeers": ["publint", "typescript", "unplugin-lightningcss", "unplugin-unused"], "bin": { "tsdown": "dist/run.js" } }, "sha512-JbBhVW799a1aOt1g8tNw5MGRuYm+xZWBkj9jMOdJJ6zSFT/pAewdQytgtgBemz4Wv3pmRLZNPK9YqUu1IVuIqA=="], @@ -641,17 +687,19 @@ "typescript": ["typescript@5.8.3", "", { "bin": { "tsc": "bin/tsc", "tsserver": "bin/tsserver" } }, "sha512-p1diW6TqL9L07nNxvRMM7hMMw4c5XOo/1ibL4aAIGmSAt9slTE1Xgw5KWuof2uTOvCg9BY7ZRi+GaF+7sfgPeQ=="], - "typescript-eslint": ["typescript-eslint@8.4.0", "", { "dependencies": { "@typescript-eslint/eslint-plugin": "8.4.0", "@typescript-eslint/parser": "8.4.0", "@typescript-eslint/utils": "8.4.0" } }, "sha512-67qoc3zQZe3CAkO0ua17+7aCLI0dU+sSQd1eKPGq06QE4rfQjstVXR6woHO5qQvGUa550NfGckT4tzh3b3c8Pw=="], + "typescript-eslint": ["typescript-eslint@8.32.1", "", { "dependencies": { "@typescript-eslint/eslint-plugin": "8.32.1", "@typescript-eslint/parser": "8.32.1", "@typescript-eslint/utils": "8.32.1" }, "peerDependencies": { "eslint": "^8.57.0 || ^9.0.0", "typescript": ">=4.8.4 <5.9.0" } }, "sha512-D7el+eaDHAmXvrZBy1zpzSNIRqnCOrkwTgZxTu3MUqRWk8k0q9m9Ho4+vPf7iHtgUfrK/o8IZaEApsxPlHTFCg=="], "unconfig": ["unconfig@7.3.2", "", { "dependencies": { "@quansync/fs": "^0.1.1", "defu": "^6.1.4", "jiti": "^2.4.2", "quansync": "^0.2.8" } }, "sha512-nqG5NNL2wFVGZ0NA/aCFw0oJ2pxSf1lwg4Z5ill8wd7K4KX/rQbHlwbh+bjctXL5Ly1xtzHenHGOK0b+lG6JVg=="], - "undici-types": ["undici-types@6.19.8", "", {}, "sha512-ve2KP6f/JnbPBFyobGHuerC9g1FYGn/F8n1LWTwNxCEzd6IfqTwUQcNXgEtmmQ6DlRrC1hrSrBnCZPokRrDHjw=="], + "undici-types": ["undici-types@6.21.0", "", {}, "sha512-iwDZqg0QAGrg9Rav5H4n0M64c3mkR59cJ6wQp+7C4nI0gsmExaedaYLNO44eT4AtBBwjbTiGPMlt2Md0T9H9JQ=="], "unplugin": ["unplugin@2.3.4", "", { "dependencies": { "acorn": "^8.14.1", "picomatch": "^4.0.2", "webpack-virtual-modules": "^0.6.2" } }, "sha512-m4PjxTurwpWfpMomp8AptjD5yj8qEZN5uQjjGM3TAs9MWWD2tXSSNNj6jGR2FoVGod4293ytyV6SwBbertfyJg=="], + "unplugin-lightningcss": ["unplugin-lightningcss@0.3.3", "", { "dependencies": { "lightningcss": "^1.29.3", "magic-string": "^0.30.17", "unplugin": "^2.3.2" } }, "sha512-mMNRCNIcxc/3410w7sJdXcPxn0IGZdEpq42OBDyckdGkhOeWYZCG9RkHs72TFyBsS82a4agFDOFU8VrFKF2ZvA=="], + "unplugin-unused": ["unplugin-unused@0.5.0", "", { "dependencies": { "js-tokens": "^9.0.1", "picocolors": "^1.1.1", "pkg-types": "^2.1.0", "unplugin": "^2.3.2" } }, "sha512-czXny3h/P/Tl5ZOnV5tSf6kswAniHjgJF0slpzBPLkq0zGGKDYa1jgWMAdbWJNu7B1YSmBJY4zf3Q/v9w0+/cg=="], - "update-browserslist-db": ["update-browserslist-db@1.1.0", "", { "dependencies": { "escalade": "^3.1.2", "picocolors": "^1.0.1" }, "peerDependencies": { "browserslist": ">= 4.21.0" }, "bin": { "update-browserslist-db": "cli.js" } }, "sha512-EdRAaAyk2cUE1wOf2DkEhzxqOQvFOoRJFNS6NeyJ01Gp2beMRpBAINjM2iDXE3KCuKhwnvHIQCJm6ThL2Z+HzQ=="], + "update-browserslist-db": ["update-browserslist-db@1.1.3", "", { "dependencies": { "escalade": "^3.2.0", "picocolors": "^1.1.1" }, "peerDependencies": { "browserslist": ">= 4.21.0" }, "bin": { "update-browserslist-db": "cli.js" } }, "sha512-UxhIZQ+QInVdunkDAaiazvvT/+fXL5Osr0JZlJulepYu6Jd7qJtDZjlur0emRlT71EN3ScPoE7gvsuIKKNavKw=="], "uri-js": ["uri-js@4.4.1", "", { "dependencies": { "punycode": "^2.1.0" } }, "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg=="], @@ -659,8 +707,6 @@ "valibot": ["valibot@1.1.0", "", { "peerDependencies": { "typescript": ">=5" }, "optionalPeers": ["typescript"] }, "sha512-Nk8lX30Qhu+9txPYTwM0cFlWLdPFsFr6LblzqIySfbZph9+BFsAHsNvHOymEviUepeIW6KFHzpX8TKhbptBXXw=="], - "validate-npm-package-license": ["validate-npm-package-license@3.0.4", "", { "dependencies": { "spdx-correct": "^3.0.0", "spdx-expression-parse": "^3.0.0" } }, "sha512-DpKm2Ui/xN7/HQKCtpZxoRWBhZ9Z0kqtygG8XCgNQ8ZlDnxuQmWhj566j8fN4Cu3/JmbhsDo7fcAJq4s9h27Ew=="], - "vite": ["vite@5.4.3", "", { "dependencies": { "esbuild": "^0.21.3", "postcss": "^8.4.43", "rollup": "^4.20.0" }, "optionalDependencies": { "fsevents": "~2.3.3" }, "peerDependencies": { "@types/node": "^18.0.0 || >=20.0.0", "less": "*", "lightningcss": "^1.21.0", "sass": "*", "sass-embedded": "*", "stylus": "*", "sugarss": "*", "terser": "^5.4.0" }, "optionalPeers": ["@types/node", "less", "lightningcss", "sass", "sass-embedded", "stylus", "sugarss", "terser"], "bin": { "vite": "bin/vite.js" } }, "sha512-IH+nl64eq9lJjFqU+/yrRnrHPVTlgy42/+IzbOdaFDVlyLgI/wDlf+FCobXLX1cT0X5+7LMyH1mIy2xJdLfo8Q=="], "vite-node": ["vite-node@3.1.4", "", { "dependencies": { "cac": "^6.7.14", "debug": "^4.4.0", "es-module-lexer": "^1.7.0", "pathe": "^2.0.3", "vite": "^5.0.0 || ^6.0.0" }, "bin": { "vite-node": "vite-node.mjs" } }, "sha512-6enNwYnpyDo4hEgytbmc6mYWHXDHYEn0D1/rw4Q+tnHUGtKTJsn8T1YkX6Q18wI5LCrS8CTYlBaiCqxOy2kvUA=="], @@ -681,80 +727,54 @@ "yocto-queue": ["yocto-queue@0.1.0", "", {}, "sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q=="], - "@babel/code-frame/picocolors": ["picocolors@1.1.0", "", {}, "sha512-TQ92mBOW0l3LeMeyLV6mzy/kWr8lkd/hp3mTg7wYK7zJhuBStmGMBG0BdeDZS/dZx1IukaX6Bk11zcln25o1Aw=="], - - "@babel/highlight/chalk": ["chalk@2.4.2", "", { "dependencies": { "ansi-styles": "^3.2.1", "escape-string-regexp": "^1.0.5", "supports-color": "^5.3.0" } }, "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ=="], + "@babel/generator/jsesc": ["jsesc@3.0.2", "", { "bin": { "jsesc": "bin/jsesc" } }, "sha512-xKqzzWXDttJuOcawBt4KnKHHIf5oQ/Cxax+0PWFG+DFDgHNAdi+TXECADI+RYiFUMmx8792xsMbbgXj4CwnP4g=="], - "@babel/highlight/js-tokens": ["js-tokens@4.0.0", "", {}, "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ=="], + "@eslint-community/eslint-utils/eslint-visitor-keys": ["eslint-visitor-keys@3.4.3", "", {}, "sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag=="], - "@babel/highlight/picocolors": ["picocolors@1.1.0", "", {}, "sha512-TQ92mBOW0l3LeMeyLV6mzy/kWr8lkd/hp3mTg7wYK7zJhuBStmGMBG0BdeDZS/dZx1IukaX6Bk11zcln25o1Aw=="], + "@eslint/eslintrc/globals": ["globals@14.0.0", "", {}, "sha512-oahGvuMGQlPw/ivIYBjVSrWAfWLBeku5tpPE2fOPLi+WHffIWbuh2tCjhyQhTBPMf5E9jDEH4FOmTYgYwbKwtQ=="], - "@babel/types/@babel/helper-validator-identifier": ["@babel/helper-validator-identifier@7.27.1", "", {}, "sha512-D2hP9eA+Sqx1kBZgzxZh0y1trbuU+JoDkiEwqhQ36nodYqJwyEIhPSdMNd7lOm/4io72luTPWH20Yda0xOuUow=="], + "@humanfs/node/@humanwhocodes/retry": ["@humanwhocodes/retry@0.3.0", "", {}, "sha512-d2CGZR2o7fS6sWB7DG/3a95bGKQyHMACZ5aW8qGkkqQpUoZV6C0X7Pc7l4ZNMZkfNBf4VWNe9E1jRsf0G146Ew=="], - "@eslint-community/eslint-utils/eslint-visitor-keys": ["eslint-visitor-keys@3.4.3", "", {}, "sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag=="], + "@typescript-eslint/eslint-plugin/@eslint-community/regexpp": ["@eslint-community/regexpp@4.11.0", "", {}, "sha512-G/M/tIiMrTAxEWRfLfQJMmGNX28IxBg4PBz8XqQhqUHLFI6TL2htpIB1iQCj144V5ee/JaKyT9/WZ0MGZWfA7A=="], - "@eslint/eslintrc/globals": ["globals@14.0.0", "", {}, "sha512-oahGvuMGQlPw/ivIYBjVSrWAfWLBeku5tpPE2fOPLi+WHffIWbuh2tCjhyQhTBPMf5E9jDEH4FOmTYgYwbKwtQ=="], + "@typescript-eslint/eslint-plugin/ignore": ["ignore@7.0.4", "", {}, "sha512-gJzzk+PQNznz8ysRrC0aOkBNVRBDtE1n53IqyqEf3PXrYwomFs5q4pGMizBMJF+ykh03insJ27hB8gSrD2Hn8A=="], "@typescript-eslint/typescript-estree/minimatch": ["minimatch@9.0.5", "", { "dependencies": { "brace-expansion": "^2.0.1" } }, "sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow=="], - "@typescript-eslint/typescript-estree/semver": ["semver@7.6.3", "", { "bin": { "semver": "bin/semver.js" } }, "sha512-oVekP1cKtI+CTDvHWYFUcMtsK/00wmAEfyqKfNdARm8u1wNVhSgaX7A8d4UuIlUI5e84iEwOhs7ZPYRmzU9U6A=="], - - "@typescript-eslint/visitor-keys/eslint-visitor-keys": ["eslint-visitor-keys@3.4.3", "", {}, "sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag=="], + "bun-types/@types/node": ["@types/node@20.16.5", "", { "dependencies": { "undici-types": "~6.19.2" } }, "sha512-VwYCweNo3ERajwy0IUlqqcyZ8/A7Zwa9ZP3MnENWcB11AejO+tLy3pu850goUW2FC/IJMdZUfKpX/yxL1gymCA=="], "clean-regexp/escape-string-regexp": ["escape-string-regexp@1.0.5", "", {}, "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg=="], "eslint-compat-utils/semver": ["semver@7.6.3", "", { "bin": { "semver": "bin/semver.js" } }, "sha512-oVekP1cKtI+CTDvHWYFUcMtsK/00wmAEfyqKfNdARm8u1wNVhSgaX7A8d4UuIlUI5e84iEwOhs7ZPYRmzU9U6A=="], - "eslint-plugin-jsdoc/semver": ["semver@7.6.3", "", { "bin": { "semver": "bin/semver.js" } }, "sha512-oVekP1cKtI+CTDvHWYFUcMtsK/00wmAEfyqKfNdARm8u1wNVhSgaX7A8d4UuIlUI5e84iEwOhs7ZPYRmzU9U6A=="], + "eslint-plugin-es-x/@eslint-community/eslint-utils": ["@eslint-community/eslint-utils@4.4.0", "", { "dependencies": { "eslint-visitor-keys": "^3.3.0" }, "peerDependencies": { "eslint": "^6.0.0 || ^7.0.0 || >=8.0.0" } }, "sha512-1/sA4dwrzBAyeUoQ6oxahHKmrZvsnLCg4RfxW3ZFGGmQkSNQPFNLV9CUEFQP1x9EYXHTo5p6xdhZM1Ne9p/AfA=="], + + "eslint-plugin-es-x/@eslint-community/regexpp": ["@eslint-community/regexpp@4.11.0", "", {}, "sha512-G/M/tIiMrTAxEWRfLfQJMmGNX28IxBg4PBz8XqQhqUHLFI6TL2htpIB1iQCj144V5ee/JaKyT9/WZ0MGZWfA7A=="], "eslint-plugin-n/minimatch": ["minimatch@9.0.5", "", { "dependencies": { "brace-expansion": "^2.0.1" } }, "sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow=="], - "eslint-plugin-n/semver": ["semver@7.6.3", "", { "bin": { "semver": "bin/semver.js" } }, "sha512-oVekP1cKtI+CTDvHWYFUcMtsK/00wmAEfyqKfNdARm8u1wNVhSgaX7A8d4UuIlUI5e84iEwOhs7ZPYRmzU9U6A=="], + "eslint-plugin-promise/@eslint-community/eslint-utils": ["@eslint-community/eslint-utils@4.4.0", "", { "dependencies": { "eslint-visitor-keys": "^3.3.0" }, "peerDependencies": { "eslint": "^6.0.0 || ^7.0.0 || >=8.0.0" } }, "sha512-1/sA4dwrzBAyeUoQ6oxahHKmrZvsnLCg4RfxW3ZFGGmQkSNQPFNLV9CUEFQP1x9EYXHTo5p6xdhZM1Ne9p/AfA=="], - "eslint-plugin-unicorn/semver": ["semver@7.6.3", "", { "bin": { "semver": "bin/semver.js" } }, "sha512-oVekP1cKtI+CTDvHWYFUcMtsK/00wmAEfyqKfNdARm8u1wNVhSgaX7A8d4UuIlUI5e84iEwOhs7ZPYRmzU9U6A=="], + "eslint-plugin-unicorn/@eslint/plugin-kit": ["@eslint/plugin-kit@0.2.8", "", { "dependencies": { "@eslint/core": "^0.13.0", "levn": "^0.4.1" } }, "sha512-ZAoA40rNMPwSm+AeHpCq8STiNAwzWLJuP8Xv4CHIc9wv/PSuExjMrmjfYNj682vW0OOiZ1HKxzvjQr9XZIisQA=="], - "eslint-plugin-vue/globals": ["globals@13.24.0", "", { "dependencies": { "type-fest": "^0.20.2" } }, "sha512-AhO5QUcj8llrbG09iWhPU2B204J1xnPeL8kQmVorSsy+Sjj1sk8gIyh6cUocGmH4L0UuhAJy+hJMRA4mgA4mFQ=="], + "eslint-plugin-unicorn/globals": ["globals@16.2.0", "", {}, "sha512-O+7l9tPdHCU320IigZZPj5zmRCFG9xHmx9cU8FqU2Rp+JN714seHV+2S9+JslCpY4gJwU2vOGox0wzgae/MCEg=="], - "eslint-plugin-vue/semver": ["semver@7.6.3", "", { "bin": { "semver": "bin/semver.js" } }, "sha512-oVekP1cKtI+CTDvHWYFUcMtsK/00wmAEfyqKfNdARm8u1wNVhSgaX7A8d4UuIlUI5e84iEwOhs7ZPYRmzU9U6A=="], + "estree-walker/@types/estree": ["@types/estree@1.0.5", "", {}, "sha512-/kYRxGDLWzHOB7q+wtSUQlFrtcdUccpfy+X+9iMBpHK8QLLhx2wIPYuS5DYtR9Wa/YlZAbIovy7qVdB1Aq6Lyw=="], "fast-glob/glob-parent": ["glob-parent@5.1.2", "", { "dependencies": { "is-glob": "^4.0.1" } }, "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow=="], "micromatch/picomatch": ["picomatch@2.3.1", "", {}, "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA=="], - "normalize-package-data/semver": ["semver@5.7.2", "", { "bin": { "semver": "bin/semver" } }, "sha512-cBznnQ9KjJqU67B52RMC65CMarK2600WFnbkcaiwWq3xy/5haFJlshgnpjovMVJ+Hff49d8GEn0b87C5pDQ10g=="], - - "parse-imports/es-module-lexer": ["es-module-lexer@1.5.4", "", {}, "sha512-MVNK56NiMrOwitFB7cqDwq0CQutbw+0BvLshJSse0MUNU+y1FC3bUS/AQg7oUng+/wKrrki7JfmwtVHkVfPLlw=="], - "postcss/picocolors": ["picocolors@1.1.0", "", {}, "sha512-TQ92mBOW0l3LeMeyLV6mzy/kWr8lkd/hp3mTg7wYK7zJhuBStmGMBG0BdeDZS/dZx1IukaX6Bk11zcln25o1Aw=="], - "read-pkg/type-fest": ["type-fest@0.6.0", "", {}, "sha512-q+MB8nYR1KDLrgr4G5yemftpMC7/QLqVndBmEEdqzmNj5dcFOO4Oo8qlwZE3ULT3+Zim1F8Kq4cBnikNhlCMlg=="], - - "read-pkg-up/find-up": ["find-up@4.1.0", "", { "dependencies": { "locate-path": "^5.0.0", "path-exists": "^4.0.0" } }, "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw=="], - - "read-pkg-up/type-fest": ["type-fest@0.8.1", "", {}, "sha512-4dbzIzqvjtgiM5rw1k5rEHtBANKmdudhGyBEajN01fEyhaAIhsoKNy6y7+IN93IfpFtwY9iqi7kD+xwKhQsNJA=="], - - "regjsparser/jsesc": ["jsesc@0.5.0", "", { "bin": { "jsesc": "bin/jsesc" } }, "sha512-uZz5UnB7u4T9LvwmFqXii7pZSouaRPorGs5who1Ip7VO0wxanFvBL7GkM6dTHlgX+jhBApRetaWpnDabOeTcnA=="], - - "rolldown-plugin-dts/debug": ["debug@4.4.1", "", { "dependencies": { "ms": "^2.1.3" } }, "sha512-KcKCqiftBJcZr++7ykoDIEwSa3XWowTfNPo92BYxjXiyYEVrUQh2aLyhxBCwww+heortUFxEJYcRzosstTEBYQ=="], - - "rolldown-plugin-dts/get-tsconfig": ["get-tsconfig@4.10.1", "", { "dependencies": { "resolve-pkg-maps": "^1.0.0" } }, "sha512-auHyJ4AgMz7vgS8Hp3N6HXSmlMdUyhSUrfBF16w153rxtLIEOE+HGqaBppczZvnHLqQJfiHotCYpNhl0lUROFQ=="], - - "spdx-correct/spdx-expression-parse": ["spdx-expression-parse@3.0.1", "", { "dependencies": { "spdx-exceptions": "^2.1.0", "spdx-license-ids": "^3.0.0" } }, "sha512-cbqHunsQWnJNE6KhVSMsMeH5H/L9EpymbzqTQ3uLwNCLZ1Q481oWaofqH7nO6V07xlXwY6PhQdQ2IedWx/ZK4Q=="], - - "tsdown/debug": ["debug@4.4.1", "", { "dependencies": { "ms": "^2.1.3" } }, "sha512-KcKCqiftBJcZr++7ykoDIEwSa3XWowTfNPo92BYxjXiyYEVrUQh2aLyhxBCwww+heortUFxEJYcRzosstTEBYQ=="], - - "unplugin/acorn": ["acorn@8.14.1", "", { "bin": { "acorn": "bin/acorn" } }, "sha512-OvQ/2pUDKmgfCg++xsTX1wGxfTaszcHVcTctW4UJB4hibJx2HXxxO5UmVgyjMa+ZDsiaf5wWLXYpRWMmBI0QHg=="], - - "update-browserslist-db/picocolors": ["picocolors@1.1.0", "", {}, "sha512-TQ92mBOW0l3LeMeyLV6mzy/kWr8lkd/hp3mTg7wYK7zJhuBStmGMBG0BdeDZS/dZx1IukaX6Bk11zcln25o1Aw=="], + "regjsparser/jsesc": ["jsesc@3.0.2", "", { "bin": { "jsesc": "bin/jsesc" } }, "sha512-xKqzzWXDttJuOcawBt4KnKHHIf5oQ/Cxax+0PWFG+DFDgHNAdi+TXECADI+RYiFUMmx8792xsMbbgXj4CwnP4g=="], - "validate-npm-package-license/spdx-expression-parse": ["spdx-expression-parse@3.0.1", "", { "dependencies": { "spdx-exceptions": "^2.1.0", "spdx-license-ids": "^3.0.0" } }, "sha512-cbqHunsQWnJNE6KhVSMsMeH5H/L9EpymbzqTQ3uLwNCLZ1Q481oWaofqH7nO6V07xlXwY6PhQdQ2IedWx/ZK4Q=="], - - "vite-node/debug": ["debug@4.4.1", "", { "dependencies": { "ms": "^2.1.3" } }, "sha512-KcKCqiftBJcZr++7ykoDIEwSa3XWowTfNPo92BYxjXiyYEVrUQh2aLyhxBCwww+heortUFxEJYcRzosstTEBYQ=="], - - "vitest/debug": ["debug@4.4.1", "", { "dependencies": { "ms": "^2.1.3" } }, "sha512-KcKCqiftBJcZr++7ykoDIEwSa3XWowTfNPo92BYxjXiyYEVrUQh2aLyhxBCwww+heortUFxEJYcRzosstTEBYQ=="], + "rollup/@types/estree": ["@types/estree@1.0.5", "", {}, "sha512-/kYRxGDLWzHOB7q+wtSUQlFrtcdUccpfy+X+9iMBpHK8QLLhx2wIPYuS5DYtR9Wa/YlZAbIovy7qVdB1Aq6Lyw=="], "vitest/tinyexec": ["tinyexec@0.3.2", "", {}, "sha512-KQQR9yN7R5+OSwaK0XQoj22pwHoTlgYqmUscPYoknOoWCWfj/5/ABTMRi69FrKU5ffPVh5QcFikpWJI/P1ocHA=="], + "vue-eslint-parser/debug": ["debug@4.3.6", "", { "dependencies": { "ms": "2.1.2" } }, "sha512-O/09Bd4Z1fBrU4VzkhFqVgpPzaGbw6Sm9FEkBT1A/YBXQFGuuSxa1dN2nxgxS34JmKXqYx8CZAwEVoJFImUXIg=="], + "vue-eslint-parser/eslint-scope": ["eslint-scope@7.2.2", "", { "dependencies": { "esrecurse": "^4.3.0", "estraverse": "^5.2.0" } }, "sha512-dOt21O7lTMhDM+X9mB4GX+DZrZtCUJPL/wlcTqxyrx5IvO0IYtILdtrQGQp+8n5S0gwSVmOf9NQrjMOgfQZlIg=="], "vue-eslint-parser/eslint-visitor-keys": ["eslint-visitor-keys@3.4.3", "", {}, "sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag=="], @@ -763,36 +783,20 @@ "vue-eslint-parser/semver": ["semver@7.6.3", "", { "bin": { "semver": "bin/semver.js" } }, "sha512-oVekP1cKtI+CTDvHWYFUcMtsK/00wmAEfyqKfNdARm8u1wNVhSgaX7A8d4UuIlUI5e84iEwOhs7ZPYRmzU9U6A=="], - "@babel/highlight/chalk/ansi-styles": ["ansi-styles@3.2.1", "", { "dependencies": { "color-convert": "^1.9.0" } }, "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA=="], - - "@babel/highlight/chalk/escape-string-regexp": ["escape-string-regexp@1.0.5", "", {}, "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg=="], - - "@babel/highlight/chalk/supports-color": ["supports-color@5.5.0", "", { "dependencies": { "has-flag": "^3.0.0" } }, "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow=="], - "@typescript-eslint/typescript-estree/minimatch/brace-expansion": ["brace-expansion@2.0.1", "", { "dependencies": { "balanced-match": "^1.0.0" } }, "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA=="], - "eslint-plugin-n/minimatch/brace-expansion": ["brace-expansion@2.0.1", "", { "dependencies": { "balanced-match": "^1.0.0" } }, "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA=="], + "bun-types/@types/node/undici-types": ["undici-types@6.19.8", "", {}, "sha512-ve2KP6f/JnbPBFyobGHuerC9g1FYGn/F8n1LWTwNxCEzd6IfqTwUQcNXgEtmmQ6DlRrC1hrSrBnCZPokRrDHjw=="], - "eslint-plugin-vue/globals/type-fest": ["type-fest@0.20.2", "", {}, "sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ=="], + "eslint-plugin-es-x/@eslint-community/eslint-utils/eslint-visitor-keys": ["eslint-visitor-keys@3.4.3", "", {}, "sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag=="], - "read-pkg-up/find-up/locate-path": ["locate-path@5.0.0", "", { "dependencies": { "p-locate": "^4.1.0" } }, "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g=="], - - "rolldown-plugin-dts/debug/ms": ["ms@2.1.3", "", {}, "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA=="], - - "tsdown/debug/ms": ["ms@2.1.3", "", {}, "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA=="], - - "vite-node/debug/ms": ["ms@2.1.3", "", {}, "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA=="], - - "vitest/debug/ms": ["ms@2.1.3", "", {}, "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA=="], - - "@babel/highlight/chalk/ansi-styles/color-convert": ["color-convert@1.9.3", "", { "dependencies": { "color-name": "1.1.3" } }, "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg=="], + "eslint-plugin-n/minimatch/brace-expansion": ["brace-expansion@2.0.1", "", { "dependencies": { "balanced-match": "^1.0.0" } }, "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA=="], - "@babel/highlight/chalk/supports-color/has-flag": ["has-flag@3.0.0", "", {}, "sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw=="], + "eslint-plugin-promise/@eslint-community/eslint-utils/eslint-visitor-keys": ["eslint-visitor-keys@3.4.3", "", {}, "sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag=="], - "read-pkg-up/find-up/locate-path/p-locate": ["p-locate@4.1.0", "", { "dependencies": { "p-limit": "^2.2.0" } }, "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A=="], + "eslint-plugin-unicorn/@eslint/plugin-kit/@eslint/core": ["@eslint/core@0.13.0", "", { "dependencies": { "@types/json-schema": "^7.0.15" } }, "sha512-yfkgDw1KR66rkT5A8ci4irzDysN7FRpq3ttJolR88OqQikAWqwA8j5VZyas+vjyBNFIJ7MfybJ9plMILI2UrCw=="], - "@babel/highlight/chalk/ansi-styles/color-convert/color-name": ["color-name@1.1.3", "", {}, "sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw=="], + "vue-eslint-parser/debug/ms": ["ms@2.1.2", "", {}, "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w=="], - "read-pkg-up/find-up/locate-path/p-locate/p-limit": ["p-limit@2.3.0", "", { "dependencies": { "p-try": "^2.0.0" } }, "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w=="], + "vue-eslint-parser/espree/acorn": ["acorn@8.12.1", "", { "bin": { "acorn": "bin/acorn" } }, "sha512-tcpGyI9zbizT9JbV6oYE477V6mTlXvvi0T0G3SNIYE2apm/G5huBa1+K89VGeovbg+jycCrfhl3ADxErOuO6Jg=="], } } diff --git a/dist/main.cjs b/dist/main.cjs index 0284cfa..28ebdfd 100644 --- a/dist/main.cjs +++ b/dist/main.cjs @@ -22,8 +22,8 @@ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__ge //#endregion const node_path = __toESM(require("node:path")); -const itty_router = __toESM(require("itty-router")); const node_fs = __toESM(require("node:fs")); +const itty_router = __toESM(require("itty-router")); //#region src/utils/is-record.ts /** @@ -173,10 +173,10 @@ const REGEXP_PATH_SLUG = /\[(\w+)]/g; function scanDirectory(router, path, regexp_parts = [""]) { const result = (0, node_fs.readdirSync)(path, { withFileTypes: true }); const routes = { - 0: [], - 1: [], - 2: [], - 3: [] + "0": [], + "1": [], + "2": [], + "3": [] }; for (const entry of result) { const entry_path = node_path.default.join(path, entry.name); @@ -245,12 +245,12 @@ var HyperAPI = class { const driver_request = arg0; const [request, module_, response] = await this.processRequest(driver_request); try { - await this.useHooks(this.handlers.response, [ + await this.useHooks(this.handlers.response, { driver_request, request, - module_, + module: module_, response - ]); + }); } catch (error) { console.error("Error in \"response\" hook:"); console.error(error); @@ -309,9 +309,9 @@ var HyperAPI = class { onResponse(callback) { this.handlers.response.push(callback); } - async useHooks(hooks, args) { + async useHooks(hooks, ctx) { const promises = []; - for (const hook of hooks) promises.push(hook(...args)); + for (const hook of hooks) promises.push(hook(ctx)); await Promise.all(promises); } async processRequest(driver_request) { @@ -319,7 +319,7 @@ var HyperAPI = class { let module_ = null; try { if (driver_request.path.startsWith("/") !== true) driver_request.path = `/${driver_request.path}`; - await this.useHooks(this.handlers.beforeRouter, [driver_request]); + await this.useHooks(this.handlers.beforeRouter, { driver_request }); const router_response = await useRouter(this.router, driver_request.method, driver_request.path); if (!router_response) throw new HyperAPIUnknownMethodError(); driver_request.args = { @@ -333,8 +333,14 @@ var HyperAPI = class { console.error(error); throw new HyperAPIInvalidParametersError(); } - request = this.handlers.requestTransformer ? await this.handlers.requestTransformer(driver_request, module_) : driver_request; - await this.useHooks(this.handlers.beforeExecute, [request, module_]); + request = this.handlers.requestTransformer ? await this.handlers.requestTransformer({ + driver_request, + module: module_ + }) : driver_request; + await this.useHooks(this.handlers.beforeExecute, { + request, + module: module_ + }); const response = await module_.default(request); return [ request, diff --git a/dist/main.d.ts b/dist/main.d.ts index 73fddd6..a21b3ff 100644 --- a/dist/main.d.ts +++ b/dist/main.d.ts @@ -142,10 +142,23 @@ declare class HyperAPIMethodNotAllowedError extends //#endregion //#region src/main.d.ts interface HyperAPIHandlers, M extends HyperAPIModule> { - beforeRouter: ((driver_request: Readonly>) => Promisable)[]; - requestTransformer: ((driver_request: Readonly>, module_: M) => Promisable) | void; - beforeExecute: ((request: Readonly, module_: M) => Promisable)[]; - response: ((driver_request: Readonly>, request: R | null, module_: M | null, response: HyperAPIResponse) => Promisable)[]; + beforeRouter: ((ctx: { + driver_request: Readonly>; + }) => Promisable)[]; + requestTransformer: ((ctx: { + driver_request: Readonly>; + module: M; + }) => Promisable) | void; + beforeExecute: ((ctx: { + request: Readonly; + module: M; + }) => Promisable)[]; + response: ((ctx: { + driver_request: Readonly>; + request: R | null; + module: M | null; + response: HyperAPIResponse; + }) => Promisable)[]; } declare class HyperAPI, R extends InferDriverRequest, M extends HyperAPIModule = HyperAPIModule> { private router; diff --git a/dist/main.js b/dist/main.js index 99c5173..1367885 100644 --- a/dist/main.js +++ b/dist/main.js @@ -1,6 +1,6 @@ import nodePath from "node:path"; -import { IttyRouter } from "itty-router"; import { readdirSync } from "node:fs"; +import { IttyRouter } from "itty-router"; //#region src/utils/is-record.ts /** @@ -150,10 +150,10 @@ const REGEXP_PATH_SLUG = /\[(\w+)]/g; function scanDirectory(router, path, regexp_parts = [""]) { const result = readdirSync(path, { withFileTypes: true }); const routes = { - 0: [], - 1: [], - 2: [], - 3: [] + "0": [], + "1": [], + "2": [], + "3": [] }; for (const entry of result) { const entry_path = nodePath.join(path, entry.name); @@ -222,12 +222,12 @@ var HyperAPI = class { const driver_request = arg0; const [request, module_, response] = await this.processRequest(driver_request); try { - await this.useHooks(this.handlers.response, [ + await this.useHooks(this.handlers.response, { driver_request, request, - module_, + module: module_, response - ]); + }); } catch (error) { console.error("Error in \"response\" hook:"); console.error(error); @@ -286,9 +286,9 @@ var HyperAPI = class { onResponse(callback) { this.handlers.response.push(callback); } - async useHooks(hooks, args) { + async useHooks(hooks, ctx) { const promises = []; - for (const hook of hooks) promises.push(hook(...args)); + for (const hook of hooks) promises.push(hook(ctx)); await Promise.all(promises); } async processRequest(driver_request) { @@ -296,7 +296,7 @@ var HyperAPI = class { let module_ = null; try { if (driver_request.path.startsWith("/") !== true) driver_request.path = `/${driver_request.path}`; - await this.useHooks(this.handlers.beforeRouter, [driver_request]); + await this.useHooks(this.handlers.beforeRouter, { driver_request }); const router_response = await useRouter(this.router, driver_request.method, driver_request.path); if (!router_response) throw new HyperAPIUnknownMethodError(); driver_request.args = { @@ -310,8 +310,14 @@ var HyperAPI = class { console.error(error); throw new HyperAPIInvalidParametersError(); } - request = this.handlers.requestTransformer ? await this.handlers.requestTransformer(driver_request, module_) : driver_request; - await this.useHooks(this.handlers.beforeExecute, [request, module_]); + request = this.handlers.requestTransformer ? await this.handlers.requestTransformer({ + driver_request, + module: module_ + }) : driver_request; + await this.useHooks(this.handlers.beforeExecute, { + request, + module: module_ + }); const response = await module_.default(request); return [ request, diff --git a/eslint.config.js b/eslint.config.js index 59ec8dc..7d4be0e 100644 --- a/eslint.config.js +++ b/eslint.config.js @@ -1 +1,4 @@ -export { config as default } from '@kirick/eslint-config'; +import { configCommon } from '@kirick/lint/eslint/common'; +import { configNode } from '@kirick/lint/eslint/node'; + +export default [...configCommon, ...configNode]; diff --git a/package.json b/package.json index cbc85a7..c3e372b 100644 --- a/package.json +++ b/package.json @@ -21,9 +21,11 @@ "itty-router": "^5.0.18" }, "devDependencies": { - "@kirick/eslint-config": "^0.1.30", + "@biomejs/biome": "1.9.4", + "@kirick/lint": "0.1.0", "@types/bun": "^1.2.13", - "eslint": "9.10.0", + "eslint": "9.27.0", + "oxlint": "0.16.12", "publint": "0.3.12", "tsdown": "0.12.2", "type-fest": "^4.41.0", @@ -35,7 +37,7 @@ "scripts": { "build": "tsdown src/main.ts --publint --unused --dts --format esm --format cjs && rm dist/main.d.cts", "check": "bun run lint && bun run build && bun run test", - "lint": "eslint . && tsc && (cd test && tsc)", + "lint": "biome check && oxlint && eslint . && tsc && (cd test && tsc)", "test": "npm run test:vitest && bun test --coverage", "test:vitest": "vitest run --no-file-parallelism" }, @@ -43,10 +45,7 @@ "type": "git", "url": "git+https://github.com/hyperapi/core.git" }, - "keywords": [ - "hyperapi", - "api" - ], + "keywords": ["hyperapi", "api"], "author": "Daniil Kirichenko (https://twitter.com/kirickme)", "license": "MIT", "bugs": { diff --git a/src/api-errors.ts b/src/api-errors.ts index b5ddf85..97fe156 100644 --- a/src/api-errors.ts +++ b/src/api-errors.ts @@ -1,81 +1,105 @@ -import { - type HyperAPIErrorData, - HyperAPIError, -} from './error.js'; +import { HyperAPIError, type HyperAPIErrorData } from './error.js'; -export class HyperAPIAuthorizationError extends HyperAPIError { +export class HyperAPIAuthorizationError< + D extends HyperAPIErrorData, +> extends HyperAPIError { override code = 1; override description = 'Authorization error'; override httpStatus = 401; // Unauthorized } -export class HyperAPIInvalidParametersError extends HyperAPIError { +export class HyperAPIInvalidParametersError< + D extends HyperAPIErrorData, +> extends HyperAPIError { override code = 2; - override description = 'One of the parameters specified was missing or invalid'; + override description = + 'One of the parameters specified was missing or invalid'; override httpStatus = 400; // Bad Request } -export class HyperAPIInternalError extends HyperAPIError { +export class HyperAPIInternalError< + D extends HyperAPIErrorData, +> extends HyperAPIError { override code = 3; override description = 'Internal error'; override httpStatus = 500; // Internal Server Error } -export class HyperAPIForbiddenError extends HyperAPIError { +export class HyperAPIForbiddenError< + D extends HyperAPIErrorData, +> extends HyperAPIError { override code = 4; override description = 'You do not have permission to perform this action'; override httpStatus = 403; // Forbidden } -export class HyperAPIUnknownMethodError extends HyperAPIError { +export class HyperAPIUnknownMethodError< + D extends HyperAPIErrorData, +> extends HyperAPIError { override code = 5; override description = 'Unknown method called'; override httpStatus = 404; // Not Found } -export class HyperAPIObjectsLimitError extends HyperAPIError { +export class HyperAPIObjectsLimitError< + D extends HyperAPIErrorData, +> extends HyperAPIError { override code = 6; override description = 'Too many objects requested'; override httpStatus = 400; // Bad Request } -export class HyperAPIRateLimitError extends HyperAPIError { +export class HyperAPIRateLimitError< + D extends HyperAPIErrorData, +> extends HyperAPIError { override code = 7; override description = 'Rate limit exceeded'; override httpStatus = 429; // Too Many Requests } -export class HyperAPICaptchaError extends HyperAPIError { +export class HyperAPICaptchaError< + D extends HyperAPIErrorData, +> extends HyperAPIError { override code = 8; override description = 'Captcha required'; override httpStatus = 428; // Precondition Required } -export class HyperAPIBusyError extends HyperAPIError { +export class HyperAPIBusyError< + D extends HyperAPIErrorData, +> extends HyperAPIError { override code = 10; override description = 'Endpoint is busy'; override httpStatus = 503; // Service Unavailable } -export class HyperAPIConfirmationError extends HyperAPIError { +export class HyperAPIConfirmationError< + D extends HyperAPIErrorData, +> extends HyperAPIError { override code = 11; override description = 'Confirmation required'; override httpStatus = 409; // Conflict } -export class HyperAPIOTPError extends HyperAPIError { +export class HyperAPIOTPError< + D extends HyperAPIErrorData, +> extends HyperAPIError { override code = 12; override description = 'One-time password required'; override httpStatus = 401; // Unauthorized } -export class HyperAPIMaintenanceError extends HyperAPIError { +export class HyperAPIMaintenanceError< + D extends HyperAPIErrorData, +> extends HyperAPIError { override code = 13; override description = 'Endpoint is in maintenance mode'; override httpStatus = 503; // Service Unavailable } -export class HyperAPIMethodNotAllowedError extends HyperAPIError { +export class HyperAPIMethodNotAllowedError< + D extends HyperAPIErrorData, +> extends HyperAPIError { override code = 14; override description = 'HTTP method not allowed'; override httpStatus = 405; // Method Not Allowed diff --git a/src/driver.ts b/src/driver.ts index 57abf74..91c004a 100644 --- a/src/driver.ts +++ b/src/driver.ts @@ -1,14 +1,14 @@ import type { Promisable } from 'type-fest'; -import type { - HyperAPIRequest, -} from './request.js'; +import type { HyperAPIRequest } from './request.js'; import type { HyperAPIResponse } from './response.js'; -export type HyperAPIDriverHandler = (request: R) => Promisable; +export type HyperAPIDriverHandler = + (request: R) => Promisable; export interface HyperAPIDriver { start(handler: HyperAPIDriverHandler): void; stop(): void; } -export type InferDriverRequest = D extends HyperAPIDriver ? R : never; +export type InferDriverRequest = + D extends HyperAPIDriver ? R : never; diff --git a/src/error.test.ts b/src/error.test.ts index 07745bf..fae024b 100644 --- a/src/error.test.ts +++ b/src/error.test.ts @@ -1,9 +1,6 @@ /* eslint-disable @typescript-eslint/no-explicit-any */ -import { - test, - expect, -} from 'vitest'; +import { expect, test } from 'vitest'; import { HyperAPIError } from './error.js'; class HyperAPICustomError extends HyperAPIError { diff --git a/src/main.test.ts b/src/main.test.ts index d74da8e..43c7b08 100644 --- a/src/main.test.ts +++ b/src/main.test.ts @@ -1,13 +1,5 @@ -import { - afterAll, - describe, - test, - expect, -} from 'vitest'; -import { - driver, - hyperApi, -} from '../test/setup.js'; +import { afterAll, describe, expect, test } from 'vitest'; +import { driver, hyperApi } from '../test/setup.js'; afterAll(() => { hyperApi.destroy(); @@ -16,13 +8,9 @@ afterAll(() => { describe('routing', () => { describe('methods', () => { test('ALL with GET', async () => { - const result = await driver.trigger( - 'GET', - 'echo', - { - name: 'world', - }, - ); + const result = await driver.trigger('GET', 'echo', { + name: 'world', + }); expect(result).toStrictEqual([ true, @@ -37,13 +25,9 @@ describe('routing', () => { }); test('ALL with DELETE', async () => { - const result = await driver.trigger( - 'DELETE', - 'echo', - { - name: 'world', - }, - ); + const result = await driver.trigger('DELETE', 'echo', { + name: 'world', + }); expect(result).toStrictEqual([ true, @@ -58,13 +42,9 @@ describe('routing', () => { }); test('POST', async () => { - const result = await driver.trigger( - 'POST', - 'echo', - { - name: 'deadbeef', - }, - ); + const result = await driver.trigger('POST', 'echo', { + name: 'deadbeef', + }); expect(result).toStrictEqual([ true, diff --git a/src/main.ts b/src/main.ts index ea5f73c..562ec36 100644 --- a/src/main.ts +++ b/src/main.ts @@ -5,28 +5,37 @@ import { HyperAPIInvalidParametersError, HyperAPIUnknownMethodError, } from './api-errors.js'; -import type { - HyperAPIDriver, - InferDriverRequest, -} from './driver.js'; +import type { HyperAPIDriver, InferDriverRequest } from './driver.js'; import { HyperAPIError } from './error.js'; import type { HyperAPIModule } from './module.js'; import type { HyperAPIRequest } from './request.js'; import type { HyperAPIResponse } from './response.js'; -import { - createRouter, - useRouter, -} from './router.js'; +import { createRouter, useRouter } from './router.js'; interface HyperAPIHandlers< D extends HyperAPIDriver, R extends InferDriverRequest, M extends HyperAPIModule, > { - beforeRouter: ((driver_request: Readonly>) => Promisable)[]; - requestTransformer: ((driver_request: Readonly>, module_: M) => Promisable) | void; - beforeExecute: ((request: Readonly, module_: M) => Promisable)[]; - response: ((driver_request: Readonly>, request: R | null, module_: M | null, response: HyperAPIResponse) => Promisable)[]; + beforeRouter: ((ctx: { + driver_request: Readonly>; + }) => Promisable)[]; + requestTransformer: + | ((ctx: { + driver_request: Readonly>; + module: M; + }) => Promisable) + | void; + beforeExecute: ((ctx: { + request: Readonly; + module: M; + }) => Promisable)[]; + response: ((ctx: { + driver_request: Readonly>; + request: R | null; + module: M | null; + response: HyperAPIResponse; + }) => Promisable)[]; } const ENTRYPOINT_PATH = nodePath.dirname(process.argv[1]!); @@ -49,8 +58,8 @@ export class HyperAPI< driver, root = nodePath.join(ENTRYPOINT_PATH, 'hyper-api'), }: { - driver: D, - root?: string, + driver: D; + root?: string; }) { this.driver = driver; this.router = createRouter(root); @@ -58,25 +67,18 @@ export class HyperAPI< this.driver.start(async (arg0) => { const driver_request = arg0 as InferDriverRequest; - const [ - request, - module_, - response, - ] = await this.processRequest(driver_request); + const [request, module_, response] = + await this.processRequest(driver_request); // 10. *Core* executes all registered `onResponse` hooks... try { - await this.useHooks( - this.handlers.response, - [ - driver_request, - request, - module_, - response, - ], - ); - } - catch (error) { + await this.useHooks(this.handlers.response, { + driver_request, + request, + module: module_, + response, + }); + } catch (error) { /* eslint-disable no-console */ console.error('Error in "response" hook:'); console.error(error); @@ -103,7 +105,9 @@ export class HyperAPI< * If error is thrown in this hook, it will abort the request processing and return an error response. * @param callback The callback function. */ - onBeforeRouter(callback: HyperAPIHandlers['beforeRouter'][number]): void { + onBeforeRouter( + callback: HyperAPIHandlers['beforeRouter'][number], + ): void { this.handlers.beforeRouter.push(callback); } @@ -115,7 +119,9 @@ export class HyperAPI< * If error is thrown in this hook, it will abort the request processing and return an error response. * @param transformer The callback function. */ - setRequestTransformer(transformer: HyperAPIHandlers['requestTransformer']): void { + setRequestTransformer( + transformer: HyperAPIHandlers['requestTransformer'], + ): void { if (this.handlers.requestTransformer) { throw new Error('Transformer has already been set.'); } @@ -131,7 +137,9 @@ export class HyperAPI< * If error is thrown in this hook, it will abort the request processing and return an error response. * @param callback - */ - onBeforeExecute(callback: HyperAPIHandlers['beforeExecute'][number]): void { + onBeforeExecute( + callback: HyperAPIHandlers['beforeExecute'][number], + ): void { this.handlers.beforeExecute.push(callback); } @@ -148,16 +156,21 @@ export class HyperAPI< } // eslint-disable-next-line class-methods-use-this, @typescript-eslint/no-explicit-any - private async useHooks void>(hooks: H[], args: Parameters) { + private async useHooks void>( + hooks: H[], + ctx: Parameters[0], + ) { const promises: Promisable[] = []; for (const hook of hooks) { - promises.push(hook(...args)); + promises.push(hook(ctx)); } await Promise.all(promises); } - private async processRequest(driver_request: InferDriverRequest): Promise<[ R | null, M | null, HyperAPIResponse ]> { + private async processRequest( + driver_request: InferDriverRequest, + ): Promise<[R | null, M | null, HyperAPIResponse]> { // 1. *Driver* creates a request and passes it to the *Core* let request: R | null = null; @@ -169,10 +182,7 @@ export class HyperAPI< } // 2. *Core* executes all registered `onBeforeRouter` hooks... - await this.useHooks( - this.handlers.beforeRouter, - [ driver_request ], - ); + await this.useHooks(this.handlers.beforeRouter, { driver_request }); // 3. *Core* uses a file router... const router_response = await useRouter( @@ -198,8 +208,7 @@ export class HyperAPI< if (module_.argsValidator) { try { driver_request.args = module_.argsValidator(driver_request.args); - } - catch (error) { + } catch (error) { // eslint-disable-next-line no-console console.error(error); @@ -209,41 +218,31 @@ export class HyperAPI< // 7. *Core* calls registered `setRequestTransformer` hook request = this.handlers.requestTransformer - ? await this.handlers.requestTransformer(driver_request, module_) - : driver_request as R; + ? await this.handlers.requestTransformer({ + driver_request, + module: module_, + }) + : (driver_request as R); // 8. *Core* executes all registered `onBeforeExecute` hooks... - await this.useHooks( - this.handlers.beforeExecute, - [ request, module_ ], - ); + await this.useHooks(this.handlers.beforeExecute, { + request, + module: module_, + }); // 9. *Core* calls the module's `export default function`... const response = await module_.default(request); - return [ - request, - module_, - response, - ]; - } - catch (error) { + return [request, module_, response]; + } catch (error) { if (error instanceof HyperAPIError) { - return [ - request, - module_, - error, - ]; + return [request, module_, error]; } // eslint-disable-next-line no-console console.error(error); - return [ - request, - module_, - new HyperAPIInternalError(), - ]; + return [request, module_, new HyperAPIInternalError()]; } } diff --git a/src/module.ts b/src/module.ts index ca5d30c..15daf6a 100644 --- a/src/module.ts +++ b/src/module.ts @@ -1,18 +1,29 @@ import type { Promisable } from 'type-fest'; -import { HyperAPI } from './main.js'; -import type { - HyperAPIRequest, - HyperAPIRequestArgs, -} from './request.js'; +import type { HyperAPI } from './main.js'; +import type { HyperAPIRequest, HyperAPIRequestArgs } from './request.js'; -export type HyperAPIModuleResponse = Record | Response | unknown[] | undefined; +export type HyperAPIModuleResponse = + | Record + | Response + | unknown[] + | undefined; -export interface HyperAPIModule> { +export interface HyperAPIModule< + R extends HyperAPIRequest, +> { readonly default: (request: R) => Promisable; - readonly argsValidator: (args: unknown) => R extends HyperAPIRequest ? A : never; + readonly argsValidator: ( + args: unknown, + ) => R extends HyperAPIRequest ? A : never; } // export type HyperAPIModuleRequest> = Parameters[0]; // eslint-disable-next-line @typescript-eslint/no-explicit-any -export type InferModule> = H extends HyperAPI ? M : never; +export type InferModule> = H extends HyperAPI< + infer _D, + infer _R, + infer M +> + ? M + : never; diff --git a/src/request.ts b/src/request.ts index 030c02d..cdb0b1a 100644 --- a/src/request.ts +++ b/src/request.ts @@ -3,9 +3,7 @@ import type { HyperAPIMethod } from './utils/methods.js'; export type HyperAPIRequestArgs = Record; -export interface HyperAPIRequest< - A extends HyperAPIRequestArgs = EmptyObject, -> { +export interface HyperAPIRequest { method: HyperAPIMethod; path: string; args: A; diff --git a/src/response.ts b/src/response.ts index 6d0c16d..8f627ff 100644 --- a/src/response.ts +++ b/src/response.ts @@ -1,4 +1,4 @@ -import { HyperAPIError } from './error.js'; +import type { HyperAPIError } from './error.js'; import type { HyperAPIModuleResponse } from './module.js'; // eslint-disable-next-line @typescript-eslint/no-explicit-any diff --git a/src/router.ts b/src/router.ts index 0815912..6683ed2 100644 --- a/src/router.ts +++ b/src/router.ts @@ -1,12 +1,8 @@ /* eslint-disable n/no-sync */ -import { - IttyRouter, - type IRequest, - type IttyRouterType, -} from 'itty-router'; import { readdirSync } from 'node:fs'; import nodePath from 'node:path'; +import { type IRequest, IttyRouter, type IttyRouterType } from 'itty-router'; import type { HyperAPIMethod } from './utils/methods.js'; /** @@ -14,8 +10,10 @@ import type { HyperAPIMethod } from './utils/methods.js'; * @param path The path to scan. * @returns The new IttyRouter. */ -// eslint-disable-next-line @typescript-eslint/no-explicit-any -export function createRouter(path: string): IttyRouterType { +export function createRouter( + path: string, + // eslint-disable-next-line @typescript-eslint/no-explicit-any +): IttyRouterType { // eslint-disable-next-line new-cap const router = IttyRouter(); @@ -67,38 +65,29 @@ interface Route { function scanDirectory( router: IttyRouterType, path: string, - regexp_parts: string[] = [ '' ], + regexp_parts: string[] = [''], ) { - const result = readdirSync( - path, - { - withFileTypes: true, - }, - ); + const result = readdirSync(path, { + withFileTypes: true, + }); const routes: Record = { - 0: [], // routes with no method and no slug - 1: [], // routes with method and no slug - 2: [], // routes with no method and slug - 3: [], // routes with method and slug + '0': [], // routes with no method and no slug + '1': [], // routes with method and no slug + '2': [], // routes with no method and slug + '3': [], // routes with method and slug }; for (const entry of result) { - const entry_path = nodePath.join( - path, - entry.name, - ); + const entry_path = nodePath.join(path, entry.name); if (entry.isFile()) { let file_name = entry.name; if ( - REGEXP_FILE_EXTENSION.test(file_name) - && REGEXP_TEST_FILE_EXTENSION.test(file_name) !== true + REGEXP_FILE_EXTENSION.test(file_name) && + REGEXP_TEST_FILE_EXTENSION.test(file_name) !== true ) { - file_name = file_name.replace( - REGEXP_FILE_EXTENSION, - '', - ); + file_name = file_name.replace(REGEXP_FILE_EXTENSION, ''); let method: Route['method'] = 'all'; const method_match = file_name.match(REGEXP_HTTP_METHOD); @@ -106,17 +95,11 @@ function scanDirectory( if (method_match) { method = method_match[1] as Exclude; - file_name = file_name.replace( - REGEXP_HTTP_METHOD, - '', - ); + file_name = file_name.replace(REGEXP_HTTP_METHOD, ''); } const has_slug = REGEXP_PATH_SLUG.test(file_name) ? 2 : 0; - file_name = file_name.replaceAll( - REGEXP_PATH_SLUG, - ':$1', - ); + file_name = file_name.replaceAll(REGEXP_PATH_SLUG, ':$1'); // console.log( // entry_path, @@ -130,48 +113,32 @@ function scanDirectory( // eslint-disable-next-line no-bitwise routes[has_method | has_slug]?.push({ method, - path: [ - ...regexp_parts, - file_name, - ].join(nodePath.sep), + path: [...regexp_parts, file_name].join(nodePath.sep), module_path: entry_path, }); } - } - else { - scanDirectory( - router, - entry_path, - [ - ...regexp_parts, - entry.name.replaceAll( - REGEXP_PATH_SLUG, - ':$1', - ), - ], - ); + } else { + scanDirectory(router, entry_path, [ + ...regexp_parts, + entry.name.replaceAll(REGEXP_PATH_SLUG, ':$1'), + ]); } } - for ( - const route of [ - // suppress indexed access to fail - ...routes[1]!, - ...routes[3]!, - ...routes[0]!, - ...routes[2]!, - ] - ) { - router[route.method]( - route.path, - (r) => { - const response: RouterResponse = { - module_path: route.module_path, - args: r.params, - }; - - return response; - }, - ); + for (const route of [ + // suppress indexed access to fail + ...routes[1]!, + ...routes[3]!, + ...routes[0]!, + ...routes[2]!, + ]) { + router[route.method](route.path, (r) => { + const response: RouterResponse = { + module_path: route.module_path, + args: r.params, + }; + + return response; + }); } } diff --git a/src/utils/is-record.ts b/src/utils/is-record.ts index a7e9ae0..c5b9253 100644 --- a/src/utils/is-record.ts +++ b/src/utils/is-record.ts @@ -4,9 +4,11 @@ * @returns - */ export function isRecord(value: unknown): value is Record { - return typeof value === 'object' - && value !== null - && !Array.isArray(value) - && value.constructor === Object - && Object.prototype.toString.call(value) === '[object Object]'; + return ( + typeof value === 'object' && + value !== null && + !Array.isArray(value) && + value.constructor === Object && + Object.prototype.toString.call(value) === '[object Object]' + ); } diff --git a/src/utils/methods.ts b/src/utils/methods.ts index 7f1c371..fa1bf95 100644 --- a/src/utils/methods.ts +++ b/src/utils/methods.ts @@ -1,4 +1,12 @@ -export type HyperAPIMethod = 'DELETE' | 'GET' | 'HEAD' | 'OPTIONS' | 'PATCH' | 'POST' | 'PUT' | 'UNKNOWN'; +export type HyperAPIMethod = + | 'DELETE' + | 'GET' + | 'HEAD' + | 'OPTIONS' + | 'PATCH' + | 'POST' + | 'PUT' + | 'UNKNOWN'; /** * Checks if the given value is a valid HyperAPI method. @@ -6,12 +14,14 @@ export type HyperAPIMethod = 'DELETE' | 'GET' | 'HEAD' | 'OPTIONS' | 'PATCH' | ' * @returns - */ export function isHyperApiMethod(method: unknown): method is HyperAPIMethod { - return method === 'DELETE' - || method === 'GET' - || method === 'HEAD' - || method === 'OPTIONS' - || method === 'PATCH' - || method === 'POST' - || method === 'PUT' - || method === 'UNKNOWN'; + return ( + method === 'DELETE' || + method === 'GET' || + method === 'HEAD' || + method === 'OPTIONS' || + method === 'PATCH' || + method === 'POST' || + method === 'PUT' || + method === 'UNKNOWN' + ); } diff --git a/test/hyper-api/echo.[post].ts b/test/hyper-api/echo.[post].ts index c13883f..9503ce6 100644 --- a/test/hyper-api/echo.[post].ts +++ b/test/hyper-api/echo.[post].ts @@ -6,11 +6,13 @@ import type { HyperAPIResponse, InferModule, } from '../../src/main.js'; -import { hyperApi } from '../setup.js'; +import type { hyperApi } from '../setup.js'; type Module = InferModule; -export default function (request: HyperAPIRequest>): HyperAPIResponse { +export default function ( + request: HyperAPIRequest>, +): HyperAPIResponse { return { method: { expected: 'POST', diff --git a/test/hyper-api/echo.ts b/test/hyper-api/echo.ts index a600866..b9bc1ae 100644 --- a/test/hyper-api/echo.ts +++ b/test/hyper-api/echo.ts @@ -1,10 +1,12 @@ /* eslint-disable jsdoc/require-jsdoc */ import * as v from 'valibot'; -import { type HyperAPIResponse } from '../../src/main.js'; -import { type LocalRequest } from '../setup.js'; +import type { HyperAPIResponse } from '../../src/main.js'; +import type { LocalRequest } from '../setup.js'; -export default function (request: LocalRequest>): HyperAPIResponse { +export default function ( + request: LocalRequest>, +): HyperAPIResponse { return { method: { expected: 'ALL', diff --git a/test/hyper-api/errors/api.test.ts b/test/hyper-api/errors/api.test.ts index 2d4cd6c..afd45bf 100644 --- a/test/hyper-api/errors/api.test.ts +++ b/test/hyper-api/errors/api.test.ts @@ -1,14 +1,8 @@ -import { - expect, - test, -} from 'vitest'; +import { expect, test } from 'vitest'; import { driver } from '../../setup.js'; test('error', async () => { - const result = await driver.trigger( - 'GET', - 'errors/api', - ); + const result = await driver.trigger('GET', 'errors/api'); expect(result).toStrictEqual([ false, @@ -20,15 +14,11 @@ test('error', async () => { }); test('error with data', async () => { - const result = await driver.trigger( - 'GET', - 'errors/api', - { - error_data: { - foo: 'bar', - }, + const result = await driver.trigger('GET', 'errors/api', { + error_data: { + foo: 'bar', }, - ); + }); expect(result).toStrictEqual([ false, diff --git a/test/hyper-api/errors/api.ts b/test/hyper-api/errors/api.ts index 3c3a4e7..fd9939e 100644 --- a/test/hyper-api/errors/api.ts +++ b/test/hyper-api/errors/api.ts @@ -2,9 +2,11 @@ import * as v from 'valibot'; import { HyperAPIBusyError } from '../../../src/api-errors.js'; -import { type LocalRequest } from '../../setup.js'; +import type { LocalRequest } from '../../setup.js'; -export default function (request: LocalRequest>) { +export default function ( + request: LocalRequest>, +) { throw new HyperAPIBusyError( Object.keys(request.args.error_data).length > 0 ? request.args.error_data @@ -14,14 +16,8 @@ export default function (request: LocalRequest> export const argsValidator = v.parser( v.strictObject({ - error_data: v.optional( - v.record( - v.string(), - v.any(), - ), - () => { - return {}; - }, - ), + error_data: v.optional(v.record(v.string(), v.any()), () => { + return {}; + }), }), ); diff --git a/test/hyper-api/errors/internal.test.ts b/test/hyper-api/errors/internal.test.ts index a1b3668..c7ef9b8 100644 --- a/test/hyper-api/errors/internal.test.ts +++ b/test/hyper-api/errors/internal.test.ts @@ -1,14 +1,8 @@ -import { - expect, - test, -} from 'vitest'; +import { expect, test } from 'vitest'; import { driver } from '../../setup.js'; test('internal error', async () => { - const result = await driver.trigger( - 'GET', - 'errors/internal', - ); + const result = await driver.trigger('GET', 'errors/internal'); expect(result).toStrictEqual([ false, diff --git a/test/hyper-api/only-get.test.ts b/test/hyper-api/only-get.test.ts index e064b71..8a4a6b6 100644 --- a/test/hyper-api/only-get.test.ts +++ b/test/hyper-api/only-get.test.ts @@ -1,14 +1,8 @@ -import { - expect, - test, -} from 'vitest'; +import { expect, test } from 'vitest'; import { driver } from '../setup.js'; test('GET', async () => { - const result = await driver.trigger( - 'GET', - 'only-get', - ); + const result = await driver.trigger('GET', 'only-get'); expect(result).toStrictEqual([ true, diff --git a/test/setup.ts b/test/setup.ts index 0ed1e80..82b4dc4 100644 --- a/test/setup.ts +++ b/test/setup.ts @@ -1,16 +1,17 @@ import type { EmptyObject } from 'type-fest'; import { + HyperAPI, type HyperAPIDriver, type HyperAPIDriverHandler, + HyperAPIError, type HyperAPIModule, type HyperAPIRequest, type HyperAPIRequestArgs, - HyperAPI, - HyperAPIError, } from '../src/main.js'; import type { HyperAPIMethod } from '../src/utils/methods.js'; -interface DriverRequest extends HyperAPIRequest { +interface DriverRequest + extends HyperAPIRequest { foo: string; } @@ -29,19 +30,21 @@ class HyperAPITestDriver implements HyperAPIDriver { method: HyperAPIMethod, path: string, args?: Record, - ): Promise<[ boolean, unknown ]>; + ): Promise<[boolean, unknown]>; async trigger( method: HyperAPIMethod, path: string, args: Record, use_http: true, - ): Promise<[ boolean, unknown, { status: number | undefined } ]>; + ): Promise<[boolean, unknown, { status: number | undefined }]>; async trigger( method: HyperAPIMethod, path: string, args: Record = {}, - use_http: boolean = false, - ): Promise<[ boolean, unknown ] | [ boolean, unknown, { status: number | undefined }]> { + use_http = false, + ): Promise< + [boolean, unknown] | [boolean, unknown, { status: number | undefined }] + > { if (!this.handler) { throw new Error('No handler available.'); } @@ -56,28 +59,23 @@ class HyperAPITestDriver implements HyperAPIDriver { if (response instanceof HyperAPIError) { return use_http === true ? [ - false, - response.getResponse(), - { - status: response.httpStatus, - }, - ] - : [ - false, - response.getResponse(), - ]; + false, + response.getResponse(), + { + status: response.httpStatus, + }, + ] + : [false, response.getResponse()]; } - return [ - true, - response, - ]; + return [true, response]; } } export const driver = new HyperAPITestDriver(); -export interface LocalRequest extends DriverRequest { +export interface LocalRequest + extends DriverRequest { bar: number; } @@ -101,63 +99,49 @@ export const hyperApi = new HyperAPI< /* eslint-disable @typescript-eslint/no-unused-vars */ -hyperApi.onBeforeRouter((driver_request) => { +hyperApi.onBeforeRouter((ctx) => { const { foo, // @ts-expect-error Accessing property that does not exist on DriverRequest bar, - } = driver_request; + } = ctx.driver_request; }); -hyperApi.setRequestTransformer((driver_request) => { +hyperApi.setRequestTransformer((ctx) => { const { foo, // @ts-expect-error Accessing property that does not exist on DriverRequest bar, - } = driver_request; + } = ctx.driver_request; return { - ...driver_request, + ...ctx.driver_request, bar: 10, }; }); -hyperApi.onBeforeExecute((request, module) => { - const { - foo, - bar, - } = request; +hyperApi.onBeforeExecute((ctx) => { + const { foo, bar } = ctx.request; - const { - default: default_, - argsValidator, - auth, - } = module; + const { default: default_, argsValidator, auth } = ctx.module; }); -hyperApi.onResponse((driver_request, request, module, response) => { +hyperApi.onResponse((ctx) => { const { foo, // @ts-expect-error Accessing property that does not exist on DriverRequest bar, - } = driver_request; + } = ctx.driver_request; - if (request) { - const { - foo, - bar, - } = request; + if (ctx.request) { + const { foo, bar } = ctx.request; } - if (module) { - const { - default: default_, - argsValidator, - auth, - } = module; + if (ctx.module) { + const { default: default_, argsValidator, auth } = ctx.module; } - console.log(response); + console.log(ctx.response); }); /* eslint-enable @typescript-eslint/no-unused-vars */ diff --git a/test/tsconfig.json b/test/tsconfig.json index 059d1f5..a1ca658 100644 --- a/test/tsconfig.json +++ b/test/tsconfig.json @@ -3,8 +3,5 @@ "compilerOptions": { "isolatedDeclarations": false }, - "include": [ - "./**/*.ts", - "../src/**/*.test.ts" - ] -} \ No newline at end of file + "include": ["./**/*.ts", "../src/**/*.test.ts"] +} diff --git a/tsconfig.json b/tsconfig.json index 6efe70c..9e0fdab 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -11,16 +11,10 @@ "noImplicitOverride": true, "module": "preserve", "noEmit": true, - "lib": [ - "es2022" - ], + "lib": ["es2022"], "declaration": true, "isolatedDeclarations": true }, - "include": [ - "src/" - ], - "exclude": [ - "**/*.test.ts" - ] -} \ No newline at end of file + "include": ["src/"], + "exclude": ["**/*.test.ts"] +} From 1cd49ca6cd7e875de1a848e9f52be4141f8d55f7 Mon Sep 17 00:00:00 2001 From: Daniil Kirichenko Date: Wed, 28 May 2025 21:07:01 +0200 Subject: [PATCH 41/57] Return `this` --- dist/main.cjs | 4 ++++ dist/main.d.ts | 8 ++++---- dist/main.js | 4 ++++ src/main.ts | 12 ++++++++---- 4 files changed, 20 insertions(+), 8 deletions(-) diff --git a/dist/main.cjs b/dist/main.cjs index 28ebdfd..fcc9081 100644 --- a/dist/main.cjs +++ b/dist/main.cjs @@ -274,6 +274,7 @@ var HyperAPI = class { */ onBeforeRouter(callback) { this.handlers.beforeRouter.push(callback); + return this; } /** * Use this hook add properties to the request before it is send to the API module. @@ -286,6 +287,7 @@ var HyperAPI = class { setRequestTransformer(transformer) { if (this.handlers.requestTransformer) throw new Error("Transformer has already been set."); this.handlers.requestTransformer = transformer; + return this; } /** * Adds a hook to be called right before the API module is executed. @@ -297,6 +299,7 @@ var HyperAPI = class { */ onBeforeExecute(callback) { this.handlers.beforeExecute.push(callback); + return this; } /** * Adds a hook to be called right before the response is sent back to the driver. @@ -308,6 +311,7 @@ var HyperAPI = class { */ onResponse(callback) { this.handlers.response.push(callback); + return this; } async useHooks(hooks, ctx) { const promises = []; diff --git a/dist/main.d.ts b/dist/main.d.ts index a21b3ff..24afa31 100644 --- a/dist/main.d.ts +++ b/dist/main.d.ts @@ -185,7 +185,7 @@ declare class HyperAPI, R extends Infe * If error is thrown in this hook, it will abort the request processing and return an error response. * @param callback The callback function. */ - onBeforeRouter(callback: HyperAPIHandlers["beforeRouter"][number]): void; + onBeforeRouter(callback: HyperAPIHandlers["beforeRouter"][number]): this; /** * Use this hook add properties to the request before it is send to the API module. * @@ -194,7 +194,7 @@ declare class HyperAPI, R extends Infe * If error is thrown in this hook, it will abort the request processing and return an error response. * @param transformer The callback function. */ - setRequestTransformer(transformer: HyperAPIHandlers["requestTransformer"]): void; + setRequestTransformer(transformer: HyperAPIHandlers["requestTransformer"]): this; /** * Adds a hook to be called right before the API module is executed. * @@ -203,7 +203,7 @@ declare class HyperAPI, R extends Infe * If error is thrown in this hook, it will abort the request processing and return an error response. * @param callback - */ - onBeforeExecute(callback: HyperAPIHandlers["beforeExecute"][number]): void; + onBeforeExecute(callback: HyperAPIHandlers["beforeExecute"][number]): this; /** * Adds a hook to be called right before the response is sent back to the driver. * @@ -212,7 +212,7 @@ declare class HyperAPI, R extends Infe * If error is thrown in this hook, it will be printed to the console, but will not prevent response from being sent to the driver. * @param callback - */ - onResponse(callback: HyperAPIHandlers["response"][number]): void; + onResponse(callback: HyperAPIHandlers["response"][number]): this; // eslint-disable-next-line class-methods-use-this, @typescript-eslint/no-explicit-any private useHooks; private processRequest; diff --git a/dist/main.js b/dist/main.js index 1367885..cebd5c9 100644 --- a/dist/main.js +++ b/dist/main.js @@ -251,6 +251,7 @@ var HyperAPI = class { */ onBeforeRouter(callback) { this.handlers.beforeRouter.push(callback); + return this; } /** * Use this hook add properties to the request before it is send to the API module. @@ -263,6 +264,7 @@ var HyperAPI = class { setRequestTransformer(transformer) { if (this.handlers.requestTransformer) throw new Error("Transformer has already been set."); this.handlers.requestTransformer = transformer; + return this; } /** * Adds a hook to be called right before the API module is executed. @@ -274,6 +276,7 @@ var HyperAPI = class { */ onBeforeExecute(callback) { this.handlers.beforeExecute.push(callback); + return this; } /** * Adds a hook to be called right before the response is sent back to the driver. @@ -285,6 +288,7 @@ var HyperAPI = class { */ onResponse(callback) { this.handlers.response.push(callback); + return this; } async useHooks(hooks, ctx) { const promises = []; diff --git a/src/main.ts b/src/main.ts index 562ec36..8f67517 100644 --- a/src/main.ts +++ b/src/main.ts @@ -107,8 +107,9 @@ export class HyperAPI< */ onBeforeRouter( callback: HyperAPIHandlers['beforeRouter'][number], - ): void { + ): this { this.handlers.beforeRouter.push(callback); + return this; } /** @@ -121,12 +122,13 @@ export class HyperAPI< */ setRequestTransformer( transformer: HyperAPIHandlers['requestTransformer'], - ): void { + ): this { if (this.handlers.requestTransformer) { throw new Error('Transformer has already been set.'); } this.handlers.requestTransformer = transformer; + return this; } /** @@ -139,8 +141,9 @@ export class HyperAPI< */ onBeforeExecute( callback: HyperAPIHandlers['beforeExecute'][number], - ): void { + ): this { this.handlers.beforeExecute.push(callback); + return this; } /** @@ -151,8 +154,9 @@ export class HyperAPI< * If error is thrown in this hook, it will be printed to the console, but will not prevent response from being sent to the driver. * @param callback - */ - onResponse(callback: HyperAPIHandlers['response'][number]): void { + onResponse(callback: HyperAPIHandlers['response'][number]): this { this.handlers.response.push(callback); + return this; } // eslint-disable-next-line class-methods-use-this, @typescript-eslint/no-explicit-any From 2b7ad6c0f24ae1f84f31702e349ce3c6b77e475c Mon Sep 17 00:00:00 2001 From: Daniil Kirichenko Date: Mon, 8 Sep 2025 15:40:23 +0200 Subject: [PATCH 42/57] New test, bump dependencies, fix warnings --- .vscode/settings.json | 8 ++ biome.json | 14 +- bun.lock | 236 +++++++++++++++++----------------- dist/main.cjs | 4 + dist/main.d.cts | 216 +++++++++++++++++++++++++++++++ dist/main.d.ts | 18 +-- dist/main.js | 4 + package.json | 34 +++-- src/main.test.ts | 15 +++ src/main.ts | 14 +- src/router.ts | 2 - test/hyper-api/echo-[name].ts | 24 ++++ test/setup.ts | 6 +- 13 files changed, 434 insertions(+), 161 deletions(-) create mode 100644 .vscode/settings.json create mode 100644 dist/main.d.cts create mode 100644 test/hyper-api/echo-[name].ts diff --git a/.vscode/settings.json b/.vscode/settings.json new file mode 100644 index 0000000..99357f2 --- /dev/null +++ b/.vscode/settings.json @@ -0,0 +1,8 @@ +{ + "editor.formatOnSave": true, + "editor.defaultFormatter": "biomejs.biome", + "editor.codeActionsOnSave": { + "source.fixAll.biome": "explicit", + "source.organizeImports.biome": "explicit" + } +} diff --git a/biome.json b/biome.json index 5071149..91c3d81 100644 --- a/biome.json +++ b/biome.json @@ -1,5 +1,5 @@ { - "$schema": "https://biomejs.dev/schemas/1.9.4/schema.json", + "$schema": "https://biomejs.dev/schemas/2.1.1/schema.json", "vcs": { "enabled": false, "clientKind": "git", @@ -7,19 +7,23 @@ }, "files": { "ignoreUnknown": false, - "ignore": ["dist/"] + "includes": ["**", "!**/dist/**"] }, "formatter": { "enabled": true, "indentStyle": "tab", "bracketSpacing": true }, - "organizeImports": { - "enabled": true - }, "linter": { "enabled": false }, + "assist": { + "actions": { + "source": { + "organizeImports": "on" + } + } + }, "javascript": { "formatter": { "quoteStyle": "single" diff --git a/bun.lock b/bun.lock index 840471c..e13669d 100644 --- a/bun.lock +++ b/bun.lock @@ -4,58 +4,58 @@ "": { "name": "@hyperapi/core", "dependencies": { - "itty-router": "^5.0.18", + "itty-router": "5.0.22", }, "devDependencies": { - "@biomejs/biome": "1.9.4", - "@kirick/lint": "0.1.0", - "@types/bun": "^1.2.13", + "@biomejs/biome": "2.1.1", + "@kirick/lint": "0.2.7", + "@types/bun": "1.2.21", "eslint": "9.27.0", - "oxlint": "0.16.12", + "oxlint": "1.3.0", "publint": "0.3.12", - "tsdown": "0.12.2", - "type-fest": "^4.41.0", - "typescript": "5.8.3", - "unplugin-unused": "0.5.0", + "tsdown": "0.14.2", + "type-fest": "4.41.0", + "typescript": "5.9.2", + "unplugin-unused": "0.5.2", "valibot": "1.1.0", - "vitest": "3.1.4", + "vitest": "3.2.4", }, }, }, "packages": { - "@babel/generator": ["@babel/generator@7.27.1", "", { "dependencies": { "@babel/parser": "^7.27.1", "@babel/types": "^7.27.1", "@jridgewell/gen-mapping": "^0.3.5", "@jridgewell/trace-mapping": "^0.3.25", "jsesc": "^3.0.2" } }, "sha512-UnJfnIpc/+JO0/+KRVQNGU+y5taA5vCbwN8+azkX6beii/ZF+enZJSOKo11ZSzGJjlNfJHfQtmQT8H+9TXPG2w=="], + "@babel/generator": ["@babel/generator@7.28.3", "", { "dependencies": { "@babel/parser": "^7.28.3", "@babel/types": "^7.28.2", "@jridgewell/gen-mapping": "^0.3.12", "@jridgewell/trace-mapping": "^0.3.28", "jsesc": "^3.0.2" } }, "sha512-3lSpxGgvnmZznmBkCRnVREPUFJv2wrv9iAoFDvADJc0ypmdOxdUtcLeBgBJ6zE0PMeTKnxeQzyk0xTBq4Ep7zw=="], "@babel/helper-string-parser": ["@babel/helper-string-parser@7.27.1", "", {}, "sha512-qMlSxKbpRlAridDExk92nSobyDdpPijUq2DW6oDnUqd0iOGxmQjyqhMIihI9+zv4LPyZdRje2cavWPbCbWm3eA=="], "@babel/helper-validator-identifier": ["@babel/helper-validator-identifier@7.27.1", "", {}, "sha512-D2hP9eA+Sqx1kBZgzxZh0y1trbuU+JoDkiEwqhQ36nodYqJwyEIhPSdMNd7lOm/4io72luTPWH20Yda0xOuUow=="], - "@babel/parser": ["@babel/parser@7.27.2", "", { "dependencies": { "@babel/types": "^7.27.1" }, "bin": "./bin/babel-parser.js" }, "sha512-QYLs8299NA7WM/bZAdp+CviYYkVoYXlDW2rzliy3chxd1PQjej7JORuMJDJXJUb9g0TT+B99EwaVLKmX+sPXWw=="], + "@babel/parser": ["@babel/parser@7.28.3", "", { "dependencies": { "@babel/types": "^7.28.2" }, "bin": "./bin/babel-parser.js" }, "sha512-7+Ey1mAgYqFAx2h0RuoxcQT5+MlG3GTV0TQrgr7/ZliKsm/MNDxVVutlWaziMq7wJNAz8MTqz55XLpWvva6StA=="], - "@babel/types": ["@babel/types@7.27.1", "", { "dependencies": { "@babel/helper-string-parser": "^7.27.1", "@babel/helper-validator-identifier": "^7.27.1" } }, "sha512-+EzkxvLNfiUeKMgy/3luqfsCWFRXLb7U6wNQTk60tovuckwB15B191tJWvpp4HjiQWdJkCxO3Wbvc6jlk3Xb2Q=="], + "@babel/types": ["@babel/types@7.28.2", "", { "dependencies": { "@babel/helper-string-parser": "^7.27.1", "@babel/helper-validator-identifier": "^7.27.1" } }, "sha512-ruv7Ae4J5dUYULmeXw1gmb7rYRz57OWCPM57pHojnLq/3Z1CK2lNSLTCVjxVk1F/TZHwOZZrOWi0ur95BbLxNQ=="], - "@biomejs/biome": ["@biomejs/biome@1.9.4", "", { "optionalDependencies": { "@biomejs/cli-darwin-arm64": "1.9.4", "@biomejs/cli-darwin-x64": "1.9.4", "@biomejs/cli-linux-arm64": "1.9.4", "@biomejs/cli-linux-arm64-musl": "1.9.4", "@biomejs/cli-linux-x64": "1.9.4", "@biomejs/cli-linux-x64-musl": "1.9.4", "@biomejs/cli-win32-arm64": "1.9.4", "@biomejs/cli-win32-x64": "1.9.4" }, "bin": { "biome": "bin/biome" } }, "sha512-1rkd7G70+o9KkTn5KLmDYXihGoTaIGO9PIIN2ZB7UJxFrWw04CZHPYiMRjYsaDvVV7hP1dYNRLxSANLaBFGpog=="], + "@biomejs/biome": ["@biomejs/biome@2.1.1", "", { "optionalDependencies": { "@biomejs/cli-darwin-arm64": "2.1.1", "@biomejs/cli-darwin-x64": "2.1.1", "@biomejs/cli-linux-arm64": "2.1.1", "@biomejs/cli-linux-arm64-musl": "2.1.1", "@biomejs/cli-linux-x64": "2.1.1", "@biomejs/cli-linux-x64-musl": "2.1.1", "@biomejs/cli-win32-arm64": "2.1.1", "@biomejs/cli-win32-x64": "2.1.1" }, "bin": { "biome": "bin/biome" } }, "sha512-HFGYkxG714KzG+8tvtXCJ1t1qXQMzgWzfvQaUjxN6UeKv+KvMEuliInnbZLJm6DXFXwqVi6446EGI0sGBLIYng=="], - "@biomejs/cli-darwin-arm64": ["@biomejs/cli-darwin-arm64@1.9.4", "", { "os": "darwin", "cpu": "arm64" }, "sha512-bFBsPWrNvkdKrNCYeAp+xo2HecOGPAy9WyNyB/jKnnedgzl4W4Hb9ZMzYNbf8dMCGmUdSavlYHiR01QaYR58cw=="], + "@biomejs/cli-darwin-arm64": ["@biomejs/cli-darwin-arm64@2.1.1", "", { "os": "darwin", "cpu": "arm64" }, "sha512-2Muinu5ok4tWxq4nu5l19el48cwCY/vzvI7Vjbkf3CYIQkjxZLyj0Ad37Jv2OtlXYaLvv+Sfu1hFeXt/JwRRXQ=="], - "@biomejs/cli-darwin-x64": ["@biomejs/cli-darwin-x64@1.9.4", "", { "os": "darwin", "cpu": "x64" }, "sha512-ngYBh/+bEedqkSevPVhLP4QfVPCpb+4BBe2p7Xs32dBgs7rh9nY2AIYUL6BgLw1JVXV8GlpKmb/hNiuIxfPfZg=="], + "@biomejs/cli-darwin-x64": ["@biomejs/cli-darwin-x64@2.1.1", "", { "os": "darwin", "cpu": "x64" }, "sha512-cC8HM5lrgKQXLAK+6Iz2FrYW5A62pAAX6KAnRlEyLb+Q3+Kr6ur/sSuoIacqlp1yvmjHJqjYfZjPvHWnqxoEIA=="], - "@biomejs/cli-linux-arm64": ["@biomejs/cli-linux-arm64@1.9.4", "", { "os": "linux", "cpu": "arm64" }, "sha512-fJIW0+LYujdjUgJJuwesP4EjIBl/N/TcOX3IvIHJQNsAqvV2CHIogsmA94BPG6jZATS4Hi+xv4SkBBQSt1N4/g=="], + "@biomejs/cli-linux-arm64": ["@biomejs/cli-linux-arm64@2.1.1", "", { "os": "linux", "cpu": "arm64" }, "sha512-tw4BEbhAUkWPe4WBr6IX04DJo+2jz5qpPzpW/SWvqMjb9QuHY8+J0M23V8EPY/zWU4IG8Ui0XESapR1CB49Q7g=="], - "@biomejs/cli-linux-arm64-musl": ["@biomejs/cli-linux-arm64-musl@1.9.4", "", { "os": "linux", "cpu": "arm64" }, "sha512-v665Ct9WCRjGa8+kTr0CzApU0+XXtRgwmzIf1SeKSGAv+2scAlW6JR5PMFo6FzqqZ64Po79cKODKf3/AAmECqA=="], + "@biomejs/cli-linux-arm64-musl": ["@biomejs/cli-linux-arm64-musl@2.1.1", "", { "os": "linux", "cpu": "arm64" }, "sha512-/7FBLnTswu4jgV9ttI3AMIdDGqVEPIZd8I5u2D4tfCoj8rl9dnjrEQbAIDlWhUXdyWlFSz8JypH3swU9h9P+2A=="], - "@biomejs/cli-linux-x64": ["@biomejs/cli-linux-x64@1.9.4", "", { "os": "linux", "cpu": "x64" }, "sha512-lRCJv/Vi3Vlwmbd6K+oQ0KhLHMAysN8lXoCI7XeHlxaajk06u7G+UsFSO01NAs5iYuWKmVZjmiOzJ0OJmGsMwg=="], + "@biomejs/cli-linux-x64": ["@biomejs/cli-linux-x64@2.1.1", "", { "os": "linux", "cpu": "x64" }, "sha512-3WJ1GKjU7NzZb6RTbwLB59v9cTIlzjbiFLDB0z4376TkDqoNYilJaC37IomCr/aXwuU8QKkrYoHrgpSq5ffJ4Q=="], - "@biomejs/cli-linux-x64-musl": ["@biomejs/cli-linux-x64-musl@1.9.4", "", { "os": "linux", "cpu": "x64" }, "sha512-gEhi/jSBhZ2m6wjV530Yy8+fNqG8PAinM3oV7CyO+6c3CEh16Eizm21uHVsyVBEB6RIM8JHIl6AGYCv6Q6Q9Tg=="], + "@biomejs/cli-linux-x64-musl": ["@biomejs/cli-linux-x64-musl@2.1.1", "", { "os": "linux", "cpu": "x64" }, "sha512-kUu+loNI3OCD2c12cUt7M5yaaSjDnGIksZwKnueubX6c/HWUyi/0mPbTBHR49Me3F0KKjWiKM+ZOjsmC+lUt9g=="], - "@biomejs/cli-win32-arm64": ["@biomejs/cli-win32-arm64@1.9.4", "", { "os": "win32", "cpu": "arm64" }, "sha512-tlbhLk+WXZmgwoIKwHIHEBZUwxml7bRJgk0X2sPyNR3S93cdRq6XulAZRQJ17FYGGzWne0fgrXBKpl7l4M87Hg=="], + "@biomejs/cli-win32-arm64": ["@biomejs/cli-win32-arm64@2.1.1", "", { "os": "win32", "cpu": "arm64" }, "sha512-vEHK0v0oW+E6RUWLoxb2isI3rZo57OX9ZNyyGH701fZPj6Il0Rn1f5DMNyCmyflMwTnIQstEbs7n2BxYSqQx4Q=="], - "@biomejs/cli-win32-x64": ["@biomejs/cli-win32-x64@1.9.4", "", { "os": "win32", "cpu": "x64" }, "sha512-8Y5wMhVIPaWe6jw2H+KlEm4wP/f7EW3810ZLmDlrEEy5KvBsb9ECEfu/kMWD484ijfQ8+nIi0giMgu9g1UAuuA=="], + "@biomejs/cli-win32-x64": ["@biomejs/cli-win32-x64@2.1.1", "", { "os": "win32", "cpu": "x64" }, "sha512-i2PKdn70kY++KEF/zkQFvQfX1e8SkA8hq4BgC+yE9dZqyLzB/XStY2MvwI3qswlRgnGpgncgqe0QYKVS1blksg=="], - "@emnapi/core": ["@emnapi/core@1.4.3", "", { "dependencies": { "@emnapi/wasi-threads": "1.0.2", "tslib": "^2.4.0" } }, "sha512-4m62DuCE07lw01soJwPiBGC0nAww0Q+RY70VZ+n49yDIO13yyinhbWCeNnaob0lakDtWQzSdtNWzJeOJt2ma+g=="], + "@emnapi/core": ["@emnapi/core@1.5.0", "", { "dependencies": { "@emnapi/wasi-threads": "1.1.0", "tslib": "^2.4.0" } }, "sha512-sbP8GzB1WDzacS8fgNPpHlp6C9VZe+SJP3F90W9rLemaQj2PzIuTEl1qDOYQf58YIpyjViI24y9aPWCjEzY2cg=="], - "@emnapi/runtime": ["@emnapi/runtime@1.4.3", "", { "dependencies": { "tslib": "^2.4.0" } }, "sha512-pBPWdu6MLKROBX05wSNKcNb++m5Er+KQ9QkB+WVM+pW2Kx9hoSrVTnu3BdkI5eBLZoKu/J6mW/B6i6bJB2ytXQ=="], + "@emnapi/runtime": ["@emnapi/runtime@1.5.0", "", { "dependencies": { "tslib": "^2.4.0" } }, "sha512-97/BJ3iXHww3djw6hYIfErCZFee7qCtrneuLa20UXFCOTCfBM2cvQHjWJ2EG0s0MtdNwInarqCTz35i4wWXHsQ=="], - "@emnapi/wasi-threads": ["@emnapi/wasi-threads@1.0.2", "", { "dependencies": { "tslib": "^2.4.0" } }, "sha512-5n3nTJblwRi8LlXkJ9eBzu+kZR8Yxcc7ubakyQTFzPMtIhFpUBRbsnc2Dv88IZDIbCDlBiWrknhB4Lsz7mg6BA=="], + "@emnapi/wasi-threads": ["@emnapi/wasi-threads@1.1.0", "", { "dependencies": { "tslib": "^2.4.0" } }, "sha512-WI0DdZ8xFSbgMjR1sFsKABJ/C5OnRrjT06JXbZKexJGrDuPTzZdDYfFlsgcCXCyf+suG5QU2e/y1Wo2V/OapLQ=="], "@es-joy/jsdoccomment": ["@es-joy/jsdoccomment@0.50.2", "", { "dependencies": { "@types/estree": "^1.0.6", "@typescript-eslint/types": "^8.11.0", "comment-parser": "1.4.1", "esquery": "^1.6.0", "jsdoc-type-pratt-parser": "~4.1.0" } }, "sha512-YAdE/IJSpwbOTiaURNCKECdAwqrJuFiZhylmesBcIRawtYKnBR2wxPhoIewMg+Yu+QuYvHfJNReWpoxGBKOChA=="], @@ -131,7 +131,9 @@ "@humanwhocodes/retry": ["@humanwhocodes/retry@0.4.3", "", {}, "sha512-bV0Tgo9K4hfPCek+aMAn81RppFKv2ySDQeMoSZuvTASywNTnVJCArCZE2FWqpvIatKu7VMRLWlR1EazvVhDyhQ=="], - "@jridgewell/gen-mapping": ["@jridgewell/gen-mapping@0.3.8", "", { "dependencies": { "@jridgewell/set-array": "^1.2.1", "@jridgewell/sourcemap-codec": "^1.4.10", "@jridgewell/trace-mapping": "^0.3.24" } }, "sha512-imAbBGkb+ebQyxKgzv5Hu2nmROxoDOXHh80evxdoXNOrvAnVx7zimzc1Oo5h9RlfV4vPXaE2iM5pOFbvOCClWA=="], + "@jridgewell/gen-mapping": ["@jridgewell/gen-mapping@0.3.13", "", { "dependencies": { "@jridgewell/sourcemap-codec": "^1.5.0", "@jridgewell/trace-mapping": "^0.3.24" } }, "sha512-2kkt/7niJ6MgEPxF0bYdQ6etZaA+fQvDcLKckhy1yIQOzaoKjBBjSj63/aLVjYE3qhRt5dvM+uUyfCg6UKCBbA=="], + + "@jridgewell/remapping": ["@jridgewell/remapping@2.3.5", "", { "dependencies": { "@jridgewell/gen-mapping": "^0.3.5", "@jridgewell/trace-mapping": "^0.3.24" } }, "sha512-LI9u/+laYG4Ds1TDKSJW2YPrIlcVYOwi2fUC6xB43lueCjgxV4lffOCZCtYFiH6TNOX+tQKXx97T4IKHbhyHEQ=="], "@jridgewell/resolve-uri": ["@jridgewell/resolve-uri@3.1.2", "", {}, "sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw=="], @@ -139,11 +141,11 @@ "@jridgewell/sourcemap-codec": ["@jridgewell/sourcemap-codec@1.5.0", "", {}, "sha512-gv3ZRaISU3fjPAgNsriBRqGWQL6quFx04YMPW/zD8XMLsU32mhCCbfbO6KZFLjvYpCZ8zyDEgqsgf+PwPaM7GQ=="], - "@jridgewell/trace-mapping": ["@jridgewell/trace-mapping@0.3.25", "", { "dependencies": { "@jridgewell/resolve-uri": "^3.1.0", "@jridgewell/sourcemap-codec": "^1.4.14" } }, "sha512-vNk6aEwybGtawWmy/PzwnGDOjCkLWSD2wqvjGGAgOAwCGWySYXfYoxt00IJkTF+8Lb57DwOb3Aa0o9CApepiYQ=="], + "@jridgewell/trace-mapping": ["@jridgewell/trace-mapping@0.3.30", "", { "dependencies": { "@jridgewell/resolve-uri": "^3.1.0", "@jridgewell/sourcemap-codec": "^1.4.14" } }, "sha512-GQ7Nw5G2lTu/BtHTKfXhKHok2WGetd4XYcVKGx00SjAk8GMwgJM3zr6zORiPGuOE+/vkc90KtTosSSvaCjKb2Q=="], - "@kirick/lint": ["@kirick/lint@0.1.0", "", { "dependencies": { "@stylistic/eslint-plugin": "^4.4.0", "eslint": "9.27.0", "eslint-plugin-jsdoc": "50.6.17", "eslint-plugin-n": "^17.18.0", "eslint-plugin-promise": "^7.2.1", "eslint-plugin-unicorn": "59.0.1", "eslint-plugin-vue": "^10.1.0", "typescript-eslint": "8.32.1" }, "bin": { "lint": "dist/main.js" } }, "sha512-/7TnjAybQvT6oEG7jwaUQegSzDOrxfhxlAE2tojefTfDJxyK/wyxWfPXI7yzMIn/b3u5LxvENYb52OVNg/QAFA=="], + "@kirick/lint": ["@kirick/lint@0.2.7", "", { "dependencies": { "@stylistic/eslint-plugin": "^4.4.0", "eslint": "9.27.0", "eslint-plugin-jsdoc": "50.6.17", "eslint-plugin-n": "^17.18.0", "eslint-plugin-promise": "^7.2.1", "eslint-plugin-unicorn": "59.0.1", "eslint-plugin-vue": "^10.1.0", "typescript-eslint": "8.32.1" }, "bin": { "lint": "dist/main.js" } }, "sha512-ZX0C0W0nZBXRJDpGWPrpOonQUkvPyh0XWkVqK36/aEwPLbZcQJ2yGKFvtbL40ehrUObzfRZjExOuFEWVzWv9cw=="], - "@napi-rs/wasm-runtime": ["@napi-rs/wasm-runtime@0.2.10", "", { "dependencies": { "@emnapi/core": "^1.4.3", "@emnapi/runtime": "^1.4.3", "@tybys/wasm-util": "^0.9.0" } }, "sha512-bCsCyeZEwVErsGmyPNSzwfwFn4OdxBj0mmv6hOFucB/k81Ojdu68RbZdxYsRQUPc9l6SU5F/cG+bXgWs3oUgsQ=="], + "@napi-rs/wasm-runtime": ["@napi-rs/wasm-runtime@1.0.3", "", { "dependencies": { "@emnapi/core": "^1.4.5", "@emnapi/runtime": "^1.4.5", "@tybys/wasm-util": "^0.10.0" } }, "sha512-rZxtMsLwjdXkMUGC3WwsPwLNVqVqnTJT6MNIB6e+5fhMcSCPP0AOsNWuMQ5mdCq6HNjs/ZeWAEchpqeprqBD2Q=="], "@nodelib/fs.scandir": ["@nodelib/fs.scandir@2.1.5", "", { "dependencies": { "@nodelib/fs.stat": "2.0.5", "run-parallel": "^1.1.9" } }, "sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g=="], @@ -151,79 +153,59 @@ "@nodelib/fs.walk": ["@nodelib/fs.walk@1.2.8", "", { "dependencies": { "@nodelib/fs.scandir": "2.1.5", "fastq": "^1.6.0" } }, "sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg=="], - "@oxc-project/types": ["@oxc-project/types@0.71.0", "", {}, "sha512-5CwQ4MI+P4MQbjLWXgNurA+igGwu/opNetIE13LBs9+V93R64MLvDKOOLZIXSzEfovU3Zef3q3GjPnMTgJTn2w=="], - - "@oxc-resolver/binding-darwin-arm64": ["@oxc-resolver/binding-darwin-arm64@9.0.2", "", { "os": "darwin", "cpu": "arm64" }, "sha512-MVyRgP2gzJJtAowjG/cHN3VQXwNLWnY+FpOEsyvDepJki1SdAX/8XDijM1yN6ESD1kr9uhBKjGelC6h3qtT+rA=="], - - "@oxc-resolver/binding-darwin-x64": ["@oxc-resolver/binding-darwin-x64@9.0.2", "", { "os": "darwin", "cpu": "x64" }, "sha512-7kV0EOFEZ3sk5Hjy4+bfA6XOQpCwbDiDkkHN4BHHyrBHsXxUR05EcEJPPL1WjItefg+9+8hrBmoK0xRoDs41+A=="], - - "@oxc-resolver/binding-freebsd-x64": ["@oxc-resolver/binding-freebsd-x64@9.0.2", "", { "os": "freebsd", "cpu": "x64" }, "sha512-6OvkEtRXrt8sJ4aVfxHRikjain9nV1clIsWtJ1J3J8NG1ZhjyJFgT00SCvqxbK+pzeWJq6XzHyTCN78ML+lY2w=="], - - "@oxc-resolver/binding-linux-arm-gnueabihf": ["@oxc-resolver/binding-linux-arm-gnueabihf@9.0.2", "", { "os": "linux", "cpu": "arm" }, "sha512-aYpNL6o5IRAUIdoweW21TyLt54Hy/ZS9tvzNzF6ya1ckOQ8DLaGVPjGpmzxdNja9j/bbV6aIzBH7lNcBtiOTkQ=="], - - "@oxc-resolver/binding-linux-arm64-gnu": ["@oxc-resolver/binding-linux-arm64-gnu@9.0.2", "", { "os": "linux", "cpu": "arm64" }, "sha512-RGFW4vCfKMFEIzb9VCY0oWyyY9tR1/o+wDdNePhiUXZU4SVniRPQaZ1SJ0sUFI1k25pXZmzQmIP6cBmazi/Dew=="], - - "@oxc-resolver/binding-linux-arm64-musl": ["@oxc-resolver/binding-linux-arm64-musl@9.0.2", "", { "os": "linux", "cpu": "arm64" }, "sha512-lxx/PibBfzqYvut2Y8N2D0Ritg9H8pKO+7NUSJb9YjR/bfk2KRmP8iaUz3zB0JhPtf/W3REs65oKpWxgflGToA=="], + "@oxc-project/runtime": ["@oxc-project/runtime@0.82.3", "", {}, "sha512-LNh5GlJvYHAnMurO+EyA8jJwN1rki7l3PSHuosDh2I7h00T6/u9rCkUjg/SvPmT1CZzvhuW0y+gf7jcqUy/Usg=="], - "@oxc-resolver/binding-linux-riscv64-gnu": ["@oxc-resolver/binding-linux-riscv64-gnu@9.0.2", "", { "os": "linux", "cpu": "none" }, "sha512-yD28ptS/OuNhwkpXRPNf+/FvrO7lwURLsEbRVcL1kIE0GxNJNMtKgIE4xQvtKDzkhk6ZRpLho5VSrkkF+3ARTQ=="], + "@oxc-project/types": ["@oxc-project/types@0.82.3", "", {}, "sha512-6nCUxBnGX0c6qfZW5MaF6/fmu5dHJDMiMPaioKHKs5mi5+8/FHQ7WGjgQIz1zxpmceMYfdIXkOaLYE+ejbuOtA=="], - "@oxc-resolver/binding-linux-s390x-gnu": ["@oxc-resolver/binding-linux-s390x-gnu@9.0.2", "", { "os": "linux", "cpu": "s390x" }, "sha512-WBwEJdspoga2w+aly6JVZeHnxuPVuztw3fPfWrei2P6rNM5hcKxBGWKKT6zO1fPMCB4sdDkFohGKkMHVV1eryQ=="], + "@oxlint/darwin-arm64": ["@oxlint/darwin-arm64@1.3.0", "", { "os": "darwin", "cpu": "arm64" }, "sha512-TcCaETXYfiEfS+u/gZNND4WwEEtnJJjqg8BIC56WiCQDduYTvmmbQ0vxtqdNXlFzlvmRpZCSs7qaqXNy8/8FLA=="], - "@oxc-resolver/binding-linux-x64-gnu": ["@oxc-resolver/binding-linux-x64-gnu@9.0.2", "", { "os": "linux", "cpu": "x64" }, "sha512-a2z3/cbOOTUq0UTBG8f3EO/usFcdwwXnCejfXv42HmV/G8GjrT4fp5+5mVDoMByH3Ce3iVPxj1LmS6OvItKMYQ=="], + "@oxlint/darwin-x64": ["@oxlint/darwin-x64@1.3.0", "", { "os": "darwin", "cpu": "x64" }, "sha512-REgq9s1ZWuh++Vi+mUPNddLTp/D+iu+T8nLd3QM1dzQoBD/SZ7wRX3Mdv8QGT/m8dknmDBQuKAP6T47ox9HRSA=="], - "@oxc-resolver/binding-linux-x64-musl": ["@oxc-resolver/binding-linux-x64-musl@9.0.2", "", { "os": "linux", "cpu": "x64" }, "sha512-bHZF+WShYQWpuswB9fyxcgMIWVk4sZQT0wnwpnZgQuvGTZLkYJ1JTCXJMtaX5mIFHf69ngvawnwPIUA4Feil0g=="], + "@oxlint/linux-arm64-gnu": ["@oxlint/linux-arm64-gnu@1.3.0", "", { "os": "linux", "cpu": "arm64" }, "sha512-QAS8AWKDcDeUe8mJaw/pF2D9+js8FbFTo75AiekZKNm9V6QAAiCkyvesmILD8RrStw9aV2D/apOD71vsfcDoGA=="], - "@oxc-resolver/binding-wasm32-wasi": ["@oxc-resolver/binding-wasm32-wasi@9.0.2", "", { "dependencies": { "@napi-rs/wasm-runtime": "^0.2.9" }, "cpu": "none" }, "sha512-I5cSgCCh5nFozGSHz+PjIOfrqW99eUszlxKLgoNNzQ1xQ2ou9ZJGzcZ94BHsM9SpyYHLtgHljmOZxCT9bgxYNA=="], + "@oxlint/linux-arm64-musl": ["@oxlint/linux-arm64-musl@1.3.0", "", { "os": "linux", "cpu": "arm64" }, "sha512-rAbz0KFkk5GPdERoFO4ZUZmVkECnHXjRG0O2MeT5zY7ddlyZUjEk1cWjw+HCtWVdKkqhZJeNFMuEiRLkpzBIIw=="], - "@oxc-resolver/binding-win32-arm64-msvc": ["@oxc-resolver/binding-win32-arm64-msvc@9.0.2", "", { "os": "win32", "cpu": "arm64" }, "sha512-5IhoOpPr38YWDWRCA5kP30xlUxbIJyLAEsAK7EMyUgqygBHEYLkElaKGgS0X5jRXUQ6l5yNxuW73caogb2FYaw=="], + "@oxlint/linux-x64-gnu": ["@oxlint/linux-x64-gnu@1.3.0", "", { "os": "linux", "cpu": "x64" }, "sha512-6uLO1WsJwCtVNGHtjXwg2TRvxQYttYJKMjSdv6RUXGWY1AI+/+yHzvu+phU/F40uNC7CFhFnqWDuPaSZ49hdAQ=="], - "@oxc-resolver/binding-win32-x64-msvc": ["@oxc-resolver/binding-win32-x64-msvc@9.0.2", "", { "os": "win32", "cpu": "x64" }, "sha512-Qc40GDkaad9rZksSQr2l/V9UubigIHsW69g94Gswc2sKYB3XfJXfIfyV8WTJ67u6ZMXsZ7BH1msSC6Aen75mCg=="], + "@oxlint/linux-x64-musl": ["@oxlint/linux-x64-musl@1.3.0", "", { "os": "linux", "cpu": "x64" }, "sha512-+vrmJUHgtJmgIo+L9eTP04NI/OQNCOZtQo6I49qGWc9cpr+0MnIh9KMcyAOxmzVTF5g+CF1I/1bUz4pk4I3LDw=="], - "@oxlint/darwin-arm64": ["@oxlint/darwin-arm64@0.16.12", "", { "os": "darwin", "cpu": "arm64" }, "sha512-G7phYhlIA4ke2nW7tHLl+E5+rvdzgGA6830D+e+y1RGllT0w2ONGdKcVTj+2pXGCw6yPmCC5fDsDEn2+RPTfxg=="], + "@oxlint/win32-arm64": ["@oxlint/win32-arm64@1.3.0", "", { "os": "win32", "cpu": "arm64" }, "sha512-k+ETUVl+O3b8Rcd2PP5V3LqQ2QoN/TOX2f19XXHZEynbVLY3twLYPb3hLdXqoo7CKRq3RJdTfn1upHH48/qrZQ=="], - "@oxlint/darwin-x64": ["@oxlint/darwin-x64@0.16.12", "", { "os": "darwin", "cpu": "x64" }, "sha512-P/LSOgJ6SzQ3OKEIf3HsebgokZiZ5nDuTgIL4LpNCHlkOLDu/fT8XL9pSkR5y+60v0SOxUF/+aN0Q8EmxblrCw=="], + "@oxlint/win32-x64": ["@oxlint/win32-x64@1.3.0", "", { "os": "win32", "cpu": "x64" }, "sha512-nWSgK0fT02TQ/BiAUCd13BaobtHySkCDcQaL+NOmhgeb0tNWjtYiktuluahaIqFcYJPWczVlbs8DU/Eqo8vsug=="], - "@oxlint/linux-arm64-gnu": ["@oxlint/linux-arm64-gnu@0.16.12", "", { "os": "linux", "cpu": "arm64" }, "sha512-0N/ZsW+cL7ZAUvOHbzMp3iApt5b/Q81q2e9RgEzkI6gUDCJK8/blWg0se/i6y9e24WH0ZC4bcxY1+Qz4ZQ+mFw=="], - - "@oxlint/linux-arm64-musl": ["@oxlint/linux-arm64-musl@0.16.12", "", { "os": "linux", "cpu": "arm64" }, "sha512-MoG1SIw4RGowsOsPjm5HjRWymisRZWBea7ewMoXA5xIVQ3eqECifG0KJW0OZp96Ad8DFBEavdlNuImB2uXsMwg=="], - - "@oxlint/linux-x64-gnu": ["@oxlint/linux-x64-gnu@0.16.12", "", { "os": "linux", "cpu": "x64" }, "sha512-STho8QdMLfn/0lqRU94tGPaYX8lGJccPbqeUcEr3eK5gZ5ZBdXmiHlvkcngXFEXksYC8/5VoJN7Vf3HsmkEskw=="], - - "@oxlint/linux-x64-musl": ["@oxlint/linux-x64-musl@0.16.12", "", { "os": "linux", "cpu": "x64" }, "sha512-i7pzSoj9nCg/ZzOe8dCZeFWyRRWDylR9tIX04xRTq3G6PBLm6i9VrOdEkxbgM9+pCkRzUc0a9D7rbtCF34TQUA=="], - - "@oxlint/win32-arm64": ["@oxlint/win32-arm64@0.16.12", "", { "os": "win32", "cpu": "arm64" }, "sha512-wcxq3IBJ7ZlONlXJxQM+7EMx+LX1nkz3ZS3R0EtDM76EOZaqe8BMkW5cXVhF8jarZTZC18oKAckW4Ng9d8adBg=="], + "@publint/pack": ["@publint/pack@0.1.2", "", {}, "sha512-S+9ANAvUmjutrshV4jZjaiG8XQyuJIZ8a4utWmN/vW1sgQ9IfBnPndwkmQYw53QmouOIytT874u65HEmu6H5jw=="], - "@oxlint/win32-x64": ["@oxlint/win32-x64@0.16.12", "", { "os": "win32", "cpu": "x64" }, "sha512-Ae1fx7wmAcMVqzS8rLINaFRpAdh29QzHh133bEYMHzfWBYyK/hLu9g4GLwC/lEIVQu9884b8qutGfdOk6Qia3w=="], + "@quansync/fs": ["@quansync/fs@0.1.5", "", { "dependencies": { "quansync": "^0.2.11" } }, "sha512-lNS9hL2aS2NZgNW7BBj+6EBl4rOf8l+tQ0eRY6JWCI8jI2kc53gSoqbjojU0OnAWhzoXiOjFyGsHcDGePB3lhA=="], - "@publint/pack": ["@publint/pack@0.1.2", "", {}, "sha512-S+9ANAvUmjutrshV4jZjaiG8XQyuJIZ8a4utWmN/vW1sgQ9IfBnPndwkmQYw53QmouOIytT874u65HEmu6H5jw=="], + "@rolldown/binding-android-arm64": ["@rolldown/binding-android-arm64@1.0.0-beta.34", "", { "os": "android", "cpu": "arm64" }, "sha512-jf5GNe5jP3Sr1Tih0WKvg2bzvh5T/1TA0fn1u32xSH7ca/p5t+/QRr4VRFCV/na5vjwKEhwWrChsL2AWlY+eoA=="], - "@quansync/fs": ["@quansync/fs@0.1.3", "", { "dependencies": { "quansync": "^0.2.10" } }, "sha512-G0OnZbMWEs5LhDyqy2UL17vGhSVHkQIfVojMtEWVenvj0V5S84VBgy86kJIuNsGDp2p7sTKlpSIpBUWdC35OKg=="], + "@rolldown/binding-darwin-arm64": ["@rolldown/binding-darwin-arm64@1.0.0-beta.34", "", { "os": "darwin", "cpu": "arm64" }, "sha512-2F/TqH4QuJQ34tgWxqBjFL3XV1gMzeQgUO8YRtCPGBSP0GhxtoFzsp7KqmQEothsxztlv+KhhT9Dbg3HHwHViQ=="], - "@rolldown/binding-darwin-arm64": ["@rolldown/binding-darwin-arm64@1.0.0-beta.9-commit.51df2b7", "", { "os": "darwin", "cpu": "arm64" }, "sha512-ho2xtXwIXiSIlI0C4G9TKxeRC0BOlML1JMNILpxvdjJiN/M6zV/MYIys6ZyqIlIlLzilr0Wu4KIpb+mnR2E7tQ=="], + "@rolldown/binding-darwin-x64": ["@rolldown/binding-darwin-x64@1.0.0-beta.34", "", { "os": "darwin", "cpu": "x64" }, "sha512-E1QuFslgLWbHQ8Qli/AqUKdfg0pockQPwRxVbhNQ74SciZEZpzLaujkdmOLSccMlSXDfFCF8RPnMoRAzQ9JV8Q=="], - "@rolldown/binding-darwin-x64": ["@rolldown/binding-darwin-x64@1.0.0-beta.9-commit.51df2b7", "", { "os": "darwin", "cpu": "x64" }, "sha512-f9llkFu7gAL/uvbU9JQtMgrPXE70HZ8VXHMD6ENvdzmM+Z/Bh8WnquwbgpSSnj9M111Tg4gyZe3R31CTYlcQow=="], + "@rolldown/binding-freebsd-x64": ["@rolldown/binding-freebsd-x64@1.0.0-beta.34", "", { "os": "freebsd", "cpu": "x64" }, "sha512-VS8VInNCwnkpI9WeQaWu3kVBq9ty6g7KrHdLxYMzeqz24+w9hg712TcWdqzdY6sn+24lUoMD9jTZrZ/qfVpk0g=="], - "@rolldown/binding-freebsd-x64": ["@rolldown/binding-freebsd-x64@1.0.0-beta.9-commit.51df2b7", "", { "os": "freebsd", "cpu": "x64" }, "sha512-ZP3+8qmcUkxzXMvGVyaPKKUswhyRfBo4EGEo4FOxQ6+D+XjTaL4rSGOs979CBpfk7f3HIxyKEXvWokv6fsdTdw=="], + "@rolldown/binding-linux-arm-gnueabihf": ["@rolldown/binding-linux-arm-gnueabihf@1.0.0-beta.34", "", { "os": "linux", "cpu": "arm" }, "sha512-4St4emjcnULnxJYb/5ZDrH/kK/j6PcUgc3eAqH5STmTrcF+I9m/X2xvSF2a2bWv1DOQhxBewThu0KkwGHdgu5w=="], - "@rolldown/binding-linux-arm-gnueabihf": ["@rolldown/binding-linux-arm-gnueabihf@1.0.0-beta.9-commit.51df2b7", "", { "os": "linux", "cpu": "arm" }, "sha512-lb4TCuCGimXdImS1fiZqfZBObgxZr32P8u1T8FeifdwGCieXnz5CjoywDyrhZuZMoLU3UU3PJV7WcD8721jK/g=="], + "@rolldown/binding-linux-arm64-gnu": ["@rolldown/binding-linux-arm64-gnu@1.0.0-beta.34", "", { "os": "linux", "cpu": "arm64" }, "sha512-a737FTqhFUoWfnebS2SnQ2BS50p0JdukdkUBwy2J06j4hZ6Eej0zEB8vTfAqoCjn8BQKkXBy+3Sx0IRkgwz1gA=="], - "@rolldown/binding-linux-arm64-gnu": ["@rolldown/binding-linux-arm64-gnu@1.0.0-beta.9-commit.51df2b7", "", { "os": "linux", "cpu": "arm64" }, "sha512-07FhoEJsku912alIEfTf1QmEMWxjuQxkPD6ewWtyyhEZHDF5XhpKpat/GFEDic/doXVRggRvxIZccyS5Kyu45A=="], + "@rolldown/binding-linux-arm64-musl": ["@rolldown/binding-linux-arm64-musl@1.0.0-beta.34", "", { "os": "linux", "cpu": "arm64" }, "sha512-NH+FeQWKyuw0k+PbXqpFWNfvD8RPvfJk766B/njdaWz4TmiEcSB0Nb6guNw1rBpM1FmltQYb3fFnTumtC6pRfA=="], - "@rolldown/binding-linux-arm64-musl": ["@rolldown/binding-linux-arm64-musl@1.0.0-beta.9-commit.51df2b7", "", { "os": "linux", "cpu": "arm64" }, "sha512-QUHSOXq6F+Z4eBud86nGq2C/KhdNs980LLQcAFDIr6tPw5fN8Z2Zqy61XeWGB01Y30G5esiMzsJqsHHQDqSvsg=="], + "@rolldown/binding-linux-x64-gnu": ["@rolldown/binding-linux-x64-gnu@1.0.0-beta.34", "", { "os": "linux", "cpu": "x64" }, "sha512-Q3RSCivp8pNadYK8ke3hLnQk08BkpZX9BmMjgwae2FWzdxhxxUiUzd9By7kneUL0vRQ4uRnhD9VkFQ+Haeqdvw=="], - "@rolldown/binding-linux-x64-gnu": ["@rolldown/binding-linux-x64-gnu@1.0.0-beta.9-commit.51df2b7", "", { "os": "linux", "cpu": "x64" }, "sha512-VdsjRgP2VlAJqbuHdY3Xh37+yU7H+KYy3fA2+falRGlhko20/Ch8V7+7SizTu2LfKgvd1LVhQek8InnmojX0tA=="], + "@rolldown/binding-linux-x64-musl": ["@rolldown/binding-linux-x64-musl@1.0.0-beta.34", "", { "os": "linux", "cpu": "x64" }, "sha512-wDd/HrNcVoBhWWBUW3evJHoo7GJE/RofssBy3Dsiip05YUBmokQVrYAyrboOY4dzs/lJ7HYeBtWQ9hj8wlyF0A=="], - "@rolldown/binding-linux-x64-musl": ["@rolldown/binding-linux-x64-musl@1.0.0-beta.9-commit.51df2b7", "", { "os": "linux", "cpu": "x64" }, "sha512-zbilaXq6n+FerHarckH20bh5QgSPO9dCC4BfAzXidaji/eMRO0gfjFjKJpVx0gxwc+LVBjdHDKB0DplGZiPMEw=="], + "@rolldown/binding-openharmony-arm64": ["@rolldown/binding-openharmony-arm64@1.0.0-beta.34", "", { "os": "none", "cpu": "arm64" }, "sha512-dH3FTEV6KTNWpYSgjSXZzeX7vLty9oBYn6R3laEdhwZftQwq030LKL+5wyQdlbX5pnbh4h127hpv3Hl1+sj8dg=="], - "@rolldown/binding-wasm32-wasi": ["@rolldown/binding-wasm32-wasi@1.0.0-beta.9-commit.51df2b7", "", { "dependencies": { "@napi-rs/wasm-runtime": "^0.2.4" }, "cpu": "none" }, "sha512-iqvvLmCl9n3TzE6QLZ1ZRYigavEoOVr33Q6qoLbDHnnXZqp1V9APLckbv8E9qaukDmbVP3dOCr/dD7AT+GsE3w=="], + "@rolldown/binding-wasm32-wasi": ["@rolldown/binding-wasm32-wasi@1.0.0-beta.34", "", { "dependencies": { "@napi-rs/wasm-runtime": "^1.0.3" }, "cpu": "none" }, "sha512-y5BUf+QtO0JsIDKA51FcGwvhJmv89BYjUl8AmN7jqD6k/eU55mH6RJYnxwCsODq5m7KSSTigVb6O7/GqB8wbPw=="], - "@rolldown/binding-win32-arm64-msvc": ["@rolldown/binding-win32-arm64-msvc@1.0.0-beta.9-commit.51df2b7", "", { "os": "win32", "cpu": "arm64" }, "sha512-ey1jfhd5BFn4bIJjQAVNclkDCl9mg9b96LyDHVETkZZrmAV8zSaE0kazXe5eWn8n7p0RH2t1cOiQWVcXrFVh0g=="], + "@rolldown/binding-win32-arm64-msvc": ["@rolldown/binding-win32-arm64-msvc@1.0.0-beta.34", "", { "os": "win32", "cpu": "arm64" }, "sha512-ga5hFhdTwpaNxEiuxZHWnD3ed0GBAzbgzS5tRHpe0ObptxM1a9Xrq6TVfNQirBLwb5Y7T/FJmJi3pmdLy95ljg=="], - "@rolldown/binding-win32-ia32-msvc": ["@rolldown/binding-win32-ia32-msvc@1.0.0-beta.9-commit.51df2b7", "", { "os": "win32", "cpu": "ia32" }, "sha512-RBWTjyturLAPInDJH+945twk31bkEw4t0wcWZFXzGFGN6fjeF0Jlj9fPQ3+TO3GhqAgeLymraFztJJdLVc7hSg=="], + "@rolldown/binding-win32-ia32-msvc": ["@rolldown/binding-win32-ia32-msvc@1.0.0-beta.34", "", { "os": "win32", "cpu": "ia32" }, "sha512-4/MBp9T9eRnZskxWr8EXD/xHvLhdjWaeX/qY9LPRG1JdCGV3DphkLTy5AWwIQ5jhAy2ZNJR5z2fYRlpWU0sIyQ=="], - "@rolldown/binding-win32-x64-msvc": ["@rolldown/binding-win32-x64-msvc@1.0.0-beta.9-commit.51df2b7", "", { "os": "win32", "cpu": "x64" }, "sha512-umDrroMuEfK3xYcRvr6p7u1AUwv3IoY2Sl6LlBZ5ncOAZ/OQo/41wHwUHtN+PRE02/BI8f84HMZrMR+rJgkmog=="], + "@rolldown/binding-win32-x64-msvc": ["@rolldown/binding-win32-x64-msvc@1.0.0-beta.34", "", { "os": "win32", "cpu": "x64" }, "sha512-7O5iUBX6HSBKlQU4WykpUoEmb0wQmonb6ziKFr3dJTHud2kzDnWMqk344T0qm3uGv9Ddq6Re/94pInxo1G2d4w=="], - "@rolldown/pluginutils": ["@rolldown/pluginutils@1.0.0-beta.9-commit.51df2b7", "", {}, "sha512-A+2WuD4O5309iooTWXMS0vMfb44bKJUOCwJj2oBYvOpaNT3VHFmgLdx++NTlKh/3hJ8Xa+Zy8c34z0EBQSU+mw=="], + "@rolldown/pluginutils": ["@rolldown/pluginutils@1.0.0-beta.34", "", {}, "sha512-LyAREkZHP5pMom7c24meKmJCdhf2hEyvam2q0unr3or9ydwDL+DJ8chTF6Av/RFPb3rH8UFBdMzO5MxTZW97oA=="], "@rollup/rollup-android-arm-eabi": ["@rollup/rollup-android-arm-eabi@4.21.2", "", { "os": "android", "cpu": "arm" }, "sha512-fSuPrt0ZO8uXeS+xP3b+yYTCBUd05MoSp2N/MFOgjhhUhMmchXlpTQrTpI8T+YAwAQuK7MafsCOxW7VrPMrJcg=="], @@ -259,15 +241,21 @@ "@stylistic/eslint-plugin": ["@stylistic/eslint-plugin@4.4.0", "", { "dependencies": { "@typescript-eslint/utils": "^8.32.1", "eslint-visitor-keys": "^4.2.0", "espree": "^10.3.0", "estraverse": "^5.3.0", "picomatch": "^4.0.2" }, "peerDependencies": { "eslint": ">=9.0.0" } }, "sha512-bIh/d9X+OQLCAMdhHtps+frvyjvAM4B1YlSJzcEEhl7wXLIqPar3ngn9DrHhkBOrTA/z9J0bUMtctAspe0dxdQ=="], - "@tybys/wasm-util": ["@tybys/wasm-util@0.9.0", "", { "dependencies": { "tslib": "^2.4.0" } }, "sha512-6+7nlbMVX/PVDCwaIQ8nTOPveOcFLSt8GcXdx8hD0bt39uWxYT88uXzqTd4fTvqta7oeUJqudepapKNt2DYJFw=="], + "@tybys/wasm-util": ["@tybys/wasm-util@0.10.0", "", { "dependencies": { "tslib": "^2.4.0" } }, "sha512-VyyPYFlOMNylG45GoAe0xDoLwWuowvf92F9kySqzYh8vmYm7D2u4iUJKa1tOUpS70Ku13ASrOkS4ScXFsTaCNQ=="], + + "@types/bun": ["@types/bun@1.2.21", "", { "dependencies": { "bun-types": "1.2.21" } }, "sha512-NiDnvEqmbfQ6dmZ3EeUO577s4P5bf4HCTXtI6trMc6f6RzirY5IrF3aIookuSpyslFzrnvv2lmEWv5HyC1X79A=="], - "@types/bun": ["@types/bun@1.2.14", "", { "dependencies": { "bun-types": "1.2.14" } }, "sha512-VsFZKs8oKHzI7zwvECiAJ5oSorWndIWEVhfbYqZd4HI/45kzW7PN2Rr5biAzvGvRuNmYLSANY+H59ubHq8xw7Q=="], + "@types/chai": ["@types/chai@5.2.2", "", { "dependencies": { "@types/deep-eql": "*" } }, "sha512-8kB30R7Hwqf40JPiKhVzodJs2Qc1ZJ5zuT3uzw5Hq/dhNCl3G3l83jfpdI1e20BP348+fV7VIL/+FxaXkqBmWg=="], + + "@types/deep-eql": ["@types/deep-eql@4.0.2", "", {}, "sha512-c9h9dVVMigMPc4bwTvC5dxqtqJZwQPePsWjPlpSOnojbor6pGqdk541lfA7AqFQr5pB1BRdq0juY9db81BwyFw=="], "@types/estree": ["@types/estree@1.0.7", "", {}, "sha512-w28IoSUCJpidD/TGviZwwMJckNESJZXFu7NBZ5YJ4mEUnNraUn9Pm8HSZm/jDF1pDWYKspWE7oVphigUPRakIQ=="], "@types/json-schema": ["@types/json-schema@7.0.15", "", {}, "sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA=="], - "@types/node": ["@types/node@22.15.23", "", { "dependencies": { "undici-types": "~6.21.0" } }, "sha512-7Ec1zaFPF4RJ0eXu1YT/xgiebqwqoJz8rYPDi/O2BcZ++Wpt0Kq9cl0eg6NN6bYbPnR67ZLo7St5Q3UK0SnARw=="], + "@types/node": ["@types/node@20.16.5", "", { "dependencies": { "undici-types": "~6.19.2" } }, "sha512-VwYCweNo3ERajwy0IUlqqcyZ8/A7Zwa9ZP3MnENWcB11AejO+tLy3pu850goUW2FC/IJMdZUfKpX/yxL1gymCA=="], + + "@types/react": ["@types/react@19.1.12", "", { "dependencies": { "csstype": "^3.0.2" } }, "sha512-cMoR+FoAf/Jyq6+Df2/Z41jISvGZZ2eTlnsaJRptmZ76Caldwy1odD4xTr/gNV9VLj0AWgg/nmkevIyUfIIq5w=="], "@typescript-eslint/eslint-plugin": ["@typescript-eslint/eslint-plugin@8.32.1", "", { "dependencies": { "@eslint-community/regexpp": "^4.10.0", "@typescript-eslint/scope-manager": "8.32.1", "@typescript-eslint/type-utils": "8.32.1", "@typescript-eslint/utils": "8.32.1", "@typescript-eslint/visitor-keys": "8.32.1", "graphemer": "^1.4.0", "ignore": "^7.0.0", "natural-compare": "^1.4.0", "ts-api-utils": "^2.1.0" }, "peerDependencies": { "@typescript-eslint/parser": "^8.0.0 || ^8.0.0-alpha.0", "eslint": "^8.57.0 || ^9.0.0", "typescript": ">=4.8.4 <5.9.0" } }, "sha512-6u6Plg9nP/J1GRpe/vcjjabo6Uc5YQPAMxsgQyGC/I0RuukiG1wIe3+Vtg3IrSCVJDmqK3j8adrtzXSENRtFgg=="], @@ -285,19 +273,19 @@ "@typescript-eslint/visitor-keys": ["@typescript-eslint/visitor-keys@8.32.1", "", { "dependencies": { "@typescript-eslint/types": "8.32.1", "eslint-visitor-keys": "^4.2.0" } }, "sha512-ar0tjQfObzhSaW3C3QNmTc5ofj0hDoNQ5XWrCy6zDyabdr0TWhCkClp+rywGNj/odAFBVzzJrK4tEq5M4Hmu4w=="], - "@vitest/expect": ["@vitest/expect@3.1.4", "", { "dependencies": { "@vitest/spy": "3.1.4", "@vitest/utils": "3.1.4", "chai": "^5.2.0", "tinyrainbow": "^2.0.0" } }, "sha512-xkD/ljeliyaClDYqHPNCiJ0plY5YIcM0OlRiZizLhlPmpXWpxnGMyTZXOHFhFeG7w9P5PBeL4IdtJ/HeQwTbQA=="], + "@vitest/expect": ["@vitest/expect@3.2.4", "", { "dependencies": { "@types/chai": "^5.2.2", "@vitest/spy": "3.2.4", "@vitest/utils": "3.2.4", "chai": "^5.2.0", "tinyrainbow": "^2.0.0" } }, "sha512-Io0yyORnB6sikFlt8QW5K7slY4OjqNX9jmJQ02QDda8lyM6B5oNgVWoSoKPac8/kgnCUzuHQKrSLtu/uOqqrig=="], - "@vitest/mocker": ["@vitest/mocker@3.1.4", "", { "dependencies": { "@vitest/spy": "3.1.4", "estree-walker": "^3.0.3", "magic-string": "^0.30.17" }, "peerDependencies": { "msw": "^2.4.9", "vite": "^5.0.0 || ^6.0.0" }, "optionalPeers": ["msw", "vite"] }, "sha512-8IJ3CvwtSw/EFXqWFL8aCMu+YyYXG2WUSrQbViOZkWTKTVicVwZ/YiEZDSqD00kX+v/+W+OnxhNWoeVKorHygA=="], + "@vitest/mocker": ["@vitest/mocker@3.2.4", "", { "dependencies": { "@vitest/spy": "3.2.4", "estree-walker": "^3.0.3", "magic-string": "^0.30.17" }, "peerDependencies": { "msw": "^2.4.9", "vite": "^5.0.0 || ^6.0.0 || ^7.0.0-0" }, "optionalPeers": ["msw", "vite"] }, "sha512-46ryTE9RZO/rfDd7pEqFl7etuyzekzEhUbTW3BvmeO/BcCMEgq59BKhek3dXDWgAj4oMK6OZi+vRr1wPW6qjEQ=="], - "@vitest/pretty-format": ["@vitest/pretty-format@3.1.4", "", { "dependencies": { "tinyrainbow": "^2.0.0" } }, "sha512-cqv9H9GvAEoTaoq+cYqUTCGscUjKqlJZC7PRwY5FMySVj5J+xOm1KQcCiYHJOEzOKRUhLH4R2pTwvFlWCEScsg=="], + "@vitest/pretty-format": ["@vitest/pretty-format@3.2.4", "", { "dependencies": { "tinyrainbow": "^2.0.0" } }, "sha512-IVNZik8IVRJRTr9fxlitMKeJeXFFFN0JaB9PHPGQ8NKQbGpfjlTx9zO4RefN8gp7eqjNy8nyK3NZmBzOPeIxtA=="], - "@vitest/runner": ["@vitest/runner@3.1.4", "", { "dependencies": { "@vitest/utils": "3.1.4", "pathe": "^2.0.3" } }, "sha512-djTeF1/vt985I/wpKVFBMWUlk/I7mb5hmD5oP8K9ACRmVXgKTae3TUOtXAEBfslNKPzUQvnKhNd34nnRSYgLNQ=="], + "@vitest/runner": ["@vitest/runner@3.2.4", "", { "dependencies": { "@vitest/utils": "3.2.4", "pathe": "^2.0.3", "strip-literal": "^3.0.0" } }, "sha512-oukfKT9Mk41LreEW09vt45f8wx7DordoWUZMYdY/cyAk7w5TWkTRCNZYF7sX7n2wB7jyGAl74OxgwhPgKaqDMQ=="], - "@vitest/snapshot": ["@vitest/snapshot@3.1.4", "", { "dependencies": { "@vitest/pretty-format": "3.1.4", "magic-string": "^0.30.17", "pathe": "^2.0.3" } }, "sha512-JPHf68DvuO7vilmvwdPr9TS0SuuIzHvxeaCkxYcCD4jTk67XwL45ZhEHFKIuCm8CYstgI6LZ4XbwD6ANrwMpFg=="], + "@vitest/snapshot": ["@vitest/snapshot@3.2.4", "", { "dependencies": { "@vitest/pretty-format": "3.2.4", "magic-string": "^0.30.17", "pathe": "^2.0.3" } }, "sha512-dEYtS7qQP2CjU27QBC5oUOxLE/v5eLkGqPE0ZKEIDGMs4vKWe7IjgLOeauHsR0D5YuuycGRO5oSRXnwnmA78fQ=="], - "@vitest/spy": ["@vitest/spy@3.1.4", "", { "dependencies": { "tinyspy": "^3.0.2" } }, "sha512-Xg1bXhu+vtPXIodYN369M86K8shGLouNjoVI78g8iAq2rFoHFdajNvJJ5A/9bPMFcfQqdaCpOgWKEoMQg/s0Yg=="], + "@vitest/spy": ["@vitest/spy@3.2.4", "", { "dependencies": { "tinyspy": "^4.0.3" } }, "sha512-vAfasCOe6AIK70iP5UD11Ac4siNUNJ9i/9PZ3NKx07sG6sUxeag1LWdNrMWeKKYBLlzuK+Gn65Yd5nyL6ds+nw=="], - "@vitest/utils": ["@vitest/utils@3.1.4", "", { "dependencies": { "@vitest/pretty-format": "3.1.4", "loupe": "^3.1.3", "tinyrainbow": "^2.0.0" } }, "sha512-yriMuO1cfFhmiGc8ataN51+9ooHRuURdfAZfwFd3usWynjzpLslZdYnRegTv32qdgtJTsj15FoeZe2g15fY1gg=="], + "@vitest/utils": ["@vitest/utils@3.2.4", "", { "dependencies": { "@vitest/pretty-format": "3.2.4", "loupe": "^3.1.4", "tinyrainbow": "^2.0.0" } }, "sha512-fB2V0JFrQSMsCo9HiSq3Ezpdv4iYaXRG1Sx8edX3MwxfyNn83mKiGzOcH+Fkxt4MHxr3y42fQi1oeAInqgX2QA=="], "acorn": ["acorn@8.14.1", "", { "bin": { "acorn": "bin/acorn" } }, "sha512-OvQ/2pUDKmgfCg++xsTX1wGxfTaszcHVcTctW4UJB4hibJx2HXxxO5UmVgyjMa+ZDsiaf5wWLXYpRWMmBI0QHg=="], @@ -307,7 +295,7 @@ "ansi-styles": ["ansi-styles@4.3.0", "", { "dependencies": { "color-convert": "^2.0.1" } }, "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg=="], - "ansis": ["ansis@4.0.0", "", {}, "sha512-P8nrHI1EyW9OfBt1X7hMSwGN2vwRuqHSKJAT1gbLWZRzDa24oHjYwGHvEgHeBepupzk878yS/HBZ0NMPYtbolw=="], + "ansis": ["ansis@4.1.0", "", {}, "sha512-BGcItUBWSMRgOCe+SVZJ+S7yTRG0eGt9cXAHev72yuGcY23hnLA7Bky5L/xLyPINoSN95geovfBkqoTlNZYa7w=="], "are-docs-informative": ["are-docs-informative@0.0.2", "", {}, "sha512-ixiS0nLNNG5jNQzgZJNoUpBKdo9yTYZMGJ+QgT2jmjR7G7+QHRCc4v6LQ3NgE7EBJq+o0ams3waJwkrlBom8Ig=="], @@ -315,11 +303,11 @@ "assertion-error": ["assertion-error@2.0.1", "", {}, "sha512-Izi8RQcffqCeNVgFigKli1ssklIbpHnCYc6AknXGYoB6grJqyeby7jv12JUQgmTAnIDnbck1uxksT4dzN3PWBA=="], - "ast-kit": ["ast-kit@2.0.0", "", { "dependencies": { "@babel/parser": "^7.27.2", "pathe": "^2.0.3" } }, "sha512-P63jzlYNz96MF9mCcprU+a7I5/ZQ5QAn3y+mZcPWEcGV3CHF/GWnkFPj3oCrWLUjL47+PD9PNiCUdXxw0cWdsg=="], + "ast-kit": ["ast-kit@2.1.2", "", { "dependencies": { "@babel/parser": "^7.28.0", "pathe": "^2.0.3" } }, "sha512-cl76xfBQM6pztbrFWRnxbrDm9EOqDr1BF6+qQnnDZG2Co2LjyUktkN9GTJfBAfdae+DbT2nJf2nCGAdDDN7W2g=="], "balanced-match": ["balanced-match@1.0.2", "", {}, "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw=="], - "birpc": ["birpc@2.3.0", "", {}, "sha512-ijbtkn/F3Pvzb6jHypHRyve2QApOCZDR25D/VnkY2G/lBNcXCTsnsCxgY4k4PkVB7zfwzYbY3O9Lcqe3xufS5g=="], + "birpc": ["birpc@2.5.0", "", {}, "sha512-VSWO/W6nNQdyP520F1mhf+Lc2f8pjGQOtoHHm7Ze8Go1kX7akpVIrtTa0fn+HB0QJEDVacl6aO08YE0PgXfdnQ=="], "boolbase": ["boolbase@1.0.0", "", {}, "sha512-JZOSA7Mo9sNGB8+UjSgzdLtokWAky1zbztM3WRLCbZ70/3cTANmQmOdR7y2g+J0e2WXywy1yS468tY+IruqEww=="], @@ -331,7 +319,7 @@ "builtin-modules": ["builtin-modules@5.0.0", "", {}, "sha512-bkXY9WsVpY7CvMhKSR6pZilZu9Ln5WDrKVBUXf2S443etkmEO4V58heTecXcUIsNsi4Rx8JUO4NfX1IcQl4deg=="], - "bun-types": ["bun-types@1.2.14", "", { "dependencies": { "@types/node": "*" } }, "sha512-Kuh4Ub28ucMRWeiUUWMHsT9Wcbr4H3kLIO72RZZElSDxSu7vpetRvxIUDUaW6QtaIeixIpm7OXtNnZPf82EzwA=="], + "bun-types": ["bun-types@1.2.21", "", { "dependencies": { "@types/node": "*" }, "peerDependencies": { "@types/react": "^19" } }, "sha512-sa2Tj77Ijc/NTLS0/Odjq/qngmEPZfbfnOERi0KRUYhT9R8M4VBioWVmMWE5GrYbKMc+5lVybXygLdibHaqVqw=="], "cac": ["cac@6.7.14", "", {}, "sha512-b6Ilus+c3RrdDk+JhLKUAQfzzgLEPy6wcXqS7f/xe1EETvsDP6GORG7SFuOs6cID5YkqchW/LXZbX5bc8j7ZcQ=="], @@ -367,6 +355,8 @@ "cssesc": ["cssesc@3.0.0", "", { "bin": { "cssesc": "bin/cssesc" } }, "sha512-/Tb/JcjK111nNScGob5MNtsntNM1aCNUDipB/TkwZFhyDrrE47SOx/18wF2bbjgc3ZzCSKW1T5nt5EbFoAz/Vg=="], + "csstype": ["csstype@3.1.3", "", {}, "sha512-M1uQkMl8rQK/szD0LNhtqxIPLpimGm8sOBwU7lLnCpSbTyY3yeU1Vc7l4KT5zT4s/yOxHH5O7tIuuLOCnLADRw=="], + "debug": ["debug@4.4.1", "", { "dependencies": { "ms": "^2.1.3" } }, "sha512-KcKCqiftBJcZr++7ykoDIEwSa3XWowTfNPo92BYxjXiyYEVrUQh2aLyhxBCwww+heortUFxEJYcRzosstTEBYQ=="], "deep-eql": ["deep-eql@5.0.2", "", {}, "sha512-h5k/5U50IJJFpzfL6nO9jaaumfjO/f2NjK/oYB2Djzm4p9L+3T9qWpZqZ2hAbLPuuYq9wrU08WQyBTL5GbPk5Q=="], @@ -379,11 +369,11 @@ "diff": ["diff@8.0.2", "", {}, "sha512-sSuxWU5j5SR9QQji/o2qMvqRNYRDOcBTgsJ/DeCf4iSN4gW+gNMXM7wFIP+fdXZxoNiAnHUTGjCr+TSWXdRDKg=="], - "dts-resolver": ["dts-resolver@2.0.1", "", { "peerDependencies": { "oxc-resolver": "^9.0.2" }, "optionalPeers": ["oxc-resolver"] }, "sha512-Pe2kqaQTNVxleYpt9Q9658fn6rEpoZbMbDpEBbcU6pnuGM3Q0IdM+Rv67kN6qcyp8Bv2Uv9NYy5Y1rG1LSgfoQ=="], + "dts-resolver": ["dts-resolver@2.1.2", "", { "peerDependencies": { "oxc-resolver": ">=11.0.0" }, "optionalPeers": ["oxc-resolver"] }, "sha512-xeXHBQkn2ISSXxbJWD828PFjtyg+/UrMDo7W4Ffcs7+YWCquxU8YjV1KoxuiL+eJ5pg3ll+bC6flVv61L3LKZg=="], "electron-to-chromium": ["electron-to-chromium@1.5.159", "", {}, "sha512-CEvHptWAMV5p6GJ0Lq8aheyvVbfzVrv5mmidu1D3pidoVNkB3tTBsTMVtPJ+rzRK5oV229mCLz9Zj/hNvU8GBA=="], - "empathic": ["empathic@1.1.0", "", {}, "sha512-rsPft6CK3eHtrlp9Y5ALBb+hfK+DWnA4WFebbazxjWyx8vSm3rZeoM3z9irsjcqO3PYRzlfv27XIB4tz2DV7RA=="], + "empathic": ["empathic@2.0.0", "", {}, "sha512-i6UzDscO/XfAcNYD75CfICkmfLedpyPDdozrLMmQc5ORaQcdMoc21OnlEylMIqI7U8eniKrPMxxtj8k0vhmJhA=="], "enhanced-resolve": ["enhanced-resolve@5.17.1", "", { "dependencies": { "graceful-fs": "^4.2.4", "tapable": "^2.2.0" } }, "sha512-LMHl3dXhTcfv8gM4kEzIUeTQ+7fpdA0l2tUf34BddXPkz2A5xJ5L/Pchd5BL6rdccM9QGvu0sWZzK1Z1t4wwyg=="], @@ -429,7 +419,7 @@ "expect-type": ["expect-type@1.2.1", "", {}, "sha512-/kP8CAwxzLVEeFrMm4kMmy4CCDlpipyA7MYLVrdJIkV0fYF0UaigQHRsxHiuY/GEea+bh4KSv3TIlgr+2UL6bw=="], - "exsolve": ["exsolve@1.0.5", "", {}, "sha512-pz5dvkYYKQ1AHVrgOzBKWeP4u4FRb3a6DNK2ucr0OoNwYIU4QWsJ+NM36LLzORT+z845MzKHHhpXiUF5nvQoJg=="], + "exsolve": ["exsolve@1.0.7", "", {}, "sha512-VO5fQUzZtI6C+vx4w/4BWJpg3s/5l+6pRQEHzFRM8WFi4XffSP1Z+4qi7GbjWbvRQEbdIco5mIMq+zX4rPuLrw=="], "fast-deep-equal": ["fast-deep-equal@3.1.3", "", {}, "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q=="], @@ -489,7 +479,7 @@ "isexe": ["isexe@2.0.0", "", {}, "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw=="], - "itty-router": ["itty-router@5.0.18", "", {}, "sha512-mK3ReOt4ARAGy0V0J7uHmArG2USN2x0zprZ+u+YgmeRjXTDbaowDy3kPcsmQY6tH+uHhDgpWit9Vqmv/4rTXwA=="], + "itty-router": ["itty-router@5.0.22", "", {}, "sha512-9hmdGErWdYDOurGYxSbqLhy4EFReIwk71hMZTJ5b+zfa2zjMNV1ftFno2b8VjAQvX615gNB8Qxbl9JMRqHnIVA=="], "jiti": ["jiti@2.4.2", "", { "bin": { "jiti": "lib/jiti-cli.mjs" } }, "sha512-rg9zJN+G4n2nfJl5MW3BMygZX56zKPNVEYYqq7adpmMh4Jn2QNEwhvQlFy6jPVdcod7txZtKHWnyZiA3a0zP7A=="], @@ -539,7 +529,7 @@ "lodash.merge": ["lodash.merge@4.6.2", "", {}, "sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ=="], - "loupe": ["loupe@3.1.3", "", {}, "sha512-kkIp7XSkP78ZxJEsSxW3712C6teJVoeHHwgo9zJ380de7IYyJ2ISlxojcH2pC5OFLewESmnRi/+XCDIEEVyoug=="], + "loupe": ["loupe@3.2.1", "", {}, "sha512-CdzqowRJCeLU72bHvWqwRBBlLcMEtIvGrlvef74kMnV2AolS9Y8xUv1I0U/MNAWMhBlKIoyuEgoJ0t/bbwHbLQ=="], "magic-string": ["magic-string@0.30.17", "", { "dependencies": { "@jridgewell/sourcemap-codec": "^1.5.0" } }, "sha512-sNPKHvyjVf7gyjwS4xGTaW/mCnF8wnjtifKBEhxfZ7E/S8tQ0rssrwGNn6q8JH/ohItJfSQp9mBtQYuTlH5QnA=="], @@ -565,9 +555,7 @@ "optionator": ["optionator@0.9.4", "", { "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" } }, "sha512-6IpQ7mKUxRcZNLIObR0hz7lxsapSSIYNZJwXPGeF0mTVqGKFIXj1DQcMoT22S3ROcLyY/rz0PWaWZ9ayWmad9g=="], - "oxc-resolver": ["oxc-resolver@9.0.2", "", { "optionalDependencies": { "@oxc-resolver/binding-darwin-arm64": "9.0.2", "@oxc-resolver/binding-darwin-x64": "9.0.2", "@oxc-resolver/binding-freebsd-x64": "9.0.2", "@oxc-resolver/binding-linux-arm-gnueabihf": "9.0.2", "@oxc-resolver/binding-linux-arm64-gnu": "9.0.2", "@oxc-resolver/binding-linux-arm64-musl": "9.0.2", "@oxc-resolver/binding-linux-riscv64-gnu": "9.0.2", "@oxc-resolver/binding-linux-s390x-gnu": "9.0.2", "@oxc-resolver/binding-linux-x64-gnu": "9.0.2", "@oxc-resolver/binding-linux-x64-musl": "9.0.2", "@oxc-resolver/binding-wasm32-wasi": "9.0.2", "@oxc-resolver/binding-win32-arm64-msvc": "9.0.2", "@oxc-resolver/binding-win32-x64-msvc": "9.0.2" } }, "sha512-w838ygc1p7rF+7+h5vR9A+Y9Fc4imy6C3xPthCMkdFUgFvUWkmABeNB8RBDQ6+afk44Q60/UMMQ+gfDUW99fBA=="], - - "oxlint": ["oxlint@0.16.12", "", { "optionalDependencies": { "@oxlint/darwin-arm64": "0.16.12", "@oxlint/darwin-x64": "0.16.12", "@oxlint/linux-arm64-gnu": "0.16.12", "@oxlint/linux-arm64-musl": "0.16.12", "@oxlint/linux-x64-gnu": "0.16.12", "@oxlint/linux-x64-musl": "0.16.12", "@oxlint/win32-arm64": "0.16.12", "@oxlint/win32-x64": "0.16.12" }, "bin": { "oxlint": "bin/oxlint", "oxc_language_server": "bin/oxc_language_server" } }, "sha512-1oN3P9bzE90zkbjLTc+uICVLwSR+eQaDaYVipS0BtmtmEd3ccQue0y7npCinb35YqKzIv1LZxhoU9nm5fgmQuw=="], + "oxlint": ["oxlint@1.3.0", "", { "optionalDependencies": { "@oxlint/darwin-arm64": "1.3.0", "@oxlint/darwin-x64": "1.3.0", "@oxlint/linux-arm64-gnu": "1.3.0", "@oxlint/linux-arm64-musl": "1.3.0", "@oxlint/linux-x64-gnu": "1.3.0", "@oxlint/linux-x64-musl": "1.3.0", "@oxlint/win32-arm64": "1.3.0", "@oxlint/win32-x64": "1.3.0" }, "bin": { "oxlint": "bin/oxlint", "oxc_language_server": "bin/oxc_language_server" } }, "sha512-PzAOmPxnXYpVF1q6h9pkOPH6uJ/44XrtFWJ8JcEMpoEq9HISNelD3lXhACtOAW8CArjLy/qSlu2KkyPxnXgctA=="], "p-limit": ["p-limit@3.1.0", "", { "dependencies": { "yocto-queue": "^0.1.0" } }, "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ=="], @@ -593,7 +581,7 @@ "picomatch": ["picomatch@4.0.2", "", {}, "sha512-M7BAV6Rlcy5u+m6oPhAPFgJTzAioX/6B0DxyvDlo9l8+T3nLKbrczg2WLUyzd45L8RqfUMyGPzekbMvX2Ldkwg=="], - "pkg-types": ["pkg-types@2.1.0", "", { "dependencies": { "confbox": "^0.2.1", "exsolve": "^1.0.1", "pathe": "^2.0.3" } }, "sha512-wmJwA+8ihJixSoHKxZJRBQG1oY8Yr9pGLzRmSsNms0iNWyHHAlZCa7mmKiFR10YPZuz/2k169JiS/inOjBCZ2A=="], + "pkg-types": ["pkg-types@2.3.0", "", { "dependencies": { "confbox": "^0.2.2", "exsolve": "^1.0.7", "pathe": "^2.0.3" } }, "sha512-SIqCzDRg0s9npO5XQ3tNZioRY1uK06lA41ynBC1YmFTmnY6FjUjVt6s4LoADmwoig1qqD0oK8h1p/8mlMx8Oig=="], "pluralize": ["pluralize@8.0.0", "", {}, "sha512-Nc3IT5yHzflTfbjgqWcCPpo7DaKy4FnpB0l/zCAW0Tc7jxAiuqSxHasntB3D7887LSrA93kDJ9IXovxJYxyLCA=="], @@ -607,7 +595,7 @@ "punycode": ["punycode@2.3.1", "", {}, "sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg=="], - "quansync": ["quansync@0.2.10", "", {}, "sha512-t41VRkMYbkHyCYmOvx/6URnN80H7k4X0lLdBMGsz+maAwrJQYB1djpV6vHrQIBE0WBSGqhtEHrK9U3DWWH8v7A=="], + "quansync": ["quansync@0.2.11", "", {}, "sha512-AifT7QEbW9Nri4tAwR5M/uzpBuqfZf+zwaEM/QkzEjj7NBuFD2rBuy0K3dE+8wltbezDV7JMA0WfnCPYRSYbXA=="], "queue-microtask": ["queue-microtask@1.2.3", "", {}, "sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A=="], @@ -623,9 +611,9 @@ "reusify": ["reusify@1.0.4", "", {}, "sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw=="], - "rolldown": ["rolldown@1.0.0-beta.9-commit.51df2b7", "", { "dependencies": { "@oxc-project/types": "0.71.0", "@rolldown/pluginutils": "1.0.0-beta.9-commit.51df2b7", "ansis": "^4.0.0" }, "optionalDependencies": { "@rolldown/binding-darwin-arm64": "1.0.0-beta.9-commit.51df2b7", "@rolldown/binding-darwin-x64": "1.0.0-beta.9-commit.51df2b7", "@rolldown/binding-freebsd-x64": "1.0.0-beta.9-commit.51df2b7", "@rolldown/binding-linux-arm-gnueabihf": "1.0.0-beta.9-commit.51df2b7", "@rolldown/binding-linux-arm64-gnu": "1.0.0-beta.9-commit.51df2b7", "@rolldown/binding-linux-arm64-musl": "1.0.0-beta.9-commit.51df2b7", "@rolldown/binding-linux-x64-gnu": "1.0.0-beta.9-commit.51df2b7", "@rolldown/binding-linux-x64-musl": "1.0.0-beta.9-commit.51df2b7", "@rolldown/binding-wasm32-wasi": "1.0.0-beta.9-commit.51df2b7", "@rolldown/binding-win32-arm64-msvc": "1.0.0-beta.9-commit.51df2b7", "@rolldown/binding-win32-ia32-msvc": "1.0.0-beta.9-commit.51df2b7", "@rolldown/binding-win32-x64-msvc": "1.0.0-beta.9-commit.51df2b7" }, "peerDependencies": { "@oxc-project/runtime": "0.71.0" }, "optionalPeers": ["@oxc-project/runtime"], "bin": { "rolldown": "bin/cli.mjs" } }, "sha512-jsHj8vikf9qezv+Ct2sL1gHgIXVq+3NATCcY24lnJNdHvmc2t9aRjuMp5nUCzZ4aFTpRFJmucSOgqfvruo4/ew=="], + "rolldown": ["rolldown@1.0.0-beta.34", "", { "dependencies": { "@oxc-project/runtime": "=0.82.3", "@oxc-project/types": "=0.82.3", "@rolldown/pluginutils": "1.0.0-beta.34", "ansis": "^4.0.0" }, "optionalDependencies": { "@rolldown/binding-android-arm64": "1.0.0-beta.34", "@rolldown/binding-darwin-arm64": "1.0.0-beta.34", "@rolldown/binding-darwin-x64": "1.0.0-beta.34", "@rolldown/binding-freebsd-x64": "1.0.0-beta.34", "@rolldown/binding-linux-arm-gnueabihf": "1.0.0-beta.34", "@rolldown/binding-linux-arm64-gnu": "1.0.0-beta.34", "@rolldown/binding-linux-arm64-musl": "1.0.0-beta.34", "@rolldown/binding-linux-x64-gnu": "1.0.0-beta.34", "@rolldown/binding-linux-x64-musl": "1.0.0-beta.34", "@rolldown/binding-openharmony-arm64": "1.0.0-beta.34", "@rolldown/binding-wasm32-wasi": "1.0.0-beta.34", "@rolldown/binding-win32-arm64-msvc": "1.0.0-beta.34", "@rolldown/binding-win32-ia32-msvc": "1.0.0-beta.34", "@rolldown/binding-win32-x64-msvc": "1.0.0-beta.34" }, "bin": { "rolldown": "bin/cli.mjs" } }, "sha512-Wwh7EwalMzzX3Yy3VN58VEajeR2Si8+HDNMf706jPLIqU7CxneRW+dQVfznf5O0TWTnJyu4npelwg2bzTXB1Nw=="], - "rolldown-plugin-dts": ["rolldown-plugin-dts@0.13.4", "", { "dependencies": { "@babel/generator": "^7.27.1", "@babel/parser": "^7.27.2", "@babel/types": "^7.27.1", "ast-kit": "^2.0.0", "birpc": "^2.3.0", "debug": "^4.4.1", "dts-resolver": "^2.0.1", "get-tsconfig": "^4.10.1" }, "peerDependencies": { "rolldown": "^1.0.0-beta.9", "typescript": "^5.0.0", "vue-tsc": "~2.2.0" }, "optionalPeers": ["typescript", "vue-tsc"] }, "sha512-2+3GnKj6A3wKfyomUKfONRHjgKE85X4PcgW1b84KkHvuN3mUuUiOMseLKafFLMF6NkqQPAJ3FErwtC4HuwIswg=="], + "rolldown-plugin-dts": ["rolldown-plugin-dts@0.15.10", "", { "dependencies": { "@babel/generator": "^7.28.3", "@babel/parser": "^7.28.3", "@babel/types": "^7.28.2", "ast-kit": "^2.1.2", "birpc": "^2.5.0", "debug": "^4.4.1", "dts-resolver": "^2.1.2", "get-tsconfig": "^4.10.1" }, "peerDependencies": { "@typescript/native-preview": ">=7.0.0-dev.20250601.1", "rolldown": "^1.0.0-beta.9", "typescript": "^5.0.0", "vue-tsc": "~3.0.3" }, "optionalPeers": ["@typescript/native-preview", "typescript", "vue-tsc"] }, "sha512-8cPVAVQUo9tYAoEpc3jFV9RxSil13hrRRg8cHC9gLXxRMNtWPc1LNMSDXzjyD+5Vny49sDZH77JlXp/vlc4I3g=="], "rollup": ["rollup@4.21.2", "", { "dependencies": { "@types/estree": "1.0.5" }, "optionalDependencies": { "@rollup/rollup-android-arm-eabi": "4.21.2", "@rollup/rollup-android-arm64": "4.21.2", "@rollup/rollup-darwin-arm64": "4.21.2", "@rollup/rollup-darwin-x64": "4.21.2", "@rollup/rollup-linux-arm-gnueabihf": "4.21.2", "@rollup/rollup-linux-arm-musleabihf": "4.21.2", "@rollup/rollup-linux-arm64-gnu": "4.21.2", "@rollup/rollup-linux-arm64-musl": "4.21.2", "@rollup/rollup-linux-powerpc64le-gnu": "4.21.2", "@rollup/rollup-linux-riscv64-gnu": "4.21.2", "@rollup/rollup-linux-s390x-gnu": "4.21.2", "@rollup/rollup-linux-x64-gnu": "4.21.2", "@rollup/rollup-linux-x64-musl": "4.21.2", "@rollup/rollup-win32-arm64-msvc": "4.21.2", "@rollup/rollup-win32-ia32-msvc": "4.21.2", "@rollup/rollup-win32-x64-msvc": "4.21.2", "fsevents": "~2.3.2" }, "bin": { "rollup": "dist/bin/rollup" } }, "sha512-e3TapAgYf9xjdLvKQCkQTnbTKd4a6jwlpQSJJFokHGaX2IVjoEqkIIhiQfqsi0cdwlOD+tQGuOd5AJkc5RngBw=="], @@ -657,6 +645,8 @@ "strip-json-comments": ["strip-json-comments@3.1.1", "", {}, "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig=="], + "strip-literal": ["strip-literal@3.0.0", "", { "dependencies": { "js-tokens": "^9.0.1" } }, "sha512-TcccoMhJOM3OebGhSBEmp3UZ2SfDMZUEBdRA/9ynfLi8yYajyWX3JiXArcJt4Umh4vISpspkQIY8ZZoCqjbviA=="], + "supports-color": ["supports-color@7.2.0", "", { "dependencies": { "has-flag": "^4.0.0" } }, "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw=="], "tapable": ["tapable@2.2.1", "", {}, "sha512-GNzQvQTOIP6RyTfE2Qxb8ZVlNmw0n88vp1szwWRimP02mnTsx3Wtn5qRdqY9w2XduFNUgvOwhNnQsjwCp+kqaQ=="], @@ -665,19 +655,21 @@ "tinyexec": ["tinyexec@1.0.1", "", {}, "sha512-5uC6DDlmeqiOwCPmK9jMSdOuZTh8bU39Ys6yidB+UTt5hfZUPGAypSgFRiEp+jbi9qH40BLDvy85jIU88wKSqw=="], - "tinyglobby": ["tinyglobby@0.2.13", "", { "dependencies": { "fdir": "^6.4.4", "picomatch": "^4.0.2" } }, "sha512-mEwzpUgrLySlveBwEVDMKk5B57bhLPYovRfPAXD5gA/98Opn0rCDj3GtLwFvCvH5RK9uPCExUROW5NjDwvqkxw=="], + "tinyglobby": ["tinyglobby@0.2.14", "", { "dependencies": { "fdir": "^6.4.4", "picomatch": "^4.0.2" } }, "sha512-tX5e7OM1HnYr2+a2C/4V0htOcSQcoSTH9KgJnVvNm5zm/cyEWKJ7j7YutsH9CxMdtOkkLFy2AHrMci9IM8IPZQ=="], - "tinypool": ["tinypool@1.0.2", "", {}, "sha512-al6n+QEANGFOMf/dmUMsuS5/r9B06uwlyNjZZql/zv8J7ybHCgoihBNORZCY2mzUuAnomQa2JdhyHKzZxPCrFA=="], + "tinypool": ["tinypool@1.1.1", "", {}, "sha512-Zba82s87IFq9A9XmjiX5uZA/ARWDrB03OHlq+Vw1fSdt0I+4/Kutwy8BP4Y/y/aORMo61FQ0vIb5j44vSo5Pkg=="], "tinyrainbow": ["tinyrainbow@2.0.0", "", {}, "sha512-op4nsTR47R6p0vMUUoYl/a+ljLFVtlfaXkLQmqfLR1qHma1h/ysYk4hEXZ880bf2CYgTskvTa/e196Vd5dDQXw=="], - "tinyspy": ["tinyspy@3.0.2", "", {}, "sha512-n1cw8k1k0x4pgA2+9XrOkFydTerNcJ1zWCO5Nn9scWHTD+5tp8dghT2x1uduQePZTZgd3Tupf+x9BxJjeJi77Q=="], + "tinyspy": ["tinyspy@4.0.3", "", {}, "sha512-t2T/WLB2WRgZ9EpE4jgPJ9w+i66UZfDc8wHh0xrwiRNN+UwH98GIJkTeZqX9rg0i0ptwzqW+uYeIF0T4F8LR7A=="], "to-regex-range": ["to-regex-range@5.0.1", "", { "dependencies": { "is-number": "^7.0.0" } }, "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ=="], + "tree-kill": ["tree-kill@1.2.2", "", { "bin": { "tree-kill": "cli.js" } }, "sha512-L0Orpi8qGpRG//Nd+H90vFB+3iHnue1zSSGmNOOCh1GLJ7rUKVwV2HvijphGQS2UmhUZewS9VgvxYIdgr+fG1A=="], + "ts-api-utils": ["ts-api-utils@2.1.0", "", { "peerDependencies": { "typescript": ">=4.8.4" } }, "sha512-CUgTZL1irw8u29bzrOD/nH85jqyc74D6SshFgujOIA7osm2Rz7dYH77agkx7H4FBNxDq7Cjf+IjaX/8zwFW+ZQ=="], - "tsdown": ["tsdown@0.12.2", "", { "dependencies": { "ansis": "^4.0.0", "cac": "^6.7.14", "chokidar": "^4.0.3", "debug": "^4.4.1", "diff": "^8.0.1", "empathic": "^1.1.0", "hookable": "^5.5.3", "rolldown": "1.0.0-beta.9-commit.51df2b7", "rolldown-plugin-dts": "^0.13.4", "semver": "^7.7.2", "tinyexec": "^1.0.1", "tinyglobby": "^0.2.13", "unconfig": "^7.3.2" }, "peerDependencies": { "publint": "^0.3.0", "typescript": "^5.0.0", "unplugin-lightningcss": "^0.4.0", "unplugin-unused": "^0.5.0" }, "optionalPeers": ["publint", "typescript", "unplugin-lightningcss", "unplugin-unused"], "bin": { "tsdown": "dist/run.js" } }, "sha512-JbBhVW799a1aOt1g8tNw5MGRuYm+xZWBkj9jMOdJJ6zSFT/pAewdQytgtgBemz4Wv3pmRLZNPK9YqUu1IVuIqA=="], + "tsdown": ["tsdown@0.14.2", "", { "dependencies": { "ansis": "^4.1.0", "cac": "^6.7.14", "chokidar": "^4.0.3", "debug": "^4.4.1", "diff": "^8.0.2", "empathic": "^2.0.0", "hookable": "^5.5.3", "rolldown": "latest", "rolldown-plugin-dts": "^0.15.8", "semver": "^7.7.2", "tinyexec": "^1.0.1", "tinyglobby": "^0.2.14", "tree-kill": "^1.2.2", "unconfig": "^7.3.3" }, "peerDependencies": { "@arethetypeswrong/core": "^0.18.1", "publint": "^0.3.0", "typescript": "^5.0.0", "unplugin-lightningcss": "^0.4.0", "unplugin-unused": "^0.5.0" }, "optionalPeers": ["@arethetypeswrong/core", "publint", "typescript", "unplugin-lightningcss", "unplugin-unused"], "bin": { "tsdown": "dist/run.mjs" } }, "sha512-6ThtxVZoTlR5YJov5rYvH8N1+/S/rD/pGfehdCLGznGgbxz+73EASV1tsIIZkLw2n+SXcERqHhcB/OkyxdKv3A=="], "tslib": ["tslib@2.7.0", "", {}, "sha512-gLXCKdN1/j47AiHiOkJN69hJmcbGTHI0ImLmbYLHykhgeN0jVGola9yVjFgzCUklsZQMW55o+dW7IXv3RCXDzA=="], @@ -685,19 +677,17 @@ "type-fest": ["type-fest@4.41.0", "", {}, "sha512-TeTSQ6H5YHvpqVwBRcnLDCBnDOHWYu7IvGbHT6N8AOymcr9PJGjc1GTtiWZTYg0NCgYwvnYWEkVChQAr9bjfwA=="], - "typescript": ["typescript@5.8.3", "", { "bin": { "tsc": "bin/tsc", "tsserver": "bin/tsserver" } }, "sha512-p1diW6TqL9L07nNxvRMM7hMMw4c5XOo/1ibL4aAIGmSAt9slTE1Xgw5KWuof2uTOvCg9BY7ZRi+GaF+7sfgPeQ=="], + "typescript": ["typescript@5.9.2", "", { "bin": { "tsc": "bin/tsc", "tsserver": "bin/tsserver" } }, "sha512-CWBzXQrc/qOkhidw1OzBTQuYRbfyxDXJMVJ1XNwUHGROVmuaeiEm3OslpZ1RV96d7SKKjZKrSJu3+t/xlw3R9A=="], "typescript-eslint": ["typescript-eslint@8.32.1", "", { "dependencies": { "@typescript-eslint/eslint-plugin": "8.32.1", "@typescript-eslint/parser": "8.32.1", "@typescript-eslint/utils": "8.32.1" }, "peerDependencies": { "eslint": "^8.57.0 || ^9.0.0", "typescript": ">=4.8.4 <5.9.0" } }, "sha512-D7el+eaDHAmXvrZBy1zpzSNIRqnCOrkwTgZxTu3MUqRWk8k0q9m9Ho4+vPf7iHtgUfrK/o8IZaEApsxPlHTFCg=="], - "unconfig": ["unconfig@7.3.2", "", { "dependencies": { "@quansync/fs": "^0.1.1", "defu": "^6.1.4", "jiti": "^2.4.2", "quansync": "^0.2.8" } }, "sha512-nqG5NNL2wFVGZ0NA/aCFw0oJ2pxSf1lwg4Z5ill8wd7K4KX/rQbHlwbh+bjctXL5Ly1xtzHenHGOK0b+lG6JVg=="], - - "undici-types": ["undici-types@6.21.0", "", {}, "sha512-iwDZqg0QAGrg9Rav5H4n0M64c3mkR59cJ6wQp+7C4nI0gsmExaedaYLNO44eT4AtBBwjbTiGPMlt2Md0T9H9JQ=="], + "unconfig": ["unconfig@7.3.3", "", { "dependencies": { "@quansync/fs": "^0.1.5", "defu": "^6.1.4", "jiti": "^2.5.1", "quansync": "^0.2.11" } }, "sha512-QCkQoOnJF8L107gxfHL0uavn7WD9b3dpBcFX6HtfQYmjw2YzWxGuFQ0N0J6tE9oguCBJn9KOvfqYDCMPHIZrBA=="], - "unplugin": ["unplugin@2.3.4", "", { "dependencies": { "acorn": "^8.14.1", "picomatch": "^4.0.2", "webpack-virtual-modules": "^0.6.2" } }, "sha512-m4PjxTurwpWfpMomp8AptjD5yj8qEZN5uQjjGM3TAs9MWWD2tXSSNNj6jGR2FoVGod4293ytyV6SwBbertfyJg=="], + "undici-types": ["undici-types@6.19.8", "", {}, "sha512-ve2KP6f/JnbPBFyobGHuerC9g1FYGn/F8n1LWTwNxCEzd6IfqTwUQcNXgEtmmQ6DlRrC1hrSrBnCZPokRrDHjw=="], - "unplugin-lightningcss": ["unplugin-lightningcss@0.3.3", "", { "dependencies": { "lightningcss": "^1.29.3", "magic-string": "^0.30.17", "unplugin": "^2.3.2" } }, "sha512-mMNRCNIcxc/3410w7sJdXcPxn0IGZdEpq42OBDyckdGkhOeWYZCG9RkHs72TFyBsS82a4agFDOFU8VrFKF2ZvA=="], + "unplugin": ["unplugin@2.3.10", "", { "dependencies": { "@jridgewell/remapping": "^2.3.5", "acorn": "^8.15.0", "picomatch": "^4.0.3", "webpack-virtual-modules": "^0.6.2" } }, "sha512-6NCPkv1ClwH+/BGE9QeoTIl09nuiAt0gS28nn1PvYXsGKRwM2TCbFA2QiilmehPDTXIe684k4rZI1yl3A1PCUw=="], - "unplugin-unused": ["unplugin-unused@0.5.0", "", { "dependencies": { "js-tokens": "^9.0.1", "picocolors": "^1.1.1", "pkg-types": "^2.1.0", "unplugin": "^2.3.2" } }, "sha512-czXny3h/P/Tl5ZOnV5tSf6kswAniHjgJF0slpzBPLkq0zGGKDYa1jgWMAdbWJNu7B1YSmBJY4zf3Q/v9w0+/cg=="], + "unplugin-unused": ["unplugin-unused@0.5.2", "", { "dependencies": { "js-tokens": "^9.0.1", "picocolors": "^1.1.1", "pkg-types": "^2.2.0", "unplugin": "^2.3.6" } }, "sha512-fn0DZrp96+NYo4U5UbLp1ZmZpBk/Z1RhjG2LvXfQxxw82dzciBxmx04ZgATxLZDD4HcGhdWlLIm2Gz1SVIBhDQ=="], "update-browserslist-db": ["update-browserslist-db@1.1.3", "", { "dependencies": { "escalade": "^3.2.0", "picocolors": "^1.1.1" }, "peerDependencies": { "browserslist": ">= 4.21.0" }, "bin": { "update-browserslist-db": "cli.js" } }, "sha512-UxhIZQ+QInVdunkDAaiazvvT/+fXL5Osr0JZlJulepYu6Jd7qJtDZjlur0emRlT71EN3ScPoE7gvsuIKKNavKw=="], @@ -709,9 +699,9 @@ "vite": ["vite@5.4.3", "", { "dependencies": { "esbuild": "^0.21.3", "postcss": "^8.4.43", "rollup": "^4.20.0" }, "optionalDependencies": { "fsevents": "~2.3.3" }, "peerDependencies": { "@types/node": "^18.0.0 || >=20.0.0", "less": "*", "lightningcss": "^1.21.0", "sass": "*", "sass-embedded": "*", "stylus": "*", "sugarss": "*", "terser": "^5.4.0" }, "optionalPeers": ["@types/node", "less", "lightningcss", "sass", "sass-embedded", "stylus", "sugarss", "terser"], "bin": { "vite": "bin/vite.js" } }, "sha512-IH+nl64eq9lJjFqU+/yrRnrHPVTlgy42/+IzbOdaFDVlyLgI/wDlf+FCobXLX1cT0X5+7LMyH1mIy2xJdLfo8Q=="], - "vite-node": ["vite-node@3.1.4", "", { "dependencies": { "cac": "^6.7.14", "debug": "^4.4.0", "es-module-lexer": "^1.7.0", "pathe": "^2.0.3", "vite": "^5.0.0 || ^6.0.0" }, "bin": { "vite-node": "vite-node.mjs" } }, "sha512-6enNwYnpyDo4hEgytbmc6mYWHXDHYEn0D1/rw4Q+tnHUGtKTJsn8T1YkX6Q18wI5LCrS8CTYlBaiCqxOy2kvUA=="], + "vite-node": ["vite-node@3.2.4", "", { "dependencies": { "cac": "^6.7.14", "debug": "^4.4.1", "es-module-lexer": "^1.7.0", "pathe": "^2.0.3", "vite": "^5.0.0 || ^6.0.0 || ^7.0.0-0" }, "bin": { "vite-node": "vite-node.mjs" } }, "sha512-EbKSKh+bh1E1IFxeO0pg1n4dvoOTt0UDiXMd/qn++r98+jPO1xtJilvXldeuQ8giIB5IkpjCgMleHMNEsGH6pg=="], - "vitest": ["vitest@3.1.4", "", { "dependencies": { "@vitest/expect": "3.1.4", "@vitest/mocker": "3.1.4", "@vitest/pretty-format": "^3.1.4", "@vitest/runner": "3.1.4", "@vitest/snapshot": "3.1.4", "@vitest/spy": "3.1.4", "@vitest/utils": "3.1.4", "chai": "^5.2.0", "debug": "^4.4.0", "expect-type": "^1.2.1", "magic-string": "^0.30.17", "pathe": "^2.0.3", "std-env": "^3.9.0", "tinybench": "^2.9.0", "tinyexec": "^0.3.2", "tinyglobby": "^0.2.13", "tinypool": "^1.0.2", "tinyrainbow": "^2.0.0", "vite": "^5.0.0 || ^6.0.0", "vite-node": "3.1.4", "why-is-node-running": "^2.3.0" }, "peerDependencies": { "@edge-runtime/vm": "*", "@types/debug": "^4.1.12", "@types/node": "^18.0.0 || ^20.0.0 || >=22.0.0", "@vitest/browser": "3.1.4", "@vitest/ui": "3.1.4", "happy-dom": "*", "jsdom": "*" }, "optionalPeers": ["@edge-runtime/vm", "@types/debug", "@types/node", "@vitest/browser", "@vitest/ui", "happy-dom", "jsdom"], "bin": { "vitest": "vitest.mjs" } }, "sha512-Ta56rT7uWxCSJXlBtKgIlApJnT6e6IGmTYxYcmxjJ4ujuZDI59GUQgVDObXXJujOmPDBYXHK1qmaGtneu6TNIQ=="], + "vitest": ["vitest@3.2.4", "", { "dependencies": { "@types/chai": "^5.2.2", "@vitest/expect": "3.2.4", "@vitest/mocker": "3.2.4", "@vitest/pretty-format": "^3.2.4", "@vitest/runner": "3.2.4", "@vitest/snapshot": "3.2.4", "@vitest/spy": "3.2.4", "@vitest/utils": "3.2.4", "chai": "^5.2.0", "debug": "^4.4.1", "expect-type": "^1.2.1", "magic-string": "^0.30.17", "pathe": "^2.0.3", "picomatch": "^4.0.2", "std-env": "^3.9.0", "tinybench": "^2.9.0", "tinyexec": "^0.3.2", "tinyglobby": "^0.2.14", "tinypool": "^1.1.1", "tinyrainbow": "^2.0.0", "vite": "^5.0.0 || ^6.0.0 || ^7.0.0-0", "vite-node": "3.2.4", "why-is-node-running": "^2.3.0" }, "peerDependencies": { "@edge-runtime/vm": "*", "@types/debug": "^4.1.12", "@types/node": "^18.0.0 || ^20.0.0 || >=22.0.0", "@vitest/browser": "3.2.4", "@vitest/ui": "3.2.4", "happy-dom": "*", "jsdom": "*" }, "optionalPeers": ["@edge-runtime/vm", "@types/debug", "@types/node", "@vitest/browser", "@vitest/ui", "happy-dom", "jsdom"], "bin": { "vitest": "vitest.mjs" } }, "sha512-LUCP5ev3GURDysTWiP47wRRUpLKMOfPh+yKTx3kVIEiu5KOMeqzpnYNsKyOoVrULivR8tLcks4+lga33Whn90A=="], "vue-eslint-parser": ["vue-eslint-parser@9.4.3", "", { "dependencies": { "debug": "^4.3.4", "eslint-scope": "^7.1.1", "eslint-visitor-keys": "^3.3.0", "espree": "^9.3.1", "esquery": "^1.4.0", "lodash": "^4.17.21", "semver": "^7.3.6" }, "peerDependencies": { "eslint": ">=6.0.0" } }, "sha512-2rYRLWlIpaiN8xbPiDyXZXRgLGOtWxERV7ND5fFAv5qo1D2N9Fu9MNajBNc6o13lZ+24DAWCkQCvj4klgmcITg=="], @@ -727,21 +717,23 @@ "yocto-queue": ["yocto-queue@0.1.0", "", {}, "sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q=="], - "@babel/generator/jsesc": ["jsesc@3.0.2", "", { "bin": { "jsesc": "bin/jsesc" } }, "sha512-xKqzzWXDttJuOcawBt4KnKHHIf5oQ/Cxax+0PWFG+DFDgHNAdi+TXECADI+RYiFUMmx8792xsMbbgXj4CwnP4g=="], - "@eslint-community/eslint-utils/eslint-visitor-keys": ["eslint-visitor-keys@3.4.3", "", {}, "sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag=="], "@eslint/eslintrc/globals": ["globals@14.0.0", "", {}, "sha512-oahGvuMGQlPw/ivIYBjVSrWAfWLBeku5tpPE2fOPLi+WHffIWbuh2tCjhyQhTBPMf5E9jDEH4FOmTYgYwbKwtQ=="], "@humanfs/node/@humanwhocodes/retry": ["@humanwhocodes/retry@0.3.0", "", {}, "sha512-d2CGZR2o7fS6sWB7DG/3a95bGKQyHMACZ5aW8qGkkqQpUoZV6C0X7Pc7l4ZNMZkfNBf4VWNe9E1jRsf0G146Ew=="], + "@jridgewell/remapping/@jridgewell/gen-mapping": ["@jridgewell/gen-mapping@0.3.8", "", { "dependencies": { "@jridgewell/set-array": "^1.2.1", "@jridgewell/sourcemap-codec": "^1.4.10", "@jridgewell/trace-mapping": "^0.3.24" } }, "sha512-imAbBGkb+ebQyxKgzv5Hu2nmROxoDOXHh80evxdoXNOrvAnVx7zimzc1Oo5h9RlfV4vPXaE2iM5pOFbvOCClWA=="], + + "@jridgewell/remapping/@jridgewell/trace-mapping": ["@jridgewell/trace-mapping@0.3.25", "", { "dependencies": { "@jridgewell/resolve-uri": "^3.1.0", "@jridgewell/sourcemap-codec": "^1.4.14" } }, "sha512-vNk6aEwybGtawWmy/PzwnGDOjCkLWSD2wqvjGGAgOAwCGWySYXfYoxt00IJkTF+8Lb57DwOb3Aa0o9CApepiYQ=="], + "@typescript-eslint/eslint-plugin/@eslint-community/regexpp": ["@eslint-community/regexpp@4.11.0", "", {}, "sha512-G/M/tIiMrTAxEWRfLfQJMmGNX28IxBg4PBz8XqQhqUHLFI6TL2htpIB1iQCj144V5ee/JaKyT9/WZ0MGZWfA7A=="], "@typescript-eslint/eslint-plugin/ignore": ["ignore@7.0.4", "", {}, "sha512-gJzzk+PQNznz8ysRrC0aOkBNVRBDtE1n53IqyqEf3PXrYwomFs5q4pGMizBMJF+ykh03insJ27hB8gSrD2Hn8A=="], "@typescript-eslint/typescript-estree/minimatch": ["minimatch@9.0.5", "", { "dependencies": { "brace-expansion": "^2.0.1" } }, "sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow=="], - "bun-types/@types/node": ["@types/node@20.16.5", "", { "dependencies": { "undici-types": "~6.19.2" } }, "sha512-VwYCweNo3ERajwy0IUlqqcyZ8/A7Zwa9ZP3MnENWcB11AejO+tLy3pu850goUW2FC/IJMdZUfKpX/yxL1gymCA=="], + "chai/loupe": ["loupe@3.1.3", "", {}, "sha512-kkIp7XSkP78ZxJEsSxW3712C6teJVoeHHwgo9zJ380de7IYyJ2ISlxojcH2pC5OFLewESmnRi/+XCDIEEVyoug=="], "clean-regexp/escape-string-regexp": ["escape-string-regexp@1.0.5", "", {}, "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg=="], @@ -771,6 +763,12 @@ "rollup/@types/estree": ["@types/estree@1.0.5", "", {}, "sha512-/kYRxGDLWzHOB7q+wtSUQlFrtcdUccpfy+X+9iMBpHK8QLLhx2wIPYuS5DYtR9Wa/YlZAbIovy7qVdB1Aq6Lyw=="], + "unconfig/jiti": ["jiti@2.5.1", "", { "bin": { "jiti": "lib/jiti-cli.mjs" } }, "sha512-twQoecYPiVA5K/h6SxtORw/Bs3ar+mLUtoPSc7iMXzQzK8d7eJ/R09wmTwAjiamETn1cXYPGfNnu7DMoHgu12w=="], + + "unplugin/acorn": ["acorn@8.15.0", "", { "bin": { "acorn": "bin/acorn" } }, "sha512-NZyJarBfL7nWwIq+FDL6Zp/yHEhePMNnnJ0y3qfieCrmNvYct8uvtiV41UvlSe6apAfk0fY1FbWx+NwfmpvtTg=="], + + "unplugin/picomatch": ["picomatch@4.0.3", "", {}, "sha512-5gTmgEY/sqK6gFXLIsQNH19lWb4ebPDLA4SdLP7dsWkIXHWlG66oPuVvXSGFPppYZz8ZDZq0dYYrbHfBCVUb1Q=="], + "vitest/tinyexec": ["tinyexec@0.3.2", "", {}, "sha512-KQQR9yN7R5+OSwaK0XQoj22pwHoTlgYqmUscPYoknOoWCWfj/5/ABTMRi69FrKU5ffPVh5QcFikpWJI/P1ocHA=="], "vue-eslint-parser/debug": ["debug@4.3.6", "", { "dependencies": { "ms": "2.1.2" } }, "sha512-O/09Bd4Z1fBrU4VzkhFqVgpPzaGbw6Sm9FEkBT1A/YBXQFGuuSxa1dN2nxgxS34JmKXqYx8CZAwEVoJFImUXIg=="], @@ -785,8 +783,6 @@ "@typescript-eslint/typescript-estree/minimatch/brace-expansion": ["brace-expansion@2.0.1", "", { "dependencies": { "balanced-match": "^1.0.0" } }, "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA=="], - "bun-types/@types/node/undici-types": ["undici-types@6.19.8", "", {}, "sha512-ve2KP6f/JnbPBFyobGHuerC9g1FYGn/F8n1LWTwNxCEzd6IfqTwUQcNXgEtmmQ6DlRrC1hrSrBnCZPokRrDHjw=="], - "eslint-plugin-es-x/@eslint-community/eslint-utils/eslint-visitor-keys": ["eslint-visitor-keys@3.4.3", "", {}, "sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag=="], "eslint-plugin-n/minimatch/brace-expansion": ["brace-expansion@2.0.1", "", { "dependencies": { "balanced-match": "^1.0.0" } }, "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA=="], diff --git a/dist/main.cjs b/dist/main.cjs index fcc9081..7f2bef0 100644 --- a/dist/main.cjs +++ b/dist/main.cjs @@ -271,6 +271,7 @@ var HyperAPI = class { * * If error is thrown in this hook, it will abort the request processing and return an error response. * @param callback The callback function. + * @returns - */ onBeforeRouter(callback) { this.handlers.beforeRouter.push(callback); @@ -283,6 +284,7 @@ var HyperAPI = class { * * If error is thrown in this hook, it will abort the request processing and return an error response. * @param transformer The callback function. + * @returns - */ setRequestTransformer(transformer) { if (this.handlers.requestTransformer) throw new Error("Transformer has already been set."); @@ -296,6 +298,7 @@ var HyperAPI = class { * * If error is thrown in this hook, it will abort the request processing and return an error response. * @param callback - + * @returns - */ onBeforeExecute(callback) { this.handlers.beforeExecute.push(callback); @@ -308,6 +311,7 @@ var HyperAPI = class { * * If error is thrown in this hook, it will be printed to the console, but will not prevent response from being sent to the driver. * @param callback - + * @returns - */ onResponse(callback) { this.handlers.response.push(callback); diff --git a/dist/main.d.cts b/dist/main.d.cts new file mode 100644 index 0000000..778e25a --- /dev/null +++ b/dist/main.d.cts @@ -0,0 +1,216 @@ +import { EmptyObject, Promisable } from "type-fest"; + +//#region src/utils/methods.d.ts +type HyperAPIMethod = "DELETE" | "GET" | "HEAD" | "OPTIONS" | "PATCH" | "POST" | "PUT" | "UNKNOWN"; +/** +* Checks if the given value is a valid HyperAPI method. +* @param method The HTTP method to check. +* @returns - +*/ +declare function isHyperApiMethod(method: unknown): method is HyperAPIMethod; +//#endregion +//#region src/request.d.ts +type HyperAPIRequestArgs = Record; +interface HyperAPIRequest { + method: HyperAPIMethod; + path: string; + args: A; +} +//#endregion +//#region src/error.d.ts +type HyperAPIErrorData = Record | undefined; +interface HyperAPIErrorResponse { + code: number; + description?: string; + data?: HyperAPIErrorData; +} +declare class HyperAPIError extends Error { + /** The error code. */ + readonly code: number; + /** The error description. */ + readonly description: string; + /** The error data. */ + readonly data?: D; + /** HTTP status code. */ + readonly httpStatus?: number; + /** HTTP headers to return. */ + readonly httpHeaders?: Record; + constructor(data?: D); + get message(): string; + /** + * Creates response object. + * @returns - + */ + getResponse(): HyperAPIErrorResponse; +} +//#endregion +//#region src/module.d.ts +type HyperAPIModuleResponse = Record | Response | unknown[] | undefined; +interface HyperAPIModule> { + readonly default: (request: R) => Promisable; + readonly argsValidator: (args: unknown) => R extends HyperAPIRequest ? A : never; +} +type InferModule> = H extends HyperAPI ? M : never; +//#endregion +//#region src/response.d.ts +type HyperAPIResponse = HyperAPIModuleResponse | HyperAPIError; +//#endregion +//#region src/driver.d.ts +type HyperAPIDriverHandler = (request: R) => Promisable; +interface HyperAPIDriver { + start(handler: HyperAPIDriverHandler): void; + stop(): void; +} +type InferDriverRequest = D extends HyperAPIDriver ? R : never; +//#endregion +//#region src/api-errors.d.ts +declare class HyperAPIAuthorizationError extends HyperAPIError { + code: number; + description: string; + httpStatus: number; +} +declare class HyperAPIInvalidParametersError extends HyperAPIError { + code: number; + description: string; + httpStatus: number; +} +declare class HyperAPIInternalError extends HyperAPIError { + code: number; + description: string; + httpStatus: number; +} +declare class HyperAPIForbiddenError extends HyperAPIError { + code: number; + description: string; + httpStatus: number; +} +declare class HyperAPIUnknownMethodError extends HyperAPIError { + code: number; + description: string; + httpStatus: number; +} +declare class HyperAPIObjectsLimitError extends HyperAPIError { + code: number; + description: string; + httpStatus: number; +} +declare class HyperAPIRateLimitError extends HyperAPIError { + code: number; + description: string; + httpStatus: number; +} +declare class HyperAPICaptchaError extends HyperAPIError { + code: number; + description: string; + httpStatus: number; +} +declare class HyperAPIBusyError extends HyperAPIError { + code: number; + description: string; + httpStatus: number; +} +declare class HyperAPIConfirmationError extends HyperAPIError { + code: number; + description: string; + httpStatus: number; +} +declare class HyperAPIOTPError extends HyperAPIError { + code: number; + description: string; + httpStatus: number; +} +declare class HyperAPIMaintenanceError extends HyperAPIError { + code: number; + description: string; + httpStatus: number; +} +declare class HyperAPIMethodNotAllowedError extends HyperAPIError { + code: number; + description: string; + httpStatus: number; +} +//#endregion +//#region src/main.d.ts +interface HyperAPIHandlers, M extends HyperAPIModule> { + beforeRouter: ((ctx: { + driver_request: Readonly>; + }) => Promisable)[]; + requestTransformer: ((ctx: { + driver_request: Readonly>; + module: M; + }) => Promisable) | void; + beforeExecute: ((ctx: { + request: Readonly; + module: M; + }) => Promisable)[]; + response: ((ctx: { + driver_request: Readonly>; + request: R | null; + module: M | null; + response: HyperAPIResponse; + }) => Promisable)[]; +} +declare class HyperAPI, R extends InferDriverRequest, M extends HyperAPIModule = HyperAPIModule> { + private router; + private driver; + /** + * Creates a HyperAPI instance. + * @param options The options. + * @param options.driver The driver. + * @param [options.root] The root directory for API methods modules. Default: `hyper-api` directory alongside the entrypoint script. + */ + constructor({ + driver, + root + }: { + driver: D; + root?: string; + }); + private handlers; + /** + * Adds a hook to be called before request is matched against the file router. + * + * This hook can be set multiple times. Every hook is executed simultaneously. + * + * If error is thrown in this hook, it will abort the request processing and return an error response. + * @param callback The callback function. + * @returns - + */ + onBeforeRouter(callback: HyperAPIHandlers["beforeRouter"][number]): this; + /** + * Use this hook add properties to the request before it is send to the API module. + * + * This hook can be set only once. + * + * If error is thrown in this hook, it will abort the request processing and return an error response. + * @param transformer The callback function. + * @returns - + */ + setRequestTransformer(transformer: HyperAPIHandlers["requestTransformer"]): this; + /** + * Adds a hook to be called right before the API module is executed. + * + * This hook can be set multiple times. Every hook is executed simultaneously. + * + * If error is thrown in this hook, it will abort the request processing and return an error response. + * @param callback - + * @returns - + */ + onBeforeExecute(callback: HyperAPIHandlers["beforeExecute"][number]): this; + /** + * Adds a hook to be called right before the response is sent back to the driver. + * + * This hook can be set multiple times. Every hook is executed simultaneously. + * + * If error is thrown in this hook, it will be printed to the console, but will not prevent response from being sent to the driver. + * @param callback - + * @returns - + */ + onResponse(callback: HyperAPIHandlers["response"][number]): this; + private useHooks; + private processRequest; + /** Destroys the HyperAPI instance. */ + destroy(): void; +} +//#endregion +export { HyperAPI, HyperAPIAuthorizationError, HyperAPIBusyError, HyperAPICaptchaError, HyperAPIConfirmationError, type HyperAPIDriver, type HyperAPIDriverHandler, HyperAPIError, type HyperAPIErrorData, HyperAPIForbiddenError, HyperAPIInternalError, HyperAPIInvalidParametersError, HyperAPIMaintenanceError, type HyperAPIMethod, HyperAPIMethodNotAllowedError, type HyperAPIModule, type HyperAPIModuleResponse, HyperAPIOTPError, HyperAPIObjectsLimitError, HyperAPIRateLimitError, type HyperAPIRequest, type HyperAPIRequestArgs, type HyperAPIResponse, HyperAPIUnknownMethodError, type InferModule, isHyperApiMethod }; \ No newline at end of file diff --git a/dist/main.d.ts b/dist/main.d.ts index 24afa31..778e25a 100644 --- a/dist/main.d.ts +++ b/dist/main.d.ts @@ -8,7 +8,6 @@ type HyperAPIMethod = "DELETE" | "GET" | "HEAD" | "OPTIONS" | "PATCH" | "POST" | * @returns - */ declare function isHyperApiMethod(method: unknown): method is HyperAPIMethod; - //#endregion //#region src/request.d.ts type HyperAPIRequestArgs = Record; @@ -17,7 +16,6 @@ interface HyperAPIRequest { path: string; args: A; } - //#endregion //#region src/error.d.ts type HyperAPIErrorData = Record | undefined; @@ -45,7 +43,6 @@ declare class HyperAPIError extends Err */ getResponse(): HyperAPIErrorResponse; } - //#endregion //#region src/module.d.ts type HyperAPIModuleResponse = Record | Response | unknown[] | undefined; @@ -53,15 +50,10 @@ interface HyperAPIModule> { readonly default: (request: R) => Promisable; readonly argsValidator: (args: unknown) => R extends HyperAPIRequest ? A : never; } -// export type HyperAPIModuleRequest> = Parameters[0]; -// eslint-disable-next-line @typescript-eslint/no-explicit-any type InferModule> = H extends HyperAPI ? M : never; - //#endregion //#region src/response.d.ts -// eslint-disable-next-line @typescript-eslint/no-explicit-any type HyperAPIResponse = HyperAPIModuleResponse | HyperAPIError; - //#endregion //#region src/driver.d.ts type HyperAPIDriverHandler = (request: R) => Promisable; @@ -70,7 +62,6 @@ interface HyperAPIDriver { stop(): void; } type InferDriverRequest = D extends HyperAPIDriver ? R : never; - //#endregion //#region src/api-errors.d.ts declare class HyperAPIAuthorizationError extends HyperAPIError { @@ -138,7 +129,6 @@ declare class HyperAPIMethodNotAllowedError extends description: string; httpStatus: number; } - //#endregion //#region src/main.d.ts interface HyperAPIHandlers, M extends HyperAPIModule> { @@ -184,6 +174,7 @@ declare class HyperAPI, R extends Infe * * If error is thrown in this hook, it will abort the request processing and return an error response. * @param callback The callback function. + * @returns - */ onBeforeRouter(callback: HyperAPIHandlers["beforeRouter"][number]): this; /** @@ -193,6 +184,7 @@ declare class HyperAPI, R extends Infe * * If error is thrown in this hook, it will abort the request processing and return an error response. * @param transformer The callback function. + * @returns - */ setRequestTransformer(transformer: HyperAPIHandlers["requestTransformer"]): this; /** @@ -202,6 +194,7 @@ declare class HyperAPI, R extends Infe * * If error is thrown in this hook, it will abort the request processing and return an error response. * @param callback - + * @returns - */ onBeforeExecute(callback: HyperAPIHandlers["beforeExecute"][number]): this; /** @@ -211,14 +204,13 @@ declare class HyperAPI, R extends Infe * * If error is thrown in this hook, it will be printed to the console, but will not prevent response from being sent to the driver. * @param callback - + * @returns - */ onResponse(callback: HyperAPIHandlers["response"][number]): this; - // eslint-disable-next-line class-methods-use-this, @typescript-eslint/no-explicit-any private useHooks; private processRequest; /** Destroys the HyperAPI instance. */ destroy(): void; } - //#endregion -export { HyperAPI, HyperAPIAuthorizationError, HyperAPIBusyError, HyperAPICaptchaError, HyperAPIConfirmationError, HyperAPIDriver, HyperAPIDriverHandler, HyperAPIError, HyperAPIErrorData, HyperAPIForbiddenError, HyperAPIInternalError, HyperAPIInvalidParametersError, HyperAPIMaintenanceError, HyperAPIMethod, HyperAPIMethodNotAllowedError, HyperAPIModule, HyperAPIModuleResponse, HyperAPIOTPError, HyperAPIObjectsLimitError, HyperAPIRateLimitError, HyperAPIRequest, HyperAPIRequestArgs, HyperAPIResponse, HyperAPIUnknownMethodError, InferModule, isHyperApiMethod }; \ No newline at end of file +export { HyperAPI, HyperAPIAuthorizationError, HyperAPIBusyError, HyperAPICaptchaError, HyperAPIConfirmationError, type HyperAPIDriver, type HyperAPIDriverHandler, HyperAPIError, type HyperAPIErrorData, HyperAPIForbiddenError, HyperAPIInternalError, HyperAPIInvalidParametersError, HyperAPIMaintenanceError, type HyperAPIMethod, HyperAPIMethodNotAllowedError, type HyperAPIModule, type HyperAPIModuleResponse, HyperAPIOTPError, HyperAPIObjectsLimitError, HyperAPIRateLimitError, type HyperAPIRequest, type HyperAPIRequestArgs, type HyperAPIResponse, HyperAPIUnknownMethodError, type InferModule, isHyperApiMethod }; \ No newline at end of file diff --git a/dist/main.js b/dist/main.js index cebd5c9..61d9d59 100644 --- a/dist/main.js +++ b/dist/main.js @@ -248,6 +248,7 @@ var HyperAPI = class { * * If error is thrown in this hook, it will abort the request processing and return an error response. * @param callback The callback function. + * @returns - */ onBeforeRouter(callback) { this.handlers.beforeRouter.push(callback); @@ -260,6 +261,7 @@ var HyperAPI = class { * * If error is thrown in this hook, it will abort the request processing and return an error response. * @param transformer The callback function. + * @returns - */ setRequestTransformer(transformer) { if (this.handlers.requestTransformer) throw new Error("Transformer has already been set."); @@ -273,6 +275,7 @@ var HyperAPI = class { * * If error is thrown in this hook, it will abort the request processing and return an error response. * @param callback - + * @returns - */ onBeforeExecute(callback) { this.handlers.beforeExecute.push(callback); @@ -285,6 +288,7 @@ var HyperAPI = class { * * If error is thrown in this hook, it will be printed to the console, but will not prevent response from being sent to the driver. * @param callback - + * @returns - */ onResponse(callback) { this.handlers.response.push(callback); diff --git a/package.json b/package.json index c3e372b..e83ac89 100644 --- a/package.json +++ b/package.json @@ -7,9 +7,12 @@ }, "type": "module", "main": "dist/main.js", - "types": "dist/main.d.ts", "exports": { ".": { + "types": { + "import": "./dist/main.d.ts", + "require": "./dist/main.d.cts" + }, "import": "./dist/main.js", "require": "./dist/main.cjs" } @@ -18,26 +21,26 @@ "node": ">=21" }, "dependencies": { - "itty-router": "^5.0.18" + "itty-router": "5.0.22" }, "devDependencies": { - "@biomejs/biome": "1.9.4", - "@kirick/lint": "0.1.0", - "@types/bun": "^1.2.13", + "@biomejs/biome": "2.1.1", + "@kirick/lint": "0.2.7", + "@types/bun": "1.2.21", "eslint": "9.27.0", - "oxlint": "0.16.12", + "oxlint": "1.3.0", "publint": "0.3.12", - "tsdown": "0.12.2", - "type-fest": "^4.41.0", - "typescript": "5.8.3", - "unplugin-unused": "0.5.0", + "tsdown": "0.14.2", + "type-fest": "4.41.0", + "typescript": "5.9.2", + "unplugin-unused": "0.5.2", "valibot": "1.1.0", - "vitest": "3.1.4" + "vitest": "3.2.4" }, "scripts": { - "build": "tsdown src/main.ts --publint --unused --dts --format esm --format cjs && rm dist/main.d.cts", + "build": "tsdown src/main.ts --publint --unused --dts --format esm --format cjs", "check": "bun run lint && bun run build && bun run test", - "lint": "biome check && oxlint && eslint . && tsc && (cd test && tsc)", + "lint": "biome format && oxlint && eslint . && tsc && (cd test && tsc)", "test": "npm run test:vitest && bun test --coverage", "test:vitest": "vitest run --no-file-parallelism" }, @@ -45,7 +48,10 @@ "type": "git", "url": "git+https://github.com/hyperapi/core.git" }, - "keywords": ["hyperapi", "api"], + "keywords": [ + "hyperapi", + "api" + ], "author": "Daniil Kirichenko (https://twitter.com/kirickme)", "license": "MIT", "bugs": { diff --git a/src/main.test.ts b/src/main.test.ts index 43c7b08..84d7d31 100644 --- a/src/main.test.ts +++ b/src/main.test.ts @@ -59,6 +59,21 @@ describe('routing', () => { }); }); + test('slug', async () => { + const result = await driver.trigger('GET', 'echo-deadbeef'); + + expect(result).toStrictEqual([ + true, + { + method: { + expected: 'ALL', + received: 'GET', + }, + message: 'Hello, deadbeef!', + }, + ]); + }); + // test('method in directory', async () => { // const result = await request( // 'dir/nested', diff --git a/src/main.ts b/src/main.ts index 8f67517..302d799 100644 --- a/src/main.ts +++ b/src/main.ts @@ -79,10 +79,10 @@ export class HyperAPI< response, }); } catch (error) { - /* eslint-disable no-console */ + // oxlint-disable-next-line no-console console.error('Error in "response" hook:'); + // oxlint-disable-next-line no-console console.error(error); - /* eslint-enable no-console */ } // 11. Finally, *Core* passes the response back to the *Driver*... @@ -104,6 +104,7 @@ export class HyperAPI< * * If error is thrown in this hook, it will abort the request processing and return an error response. * @param callback The callback function. + * @returns - */ onBeforeRouter( callback: HyperAPIHandlers['beforeRouter'][number], @@ -119,6 +120,7 @@ export class HyperAPI< * * If error is thrown in this hook, it will abort the request processing and return an error response. * @param transformer The callback function. + * @returns - */ setRequestTransformer( transformer: HyperAPIHandlers['requestTransformer'], @@ -138,6 +140,7 @@ export class HyperAPI< * * If error is thrown in this hook, it will abort the request processing and return an error response. * @param callback - + * @returns - */ onBeforeExecute( callback: HyperAPIHandlers['beforeExecute'][number], @@ -153,6 +156,7 @@ export class HyperAPI< * * If error is thrown in this hook, it will be printed to the console, but will not prevent response from being sent to the driver. * @param callback - + * @returns - */ onResponse(callback: HyperAPIHandlers['response'][number]): this { this.handlers.response.push(callback); @@ -213,7 +217,7 @@ export class HyperAPI< try { driver_request.args = module_.argsValidator(driver_request.args); } catch (error) { - // eslint-disable-next-line no-console + // oxlint-disable-next-line no-console console.error(error); throw new HyperAPIInvalidParametersError(); @@ -243,7 +247,7 @@ export class HyperAPI< return [request, module_, error]; } - // eslint-disable-next-line no-console + // oxlint-disable-next-line no-console console.error(error); return [request, module_, new HyperAPIInternalError()]; @@ -265,8 +269,8 @@ export type { HyperAPIDriverHandler, } from './driver.js'; export { - type HyperAPIErrorData, HyperAPIError, + type HyperAPIErrorData, } from './error.js'; export type { HyperAPIModule, diff --git a/src/router.ts b/src/router.ts index 6683ed2..e439d5a 100644 --- a/src/router.ts +++ b/src/router.ts @@ -1,5 +1,3 @@ -/* eslint-disable n/no-sync */ - import { readdirSync } from 'node:fs'; import nodePath from 'node:path'; import { type IRequest, IttyRouter, type IttyRouterType } from 'itty-router'; diff --git a/test/hyper-api/echo-[name].ts b/test/hyper-api/echo-[name].ts new file mode 100644 index 0000000..0ea2788 --- /dev/null +++ b/test/hyper-api/echo-[name].ts @@ -0,0 +1,24 @@ +/* eslint-disable unicorn/filename-case */ +/* eslint-disable jsdoc/require-jsdoc */ + +import * as v from 'valibot'; +import type { HyperAPIResponse } from '../../src/main.js'; +import type { LocalRequest } from '../setup.js'; + +export default function ( + request: LocalRequest>, +): HyperAPIResponse { + return { + method: { + expected: 'ALL', + received: request.method, + }, + message: `Hello, ${request.args.name}!`, + }; +} + +export const argsValidator = v.parser( + v.strictObject({ + name: v.string(), + }), +); diff --git a/test/setup.ts b/test/setup.ts index 82b4dc4..662d3e8 100644 --- a/test/setup.ts +++ b/test/setup.ts @@ -97,7 +97,7 @@ export const hyperApi = new HyperAPI< root: new URL('../test/hyper-api', import.meta.url).pathname, }); -/* eslint-disable @typescript-eslint/no-unused-vars */ +/* oxlint-disable no-unused-vars */ hyperApi.onBeforeRouter((ctx) => { const { @@ -134,6 +134,7 @@ hyperApi.onResponse((ctx) => { } = ctx.driver_request; if (ctx.request) { + // eslint-disable-next-line no-shadow const { foo, bar } = ctx.request; } @@ -141,7 +142,8 @@ hyperApi.onResponse((ctx) => { const { default: default_, argsValidator, auth } = ctx.module; } + // oxlint-disable-next-line no-console console.log(ctx.response); }); -/* eslint-enable @typescript-eslint/no-unused-vars */ +/* oxlint-enable no-unused-vars */ From 3d1898caa28e0cbc55c978f33bd9edf5a836337a Mon Sep 17 00:00:00 2001 From: Daniil Kirichenko Date: Tue, 9 Sep 2025 15:32:56 +0200 Subject: [PATCH 43/57] Fix router - router now accepts `[post].ts`-like files, where filename contains only slug --- dist/main.cjs | 2 +- dist/main.js | 2 +- src/main.test.ts | 43 +++++++++++++++++++++++++---------- src/router.ts | 8 +++---- test/hyper-api/user/[post].ts | 23 +++++++++++++++++++ 5 files changed, 59 insertions(+), 19 deletions(-) create mode 100644 test/hyper-api/user/[post].ts diff --git a/dist/main.cjs b/dist/main.cjs index 7f2bef0..54e01b0 100644 --- a/dist/main.cjs +++ b/dist/main.cjs @@ -162,7 +162,7 @@ function useRouter(router, method, path) { } const REGEXP_FILE_EXTENSION = /\.(js|mjs|cjs|ts)$/; const REGEXP_TEST_FILE_EXTENSION = /\.test\.(js|mjs|cjs|ts)$/; -const REGEXP_HTTP_METHOD = /\.\[(delete|get|head|options|patch|post|put)]$/; +const REGEXP_HTTP_METHOD = /(?:^|\.)\[(delete|get|head|options|patch|post|put)]$/; const REGEXP_PATH_SLUG = /\[(\w+)]/g; /** * Scans directory for routes. diff --git a/dist/main.js b/dist/main.js index 61d9d59..cc829e8 100644 --- a/dist/main.js +++ b/dist/main.js @@ -139,7 +139,7 @@ function useRouter(router, method, path) { } const REGEXP_FILE_EXTENSION = /\.(js|mjs|cjs|ts)$/; const REGEXP_TEST_FILE_EXTENSION = /\.test\.(js|mjs|cjs|ts)$/; -const REGEXP_HTTP_METHOD = /\.\[(delete|get|head|options|patch|post|put)]$/; +const REGEXP_HTTP_METHOD = /(?:^|\.)\[(delete|get|head|options|patch|post|put)]$/; const REGEXP_PATH_SLUG = /\[(\w+)]/g; /** * Scans directory for routes. diff --git a/src/main.test.ts b/src/main.test.ts index 84d7d31..0171cfb 100644 --- a/src/main.test.ts +++ b/src/main.test.ts @@ -59,19 +59,38 @@ describe('routing', () => { }); }); - test('slug', async () => { - const result = await driver.trigger('GET', 'echo-deadbeef'); - - expect(result).toStrictEqual([ - true, - { - method: { - expected: 'ALL', - received: 'GET', + describe('slug', () => { + test('in the file name', async () => { + const result = await driver.trigger('GET', 'echo-deadbeef'); + + expect(result).toStrictEqual([ + true, + { + method: { + expected: 'ALL', + received: 'GET', + }, + message: 'Hello, deadbeef!', + }, + ]); + }); + + test('in the directory name', async () => { + const result = await driver.trigger('POST', 'user', { + name: 'bax', + }); + + expect(result).toStrictEqual([ + true, + { + method: { + expected: 'POST', + received: 'POST', + }, + message: 'Hello, bax!', }, - message: 'Hello, deadbeef!', - }, - ]); + ]); + }); }); // test('method in directory', async () => { diff --git a/src/router.ts b/src/router.ts index e439d5a..27cda7b 100644 --- a/src/router.ts +++ b/src/router.ts @@ -45,7 +45,8 @@ export function useRouter( const REGEXP_FILE_EXTENSION = /\.(js|mjs|cjs|ts)$/; const REGEXP_TEST_FILE_EXTENSION = /\.test\.(js|mjs|cjs|ts)$/; -const REGEXP_HTTP_METHOD = /\.\[(delete|get|head|options|patch|post|put)]$/; +const REGEXP_HTTP_METHOD = + /(?:^|\.)\[(delete|get|head|options|patch|post|put)]$/; const REGEXP_PATH_SLUG = /\[(\w+)]/g; interface Route { @@ -102,10 +103,7 @@ function scanDirectory( // console.log( // entry_path, // method, - // [ - // ...regexp_parts, - // file_name, - // ].join(nodePath.sep), + // [...regexp_parts, file_name].join(nodePath.sep), // ); // eslint-disable-next-line no-bitwise diff --git a/test/hyper-api/user/[post].ts b/test/hyper-api/user/[post].ts new file mode 100644 index 0000000..2e2eb0b --- /dev/null +++ b/test/hyper-api/user/[post].ts @@ -0,0 +1,23 @@ +/* eslint-disable jsdoc/require-jsdoc */ + +import * as v from 'valibot'; +import type { HyperAPIResponse } from '../../../src/main.js'; +import type { LocalRequest } from '../../setup.js'; + +export default function ( + request: LocalRequest>, +): HyperAPIResponse { + return { + method: { + expected: 'POST', + received: request.method, + }, + message: `Hello, ${request.args.name}!`, + }; +} + +export const argsValidator = v.parser( + v.strictObject({ + name: v.string(), + }), +); From 7627893c85005bc059cabeaa43e1604bc4a9458e Mon Sep 17 00:00:00 2001 From: Daniil Kirichenko Date: Sat, 13 Sep 2025 22:44:57 +0200 Subject: [PATCH 44/57] [v0.5.0-dev] Huge rework - new module syntax - stronger types - more tests - support for optional/catch-all routes --- README.md | 289 +++++----- bun.lock | 3 + dist/main.cjs | 502 +++++++++++------- dist/main.d.cts | 144 ++--- dist/main.d.ts | 144 ++--- dist/main.js | 502 +++++++++++------- package.json | 5 +- src/api-errors.ts | 8 + src/driver.ts | 22 +- src/error.test.ts | 8 + src/error.ts | 2 +- src/main.test.ts | 357 ++++++------- src/main.ts | 314 ++++------- src/module.ts | 92 +++- src/request.ts | 4 +- src/response.ts | 20 +- src/router.ts | 171 +++--- src/router/file-tree.ts | 171 ++++++ src/router/filename.ts | 106 ++++ src/utils/is-record.ts | 14 - src/utils/record.test.ts | 24 + src/utils/record.ts | 33 ++ src/utils/types.ts | 26 + test/driver.ts | 43 ++ test/errors.test.ts | 22 + test/hyper-api/echo-[name].ts | 24 - test/hyper-api/echo.[post].ts | 31 -- test/hyper-api/echo.ts | 23 - test/hyper-api/errors/api.test.ts | 33 -- test/hyper-api/errors/api.ts | 25 +- test/hyper-api/errors/internal.test.ts | 14 - test/hyper-api/errors/internal.ts | 8 +- test/hyper-api/module/async.ts | 7 + test/hyper-api/module/main.ts | 7 + test/hyper-api/module/set.ts | 10 + test/hyper-api/module/set/async.ts | 13 + test/hyper-api/module/set/error.ts | 13 + test/hyper-api/module/set/multiple.ts | 11 + test/hyper-api/module/set/override.ts | 11 + test/hyper-api/module/use.ts | 12 + test/hyper-api/module/use/async.ts | 15 + test/hyper-api/module/use/error.ts | 13 + test/hyper-api/module/use/multiple.ts | 16 + test/hyper-api/module/use/override.ts | 15 + test/hyper-api/module/void.ts | 5 + test/hyper-api/only-get.[get].ts | 9 - test/hyper-api/only-get.test.ts | 34 -- test/hyper-api/router/all.ts | 9 + test/hyper-api/router/catch/[...slug].ts | 9 + test/hyper-api/router/index.get.ts | 9 + .../router/optional-catch/[[...slug]].ts | 9 + .../router/optional-slug/[name].[[ext]].ts | 9 + test/hyper-api/router/slug/[slug].ts | 9 + test/hyper-api/router/slug/[slug]/x.ts | 9 + test/hyper-api/router/slug/x-[slug]-x.ts | 11 + test/hyper-api/router/slug/x-[slug].ts | 11 + test/hyper-api/router/x.get.ts | 9 + test/hyper-api/user/[post].ts | 23 - test/module.test.ts | 90 ++++ test/router.test.ts | 248 +++++++++ test/server.ts | 8 + test/setup.ts | 149 ------ 62 files changed, 2376 insertions(+), 1611 deletions(-) create mode 100644 src/router/file-tree.ts create mode 100644 src/router/filename.ts delete mode 100644 src/utils/is-record.ts create mode 100644 src/utils/record.test.ts create mode 100644 src/utils/record.ts create mode 100644 src/utils/types.ts create mode 100644 test/driver.ts create mode 100644 test/errors.test.ts delete mode 100644 test/hyper-api/echo-[name].ts delete mode 100644 test/hyper-api/echo.[post].ts delete mode 100644 test/hyper-api/echo.ts delete mode 100644 test/hyper-api/errors/api.test.ts delete mode 100644 test/hyper-api/errors/internal.test.ts create mode 100644 test/hyper-api/module/async.ts create mode 100644 test/hyper-api/module/main.ts create mode 100644 test/hyper-api/module/set.ts create mode 100644 test/hyper-api/module/set/async.ts create mode 100644 test/hyper-api/module/set/error.ts create mode 100644 test/hyper-api/module/set/multiple.ts create mode 100644 test/hyper-api/module/set/override.ts create mode 100644 test/hyper-api/module/use.ts create mode 100644 test/hyper-api/module/use/async.ts create mode 100644 test/hyper-api/module/use/error.ts create mode 100644 test/hyper-api/module/use/multiple.ts create mode 100644 test/hyper-api/module/use/override.ts create mode 100644 test/hyper-api/module/void.ts delete mode 100644 test/hyper-api/only-get.[get].ts delete mode 100644 test/hyper-api/only-get.test.ts create mode 100644 test/hyper-api/router/all.ts create mode 100644 test/hyper-api/router/catch/[...slug].ts create mode 100644 test/hyper-api/router/index.get.ts create mode 100644 test/hyper-api/router/optional-catch/[[...slug]].ts create mode 100644 test/hyper-api/router/optional-slug/[name].[[ext]].ts create mode 100644 test/hyper-api/router/slug/[slug].ts create mode 100644 test/hyper-api/router/slug/[slug]/x.ts create mode 100644 test/hyper-api/router/slug/x-[slug]-x.ts create mode 100644 test/hyper-api/router/slug/x-[slug].ts create mode 100644 test/hyper-api/router/x.get.ts delete mode 100644 test/hyper-api/user/[post].ts create mode 100644 test/module.test.ts create mode 100644 test/router.test.ts create mode 100644 test/server.ts delete mode 100644 test/setup.ts diff --git a/README.md b/README.md index 66ef31f..b0bd87e 100644 --- a/README.md +++ b/README.md @@ -10,7 +10,6 @@ A powerful, type-safe foundation framework for building APIs with minimal boiler - 🔒 **Type-safe API development** - Get full TypeScript support and inference - 🧩 **File-based routing** - Automatically generate API endpoints from your file structure - 🚀 **Driver-based architecture** - Easily adapt to different environments (HTTP, WebSockets, etc.) -- 🔍 **Input validation** - Built-in support for request validation - 🪝 **Middleware hooks** - Extensible system for authentication, logging, and more ## Installation @@ -35,57 +34,93 @@ Create a directory to hold your API methods (default: `hyper-api` in your projec ``` my-project/ ├── hyper-api/ -│ ├── users.[get].ts -│ ├── users.[post].ts +│ ├── users.get.ts +│ ├── users.post.ts │ └── products/ -│ ├── [id].[get].ts -│ └── search.[get].ts +│ ├── [id].get.ts +│ └── search.get.ts ├── index.ts └── package.json ``` HyperAPI uses file names to determine routes and HTTP methods: -- `users.ts` → `GET /users` -- `users.[post].ts` → `POST /users` -- `users/[id].ts` → `GET /users/:id` -- `users/[id].[delete].ts` → `DELETE /users/:id` +#### Static Routes -### 2. Create your API handlers +File name will require an exact match. For example: -Example of a basic endpoint (`hyper-api/hello.[get].ts`): +| File name | Route pattern | Matched requests | +| - | - | - | +| `/users.ts` | `/users` | `GET /users` | -```typescript -import type { HyperAPIRequest, HyperAPIResponse } from '@hyperapi/core'; -import * as v from 'valibot'; +#### Index Routes -// Define your handler function -export default function(request: HyperAPIRequest>): HyperAPIResponse { - return { - message: `Hello, ${request.args.name}!`, - timestamp: new Date().toISOString() - }; -} +Files named as `index.ts` do not add `index` to the route. -// Define input validation -export const argsValidator = v.parser( - v.strictObject({ - name: v.string('Name is required'), - }) -); -``` +| File name | Route pattern | Matched requests | +| - | - | - | +| `/index.ts` | `/` | `GET /` | +| `/account/index.ts` | `/account` | `GET /account` | + +#### Route parameters + +Wrap any route parameter with `[]` to capture it. + +| File name | Route pattern | Matched requests | +| - | - | - | +| `/users/[id].ts` | `/users/:id` | `GET /users/123` with `{ id: "123" }`
`GET /users/foo` with `{ id: "foo" }` | + +#### Optional route parameters + +Make a route parameter optional by wrapping it name with `[[]]` (double brackets). + +| File name | Route pattern | Matched requests | +| - | - | - | +| `/users/[[id]].ts` | `/users/:id?` | `GET /users` with `{}`
`GET /users/123` with `{ id: "123" }`
`GET /users/foo` with `{ id: "foo" }` | + +You can mix parameters (both required and optional) in a single route segment: + +| File name | Route pattern | Matched requests | +| - | - | - | +| `/files/[name].[[ext]].ts` | `/files/:name.:ext?` | `GET /files/image.png` with `{ name: "image", ext: "png" }`
`GET /files/README` with `{ name: "README" }` | -### 3. Initialize HyperAPI +#### Catch-all parameters + +Route parameter names as `[...name]` consumes all remaining path segments. This route can only be used in a file name. + +| File name | Route pattern | Matched requests | Unmatched requests | +| - | - | - | - | +| `/docs/[...path].ts` | `/docs/:path+` | `GET /docs/foo` with `{ path: "foo" }`
`GET /docs/a/b/c` with `{ path: "a/b/c" }` | `GET /docs` | + +#### Optional catch-all parameters + +Route parameter names as `[[...name]]` consumes all remaining path segments, but also matches routes with no segments. This route can only be used in a file name. + +| File name | Route pattern | Matched requests | +| - | - | - | +| `/docs/[[...path]].ts` | `/docs/:path+` | `GET /docs` with `{}`
`GET /docs/foo` with `{ path: "foo" }`
`GET /docs/a/b/c` with `{ path: "a/b/c" }` | + +#### HTTP methods + +Add HTTP method before an extension to make route match only given HTTP method. By default, route will serve any incoming HTTP method. + +| File name | Route pattern | Matched requests | Unmatched requests | +| - | - | - | - | +| `/user/[id].get.ts` | `/user/:id` | `GET /user/1` with `{ id: "1" }` | `POST /user/1`
`DELETE /user/1` | + +But you can not use HTTP method in the filename if there is no name for the route. If you want to serve `POST /account`, create file `/account.post.ts` or `account/index.post.ts`, not just `account/post.ts`. + +### 2. Initialize HyperAPI ```typescript import { HyperAPI } from '@hyperapi/core'; -import { SomeHttpDriver } from '@hyperapi/some-http-driver'; // functional driver +import { SomeHttpDriver } from '@hyperapi/some-http-driver'; // fictional driver // Create a driver instance const driver = new SomeHttpDriver({ port: 3000 }); -// Initialize HyperAPI with the driver -const hyperApiCore = new HyperAPI({ +// Initialize HyperAPI with the driver and export it +export const hyperApi = new HyperAPI({ driver, // Optional: custom root path for API methods // root: path.join(import.meta.dir, 'api') @@ -94,113 +129,136 @@ const hyperApiCore = new HyperAPI({ console.log('API server running on http://localhost:3000'); ``` +### 3. Create your API handlers + +Example of a basic endpoint (`hyper-api/hello.get.ts`): + +```typescript +import * as v from 'valibot'; +// import HyperAPI instance you created +import { hyperApi } from '../main.js'; + +// Define input validation +function params>(schema: S) { + return (request) => { + return { args: v.parse(schema, request.args) }; + }; +} + +// Define your handler function +export default hyperApi.module() + .use(params( + v.strictObject({ + name: v.string('Name is required'), + }), + )) + .action((request) => { + // request.args now typed as { name: string } + return { + message: `Hello, ${request.args.name}!`, + timestamp: new Date().toISOString() + }; + }); +``` + ## Request Pipeline HyperAPI Core processes requests through a well-defined sequence of steps: 1. *Driver* creates a [request](src/request.ts#L6) and passes it to the *Core* -2. *Core* executes all registered `onBeforeRouter` hooks with request it received from the *Driver* +2. *Core* runs all registered `onBeforeRouter` hooks with request it received from the *Driver* 3. *Core* uses a file router to match the request path and method to a module file - - If no match is found, a [`HyperAPIUnknownMethodError`](src/api-errors.ts#L30) is thrown + - If no match is found, a [`HyperAPIUnknownMethodError`](src/api-errors.ts#L36) is thrown 4. *Core* merges arguments received from the driver with arguments extracted from the request path by the file router -5. *Core* imports the matched module file dynamically -6. If `argsValidator` is defined, *Core* calls it to validate the request arguments. Returned value is set as new request arguments value - - If `argsValidator` throws, a [`HyperAPIInvalidParametersError`](src/api-errors.ts#L12) is thrown -7. *Core* calls registered `setRequestTransformer` hook to update request with developer-defined transformations. -8. *Core* executes all registered `onBeforeExecute` hooks with request and module -9. *Core* calls the module's `export default function` with the request object -10. *Core* executes all registered `onResponse` hooks with request it received from the *Driver*, modified request, module, and response received from the module -11. Finally, *Core* passes the response back to the *Driver*, which sends it to the client. +5. *Core* imports the matched module file dynamically and runs it +6. *Core* executes all registered `onResponse` hooks +7. Finally, *Core* passes the response back to the *Driver*, which sends it to the client. -If an error occurs at any steps from 2 to 9, the pipeline short-circuits to the step 10. Before executing step 10, *Core* sets [`HyperAPIInternalError`](src/api-errors.ts#L18) as a response, if error occurred before is not instance of `HyperAPIError`. +If an error occurs at any steps from 2 to 5, the pipeline short-circuits to the step 6. Before executing step 6, *Core* sets [`HyperAPIInternalError`](src/api-errors.ts#L18) as a response, if error thrown is not instance of `HyperAPIError`. -## Input Validation +## Using plugins before executing the module -HyperAPI has built-in support for input validation using libraries like [valibot](https://github.com/fabian-hiller/valibot): +HyperAPI module allows you to use plugins (methods `use` and `set`) before executing the main code (method `action`). We described above how you can validate arguments using `valibot` and `use`. + +Properties returned from method `use` will be added to the request object. ```typescript -import * as v from 'valibot'; +import { hyperApi } from '../somewhere.js'; -export const argsValidator = v.parser( - v.strictObject({ - id: v.number('ID must be a number'), - email: v.string([v.email('Invalid email format')]), - tags: v.optional(v.array(v.string())), +export default hyperApi.module() + .use((request) => { + return { foo: 1 }; }) -); + .action((request) => { + // request now has property foo: number + return {}; + }); ``` -In general, you define `argsValidator` function that throws if validation fails and returns a valid object if the input is correct. But validation library is your choice. +If you want to add just one property, you can use the `set` method: -## Hooks and Middleware - -HyperAPI provides several hooks for extending functionality at different stages of the request pipeline. Every type of hook executed in parallel, so be careful when changing request object there and avoid race conditions. - -### `beforeRouter` hook +```typescript +import { hyperApi } from '../somewhere.js'; + +export default hyperApi.module() + .set('foo', 1) + .action((request) => { + // request now has property foo: number + return {}; + }); +``` -Executed after path normalization but before route matching. Use for logging, request inspection, or early validation. +Obviously, you can `use` after `action` to do some job. Value returned from `action` is located in the `response` property of the request object. ```typescript -hyperApiCore.onBeforeRouter((driver_request) => { - console.log(`Incoming request: ${driver_request.method} ${driver_request.path}`); +import { hyperApi } from '../somewhere.js'; - // Verify request integrity, implement rate limiting, etc. - if (isRateLimited(driver_request)) { - throw new HyperAPIRateLimitError(); - } -}); +export default hyperApi.module() + .action((request) => { + return { foo: 1 }; + }) + .use((request) => { + // request now has property response: { foo: number } + console.log('use after action', request.response); + }); ``` -### `requestTransformer` hook - -Executed after module loading and argument validation, but before module execution. Can access both driver request and module. +## Hooks -This hook can be set only once. +HyperAPI provides several hooks for extending functionality at different stages of the request pipeline. -> [!TIP] -> This is the only hook that can change the request type, allowing you to add custom properties or modify existing ones. -> -> For example, if module exports `auth = true` property, you can validate token and add user information to the request object. - -```typescript -hyperApiCore.setRequestTransformer((driver_request, module) => { - return { - ...driver_request, - user: module.auth - ? getCurrentUser(driver_request) - : null, - }; -}); -``` +### `beforeRouter` hook -### `beforeExecute` hook +Executed after path normalization but before route matching. Use for logging, request inspection, or early validation. If this hook returns an object, it will be merged with the request object. However, extra properties will be visible only to the next hooks, not the API module. -Executed before the module's default export function runs. +These hooks are executed in order of their definition, allowing you to extend request object multiple times. ```typescript -hyperApiCore.onBeforeExecute((request, module) => { - // Runs after transformation, with the final request object - // Perfect for authorization checks based on both request and module - if (module.auth && !isAuthorized(request, module.auth)) { - throw new HyperAPIUnauthorizedError(); - } -}); +hyperApi + .onBeforeRouter((request) => { + console.log(`Incoming request: ${request.method} ${request.path}`); + return { started_at: Date.now() }; + }) + .onBeforeRouter((request) => { + // request has "started_at" property + if (isRateLimited(request)) { + throw new HyperAPIRateLimitError(); + } + }); ``` ### `onResponse` hook -Executed before returning response to driver. Receives all context from the request lifecycle. +Executed before returning response to driver. Multiple hooks will be executed in parallel. -This hook has access to both the original driver request and the transformed request. Also, errors thrown from this hook will not change the response. +This hook has access to request and response returned from API method module. Errors thrown from this hook will not change the response. ```typescript -hyperApiCore.onResponse((driver_request, request, module, response) => { - // Has access to both original driver request and transformed request +hyperApi.onResponse((request, response) => { + // request still has "started_at" property added by onBeforeRouter hook // Useful for metrics, logging, and response modification - if (request) { - const duration = Date.now() - request.startTime; - console.log(`${request.method} ${request.path} completed in ${duration}ms`); - } + const duration = Date.now() - request.started_at; + console.log(`${request.method} ${request.path} completed in ${duration}ms`); }); ``` @@ -238,32 +296,7 @@ HyperAPI is designed to work with any transport layer or protocol through driver ## TypeScript Support -HyperAPI is built with TypeScript and provides excellent type inference: - -```typescript -// Define custom request type -interface MyRequest extends HyperAPIRequest { - user: { - id: string; - roles: string[]; - } -} - -// Define custom module interface -interface MyModule extends HyperAPIModule { - auth: boolean; - roles?: string[]; -} - -// Initialize with type parameters -const hyperApiCore = new HyperAPI< - typeof myDriver, - MyRequest, - MyModule ->({ - driver: myDriver -}); -``` +HyperAPI is built with TypeScript and provides excellent type inference. ## Contributing diff --git a/bun.lock b/bun.lock index e13669d..cdacb42 100644 --- a/bun.lock +++ b/bun.lock @@ -5,6 +5,7 @@ "name": "@hyperapi/core", "dependencies": { "itty-router": "5.0.22", + "neoevents": "^0.3.0", }, "devDependencies": { "@biomejs/biome": "2.1.1", @@ -549,6 +550,8 @@ "natural-compare": ["natural-compare@1.4.0", "", {}, "sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw=="], + "neoevents": ["neoevents@0.3.0", "", {}, "sha512-et9vcJ8ElRUbgxeJXAw++1noXVY302fxRvwEoIDll9KiQAeySjTQBdLtATvtE17MgbitLjjixI5UcFOS92EI+w=="], + "node-releases": ["node-releases@2.0.19", "", {}, "sha512-xxOWJsBKtzAq7DY0J+DTzuz58K8e7sJbdgwkbMWQe8UYB6ekmsQ45q0M/tJDsGaZmbC+l7n57UV8Hl5tHxO9uw=="], "nth-check": ["nth-check@2.1.1", "", { "dependencies": { "boolbase": "^1.0.0" } }, "sha512-lqjrjmaOoAnWfMmBPL+XNnynZh2+swxiX3WUE0s4yEHI6m+AwrK2UZOimIRl3X/4QctVqS8AiZjFqyOGrMXb/w=="], diff --git a/dist/main.cjs b/dist/main.cjs index 54e01b0..63717d3 100644 --- a/dist/main.cjs +++ b/dist/main.cjs @@ -22,10 +22,11 @@ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__ge //#endregion const node_path = __toESM(require("node:path")); -const node_fs = __toESM(require("node:fs")); const itty_router = __toESM(require("itty-router")); +const node_fs = __toESM(require("node:fs")); +const neoevents = __toESM(require("neoevents")); -//#region src/utils/is-record.ts +//#region src/utils/record.ts /** * Check if a value is a record. * @param value - @@ -34,6 +35,16 @@ const itty_router = __toESM(require("itty-router")); function isRecord(value) { return typeof value === "object" && value !== null && !Array.isArray(value) && value.constructor === Object && Object.prototype.toString.call(value) === "[object Object]"; } +/** +* Checks if there are common keys in both object. +* @param value1 - +* @param value2 - +* @returns - +*/ +function hasCommonKeys(value1, value2) { + for (const key of Object.keys(value2)) if (Object.hasOwn(value1, key)) return true; + return false; +} //#endregion //#region src/error.ts @@ -94,6 +105,11 @@ var HyperAPIUnknownMethodError = class extends HyperAPIError { description = "Unknown method called"; httpStatus = 404; }; +var HyperAPIUnknownMethodNotAllowedError = class extends HyperAPIError { + code = 5; + description = "Unknown method called"; + httpStatus = 405; +}; var HyperAPIObjectsLimitError = class extends HyperAPIError { code = 6; description = "Too many objects requested"; @@ -135,86 +151,267 @@ var HyperAPIMethodNotAllowedError = class extends HyperAPIError { httpStatus = 405; }; +//#endregion +//#region src/module.ts +var HyperAPIModule = class { + chain = []; + use(fn) { + this.chain.push(fn); + return this; + } + set(key, arg1) { + this.chain.push(async (request) => { + const value = typeof arg1 === "function" ? await arg1(request) : arg1; + if (value) return { [key]: value }; + }); + return this; + } + action(fn) { + this.chain.push(async (request) => { + const response = await fn(request); + if (response) return { response }; + }); + return this; + } + async _run(request) { + let request_result = request; + for (const fn of this.chain) { + const request_add = await fn(request_result); + if (request_add) request_result = { + ...request_result, + ...request_add + }; + } + return request_result; + } +}; + +//#endregion +//#region src/response.ts +/** +* Checks if the given value is a HyperAPIResponse. +* @param response - The value to check. +* @returns True if the value is a HyperAPIResponse, false otherwise. +*/ +function isHyperAPIResponse(response) { + return response instanceof HyperAPIError || response instanceof Response || isRecord(response) || Array.isArray(response) || response === void 0; +} + +//#endregion +//#region src/router/filename.ts +const RE_OPTIONAL_CATCH_ALL = /^\[\[\.\.\.([a-z_][\da-z_]*)\]\]$/i; +const RE_GREEDY = /^\[\.\.\.([a-z_][\da-z_]*)\]$/i; +/** +* Returns specificity for route. +* +* Values: +* - 0: static route (e.g. `/foo`) +* - 1: route with parameter (e.g. `/foo-:id`) +* - 2: route with optional parameter (e.g. `/foo-:id?`) +* - 3: route with greedy parameter (e.g. `/foo-:id+`) +* - 4: (NOT USED) route with wildcard (e.g. `/*`) +* @param name - +* @returns - +*/ +function parseFilename(name) { + if (name === "index" || name.length === 0) return { self: true }; + const match_optional_catch_all = RE_OPTIONAL_CATCH_ALL.exec(name); + if (match_optional_catch_all) return { + self: true, + route: { + part: `:${match_optional_catch_all[1]}+`, + specificity: { + type: 3, + static_length: 0 + } + } + }; + const match_greedy = RE_GREEDY.exec(name); + if (match_greedy) return { route: { + part: `:${match_greedy[1]}+`, + specificity: { + type: 3, + static_length: 0 + } + } }; + let has_optional = false; + let static_length = name.length; + const route_part = name.replaceAll(/(\[([a-z_][\da-z_]*)\]|\[\[([a-z_][\da-z_]*)\]\])([^\da-z_]|$)/gi, (...args) => { + static_length -= args[1].length; + if (args[3] !== void 0) { + has_optional = true; + return `:${args[3]}?${args[4]}`; + } + return `:${args[2]}${args[4]}`; + }); + if (name !== route_part) return { route: { + part: route_part, + specificity: { + type: has_optional ? 2 : 1, + static_length + } + } }; + if (name.includes("[") !== true) return { route: { + part: route_part, + specificity: { + type: 0, + static_length: 0 + } + } }; + throw new Error(`Invalid filename "${name}".`); +} + +//#endregion +//#region src/router/file-tree.ts +const RE_EXT = /\.([cm]?[jt]s)$/i; +const RE_METHOD = /\.(delete|get|head|options|patch|post|put)$/i; +var WalkSpecificityPosition = /* @__PURE__ */ function(WalkSpecificityPosition$1) { + WalkSpecificityPosition$1[WalkSpecificityPosition$1["FILE_METHOD"] = 0] = "FILE_METHOD"; + WalkSpecificityPosition$1[WalkSpecificityPosition$1["FILE_ALL"] = 1] = "FILE_ALL"; + WalkSpecificityPosition$1[WalkSpecificityPosition$1["DIRECTORY"] = 2] = "DIRECTORY"; + return WalkSpecificityPosition$1; +}(WalkSpecificityPosition || {}); +/** +* Reads the file system and returns a tree of routes sorted correctly. +* @param path_given The directory to read. +* @param _state Internal state. +* @returns - +*/ +function readFiles(path_given, _state) { + _state ??= { + route: null, + specificity: { + type: 0, + static_length: 0, + position: WalkSpecificityPosition.DIRECTORY + } + }; + const result_directory = { + specificity: _state.specificity, + children: [] + }; + const result_routes = []; + const entries = (0, node_fs.readdirSync)(path_given, { withFileTypes: true }); + if (process.env.NODE_ENV === "test") for (let i = entries.length - 1; i > 0; i--) { + const j = Math.floor(Math.random() * (i + 1)); + [entries[i], entries[j]] = [entries[j], entries[i]]; + } + for (const entry of entries) { + const path = node_path.default.join(entry.parentPath, entry.name); + if (entry.isFile()) { + let name = entry.name.replace(RE_EXT, ""); + if (name.endsWith(".test")) continue; + let method = "all"; + name = name.replace(RE_METHOD, (_, g1) => { + method = g1.toLowerCase(); + return ""; + }); + const { self, route } = parseFilename(name); + const specificity_position = method === "all" ? WalkSpecificityPosition.FILE_ALL : WalkSpecificityPosition.FILE_METHOD; + if (self) result_routes.push({ + specificity: { + ..._state.specificity, + position: specificity_position + }, + method, + route: _state.route ?? "/", + path + }); + if (route) result_directory.children.push({ + specificity: { + ...route.specificity, + position: specificity_position + }, + method, + route: (_state.route ?? "") + node_path.default.sep + route.part, + path + }); + } else if (entry.isDirectory()) { + const { self, route } = parseFilename(entry.name); + if (self) throw new Error(`Invalid directory name "${entry.name}" at "${path}". Can not use optional catch-all in directory name.`); + if (!route) throw new Error(`Invalid directory name "${entry.name}" at "${path}".`); + result_directory.children.push(...readFiles(path, { + route: (_state.route ?? "") + node_path.default.sep + route.part, + specificity: { + ...route.specificity, + position: WalkSpecificityPosition.DIRECTORY + } + })); + } + } + sortRoutes(result_directory.children); + const result = [result_directory, ...result_routes]; + if (_state.route === null) sortRoutes(result); + return result; +} +/** +* Sorts the routes in the given result. +* @param result The result to sort. +* @returns - +*/ +function sortRoutes(result) { + return result.sort((a, b) => { + if (a.specificity.type !== b.specificity.type) return a.specificity.type - b.specificity.type; + if (a.specificity.static_length !== b.specificity.static_length) return b.specificity.static_length - a.specificity.static_length; + if (a.specificity.position !== b.specificity.position) return a.specificity.position - b.specificity.position; + return 0; + }); +} + //#endregion //#region src/router.ts /** * Creates new IttyRouter from filesystem. -* @param path The path to scan. +* @param path_root The path to scan. * @returns The new IttyRouter. */ -function createRouter(path) { +function createRouter(path_root) { const router = (0, itty_router.IttyRouter)(); - scanDirectory(router, path); + const routes = readFiles(path_root); + fillRouter(routes, router); return router; } /** +* Attaches routes to IttyRouter. +* @param routes The routes to attach. +* @param router The IttyRouter to attach to. +*/ +function fillRouter(routes, router) { + for (const route of routes) if ("method" in route) router[route.method](route.route, (request) => ({ + async getHandler() { + const module_ = await import(route.path); + return module_.default; + }, + path: route.path, + args: request.params + })); + else if ("children" in route) fillRouter(route.children, router); +} +/** * Fetches data from router. * @param router The router to fetch data from. * @param method The HTTP method. * @param path The path to fetch data from. * @returns The response. */ -function useRouter(router, method, path) { - return router.fetch({ +async function useRouter(router, method, path) { + const url = `file://${path}`; + const result = await router.fetch({ method, - url: `file://${path}` + url }); -} -const REGEXP_FILE_EXTENSION = /\.(js|mjs|cjs|ts)$/; -const REGEXP_TEST_FILE_EXTENSION = /\.test\.(js|mjs|cjs|ts)$/; -const REGEXP_HTTP_METHOD = /(?:^|\.)\[(delete|get|head|options|patch|post|put)]$/; -const REGEXP_PATH_SLUG = /\[(\w+)]/g; -/** -* Scans directory for routes. -* @param router The router to add routes to. -* @param path The path to scan. -* @param [regexp_parts] The parts of the regular expression. -*/ -function scanDirectory(router, path, regexp_parts = [""]) { - const result = (0, node_fs.readdirSync)(path, { withFileTypes: true }); - const routes = { - "0": [], - "1": [], - "2": [], - "3": [] - }; - for (const entry of result) { - const entry_path = node_path.default.join(path, entry.name); - if (entry.isFile()) { - let file_name = entry.name; - if (REGEXP_FILE_EXTENSION.test(file_name) && REGEXP_TEST_FILE_EXTENSION.test(file_name) !== true) { - file_name = file_name.replace(REGEXP_FILE_EXTENSION, ""); - let method = "all"; - const method_match = file_name.match(REGEXP_HTTP_METHOD); - const has_method = method_match ? 1 : 0; - if (method_match) { - method = method_match[1]; - file_name = file_name.replace(REGEXP_HTTP_METHOD, ""); - } - const has_slug = REGEXP_PATH_SLUG.test(file_name) ? 2 : 0; - file_name = file_name.replaceAll(REGEXP_PATH_SLUG, ":$1"); - routes[has_method | has_slug]?.push({ - method, - path: [...regexp_parts, file_name].join(node_path.default.sep), - module_path: entry_path - }); - } - } else scanDirectory(router, entry_path, [...regexp_parts, entry.name.replaceAll(REGEXP_PATH_SLUG, ":$1")]); - } - for (const route of [ - ...routes[1], - ...routes[3], - ...routes[0], - ...routes[2] - ]) router[route.method](route.path, (r) => { - const response = { - module_path: route.module_path, - args: r.params - }; - return response; + if (result) return result; + const result_unknown = await router.fetch({ + method: "UNKNOWN", + url }); + return result_unknown ? "INVALID" : "NOT_EXISTS"; } +//#endregion +//#region src/driver.ts +var HyperAPIDriver = class extends neoevents.NeoEventTarget {}; + //#endregion //#region src/utils/methods.ts /** @@ -231,150 +428,77 @@ function isHyperApiMethod(method) { const ENTRYPOINT_PATH = node_path.default.dirname(process.argv[1]); var HyperAPI = class { router; - driver; - /** - * Creates a HyperAPI instance. - * @param options The options. - * @param options.driver The driver. - * @param [options.root] The root directory for API methods modules. Default: `hyper-api` directory alongside the entrypoint script. - */ - constructor({ driver, root = node_path.default.join(ENTRYPOINT_PATH, "hyper-api") }) { - this.driver = driver; + off; + constructor(driver, root = node_path.default.join(ENTRYPOINT_PATH, "hyper-api")) { this.router = createRouter(root); - this.driver.start(async (arg0) => { - const driver_request = arg0; - const [request, module_, response] = await this.processRequest(driver_request); - try { - await this.useHooks(this.handlers.response, { - driver_request, - request, - module: module_, - response - }); - } catch (error) { - console.error("Error in \"response\" hook:"); - console.error(error); + this.off = driver.on("request", async (event) => { + const [request_external, response] = await this.processRequest(event.detail.request); + if (this.hooks_response.length > 0) { + const promises = []; + for (const fn of this.hooks_response) try { + const result = fn({ + ...event.detail.request, + ...request_external + }); + if (result instanceof Promise) promises.push(result.catch(console.error)); + } catch (error) { + console.error(error); + } + await Promise.all(promises); } - return response; + event.detail.callback(response); }); } - handlers = { - beforeRouter: [], - requestTransformer: void 0, - beforeExecute: [], - response: [] - }; - /** - * Adds a hook to be called before request is matched against the file router. - * - * This hook can be set multiple times. Every hook is executed simultaneously. - * - * If error is thrown in this hook, it will abort the request processing and return an error response. - * @param callback The callback function. - * @returns - - */ - onBeforeRouter(callback) { - this.handlers.beforeRouter.push(callback); - return this; - } - /** - * Use this hook add properties to the request before it is send to the API module. - * - * This hook can be set only once. - * - * If error is thrown in this hook, it will abort the request processing and return an error response. - * @param transformer The callback function. - * @returns - - */ - setRequestTransformer(transformer) { - if (this.handlers.requestTransformer) throw new Error("Transformer has already been set."); - this.handlers.requestTransformer = transformer; - return this; - } - /** - * Adds a hook to be called right before the API module is executed. - * - * This hook can be set multiple times. Every hook is executed simultaneously. - * - * If error is thrown in this hook, it will abort the request processing and return an error response. - * @param callback - - * @returns - - */ - onBeforeExecute(callback) { - this.handlers.beforeExecute.push(callback); + hooks_before_router = []; + onBeforeRouter(fn) { + this.hooks_before_router.push(fn); return this; } - /** - * Adds a hook to be called right before the response is sent back to the driver. - * - * This hook can be set multiple times. Every hook is executed simultaneously. - * - * If error is thrown in this hook, it will be printed to the console, but will not prevent response from being sent to the driver. - * @param callback - - * @returns - - */ - onResponse(callback) { - this.handlers.response.push(callback); + hooks_response = []; + onResponse(fn) { + this.hooks_response.push(fn); return this; } - async useHooks(hooks, ctx) { - const promises = []; - for (const hook of hooks) promises.push(hook(ctx)); - await Promise.all(promises); - } - async processRequest(driver_request) { - let request = null; - let module_ = null; + async processRequest(request) { + let request_external = {}; try { - if (driver_request.path.startsWith("/") !== true) driver_request.path = `/${driver_request.path}`; - await this.useHooks(this.handlers.beforeRouter, { driver_request }); - const router_response = await useRouter(this.router, driver_request.method, driver_request.path); - if (!router_response) throw new HyperAPIUnknownMethodError(); - driver_request.args = { - ...driver_request.args, + if (request.path.startsWith("/") !== true) request.path = `/${request.path}`; + for (const fn of this.hooks_before_router) { + const request_added = await fn({ + ...request, + ...request_external + }); + if (request_added !== void 0) request_external = { + ...request_external, + ...request_added + }; + } + const router_response = await useRouter(this.router, request.method, request.path); + if (router_response === "INVALID") throw new HyperAPIUnknownMethodNotAllowedError(); + if (router_response === "NOT_EXISTS") throw new HyperAPIUnknownMethodError(); + if (hasCommonKeys(router_response.args, request.args)) throw new HyperAPIInvalidParametersError(); + request.args = { + ...request.args, ...router_response.args }; - module_ = await import(router_response.module_path); - if (module_.argsValidator) try { - driver_request.args = module_.argsValidator(driver_request.args); - } catch (error) { - console.error(error); - throw new HyperAPIInvalidParametersError(); - } - request = this.handlers.requestTransformer ? await this.handlers.requestTransformer({ - driver_request, - module: module_ - }) : driver_request; - await this.useHooks(this.handlers.beforeExecute, { - request, - module: module_ + const handler = await router_response.getHandler(); + const { response } = await handler._run({ + ...request, + ...request_external }); - const response = await module_.default(request); - return [ - request, - module_, - response - ]; + if (isHyperAPIResponse(response) !== true) throw new TypeError(`Invalid response type from module ${router_response.path}. Expected Response, HyperAPIError, array, object or undefined.`); + return [request_external, response]; } catch (error) { - if (error instanceof HyperAPIError) return [ - request, - module_, - error - ]; + if (error instanceof HyperAPIError) return [request_external, error]; console.error(error); - return [ - request, - module_, - new HyperAPIInternalError() - ]; + return [request_external, new HyperAPIInternalError()]; } } - /** Destroys the HyperAPI instance. */ + module() { + return new HyperAPIModule(); + } destroy() { - this.handlers.beforeRouter.splice(0); - this.handlers.requestTransformer = void 0; - this.handlers.beforeExecute.splice(0); - this.handlers.response.splice(0); + this.off(); } }; @@ -384,6 +508,7 @@ exports.HyperAPIAuthorizationError = HyperAPIAuthorizationError; exports.HyperAPIBusyError = HyperAPIBusyError; exports.HyperAPICaptchaError = HyperAPICaptchaError; exports.HyperAPIConfirmationError = HyperAPIConfirmationError; +exports.HyperAPIDriver = HyperAPIDriver; exports.HyperAPIError = HyperAPIError; exports.HyperAPIForbiddenError = HyperAPIForbiddenError; exports.HyperAPIInternalError = HyperAPIInternalError; @@ -394,4 +519,5 @@ exports.HyperAPIOTPError = HyperAPIOTPError; exports.HyperAPIObjectsLimitError = HyperAPIObjectsLimitError; exports.HyperAPIRateLimitError = HyperAPIRateLimitError; exports.HyperAPIUnknownMethodError = HyperAPIUnknownMethodError; +exports.HyperAPIUnknownMethodNotAllowedError = HyperAPIUnknownMethodNotAllowedError; exports.isHyperApiMethod = isHyperApiMethod; \ No newline at end of file diff --git a/dist/main.d.cts b/dist/main.d.cts index 778e25a..c4c363a 100644 --- a/dist/main.d.cts +++ b/dist/main.d.cts @@ -1,4 +1,5 @@ -import { EmptyObject, Promisable } from "type-fest"; +import { IsEqual, Promisable, Simplify } from "type-fest"; +import { NeoEvent, NeoEventTarget } from "neoevents"; //#region src/utils/methods.d.ts type HyperAPIMethod = "DELETE" | "GET" | "HEAD" | "OPTIONS" | "PATCH" | "POST" | "PUT" | "UNKNOWN"; @@ -9,8 +10,17 @@ type HyperAPIMethod = "DELETE" | "GET" | "HEAD" | "OPTIONS" | "PATCH" | "POST" | */ declare function isHyperApiMethod(method: unknown): method is HyperAPIMethod; //#endregion +//#region src/utils/record.d.ts +type BaseRecord = Record; +type EmptyObject = Record; +/** +* Check if a value is a record. +* @param value - +* @returns - +*/ +//#endregion //#region src/request.d.ts -type HyperAPIRequestArgs = Record; +type HyperAPIRequestArgs = BaseRecord; interface HyperAPIRequest
{ method: HyperAPIMethod; path: string; @@ -44,24 +54,42 @@ declare class HyperAPIError extends Err getResponse(): HyperAPIErrorResponse; } //#endregion +//#region src/utils/types.d.ts +type Join, ReqExtra extends BaseRecord> = R & ([ReqExtra] extends [never] ? unknown : IsEqual extends true ? unknown : ReqExtra); +type Extend = Simplify extends true ? unknown : V1) & V2>; +//#endregion //#region src/module.d.ts -type HyperAPIModuleResponse = Record | Response | unknown[] | undefined; -interface HyperAPIModule> { - readonly default: (request: R) => Promisable; - readonly argsValidator: (args: unknown) => R extends HyperAPIRequest ? A : never; +type HyperAPIModuleResponse = Response | BaseRecord | unknown[] | undefined; +declare class HyperAPIModule, ReqExtra extends BaseRecord = never> { + private chain; + use(fn: (request: Join) => Promisable): HyperAPIModule>; + set(key: K, fn: (request: Join) => Promisable): HyperAPIModule>; + set(key: K, value: V): HyperAPIModule>; + action(fn: (request: Join) => Promisable): HyperAPIModule>; + _run(request: Req): Promise, ReqExtra>>; } -type InferModule> = H extends HyperAPI ? M : never; //#endregion //#region src/response.d.ts type HyperAPIResponse = HyperAPIModuleResponse | HyperAPIError; +/** +* Checks if the given value is a HyperAPIResponse. +* @param response - The value to check. +* @returns True if the value is a HyperAPIResponse, false otherwise. +*/ //#endregion //#region src/driver.d.ts -type HyperAPIDriverHandler = (request: R) => Promisable; -interface HyperAPIDriver { - start(handler: HyperAPIDriverHandler): void; - stop(): void; +declare class HyperAPIDriver extends NeoEventTarget<{ + request: NeoEvent<{ + request: R; + callback: (response: HyperAPIResponse) => void; + }>; +}> { + R: R; } -type InferDriverRequest = D extends HyperAPIDriver ? R : never; //#endregion //#region src/api-errors.d.ts declare class HyperAPIAuthorizationError extends HyperAPIError { @@ -89,6 +117,11 @@ declare class HyperAPIUnknownMethodError extends Hy description: string; httpStatus: number; } +declare class HyperAPIUnknownMethodNotAllowedError extends HyperAPIError { + code: number; + description: string; + httpStatus: number; +} declare class HyperAPIObjectsLimitError extends HyperAPIError { code: number; description: string; @@ -131,86 +164,17 @@ declare class HyperAPIMethodNotAllowedError extends } //#endregion //#region src/main.d.ts -interface HyperAPIHandlers, M extends HyperAPIModule> { - beforeRouter: ((ctx: { - driver_request: Readonly>; - }) => Promisable)[]; - requestTransformer: ((ctx: { - driver_request: Readonly>; - module: M; - }) => Promisable) | void; - beforeExecute: ((ctx: { - request: Readonly; - module: M; - }) => Promisable)[]; - response: ((ctx: { - driver_request: Readonly>; - request: R | null; - module: M | null; - response: HyperAPIResponse; - }) => Promisable)[]; -} -declare class HyperAPI, R extends InferDriverRequest, M extends HyperAPIModule = HyperAPIModule> { +declare class HyperAPI { private router; - private driver; - /** - * Creates a HyperAPI instance. - * @param options The options. - * @param options.driver The driver. - * @param [options.root] The root directory for API methods modules. Default: `hyper-api` directory alongside the entrypoint script. - */ - constructor({ - driver, - root - }: { - driver: D; - root?: string; - }); - private handlers; - /** - * Adds a hook to be called before request is matched against the file router. - * - * This hook can be set multiple times. Every hook is executed simultaneously. - * - * If error is thrown in this hook, it will abort the request processing and return an error response. - * @param callback The callback function. - * @returns - - */ - onBeforeRouter(callback: HyperAPIHandlers["beforeRouter"][number]): this; - /** - * Use this hook add properties to the request before it is send to the API module. - * - * This hook can be set only once. - * - * If error is thrown in this hook, it will abort the request processing and return an error response. - * @param transformer The callback function. - * @returns - - */ - setRequestTransformer(transformer: HyperAPIHandlers["requestTransformer"]): this; - /** - * Adds a hook to be called right before the API module is executed. - * - * This hook can be set multiple times. Every hook is executed simultaneously. - * - * If error is thrown in this hook, it will abort the request processing and return an error response. - * @param callback - - * @returns - - */ - onBeforeExecute(callback: HyperAPIHandlers["beforeExecute"][number]): this; - /** - * Adds a hook to be called right before the response is sent back to the driver. - * - * This hook can be set multiple times. Every hook is executed simultaneously. - * - * If error is thrown in this hook, it will be printed to the console, but will not prevent response from being sent to the driver. - * @param callback - - * @returns - - */ - onResponse(callback: HyperAPIHandlers["response"][number]): this; - private useHooks; + private off; + constructor(driver: HyperAPIDriver, root?: string); + private hooks_before_router; + onBeforeRouter(fn: (request: Join) => Promisable): HyperAPI>; + private hooks_response; + onResponse(fn: (request: Join) => Promisable): HyperAPI; private processRequest; - /** Destroys the HyperAPI instance. */ + module(): HyperAPIModule; destroy(): void; } //#endregion -export { HyperAPI, HyperAPIAuthorizationError, HyperAPIBusyError, HyperAPICaptchaError, HyperAPIConfirmationError, type HyperAPIDriver, type HyperAPIDriverHandler, HyperAPIError, type HyperAPIErrorData, HyperAPIForbiddenError, HyperAPIInternalError, HyperAPIInvalidParametersError, HyperAPIMaintenanceError, type HyperAPIMethod, HyperAPIMethodNotAllowedError, type HyperAPIModule, type HyperAPIModuleResponse, HyperAPIOTPError, HyperAPIObjectsLimitError, HyperAPIRateLimitError, type HyperAPIRequest, type HyperAPIRequestArgs, type HyperAPIResponse, HyperAPIUnknownMethodError, type InferModule, isHyperApiMethod }; \ No newline at end of file +export { HyperAPI, HyperAPIAuthorizationError, HyperAPIBusyError, HyperAPICaptchaError, HyperAPIConfirmationError, HyperAPIDriver, HyperAPIError, type HyperAPIErrorData, HyperAPIForbiddenError, HyperAPIInternalError, HyperAPIInvalidParametersError, HyperAPIMaintenanceError, type HyperAPIMethod, HyperAPIMethodNotAllowedError, type HyperAPIModule, type HyperAPIModuleResponse, HyperAPIOTPError, HyperAPIObjectsLimitError, HyperAPIRateLimitError, type HyperAPIRequest, type HyperAPIRequestArgs, type HyperAPIResponse, HyperAPIUnknownMethodError, HyperAPIUnknownMethodNotAllowedError, isHyperApiMethod }; \ No newline at end of file diff --git a/dist/main.d.ts b/dist/main.d.ts index 778e25a..0748031 100644 --- a/dist/main.d.ts +++ b/dist/main.d.ts @@ -1,4 +1,5 @@ -import { EmptyObject, Promisable } from "type-fest"; +import { NeoEvent, NeoEventTarget } from "neoevents"; +import { IsEqual, Promisable, Simplify } from "type-fest"; //#region src/utils/methods.d.ts type HyperAPIMethod = "DELETE" | "GET" | "HEAD" | "OPTIONS" | "PATCH" | "POST" | "PUT" | "UNKNOWN"; @@ -9,8 +10,17 @@ type HyperAPIMethod = "DELETE" | "GET" | "HEAD" | "OPTIONS" | "PATCH" | "POST" | */ declare function isHyperApiMethod(method: unknown): method is HyperAPIMethod; //#endregion +//#region src/utils/record.d.ts +type BaseRecord = Record; +type EmptyObject = Record; +/** +* Check if a value is a record. +* @param value - +* @returns - +*/ +//#endregion //#region src/request.d.ts -type HyperAPIRequestArgs = Record; +type HyperAPIRequestArgs = BaseRecord; interface HyperAPIRequest { method: HyperAPIMethod; path: string; @@ -44,24 +54,42 @@ declare class HyperAPIError extends Err getResponse(): HyperAPIErrorResponse; } //#endregion +//#region src/utils/types.d.ts +type Join, ReqExtra extends BaseRecord> = R & ([ReqExtra] extends [never] ? unknown : IsEqual extends true ? unknown : ReqExtra); +type Extend = Simplify extends true ? unknown : V1) & V2>; +//#endregion //#region src/module.d.ts -type HyperAPIModuleResponse = Record | Response | unknown[] | undefined; -interface HyperAPIModule> { - readonly default: (request: R) => Promisable; - readonly argsValidator: (args: unknown) => R extends HyperAPIRequest ? A : never; +type HyperAPIModuleResponse = Response | BaseRecord | unknown[] | undefined; +declare class HyperAPIModule, ReqExtra extends BaseRecord = never> { + private chain; + use(fn: (request: Join) => Promisable): HyperAPIModule>; + set(key: K, fn: (request: Join) => Promisable): HyperAPIModule>; + set(key: K, value: V): HyperAPIModule>; + action(fn: (request: Join) => Promisable): HyperAPIModule>; + _run(request: Req): Promise, ReqExtra>>; } -type InferModule> = H extends HyperAPI ? M : never; //#endregion //#region src/response.d.ts type HyperAPIResponse = HyperAPIModuleResponse | HyperAPIError; +/** +* Checks if the given value is a HyperAPIResponse. +* @param response - The value to check. +* @returns True if the value is a HyperAPIResponse, false otherwise. +*/ //#endregion //#region src/driver.d.ts -type HyperAPIDriverHandler = (request: R) => Promisable; -interface HyperAPIDriver { - start(handler: HyperAPIDriverHandler): void; - stop(): void; +declare class HyperAPIDriver extends NeoEventTarget<{ + request: NeoEvent<{ + request: R; + callback: (response: HyperAPIResponse) => void; + }>; +}> { + R: R; } -type InferDriverRequest = D extends HyperAPIDriver ? R : never; //#endregion //#region src/api-errors.d.ts declare class HyperAPIAuthorizationError extends HyperAPIError { @@ -89,6 +117,11 @@ declare class HyperAPIUnknownMethodError extends Hy description: string; httpStatus: number; } +declare class HyperAPIUnknownMethodNotAllowedError extends HyperAPIError { + code: number; + description: string; + httpStatus: number; +} declare class HyperAPIObjectsLimitError extends HyperAPIError { code: number; description: string; @@ -131,86 +164,17 @@ declare class HyperAPIMethodNotAllowedError extends } //#endregion //#region src/main.d.ts -interface HyperAPIHandlers, M extends HyperAPIModule> { - beforeRouter: ((ctx: { - driver_request: Readonly>; - }) => Promisable)[]; - requestTransformer: ((ctx: { - driver_request: Readonly>; - module: M; - }) => Promisable) | void; - beforeExecute: ((ctx: { - request: Readonly; - module: M; - }) => Promisable)[]; - response: ((ctx: { - driver_request: Readonly>; - request: R | null; - module: M | null; - response: HyperAPIResponse; - }) => Promisable)[]; -} -declare class HyperAPI, R extends InferDriverRequest, M extends HyperAPIModule = HyperAPIModule> { +declare class HyperAPI { private router; - private driver; - /** - * Creates a HyperAPI instance. - * @param options The options. - * @param options.driver The driver. - * @param [options.root] The root directory for API methods modules. Default: `hyper-api` directory alongside the entrypoint script. - */ - constructor({ - driver, - root - }: { - driver: D; - root?: string; - }); - private handlers; - /** - * Adds a hook to be called before request is matched against the file router. - * - * This hook can be set multiple times. Every hook is executed simultaneously. - * - * If error is thrown in this hook, it will abort the request processing and return an error response. - * @param callback The callback function. - * @returns - - */ - onBeforeRouter(callback: HyperAPIHandlers["beforeRouter"][number]): this; - /** - * Use this hook add properties to the request before it is send to the API module. - * - * This hook can be set only once. - * - * If error is thrown in this hook, it will abort the request processing and return an error response. - * @param transformer The callback function. - * @returns - - */ - setRequestTransformer(transformer: HyperAPIHandlers["requestTransformer"]): this; - /** - * Adds a hook to be called right before the API module is executed. - * - * This hook can be set multiple times. Every hook is executed simultaneously. - * - * If error is thrown in this hook, it will abort the request processing and return an error response. - * @param callback - - * @returns - - */ - onBeforeExecute(callback: HyperAPIHandlers["beforeExecute"][number]): this; - /** - * Adds a hook to be called right before the response is sent back to the driver. - * - * This hook can be set multiple times. Every hook is executed simultaneously. - * - * If error is thrown in this hook, it will be printed to the console, but will not prevent response from being sent to the driver. - * @param callback - - * @returns - - */ - onResponse(callback: HyperAPIHandlers["response"][number]): this; - private useHooks; + private off; + constructor(driver: HyperAPIDriver, root?: string); + private hooks_before_router; + onBeforeRouter(fn: (request: Join) => Promisable): HyperAPI>; + private hooks_response; + onResponse(fn: (request: Join) => Promisable): HyperAPI; private processRequest; - /** Destroys the HyperAPI instance. */ + module(): HyperAPIModule; destroy(): void; } //#endregion -export { HyperAPI, HyperAPIAuthorizationError, HyperAPIBusyError, HyperAPICaptchaError, HyperAPIConfirmationError, type HyperAPIDriver, type HyperAPIDriverHandler, HyperAPIError, type HyperAPIErrorData, HyperAPIForbiddenError, HyperAPIInternalError, HyperAPIInvalidParametersError, HyperAPIMaintenanceError, type HyperAPIMethod, HyperAPIMethodNotAllowedError, type HyperAPIModule, type HyperAPIModuleResponse, HyperAPIOTPError, HyperAPIObjectsLimitError, HyperAPIRateLimitError, type HyperAPIRequest, type HyperAPIRequestArgs, type HyperAPIResponse, HyperAPIUnknownMethodError, type InferModule, isHyperApiMethod }; \ No newline at end of file +export { HyperAPI, HyperAPIAuthorizationError, HyperAPIBusyError, HyperAPICaptchaError, HyperAPIConfirmationError, HyperAPIDriver, HyperAPIError, type HyperAPIErrorData, HyperAPIForbiddenError, HyperAPIInternalError, HyperAPIInvalidParametersError, HyperAPIMaintenanceError, type HyperAPIMethod, HyperAPIMethodNotAllowedError, type HyperAPIModule, type HyperAPIModuleResponse, HyperAPIOTPError, HyperAPIObjectsLimitError, HyperAPIRateLimitError, type HyperAPIRequest, type HyperAPIRequestArgs, type HyperAPIResponse, HyperAPIUnknownMethodError, HyperAPIUnknownMethodNotAllowedError, isHyperApiMethod }; \ No newline at end of file diff --git a/dist/main.js b/dist/main.js index cc829e8..745f573 100644 --- a/dist/main.js +++ b/dist/main.js @@ -1,8 +1,9 @@ import nodePath from "node:path"; -import { readdirSync } from "node:fs"; import { IttyRouter } from "itty-router"; +import { readdirSync } from "node:fs"; +import { NeoEvent, NeoEventTarget } from "neoevents"; -//#region src/utils/is-record.ts +//#region src/utils/record.ts /** * Check if a value is a record. * @param value - @@ -11,6 +12,16 @@ import { IttyRouter } from "itty-router"; function isRecord(value) { return typeof value === "object" && value !== null && !Array.isArray(value) && value.constructor === Object && Object.prototype.toString.call(value) === "[object Object]"; } +/** +* Checks if there are common keys in both object. +* @param value1 - +* @param value2 - +* @returns - +*/ +function hasCommonKeys(value1, value2) { + for (const key of Object.keys(value2)) if (Object.hasOwn(value1, key)) return true; + return false; +} //#endregion //#region src/error.ts @@ -71,6 +82,11 @@ var HyperAPIUnknownMethodError = class extends HyperAPIError { description = "Unknown method called"; httpStatus = 404; }; +var HyperAPIUnknownMethodNotAllowedError = class extends HyperAPIError { + code = 5; + description = "Unknown method called"; + httpStatus = 405; +}; var HyperAPIObjectsLimitError = class extends HyperAPIError { code = 6; description = "Too many objects requested"; @@ -112,86 +128,267 @@ var HyperAPIMethodNotAllowedError = class extends HyperAPIError { httpStatus = 405; }; +//#endregion +//#region src/module.ts +var HyperAPIModule = class { + chain = []; + use(fn) { + this.chain.push(fn); + return this; + } + set(key, arg1) { + this.chain.push(async (request) => { + const value = typeof arg1 === "function" ? await arg1(request) : arg1; + if (value) return { [key]: value }; + }); + return this; + } + action(fn) { + this.chain.push(async (request) => { + const response = await fn(request); + if (response) return { response }; + }); + return this; + } + async _run(request) { + let request_result = request; + for (const fn of this.chain) { + const request_add = await fn(request_result); + if (request_add) request_result = { + ...request_result, + ...request_add + }; + } + return request_result; + } +}; + +//#endregion +//#region src/response.ts +/** +* Checks if the given value is a HyperAPIResponse. +* @param response - The value to check. +* @returns True if the value is a HyperAPIResponse, false otherwise. +*/ +function isHyperAPIResponse(response) { + return response instanceof HyperAPIError || response instanceof Response || isRecord(response) || Array.isArray(response) || response === void 0; +} + +//#endregion +//#region src/router/filename.ts +const RE_OPTIONAL_CATCH_ALL = /^\[\[\.\.\.([a-z_][\da-z_]*)\]\]$/i; +const RE_GREEDY = /^\[\.\.\.([a-z_][\da-z_]*)\]$/i; +/** +* Returns specificity for route. +* +* Values: +* - 0: static route (e.g. `/foo`) +* - 1: route with parameter (e.g. `/foo-:id`) +* - 2: route with optional parameter (e.g. `/foo-:id?`) +* - 3: route with greedy parameter (e.g. `/foo-:id+`) +* - 4: (NOT USED) route with wildcard (e.g. `/*`) +* @param name - +* @returns - +*/ +function parseFilename(name) { + if (name === "index" || name.length === 0) return { self: true }; + const match_optional_catch_all = RE_OPTIONAL_CATCH_ALL.exec(name); + if (match_optional_catch_all) return { + self: true, + route: { + part: `:${match_optional_catch_all[1]}+`, + specificity: { + type: 3, + static_length: 0 + } + } + }; + const match_greedy = RE_GREEDY.exec(name); + if (match_greedy) return { route: { + part: `:${match_greedy[1]}+`, + specificity: { + type: 3, + static_length: 0 + } + } }; + let has_optional = false; + let static_length = name.length; + const route_part = name.replaceAll(/(\[([a-z_][\da-z_]*)\]|\[\[([a-z_][\da-z_]*)\]\])([^\da-z_]|$)/gi, (...args) => { + static_length -= args[1].length; + if (args[3] !== void 0) { + has_optional = true; + return `:${args[3]}?${args[4]}`; + } + return `:${args[2]}${args[4]}`; + }); + if (name !== route_part) return { route: { + part: route_part, + specificity: { + type: has_optional ? 2 : 1, + static_length + } + } }; + if (name.includes("[") !== true) return { route: { + part: route_part, + specificity: { + type: 0, + static_length: 0 + } + } }; + throw new Error(`Invalid filename "${name}".`); +} + +//#endregion +//#region src/router/file-tree.ts +const RE_EXT = /\.([cm]?[jt]s)$/i; +const RE_METHOD = /\.(delete|get|head|options|patch|post|put)$/i; +var WalkSpecificityPosition = /* @__PURE__ */ function(WalkSpecificityPosition$1) { + WalkSpecificityPosition$1[WalkSpecificityPosition$1["FILE_METHOD"] = 0] = "FILE_METHOD"; + WalkSpecificityPosition$1[WalkSpecificityPosition$1["FILE_ALL"] = 1] = "FILE_ALL"; + WalkSpecificityPosition$1[WalkSpecificityPosition$1["DIRECTORY"] = 2] = "DIRECTORY"; + return WalkSpecificityPosition$1; +}(WalkSpecificityPosition || {}); +/** +* Reads the file system and returns a tree of routes sorted correctly. +* @param path_given The directory to read. +* @param _state Internal state. +* @returns - +*/ +function readFiles(path_given, _state) { + _state ??= { + route: null, + specificity: { + type: 0, + static_length: 0, + position: WalkSpecificityPosition.DIRECTORY + } + }; + const result_directory = { + specificity: _state.specificity, + children: [] + }; + const result_routes = []; + const entries = readdirSync(path_given, { withFileTypes: true }); + if (process.env.NODE_ENV === "test") for (let i = entries.length - 1; i > 0; i--) { + const j = Math.floor(Math.random() * (i + 1)); + [entries[i], entries[j]] = [entries[j], entries[i]]; + } + for (const entry of entries) { + const path = nodePath.join(entry.parentPath, entry.name); + if (entry.isFile()) { + let name = entry.name.replace(RE_EXT, ""); + if (name.endsWith(".test")) continue; + let method = "all"; + name = name.replace(RE_METHOD, (_, g1) => { + method = g1.toLowerCase(); + return ""; + }); + const { self, route } = parseFilename(name); + const specificity_position = method === "all" ? WalkSpecificityPosition.FILE_ALL : WalkSpecificityPosition.FILE_METHOD; + if (self) result_routes.push({ + specificity: { + ..._state.specificity, + position: specificity_position + }, + method, + route: _state.route ?? "/", + path + }); + if (route) result_directory.children.push({ + specificity: { + ...route.specificity, + position: specificity_position + }, + method, + route: (_state.route ?? "") + nodePath.sep + route.part, + path + }); + } else if (entry.isDirectory()) { + const { self, route } = parseFilename(entry.name); + if (self) throw new Error(`Invalid directory name "${entry.name}" at "${path}". Can not use optional catch-all in directory name.`); + if (!route) throw new Error(`Invalid directory name "${entry.name}" at "${path}".`); + result_directory.children.push(...readFiles(path, { + route: (_state.route ?? "") + nodePath.sep + route.part, + specificity: { + ...route.specificity, + position: WalkSpecificityPosition.DIRECTORY + } + })); + } + } + sortRoutes(result_directory.children); + const result = [result_directory, ...result_routes]; + if (_state.route === null) sortRoutes(result); + return result; +} +/** +* Sorts the routes in the given result. +* @param result The result to sort. +* @returns - +*/ +function sortRoutes(result) { + return result.sort((a, b) => { + if (a.specificity.type !== b.specificity.type) return a.specificity.type - b.specificity.type; + if (a.specificity.static_length !== b.specificity.static_length) return b.specificity.static_length - a.specificity.static_length; + if (a.specificity.position !== b.specificity.position) return a.specificity.position - b.specificity.position; + return 0; + }); +} + //#endregion //#region src/router.ts /** * Creates new IttyRouter from filesystem. -* @param path The path to scan. +* @param path_root The path to scan. * @returns The new IttyRouter. */ -function createRouter(path) { +function createRouter(path_root) { const router = IttyRouter(); - scanDirectory(router, path); + const routes = readFiles(path_root); + fillRouter(routes, router); return router; } /** +* Attaches routes to IttyRouter. +* @param routes The routes to attach. +* @param router The IttyRouter to attach to. +*/ +function fillRouter(routes, router) { + for (const route of routes) if ("method" in route) router[route.method](route.route, (request) => ({ + async getHandler() { + const module_ = await import(route.path); + return module_.default; + }, + path: route.path, + args: request.params + })); + else if ("children" in route) fillRouter(route.children, router); +} +/** * Fetches data from router. * @param router The router to fetch data from. * @param method The HTTP method. * @param path The path to fetch data from. * @returns The response. */ -function useRouter(router, method, path) { - return router.fetch({ +async function useRouter(router, method, path) { + const url = `file://${path}`; + const result = await router.fetch({ method, - url: `file://${path}` + url }); -} -const REGEXP_FILE_EXTENSION = /\.(js|mjs|cjs|ts)$/; -const REGEXP_TEST_FILE_EXTENSION = /\.test\.(js|mjs|cjs|ts)$/; -const REGEXP_HTTP_METHOD = /(?:^|\.)\[(delete|get|head|options|patch|post|put)]$/; -const REGEXP_PATH_SLUG = /\[(\w+)]/g; -/** -* Scans directory for routes. -* @param router The router to add routes to. -* @param path The path to scan. -* @param [regexp_parts] The parts of the regular expression. -*/ -function scanDirectory(router, path, regexp_parts = [""]) { - const result = readdirSync(path, { withFileTypes: true }); - const routes = { - "0": [], - "1": [], - "2": [], - "3": [] - }; - for (const entry of result) { - const entry_path = nodePath.join(path, entry.name); - if (entry.isFile()) { - let file_name = entry.name; - if (REGEXP_FILE_EXTENSION.test(file_name) && REGEXP_TEST_FILE_EXTENSION.test(file_name) !== true) { - file_name = file_name.replace(REGEXP_FILE_EXTENSION, ""); - let method = "all"; - const method_match = file_name.match(REGEXP_HTTP_METHOD); - const has_method = method_match ? 1 : 0; - if (method_match) { - method = method_match[1]; - file_name = file_name.replace(REGEXP_HTTP_METHOD, ""); - } - const has_slug = REGEXP_PATH_SLUG.test(file_name) ? 2 : 0; - file_name = file_name.replaceAll(REGEXP_PATH_SLUG, ":$1"); - routes[has_method | has_slug]?.push({ - method, - path: [...regexp_parts, file_name].join(nodePath.sep), - module_path: entry_path - }); - } - } else scanDirectory(router, entry_path, [...regexp_parts, entry.name.replaceAll(REGEXP_PATH_SLUG, ":$1")]); - } - for (const route of [ - ...routes[1], - ...routes[3], - ...routes[0], - ...routes[2] - ]) router[route.method](route.path, (r) => { - const response = { - module_path: route.module_path, - args: r.params - }; - return response; + if (result) return result; + const result_unknown = await router.fetch({ + method: "UNKNOWN", + url }); + return result_unknown ? "INVALID" : "NOT_EXISTS"; } +//#endregion +//#region src/driver.ts +var HyperAPIDriver = class extends NeoEventTarget {}; + //#endregion //#region src/utils/methods.ts /** @@ -208,152 +405,79 @@ function isHyperApiMethod(method) { const ENTRYPOINT_PATH = nodePath.dirname(process.argv[1]); var HyperAPI = class { router; - driver; - /** - * Creates a HyperAPI instance. - * @param options The options. - * @param options.driver The driver. - * @param [options.root] The root directory for API methods modules. Default: `hyper-api` directory alongside the entrypoint script. - */ - constructor({ driver, root = nodePath.join(ENTRYPOINT_PATH, "hyper-api") }) { - this.driver = driver; + off; + constructor(driver, root = nodePath.join(ENTRYPOINT_PATH, "hyper-api")) { this.router = createRouter(root); - this.driver.start(async (arg0) => { - const driver_request = arg0; - const [request, module_, response] = await this.processRequest(driver_request); - try { - await this.useHooks(this.handlers.response, { - driver_request, - request, - module: module_, - response - }); - } catch (error) { - console.error("Error in \"response\" hook:"); - console.error(error); + this.off = driver.on("request", async (event) => { + const [request_external, response] = await this.processRequest(event.detail.request); + if (this.hooks_response.length > 0) { + const promises = []; + for (const fn of this.hooks_response) try { + const result = fn({ + ...event.detail.request, + ...request_external + }); + if (result instanceof Promise) promises.push(result.catch(console.error)); + } catch (error) { + console.error(error); + } + await Promise.all(promises); } - return response; + event.detail.callback(response); }); } - handlers = { - beforeRouter: [], - requestTransformer: void 0, - beforeExecute: [], - response: [] - }; - /** - * Adds a hook to be called before request is matched against the file router. - * - * This hook can be set multiple times. Every hook is executed simultaneously. - * - * If error is thrown in this hook, it will abort the request processing and return an error response. - * @param callback The callback function. - * @returns - - */ - onBeforeRouter(callback) { - this.handlers.beforeRouter.push(callback); - return this; - } - /** - * Use this hook add properties to the request before it is send to the API module. - * - * This hook can be set only once. - * - * If error is thrown in this hook, it will abort the request processing and return an error response. - * @param transformer The callback function. - * @returns - - */ - setRequestTransformer(transformer) { - if (this.handlers.requestTransformer) throw new Error("Transformer has already been set."); - this.handlers.requestTransformer = transformer; - return this; - } - /** - * Adds a hook to be called right before the API module is executed. - * - * This hook can be set multiple times. Every hook is executed simultaneously. - * - * If error is thrown in this hook, it will abort the request processing and return an error response. - * @param callback - - * @returns - - */ - onBeforeExecute(callback) { - this.handlers.beforeExecute.push(callback); + hooks_before_router = []; + onBeforeRouter(fn) { + this.hooks_before_router.push(fn); return this; } - /** - * Adds a hook to be called right before the response is sent back to the driver. - * - * This hook can be set multiple times. Every hook is executed simultaneously. - * - * If error is thrown in this hook, it will be printed to the console, but will not prevent response from being sent to the driver. - * @param callback - - * @returns - - */ - onResponse(callback) { - this.handlers.response.push(callback); + hooks_response = []; + onResponse(fn) { + this.hooks_response.push(fn); return this; } - async useHooks(hooks, ctx) { - const promises = []; - for (const hook of hooks) promises.push(hook(ctx)); - await Promise.all(promises); - } - async processRequest(driver_request) { - let request = null; - let module_ = null; + async processRequest(request) { + let request_external = {}; try { - if (driver_request.path.startsWith("/") !== true) driver_request.path = `/${driver_request.path}`; - await this.useHooks(this.handlers.beforeRouter, { driver_request }); - const router_response = await useRouter(this.router, driver_request.method, driver_request.path); - if (!router_response) throw new HyperAPIUnknownMethodError(); - driver_request.args = { - ...driver_request.args, + if (request.path.startsWith("/") !== true) request.path = `/${request.path}`; + for (const fn of this.hooks_before_router) { + const request_added = await fn({ + ...request, + ...request_external + }); + if (request_added !== void 0) request_external = { + ...request_external, + ...request_added + }; + } + const router_response = await useRouter(this.router, request.method, request.path); + if (router_response === "INVALID") throw new HyperAPIUnknownMethodNotAllowedError(); + if (router_response === "NOT_EXISTS") throw new HyperAPIUnknownMethodError(); + if (hasCommonKeys(router_response.args, request.args)) throw new HyperAPIInvalidParametersError(); + request.args = { + ...request.args, ...router_response.args }; - module_ = await import(router_response.module_path); - if (module_.argsValidator) try { - driver_request.args = module_.argsValidator(driver_request.args); - } catch (error) { - console.error(error); - throw new HyperAPIInvalidParametersError(); - } - request = this.handlers.requestTransformer ? await this.handlers.requestTransformer({ - driver_request, - module: module_ - }) : driver_request; - await this.useHooks(this.handlers.beforeExecute, { - request, - module: module_ + const handler = await router_response.getHandler(); + const { response } = await handler._run({ + ...request, + ...request_external }); - const response = await module_.default(request); - return [ - request, - module_, - response - ]; + if (isHyperAPIResponse(response) !== true) throw new TypeError(`Invalid response type from module ${router_response.path}. Expected Response, HyperAPIError, array, object or undefined.`); + return [request_external, response]; } catch (error) { - if (error instanceof HyperAPIError) return [ - request, - module_, - error - ]; + if (error instanceof HyperAPIError) return [request_external, error]; console.error(error); - return [ - request, - module_, - new HyperAPIInternalError() - ]; + return [request_external, new HyperAPIInternalError()]; } } - /** Destroys the HyperAPI instance. */ + module() { + return new HyperAPIModule(); + } destroy() { - this.handlers.beforeRouter.splice(0); - this.handlers.requestTransformer = void 0; - this.handlers.beforeExecute.splice(0); - this.handlers.response.splice(0); + this.off(); } }; //#endregion -export { HyperAPI, HyperAPIAuthorizationError, HyperAPIBusyError, HyperAPICaptchaError, HyperAPIConfirmationError, HyperAPIError, HyperAPIForbiddenError, HyperAPIInternalError, HyperAPIInvalidParametersError, HyperAPIMaintenanceError, HyperAPIMethodNotAllowedError, HyperAPIOTPError, HyperAPIObjectsLimitError, HyperAPIRateLimitError, HyperAPIUnknownMethodError, isHyperApiMethod }; \ No newline at end of file +export { HyperAPI, HyperAPIAuthorizationError, HyperAPIBusyError, HyperAPICaptchaError, HyperAPIConfirmationError, HyperAPIDriver, HyperAPIError, HyperAPIForbiddenError, HyperAPIInternalError, HyperAPIInvalidParametersError, HyperAPIMaintenanceError, HyperAPIMethodNotAllowedError, HyperAPIOTPError, HyperAPIObjectsLimitError, HyperAPIRateLimitError, HyperAPIUnknownMethodError, HyperAPIUnknownMethodNotAllowedError, isHyperApiMethod }; \ No newline at end of file diff --git a/package.json b/package.json index e83ac89..c0de69e 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@hyperapi/core", - "version": "0.4.0-dev", + "version": "0.5.0-dev", "description": "Core package of the HyperAPI project.", "publishConfig": { "access": "public" @@ -21,7 +21,8 @@ "node": ">=21" }, "dependencies": { - "itty-router": "5.0.22" + "itty-router": "5.0.22", + "neoevents": "0.3.0" }, "devDependencies": { "@biomejs/biome": "2.1.1", diff --git a/src/api-errors.ts b/src/api-errors.ts index 97fe156..3e54602 100644 --- a/src/api-errors.ts +++ b/src/api-errors.ts @@ -41,6 +41,14 @@ export class HyperAPIUnknownMethodError< override httpStatus = 404; // Not Found } +export class HyperAPIUnknownMethodNotAllowedError< + D extends HyperAPIErrorData, +> extends HyperAPIError { + override code = 5; + override description = 'Unknown method called'; + override httpStatus = 405; // Method Not Allowed +} + export class HyperAPIObjectsLimitError< D extends HyperAPIErrorData, > extends HyperAPIError { diff --git a/src/driver.ts b/src/driver.ts index 91c004a..e773df0 100644 --- a/src/driver.ts +++ b/src/driver.ts @@ -1,14 +1,18 @@ -import type { Promisable } from 'type-fest'; +import { NeoEvent, NeoEventTarget } from 'neoevents'; import type { HyperAPIRequest } from './request.js'; import type { HyperAPIResponse } from './response.js'; -export type HyperAPIDriverHandler = - (request: R) => Promisable; +export class HyperAPIDriver< + R extends HyperAPIRequest = HyperAPIRequest, +> extends NeoEventTarget<{ + request: NeoEvent<{ + request: R; + callback: (response: HyperAPIResponse) => void; + }>; +}> { + declare R: R; -export interface HyperAPIDriver { - start(handler: HyperAPIDriverHandler): void; - stop(): void; + // override destroy(): void { + // this.destroy(); + // } } - -export type InferDriverRequest = - D extends HyperAPIDriver ? R : never; diff --git a/src/error.test.ts b/src/error.test.ts index fae024b..e9c6132 100644 --- a/src/error.test.ts +++ b/src/error.test.ts @@ -1,8 +1,16 @@ /* eslint-disable @typescript-eslint/no-explicit-any */ import { expect, test } from 'vitest'; +import { HyperAPIBusyError } from './api-errors.js'; import { HyperAPIError } from './error.js'; +test('data', () => { + const error = new HyperAPIBusyError({ + foo: 'bar', + }); + expect(error.data?.foo).toBe('bar'); +}); + class HyperAPICustomError extends HyperAPIError { code = 1001; description = 'This is a custom error'; diff --git a/src/error.ts b/src/error.ts index 46dfdfc..83bb45b 100644 --- a/src/error.ts +++ b/src/error.ts @@ -1,4 +1,4 @@ -import { isRecord } from './utils/is-record.js'; +import { isRecord } from './utils/record.js'; export type HyperAPIErrorData = Record | undefined; diff --git a/src/main.test.ts b/src/main.test.ts index 0171cfb..b3b254a 100644 --- a/src/main.test.ts +++ b/src/main.test.ts @@ -1,225 +1,176 @@ -import { afterAll, describe, expect, test } from 'vitest'; -import { driver, hyperApi } from '../test/setup.js'; +import { describe, expect, expectTypeOf, test, vi } from 'vitest'; +import { HyperAPITestDriver, TestRequest } from '../test/driver.js'; +import { HyperAPI } from './main.js'; + +test('HyperAPI constructor', () => { + const driver = new HyperAPITestDriver(); + const hyperApi = new HyperAPI( + driver, + new URL('../test/hyper-api', import.meta.url).pathname, + ); + + expect(hyperApi).toBeInstanceOf(HyperAPI); -afterAll(() => { hyperApi.destroy(); + driver.destroy(); }); -describe('routing', () => { - describe('methods', () => { - test('ALL with GET', async () => { - const result = await driver.trigger('GET', 'echo', { - name: 'world', - }); +describe('hooks', () => { + describe('onBeforeRouter', () => { + test('run & pass props', async () => { + const mockFnFirst = vi.fn(() => null); + const mockFnSecond = vi.fn(() => null); - expect(result).toStrictEqual([ - true, - { - method: { - expected: 'ALL', - received: 'GET', - }, - message: 'Hello, world!', - }, - ]); - }); + const driver = new HyperAPITestDriver(); + const hyperApi = new HyperAPI( + driver, + new URL('../test/hyper-api', import.meta.url).pathname, + ) + .onBeforeRouter((request) => { + expectTypeOf(request).toExtend(); + expectTypeOf(request.foo).toBeString(); + + mockFnFirst(); + + return { external: 1 }; + }) + .onBeforeRouter((request) => { + expectTypeOf(request).toExtend(); + expectTypeOf(request.external).toBeNumber(); + + mockFnSecond(); - test('ALL with DELETE', async () => { - const result = await driver.trigger('DELETE', 'echo', { - name: 'world', + expect(request.external).toBe(1); + }); + + expect(hyperApi).toBeInstanceOf(HyperAPI); + + const [success, response] = await driver.trigger('GET', '/module/main'); + expect(success).toBe(true); + expect(response).toStrictEqual({ + external: 1, }); - expect(result).toStrictEqual([ - true, - { - method: { - expected: 'ALL', - received: 'DELETE', - }, - message: 'Hello, world!', - }, - ]); + expect(mockFnFirst).toHaveBeenCalledOnce(); + expect(mockFnSecond).toHaveBeenCalledOnce(); + + hyperApi.destroy(); + driver.destroy(); }); - test('POST', async () => { - const result = await driver.trigger('POST', 'echo', { - name: 'deadbeef', + test('throw', async () => { + const mockFn = vi.fn(() => null); + + const driver = new HyperAPITestDriver(); + const hyperApi = new HyperAPI( + driver, + new URL('../test/hyper-api', import.meta.url).pathname, + ).onBeforeRouter((request) => { + expectTypeOf(request).toExtend(); + expectTypeOf(request.foo).toBeString(); + + mockFn(); + + throw new Error('test'); }); - expect(result).toStrictEqual([ - true, - { - method: { - expected: 'POST', - received: 'POST', - }, - message: 'Hello, deadbeef!', - }, - ]); + const [success, response] = await driver.trigger('GET', '/router'); + expect(success).toBe(false); + expect(response).toStrictEqual({ + code: 3, + description: 'Internal error', + }); + + expect(mockFn).toHaveBeenCalledOnce(); + + hyperApi.destroy(); + driver.destroy(); }); }); - describe('slug', () => { - test('in the file name', async () => { - const result = await driver.trigger('GET', 'echo-deadbeef'); - - expect(result).toStrictEqual([ - true, - { - method: { - expected: 'ALL', - received: 'GET', - }, - message: 'Hello, deadbeef!', - }, - ]); + describe('onResponse', () => { + test('run at once', async () => { + const mockFnFirst = vi.fn(() => Date.now()); + let valueFirst: number = Number.NEGATIVE_INFINITY; + const mockFnSecond = vi.fn(() => Date.now()); + let valueSecond: number = Number.POSITIVE_INFINITY; + + const driver = new HyperAPITestDriver(); + const hyperApi = new HyperAPI( + driver, + new URL('../test/hyper-api', import.meta.url).pathname, + ) + .onResponse(async (request) => { + expectTypeOf(request).toExtend(); + expectTypeOf(request.foo).toBeString(); + + valueFirst = mockFnFirst(); + + await new Promise((resolve) => { + setTimeout(resolve, 100); + }); + }) + .onResponse((request) => { + expectTypeOf(request).toExtend(); + expectTypeOf(request.foo).toBeString(); + + valueSecond = mockFnSecond(); + }); + + expect(hyperApi).toBeInstanceOf(HyperAPI); + const [success] = await driver.trigger('GET', '/router'); + expect(success).toBe(true); + expect(mockFnFirst).toHaveBeenCalledOnce(); + expect(mockFnSecond).toHaveBeenCalledOnce(); + expect(valueSecond - valueFirst).toBeLessThanOrEqual(100); + + hyperApi.destroy(); + driver.destroy(); }); - test('in the directory name', async () => { - const result = await driver.trigger('POST', 'user', { - name: 'bax', + describe('throw', () => { + test('sync', async () => { + const mockFn = vi.fn(() => null); + + const driver = new HyperAPITestDriver(); + const hyperApi = new HyperAPI( + driver, + new URL('../test/hyper-api', import.meta.url).pathname, + ).onResponse(() => { + mockFn(); + throw new Error('test'); + }); + + const [success] = await driver.trigger('GET', '/router'); + expect(success).toBe(true); + + expect(mockFn).toHaveBeenCalledOnce(); + + hyperApi.destroy(); + driver.destroy(); }); - expect(result).toStrictEqual([ - true, - { - method: { - expected: 'POST', - received: 'POST', - }, - message: 'Hello, bax!', - }, - ]); + test('async', async () => { + const mockFn = vi.fn(() => null); + + const driver = new HyperAPITestDriver(); + const hyperApi = new HyperAPI( + driver, + new URL('../test/hyper-api', import.meta.url).pathname, + ).onResponse(async () => { + await Promise.resolve(); + mockFn(); + throw new Error('test'); + }); + + const [success] = await driver.trigger('GET', '/router'); + expect(success).toBe(true); + + expect(mockFn).toHaveBeenCalledOnce(); + + hyperApi.destroy(); + driver.destroy(); + }); }); }); - - // test('method in directory', async () => { - // const result = await request( - // 'dir/nested', - // ); - - // expect(result).toStrictEqual([ - // true, - // { - // ok: true, - // }, - // ]); - // }); - - // test('correct request (async)', async () => { - // const result = await request( - // 'echo.async', - // { - // name: 'user', - // }, - // ); - - // expect(result).toStrictEqual([ - // true, - // { - // message: 'Hello, user!', - // }, - // ]); - // }); - - // test('invalid arguments', async () => { - // const result = await request( - // 'echo', - // { - // name: 123, - // }, - // ); - - // expect(result).toStrictEqual([ - // false, - // { - // code: 2, - // description: 'One of the parameters specified was missing or invalid', - // }, - // ]); - // }); - - // test('missing arguments', async () => { - // const result = await request('echo'); - - // expect(result).toStrictEqual([ - // false, - // { - // code: 2, - // description: 'One of the parameters specified was missing or invalid', - // }, - // ]); - // }); - - // test('api error', async () => { - // const result = await request('error.api'); - - // expect(result).toStrictEqual([ - // false, - // { - // code: 10, - // description: 'Endpoint is busy', - // }, - // ]); - // }); - - // test('internal error', async () => { - // const result = await request('error.internal'); - - // expect(result).toStrictEqual([ - // false, - // { - // code: 3, - // description: 'Internal error', - // }, - // ]); - // }); - - // test('invalid return type', async () => { - // const result = await request('error.type'); - - // expect(result).toStrictEqual([ - // false, - // { - // code: 3, - // description: 'Internal error', - // }, - // ]); - // }); - - // test('unknown method', async () => { - // const result = await request('error.unknown-method'); - - // expect(result).toStrictEqual([ - // false, - // { - // code: 5, - // description: 'Unknown method called', - // }, - // ]); - // }); - - // test('invalid import path inside module', async () => { - // const result = await request('error.import.path'); - - // expect(result).toStrictEqual([ - // false, - // { - // code: 3, - // description: 'Internal error', - // }, - // ]); - // }); - - // test('invalid import field inside module', async () => { - // const result = await request('error.import.field'); - - // expect(result).toStrictEqual([ - // false, - // { - // code: 3, - // description: 'Internal error', - // }, - // ]); - // }); }); diff --git a/src/main.ts b/src/main.ts index 302d799..6125a74 100644 --- a/src/main.ts +++ b/src/main.ts @@ -4,270 +4,183 @@ import { HyperAPIInternalError, HyperAPIInvalidParametersError, HyperAPIUnknownMethodError, + HyperAPIUnknownMethodNotAllowedError, } from './api-errors.js'; -import type { HyperAPIDriver, InferDriverRequest } from './driver.js'; +import type { HyperAPIDriver } from './driver.js'; import { HyperAPIError } from './error.js'; -import type { HyperAPIModule } from './module.js'; +import { HyperAPIModule } from './module.js'; import type { HyperAPIRequest } from './request.js'; -import type { HyperAPIResponse } from './response.js'; +import { type HyperAPIResponse, isHyperAPIResponse } from './response.js'; import { createRouter, useRouter } from './router.js'; - -interface HyperAPIHandlers< - D extends HyperAPIDriver, - R extends InferDriverRequest, - M extends HyperAPIModule, -> { - beforeRouter: ((ctx: { - driver_request: Readonly>; - }) => Promisable)[]; - requestTransformer: - | ((ctx: { - driver_request: Readonly>; - module: M; - }) => Promisable) - | void; - beforeExecute: ((ctx: { - request: Readonly; - module: M; - }) => Promisable)[]; - response: ((ctx: { - driver_request: Readonly>; - request: R | null; - module: M | null; - response: HyperAPIResponse; - }) => Promisable)[]; -} +import { + type BaseRecord, + type EmptyObject, + hasCommonKeys, +} from './utils/record.js'; +import type { Extend, Join } from './utils/types.js'; const ENTRYPOINT_PATH = nodePath.dirname(process.argv[1]!); export class HyperAPI< - D extends HyperAPIDriver, - R extends InferDriverRequest, - M extends HyperAPIModule = HyperAPIModule, + Req extends HyperAPIRequest, + ReqExtra extends BaseRecord = EmptyObject, > { - private router: ReturnType; - private driver: D; - - /** - * Creates a HyperAPI instance. - * @param options The options. - * @param options.driver The driver. - * @param [options.root] The root directory for API methods modules. Default: `hyper-api` directory alongside the entrypoint script. - */ - constructor({ - driver, - root = nodePath.join(ENTRYPOINT_PATH, 'hyper-api'), - }: { - driver: D; - root?: string; - }) { - this.driver = driver; + private router; + private off: () => void; + + constructor( + driver: HyperAPIDriver, + root: string = nodePath.join(ENTRYPOINT_PATH, 'hyper-api'), + ) { this.router = createRouter(root); - this.driver.start(async (arg0) => { - const driver_request = arg0 as InferDriverRequest; + this.off = driver.on('request', async (event) => { + const [request_external, response] = await this.processRequest( + event.detail.request, + ); - const [request, module_, response] = - await this.processRequest(driver_request); + if (this.hooks_response.length > 0) { + const promises = []; + for (const fn of this.hooks_response) { + // catch sync errors + try { + const result = fn({ + ...event.detail.request, + ...request_external, + }); + + if (result instanceof Promise) { + // oxlint-disable-next-line no-console + promises.push(result.catch(console.error)); + } + } catch (error) { + // oxlint-disable-next-line no-console + console.error(error); + } + } - // 10. *Core* executes all registered `onResponse` hooks... - try { - await this.useHooks(this.handlers.response, { - driver_request, - request, - module: module_, - response, - }); - } catch (error) { - // oxlint-disable-next-line no-console - console.error('Error in "response" hook:'); - // oxlint-disable-next-line no-console - console.error(error); + await Promise.all(promises); } - // 11. Finally, *Core* passes the response back to the *Driver*... - return response; + event.detail.callback(response); }); } - private handlers: HyperAPIHandlers = { - beforeRouter: [], - requestTransformer: undefined, - beforeExecute: [], - response: [], - }; - - /** - * Adds a hook to be called before request is matched against the file router. - * - * This hook can be set multiple times. Every hook is executed simultaneously. - * - * If error is thrown in this hook, it will abort the request processing and return an error response. - * @param callback The callback function. - * @returns - - */ - onBeforeRouter( - callback: HyperAPIHandlers['beforeRouter'][number], - ): this { - this.handlers.beforeRouter.push(callback); - return this; - } + private hooks_before_router: (( + request: Join, + ) => Promisable)[] = []; - /** - * Use this hook add properties to the request before it is send to the API module. - * - * This hook can be set only once. - * - * If error is thrown in this hook, it will abort the request processing and return an error response. - * @param transformer The callback function. - * @returns - - */ - setRequestTransformer( - transformer: HyperAPIHandlers['requestTransformer'], - ): this { - if (this.handlers.requestTransformer) { - throw new Error('Transformer has already been set.'); - } + onBeforeRouter( + fn: (request: Join) => Promisable, + ) { + this.hooks_before_router.push(fn); - this.handlers.requestTransformer = transformer; - return this; + return this as unknown as HyperAPI>; } - /** - * Adds a hook to be called right before the API module is executed. - * - * This hook can be set multiple times. Every hook is executed simultaneously. - * - * If error is thrown in this hook, it will abort the request processing and return an error response. - * @param callback - - * @returns - - */ - onBeforeExecute( - callback: HyperAPIHandlers['beforeExecute'][number], - ): this { - this.handlers.beforeExecute.push(callback); - return this; - } + private hooks_response: (( + request: Join, + ) => Promisable)[] = []; - /** - * Adds a hook to be called right before the response is sent back to the driver. - * - * This hook can be set multiple times. Every hook is executed simultaneously. - * - * If error is thrown in this hook, it will be printed to the console, but will not prevent response from being sent to the driver. - * @param callback - - * @returns - - */ - onResponse(callback: HyperAPIHandlers['response'][number]): this { - this.handlers.response.push(callback); - return this; - } + onResponse(fn: (request: Join) => Promisable) { + this.hooks_response.push(fn); - // eslint-disable-next-line class-methods-use-this, @typescript-eslint/no-explicit-any - private async useHooks void>( - hooks: H[], - ctx: Parameters[0], - ) { - const promises: Promisable[] = []; - for (const hook of hooks) { - promises.push(hook(ctx)); - } - - await Promise.all(promises); + return this as HyperAPI; } private async processRequest( - driver_request: InferDriverRequest, - ): Promise<[R | null, M | null, HyperAPIResponse]> { + request: Req, + ): Promise<[ReqExtra, HyperAPIResponse]> { // 1. *Driver* creates a request and passes it to the *Core* - let request: R | null = null; - let module_: M | null = null; + // console.log('Processing request:', request); + + let request_external = {} as ReqExtra; try { - if (driver_request.path.startsWith('/') !== true) { - driver_request.path = `/${driver_request.path}`; + if (request.path.startsWith('/') !== true) { + request.path = `/${request.path}`; } // 2. *Core* executes all registered `onBeforeRouter` hooks... - await this.useHooks(this.handlers.beforeRouter, { driver_request }); + for (const fn of this.hooks_before_router) { + // oxlint-disable-next-line no-await-in-loop + const request_added = await fn({ + ...request, + ...request_external, + }); + if (request_added !== undefined) { + request_external = { + ...request_external, + ...request_added, + }; + } + } // 3. *Core* uses a file router... const router_response = await useRouter( this.router, - driver_request.method, - driver_request.path, + request.method, + request.path, ); - if (!router_response) { - // TODO throw HyperAPIMethodNotAllowedError when path exists but HTTP method does not match + + if (router_response === 'INVALID') { + throw new HyperAPIUnknownMethodNotAllowedError(); + } + + if (router_response === 'NOT_EXISTS') { throw new HyperAPIUnknownMethodError(); } // 4. *Core* merges arguments received from the driver with arguments extracted from the request path by the file router - driver_request.args = { - ...driver_request.args, + if (hasCommonKeys(router_response.args, request.args)) { + throw new HyperAPIInvalidParametersError(); + } + + request.args = { + ...request.args, ...router_response.args, - }; + } as Req['args']; // 5. *Core* imports the matched module file... - module_ = (await import(router_response.module_path)) as M; - - // 6. If `argsValidator` is defined, *Core* calls it to validate the request arguments... - if (module_.argsValidator) { - try { - driver_request.args = module_.argsValidator(driver_request.args); - } catch (error) { - // oxlint-disable-next-line no-console - console.error(error); + const handler = await router_response.getHandler(); - throw new HyperAPIInvalidParametersError(); - } - } - - // 7. *Core* calls registered `setRequestTransformer` hook - request = this.handlers.requestTransformer - ? await this.handlers.requestTransformer({ - driver_request, - module: module_, - }) - : (driver_request as R); - - // 8. *Core* executes all registered `onBeforeExecute` hooks... - await this.useHooks(this.handlers.beforeExecute, { - request, - module: module_, + // 6. *Core* calls the module + const { response } = await handler._run({ + ...request, + ...request_external, }); + if (isHyperAPIResponse(response) !== true) { + throw new TypeError( + `Invalid response type from module ${router_response.path}. Expected Response, HyperAPIError, array, object or undefined.`, + ); + } - // 9. *Core* calls the module's `export default function`... - const response = await module_.default(request); - - return [request, module_, response]; + return [request_external, response]; } catch (error) { if (error instanceof HyperAPIError) { - return [request, module_, error]; + return [request_external, error]; } // oxlint-disable-next-line no-console console.error(error); - return [request, module_, new HyperAPIInternalError()]; + return [request_external, new HyperAPIInternalError()]; } } - /** Destroys the HyperAPI instance. */ + // eslint-disable-next-line class-methods-use-this + module(): HyperAPIModule { + return new HyperAPIModule(); + } + destroy(): void { - this.handlers.beforeRouter.splice(0); - this.handlers.requestTransformer = undefined; - this.handlers.beforeExecute.splice(0); - this.handlers.response.splice(0); + this.off(); } } export * from './api-errors.js'; -export type { - HyperAPIDriver, - HyperAPIDriverHandler, -} from './driver.js'; +export { HyperAPIDriver } from './driver.js'; export { HyperAPIError, type HyperAPIErrorData, @@ -275,7 +188,6 @@ export { export type { HyperAPIModule, HyperAPIModuleResponse, - InferModule, } from './module.js'; export type { HyperAPIRequest, diff --git a/src/module.ts b/src/module.ts index 15daf6a..4e516b2 100644 --- a/src/module.ts +++ b/src/module.ts @@ -1,29 +1,83 @@ import type { Promisable } from 'type-fest'; -import type { HyperAPI } from './main.js'; -import type { HyperAPIRequest, HyperAPIRequestArgs } from './request.js'; +import type { HyperAPIRequest } from './request.js'; +import type { BaseRecord } from './utils/record.js'; +import type { Extend, Join } from './utils/types.js'; export type HyperAPIModuleResponse = - | Record | Response + | BaseRecord | unknown[] | undefined; -export interface HyperAPIModule< - R extends HyperAPIRequest, +export class HyperAPIModule< + Req extends HyperAPIRequest, + ReqExtra extends BaseRecord = never, > { - readonly default: (request: R) => Promisable; - readonly argsValidator: ( - args: unknown, - ) => R extends HyperAPIRequest ? A : never; -} + private chain: (( + request: Req & ReqExtra, + ) => Promisable)[] = []; + + use( + fn: (request: Join) => Promisable, + ) { + this.chain.push(fn); + + return this as unknown as HyperAPIModule>; + } + + set( + key: K, + fn: (request: Join) => Promisable, + ): HyperAPIModule>; + set( + key: K, + value: V, + ): HyperAPIModule>; + set(key: K, arg1: unknown) { + this.chain.push(async (request) => { + const value = typeof arg1 === 'function' ? await arg1(request) : arg1; + if (value) { + return { [key]: value }; + } + }); -// export type HyperAPIModuleRequest> = Parameters[0]; + return this as unknown as HyperAPIModule< + Req, + Extend + >; + } -// eslint-disable-next-line @typescript-eslint/no-explicit-any -export type InferModule> = H extends HyperAPI< - infer _D, - infer _R, - infer M -> - ? M - : never; + action( + fn: (request: Join) => Promisable, + ) { + this.chain.push(async (request) => { + const response = await fn(request); + if (response) { + return { response }; + } + }); + + return this as unknown as HyperAPIModule< + Req, + Extend + >; + } + + async _run( + request: Req, + ): Promise, ReqExtra>> { + let request_result = request; + for (const fn of this.chain) { + // oxlint-disable-next-line no-await-in-loop + const request_add = await fn(request_result as Req & ReqExtra); + if (request_add) { + request_result = { + ...request_result, + ...request_add, + }; + } + } + + return request_result as Join; + } +} diff --git a/src/request.ts b/src/request.ts index cdb0b1a..9b86213 100644 --- a/src/request.ts +++ b/src/request.ts @@ -1,7 +1,7 @@ -import type { EmptyObject } from 'type-fest'; import type { HyperAPIMethod } from './utils/methods.js'; +import type { BaseRecord, EmptyObject } from './utils/record.js'; -export type HyperAPIRequestArgs = Record; +export type HyperAPIRequestArgs = BaseRecord; export interface HyperAPIRequest { method: HyperAPIMethod; diff --git a/src/response.ts b/src/response.ts index 8f627ff..7b5eeda 100644 --- a/src/response.ts +++ b/src/response.ts @@ -1,5 +1,23 @@ -import type { HyperAPIError } from './error.js'; +import { HyperAPIError } from './error.js'; import type { HyperAPIModuleResponse } from './module.js'; +import { isRecord } from './utils/record.js'; // eslint-disable-next-line @typescript-eslint/no-explicit-any export type HyperAPIResponse = HyperAPIModuleResponse | HyperAPIError; + +/** + * Checks if the given value is a HyperAPIResponse. + * @param response - The value to check. + * @returns True if the value is a HyperAPIResponse, false otherwise. + */ +export function isHyperAPIResponse( + response: unknown, +): response is HyperAPIResponse { + return ( + response instanceof HyperAPIError || + response instanceof Response || + isRecord(response) || + Array.isArray(response) || + response === undefined + ); +} diff --git a/src/router.ts b/src/router.ts index 27cda7b..afb48d9 100644 --- a/src/router.ts +++ b/src/router.ts @@ -1,28 +1,63 @@ -import { readdirSync } from 'node:fs'; -import nodePath from 'node:path'; import { type IRequest, IttyRouter, type IttyRouterType } from 'itty-router'; +import type { HyperAPIModule } from './module.js'; +import type { HyperAPIRequest } from './request.js'; +import { readFiles, type WalkResult } from './router/file-tree.js'; import type { HyperAPIMethod } from './utils/methods.js'; +import type { BaseRecord } from './utils/record.js'; + +type HyperAPIIttyRouterResponse = { + getHandler: () => Promise>>; + path: string; + args: BaseRecord; +}; +type HyperAPIIttyRouter = IttyRouterType< + IRequest, + [], + HyperAPIIttyRouterResponse +>; /** * Creates new IttyRouter from filesystem. - * @param path The path to scan. + * @param path_root The path to scan. * @returns The new IttyRouter. */ -export function createRouter( - path: string, - // eslint-disable-next-line @typescript-eslint/no-explicit-any -): IttyRouterType { +export function createRouter(path_root: string): HyperAPIIttyRouter { // eslint-disable-next-line new-cap - const router = IttyRouter(); + const router: HyperAPIIttyRouter = IttyRouter(); + + const routes = readFiles(path_root); + // console.log(Bun.inspect(routes, { colors: true })); - scanDirectory(router, path); + fillRouter(routes, router); return router; } -interface RouterResponse { - module_path: string; - args: Record; +/** + * Attaches routes to IttyRouter. + * @param routes The routes to attach. + * @param router The IttyRouter to attach to. + */ +function fillRouter(routes: WalkResult, router: HyperAPIIttyRouter) { + for (const route of routes) { + if ('method' in route) { + // console.log('[fillRouter]', route.method, route.route); + router[route.method]( + route.route, + (request) => + ({ + async getHandler() { + const module_ = await import(route.path); + return module_.default; + }, + path: route.path, + args: request.params, + }) as HyperAPIIttyRouterResponse, + ); + } else if ('children' in route) { + fillRouter(route.children, router); + } + } } /** @@ -32,109 +67,27 @@ interface RouterResponse { * @param path The path to fetch data from. * @returns The response. */ -export function useRouter( - router: IttyRouterType, +export async function useRouter( + router: HyperAPIIttyRouter, method: HyperAPIMethod, path: string, -) { - return router.fetch({ +): Promise { + // console.log('[useRouter]', method, path); + const url = `file://${path}`; + const result = await router.fetch({ method, - url: `file://${path}`, - }) as Promise; -} - -const REGEXP_FILE_EXTENSION = /\.(js|mjs|cjs|ts)$/; -const REGEXP_TEST_FILE_EXTENSION = /\.test\.(js|mjs|cjs|ts)$/; -const REGEXP_HTTP_METHOD = - /(?:^|\.)\[(delete|get|head|options|patch|post|put)]$/; -const REGEXP_PATH_SLUG = /\[(\w+)]/g; - -interface Route { - method: Lowercase> | 'all'; - path: string; - module_path: string; -} - -/** - * Scans directory for routes. - * @param router The router to add routes to. - * @param path The path to scan. - * @param [regexp_parts] The parts of the regular expression. - */ -function scanDirectory( - router: IttyRouterType, - path: string, - regexp_parts: string[] = [''], -) { - const result = readdirSync(path, { - withFileTypes: true, + url, }); - const routes: Record = { - '0': [], // routes with no method and no slug - '1': [], // routes with method and no slug - '2': [], // routes with no method and slug - '3': [], // routes with method and slug - }; - - for (const entry of result) { - const entry_path = nodePath.join(path, entry.name); - - if (entry.isFile()) { - let file_name = entry.name; - if ( - REGEXP_FILE_EXTENSION.test(file_name) && - REGEXP_TEST_FILE_EXTENSION.test(file_name) !== true - ) { - file_name = file_name.replace(REGEXP_FILE_EXTENSION, ''); - - let method: Route['method'] = 'all'; - const method_match = file_name.match(REGEXP_HTTP_METHOD); - const has_method = method_match ? 1 : 0; - if (method_match) { - method = method_match[1] as Exclude; - - file_name = file_name.replace(REGEXP_HTTP_METHOD, ''); - } - - const has_slug = REGEXP_PATH_SLUG.test(file_name) ? 2 : 0; - file_name = file_name.replaceAll(REGEXP_PATH_SLUG, ':$1'); - - // console.log( - // entry_path, - // method, - // [...regexp_parts, file_name].join(nodePath.sep), - // ); - - // eslint-disable-next-line no-bitwise - routes[has_method | has_slug]?.push({ - method, - path: [...regexp_parts, file_name].join(nodePath.sep), - module_path: entry_path, - }); - } - } else { - scanDirectory(router, entry_path, [ - ...regexp_parts, - entry.name.replaceAll(REGEXP_PATH_SLUG, ':$1'), - ]); - } + if (result) { + // console.log('result', result); + return result; } - for (const route of [ - // suppress indexed access to fail - ...routes[1]!, - ...routes[3]!, - ...routes[0]!, - ...routes[2]!, - ]) { - router[route.method](route.path, (r) => { - const response: RouterResponse = { - module_path: route.module_path, - args: r.params, - }; + const result_unknown = await router.fetch({ + method: 'UNKNOWN', + url, + }); - return response; - }); - } + return result_unknown ? 'INVALID' : 'NOT_EXISTS'; } diff --git a/src/router/file-tree.ts b/src/router/file-tree.ts new file mode 100644 index 0000000..d177566 --- /dev/null +++ b/src/router/file-tree.ts @@ -0,0 +1,171 @@ +import { readdirSync } from 'node:fs'; +import nodePath from 'node:path'; +import type { HyperAPIMethod } from '../utils/methods.js'; +import { parseFilename } from './filename.js'; + +const RE_EXT = /\.([cm]?[jt]s)$/i; +const RE_METHOD = /\.(delete|get|head|options|patch|post|put)$/i; + +type WalkState = { + route: string | null; + specificity: WalkSpecificity; +}; +enum WalkSpecificityPosition { + FILE_METHOD = 0, + FILE_ALL = 1, + DIRECTORY = 2, +} +type WalkSpecificity = { + type: number; + static_length: number; + position: WalkSpecificityPosition; +}; +type WalkRoute = { + specificity: WalkSpecificity; + method: Lowercase> | 'all'; + route: string; + path: string; +}; +type WalkDirectory = { + specificity: WalkSpecificity; + children: WalkResult; +}; +export type WalkResult = (WalkRoute | WalkDirectory)[]; + +/** + * Reads the file system and returns a tree of routes sorted correctly. + * @param path_given The directory to read. + * @param _state Internal state. + * @returns - + */ +export function readFiles(path_given: string, _state?: WalkState): WalkResult { + _state ??= { + route: null, + specificity: { + type: 0, + static_length: 0, + position: WalkSpecificityPosition.DIRECTORY, + }, + }; + + const result_directory: WalkDirectory = { + specificity: _state.specificity, + children: [], + }; + const result_routes: WalkRoute[] = []; + + const entries = readdirSync(path_given, { + withFileTypes: true, + }); + // shuffle response if we are running tests + // different filesystems may have different ordering in response + if (process.env.NODE_ENV === 'test') { + for (let i = entries.length - 1; i > 0; i--) { + const j = Math.floor(Math.random() * (i + 1)); // random index from 0 to i + [entries[i], entries[j]] = [entries[j]!, entries[i]!]; // swap elements + } + } + + for (const entry of entries) { + const path = nodePath.join(entry.parentPath, entry.name); + + if (entry.isFile()) { + let name = entry.name.replace(RE_EXT, ''); + + if (name.endsWith('.test')) { + continue; + } + + let method: WalkRoute['method'] = 'all'; + name = name.replace(RE_METHOD, (_, g1) => { + method = g1.toLowerCase() as WalkRoute['method']; + return ''; + }); + + const { self, route } = parseFilename(name); + const specificity_position = + method === 'all' + ? WalkSpecificityPosition.FILE_ALL + : WalkSpecificityPosition.FILE_METHOD; + + if (self) { + result_routes.push({ + specificity: { + ..._state.specificity, + position: specificity_position, + }, + method, + route: _state.route ?? '/', + path, + }); + } + + if (route) { + result_directory.children.push({ + specificity: { + ...route.specificity, + position: specificity_position, + }, + method, + route: (_state.route ?? '') + nodePath.sep + route.part, + path, + }); + } + } else if (entry.isDirectory()) { + const { self, route } = parseFilename(entry.name); + if (self) { + throw new Error( + `Invalid directory name "${entry.name}" at "${path}". Can not use optional catch-all in directory name.`, + ); + } + + if (!route) { + throw new Error(`Invalid directory name "${entry.name}" at "${path}".`); + } + + result_directory.children.push( + ...readFiles(path, { + route: (_state.route ?? '') + nodePath.sep + route.part, + specificity: { + ...route.specificity, + position: WalkSpecificityPosition.DIRECTORY, + }, + }), + ); + } + } + + sortRoutes(result_directory.children); + + const result = [result_directory, ...result_routes]; + // sort result itself if we are at the root + // otherwise, sort will be done by the parent + if (_state.route === null) { + sortRoutes(result); + } + + return result; +} + +/** + * Sorts the routes in the given result. + * @param result The result to sort. + * @returns - + */ +function sortRoutes(result: WalkResult) { + return result.sort((a, b) => { + if (a.specificity.type !== b.specificity.type) { + return a.specificity.type - b.specificity.type; + } + + if (a.specificity.static_length !== b.specificity.static_length) { + return b.specificity.static_length - a.specificity.static_length; + } + + if (a.specificity.position !== b.specificity.position) { + return a.specificity.position - b.specificity.position; + } + + return 0; + }); +} diff --git a/src/router/filename.ts b/src/router/filename.ts new file mode 100644 index 0000000..b89c101 --- /dev/null +++ b/src/router/filename.ts @@ -0,0 +1,106 @@ +const RE_OPTIONAL_CATCH_ALL = /^\[\[\.\.\.([a-z_][\da-z_]*)\]\]$/i; +const RE_GREEDY = /^\[\.\.\.([a-z_][\da-z_]*)\]$/i; + +type ParsedFilename = { + self?: boolean; + route?: { + part: string; + specificity: { + type: number; + static_length: number; + }; + }; +}; + +/** + * Returns specificity for route. + * + * Values: + * - 0: static route (e.g. `/foo`) + * - 1: route with parameter (e.g. `/foo-:id`) + * - 2: route with optional parameter (e.g. `/foo-:id?`) + * - 3: route with greedy parameter (e.g. `/foo-:id+`) + * - 4: (NOT USED) route with wildcard (e.g. `/*`) + * @param name - + * @returns - + */ +export function parseFilename(name: string): ParsedFilename { + if (name === 'index' || name.length === 0) { + return { + self: true, + }; + } + + // Optional catch-all uses double brackets [[...slug]] + const match_optional_catch_all = RE_OPTIONAL_CATCH_ALL.exec(name); + if (match_optional_catch_all) { + // We return a sentinel; caller will produce both '/base' and '/base/:slug+' + return { + self: true, + route: { + part: `:${match_optional_catch_all[1]}+`, + specificity: { + type: 3, + static_length: 0, + }, + }, + }; + } + + // Greedy: [...slug] -> :slug+ + const match_greedy = RE_GREEDY.exec(name); + if (match_greedy) { + return { + route: { + part: `:${match_greedy[1]}+`, + specificity: { + type: 3, + static_length: 0, + }, + }, + }; + } + + let has_optional = false; + let static_length = name.length; + const route_part = name.replaceAll( + /(\[([a-z_][\da-z_]*)\]|\[\[([a-z_][\da-z_]*)\]\])([^\da-z_]|$)/gi, + (...args) => { + static_length -= args[1].length; + + if (args[3] !== undefined) { + has_optional = true; + return `:${args[3]}?${args[4]}`; + } + + return `:${args[2]}${args[4]}`; + }, + ); + + // something was replaced + if (name !== route_part) { + return { + route: { + part: route_part, + specificity: { + type: has_optional ? 2 : 1, + static_length, + }, + }, + }; + } + + if (name.includes('[') !== true) { + return { + route: { + part: route_part, + specificity: { + type: 0, + static_length: 0, + }, + }, + }; + } + + throw new Error(`Invalid filename "${name}".`); +} diff --git a/src/utils/is-record.ts b/src/utils/is-record.ts deleted file mode 100644 index c5b9253..0000000 --- a/src/utils/is-record.ts +++ /dev/null @@ -1,14 +0,0 @@ -/** - * Check if a value is a record. - * @param value - - * @returns - - */ -export function isRecord(value: unknown): value is Record { - return ( - typeof value === 'object' && - value !== null && - !Array.isArray(value) && - value.constructor === Object && - Object.prototype.toString.call(value) === '[object Object]' - ); -} diff --git a/src/utils/record.test.ts b/src/utils/record.test.ts new file mode 100644 index 0000000..c2e826a --- /dev/null +++ b/src/utils/record.test.ts @@ -0,0 +1,24 @@ +import { expect, test } from 'vitest'; +import { hasCommonKeys, isRecord } from './record.js'; + +test('isRecord', () => { + expect(isRecord({})).toBe(true); + expect(isRecord({ a: 1 })).toBe(true); + expect(isRecord({ a: 1, b: '2' })).toBe(true); + expect(isRecord([1, 2, 3])).toBe(false); + expect(isRecord(null)).toBe(false); + expect(isRecord(undefined)).toBe(false); + expect(isRecord(1)).toBe(false); + expect(isRecord('string')).toBe(false); + expect(isRecord(true)).toBe(false); + expect(isRecord(false)).toBe(false); +}); + +test('hasCommonKeys', () => { + expect(hasCommonKeys({ a: 1 }, { a: 2 })).toBe(true); + expect(hasCommonKeys({ a: 1 }, { b: 2 })).toBe(false); + expect(hasCommonKeys({ a: 1 }, { a: 2, b: 3 })).toBe(true); + expect(hasCommonKeys({ a: 1 }, { b: 2, c: 3 })).toBe(false); + expect(hasCommonKeys({ a: 1 }, { a: 2, b: 3, c: 4 })).toBe(true); + expect(hasCommonKeys({ a: 1 }, { b: 2, c: 3, d: 4 })).toBe(false); +}); diff --git a/src/utils/record.ts b/src/utils/record.ts new file mode 100644 index 0000000..fbcb8dd --- /dev/null +++ b/src/utils/record.ts @@ -0,0 +1,33 @@ +export type BaseRecord = Record; +export type EmptyObject = Record; + +/** + * Check if a value is a record. + * @param value - + * @returns - + */ +export function isRecord(value: unknown): value is BaseRecord { + return ( + typeof value === 'object' && + value !== null && + !Array.isArray(value) && + value.constructor === Object && + Object.prototype.toString.call(value) === '[object Object]' + ); +} + +/** + * Checks if there are common keys in both object. + * @param value1 - + * @param value2 - + * @returns - + */ +export function hasCommonKeys(value1: BaseRecord, value2: BaseRecord): boolean { + for (const key of Object.keys(value2)) { + if (Object.hasOwn(value1, key)) { + return true; + } + } + + return false; +} diff --git a/src/utils/types.ts b/src/utils/types.ts new file mode 100644 index 0000000..8cc7682 --- /dev/null +++ b/src/utils/types.ts @@ -0,0 +1,26 @@ +import type { IsEqual, Simplify } from 'type-fest'; +import type { HyperAPIRequest } from '../request.js'; +import type { BaseRecord, EmptyObject } from './record.js'; + +export type Join< + R extends HyperAPIRequest, + ReqExtra extends BaseRecord, +> = R & + ([ReqExtra] extends [never] + ? unknown + : IsEqual extends true + ? unknown + : ReqExtra); +export type Extend< + V1 extends BaseRecord, + V2 extends BaseRecord | void, +> = Simplify< + V2 extends void + ? V1 + : ([V1] extends [never] + ? unknown + : IsEqual extends true + ? unknown + : V1) & + V2 +>; diff --git a/test/driver.ts b/test/driver.ts new file mode 100644 index 0000000..bf66f7c --- /dev/null +++ b/test/driver.ts @@ -0,0 +1,43 @@ +import { HyperAPIDriver } from '../src/driver.js'; +import { HyperAPIError } from '../src/error.js'; +import type { HyperAPIRequest, HyperAPIRequestArgs } from '../src/request.js'; +import type { HyperAPIResponse } from '../src/response.js'; +import type { HyperAPIMethod } from '../src/utils/methods.js'; +import type { EmptyObject } from '../src/utils/record.js'; + +export interface TestRequest + extends HyperAPIRequest { + foo: string; +} + +export class HyperAPITestDriver extends HyperAPIDriver { + async trigger( + method: HyperAPIMethod, + path: string, + args: Record = {}, + ): Promise<[boolean, unknown, { status: number | undefined }]> { + const response = await new Promise((resolve) => { + this.emit('request', { + request: { + method, + path, + args, + foo: 'bar', + }, + callback: resolve, + }); + }); + + if (response instanceof HyperAPIError) { + return [ + false, + response.getResponse(), + { + status: response.httpStatus, + }, + ]; + } + + return [true, response, { status: 200 }]; + } +} diff --git a/test/errors.test.ts b/test/errors.test.ts new file mode 100644 index 0000000..e8d6441 --- /dev/null +++ b/test/errors.test.ts @@ -0,0 +1,22 @@ +import { expect, test } from 'vitest'; +import { driver } from './server.js'; + +test('api', async () => { + const [success, response] = await driver.trigger('GET', 'errors/api'); + + expect(success).toBe(false); + expect(response).toStrictEqual({ + code: 10, + description: 'Endpoint is busy', + }); +}); + +test('internal', async () => { + const [success, response] = await driver.trigger('GET', 'errors/internal'); + + expect(success).toBe(false); + expect(response).toStrictEqual({ + code: 3, + description: 'Internal error', + }); +}); diff --git a/test/hyper-api/echo-[name].ts b/test/hyper-api/echo-[name].ts deleted file mode 100644 index 0ea2788..0000000 --- a/test/hyper-api/echo-[name].ts +++ /dev/null @@ -1,24 +0,0 @@ -/* eslint-disable unicorn/filename-case */ -/* eslint-disable jsdoc/require-jsdoc */ - -import * as v from 'valibot'; -import type { HyperAPIResponse } from '../../src/main.js'; -import type { LocalRequest } from '../setup.js'; - -export default function ( - request: LocalRequest>, -): HyperAPIResponse { - return { - method: { - expected: 'ALL', - received: request.method, - }, - message: `Hello, ${request.args.name}!`, - }; -} - -export const argsValidator = v.parser( - v.strictObject({ - name: v.string(), - }), -); diff --git a/test/hyper-api/echo.[post].ts b/test/hyper-api/echo.[post].ts deleted file mode 100644 index 9503ce6..0000000 --- a/test/hyper-api/echo.[post].ts +++ /dev/null @@ -1,31 +0,0 @@ -/* eslint-disable jsdoc/require-jsdoc */ - -import * as v from 'valibot'; -import type { - HyperAPIRequest, - HyperAPIResponse, - InferModule, -} from '../../src/main.js'; -import type { hyperApi } from '../setup.js'; - -type Module = InferModule; - -export default function ( - request: HyperAPIRequest>, -): HyperAPIResponse { - return { - method: { - expected: 'POST', - received: request.method, - }, - message: `Hello, ${request.args.name}!`, - }; -} - -export const argsValidator = v.parser( - v.strictObject({ - name: v.string(), - }), -); - -export const auth: Module['auth'] = true; diff --git a/test/hyper-api/echo.ts b/test/hyper-api/echo.ts deleted file mode 100644 index b9bc1ae..0000000 --- a/test/hyper-api/echo.ts +++ /dev/null @@ -1,23 +0,0 @@ -/* eslint-disable jsdoc/require-jsdoc */ - -import * as v from 'valibot'; -import type { HyperAPIResponse } from '../../src/main.js'; -import type { LocalRequest } from '../setup.js'; - -export default function ( - request: LocalRequest>, -): HyperAPIResponse { - return { - method: { - expected: 'ALL', - received: request.method, - }, - message: `Hello, ${request.args.name}!`, - }; -} - -export const argsValidator = v.parser( - v.strictObject({ - name: v.string(), - }), -); diff --git a/test/hyper-api/errors/api.test.ts b/test/hyper-api/errors/api.test.ts deleted file mode 100644 index afd45bf..0000000 --- a/test/hyper-api/errors/api.test.ts +++ /dev/null @@ -1,33 +0,0 @@ -import { expect, test } from 'vitest'; -import { driver } from '../../setup.js'; - -test('error', async () => { - const result = await driver.trigger('GET', 'errors/api'); - - expect(result).toStrictEqual([ - false, - { - code: 10, - description: 'Endpoint is busy', - }, - ]); -}); - -test('error with data', async () => { - const result = await driver.trigger('GET', 'errors/api', { - error_data: { - foo: 'bar', - }, - }); - - expect(result).toStrictEqual([ - false, - { - code: 10, - description: 'Endpoint is busy', - data: { - foo: 'bar', - }, - }, - ]); -}); diff --git a/test/hyper-api/errors/api.ts b/test/hyper-api/errors/api.ts index fd9939e..ebbd738 100644 --- a/test/hyper-api/errors/api.ts +++ b/test/hyper-api/errors/api.ts @@ -1,23 +1,6 @@ -/* eslint-disable jsdoc/require-jsdoc */ - -import * as v from 'valibot'; import { HyperAPIBusyError } from '../../../src/api-errors.js'; -import type { LocalRequest } from '../../setup.js'; - -export default function ( - request: LocalRequest>, -) { - throw new HyperAPIBusyError( - Object.keys(request.args.error_data).length > 0 - ? request.args.error_data - : undefined, - ); -} +import { hyperApi } from '../../server.js'; -export const argsValidator = v.parser( - v.strictObject({ - error_data: v.optional(v.record(v.string(), v.any()), () => { - return {}; - }), - }), -); +export default hyperApi.module().action(() => { + throw new HyperAPIBusyError(); +}); diff --git a/test/hyper-api/errors/internal.test.ts b/test/hyper-api/errors/internal.test.ts deleted file mode 100644 index c7ef9b8..0000000 --- a/test/hyper-api/errors/internal.test.ts +++ /dev/null @@ -1,14 +0,0 @@ -import { expect, test } from 'vitest'; -import { driver } from '../../setup.js'; - -test('internal error', async () => { - const result = await driver.trigger('GET', 'errors/internal'); - - expect(result).toStrictEqual([ - false, - { - code: 3, - description: 'Internal error', - }, - ]); -}); diff --git a/test/hyper-api/errors/internal.ts b/test/hyper-api/errors/internal.ts index a45ad0a..e861bfe 100644 --- a/test/hyper-api/errors/internal.ts +++ b/test/hyper-api/errors/internal.ts @@ -1,5 +1,5 @@ -/* eslint-disable jsdoc/require-jsdoc */ +import { hyperApi } from '../../server.js'; -export default function () { - throw new TypeError('This is a test error inside API module.'); -} +export default hyperApi.module().action(() => { + throw new Error('This is a test error inside API module.'); +}); diff --git a/test/hyper-api/module/async.ts b/test/hyper-api/module/async.ts new file mode 100644 index 0000000..6add002 --- /dev/null +++ b/test/hyper-api/module/async.ts @@ -0,0 +1,7 @@ +import { hyperApi } from '../../server.js'; + +export default hyperApi.module().action(async () => { + await Promise.resolve(); + + return { foo: 1 }; +}); diff --git a/test/hyper-api/module/main.ts b/test/hyper-api/module/main.ts new file mode 100644 index 0000000..80c8b12 --- /dev/null +++ b/test/hyper-api/module/main.ts @@ -0,0 +1,7 @@ +import { hyperApi } from '../../server.js'; + +export default hyperApi.module().action((request) => { + return { + external: 'external' in request ? request.external : undefined, + }; +}); diff --git a/test/hyper-api/module/set.ts b/test/hyper-api/module/set.ts new file mode 100644 index 0000000..0ea4fee --- /dev/null +++ b/test/hyper-api/module/set.ts @@ -0,0 +1,10 @@ +import { hyperApi } from '../../server.js'; + +export default hyperApi + .module() + .set('extra', () => 1) + .action((request) => { + return { + extra: request.extra, + }; + }); diff --git a/test/hyper-api/module/set/async.ts b/test/hyper-api/module/set/async.ts new file mode 100644 index 0000000..38a7259 --- /dev/null +++ b/test/hyper-api/module/set/async.ts @@ -0,0 +1,13 @@ +import { hyperApi } from '../../../server.js'; + +export default hyperApi + .module() + .set('extra', async () => { + await Promise.resolve(); + return 1; + }) + .action((request) => { + return { + extra: request.extra, + }; + }); diff --git a/test/hyper-api/module/set/error.ts b/test/hyper-api/module/set/error.ts new file mode 100644 index 0000000..410eaa7 --- /dev/null +++ b/test/hyper-api/module/set/error.ts @@ -0,0 +1,13 @@ +import { HyperAPIInvalidParametersError } from '../../../../src/api-errors.js'; +import { hyperApi } from '../../../server.js'; + +export default hyperApi + .module() + .set('extra', () => { + throw new HyperAPIInvalidParametersError(); + }) + .action((request) => { + return { + extra: request.extra, + }; + }); diff --git a/test/hyper-api/module/set/multiple.ts b/test/hyper-api/module/set/multiple.ts new file mode 100644 index 0000000..f0ef688 --- /dev/null +++ b/test/hyper-api/module/set/multiple.ts @@ -0,0 +1,11 @@ +import { hyperApi } from '../../../server.js'; + +export default hyperApi + .module() + .set('extra1', () => 1 as const) + .set('extra2', () => 2 as const) + .action((request) => { + return { + extra: [request.extra1, request.extra2], + }; + }); diff --git a/test/hyper-api/module/set/override.ts b/test/hyper-api/module/set/override.ts new file mode 100644 index 0000000..881459a --- /dev/null +++ b/test/hyper-api/module/set/override.ts @@ -0,0 +1,11 @@ +import { hyperApi } from '../../../server.js'; + +export default hyperApi + .module() + .set('extra', () => 1) + .set('extra', 2 as const) + .action((request) => { + return { + extra: request.extra, + }; + }); diff --git a/test/hyper-api/module/use.ts b/test/hyper-api/module/use.ts new file mode 100644 index 0000000..63aef32 --- /dev/null +++ b/test/hyper-api/module/use.ts @@ -0,0 +1,12 @@ +import { hyperApi } from '../../server.js'; + +export default hyperApi + .module() + .use(() => { + return { extra: 1 }; + }) + .action((request) => { + return { + extra: request.extra, + }; + }); diff --git a/test/hyper-api/module/use/async.ts b/test/hyper-api/module/use/async.ts new file mode 100644 index 0000000..24ee3b6 --- /dev/null +++ b/test/hyper-api/module/use/async.ts @@ -0,0 +1,15 @@ +import { hyperApi } from '../../../server.js'; + +export default hyperApi + .module() + .use(async () => { + await Promise.resolve(); + return { + extra: 1, + }; + }) + .action((request) => { + return { + extra: request.extra, + }; + }); diff --git a/test/hyper-api/module/use/error.ts b/test/hyper-api/module/use/error.ts new file mode 100644 index 0000000..a211e71 --- /dev/null +++ b/test/hyper-api/module/use/error.ts @@ -0,0 +1,13 @@ +import { HyperAPIInvalidParametersError } from '../../../../src/api-errors.js'; +import { hyperApi } from '../../../server.js'; + +export default hyperApi + .module() + .use(() => { + throw new HyperAPIInvalidParametersError(); + }) + .action((request) => { + return { + foo: request.foo, + }; + }); diff --git a/test/hyper-api/module/use/multiple.ts b/test/hyper-api/module/use/multiple.ts new file mode 100644 index 0000000..9800771 --- /dev/null +++ b/test/hyper-api/module/use/multiple.ts @@ -0,0 +1,16 @@ +import { hyperApi } from '../../../server.js'; + +export default hyperApi + .module() + .use(() => { + return { extra1: 1 }; + }) + .use(async () => { + await Promise.resolve(); + return { extra2: 2 }; + }) + .action((request) => { + return { + extra: [request.extra1, request.extra2], + }; + }); diff --git a/test/hyper-api/module/use/override.ts b/test/hyper-api/module/use/override.ts new file mode 100644 index 0000000..1c80958 --- /dev/null +++ b/test/hyper-api/module/use/override.ts @@ -0,0 +1,15 @@ +import { hyperApi } from '../../../server.js'; + +export default hyperApi + .module() + .use(() => { + return { extra: 1 }; + }) + .use(() => { + return { extra: 2 as const }; + }) + .action((request) => { + return { + extra: request.extra, + }; + }); diff --git a/test/hyper-api/module/void.ts b/test/hyper-api/module/void.ts new file mode 100644 index 0000000..e7a2f92 --- /dev/null +++ b/test/hyper-api/module/void.ts @@ -0,0 +1,5 @@ +import { hyperApi } from '../../server.js'; + +export default hyperApi.module().action(() => { + process.hrtime(); +}); diff --git a/test/hyper-api/only-get.[get].ts b/test/hyper-api/only-get.[get].ts deleted file mode 100644 index 05dd31d..0000000 --- a/test/hyper-api/only-get.[get].ts +++ /dev/null @@ -1,9 +0,0 @@ -/* eslint-disable jsdoc/require-jsdoc */ - -import type { HyperAPIModuleResponse } from '../../src/main.js'; - -export default function (): HyperAPIModuleResponse { - return { - foo: 'bar', - }; -} diff --git a/test/hyper-api/only-get.test.ts b/test/hyper-api/only-get.test.ts deleted file mode 100644 index 8a4a6b6..0000000 --- a/test/hyper-api/only-get.test.ts +++ /dev/null @@ -1,34 +0,0 @@ -import { expect, test } from 'vitest'; -import { driver } from '../setup.js'; - -test('GET', async () => { - const result = await driver.trigger('GET', 'only-get'); - - expect(result).toStrictEqual([ - true, - { - foo: 'bar', - }, - ]); -}); - -// TODO uncomment this test when HyperAPIMethodNotAllowedError supported -// test('POST', async () => { -// const result = await driver.trigger( -// 'POST', -// 'only-get', -// {}, -// true, -// ); - -// expect(result).toStrictEqual([ -// false, -// { -// code: 5, -// description: 'Unknown method called', -// }, -// { -// status: 405, -// }, -// ]); -// }); diff --git a/test/hyper-api/router/all.ts b/test/hyper-api/router/all.ts new file mode 100644 index 0000000..e305655 --- /dev/null +++ b/test/hyper-api/router/all.ts @@ -0,0 +1,9 @@ +import { hyperApi } from '../../server.js'; + +export default hyperApi.module().action((request) => { + return { + path: decodeURIComponent(import.meta.url.split('/hyper-api/')[1]!), + method: request.method, + args: request.args, + }; +}); diff --git a/test/hyper-api/router/catch/[...slug].ts b/test/hyper-api/router/catch/[...slug].ts new file mode 100644 index 0000000..a044295 --- /dev/null +++ b/test/hyper-api/router/catch/[...slug].ts @@ -0,0 +1,9 @@ +import { hyperApi } from '../../../server.js'; + +export default hyperApi.module().action((request) => { + return { + path: decodeURIComponent(import.meta.url.split('/hyper-api/')[1]!), + method: request.method, + args: request.args, + }; +}); diff --git a/test/hyper-api/router/index.get.ts b/test/hyper-api/router/index.get.ts new file mode 100644 index 0000000..e305655 --- /dev/null +++ b/test/hyper-api/router/index.get.ts @@ -0,0 +1,9 @@ +import { hyperApi } from '../../server.js'; + +export default hyperApi.module().action((request) => { + return { + path: decodeURIComponent(import.meta.url.split('/hyper-api/')[1]!), + method: request.method, + args: request.args, + }; +}); diff --git a/test/hyper-api/router/optional-catch/[[...slug]].ts b/test/hyper-api/router/optional-catch/[[...slug]].ts new file mode 100644 index 0000000..a044295 --- /dev/null +++ b/test/hyper-api/router/optional-catch/[[...slug]].ts @@ -0,0 +1,9 @@ +import { hyperApi } from '../../../server.js'; + +export default hyperApi.module().action((request) => { + return { + path: decodeURIComponent(import.meta.url.split('/hyper-api/')[1]!), + method: request.method, + args: request.args, + }; +}); diff --git a/test/hyper-api/router/optional-slug/[name].[[ext]].ts b/test/hyper-api/router/optional-slug/[name].[[ext]].ts new file mode 100644 index 0000000..a044295 --- /dev/null +++ b/test/hyper-api/router/optional-slug/[name].[[ext]].ts @@ -0,0 +1,9 @@ +import { hyperApi } from '../../../server.js'; + +export default hyperApi.module().action((request) => { + return { + path: decodeURIComponent(import.meta.url.split('/hyper-api/')[1]!), + method: request.method, + args: request.args, + }; +}); diff --git a/test/hyper-api/router/slug/[slug].ts b/test/hyper-api/router/slug/[slug].ts new file mode 100644 index 0000000..a044295 --- /dev/null +++ b/test/hyper-api/router/slug/[slug].ts @@ -0,0 +1,9 @@ +import { hyperApi } from '../../../server.js'; + +export default hyperApi.module().action((request) => { + return { + path: decodeURIComponent(import.meta.url.split('/hyper-api/')[1]!), + method: request.method, + args: request.args, + }; +}); diff --git a/test/hyper-api/router/slug/[slug]/x.ts b/test/hyper-api/router/slug/[slug]/x.ts new file mode 100644 index 0000000..7223846 --- /dev/null +++ b/test/hyper-api/router/slug/[slug]/x.ts @@ -0,0 +1,9 @@ +import { hyperApi } from '../../../../server.js'; + +export default hyperApi.module().action((request) => { + return { + path: decodeURIComponent(import.meta.url.split('/hyper-api/')[1]!), + method: request.method, + args: request.args, + }; +}); diff --git a/test/hyper-api/router/slug/x-[slug]-x.ts b/test/hyper-api/router/slug/x-[slug]-x.ts new file mode 100644 index 0000000..542c056 --- /dev/null +++ b/test/hyper-api/router/slug/x-[slug]-x.ts @@ -0,0 +1,11 @@ +/* eslint-disable unicorn/filename-case */ + +import { hyperApi } from '../../../server.js'; + +export default hyperApi.module().action((request) => { + return { + path: decodeURIComponent(import.meta.url.split('/hyper-api/')[1]!), + method: request.method, + args: request.args, + }; +}); diff --git a/test/hyper-api/router/slug/x-[slug].ts b/test/hyper-api/router/slug/x-[slug].ts new file mode 100644 index 0000000..542c056 --- /dev/null +++ b/test/hyper-api/router/slug/x-[slug].ts @@ -0,0 +1,11 @@ +/* eslint-disable unicorn/filename-case */ + +import { hyperApi } from '../../../server.js'; + +export default hyperApi.module().action((request) => { + return { + path: decodeURIComponent(import.meta.url.split('/hyper-api/')[1]!), + method: request.method, + args: request.args, + }; +}); diff --git a/test/hyper-api/router/x.get.ts b/test/hyper-api/router/x.get.ts new file mode 100644 index 0000000..e305655 --- /dev/null +++ b/test/hyper-api/router/x.get.ts @@ -0,0 +1,9 @@ +import { hyperApi } from '../../server.js'; + +export default hyperApi.module().action((request) => { + return { + path: decodeURIComponent(import.meta.url.split('/hyper-api/')[1]!), + method: request.method, + args: request.args, + }; +}); diff --git a/test/hyper-api/user/[post].ts b/test/hyper-api/user/[post].ts deleted file mode 100644 index 2e2eb0b..0000000 --- a/test/hyper-api/user/[post].ts +++ /dev/null @@ -1,23 +0,0 @@ -/* eslint-disable jsdoc/require-jsdoc */ - -import * as v from 'valibot'; -import type { HyperAPIResponse } from '../../../src/main.js'; -import type { LocalRequest } from '../../setup.js'; - -export default function ( - request: LocalRequest>, -): HyperAPIResponse { - return { - method: { - expected: 'POST', - received: request.method, - }, - message: `Hello, ${request.args.name}!`, - }; -} - -export const argsValidator = v.parser( - v.strictObject({ - name: v.string(), - }), -); diff --git a/test/module.test.ts b/test/module.test.ts new file mode 100644 index 0000000..ce79bd8 --- /dev/null +++ b/test/module.test.ts @@ -0,0 +1,90 @@ +import { describe, expect, test } from 'vitest'; +import { driver } from './server.js'; + +describe('action', () => { + test('async', async () => { + const [status, data] = await driver.trigger('GET', 'module/async'); + expect(status).toBe(true); + expect(data).toStrictEqual({ foo: 1 }); + }); + + test('returns void', async () => { + const [status, data] = await driver.trigger('GET', 'module/void'); + expect(status).toBe(true); + expect(data).toBeUndefined(); + }); +}); + +describe('use', () => { + test('single', async () => { + const [status, data] = await driver.trigger('GET', 'module/use'); + expect(status).toBe(true); + expect(data).toStrictEqual({ extra: 1 }); + }); + + test('async', async () => { + const [status, data] = await driver.trigger('GET', 'module/use/async'); + expect(status).toBe(true); + expect(data).toStrictEqual({ extra: 1 }); + }); + + test('multiple', async () => { + const [status, data] = await driver.trigger('GET', 'module/use/multiple'); + expect(status).toBe(true); + expect(data).toStrictEqual({ + extra: [1, 2], + }); + }); + + test('override', async () => { + const [status, data] = await driver.trigger('GET', 'module/use/override'); + expect(status).toBe(true); + expect(data).toStrictEqual({ extra: 2 }); + }); + + test('error', async () => { + const [status, data] = await driver.trigger('GET', 'module/use/error'); + expect(status).toBe(false); + expect(data).toStrictEqual({ + code: 2, + description: 'One of the parameters specified was missing or invalid', + }); + }); +}); + +describe('set', () => { + test('single', async () => { + const [status, data] = await driver.trigger('GET', 'module/set'); + expect(status).toBe(true); + expect(data).toStrictEqual({ extra: 1 }); + }); + + test('async', async () => { + const [status, data] = await driver.trigger('GET', 'module/set/async'); + expect(status).toBe(true); + expect(data).toStrictEqual({ extra: 1 }); + }); + + test('multiple', async () => { + const [status, data] = await driver.trigger('GET', 'module/set/multiple'); + expect(status).toBe(true); + expect(data).toStrictEqual({ + extra: [1, 2], + }); + }); + + test('override', async () => { + const [status, data] = await driver.trigger('GET', 'module/set/override'); + expect(status).toBe(true); + expect(data).toStrictEqual({ extra: 2 }); + }); + + test('error', async () => { + const [status, data] = await driver.trigger('GET', 'module/set/error'); + expect(status).toBe(false); + expect(data).toStrictEqual({ + code: 2, + description: 'One of the parameters specified was missing or invalid', + }); + }); +}); diff --git a/test/router.test.ts b/test/router.test.ts new file mode 100644 index 0000000..03fd8c3 --- /dev/null +++ b/test/router.test.ts @@ -0,0 +1,248 @@ +import { describe, expect, test } from 'vitest'; +import { HyperAPI } from '../src/main.js'; +import { HyperAPITestDriver } from './driver.js'; +import { driver } from './server.js'; + +// eslint-disable-next-line jsdoc/require-jsdoc +function repeat(times: number): number[] { + return Array.from({ length: times }, (_, i) => i); +} + +describe('ALL', () => { + test('with GET', async () => { + const [success, response] = await driver.trigger('GET', 'router/all'); + expect(success).toBe(true); + expect(response).toStrictEqual({ + path: 'router/all.ts', + method: 'GET', + args: {}, + }); + }); + + test('with POST', async () => { + const [success, response] = await driver.trigger('POST', 'router/all'); + expect(success).toBe(true); + expect(response).toStrictEqual({ + path: 'router/all.ts', + method: 'POST', + args: {}, + }); + }); +}); + +describe('only GET', () => { + test('with GET', async () => { + const [success, response] = await driver.trigger('GET', 'router/x'); + expect(success).toBe(true); + expect(response).toStrictEqual({ + path: 'router/x.get.ts', + method: 'GET', + args: {}, + }); + }); + + // test('with POST', async () => { + // const [success, response, http] = await driver.trigger( + // 'POST', + // 'router/x', + // ); + // expect(success).toBe(false); + // expect(response).toStrictEqual({ + // code: 5, + // description: 'Unknown method called', + // }); + // expect(http.status).toBe(405); + // }); +}); + +test('only method in the filename', async () => { + const [success, response] = await driver.trigger('GET', 'router'); + expect(success).toBe(true); + expect(response).toStrictEqual({ + path: 'router/index.get.ts', + method: 'GET', + args: {}, + }); +}); + +// rerun tests shuffling files simulating different order of files returned by filesystem +// our router should order files by their name (static, slugs, optional) +describe.each(repeat(10))('slug', () => { + const driver_slug = new HyperAPITestDriver(); + const _ = new HyperAPI( + driver_slug, + new URL('hyper-api', import.meta.url).pathname, + ); + + test('filename with slug in the end', async () => { + const [success, response] = await driver_slug.trigger( + 'GET', + 'router/slug/x-123', + ); + expect(success).toBe(true); + expect(response).toStrictEqual({ + path: 'router/slug/x-[slug].ts', + method: 'GET', + args: { slug: '123' }, + }); + }); + + test('filename with slug in the middle', async () => { + const [success, response] = await driver_slug.trigger( + 'GET', + 'router/slug/x-123-x', + ); + expect(success).toBe(true); + expect(response).toStrictEqual({ + path: 'router/slug/x-[slug]-x.ts', + method: 'GET', + args: { slug: '123' }, + }); + }); + + test('filename with slug only', async () => { + const [success, response] = await driver_slug.trigger( + 'GET', + 'router/slug/123', + ); + expect(success).toBe(true); + expect(response).toStrictEqual({ + path: 'router/slug/[slug].ts', + method: 'GET', + args: { slug: '123' }, + }); + }); + + test('directory with slug only', async () => { + const [success, response] = await driver_slug.trigger( + 'GET', + 'router/slug/123/x', + ); + expect(success).toBe(true); + expect(response).toStrictEqual({ + path: 'router/slug/[slug]/x.ts', + method: 'GET', + args: { slug: '123' }, + }); + }); +}); + +describe('optional slug', () => { + describe('filename with slug and optional slug', () => { + test('pass optional', async () => { + const [success, response] = await driver.trigger( + 'GET', + 'router/optional-slug/image.png', + ); + expect(success).toBe(true); + expect(response).toStrictEqual({ + path: 'router/optional-slug/[name].[[ext]].ts', + method: 'GET', + args: { name: 'image', ext: 'png' }, + }); + }); + + test('omit optional', async () => { + const [success, response] = await driver.trigger( + 'GET', + 'router/optional-slug/image', + ); + expect(success).toBe(true); + expect(response).toStrictEqual({ + path: 'router/optional-slug/[name].[[ext]].ts', + method: 'GET', + args: { name: 'image', ext: undefined }, + }); + }); + }); +}); + +describe('catch all', () => { + test('0 level deep', async () => { + const [success, response] = await driver.trigger('GET', 'router/catch'); + expect(success).toBe(false); + expect(response).toStrictEqual({ + code: 5, + description: 'Unknown method called', + }); + }); + + test('1 level deep', async () => { + const [success, response] = await driver.trigger('GET', 'router/catch/foo'); + expect(success).toBe(true); + expect(response).toStrictEqual({ + path: 'router/catch/[...slug].ts', + method: 'GET', + args: { slug: 'foo' }, + }); + }); + + test('3 level deep', async () => { + const [success, response] = await driver.trigger( + 'GET', + 'router/catch/foo/bar/baz', + ); + expect(success).toBe(true); + expect(response).toStrictEqual({ + path: 'router/catch/[...slug].ts', + method: 'GET', + args: { slug: 'foo/bar/baz' }, + }); + }); +}); + +describe('optional catch all', () => { + test('0 level deep', async () => { + const [success, response] = await driver.trigger( + 'GET', + 'router/optional-catch', + ); + expect(success).toBe(true); + expect(response).toStrictEqual({ + path: 'router/optional-catch/[[...slug]].ts', + method: 'GET', + args: {}, + }); + }); + + test('1 level deep', async () => { + const [success, response] = await driver.trigger( + 'GET', + 'router/optional-catch/foo', + ); + expect(success).toBe(true); + expect(response).toStrictEqual({ + path: 'router/optional-catch/[[...slug]].ts', + method: 'GET', + args: { slug: 'foo' }, + }); + }); + + test('3 level deep', async () => { + const [success, response] = await driver.trigger( + 'GET', + 'router/optional-catch/foo/bar/baz', + ); + expect(success).toBe(true); + expect(response).toStrictEqual({ + path: 'router/optional-catch/[[...slug]].ts', + method: 'GET', + args: { slug: 'foo/bar/baz' }, + }); + }); +}); + +describe('errors', () => { + test('unknown method', async () => { + const [success, response, http] = await driver.trigger( + 'POST', + 'router/unknown', + ); + expect(success).toBe(false); + expect(response).toStrictEqual({ + code: 5, + description: 'Unknown method called', + }); + expect(http.status).toBe(404); + }); +}); diff --git a/test/server.ts b/test/server.ts new file mode 100644 index 0000000..7ca4a63 --- /dev/null +++ b/test/server.ts @@ -0,0 +1,8 @@ +import { HyperAPI } from '../src/main.js'; +import { HyperAPITestDriver } from './driver.js'; + +export const driver = new HyperAPITestDriver(); +export const hyperApi = new HyperAPI( + driver, + new URL('hyper-api', import.meta.url).pathname, +); diff --git a/test/setup.ts b/test/setup.ts deleted file mode 100644 index 662d3e8..0000000 --- a/test/setup.ts +++ /dev/null @@ -1,149 +0,0 @@ -import type { EmptyObject } from 'type-fest'; -import { - HyperAPI, - type HyperAPIDriver, - type HyperAPIDriverHandler, - HyperAPIError, - type HyperAPIModule, - type HyperAPIRequest, - type HyperAPIRequestArgs, -} from '../src/main.js'; -import type { HyperAPIMethod } from '../src/utils/methods.js'; - -interface DriverRequest - extends HyperAPIRequest { - foo: string; -} - -class HyperAPITestDriver implements HyperAPIDriver { - private handler: HyperAPIDriverHandler | null = null; - - start(handler: HyperAPIDriverHandler): void { - this.handler = handler; - } - - stop(): void { - this.handler = null; - } - - async trigger( - method: HyperAPIMethod, - path: string, - args?: Record, - ): Promise<[boolean, unknown]>; - async trigger( - method: HyperAPIMethod, - path: string, - args: Record, - use_http: true, - ): Promise<[boolean, unknown, { status: number | undefined }]>; - async trigger( - method: HyperAPIMethod, - path: string, - args: Record = {}, - use_http = false, - ): Promise< - [boolean, unknown] | [boolean, unknown, { status: number | undefined }] - > { - if (!this.handler) { - throw new Error('No handler available.'); - } - - const response = await this.handler({ - method, - path, - args, - foo: 'bar', - }); - - if (response instanceof HyperAPIError) { - return use_http === true - ? [ - false, - response.getResponse(), - { - status: response.httpStatus, - }, - ] - : [false, response.getResponse()]; - } - - return [true, response]; - } -} - -export const driver = new HyperAPITestDriver(); - -export interface LocalRequest - extends DriverRequest { - bar: number; -} - -export interface LocalModule extends HyperAPIModule { - auth: boolean; -} - -export const hyperApi_simple = new HyperAPI({ - driver, - root: new URL('../test/hyper-api', import.meta.url).pathname, -}); - -export const hyperApi = new HyperAPI< - typeof driver, - LocalRequest, - LocalModule ->({ - driver, - root: new URL('../test/hyper-api', import.meta.url).pathname, -}); - -/* oxlint-disable no-unused-vars */ - -hyperApi.onBeforeRouter((ctx) => { - const { - foo, - // @ts-expect-error Accessing property that does not exist on DriverRequest - bar, - } = ctx.driver_request; -}); - -hyperApi.setRequestTransformer((ctx) => { - const { - foo, - // @ts-expect-error Accessing property that does not exist on DriverRequest - bar, - } = ctx.driver_request; - - return { - ...ctx.driver_request, - bar: 10, - }; -}); - -hyperApi.onBeforeExecute((ctx) => { - const { foo, bar } = ctx.request; - - const { default: default_, argsValidator, auth } = ctx.module; -}); - -hyperApi.onResponse((ctx) => { - const { - foo, - // @ts-expect-error Accessing property that does not exist on DriverRequest - bar, - } = ctx.driver_request; - - if (ctx.request) { - // eslint-disable-next-line no-shadow - const { foo, bar } = ctx.request; - } - - if (ctx.module) { - const { default: default_, argsValidator, auth } = ctx.module; - } - - // oxlint-disable-next-line no-console - console.log(ctx.response); -}); - -/* oxlint-enable no-unused-vars */ From 19734a315cd60d36bfcdffee4d5bd6e6fef0d2ed Mon Sep 17 00:00:00 2001 From: Daniil Kirichenko Date: Sat, 13 Sep 2025 23:29:03 +0200 Subject: [PATCH 45/57] Update Bun version in CI --- .github/workflows/npm-publish.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/npm-publish.yml b/.github/workflows/npm-publish.yml index f23335f..848f3a2 100644 --- a/.github/workflows/npm-publish.yml +++ b/.github/workflows/npm-publish.yml @@ -13,7 +13,7 @@ on: - 'dev-*' env: - BUN_VERSION: 1.2.2 + BUN_VERSION: 1.2.21 NODE_VERSION: 22 jobs: From 6bdbe9809ed8875e60f26b7318f0f9b8526b5300 Mon Sep 17 00:00:00 2001 From: Daniil Kirichenko Date: Sat, 13 Sep 2025 23:29:49 +0200 Subject: [PATCH 46/57] Removing blank lines from action --- .github/workflows/npm-publish.yml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/workflows/npm-publish.yml b/.github/workflows/npm-publish.yml index 848f3a2..9915e21 100644 --- a/.github/workflows/npm-publish.yml +++ b/.github/workflows/npm-publish.yml @@ -28,7 +28,7 @@ jobs: id: set-tag run: | VERSION=$(node -p "require('./package.json').version") - + if [[ $VERSION == *"-beta."* ]]; then NPM_TAG="beta" elif [[ $VERSION =~ ^[0-9]+\.[0-9]+\.[0-9]+$ ]]; then @@ -36,7 +36,7 @@ jobs: else NPM_TAG="dev" fi - + echo "Detected version: $VERSION" echo "NPM tag: $NPM_TAG" echo "npm_tag=$NPM_TAG" >> $GITHUB_OUTPUT @@ -51,7 +51,7 @@ jobs: else BRANCH=${{ github.base_ref }} fi - + NPM_TAG=${{ steps.set-tag.outputs.npm_tag }} if [[ $BRANCH == "main" && $NPM_TAG != "latest" ]] || \ From f93a9b901b8de38ba71d2cbd640a74a0949cfb77 Mon Sep 17 00:00:00 2001 From: Daniil Kirichenko Date: Sun, 14 Sep 2025 11:26:44 +0200 Subject: [PATCH 47/57] Add `response` property to `onResponse` hook --- dist/main.cjs | 3 ++- dist/main.d.cts | 4 +++- dist/main.d.ts | 4 +++- dist/main.js | 3 ++- src/main.test.ts | 14 +++++++++++++- src/main.ts | 9 +++++++-- 6 files changed, 30 insertions(+), 7 deletions(-) diff --git a/dist/main.cjs b/dist/main.cjs index 63717d3..61f7592 100644 --- a/dist/main.cjs +++ b/dist/main.cjs @@ -438,7 +438,8 @@ var HyperAPI = class { for (const fn of this.hooks_response) try { const result = fn({ ...event.detail.request, - ...request_external + ...request_external, + response }); if (result instanceof Promise) promises.push(result.catch(console.error)); } catch (error) { diff --git a/dist/main.d.cts b/dist/main.d.cts index c4c363a..f3d8f41 100644 --- a/dist/main.d.cts +++ b/dist/main.d.cts @@ -171,7 +171,9 @@ declare class HyperAPI(fn: (request: Join) => Promisable): HyperAPI>; private hooks_response; - onResponse(fn: (request: Join) => Promisable): HyperAPI; + onResponse(fn: (request: Join>) => Promisable): HyperAPI; private processRequest; module(): HyperAPIModule; destroy(): void; diff --git a/dist/main.d.ts b/dist/main.d.ts index 0748031..3bb3716 100644 --- a/dist/main.d.ts +++ b/dist/main.d.ts @@ -171,7 +171,9 @@ declare class HyperAPI(fn: (request: Join) => Promisable): HyperAPI>; private hooks_response; - onResponse(fn: (request: Join) => Promisable): HyperAPI; + onResponse(fn: (request: Join>) => Promisable): HyperAPI; private processRequest; module(): HyperAPIModule; destroy(): void; diff --git a/dist/main.js b/dist/main.js index 745f573..5eeff16 100644 --- a/dist/main.js +++ b/dist/main.js @@ -415,7 +415,8 @@ var HyperAPI = class { for (const fn of this.hooks_response) try { const result = fn({ ...event.detail.request, - ...request_external + ...request_external, + response }); if (result instanceof Promise) promises.push(result.catch(console.error)); } catch (error) { diff --git a/src/main.test.ts b/src/main.test.ts index b3b254a..0ddaf10 100644 --- a/src/main.test.ts +++ b/src/main.test.ts @@ -1,6 +1,6 @@ import { describe, expect, expectTypeOf, test, vi } from 'vitest'; import { HyperAPITestDriver, TestRequest } from '../test/driver.js'; -import { HyperAPI } from './main.js'; +import { HyperAPI, HyperAPIResponse } from './main.js'; test('HyperAPI constructor', () => { const driver = new HyperAPITestDriver(); @@ -103,6 +103,12 @@ describe('hooks', () => { .onResponse(async (request) => { expectTypeOf(request).toExtend(); expectTypeOf(request.foo).toBeString(); + expectTypeOf(request.response).toEqualTypeOf(); + expect(request.response).toStrictEqual({ + path: 'router/index.get.ts', + method: 'GET', + args: {}, + }); valueFirst = mockFnFirst(); @@ -113,6 +119,12 @@ describe('hooks', () => { .onResponse((request) => { expectTypeOf(request).toExtend(); expectTypeOf(request.foo).toBeString(); + expectTypeOf(request.response).toEqualTypeOf(); + expect(request.response).toStrictEqual({ + path: 'router/index.get.ts', + method: 'GET', + args: {}, + }); valueSecond = mockFnSecond(); }); diff --git a/src/main.ts b/src/main.ts index 6125a74..0864e14 100644 --- a/src/main.ts +++ b/src/main.ts @@ -47,6 +47,7 @@ export class HyperAPI< const result = fn({ ...event.detail.request, ...request_external, + response, }); if (result instanceof Promise) { @@ -79,10 +80,14 @@ export class HyperAPI< } private hooks_response: (( - request: Join, + request: Join>, ) => Promisable)[] = []; - onResponse(fn: (request: Join) => Promisable) { + onResponse( + fn: ( + request: Join>, + ) => Promisable, + ) { this.hooks_response.push(fn); return this as HyperAPI; From 24cb31d1ed899cc66ee6c1501a0f049ffe9eedc5 Mon Sep 17 00:00:00 2001 From: Daniil Kirichenko Date: Sun, 14 Sep 2025 11:31:02 +0200 Subject: [PATCH 48/57] Update README --- README.md | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index b0bd87e..1feb9e2 100644 --- a/README.md +++ b/README.md @@ -3,7 +3,7 @@ [![npm version](https://img.shields.io/npm/v/@hyperapi/core.svg)](https://www.npmjs.com/package/@hyperapi/core) [![license](https://img.shields.io/npm/l/@hyperapi/core.svg?color=blue)](https://github.com/hyperapi/core/blob/main/LICENSE) -A powerful, type-safe foundation framework for building APIs with minimal boilerplate. HyperAPI Core provides routing, standardized API method modules, validation, and hooks, while leaving the connection to the outside world to be handled by drivers. +A powerful, type-safe foundation framework for building APIs with minimal boilerplate. HyperAPI Core provides routing, standardized API method modules, and hooks, while leaving the connection to the outside world to be handled by drivers. ## Features @@ -254,11 +254,13 @@ Executed before returning response to driver. Multiple hooks will be executed in This hook has access to request and response returned from API method module. Errors thrown from this hook will not change the response. ```typescript -hyperApi.onResponse((request, response) => { +hyperApi.onResponse((request) => { // request still has "started_at" property added by onBeforeRouter hook // Useful for metrics, logging, and response modification const duration = Date.now() - request.started_at; console.log(`${request.method} ${request.path} completed in ${duration}ms`); + // also, request has "response" property + console.log('response =', request.response); }); ``` From f21b619a90e85661023f2142b5206e5ab3b46ad5 Mon Sep 17 00:00:00 2001 From: Daniil Kirichenko Date: Sun, 14 Sep 2025 15:34:01 +0200 Subject: [PATCH 49/57] Add `/dev` export --- dist/chunk-CUT6urMc.cjs | 30 ++++++++++++ dist/dev.cjs | 20 ++++++++ dist/dev.d.cts | 2 + dist/dev.d.ts | 2 + dist/dev.js | 18 +++++++ dist/driver-BbNhCfMO.d.ts | 94 +++++++++++++++++++++++++++++++++++++ dist/driver-iGRbxqhV.d.cts | 94 +++++++++++++++++++++++++++++++++++++ dist/main.cjs | 50 ++------------------ dist/main.d.cts | 96 ++------------------------------------ dist/main.d.ts | 96 ++------------------------------------ dist/main.js | 18 +------ package.json | 10 +++- src/dev.ts | 13 ++++++ src/main.ts | 19 +------- 14 files changed, 295 insertions(+), 267 deletions(-) create mode 100644 dist/chunk-CUT6urMc.cjs create mode 100644 dist/dev.cjs create mode 100644 dist/dev.d.cts create mode 100644 dist/dev.d.ts create mode 100644 dist/dev.js create mode 100644 dist/driver-BbNhCfMO.d.ts create mode 100644 dist/driver-iGRbxqhV.d.cts create mode 100644 src/dev.ts diff --git a/dist/chunk-CUT6urMc.cjs b/dist/chunk-CUT6urMc.cjs new file mode 100644 index 0000000..8038bcc --- /dev/null +++ b/dist/chunk-CUT6urMc.cjs @@ -0,0 +1,30 @@ +//#region rolldown:runtime +var __create = Object.create; +var __defProp = Object.defineProperty; +var __getOwnPropDesc = Object.getOwnPropertyDescriptor; +var __getOwnPropNames = Object.getOwnPropertyNames; +var __getProtoOf = Object.getPrototypeOf; +var __hasOwnProp = Object.prototype.hasOwnProperty; +var __copyProps = (to, from, except, desc) => { + if (from && typeof from === "object" || typeof from === "function") for (var keys = __getOwnPropNames(from), i = 0, n = keys.length, key; i < n; i++) { + key = keys[i]; + if (!__hasOwnProp.call(to, key) && key !== except) __defProp(to, key, { + get: ((k) => from[k]).bind(null, key), + enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable + }); + } + return to; +}; +var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { + value: mod, + enumerable: true +}) : target, mod)); + +//#endregion + +Object.defineProperty(exports, '__toESM', { + enumerable: true, + get: function () { + return __toESM; + } +}); \ No newline at end of file diff --git a/dist/dev.cjs b/dist/dev.cjs new file mode 100644 index 0000000..db9ac6d --- /dev/null +++ b/dist/dev.cjs @@ -0,0 +1,20 @@ +const require_chunk = require('./chunk-CUT6urMc.cjs'); +const neoevents = require_chunk.__toESM(require("neoevents")); + +//#region src/driver.ts +var HyperAPIDriver = class extends neoevents.NeoEventTarget {}; + +//#endregion +//#region src/utils/methods.ts +/** +* Checks if the given value is a valid HyperAPI method. +* @param method The HTTP method to check. +* @returns - +*/ +function isHyperApiMethod(method) { + return method === "DELETE" || method === "GET" || method === "HEAD" || method === "OPTIONS" || method === "PATCH" || method === "POST" || method === "PUT" || method === "UNKNOWN"; +} + +//#endregion +exports.HyperAPIDriver = HyperAPIDriver; +exports.isHyperApiMethod = isHyperApiMethod; \ No newline at end of file diff --git a/dist/dev.d.cts b/dist/dev.d.cts new file mode 100644 index 0000000..caae2e1 --- /dev/null +++ b/dist/dev.d.cts @@ -0,0 +1,2 @@ +import { BaseRecord, EmptyObject, HyperAPIDriver, HyperAPIErrorData, HyperAPIMethod, HyperAPIModule, HyperAPIModuleResponse, HyperAPIRequest, HyperAPIRequestArgs, HyperAPIResponse, isHyperApiMethod } from "./driver-iGRbxqhV.cjs"; +export { type BaseRecord, type EmptyObject, HyperAPIDriver, type HyperAPIErrorData, type HyperAPIMethod, type HyperAPIModule, type HyperAPIModuleResponse, type HyperAPIRequest, type HyperAPIRequestArgs, type HyperAPIResponse, isHyperApiMethod }; \ No newline at end of file diff --git a/dist/dev.d.ts b/dist/dev.d.ts new file mode 100644 index 0000000..57f149a --- /dev/null +++ b/dist/dev.d.ts @@ -0,0 +1,2 @@ +import { BaseRecord, EmptyObject, HyperAPIDriver, HyperAPIErrorData, HyperAPIMethod, HyperAPIModule, HyperAPIModuleResponse, HyperAPIRequest, HyperAPIRequestArgs, HyperAPIResponse, isHyperApiMethod } from "./driver-BbNhCfMO.js"; +export { type BaseRecord, type EmptyObject, HyperAPIDriver, type HyperAPIErrorData, type HyperAPIMethod, type HyperAPIModule, type HyperAPIModuleResponse, type HyperAPIRequest, type HyperAPIRequestArgs, type HyperAPIResponse, isHyperApiMethod }; \ No newline at end of file diff --git a/dist/dev.js b/dist/dev.js new file mode 100644 index 0000000..47121e6 --- /dev/null +++ b/dist/dev.js @@ -0,0 +1,18 @@ +import { NeoEvent, NeoEventTarget } from "neoevents"; + +//#region src/driver.ts +var HyperAPIDriver = class extends NeoEventTarget {}; + +//#endregion +//#region src/utils/methods.ts +/** +* Checks if the given value is a valid HyperAPI method. +* @param method The HTTP method to check. +* @returns - +*/ +function isHyperApiMethod(method) { + return method === "DELETE" || method === "GET" || method === "HEAD" || method === "OPTIONS" || method === "PATCH" || method === "POST" || method === "PUT" || method === "UNKNOWN"; +} + +//#endregion +export { HyperAPIDriver, isHyperApiMethod }; \ No newline at end of file diff --git a/dist/driver-BbNhCfMO.d.ts b/dist/driver-BbNhCfMO.d.ts new file mode 100644 index 0000000..8bd74e8 --- /dev/null +++ b/dist/driver-BbNhCfMO.d.ts @@ -0,0 +1,94 @@ +import { NeoEvent, NeoEventTarget } from "neoevents"; +import { IsEqual, Promisable, Simplify } from "type-fest"; + +//#region src/utils/methods.d.ts +type HyperAPIMethod = "DELETE" | "GET" | "HEAD" | "OPTIONS" | "PATCH" | "POST" | "PUT" | "UNKNOWN"; +/** +* Checks if the given value is a valid HyperAPI method. +* @param method The HTTP method to check. +* @returns - +*/ +declare function isHyperApiMethod(method: unknown): method is HyperAPIMethod; +//#endregion +//#region src/utils/record.d.ts +type BaseRecord = Record; +type EmptyObject = Record; +/** +* Check if a value is a record. +* @param value - +* @returns - +*/ +//#endregion +//#region src/request.d.ts +type HyperAPIRequestArgs = BaseRecord; +interface HyperAPIRequest { + method: HyperAPIMethod; + path: string; + args: A; +} +//#endregion +//#region src/error.d.ts +type HyperAPIErrorData = Record | undefined; +interface HyperAPIErrorResponse { + code: number; + description?: string; + data?: HyperAPIErrorData; +} +declare class HyperAPIError extends Error { + /** The error code. */ + readonly code: number; + /** The error description. */ + readonly description: string; + /** The error data. */ + readonly data?: D; + /** HTTP status code. */ + readonly httpStatus?: number; + /** HTTP headers to return. */ + readonly httpHeaders?: Record; + constructor(data?: D); + get message(): string; + /** + * Creates response object. + * @returns - + */ + getResponse(): HyperAPIErrorResponse; +} +//#endregion +//#region src/utils/types.d.ts +type Join, ReqExtra extends BaseRecord> = R & ([ReqExtra] extends [never] ? unknown : IsEqual extends true ? unknown : ReqExtra); +type Extend = Simplify extends true ? unknown : V1) & V2>; +//#endregion +//#region src/module.d.ts +type HyperAPIModuleResponse = Response | BaseRecord | unknown[] | undefined; +declare class HyperAPIModule, ReqExtra extends BaseRecord = never> { + private chain; + use(fn: (request: Join) => Promisable): HyperAPIModule>; + set(key: K, fn: (request: Join) => Promisable): HyperAPIModule>; + set(key: K, value: V): HyperAPIModule>; + action(fn: (request: Join) => Promisable): HyperAPIModule>; + _run(request: Req): Promise, ReqExtra>>; +} +//#endregion +//#region src/response.d.ts +type HyperAPIResponse = HyperAPIModuleResponse | HyperAPIError; +/** +* Checks if the given value is a HyperAPIResponse. +* @param response - The value to check. +* @returns True if the value is a HyperAPIResponse, false otherwise. +*/ +//#endregion +//#region src/driver.d.ts +declare class HyperAPIDriver extends NeoEventTarget<{ + request: NeoEvent<{ + request: R; + callback: (response: HyperAPIResponse) => void; + }>; +}> { + R: R; +} +//#endregion +export { BaseRecord, EmptyObject, Extend, HyperAPIDriver, HyperAPIError, HyperAPIErrorData, HyperAPIMethod, HyperAPIModule, HyperAPIModuleResponse, HyperAPIRequest, HyperAPIRequestArgs, HyperAPIResponse, Join, isHyperApiMethod }; \ No newline at end of file diff --git a/dist/driver-iGRbxqhV.d.cts b/dist/driver-iGRbxqhV.d.cts new file mode 100644 index 0000000..8bd74e8 --- /dev/null +++ b/dist/driver-iGRbxqhV.d.cts @@ -0,0 +1,94 @@ +import { NeoEvent, NeoEventTarget } from "neoevents"; +import { IsEqual, Promisable, Simplify } from "type-fest"; + +//#region src/utils/methods.d.ts +type HyperAPIMethod = "DELETE" | "GET" | "HEAD" | "OPTIONS" | "PATCH" | "POST" | "PUT" | "UNKNOWN"; +/** +* Checks if the given value is a valid HyperAPI method. +* @param method The HTTP method to check. +* @returns - +*/ +declare function isHyperApiMethod(method: unknown): method is HyperAPIMethod; +//#endregion +//#region src/utils/record.d.ts +type BaseRecord = Record; +type EmptyObject = Record; +/** +* Check if a value is a record. +* @param value - +* @returns - +*/ +//#endregion +//#region src/request.d.ts +type HyperAPIRequestArgs = BaseRecord; +interface HyperAPIRequest { + method: HyperAPIMethod; + path: string; + args: A; +} +//#endregion +//#region src/error.d.ts +type HyperAPIErrorData = Record | undefined; +interface HyperAPIErrorResponse { + code: number; + description?: string; + data?: HyperAPIErrorData; +} +declare class HyperAPIError extends Error { + /** The error code. */ + readonly code: number; + /** The error description. */ + readonly description: string; + /** The error data. */ + readonly data?: D; + /** HTTP status code. */ + readonly httpStatus?: number; + /** HTTP headers to return. */ + readonly httpHeaders?: Record; + constructor(data?: D); + get message(): string; + /** + * Creates response object. + * @returns - + */ + getResponse(): HyperAPIErrorResponse; +} +//#endregion +//#region src/utils/types.d.ts +type Join, ReqExtra extends BaseRecord> = R & ([ReqExtra] extends [never] ? unknown : IsEqual extends true ? unknown : ReqExtra); +type Extend = Simplify extends true ? unknown : V1) & V2>; +//#endregion +//#region src/module.d.ts +type HyperAPIModuleResponse = Response | BaseRecord | unknown[] | undefined; +declare class HyperAPIModule, ReqExtra extends BaseRecord = never> { + private chain; + use(fn: (request: Join) => Promisable): HyperAPIModule>; + set(key: K, fn: (request: Join) => Promisable): HyperAPIModule>; + set(key: K, value: V): HyperAPIModule>; + action(fn: (request: Join) => Promisable): HyperAPIModule>; + _run(request: Req): Promise, ReqExtra>>; +} +//#endregion +//#region src/response.d.ts +type HyperAPIResponse = HyperAPIModuleResponse | HyperAPIError; +/** +* Checks if the given value is a HyperAPIResponse. +* @param response - The value to check. +* @returns True if the value is a HyperAPIResponse, false otherwise. +*/ +//#endregion +//#region src/driver.d.ts +declare class HyperAPIDriver extends NeoEventTarget<{ + request: NeoEvent<{ + request: R; + callback: (response: HyperAPIResponse) => void; + }>; +}> { + R: R; +} +//#endregion +export { BaseRecord, EmptyObject, Extend, HyperAPIDriver, HyperAPIError, HyperAPIErrorData, HyperAPIMethod, HyperAPIModule, HyperAPIModuleResponse, HyperAPIRequest, HyperAPIRequestArgs, HyperAPIResponse, Join, isHyperApiMethod }; \ No newline at end of file diff --git a/dist/main.cjs b/dist/main.cjs index 61f7592..2b2b7d4 100644 --- a/dist/main.cjs +++ b/dist/main.cjs @@ -1,30 +1,7 @@ -//#region rolldown:runtime -var __create = Object.create; -var __defProp = Object.defineProperty; -var __getOwnPropDesc = Object.getOwnPropertyDescriptor; -var __getOwnPropNames = Object.getOwnPropertyNames; -var __getProtoOf = Object.getPrototypeOf; -var __hasOwnProp = Object.prototype.hasOwnProperty; -var __copyProps = (to, from, except, desc) => { - if (from && typeof from === "object" || typeof from === "function") for (var keys = __getOwnPropNames(from), i = 0, n = keys.length, key; i < n; i++) { - key = keys[i]; - if (!__hasOwnProp.call(to, key) && key !== except) __defProp(to, key, { - get: ((k) => from[k]).bind(null, key), - enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable - }); - } - return to; -}; -var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { - value: mod, - enumerable: true -}) : target, mod)); - -//#endregion -const node_path = __toESM(require("node:path")); -const itty_router = __toESM(require("itty-router")); -const node_fs = __toESM(require("node:fs")); -const neoevents = __toESM(require("neoevents")); +const require_chunk = require('./chunk-CUT6urMc.cjs'); +const node_path = require_chunk.__toESM(require("node:path")); +const itty_router = require_chunk.__toESM(require("itty-router")); +const node_fs = require_chunk.__toESM(require("node:fs")); //#region src/utils/record.ts /** @@ -408,21 +385,6 @@ async function useRouter(router, method, path) { return result_unknown ? "INVALID" : "NOT_EXISTS"; } -//#endregion -//#region src/driver.ts -var HyperAPIDriver = class extends neoevents.NeoEventTarget {}; - -//#endregion -//#region src/utils/methods.ts -/** -* Checks if the given value is a valid HyperAPI method. -* @param method The HTTP method to check. -* @returns - -*/ -function isHyperApiMethod(method) { - return method === "DELETE" || method === "GET" || method === "HEAD" || method === "OPTIONS" || method === "PATCH" || method === "POST" || method === "PUT" || method === "UNKNOWN"; -} - //#endregion //#region src/main.ts const ENTRYPOINT_PATH = node_path.default.dirname(process.argv[1]); @@ -509,7 +471,6 @@ exports.HyperAPIAuthorizationError = HyperAPIAuthorizationError; exports.HyperAPIBusyError = HyperAPIBusyError; exports.HyperAPICaptchaError = HyperAPICaptchaError; exports.HyperAPIConfirmationError = HyperAPIConfirmationError; -exports.HyperAPIDriver = HyperAPIDriver; exports.HyperAPIError = HyperAPIError; exports.HyperAPIForbiddenError = HyperAPIForbiddenError; exports.HyperAPIInternalError = HyperAPIInternalError; @@ -520,5 +481,4 @@ exports.HyperAPIOTPError = HyperAPIOTPError; exports.HyperAPIObjectsLimitError = HyperAPIObjectsLimitError; exports.HyperAPIRateLimitError = HyperAPIRateLimitError; exports.HyperAPIUnknownMethodError = HyperAPIUnknownMethodError; -exports.HyperAPIUnknownMethodNotAllowedError = HyperAPIUnknownMethodNotAllowedError; -exports.isHyperApiMethod = isHyperApiMethod; \ No newline at end of file +exports.HyperAPIUnknownMethodNotAllowedError = HyperAPIUnknownMethodNotAllowedError; \ No newline at end of file diff --git a/dist/main.d.cts b/dist/main.d.cts index f3d8f41..3a75479 100644 --- a/dist/main.d.cts +++ b/dist/main.d.cts @@ -1,96 +1,6 @@ -import { IsEqual, Promisable, Simplify } from "type-fest"; -import { NeoEvent, NeoEventTarget } from "neoevents"; +import { BaseRecord, EmptyObject, Extend, HyperAPIDriver, HyperAPIError, HyperAPIErrorData, HyperAPIModule, HyperAPIRequest, HyperAPIResponse, Join } from "./driver-iGRbxqhV.cjs"; +import { Promisable } from "type-fest"; -//#region src/utils/methods.d.ts -type HyperAPIMethod = "DELETE" | "GET" | "HEAD" | "OPTIONS" | "PATCH" | "POST" | "PUT" | "UNKNOWN"; -/** -* Checks if the given value is a valid HyperAPI method. -* @param method The HTTP method to check. -* @returns - -*/ -declare function isHyperApiMethod(method: unknown): method is HyperAPIMethod; -//#endregion -//#region src/utils/record.d.ts -type BaseRecord = Record; -type EmptyObject = Record; -/** -* Check if a value is a record. -* @param value - -* @returns - -*/ -//#endregion -//#region src/request.d.ts -type HyperAPIRequestArgs = BaseRecord; -interface HyperAPIRequest { - method: HyperAPIMethod; - path: string; - args: A; -} -//#endregion -//#region src/error.d.ts -type HyperAPIErrorData = Record | undefined; -interface HyperAPIErrorResponse { - code: number; - description?: string; - data?: HyperAPIErrorData; -} -declare class HyperAPIError extends Error { - /** The error code. */ - readonly code: number; - /** The error description. */ - readonly description: string; - /** The error data. */ - readonly data?: D; - /** HTTP status code. */ - readonly httpStatus?: number; - /** HTTP headers to return. */ - readonly httpHeaders?: Record; - constructor(data?: D); - get message(): string; - /** - * Creates response object. - * @returns - - */ - getResponse(): HyperAPIErrorResponse; -} -//#endregion -//#region src/utils/types.d.ts -type Join, ReqExtra extends BaseRecord> = R & ([ReqExtra] extends [never] ? unknown : IsEqual extends true ? unknown : ReqExtra); -type Extend = Simplify extends true ? unknown : V1) & V2>; -//#endregion -//#region src/module.d.ts -type HyperAPIModuleResponse = Response | BaseRecord | unknown[] | undefined; -declare class HyperAPIModule, ReqExtra extends BaseRecord = never> { - private chain; - use(fn: (request: Join) => Promisable): HyperAPIModule>; - set(key: K, fn: (request: Join) => Promisable): HyperAPIModule>; - set(key: K, value: V): HyperAPIModule>; - action(fn: (request: Join) => Promisable): HyperAPIModule>; - _run(request: Req): Promise, ReqExtra>>; -} -//#endregion -//#region src/response.d.ts -type HyperAPIResponse = HyperAPIModuleResponse | HyperAPIError; -/** -* Checks if the given value is a HyperAPIResponse. -* @param response - The value to check. -* @returns True if the value is a HyperAPIResponse, false otherwise. -*/ -//#endregion -//#region src/driver.d.ts -declare class HyperAPIDriver extends NeoEventTarget<{ - request: NeoEvent<{ - request: R; - callback: (response: HyperAPIResponse) => void; - }>; -}> { - R: R; -} -//#endregion //#region src/api-errors.d.ts declare class HyperAPIAuthorizationError extends HyperAPIError { code: number; @@ -179,4 +89,4 @@ declare class HyperAPI; -type EmptyObject = Record; -/** -* Check if a value is a record. -* @param value - -* @returns - -*/ -//#endregion -//#region src/request.d.ts -type HyperAPIRequestArgs = BaseRecord; -interface HyperAPIRequest { - method: HyperAPIMethod; - path: string; - args: A; -} -//#endregion -//#region src/error.d.ts -type HyperAPIErrorData = Record | undefined; -interface HyperAPIErrorResponse { - code: number; - description?: string; - data?: HyperAPIErrorData; -} -declare class HyperAPIError extends Error { - /** The error code. */ - readonly code: number; - /** The error description. */ - readonly description: string; - /** The error data. */ - readonly data?: D; - /** HTTP status code. */ - readonly httpStatus?: number; - /** HTTP headers to return. */ - readonly httpHeaders?: Record; - constructor(data?: D); - get message(): string; - /** - * Creates response object. - * @returns - - */ - getResponse(): HyperAPIErrorResponse; -} -//#endregion -//#region src/utils/types.d.ts -type Join, ReqExtra extends BaseRecord> = R & ([ReqExtra] extends [never] ? unknown : IsEqual extends true ? unknown : ReqExtra); -type Extend = Simplify extends true ? unknown : V1) & V2>; -//#endregion -//#region src/module.d.ts -type HyperAPIModuleResponse = Response | BaseRecord | unknown[] | undefined; -declare class HyperAPIModule, ReqExtra extends BaseRecord = never> { - private chain; - use(fn: (request: Join) => Promisable): HyperAPIModule>; - set(key: K, fn: (request: Join) => Promisable): HyperAPIModule>; - set(key: K, value: V): HyperAPIModule>; - action(fn: (request: Join) => Promisable): HyperAPIModule>; - _run(request: Req): Promise, ReqExtra>>; -} -//#endregion -//#region src/response.d.ts -type HyperAPIResponse = HyperAPIModuleResponse | HyperAPIError; -/** -* Checks if the given value is a HyperAPIResponse. -* @param response - The value to check. -* @returns True if the value is a HyperAPIResponse, false otherwise. -*/ -//#endregion -//#region src/driver.d.ts -declare class HyperAPIDriver extends NeoEventTarget<{ - request: NeoEvent<{ - request: R; - callback: (response: HyperAPIResponse) => void; - }>; -}> { - R: R; -} -//#endregion //#region src/api-errors.d.ts declare class HyperAPIAuthorizationError extends HyperAPIError { code: number; @@ -179,4 +89,4 @@ declare class HyperAPI Date: Sun, 14 Sep 2025 15:42:42 +0200 Subject: [PATCH 50/57] Add `emitRequest` method to driver class --- dist/dev.cjs | 11 ++++++++++- dist/dev.d.cts | 2 +- dist/dev.d.ts | 2 +- dist/dev.js | 11 ++++++++++- ...river-BbNhCfMO.d.ts => driver-BOKkIF0R.d.cts} | 2 +- ...river-iGRbxqhV.d.cts => driver-VgPmdOyo.d.ts} | 2 +- dist/main.d.cts | 2 +- dist/main.d.ts | 2 +- src/driver.ts | 11 ++++++++++- test/driver.ts | 16 +++++----------- 10 files changed, 41 insertions(+), 20 deletions(-) rename dist/{driver-BbNhCfMO.d.ts => driver-BOKkIF0R.d.cts} (98%) rename dist/{driver-iGRbxqhV.d.cts => driver-VgPmdOyo.d.ts} (98%) diff --git a/dist/dev.cjs b/dist/dev.cjs index db9ac6d..1121797 100644 --- a/dist/dev.cjs +++ b/dist/dev.cjs @@ -2,7 +2,16 @@ const require_chunk = require('./chunk-CUT6urMc.cjs'); const neoevents = require_chunk.__toESM(require("neoevents")); //#region src/driver.ts -var HyperAPIDriver = class extends neoevents.NeoEventTarget {}; +var HyperAPIDriver = class extends neoevents.NeoEventTarget { + emitRequest(request) { + return new Promise((resolve) => { + this.emit("request", { + request, + callback: resolve + }); + }); + } +}; //#endregion //#region src/utils/methods.ts diff --git a/dist/dev.d.cts b/dist/dev.d.cts index caae2e1..d6ab973 100644 --- a/dist/dev.d.cts +++ b/dist/dev.d.cts @@ -1,2 +1,2 @@ -import { BaseRecord, EmptyObject, HyperAPIDriver, HyperAPIErrorData, HyperAPIMethod, HyperAPIModule, HyperAPIModuleResponse, HyperAPIRequest, HyperAPIRequestArgs, HyperAPIResponse, isHyperApiMethod } from "./driver-iGRbxqhV.cjs"; +import { BaseRecord, EmptyObject, HyperAPIDriver, HyperAPIErrorData, HyperAPIMethod, HyperAPIModule, HyperAPIModuleResponse, HyperAPIRequest, HyperAPIRequestArgs, HyperAPIResponse, isHyperApiMethod } from "./driver-BOKkIF0R.cjs"; export { type BaseRecord, type EmptyObject, HyperAPIDriver, type HyperAPIErrorData, type HyperAPIMethod, type HyperAPIModule, type HyperAPIModuleResponse, type HyperAPIRequest, type HyperAPIRequestArgs, type HyperAPIResponse, isHyperApiMethod }; \ No newline at end of file diff --git a/dist/dev.d.ts b/dist/dev.d.ts index 57f149a..5bb4b92 100644 --- a/dist/dev.d.ts +++ b/dist/dev.d.ts @@ -1,2 +1,2 @@ -import { BaseRecord, EmptyObject, HyperAPIDriver, HyperAPIErrorData, HyperAPIMethod, HyperAPIModule, HyperAPIModuleResponse, HyperAPIRequest, HyperAPIRequestArgs, HyperAPIResponse, isHyperApiMethod } from "./driver-BbNhCfMO.js"; +import { BaseRecord, EmptyObject, HyperAPIDriver, HyperAPIErrorData, HyperAPIMethod, HyperAPIModule, HyperAPIModuleResponse, HyperAPIRequest, HyperAPIRequestArgs, HyperAPIResponse, isHyperApiMethod } from "./driver-VgPmdOyo.js"; export { type BaseRecord, type EmptyObject, HyperAPIDriver, type HyperAPIErrorData, type HyperAPIMethod, type HyperAPIModule, type HyperAPIModuleResponse, type HyperAPIRequest, type HyperAPIRequestArgs, type HyperAPIResponse, isHyperApiMethod }; \ No newline at end of file diff --git a/dist/dev.js b/dist/dev.js index 47121e6..d8ccc96 100644 --- a/dist/dev.js +++ b/dist/dev.js @@ -1,7 +1,16 @@ import { NeoEvent, NeoEventTarget } from "neoevents"; //#region src/driver.ts -var HyperAPIDriver = class extends NeoEventTarget {}; +var HyperAPIDriver = class extends NeoEventTarget { + emitRequest(request) { + return new Promise((resolve) => { + this.emit("request", { + request, + callback: resolve + }); + }); + } +}; //#endregion //#region src/utils/methods.ts diff --git a/dist/driver-BbNhCfMO.d.ts b/dist/driver-BOKkIF0R.d.cts similarity index 98% rename from dist/driver-BbNhCfMO.d.ts rename to dist/driver-BOKkIF0R.d.cts index 8bd74e8..21fbfe9 100644 --- a/dist/driver-BbNhCfMO.d.ts +++ b/dist/driver-BOKkIF0R.d.cts @@ -88,7 +88,7 @@ declare class HyperAPIDriver extend callback: (response: HyperAPIResponse) => void; }>; }> { - R: R; + protected emitRequest(request: R): Promise; } //#endregion export { BaseRecord, EmptyObject, Extend, HyperAPIDriver, HyperAPIError, HyperAPIErrorData, HyperAPIMethod, HyperAPIModule, HyperAPIModuleResponse, HyperAPIRequest, HyperAPIRequestArgs, HyperAPIResponse, Join, isHyperApiMethod }; \ No newline at end of file diff --git a/dist/driver-iGRbxqhV.d.cts b/dist/driver-VgPmdOyo.d.ts similarity index 98% rename from dist/driver-iGRbxqhV.d.cts rename to dist/driver-VgPmdOyo.d.ts index 8bd74e8..21fbfe9 100644 --- a/dist/driver-iGRbxqhV.d.cts +++ b/dist/driver-VgPmdOyo.d.ts @@ -88,7 +88,7 @@ declare class HyperAPIDriver extend callback: (response: HyperAPIResponse) => void; }>; }> { - R: R; + protected emitRequest(request: R): Promise; } //#endregion export { BaseRecord, EmptyObject, Extend, HyperAPIDriver, HyperAPIError, HyperAPIErrorData, HyperAPIMethod, HyperAPIModule, HyperAPIModuleResponse, HyperAPIRequest, HyperAPIRequestArgs, HyperAPIResponse, Join, isHyperApiMethod }; \ No newline at end of file diff --git a/dist/main.d.cts b/dist/main.d.cts index 3a75479..f6aabd5 100644 --- a/dist/main.d.cts +++ b/dist/main.d.cts @@ -1,4 +1,4 @@ -import { BaseRecord, EmptyObject, Extend, HyperAPIDriver, HyperAPIError, HyperAPIErrorData, HyperAPIModule, HyperAPIRequest, HyperAPIResponse, Join } from "./driver-iGRbxqhV.cjs"; +import { BaseRecord, EmptyObject, Extend, HyperAPIDriver, HyperAPIError, HyperAPIErrorData, HyperAPIModule, HyperAPIRequest, HyperAPIResponse, Join } from "./driver-BOKkIF0R.cjs"; import { Promisable } from "type-fest"; //#region src/api-errors.d.ts diff --git a/dist/main.d.ts b/dist/main.d.ts index 6717023..647543c 100644 --- a/dist/main.d.ts +++ b/dist/main.d.ts @@ -1,4 +1,4 @@ -import { BaseRecord, EmptyObject, Extend, HyperAPIDriver, HyperAPIError, HyperAPIErrorData, HyperAPIModule, HyperAPIRequest, HyperAPIResponse, Join } from "./driver-BbNhCfMO.js"; +import { BaseRecord, EmptyObject, Extend, HyperAPIDriver, HyperAPIError, HyperAPIErrorData, HyperAPIModule, HyperAPIRequest, HyperAPIResponse, Join } from "./driver-VgPmdOyo.js"; import { Promisable } from "type-fest"; //#region src/api-errors.d.ts diff --git a/src/driver.ts b/src/driver.ts index e773df0..32b4845 100644 --- a/src/driver.ts +++ b/src/driver.ts @@ -10,7 +10,16 @@ export class HyperAPIDriver< callback: (response: HyperAPIResponse) => void; }>; }> { - declare R: R; + // declare R: R; + + protected emitRequest(request: R): Promise { + return new Promise((resolve) => { + this.emit('request', { + request, + callback: resolve, + }); + }); + } // override destroy(): void { // this.destroy(); diff --git a/test/driver.ts b/test/driver.ts index bf66f7c..0f1f518 100644 --- a/test/driver.ts +++ b/test/driver.ts @@ -1,7 +1,6 @@ import { HyperAPIDriver } from '../src/driver.js'; import { HyperAPIError } from '../src/error.js'; import type { HyperAPIRequest, HyperAPIRequestArgs } from '../src/request.js'; -import type { HyperAPIResponse } from '../src/response.js'; import type { HyperAPIMethod } from '../src/utils/methods.js'; import type { EmptyObject } from '../src/utils/record.js'; @@ -16,16 +15,11 @@ export class HyperAPITestDriver extends HyperAPIDriver { path: string, args: Record = {}, ): Promise<[boolean, unknown, { status: number | undefined }]> { - const response = await new Promise((resolve) => { - this.emit('request', { - request: { - method, - path, - args, - foo: 'bar', - }, - callback: resolve, - }); + const response = await this.emitRequest({ + method, + path, + args, + foo: 'bar', }); if (response instanceof HyperAPIError) { From 5b3d7425be5b8526055aceeb4475a48f430d1736 Mon Sep 17 00:00:00 2001 From: Daniil Kirichenko Date: Sun, 14 Sep 2025 15:48:22 +0200 Subject: [PATCH 51/57] Export `isRecord` function --- dist/dev.cjs | 7 ++-- dist/dev.d.cts | 4 +-- dist/dev.d.ts | 4 +-- dist/dev.js | 3 +- ...er-BOKkIF0R.d.cts => driver-BXowmZ9P.d.ts} | 9 ++++- ...er-VgPmdOyo.d.ts => driver-C8QSD3Oq.d.cts} | 9 ++++- dist/main.cjs | 35 ++++--------------- dist/main.d.cts | 2 +- dist/main.d.ts | 2 +- dist/main.js | 22 +----------- ...chunk-CUT6urMc.cjs => record-D97pjgdq.cjs} | 33 +++++++++++++++++ dist/record-DFObD9mD.js | 22 ++++++++++++ src/dev.ts | 1 + src/main.test.ts | 3 +- 14 files changed, 94 insertions(+), 62 deletions(-) rename dist/{driver-BOKkIF0R.d.cts => driver-BXowmZ9P.d.ts} (94%) rename dist/{driver-VgPmdOyo.d.ts => driver-C8QSD3Oq.d.cts} (94%) rename dist/{chunk-CUT6urMc.cjs => record-D97pjgdq.cjs} (57%) create mode 100644 dist/record-DFObD9mD.js diff --git a/dist/dev.cjs b/dist/dev.cjs index 1121797..5d9cd99 100644 --- a/dist/dev.cjs +++ b/dist/dev.cjs @@ -1,5 +1,5 @@ -const require_chunk = require('./chunk-CUT6urMc.cjs'); -const neoevents = require_chunk.__toESM(require("neoevents")); +const require_record = require('./record-D97pjgdq.cjs'); +const neoevents = require_record.__toESM(require("neoevents")); //#region src/driver.ts var HyperAPIDriver = class extends neoevents.NeoEventTarget { @@ -26,4 +26,5 @@ function isHyperApiMethod(method) { //#endregion exports.HyperAPIDriver = HyperAPIDriver; -exports.isHyperApiMethod = isHyperApiMethod; \ No newline at end of file +exports.isHyperApiMethod = isHyperApiMethod; +exports.isRecord = require_record.isRecord; \ No newline at end of file diff --git a/dist/dev.d.cts b/dist/dev.d.cts index d6ab973..e03a41a 100644 --- a/dist/dev.d.cts +++ b/dist/dev.d.cts @@ -1,2 +1,2 @@ -import { BaseRecord, EmptyObject, HyperAPIDriver, HyperAPIErrorData, HyperAPIMethod, HyperAPIModule, HyperAPIModuleResponse, HyperAPIRequest, HyperAPIRequestArgs, HyperAPIResponse, isHyperApiMethod } from "./driver-BOKkIF0R.cjs"; -export { type BaseRecord, type EmptyObject, HyperAPIDriver, type HyperAPIErrorData, type HyperAPIMethod, type HyperAPIModule, type HyperAPIModuleResponse, type HyperAPIRequest, type HyperAPIRequestArgs, type HyperAPIResponse, isHyperApiMethod }; \ No newline at end of file +import { BaseRecord, EmptyObject, HyperAPIDriver, HyperAPIErrorData, HyperAPIMethod, HyperAPIModule, HyperAPIModuleResponse, HyperAPIRequest, HyperAPIRequestArgs, HyperAPIResponse, isHyperApiMethod, isRecord } from "./driver-C8QSD3Oq.cjs"; +export { type BaseRecord, type EmptyObject, HyperAPIDriver, type HyperAPIErrorData, type HyperAPIMethod, type HyperAPIModule, type HyperAPIModuleResponse, type HyperAPIRequest, type HyperAPIRequestArgs, type HyperAPIResponse, isHyperApiMethod, isRecord }; \ No newline at end of file diff --git a/dist/dev.d.ts b/dist/dev.d.ts index 5bb4b92..f9fab32 100644 --- a/dist/dev.d.ts +++ b/dist/dev.d.ts @@ -1,2 +1,2 @@ -import { BaseRecord, EmptyObject, HyperAPIDriver, HyperAPIErrorData, HyperAPIMethod, HyperAPIModule, HyperAPIModuleResponse, HyperAPIRequest, HyperAPIRequestArgs, HyperAPIResponse, isHyperApiMethod } from "./driver-VgPmdOyo.js"; -export { type BaseRecord, type EmptyObject, HyperAPIDriver, type HyperAPIErrorData, type HyperAPIMethod, type HyperAPIModule, type HyperAPIModuleResponse, type HyperAPIRequest, type HyperAPIRequestArgs, type HyperAPIResponse, isHyperApiMethod }; \ No newline at end of file +import { BaseRecord, EmptyObject, HyperAPIDriver, HyperAPIErrorData, HyperAPIMethod, HyperAPIModule, HyperAPIModuleResponse, HyperAPIRequest, HyperAPIRequestArgs, HyperAPIResponse, isHyperApiMethod, isRecord } from "./driver-BXowmZ9P.js"; +export { type BaseRecord, type EmptyObject, HyperAPIDriver, type HyperAPIErrorData, type HyperAPIMethod, type HyperAPIModule, type HyperAPIModuleResponse, type HyperAPIRequest, type HyperAPIRequestArgs, type HyperAPIResponse, isHyperApiMethod, isRecord }; \ No newline at end of file diff --git a/dist/dev.js b/dist/dev.js index d8ccc96..ab7ac6b 100644 --- a/dist/dev.js +++ b/dist/dev.js @@ -1,3 +1,4 @@ +import { isRecord } from "./record-DFObD9mD.js"; import { NeoEvent, NeoEventTarget } from "neoevents"; //#region src/driver.ts @@ -24,4 +25,4 @@ function isHyperApiMethod(method) { } //#endregion -export { HyperAPIDriver, isHyperApiMethod }; \ No newline at end of file +export { HyperAPIDriver, isHyperApiMethod, isRecord }; \ No newline at end of file diff --git a/dist/driver-BOKkIF0R.d.cts b/dist/driver-BXowmZ9P.d.ts similarity index 94% rename from dist/driver-BOKkIF0R.d.cts rename to dist/driver-BXowmZ9P.d.ts index 21fbfe9..39f7ffc 100644 --- a/dist/driver-BOKkIF0R.d.cts +++ b/dist/driver-BXowmZ9P.d.ts @@ -18,6 +18,13 @@ type EmptyObject = Record; * @param value - * @returns - */ +declare function isRecord(value: unknown): value is BaseRecord; +/** +* Checks if there are common keys in both object. +* @param value1 - +* @param value2 - +* @returns - +*/ //#endregion //#region src/request.d.ts type HyperAPIRequestArgs = BaseRecord; @@ -91,4 +98,4 @@ declare class HyperAPIDriver extend protected emitRequest(request: R): Promise; } //#endregion -export { BaseRecord, EmptyObject, Extend, HyperAPIDriver, HyperAPIError, HyperAPIErrorData, HyperAPIMethod, HyperAPIModule, HyperAPIModuleResponse, HyperAPIRequest, HyperAPIRequestArgs, HyperAPIResponse, Join, isHyperApiMethod }; \ No newline at end of file +export { BaseRecord, EmptyObject, Extend, HyperAPIDriver, HyperAPIError, HyperAPIErrorData, HyperAPIMethod, HyperAPIModule, HyperAPIModuleResponse, HyperAPIRequest, HyperAPIRequestArgs, HyperAPIResponse, Join, isHyperApiMethod, isRecord }; \ No newline at end of file diff --git a/dist/driver-VgPmdOyo.d.ts b/dist/driver-C8QSD3Oq.d.cts similarity index 94% rename from dist/driver-VgPmdOyo.d.ts rename to dist/driver-C8QSD3Oq.d.cts index 21fbfe9..39f7ffc 100644 --- a/dist/driver-VgPmdOyo.d.ts +++ b/dist/driver-C8QSD3Oq.d.cts @@ -18,6 +18,13 @@ type EmptyObject = Record; * @param value - * @returns - */ +declare function isRecord(value: unknown): value is BaseRecord; +/** +* Checks if there are common keys in both object. +* @param value1 - +* @param value2 - +* @returns - +*/ //#endregion //#region src/request.d.ts type HyperAPIRequestArgs = BaseRecord; @@ -91,4 +98,4 @@ declare class HyperAPIDriver extend protected emitRequest(request: R): Promise; } //#endregion -export { BaseRecord, EmptyObject, Extend, HyperAPIDriver, HyperAPIError, HyperAPIErrorData, HyperAPIMethod, HyperAPIModule, HyperAPIModuleResponse, HyperAPIRequest, HyperAPIRequestArgs, HyperAPIResponse, Join, isHyperApiMethod }; \ No newline at end of file +export { BaseRecord, EmptyObject, Extend, HyperAPIDriver, HyperAPIError, HyperAPIErrorData, HyperAPIMethod, HyperAPIModule, HyperAPIModuleResponse, HyperAPIRequest, HyperAPIRequestArgs, HyperAPIResponse, Join, isHyperApiMethod, isRecord }; \ No newline at end of file diff --git a/dist/main.cjs b/dist/main.cjs index 2b2b7d4..6657bc7 100644 --- a/dist/main.cjs +++ b/dist/main.cjs @@ -1,29 +1,8 @@ -const require_chunk = require('./chunk-CUT6urMc.cjs'); -const node_path = require_chunk.__toESM(require("node:path")); -const itty_router = require_chunk.__toESM(require("itty-router")); -const node_fs = require_chunk.__toESM(require("node:fs")); +const require_record = require('./record-D97pjgdq.cjs'); +const node_path = require_record.__toESM(require("node:path")); +const itty_router = require_record.__toESM(require("itty-router")); +const node_fs = require_record.__toESM(require("node:fs")); -//#region src/utils/record.ts -/** -* Check if a value is a record. -* @param value - -* @returns - -*/ -function isRecord(value) { - return typeof value === "object" && value !== null && !Array.isArray(value) && value.constructor === Object && Object.prototype.toString.call(value) === "[object Object]"; -} -/** -* Checks if there are common keys in both object. -* @param value1 - -* @param value2 - -* @returns - -*/ -function hasCommonKeys(value1, value2) { - for (const key of Object.keys(value2)) if (Object.hasOwn(value1, key)) return true; - return false; -} - -//#endregion //#region src/error.ts var HyperAPIError = class extends Error { /** The error code. */ @@ -38,7 +17,7 @@ var HyperAPIError = class extends Error { httpHeaders; constructor(data) { super(); - if (isRecord(data)) this.data = data; + if (require_record.isRecord(data)) this.data = data; } get message() { return `${this.description} (code ${this.code}).`; @@ -171,7 +150,7 @@ var HyperAPIModule = class { * @returns True if the value is a HyperAPIResponse, false otherwise. */ function isHyperAPIResponse(response) { - return response instanceof HyperAPIError || response instanceof Response || isRecord(response) || Array.isArray(response) || response === void 0; + return response instanceof HyperAPIError || response instanceof Response || require_record.isRecord(response) || Array.isArray(response) || response === void 0; } //#endregion @@ -439,7 +418,7 @@ var HyperAPI = class { const router_response = await useRouter(this.router, request.method, request.path); if (router_response === "INVALID") throw new HyperAPIUnknownMethodNotAllowedError(); if (router_response === "NOT_EXISTS") throw new HyperAPIUnknownMethodError(); - if (hasCommonKeys(router_response.args, request.args)) throw new HyperAPIInvalidParametersError(); + if (require_record.hasCommonKeys(router_response.args, request.args)) throw new HyperAPIInvalidParametersError(); request.args = { ...request.args, ...router_response.args diff --git a/dist/main.d.cts b/dist/main.d.cts index f6aabd5..1ea9074 100644 --- a/dist/main.d.cts +++ b/dist/main.d.cts @@ -1,4 +1,4 @@ -import { BaseRecord, EmptyObject, Extend, HyperAPIDriver, HyperAPIError, HyperAPIErrorData, HyperAPIModule, HyperAPIRequest, HyperAPIResponse, Join } from "./driver-BOKkIF0R.cjs"; +import { BaseRecord, EmptyObject, Extend, HyperAPIDriver, HyperAPIError, HyperAPIErrorData, HyperAPIModule, HyperAPIRequest, HyperAPIResponse, Join } from "./driver-C8QSD3Oq.cjs"; import { Promisable } from "type-fest"; //#region src/api-errors.d.ts diff --git a/dist/main.d.ts b/dist/main.d.ts index 647543c..5bea6d6 100644 --- a/dist/main.d.ts +++ b/dist/main.d.ts @@ -1,4 +1,4 @@ -import { BaseRecord, EmptyObject, Extend, HyperAPIDriver, HyperAPIError, HyperAPIErrorData, HyperAPIModule, HyperAPIRequest, HyperAPIResponse, Join } from "./driver-VgPmdOyo.js"; +import { BaseRecord, EmptyObject, Extend, HyperAPIDriver, HyperAPIError, HyperAPIErrorData, HyperAPIModule, HyperAPIRequest, HyperAPIResponse, Join } from "./driver-BXowmZ9P.js"; import { Promisable } from "type-fest"; //#region src/api-errors.d.ts diff --git a/dist/main.js b/dist/main.js index 6ad90f5..159c96b 100644 --- a/dist/main.js +++ b/dist/main.js @@ -1,28 +1,8 @@ +import { hasCommonKeys, isRecord } from "./record-DFObD9mD.js"; import nodePath from "node:path"; import { IttyRouter } from "itty-router"; import { readdirSync } from "node:fs"; -//#region src/utils/record.ts -/** -* Check if a value is a record. -* @param value - -* @returns - -*/ -function isRecord(value) { - return typeof value === "object" && value !== null && !Array.isArray(value) && value.constructor === Object && Object.prototype.toString.call(value) === "[object Object]"; -} -/** -* Checks if there are common keys in both object. -* @param value1 - -* @param value2 - -* @returns - -*/ -function hasCommonKeys(value1, value2) { - for (const key of Object.keys(value2)) if (Object.hasOwn(value1, key)) return true; - return false; -} - -//#endregion //#region src/error.ts var HyperAPIError = class extends Error { /** The error code. */ diff --git a/dist/chunk-CUT6urMc.cjs b/dist/record-D97pjgdq.cjs similarity index 57% rename from dist/chunk-CUT6urMc.cjs rename to dist/record-D97pjgdq.cjs index 8038bcc..6432d49 100644 --- a/dist/chunk-CUT6urMc.cjs +++ b/dist/record-D97pjgdq.cjs @@ -22,9 +22,42 @@ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__ge //#endregion +//#region src/utils/record.ts +/** +* Check if a value is a record. +* @param value - +* @returns - +*/ +function isRecord(value) { + return typeof value === "object" && value !== null && !Array.isArray(value) && value.constructor === Object && Object.prototype.toString.call(value) === "[object Object]"; +} +/** +* Checks if there are common keys in both object. +* @param value1 - +* @param value2 - +* @returns - +*/ +function hasCommonKeys(value1, value2) { + for (const key of Object.keys(value2)) if (Object.hasOwn(value1, key)) return true; + return false; +} + +//#endregion Object.defineProperty(exports, '__toESM', { enumerable: true, get: function () { return __toESM; } +}); +Object.defineProperty(exports, 'hasCommonKeys', { + enumerable: true, + get: function () { + return hasCommonKeys; + } +}); +Object.defineProperty(exports, 'isRecord', { + enumerable: true, + get: function () { + return isRecord; + } }); \ No newline at end of file diff --git a/dist/record-DFObD9mD.js b/dist/record-DFObD9mD.js new file mode 100644 index 0000000..44f6073 --- /dev/null +++ b/dist/record-DFObD9mD.js @@ -0,0 +1,22 @@ +//#region src/utils/record.ts +/** +* Check if a value is a record. +* @param value - +* @returns - +*/ +function isRecord(value) { + return typeof value === "object" && value !== null && !Array.isArray(value) && value.constructor === Object && Object.prototype.toString.call(value) === "[object Object]"; +} +/** +* Checks if there are common keys in both object. +* @param value1 - +* @param value2 - +* @returns - +*/ +function hasCommonKeys(value1, value2) { + for (const key of Object.keys(value2)) if (Object.hasOwn(value1, key)) return true; + return false; +} + +//#endregion +export { hasCommonKeys, isRecord }; \ No newline at end of file diff --git a/src/dev.ts b/src/dev.ts index fd0db41..bd5398d 100644 --- a/src/dev.ts +++ b/src/dev.ts @@ -11,3 +11,4 @@ export type { export type { HyperAPIResponse } from './response.js'; export { type HyperAPIMethod, isHyperApiMethod } from './utils/methods.js'; export type { BaseRecord, EmptyObject } from './utils/record.js'; +export { isRecord } from './utils/record.js'; diff --git a/src/main.test.ts b/src/main.test.ts index 0ddaf10..ec602e4 100644 --- a/src/main.test.ts +++ b/src/main.test.ts @@ -1,6 +1,7 @@ import { describe, expect, expectTypeOf, test, vi } from 'vitest'; import { HyperAPITestDriver, TestRequest } from '../test/driver.js'; -import { HyperAPI, HyperAPIResponse } from './main.js'; +import { HyperAPI } from './main.js'; +import { HyperAPIResponse } from './response.js'; test('HyperAPI constructor', () => { const driver = new HyperAPITestDriver(); From 2a09af19fdfea47f43975c17b63d3ad61c49a092 Mon Sep 17 00:00:00 2001 From: Daniil Kirichenko Date: Sun, 14 Sep 2025 23:13:51 +0200 Subject: [PATCH 52/57] Fix types --- dist/dev.d.cts | 2 +- dist/dev.d.ts | 2 +- ...er-BXowmZ9P.d.ts => driver-4SJMBJcu.d.cts} | 14 +++--- ...er-C8QSD3Oq.d.cts => driver-zDj9PJPr.d.ts} | 14 +++--- dist/main.d.cts | 2 +- dist/main.d.ts | 2 +- src/main.ts | 4 +- src/module.ts | 4 +- src/utils/record.ts | 2 +- src/utils/types.test.ts | 26 +++++++++++ src/utils/types.ts | 43 +++++++++++-------- test/hyper-api/module/use/error.ts | 4 +- 12 files changed, 78 insertions(+), 41 deletions(-) rename dist/{driver-BXowmZ9P.d.ts => driver-4SJMBJcu.d.cts} (83%) rename dist/{driver-C8QSD3Oq.d.cts => driver-zDj9PJPr.d.ts} (83%) create mode 100644 src/utils/types.test.ts diff --git a/dist/dev.d.cts b/dist/dev.d.cts index e03a41a..7b19295 100644 --- a/dist/dev.d.cts +++ b/dist/dev.d.cts @@ -1,2 +1,2 @@ -import { BaseRecord, EmptyObject, HyperAPIDriver, HyperAPIErrorData, HyperAPIMethod, HyperAPIModule, HyperAPIModuleResponse, HyperAPIRequest, HyperAPIRequestArgs, HyperAPIResponse, isHyperApiMethod, isRecord } from "./driver-C8QSD3Oq.cjs"; +import { BaseRecord, EmptyObject, HyperAPIDriver, HyperAPIErrorData, HyperAPIMethod, HyperAPIModule, HyperAPIModuleResponse, HyperAPIRequest, HyperAPIRequestArgs, HyperAPIResponse, isHyperApiMethod, isRecord } from "./driver-4SJMBJcu.cjs"; export { type BaseRecord, type EmptyObject, HyperAPIDriver, type HyperAPIErrorData, type HyperAPIMethod, type HyperAPIModule, type HyperAPIModuleResponse, type HyperAPIRequest, type HyperAPIRequestArgs, type HyperAPIResponse, isHyperApiMethod, isRecord }; \ No newline at end of file diff --git a/dist/dev.d.ts b/dist/dev.d.ts index f9fab32..75c3463 100644 --- a/dist/dev.d.ts +++ b/dist/dev.d.ts @@ -1,2 +1,2 @@ -import { BaseRecord, EmptyObject, HyperAPIDriver, HyperAPIErrorData, HyperAPIMethod, HyperAPIModule, HyperAPIModuleResponse, HyperAPIRequest, HyperAPIRequestArgs, HyperAPIResponse, isHyperApiMethod, isRecord } from "./driver-BXowmZ9P.js"; +import { BaseRecord, EmptyObject, HyperAPIDriver, HyperAPIErrorData, HyperAPIMethod, HyperAPIModule, HyperAPIModuleResponse, HyperAPIRequest, HyperAPIRequestArgs, HyperAPIResponse, isHyperApiMethod, isRecord } from "./driver-zDj9PJPr.js"; export { type BaseRecord, type EmptyObject, HyperAPIDriver, type HyperAPIErrorData, type HyperAPIMethod, type HyperAPIModule, type HyperAPIModuleResponse, type HyperAPIRequest, type HyperAPIRequestArgs, type HyperAPIResponse, isHyperApiMethod, isRecord }; \ No newline at end of file diff --git a/dist/driver-BXowmZ9P.d.ts b/dist/driver-4SJMBJcu.d.cts similarity index 83% rename from dist/driver-BXowmZ9P.d.ts rename to dist/driver-4SJMBJcu.d.cts index 39f7ffc..c2ddb9f 100644 --- a/dist/driver-BXowmZ9P.d.ts +++ b/dist/driver-4SJMBJcu.d.cts @@ -1,5 +1,5 @@ import { NeoEvent, NeoEventTarget } from "neoevents"; -import { IsEqual, Promisable, Simplify } from "type-fest"; +import { IsEqual, Merge, Promisable, Simplify } from "type-fest"; //#region src/utils/methods.d.ts type HyperAPIMethod = "DELETE" | "GET" | "HEAD" | "OPTIONS" | "PATCH" | "POST" | "PUT" | "UNKNOWN"; @@ -11,7 +11,7 @@ type HyperAPIMethod = "DELETE" | "GET" | "HEAD" | "OPTIONS" | "PATCH" | "POST" | declare function isHyperApiMethod(method: unknown): method is HyperAPIMethod; //#endregion //#region src/utils/record.d.ts -type BaseRecord = Record; +type BaseRecord = Record; type EmptyObject = Record; /** * Check if a value is a record. @@ -62,8 +62,10 @@ declare class HyperAPIError extends Err } //#endregion //#region src/utils/types.d.ts -type Join, ReqExtra extends BaseRecord> = R & ([ReqExtra] extends [never] ? unknown : IsEqual extends true ? unknown : ReqExtra); -type Extend = Simplify extends true ? unknown : V1) & V2>; +type IsRecord = T extends void ? false : [T] extends [never] ? false : IsEqual extends true ? false : true; +type Join, ReqExtra extends BaseRecord> = IsRecord extends true ? Merge : R; +type SimpleMerge = Simplify<{ [Key in keyof Destination as Key extends keyof Source ? never : Key]: Destination[Key] } & Source>; +type Extend = IsRecord extends true ? IsRecord extends true ? SimpleMerge : V1 : IsRecord extends true ? Exclude : EmptyObject; //#endregion //#region src/module.d.ts type HyperAPIModuleResponse = Response | BaseRecord | unknown[] | undefined; @@ -75,9 +77,9 @@ declare class HyperAPIModule, ReqExtra e action(fn: (request: Join) => Promisable): HyperAPIModule>; - _run(request: Req): Promise, ReqExtra>>; + }>>>; } //#endregion //#region src/response.d.ts diff --git a/dist/driver-C8QSD3Oq.d.cts b/dist/driver-zDj9PJPr.d.ts similarity index 83% rename from dist/driver-C8QSD3Oq.d.cts rename to dist/driver-zDj9PJPr.d.ts index 39f7ffc..c2ddb9f 100644 --- a/dist/driver-C8QSD3Oq.d.cts +++ b/dist/driver-zDj9PJPr.d.ts @@ -1,5 +1,5 @@ import { NeoEvent, NeoEventTarget } from "neoevents"; -import { IsEqual, Promisable, Simplify } from "type-fest"; +import { IsEqual, Merge, Promisable, Simplify } from "type-fest"; //#region src/utils/methods.d.ts type HyperAPIMethod = "DELETE" | "GET" | "HEAD" | "OPTIONS" | "PATCH" | "POST" | "PUT" | "UNKNOWN"; @@ -11,7 +11,7 @@ type HyperAPIMethod = "DELETE" | "GET" | "HEAD" | "OPTIONS" | "PATCH" | "POST" | declare function isHyperApiMethod(method: unknown): method is HyperAPIMethod; //#endregion //#region src/utils/record.d.ts -type BaseRecord = Record; +type BaseRecord = Record; type EmptyObject = Record; /** * Check if a value is a record. @@ -62,8 +62,10 @@ declare class HyperAPIError extends Err } //#endregion //#region src/utils/types.d.ts -type Join, ReqExtra extends BaseRecord> = R & ([ReqExtra] extends [never] ? unknown : IsEqual extends true ? unknown : ReqExtra); -type Extend = Simplify extends true ? unknown : V1) & V2>; +type IsRecord = T extends void ? false : [T] extends [never] ? false : IsEqual extends true ? false : true; +type Join, ReqExtra extends BaseRecord> = IsRecord extends true ? Merge : R; +type SimpleMerge = Simplify<{ [Key in keyof Destination as Key extends keyof Source ? never : Key]: Destination[Key] } & Source>; +type Extend = IsRecord extends true ? IsRecord extends true ? SimpleMerge : V1 : IsRecord extends true ? Exclude : EmptyObject; //#endregion //#region src/module.d.ts type HyperAPIModuleResponse = Response | BaseRecord | unknown[] | undefined; @@ -75,9 +77,9 @@ declare class HyperAPIModule, ReqExtra e action(fn: (request: Join) => Promisable): HyperAPIModule>; - _run(request: Req): Promise, ReqExtra>>; + }>>>; } //#endregion //#region src/response.d.ts diff --git a/dist/main.d.cts b/dist/main.d.cts index 1ea9074..3ab2ada 100644 --- a/dist/main.d.cts +++ b/dist/main.d.cts @@ -1,4 +1,4 @@ -import { BaseRecord, EmptyObject, Extend, HyperAPIDriver, HyperAPIError, HyperAPIErrorData, HyperAPIModule, HyperAPIRequest, HyperAPIResponse, Join } from "./driver-C8QSD3Oq.cjs"; +import { BaseRecord, EmptyObject, Extend, HyperAPIDriver, HyperAPIError, HyperAPIErrorData, HyperAPIModule, HyperAPIRequest, HyperAPIResponse, Join } from "./driver-4SJMBJcu.cjs"; import { Promisable } from "type-fest"; //#region src/api-errors.d.ts diff --git a/dist/main.d.ts b/dist/main.d.ts index 5bea6d6..479faec 100644 --- a/dist/main.d.ts +++ b/dist/main.d.ts @@ -1,4 +1,4 @@ -import { BaseRecord, EmptyObject, Extend, HyperAPIDriver, HyperAPIError, HyperAPIErrorData, HyperAPIModule, HyperAPIRequest, HyperAPIResponse, Join } from "./driver-BXowmZ9P.js"; +import { BaseRecord, EmptyObject, Extend, HyperAPIDriver, HyperAPIError, HyperAPIErrorData, HyperAPIModule, HyperAPIRequest, HyperAPIResponse, Join } from "./driver-zDj9PJPr.js"; import { Promisable } from "type-fest"; //#region src/api-errors.d.ts diff --git a/src/main.ts b/src/main.ts index ab6a862..4126442 100644 --- a/src/main.ts +++ b/src/main.ts @@ -79,9 +79,7 @@ export class HyperAPI< return this as unknown as HyperAPI>; } - private hooks_response: (( - request: Join>, - ) => Promisable)[] = []; + private hooks_response: Parameters[0][] = []; onResponse( fn: ( diff --git a/src/module.ts b/src/module.ts index 4e516b2..25d84d7 100644 --- a/src/module.ts +++ b/src/module.ts @@ -65,7 +65,7 @@ export class HyperAPIModule< async _run( request: Req, - ): Promise, ReqExtra>> { + ): Promise>> { let request_result = request; for (const fn of this.chain) { // oxlint-disable-next-line no-await-in-loop @@ -78,6 +78,6 @@ export class HyperAPIModule< } } - return request_result as Join; + return request_result as Awaited>; } } diff --git a/src/utils/record.ts b/src/utils/record.ts index fbcb8dd..ef92494 100644 --- a/src/utils/record.ts +++ b/src/utils/record.ts @@ -1,4 +1,4 @@ -export type BaseRecord = Record; +export type BaseRecord = Record; export type EmptyObject = Record; /** diff --git a/src/utils/types.test.ts b/src/utils/types.test.ts new file mode 100644 index 0000000..ab4c643 --- /dev/null +++ b/src/utils/types.test.ts @@ -0,0 +1,26 @@ +import { expectTypeOf, test } from 'vitest'; +import { EmptyObject } from './record.js'; +import { Extend } from './types.js'; + +test('Extend', () => { + expectTypeOf>().toEqualTypeOf<{ + a: string; + b: number; + }>(); + + expectTypeOf>().toEqualTypeOf<{ + a: number; + }>(); + + expectTypeOf>().toEqualTypeOf<{ + a: string; + }>(); + + expectTypeOf>().toEqualTypeOf<{ + a: string; + }>(); + + expectTypeOf>().toEqualTypeOf(); + + expectTypeOf>().toEqualTypeOf<{ a: string }>(); +}); diff --git a/src/utils/types.ts b/src/utils/types.ts index 8cc7682..d940c5f 100644 --- a/src/utils/types.ts +++ b/src/utils/types.ts @@ -1,26 +1,35 @@ -import type { IsEqual, Simplify } from 'type-fest'; +import type { IsEqual, Merge, Simplify } from 'type-fest'; import type { HyperAPIRequest } from '../request.js'; import type { BaseRecord, EmptyObject } from './record.js'; +type IsRecord = T extends void + ? false + : [T] extends [never] + ? false + : IsEqual extends true + ? false + : true; + export type Join< R extends HyperAPIRequest, ReqExtra extends BaseRecord, -> = R & - ([ReqExtra] extends [never] - ? unknown - : IsEqual extends true - ? unknown - : ReqExtra); +> = IsRecord extends true ? Merge : R; + +type SimpleMerge = Simplify< + { + [Key in keyof Destination as Key extends keyof Source + ? never + : Key]: Destination[Key]; + } & Source +>; + export type Extend< V1 extends BaseRecord, V2 extends BaseRecord | void, -> = Simplify< - V2 extends void - ? V1 - : ([V1] extends [never] - ? unknown - : IsEqual extends true - ? unknown - : V1) & - V2 ->; +> = IsRecord extends true + ? IsRecord extends true + ? SimpleMerge + : V1 + : IsRecord extends true + ? Exclude + : EmptyObject; diff --git a/test/hyper-api/module/use/error.ts b/test/hyper-api/module/use/error.ts index a211e71..797e5cf 100644 --- a/test/hyper-api/module/use/error.ts +++ b/test/hyper-api/module/use/error.ts @@ -6,8 +6,8 @@ export default hyperApi .use(() => { throw new HyperAPIInvalidParametersError(); }) - .action((request) => { + .action((_request) => { return { - foo: request.foo, + foo: 'request is never', }; }); From 5acc4c8f59d81a1c28bcfafaf34526c50e16c311 Mon Sep 17 00:00:00 2001 From: Daniil Kirichenko Date: Sun, 14 Sep 2025 23:23:11 +0200 Subject: [PATCH 53/57] Fix types (again) --- dist/dev.d.cts | 2 +- dist/dev.d.ts | 2 +- dist/{driver-4SJMBJcu.d.cts => driver-CUWsjHjM.d.ts} | 4 ++-- dist/{driver-zDj9PJPr.d.ts => driver-suOL9gid.d.cts} | 4 ++-- dist/main.d.cts | 2 +- dist/main.d.ts | 2 +- src/utils/types.test.ts | 8 ++++++++ src/utils/types.ts | 6 +++--- 8 files changed, 19 insertions(+), 11 deletions(-) rename dist/{driver-4SJMBJcu.d.cts => driver-CUWsjHjM.d.ts} (94%) rename dist/{driver-zDj9PJPr.d.ts => driver-suOL9gid.d.cts} (94%) diff --git a/dist/dev.d.cts b/dist/dev.d.cts index 7b19295..6b87b65 100644 --- a/dist/dev.d.cts +++ b/dist/dev.d.cts @@ -1,2 +1,2 @@ -import { BaseRecord, EmptyObject, HyperAPIDriver, HyperAPIErrorData, HyperAPIMethod, HyperAPIModule, HyperAPIModuleResponse, HyperAPIRequest, HyperAPIRequestArgs, HyperAPIResponse, isHyperApiMethod, isRecord } from "./driver-4SJMBJcu.cjs"; +import { BaseRecord, EmptyObject, HyperAPIDriver, HyperAPIErrorData, HyperAPIMethod, HyperAPIModule, HyperAPIModuleResponse, HyperAPIRequest, HyperAPIRequestArgs, HyperAPIResponse, isHyperApiMethod, isRecord } from "./driver-suOL9gid.cjs"; export { type BaseRecord, type EmptyObject, HyperAPIDriver, type HyperAPIErrorData, type HyperAPIMethod, type HyperAPIModule, type HyperAPIModuleResponse, type HyperAPIRequest, type HyperAPIRequestArgs, type HyperAPIResponse, isHyperApiMethod, isRecord }; \ No newline at end of file diff --git a/dist/dev.d.ts b/dist/dev.d.ts index 75c3463..50bf975 100644 --- a/dist/dev.d.ts +++ b/dist/dev.d.ts @@ -1,2 +1,2 @@ -import { BaseRecord, EmptyObject, HyperAPIDriver, HyperAPIErrorData, HyperAPIMethod, HyperAPIModule, HyperAPIModuleResponse, HyperAPIRequest, HyperAPIRequestArgs, HyperAPIResponse, isHyperApiMethod, isRecord } from "./driver-zDj9PJPr.js"; +import { BaseRecord, EmptyObject, HyperAPIDriver, HyperAPIErrorData, HyperAPIMethod, HyperAPIModule, HyperAPIModuleResponse, HyperAPIRequest, HyperAPIRequestArgs, HyperAPIResponse, isHyperApiMethod, isRecord } from "./driver-CUWsjHjM.js"; export { type BaseRecord, type EmptyObject, HyperAPIDriver, type HyperAPIErrorData, type HyperAPIMethod, type HyperAPIModule, type HyperAPIModuleResponse, type HyperAPIRequest, type HyperAPIRequestArgs, type HyperAPIResponse, isHyperApiMethod, isRecord }; \ No newline at end of file diff --git a/dist/driver-4SJMBJcu.d.cts b/dist/driver-CUWsjHjM.d.ts similarity index 94% rename from dist/driver-4SJMBJcu.d.cts rename to dist/driver-CUWsjHjM.d.ts index c2ddb9f..aa58064 100644 --- a/dist/driver-4SJMBJcu.d.cts +++ b/dist/driver-CUWsjHjM.d.ts @@ -1,5 +1,5 @@ import { NeoEvent, NeoEventTarget } from "neoevents"; -import { IsEqual, Merge, Promisable, Simplify } from "type-fest"; +import { IsEqual, IsNever, Merge, Promisable, Simplify } from "type-fest"; //#region src/utils/methods.d.ts type HyperAPIMethod = "DELETE" | "GET" | "HEAD" | "OPTIONS" | "PATCH" | "POST" | "PUT" | "UNKNOWN"; @@ -62,7 +62,7 @@ declare class HyperAPIError extends Err } //#endregion //#region src/utils/types.d.ts -type IsRecord = T extends void ? false : [T] extends [never] ? false : IsEqual extends true ? false : true; +type IsRecord = IsNever extends true ? false : T extends void ? false : IsEqual extends true ? false : true; type Join, ReqExtra extends BaseRecord> = IsRecord extends true ? Merge : R; type SimpleMerge = Simplify<{ [Key in keyof Destination as Key extends keyof Source ? never : Key]: Destination[Key] } & Source>; type Extend = IsRecord extends true ? IsRecord extends true ? SimpleMerge : V1 : IsRecord extends true ? Exclude : EmptyObject; diff --git a/dist/driver-zDj9PJPr.d.ts b/dist/driver-suOL9gid.d.cts similarity index 94% rename from dist/driver-zDj9PJPr.d.ts rename to dist/driver-suOL9gid.d.cts index c2ddb9f..aa58064 100644 --- a/dist/driver-zDj9PJPr.d.ts +++ b/dist/driver-suOL9gid.d.cts @@ -1,5 +1,5 @@ import { NeoEvent, NeoEventTarget } from "neoevents"; -import { IsEqual, Merge, Promisable, Simplify } from "type-fest"; +import { IsEqual, IsNever, Merge, Promisable, Simplify } from "type-fest"; //#region src/utils/methods.d.ts type HyperAPIMethod = "DELETE" | "GET" | "HEAD" | "OPTIONS" | "PATCH" | "POST" | "PUT" | "UNKNOWN"; @@ -62,7 +62,7 @@ declare class HyperAPIError extends Err } //#endregion //#region src/utils/types.d.ts -type IsRecord = T extends void ? false : [T] extends [never] ? false : IsEqual extends true ? false : true; +type IsRecord = IsNever extends true ? false : T extends void ? false : IsEqual extends true ? false : true; type Join, ReqExtra extends BaseRecord> = IsRecord extends true ? Merge : R; type SimpleMerge = Simplify<{ [Key in keyof Destination as Key extends keyof Source ? never : Key]: Destination[Key] } & Source>; type Extend = IsRecord extends true ? IsRecord extends true ? SimpleMerge : V1 : IsRecord extends true ? Exclude : EmptyObject; diff --git a/dist/main.d.cts b/dist/main.d.cts index 3ab2ada..ce3b9f7 100644 --- a/dist/main.d.cts +++ b/dist/main.d.cts @@ -1,4 +1,4 @@ -import { BaseRecord, EmptyObject, Extend, HyperAPIDriver, HyperAPIError, HyperAPIErrorData, HyperAPIModule, HyperAPIRequest, HyperAPIResponse, Join } from "./driver-4SJMBJcu.cjs"; +import { BaseRecord, EmptyObject, Extend, HyperAPIDriver, HyperAPIError, HyperAPIErrorData, HyperAPIModule, HyperAPIRequest, HyperAPIResponse, Join } from "./driver-suOL9gid.cjs"; import { Promisable } from "type-fest"; //#region src/api-errors.d.ts diff --git a/dist/main.d.ts b/dist/main.d.ts index 479faec..9a3c1bb 100644 --- a/dist/main.d.ts +++ b/dist/main.d.ts @@ -1,4 +1,4 @@ -import { BaseRecord, EmptyObject, Extend, HyperAPIDriver, HyperAPIError, HyperAPIErrorData, HyperAPIModule, HyperAPIRequest, HyperAPIResponse, Join } from "./driver-zDj9PJPr.js"; +import { BaseRecord, EmptyObject, Extend, HyperAPIDriver, HyperAPIError, HyperAPIErrorData, HyperAPIModule, HyperAPIRequest, HyperAPIResponse, Join } from "./driver-CUWsjHjM.js"; import { Promisable } from "type-fest"; //#region src/api-errors.d.ts diff --git a/src/utils/types.test.ts b/src/utils/types.test.ts index ab4c643..7c266b0 100644 --- a/src/utils/types.test.ts +++ b/src/utils/types.test.ts @@ -22,5 +22,13 @@ test('Extend', () => { expectTypeOf>().toEqualTypeOf(); + expectTypeOf>().toEqualTypeOf<{ + a: string; + }>(); + + expectTypeOf>().toEqualTypeOf<{ + a: string; + }>(); + expectTypeOf>().toEqualTypeOf<{ a: string }>(); }); diff --git a/src/utils/types.ts b/src/utils/types.ts index d940c5f..6ac90b0 100644 --- a/src/utils/types.ts +++ b/src/utils/types.ts @@ -1,10 +1,10 @@ -import type { IsEqual, Merge, Simplify } from 'type-fest'; +import type { IsEqual, IsNever, Merge, Simplify } from 'type-fest'; import type { HyperAPIRequest } from '../request.js'; import type { BaseRecord, EmptyObject } from './record.js'; -type IsRecord = T extends void +type IsRecord = IsNever extends true ? false - : [T] extends [never] + : T extends void ? false : IsEqual extends true ? false From fda360853e4fdd986bedc7e275e11241fd62140e Mon Sep 17 00:00:00 2001 From: Daniil Kirichenko Date: Mon, 15 Sep 2025 00:52:34 +0200 Subject: [PATCH 54/57] Update types --- src/module.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/module.ts b/src/module.ts index 25d84d7..d76a59e 100644 --- a/src/module.ts +++ b/src/module.ts @@ -14,7 +14,7 @@ export class HyperAPIModule< ReqExtra extends BaseRecord = never, > { private chain: (( - request: Req & ReqExtra, + request: Join, ) => Promisable)[] = []; use( @@ -69,7 +69,7 @@ export class HyperAPIModule< let request_result = request; for (const fn of this.chain) { // oxlint-disable-next-line no-await-in-loop - const request_add = await fn(request_result as Req & ReqExtra); + const request_add = await fn(request_result as Join); if (request_add) { request_result = { ...request_result, From fc3b443a432afc2b6ea381d67e9283f0389d12fb Mon Sep 17 00:00:00 2001 From: Daniil Kirichenko Date: Wed, 17 Sep 2025 02:26:33 +0200 Subject: [PATCH 55/57] Move `type-fest` to dependencies --- dist/dev.d.cts | 2 +- dist/dev.d.ts | 2 +- dist/{driver-CUWsjHjM.d.ts => driver--QMVe1BB.d.ts} | 5 ++--- .../{driver-suOL9gid.d.cts => driver-B9cVUC-_.d.cts} | 5 ++--- dist/main.d.cts | 2 +- dist/main.d.ts | 2 +- package.json | 4 ++-- src/utils/types.test.ts | 4 ++++ src/utils/types.ts | 12 ++---------- 9 files changed, 16 insertions(+), 22 deletions(-) rename dist/{driver-CUWsjHjM.d.ts => driver--QMVe1BB.d.ts} (91%) rename dist/{driver-suOL9gid.d.cts => driver-B9cVUC-_.d.cts} (91%) diff --git a/dist/dev.d.cts b/dist/dev.d.cts index 6b87b65..8d6592b 100644 --- a/dist/dev.d.cts +++ b/dist/dev.d.cts @@ -1,2 +1,2 @@ -import { BaseRecord, EmptyObject, HyperAPIDriver, HyperAPIErrorData, HyperAPIMethod, HyperAPIModule, HyperAPIModuleResponse, HyperAPIRequest, HyperAPIRequestArgs, HyperAPIResponse, isHyperApiMethod, isRecord } from "./driver-suOL9gid.cjs"; +import { BaseRecord, EmptyObject, HyperAPIDriver, HyperAPIErrorData, HyperAPIMethod, HyperAPIModule, HyperAPIModuleResponse, HyperAPIRequest, HyperAPIRequestArgs, HyperAPIResponse, isHyperApiMethod, isRecord } from "./driver-B9cVUC-_.cjs"; export { type BaseRecord, type EmptyObject, HyperAPIDriver, type HyperAPIErrorData, type HyperAPIMethod, type HyperAPIModule, type HyperAPIModuleResponse, type HyperAPIRequest, type HyperAPIRequestArgs, type HyperAPIResponse, isHyperApiMethod, isRecord }; \ No newline at end of file diff --git a/dist/dev.d.ts b/dist/dev.d.ts index 50bf975..ab8cf9c 100644 --- a/dist/dev.d.ts +++ b/dist/dev.d.ts @@ -1,2 +1,2 @@ -import { BaseRecord, EmptyObject, HyperAPIDriver, HyperAPIErrorData, HyperAPIMethod, HyperAPIModule, HyperAPIModuleResponse, HyperAPIRequest, HyperAPIRequestArgs, HyperAPIResponse, isHyperApiMethod, isRecord } from "./driver-CUWsjHjM.js"; +import { BaseRecord, EmptyObject, HyperAPIDriver, HyperAPIErrorData, HyperAPIMethod, HyperAPIModule, HyperAPIModuleResponse, HyperAPIRequest, HyperAPIRequestArgs, HyperAPIResponse, isHyperApiMethod, isRecord } from "./driver--QMVe1BB.js"; export { type BaseRecord, type EmptyObject, HyperAPIDriver, type HyperAPIErrorData, type HyperAPIMethod, type HyperAPIModule, type HyperAPIModuleResponse, type HyperAPIRequest, type HyperAPIRequestArgs, type HyperAPIResponse, isHyperApiMethod, isRecord }; \ No newline at end of file diff --git a/dist/driver-CUWsjHjM.d.ts b/dist/driver--QMVe1BB.d.ts similarity index 91% rename from dist/driver-CUWsjHjM.d.ts rename to dist/driver--QMVe1BB.d.ts index aa58064..378cb3f 100644 --- a/dist/driver-CUWsjHjM.d.ts +++ b/dist/driver--QMVe1BB.d.ts @@ -1,5 +1,5 @@ import { NeoEvent, NeoEventTarget } from "neoevents"; -import { IsEqual, IsNever, Merge, Promisable, Simplify } from "type-fest"; +import { IsEqual, IsNever, Merge, Promisable } from "type-fest"; //#region src/utils/methods.d.ts type HyperAPIMethod = "DELETE" | "GET" | "HEAD" | "OPTIONS" | "PATCH" | "POST" | "PUT" | "UNKNOWN"; @@ -64,8 +64,7 @@ declare class HyperAPIError extends Err //#region src/utils/types.d.ts type IsRecord = IsNever extends true ? false : T extends void ? false : IsEqual extends true ? false : true; type Join, ReqExtra extends BaseRecord> = IsRecord extends true ? Merge : R; -type SimpleMerge = Simplify<{ [Key in keyof Destination as Key extends keyof Source ? never : Key]: Destination[Key] } & Source>; -type Extend = IsRecord extends true ? IsRecord extends true ? SimpleMerge : V1 : IsRecord extends true ? Exclude : EmptyObject; +type Extend = IsRecord extends true ? IsRecord extends true ? Merge : V1 : IsRecord extends true ? Exclude : EmptyObject; //#endregion //#region src/module.d.ts type HyperAPIModuleResponse = Response | BaseRecord | unknown[] | undefined; diff --git a/dist/driver-suOL9gid.d.cts b/dist/driver-B9cVUC-_.d.cts similarity index 91% rename from dist/driver-suOL9gid.d.cts rename to dist/driver-B9cVUC-_.d.cts index aa58064..378cb3f 100644 --- a/dist/driver-suOL9gid.d.cts +++ b/dist/driver-B9cVUC-_.d.cts @@ -1,5 +1,5 @@ import { NeoEvent, NeoEventTarget } from "neoevents"; -import { IsEqual, IsNever, Merge, Promisable, Simplify } from "type-fest"; +import { IsEqual, IsNever, Merge, Promisable } from "type-fest"; //#region src/utils/methods.d.ts type HyperAPIMethod = "DELETE" | "GET" | "HEAD" | "OPTIONS" | "PATCH" | "POST" | "PUT" | "UNKNOWN"; @@ -64,8 +64,7 @@ declare class HyperAPIError extends Err //#region src/utils/types.d.ts type IsRecord = IsNever extends true ? false : T extends void ? false : IsEqual extends true ? false : true; type Join, ReqExtra extends BaseRecord> = IsRecord extends true ? Merge : R; -type SimpleMerge = Simplify<{ [Key in keyof Destination as Key extends keyof Source ? never : Key]: Destination[Key] } & Source>; -type Extend = IsRecord extends true ? IsRecord extends true ? SimpleMerge : V1 : IsRecord extends true ? Exclude : EmptyObject; +type Extend = IsRecord extends true ? IsRecord extends true ? Merge : V1 : IsRecord extends true ? Exclude : EmptyObject; //#endregion //#region src/module.d.ts type HyperAPIModuleResponse = Response | BaseRecord | unknown[] | undefined; diff --git a/dist/main.d.cts b/dist/main.d.cts index ce3b9f7..05e85ad 100644 --- a/dist/main.d.cts +++ b/dist/main.d.cts @@ -1,4 +1,4 @@ -import { BaseRecord, EmptyObject, Extend, HyperAPIDriver, HyperAPIError, HyperAPIErrorData, HyperAPIModule, HyperAPIRequest, HyperAPIResponse, Join } from "./driver-suOL9gid.cjs"; +import { BaseRecord, EmptyObject, Extend, HyperAPIDriver, HyperAPIError, HyperAPIErrorData, HyperAPIModule, HyperAPIRequest, HyperAPIResponse, Join } from "./driver-B9cVUC-_.cjs"; import { Promisable } from "type-fest"; //#region src/api-errors.d.ts diff --git a/dist/main.d.ts b/dist/main.d.ts index 9a3c1bb..8814c32 100644 --- a/dist/main.d.ts +++ b/dist/main.d.ts @@ -1,4 +1,4 @@ -import { BaseRecord, EmptyObject, Extend, HyperAPIDriver, HyperAPIError, HyperAPIErrorData, HyperAPIModule, HyperAPIRequest, HyperAPIResponse, Join } from "./driver-CUWsjHjM.js"; +import { BaseRecord, EmptyObject, Extend, HyperAPIDriver, HyperAPIError, HyperAPIErrorData, HyperAPIModule, HyperAPIRequest, HyperAPIResponse, Join } from "./driver--QMVe1BB.js"; import { Promisable } from "type-fest"; //#region src/api-errors.d.ts diff --git a/package.json b/package.json index f4aaec6..fc7bd68 100644 --- a/package.json +++ b/package.json @@ -30,7 +30,8 @@ }, "dependencies": { "itty-router": "5.0.22", - "neoevents": "0.3.0" + "neoevents": "0.3.0", + "type-fest": "4.41.0" }, "devDependencies": { "@biomejs/biome": "2.1.1", @@ -40,7 +41,6 @@ "oxlint": "1.3.0", "publint": "0.3.12", "tsdown": "0.14.2", - "type-fest": "4.41.0", "typescript": "5.9.2", "unplugin-unused": "0.5.2", "valibot": "1.1.0", diff --git a/src/utils/types.test.ts b/src/utils/types.test.ts index 7c266b0..9e2e9c0 100644 --- a/src/utils/types.test.ts +++ b/src/utils/types.test.ts @@ -3,6 +3,7 @@ import { EmptyObject } from './record.js'; import { Extend } from './types.js'; test('Extend', () => { + // type T = Extend<{ a: string }, { b: number }>; expectTypeOf>().toEqualTypeOf<{ a: string; b: number; @@ -20,8 +21,10 @@ test('Extend', () => { a: string; }>(); + // type T = Extend; expectTypeOf>().toEqualTypeOf(); + // type T = Extend<{ a: string }, never>; expectTypeOf>().toEqualTypeOf<{ a: string; }>(); @@ -30,5 +33,6 @@ test('Extend', () => { a: string; }>(); + // type T = Extend<{ a: string }, void>; expectTypeOf>().toEqualTypeOf<{ a: string }>(); }); diff --git a/src/utils/types.ts b/src/utils/types.ts index 6ac90b0..aee43a5 100644 --- a/src/utils/types.ts +++ b/src/utils/types.ts @@ -1,4 +1,4 @@ -import type { IsEqual, IsNever, Merge, Simplify } from 'type-fest'; +import type { IsEqual, IsNever, Merge } from 'type-fest'; import type { HyperAPIRequest } from '../request.js'; import type { BaseRecord, EmptyObject } from './record.js'; @@ -15,20 +15,12 @@ export type Join< ReqExtra extends BaseRecord, > = IsRecord extends true ? Merge : R; -type SimpleMerge = Simplify< - { - [Key in keyof Destination as Key extends keyof Source - ? never - : Key]: Destination[Key]; - } & Source ->; - export type Extend< V1 extends BaseRecord, V2 extends BaseRecord | void, > = IsRecord extends true ? IsRecord extends true - ? SimpleMerge + ? Merge : V1 : IsRecord extends true ? Exclude From 9672bb04b66832d3c7f9cb52596366200f4612ab Mon Sep 17 00:00:00 2001 From: Daniil Kirichenko Date: Thu, 30 Oct 2025 15:39:54 +0100 Subject: [PATCH 56/57] Update dependencies & linter --- .oxlintrc.json | 9 +- .zed/settings.json | 76 ++- biome.json | 24 +- bun.lock | 464 +++++++++--------- dist/dev.cjs | 3 +- dist/dev.d.cts | 2 +- dist/dev.d.ts | 2 +- dist/dev.js | 2 +- ...ver--QMVe1BB.d.ts => driver-D8sen_tB.d.ts} | 13 +- ...r-B9cVUC-_.d.cts => driver-DO8IdV_Q.d.cts} | 13 +- dist/main.cjs | 54 +- dist/main.d.cts | 2 +- dist/main.d.ts | 2 +- dist/main.js | 47 +- ...{record-DFObD9mD.js => record-BeJ2ZKAR.js} | 2 +- eslint.config.js | 4 +- package.json | 20 +- src/error.test.ts | 3 +- src/main.test.ts | 2 + src/main.ts | 9 +- src/module.ts | 7 +- src/response.ts | 12 +- src/router.ts | 26 +- src/router/file-tree.ts | 3 +- src/utils/methods.ts | 16 +- src/utils/record.ts | 10 +- test/hyper-api/router/slug/x-[slug]-x.ts | 2 - test/hyper-api/router/slug/x-[slug].ts | 2 - tsconfig.json | 2 +- 29 files changed, 442 insertions(+), 391 deletions(-) rename dist/{driver--QMVe1BB.d.ts => driver-D8sen_tB.d.ts} (87%) rename dist/{driver-B9cVUC-_.d.cts => driver-DO8IdV_Q.d.cts} (87%) rename dist/{record-DFObD9mD.js => record-BeJ2ZKAR.js} (92%) diff --git a/.oxlintrc.json b/.oxlintrc.json index 13b8341..7c73db6 100644 --- a/.oxlintrc.json +++ b/.oxlintrc.json @@ -1,9 +1,12 @@ { "$schema": "./node_modules/oxlint/configuration_schema.json", "extends": [ - "./node_modules/@kirick/lint/configs/oxlint/correctness.json", - "./node_modules/@kirick/lint/configs/oxlint/perf.json", - "./node_modules/@kirick/lint/configs/oxlint/restriction.json" + "./node_modules/@kirick/lint/configs/oxlint/correctness.jsonc", + "./node_modules/@kirick/lint/configs/oxlint/pedantic.jsonc", + "./node_modules/@kirick/lint/configs/oxlint/perf.jsonc", + "./node_modules/@kirick/lint/configs/oxlint/restriction.jsonc", + "./node_modules/@kirick/lint/configs/oxlint/style.jsonc", + "./node_modules/@kirick/lint/configs/oxlint/suspicious.jsonc" ], "ignorePatterns": ["dist"] } diff --git a/.zed/settings.json b/.zed/settings.json index 24cc794..66d29b4 100644 --- a/.zed/settings.json +++ b/.zed/settings.json @@ -1,12 +1,72 @@ { - "format_on_save": "on", - "formatter": { - "language_server": { - "name": "biome" + "languages": { + "JavaScript": { + "format_on_save": "on", + "formatter": [ + { "language_server": { "name": "biome" } }, + { "code_action": "source.organizeImports.biome" }, + { "code_action": "source.fixAll.biome" } + ] + }, + "TypeScript": { + "format_on_save": "on", + "formatter": [ + { "language_server": { "name": "biome" } }, + { "code_action": "source.organizeImports.biome" }, + { "code_action": "source.fixAll.biome" } + ] + }, + "TSX": { + "format_on_save": "on", + "formatter": [ + { "language_server": { "name": "biome" } }, + { "code_action": "source.organizeImports.biome" }, + { "code_action": "source.fixAll.biome" } + ] + }, + "JSON": { + "format_on_save": "on", + "formatter": [{ "language_server": { "name": "biome" } }] + }, + "JSONC": { + "format_on_save": "on", + "formatter": [{ "language_server": { "name": "biome" } }] + }, + "CSS": { + "format_on_save": "on", + "formatter": [{ "language_server": { "name": "biome" } }] + }, + "HTML": { + "format_on_save": "on", + "formatter": [ + { + "external": { + "command": "bunx", + "arguments": [ + "--bun", + "prettier", + "--stdin-filepath", + "{buffer_path}" + ] + } + } + ] + }, + "Vue.js": { + "format_on_save": "on", + "formatter": [ + { + "external": { + "command": "bunx", + "arguments": [ + "--bun", + "prettier", + "--stdin-filepath", + "{buffer_path}" + ] + } + } + ] } - }, - "code_actions_on_format": { - "source.fixAll.biome": true, - "source.organizeImports.biome": true } } diff --git a/biome.json b/biome.json index 91c3d81..3340c42 100644 --- a/biome.json +++ b/biome.json @@ -1,5 +1,5 @@ { - "$schema": "https://biomejs.dev/schemas/2.1.1/schema.json", + "$schema": "https://biomejs.dev/schemas/2.3.1/schema.json", "vcs": { "enabled": false, "clientKind": "git", @@ -7,7 +7,7 @@ }, "files": { "ignoreUnknown": false, - "includes": ["**", "!**/dist/**"] + "includes": ["**", "!**/dist/**", "!**/*.html", "!**/*.ejs", "!**/*.vue"] }, "formatter": { "enabled": true, @@ -26,7 +26,25 @@ }, "javascript": { "formatter": { - "quoteStyle": "single" + "quoteStyle": "single", + "operatorLinebreak": "before" + } + }, + "css": { + "parser": { + "tailwindDirectives": true + }, + "formatter": { + "enabled": true + } + }, + "html": { + "experimentalFullSupportEnabled": true, + "parser": { + "interpolation": true + }, + "formatter": { + "enabled": true } } } diff --git a/bun.lock b/bun.lock index cdacb42..da4546b 100644 --- a/bun.lock +++ b/bun.lock @@ -5,52 +5,52 @@ "name": "@hyperapi/core", "dependencies": { "itty-router": "5.0.22", - "neoevents": "^0.3.0", + "neoevents": "0.3.0", + "type-fest": "4.41.0", }, "devDependencies": { - "@biomejs/biome": "2.1.1", - "@kirick/lint": "0.2.7", - "@types/bun": "1.2.21", - "eslint": "9.27.0", - "oxlint": "1.3.0", - "publint": "0.3.12", - "tsdown": "0.14.2", - "type-fest": "4.41.0", - "typescript": "5.9.2", - "unplugin-unused": "0.5.2", + "@biomejs/biome": "2.3.1", + "@kirick/lint": "0.2.12", + "@types/bun": "1.3.1", + "eslint": "9.38.0", + "oxlint": "1.24.0", + "publint": "0.3.15", + "tsdown": "0.15.12", + "typescript": "5.9.3", + "unplugin-unused": "0.5.4", "valibot": "1.1.0", - "vitest": "3.2.4", + "vitest": "4.0.4", }, }, }, "packages": { - "@babel/generator": ["@babel/generator@7.28.3", "", { "dependencies": { "@babel/parser": "^7.28.3", "@babel/types": "^7.28.2", "@jridgewell/gen-mapping": "^0.3.12", "@jridgewell/trace-mapping": "^0.3.28", "jsesc": "^3.0.2" } }, "sha512-3lSpxGgvnmZznmBkCRnVREPUFJv2wrv9iAoFDvADJc0ypmdOxdUtcLeBgBJ6zE0PMeTKnxeQzyk0xTBq4Ep7zw=="], + "@babel/generator": ["@babel/generator@7.28.5", "", { "dependencies": { "@babel/parser": "^7.28.5", "@babel/types": "^7.28.5", "@jridgewell/gen-mapping": "^0.3.12", "@jridgewell/trace-mapping": "^0.3.28", "jsesc": "^3.0.2" } }, "sha512-3EwLFhZ38J4VyIP6WNtt2kUdW9dokXA9Cr4IVIFHuCpZ3H8/YFOl5JjZHisrn1fATPBmKKqXzDFvh9fUwHz6CQ=="], "@babel/helper-string-parser": ["@babel/helper-string-parser@7.27.1", "", {}, "sha512-qMlSxKbpRlAridDExk92nSobyDdpPijUq2DW6oDnUqd0iOGxmQjyqhMIihI9+zv4LPyZdRje2cavWPbCbWm3eA=="], - "@babel/helper-validator-identifier": ["@babel/helper-validator-identifier@7.27.1", "", {}, "sha512-D2hP9eA+Sqx1kBZgzxZh0y1trbuU+JoDkiEwqhQ36nodYqJwyEIhPSdMNd7lOm/4io72luTPWH20Yda0xOuUow=="], + "@babel/helper-validator-identifier": ["@babel/helper-validator-identifier@7.28.5", "", {}, "sha512-qSs4ifwzKJSV39ucNjsvc6WVHs6b7S03sOh2OcHF9UHfVPqWWALUsNUVzhSBiItjRZoLHx7nIarVjqKVusUZ1Q=="], - "@babel/parser": ["@babel/parser@7.28.3", "", { "dependencies": { "@babel/types": "^7.28.2" }, "bin": "./bin/babel-parser.js" }, "sha512-7+Ey1mAgYqFAx2h0RuoxcQT5+MlG3GTV0TQrgr7/ZliKsm/MNDxVVutlWaziMq7wJNAz8MTqz55XLpWvva6StA=="], + "@babel/parser": ["@babel/parser@7.28.5", "", { "dependencies": { "@babel/types": "^7.28.5" }, "bin": "./bin/babel-parser.js" }, "sha512-KKBU1VGYR7ORr3At5HAtUQ+TV3SzRCXmA/8OdDZiLDBIZxVyzXuztPjfLd3BV1PRAQGCMWWSHYhL0F8d5uHBDQ=="], - "@babel/types": ["@babel/types@7.28.2", "", { "dependencies": { "@babel/helper-string-parser": "^7.27.1", "@babel/helper-validator-identifier": "^7.27.1" } }, "sha512-ruv7Ae4J5dUYULmeXw1gmb7rYRz57OWCPM57pHojnLq/3Z1CK2lNSLTCVjxVk1F/TZHwOZZrOWi0ur95BbLxNQ=="], + "@babel/types": ["@babel/types@7.28.5", "", { "dependencies": { "@babel/helper-string-parser": "^7.27.1", "@babel/helper-validator-identifier": "^7.28.5" } }, "sha512-qQ5m48eI/MFLQ5PxQj4PFaprjyCTLI37ElWMmNs0K8Lk3dVeOdNpB3ks8jc7yM5CDmVC73eMVk/trk3fgmrUpA=="], - "@biomejs/biome": ["@biomejs/biome@2.1.1", "", { "optionalDependencies": { "@biomejs/cli-darwin-arm64": "2.1.1", "@biomejs/cli-darwin-x64": "2.1.1", "@biomejs/cli-linux-arm64": "2.1.1", "@biomejs/cli-linux-arm64-musl": "2.1.1", "@biomejs/cli-linux-x64": "2.1.1", "@biomejs/cli-linux-x64-musl": "2.1.1", "@biomejs/cli-win32-arm64": "2.1.1", "@biomejs/cli-win32-x64": "2.1.1" }, "bin": { "biome": "bin/biome" } }, "sha512-HFGYkxG714KzG+8tvtXCJ1t1qXQMzgWzfvQaUjxN6UeKv+KvMEuliInnbZLJm6DXFXwqVi6446EGI0sGBLIYng=="], + "@biomejs/biome": ["@biomejs/biome@2.3.1", "", { "optionalDependencies": { "@biomejs/cli-darwin-arm64": "2.3.1", "@biomejs/cli-darwin-x64": "2.3.1", "@biomejs/cli-linux-arm64": "2.3.1", "@biomejs/cli-linux-arm64-musl": "2.3.1", "@biomejs/cli-linux-x64": "2.3.1", "@biomejs/cli-linux-x64-musl": "2.3.1", "@biomejs/cli-win32-arm64": "2.3.1", "@biomejs/cli-win32-x64": "2.3.1" }, "bin": { "biome": "bin/biome" } }, "sha512-A29evf1R72V5bo4o2EPxYMm5mtyGvzp2g+biZvRFx29nWebGyyeOSsDWGx3tuNNMFRepGwxmA9ZQ15mzfabK2w=="], - "@biomejs/cli-darwin-arm64": ["@biomejs/cli-darwin-arm64@2.1.1", "", { "os": "darwin", "cpu": "arm64" }, "sha512-2Muinu5ok4tWxq4nu5l19el48cwCY/vzvI7Vjbkf3CYIQkjxZLyj0Ad37Jv2OtlXYaLvv+Sfu1hFeXt/JwRRXQ=="], + "@biomejs/cli-darwin-arm64": ["@biomejs/cli-darwin-arm64@2.3.1", "", { "os": "darwin", "cpu": "arm64" }, "sha512-ombSf3MnTUueiYGN1SeI9tBCsDUhpWzOwS63Dove42osNh0PfE1cUtHFx6eZ1+MYCCLwXzlFlYFdrJ+U7h6LcA=="], - "@biomejs/cli-darwin-x64": ["@biomejs/cli-darwin-x64@2.1.1", "", { "os": "darwin", "cpu": "x64" }, "sha512-cC8HM5lrgKQXLAK+6Iz2FrYW5A62pAAX6KAnRlEyLb+Q3+Kr6ur/sSuoIacqlp1yvmjHJqjYfZjPvHWnqxoEIA=="], + "@biomejs/cli-darwin-x64": ["@biomejs/cli-darwin-x64@2.3.1", "", { "os": "darwin", "cpu": "x64" }, "sha512-pcOfwyoQkrkbGvXxRvZNe5qgD797IowpJPovPX5biPk2FwMEV+INZqfCaz4G5bVq9hYnjwhRMamg11U4QsRXrQ=="], - "@biomejs/cli-linux-arm64": ["@biomejs/cli-linux-arm64@2.1.1", "", { "os": "linux", "cpu": "arm64" }, "sha512-tw4BEbhAUkWPe4WBr6IX04DJo+2jz5qpPzpW/SWvqMjb9QuHY8+J0M23V8EPY/zWU4IG8Ui0XESapR1CB49Q7g=="], + "@biomejs/cli-linux-arm64": ["@biomejs/cli-linux-arm64@2.3.1", "", { "os": "linux", "cpu": "arm64" }, "sha512-td5O8pFIgLs8H1sAZsD6v+5quODihyEw4nv2R8z7swUfIK1FKk+15e4eiYVLcAE4jUqngvh4j3JCNgg0Y4o4IQ=="], - "@biomejs/cli-linux-arm64-musl": ["@biomejs/cli-linux-arm64-musl@2.1.1", "", { "os": "linux", "cpu": "arm64" }, "sha512-/7FBLnTswu4jgV9ttI3AMIdDGqVEPIZd8I5u2D4tfCoj8rl9dnjrEQbAIDlWhUXdyWlFSz8JypH3swU9h9P+2A=="], + "@biomejs/cli-linux-arm64-musl": ["@biomejs/cli-linux-arm64-musl@2.3.1", "", { "os": "linux", "cpu": "arm64" }, "sha512-+DZYv8l7FlUtTrWs1Tdt1KcNCAmRO87PyOnxKGunbWm5HKg1oZBSbIIPkjrCtDZaeqSG1DiGx7qF+CPsquQRcg=="], - "@biomejs/cli-linux-x64": ["@biomejs/cli-linux-x64@2.1.1", "", { "os": "linux", "cpu": "x64" }, "sha512-3WJ1GKjU7NzZb6RTbwLB59v9cTIlzjbiFLDB0z4376TkDqoNYilJaC37IomCr/aXwuU8QKkrYoHrgpSq5ffJ4Q=="], + "@biomejs/cli-linux-x64": ["@biomejs/cli-linux-x64@2.3.1", "", { "os": "linux", "cpu": "x64" }, "sha512-PYWgEO7up7XYwSAArOpzsVCiqxBCXy53gsReAb1kKYIyXaoAlhBaBMvxR/k2Rm9aTuZ662locXUmPk/Aj+Xu+Q=="], - "@biomejs/cli-linux-x64-musl": ["@biomejs/cli-linux-x64-musl@2.1.1", "", { "os": "linux", "cpu": "x64" }, "sha512-kUu+loNI3OCD2c12cUt7M5yaaSjDnGIksZwKnueubX6c/HWUyi/0mPbTBHR49Me3F0KKjWiKM+ZOjsmC+lUt9g=="], + "@biomejs/cli-linux-x64-musl": ["@biomejs/cli-linux-x64-musl@2.3.1", "", { "os": "linux", "cpu": "x64" }, "sha512-Y3Ob4nqgv38Mh+6EGHltuN+Cq8aj/gyMTJYzkFZV2AEj+9XzoXB9VNljz9pjfFNHUxvLEV4b55VWyxozQTBaUQ=="], - "@biomejs/cli-win32-arm64": ["@biomejs/cli-win32-arm64@2.1.1", "", { "os": "win32", "cpu": "arm64" }, "sha512-vEHK0v0oW+E6RUWLoxb2isI3rZo57OX9ZNyyGH701fZPj6Il0Rn1f5DMNyCmyflMwTnIQstEbs7n2BxYSqQx4Q=="], + "@biomejs/cli-win32-arm64": ["@biomejs/cli-win32-arm64@2.3.1", "", { "os": "win32", "cpu": "arm64" }, "sha512-RHIG/zgo+69idUqVvV3n8+j58dKYABRpMyDmfWu2TITC+jwGPiEaT0Q3RKD+kQHiS80mpBrST0iUGeEXT0bU9A=="], - "@biomejs/cli-win32-x64": ["@biomejs/cli-win32-x64@2.1.1", "", { "os": "win32", "cpu": "x64" }, "sha512-i2PKdn70kY++KEF/zkQFvQfX1e8SkA8hq4BgC+yE9dZqyLzB/XStY2MvwI3qswlRgnGpgncgqe0QYKVS1blksg=="], + "@biomejs/cli-win32-x64": ["@biomejs/cli-win32-x64@2.3.1", "", { "os": "win32", "cpu": "x64" }, "sha512-izl30JJ5Dp10mi90Eko47zhxE6pYyWPcnX1NQxKpL/yMhXxf95oLTzfpu4q+MDBh/gemNqyJEwjBpe0MT5iWPA=="], "@emnapi/core": ["@emnapi/core@1.5.0", "", { "dependencies": { "@emnapi/wasi-threads": "1.1.0", "tslib": "^2.4.0" } }, "sha512-sbP8GzB1WDzacS8fgNPpHlp6C9VZe+SJP3F90W9rLemaQj2PzIuTEl1qDOYQf58YIpyjViI24y9aPWCjEzY2cg=="], @@ -58,71 +58,79 @@ "@emnapi/wasi-threads": ["@emnapi/wasi-threads@1.1.0", "", { "dependencies": { "tslib": "^2.4.0" } }, "sha512-WI0DdZ8xFSbgMjR1sFsKABJ/C5OnRrjT06JXbZKexJGrDuPTzZdDYfFlsgcCXCyf+suG5QU2e/y1Wo2V/OapLQ=="], - "@es-joy/jsdoccomment": ["@es-joy/jsdoccomment@0.50.2", "", { "dependencies": { "@types/estree": "^1.0.6", "@typescript-eslint/types": "^8.11.0", "comment-parser": "1.4.1", "esquery": "^1.6.0", "jsdoc-type-pratt-parser": "~4.1.0" } }, "sha512-YAdE/IJSpwbOTiaURNCKECdAwqrJuFiZhylmesBcIRawtYKnBR2wxPhoIewMg+Yu+QuYvHfJNReWpoxGBKOChA=="], + "@es-joy/jsdoccomment": ["@es-joy/jsdoccomment@0.76.0", "", { "dependencies": { "@types/estree": "^1.0.8", "@typescript-eslint/types": "^8.46.0", "comment-parser": "1.4.1", "esquery": "^1.6.0", "jsdoc-type-pratt-parser": "~6.10.0" } }, "sha512-g+RihtzFgGTx2WYCuTHbdOXJeAlGnROws0TeALx9ow/ZmOROOZkVg5wp/B44n0WJgI4SQFP1eWM2iRPlU2Y14w=="], + + "@es-joy/resolve.exports": ["@es-joy/resolve.exports@1.0.0", "", {}, "sha512-bbrmzsAZ9GA/3oBS6r8PWMtZarEhKHr413hak8ArwMEZ5DtaLErnkcyEWUsXy7urBcmVu/TpDzHPDVM5uIbx9A=="], + + "@esbuild/aix-ppc64": ["@esbuild/aix-ppc64@0.25.11", "", { "os": "aix", "cpu": "ppc64" }, "sha512-Xt1dOL13m8u0WE8iplx9Ibbm+hFAO0GsU2P34UNoDGvZYkY8ifSiy6Zuc1lYxfG7svWE2fzqCUmFp5HCn51gJg=="], - "@esbuild/aix-ppc64": ["@esbuild/aix-ppc64@0.21.5", "", { "os": "aix", "cpu": "ppc64" }, "sha512-1SDgH6ZSPTlggy1yI6+Dbkiz8xzpHJEVAlF/AM1tHPLsf5STom9rwtjE4hKAF20FfXXNTFqEYXyJNWh1GiZedQ=="], + "@esbuild/android-arm": ["@esbuild/android-arm@0.25.11", "", { "os": "android", "cpu": "arm" }, "sha512-uoa7dU+Dt3HYsethkJ1k6Z9YdcHjTrSb5NUy66ZfZaSV8hEYGD5ZHbEMXnqLFlbBflLsl89Zke7CAdDJ4JI+Gg=="], - "@esbuild/android-arm": ["@esbuild/android-arm@0.21.5", "", { "os": "android", "cpu": "arm" }, "sha512-vCPvzSjpPHEi1siZdlvAlsPxXl7WbOVUBBAowWug4rJHb68Ox8KualB+1ocNvT5fjv6wpkX6o/iEpbDrf68zcg=="], + "@esbuild/android-arm64": ["@esbuild/android-arm64@0.25.11", "", { "os": "android", "cpu": "arm64" }, "sha512-9slpyFBc4FPPz48+f6jyiXOx/Y4v34TUeDDXJpZqAWQn/08lKGeD8aDp9TMn9jDz2CiEuHwfhRmGBvpnd/PWIQ=="], - "@esbuild/android-arm64": ["@esbuild/android-arm64@0.21.5", "", { "os": "android", "cpu": "arm64" }, "sha512-c0uX9VAUBQ7dTDCjq+wdyGLowMdtR/GoC2U5IYk/7D1H1JYC0qseD7+11iMP2mRLN9RcCMRcjC4YMclCzGwS/A=="], + "@esbuild/android-x64": ["@esbuild/android-x64@0.25.11", "", { "os": "android", "cpu": "x64" }, "sha512-Sgiab4xBjPU1QoPEIqS3Xx+R2lezu0LKIEcYe6pftr56PqPygbB7+szVnzoShbx64MUupqoE0KyRlN7gezbl8g=="], - "@esbuild/android-x64": ["@esbuild/android-x64@0.21.5", "", { "os": "android", "cpu": "x64" }, "sha512-D7aPRUUNHRBwHxzxRvp856rjUHRFW1SdQATKXH2hqA0kAZb1hKmi02OpYRacl0TxIGz/ZmXWlbZgjwWYaCakTA=="], + "@esbuild/darwin-arm64": ["@esbuild/darwin-arm64@0.25.11", "", { "os": "darwin", "cpu": "arm64" }, "sha512-VekY0PBCukppoQrycFxUqkCojnTQhdec0vevUL/EDOCnXd9LKWqD/bHwMPzigIJXPhC59Vd1WFIL57SKs2mg4w=="], - "@esbuild/darwin-arm64": ["@esbuild/darwin-arm64@0.21.5", "", { "os": "darwin", "cpu": "arm64" }, "sha512-DwqXqZyuk5AiWWf3UfLiRDJ5EDd49zg6O9wclZ7kUMv2WRFr4HKjXp/5t8JZ11QbQfUS6/cRCKGwYhtNAY88kQ=="], + "@esbuild/darwin-x64": ["@esbuild/darwin-x64@0.25.11", "", { "os": "darwin", "cpu": "x64" }, "sha512-+hfp3yfBalNEpTGp9loYgbknjR695HkqtY3d3/JjSRUyPg/xd6q+mQqIb5qdywnDxRZykIHs3axEqU6l1+oWEQ=="], - "@esbuild/darwin-x64": ["@esbuild/darwin-x64@0.21.5", "", { "os": "darwin", "cpu": "x64" }, "sha512-se/JjF8NlmKVG4kNIuyWMV/22ZaerB+qaSi5MdrXtd6R08kvs2qCN4C09miupktDitvh8jRFflwGFBQcxZRjbw=="], + "@esbuild/freebsd-arm64": ["@esbuild/freebsd-arm64@0.25.11", "", { "os": "freebsd", "cpu": "arm64" }, "sha512-CmKjrnayyTJF2eVuO//uSjl/K3KsMIeYeyN7FyDBjsR3lnSJHaXlVoAK8DZa7lXWChbuOk7NjAc7ygAwrnPBhA=="], - "@esbuild/freebsd-arm64": ["@esbuild/freebsd-arm64@0.21.5", "", { "os": "freebsd", "cpu": "arm64" }, "sha512-5JcRxxRDUJLX8JXp/wcBCy3pENnCgBR9bN6JsY4OmhfUtIHe3ZW0mawA7+RDAcMLrMIZaf03NlQiX9DGyB8h4g=="], + "@esbuild/freebsd-x64": ["@esbuild/freebsd-x64@0.25.11", "", { "os": "freebsd", "cpu": "x64" }, "sha512-Dyq+5oscTJvMaYPvW3x3FLpi2+gSZTCE/1ffdwuM6G1ARang/mb3jvjxs0mw6n3Lsw84ocfo9CrNMqc5lTfGOw=="], - "@esbuild/freebsd-x64": ["@esbuild/freebsd-x64@0.21.5", "", { "os": "freebsd", "cpu": "x64" }, "sha512-J95kNBj1zkbMXtHVH29bBriQygMXqoVQOQYA+ISs0/2l3T9/kj42ow2mpqerRBxDJnmkUDCaQT/dfNXWX/ZZCQ=="], + "@esbuild/linux-arm": ["@esbuild/linux-arm@0.25.11", "", { "os": "linux", "cpu": "arm" }, "sha512-TBMv6B4kCfrGJ8cUPo7vd6NECZH/8hPpBHHlYI3qzoYFvWu2AdTvZNuU/7hsbKWqu/COU7NIK12dHAAqBLLXgw=="], - "@esbuild/linux-arm": ["@esbuild/linux-arm@0.21.5", "", { "os": "linux", "cpu": "arm" }, "sha512-bPb5AHZtbeNGjCKVZ9UGqGwo8EUu4cLq68E95A53KlxAPRmUyYv2D6F0uUI65XisGOL1hBP5mTronbgo+0bFcA=="], + "@esbuild/linux-arm64": ["@esbuild/linux-arm64@0.25.11", "", { "os": "linux", "cpu": "arm64" }, "sha512-Qr8AzcplUhGvdyUF08A1kHU3Vr2O88xxP0Tm8GcdVOUm25XYcMPp2YqSVHbLuXzYQMf9Bh/iKx7YPqECs6ffLA=="], - "@esbuild/linux-arm64": ["@esbuild/linux-arm64@0.21.5", "", { "os": "linux", "cpu": "arm64" }, "sha512-ibKvmyYzKsBeX8d8I7MH/TMfWDXBF3db4qM6sy+7re0YXya+K1cem3on9XgdT2EQGMu4hQyZhan7TeQ8XkGp4Q=="], + "@esbuild/linux-ia32": ["@esbuild/linux-ia32@0.25.11", "", { "os": "linux", "cpu": "ia32" }, "sha512-TmnJg8BMGPehs5JKrCLqyWTVAvielc615jbkOirATQvWWB1NMXY77oLMzsUjRLa0+ngecEmDGqt5jiDC6bfvOw=="], - "@esbuild/linux-ia32": ["@esbuild/linux-ia32@0.21.5", "", { "os": "linux", "cpu": "ia32" }, "sha512-YvjXDqLRqPDl2dvRODYmmhz4rPeVKYvppfGYKSNGdyZkA01046pLWyRKKI3ax8fbJoK5QbxblURkwK/MWY18Tg=="], + "@esbuild/linux-loong64": ["@esbuild/linux-loong64@0.25.11", "", { "os": "linux", "cpu": "none" }, "sha512-DIGXL2+gvDaXlaq8xruNXUJdT5tF+SBbJQKbWy/0J7OhU8gOHOzKmGIlfTTl6nHaCOoipxQbuJi7O++ldrxgMw=="], - "@esbuild/linux-loong64": ["@esbuild/linux-loong64@0.21.5", "", { "os": "linux", "cpu": "none" }, "sha512-uHf1BmMG8qEvzdrzAqg2SIG/02+4/DHB6a9Kbya0XDvwDEKCoC8ZRWI5JJvNdUjtciBGFQ5PuBlpEOXQj+JQSg=="], + "@esbuild/linux-mips64el": ["@esbuild/linux-mips64el@0.25.11", "", { "os": "linux", "cpu": "none" }, "sha512-Osx1nALUJu4pU43o9OyjSCXokFkFbyzjXb6VhGIJZQ5JZi8ylCQ9/LFagolPsHtgw6himDSyb5ETSfmp4rpiKQ=="], - "@esbuild/linux-mips64el": ["@esbuild/linux-mips64el@0.21.5", "", { "os": "linux", "cpu": "none" }, "sha512-IajOmO+KJK23bj52dFSNCMsz1QP1DqM6cwLUv3W1QwyxkyIWecfafnI555fvSGqEKwjMXVLokcV5ygHW5b3Jbg=="], + "@esbuild/linux-ppc64": ["@esbuild/linux-ppc64@0.25.11", "", { "os": "linux", "cpu": "ppc64" }, "sha512-nbLFgsQQEsBa8XSgSTSlrnBSrpoWh7ioFDUmwo158gIm5NNP+17IYmNWzaIzWmgCxq56vfr34xGkOcZ7jX6CPw=="], - "@esbuild/linux-ppc64": ["@esbuild/linux-ppc64@0.21.5", "", { "os": "linux", "cpu": "ppc64" }, "sha512-1hHV/Z4OEfMwpLO8rp7CvlhBDnjsC3CttJXIhBi+5Aj5r+MBvy4egg7wCbe//hSsT+RvDAG7s81tAvpL2XAE4w=="], + "@esbuild/linux-riscv64": ["@esbuild/linux-riscv64@0.25.11", "", { "os": "linux", "cpu": "none" }, "sha512-HfyAmqZi9uBAbgKYP1yGuI7tSREXwIb438q0nqvlpxAOs3XnZ8RsisRfmVsgV486NdjD7Mw2UrFSw51lzUk1ww=="], - "@esbuild/linux-riscv64": ["@esbuild/linux-riscv64@0.21.5", "", { "os": "linux", "cpu": "none" }, "sha512-2HdXDMd9GMgTGrPWnJzP2ALSokE/0O5HhTUvWIbD3YdjME8JwvSCnNGBnTThKGEB91OZhzrJ4qIIxk/SBmyDDA=="], + "@esbuild/linux-s390x": ["@esbuild/linux-s390x@0.25.11", "", { "os": "linux", "cpu": "s390x" }, "sha512-HjLqVgSSYnVXRisyfmzsH6mXqyvj0SA7pG5g+9W7ESgwA70AXYNpfKBqh1KbTxmQVaYxpzA/SvlB9oclGPbApw=="], - "@esbuild/linux-s390x": ["@esbuild/linux-s390x@0.21.5", "", { "os": "linux", "cpu": "s390x" }, "sha512-zus5sxzqBJD3eXxwvjN1yQkRepANgxE9lgOW2qLnmr8ikMTphkjgXu1HR01K4FJg8h1kEEDAqDcZQtbrRnB41A=="], + "@esbuild/linux-x64": ["@esbuild/linux-x64@0.25.11", "", { "os": "linux", "cpu": "x64" }, "sha512-HSFAT4+WYjIhrHxKBwGmOOSpphjYkcswF449j6EjsjbinTZbp8PJtjsVK1XFJStdzXdy/jaddAep2FGY+wyFAQ=="], - "@esbuild/linux-x64": ["@esbuild/linux-x64@0.21.5", "", { "os": "linux", "cpu": "x64" }, "sha512-1rYdTpyv03iycF1+BhzrzQJCdOuAOtaqHTWJZCWvijKD2N5Xu0TtVC8/+1faWqcP9iBCWOmjmhoH94dH82BxPQ=="], + "@esbuild/netbsd-arm64": ["@esbuild/netbsd-arm64@0.25.11", "", { "os": "none", "cpu": "arm64" }, "sha512-hr9Oxj1Fa4r04dNpWr3P8QKVVsjQhqrMSUzZzf+LZcYjZNqhA3IAfPQdEh1FLVUJSiu6sgAwp3OmwBfbFgG2Xg=="], - "@esbuild/netbsd-x64": ["@esbuild/netbsd-x64@0.21.5", "", { "os": "none", "cpu": "x64" }, "sha512-Woi2MXzXjMULccIwMnLciyZH4nCIMpWQAs049KEeMvOcNADVxo0UBIQPfSmxB3CWKedngg7sWZdLvLczpe0tLg=="], + "@esbuild/netbsd-x64": ["@esbuild/netbsd-x64@0.25.11", "", { "os": "none", "cpu": "x64" }, "sha512-u7tKA+qbzBydyj0vgpu+5h5AeudxOAGncb8N6C9Kh1N4n7wU1Xw1JDApsRjpShRpXRQlJLb9wY28ELpwdPcZ7A=="], - "@esbuild/openbsd-x64": ["@esbuild/openbsd-x64@0.21.5", "", { "os": "openbsd", "cpu": "x64" }, "sha512-HLNNw99xsvx12lFBUwoT8EVCsSvRNDVxNpjZ7bPn947b8gJPzeHWyNVhFsaerc0n3TsbOINvRP2byTZ5LKezow=="], + "@esbuild/openbsd-arm64": ["@esbuild/openbsd-arm64@0.25.11", "", { "os": "openbsd", "cpu": "arm64" }, "sha512-Qq6YHhayieor3DxFOoYM1q0q1uMFYb7cSpLD2qzDSvK1NAvqFi8Xgivv0cFC6J+hWVw2teCYltyy9/m/14ryHg=="], - "@esbuild/sunos-x64": ["@esbuild/sunos-x64@0.21.5", "", { "os": "sunos", "cpu": "x64" }, "sha512-6+gjmFpfy0BHU5Tpptkuh8+uw3mnrvgs+dSPQXQOv3ekbordwnzTVEb4qnIvQcYXq6gzkyTnoZ9dZG+D4garKg=="], + "@esbuild/openbsd-x64": ["@esbuild/openbsd-x64@0.25.11", "", { "os": "openbsd", "cpu": "x64" }, "sha512-CN+7c++kkbrckTOz5hrehxWN7uIhFFlmS/hqziSFVWpAzpWrQoAG4chH+nN3Be+Kzv/uuo7zhX716x3Sn2Jduw=="], - "@esbuild/win32-arm64": ["@esbuild/win32-arm64@0.21.5", "", { "os": "win32", "cpu": "arm64" }, "sha512-Z0gOTd75VvXqyq7nsl93zwahcTROgqvuAcYDUr+vOv8uHhNSKROyU961kgtCD1e95IqPKSQKH7tBTslnS3tA8A=="], + "@esbuild/openharmony-arm64": ["@esbuild/openharmony-arm64@0.25.11", "", { "os": "none", "cpu": "arm64" }, "sha512-rOREuNIQgaiR+9QuNkbkxubbp8MSO9rONmwP5nKncnWJ9v5jQ4JxFnLu4zDSRPf3x4u+2VN4pM4RdyIzDty/wQ=="], - "@esbuild/win32-ia32": ["@esbuild/win32-ia32@0.21.5", "", { "os": "win32", "cpu": "ia32" }, "sha512-SWXFF1CL2RVNMaVs+BBClwtfZSvDgtL//G/smwAc5oVK/UPu2Gu9tIaRgFmYFFKrmg3SyAjSrElf0TiJ1v8fYA=="], + "@esbuild/sunos-x64": ["@esbuild/sunos-x64@0.25.11", "", { "os": "sunos", "cpu": "x64" }, "sha512-nq2xdYaWxyg9DcIyXkZhcYulC6pQ2FuCgem3LI92IwMgIZ69KHeY8T4Y88pcwoLIjbed8n36CyKoYRDygNSGhA=="], - "@esbuild/win32-x64": ["@esbuild/win32-x64@0.21.5", "", { "os": "win32", "cpu": "x64" }, "sha512-tQd/1efJuzPC6rCFwEvLtci/xNFcTZknmXs98FYDfGE4wP9ClFV98nyKrzJKVPMhdDnjzLhdUyMX4PsQAPjwIw=="], + "@esbuild/win32-arm64": ["@esbuild/win32-arm64@0.25.11", "", { "os": "win32", "cpu": "arm64" }, "sha512-3XxECOWJq1qMZ3MN8srCJ/QfoLpL+VaxD/WfNRm1O3B4+AZ/BnLVgFbUV3eiRYDMXetciH16dwPbbHqwe1uU0Q=="], - "@eslint-community/eslint-utils": ["@eslint-community/eslint-utils@4.7.0", "", { "dependencies": { "eslint-visitor-keys": "^3.4.3" }, "peerDependencies": { "eslint": "^6.0.0 || ^7.0.0 || >=8.0.0" } }, "sha512-dyybb3AcajC7uha6CvhdVRJqaKyn7w2YKqKyAN37NKYgZT36w+iRb0Dymmc5qEJ549c/S31cMMSFd75bteCpCw=="], + "@esbuild/win32-ia32": ["@esbuild/win32-ia32@0.25.11", "", { "os": "win32", "cpu": "ia32" }, "sha512-3ukss6gb9XZ8TlRyJlgLn17ecsK4NSQTmdIXRASVsiS2sQ6zPPZklNJT5GR5tE/MUarymmy8kCEf5xPCNCqVOA=="], + + "@esbuild/win32-x64": ["@esbuild/win32-x64@0.25.11", "", { "os": "win32", "cpu": "x64" }, "sha512-D7Hpz6A2L4hzsRpPaCYkQnGOotdUpDzSGRIv9I+1ITdHROSFUWW95ZPZWQmGka1Fg7W3zFJowyn9WGwMJ0+KPA=="], + + "@eslint-community/eslint-utils": ["@eslint-community/eslint-utils@4.9.0", "", { "dependencies": { "eslint-visitor-keys": "^3.4.3" }, "peerDependencies": { "eslint": "^6.0.0 || ^7.0.0 || >=8.0.0" } }, "sha512-ayVFHdtZ+hsq1t2Dy24wCmGXGe4q9Gu3smhLYALJrr473ZH27MsnSL+LKUlimp4BWJqMDMLmPpx/Q9R3OAlL4g=="], "@eslint-community/regexpp": ["@eslint-community/regexpp@4.12.1", "", {}, "sha512-CCZCDJuduB9OUkFkY2IgppNZMi2lBQgD2qzwXkEia16cge2pijY/aXi96CJMquDMn3nJdlPV1A5KrJEXwfLNzQ=="], - "@eslint/config-array": ["@eslint/config-array@0.20.0", "", { "dependencies": { "@eslint/object-schema": "^2.1.6", "debug": "^4.3.1", "minimatch": "^3.1.2" } }, "sha512-fxlS1kkIjx8+vy2SjuCB94q3htSNrufYTXubwiBFeaQHbH6Ipi43gFJq2zCMt6PHhImH3Xmr0NksKDvchWlpQQ=="], + "@eslint/config-array": ["@eslint/config-array@0.21.1", "", { "dependencies": { "@eslint/object-schema": "^2.1.7", "debug": "^4.3.1", "minimatch": "^3.1.2" } }, "sha512-aw1gNayWpdI/jSYVgzN5pL0cfzU02GT3NBpeT/DXbx1/1x7ZKxFPd9bwrzygx/qiwIQiJ1sw/zD8qY/kRvlGHA=="], - "@eslint/config-helpers": ["@eslint/config-helpers@0.2.2", "", {}, "sha512-+GPzk8PlG0sPpzdU5ZvIRMPidzAnZDl/s9L+y13iodqvb8leL53bTannOrQ/Im7UkpsmFU5Ily5U60LWixnmLg=="], + "@eslint/config-helpers": ["@eslint/config-helpers@0.4.1", "", { "dependencies": { "@eslint/core": "^0.16.0" } }, "sha512-csZAzkNhsgwb0I/UAV6/RGFTbiakPCf0ZrGmrIxQpYvGZ00PhTkSnyKNolphgIvmnJeGw6rcGVEXfTzUnFuEvw=="], - "@eslint/core": ["@eslint/core@0.14.0", "", { "dependencies": { "@types/json-schema": "^7.0.15" } }, "sha512-qIbV0/JZr7iSDjqAc60IqbLdsj9GDt16xQtWD+B78d/HAlvysGdZZ6rpJHGAc2T0FQx1X6thsSPdnoiGKdNtdg=="], + "@eslint/core": ["@eslint/core@0.16.0", "", { "dependencies": { "@types/json-schema": "^7.0.15" } }, "sha512-nmC8/totwobIiFcGkDza3GIKfAw1+hLiYVrh3I1nIomQ8PEr5cxg34jnkmGawul/ep52wGRAcyeDCNtWKSOj4Q=="], "@eslint/eslintrc": ["@eslint/eslintrc@3.3.1", "", { "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" } }, "sha512-gtF186CXhIl1p4pJNGZw8Yc6RlshoePRvE0X91oPGb3vZ8pM3qOS9W9NGPat9LziaBV7XrJWGylNQXkGcnM3IQ=="], - "@eslint/js": ["@eslint/js@9.27.0", "", {}, "sha512-G5JD9Tu5HJEu4z2Uo4aHY2sLV64B7CDMXxFzqzjl3NKd6RVzSXNoE80jk7Y0lJkTTkjiIhBAqmlYwjuBY3tvpA=="], + "@eslint/js": ["@eslint/js@9.38.0", "", {}, "sha512-UZ1VpFvXf9J06YG9xQBdnzU+kthors6KjhMAl6f4gH4usHyh31rUf2DLGInT8RFYIReYXNSydgPY0V2LuWgl7A=="], - "@eslint/object-schema": ["@eslint/object-schema@2.1.6", "", {}, "sha512-RBMg5FRL0I0gs51M/guSAj5/e14VQ4tpZnQNWwuDT66P14I43ItmPfIZRhO9fUVIPOAQXU47atlywZ/czoqFPA=="], + "@eslint/object-schema": ["@eslint/object-schema@2.1.7", "", {}, "sha512-VtAOaymWVfZcmZbp6E2mympDIHvyjXs/12LqWYjVw6qjrfF+VK+fyG33kChz3nnK+SU5/NeHOqrTEHS8sXO3OA=="], - "@eslint/plugin-kit": ["@eslint/plugin-kit@0.3.1", "", { "dependencies": { "@eslint/core": "^0.14.0", "levn": "^0.4.1" } }, "sha512-0J+zgWxHN+xXONWIyPWKFMgVuJoZuGiIFu8yxk7RJjxkzpGmyja5wRFqZIVtjDVOQpV+Rw0iOAjYPE2eQyjr0w=="], + "@eslint/plugin-kit": ["@eslint/plugin-kit@0.4.0", "", { "dependencies": { "@eslint/core": "^0.16.0", "levn": "^0.4.1" } }, "sha512-sB5uyeq+dwCWyPi31B2gQlVlo+j5brPlWx4yZBrEaRo/nhdDE8Xke1gsGgtiBdaBTxuTkceLVuVt/pclrasb0A=="], "@humanfs/core": ["@humanfs/core@0.19.1", "", {}, "sha512-5DyQ4+1JEUzejeK1JGICcideyfUbGixgS9jNgex5nqkW+cY7WZhxBigmieN5Qnw9ZosSNVC9KQKyb+GUaGyKUA=="], @@ -140,13 +148,13 @@ "@jridgewell/set-array": ["@jridgewell/set-array@1.2.1", "", {}, "sha512-R8gLRTZeyp03ymzP/6Lil/28tGeGEzhx1q2k703KGWRAI1VdvPIXdG70VJc2pAMw3NA6JKL5hhFu1sJX0Mnn/A=="], - "@jridgewell/sourcemap-codec": ["@jridgewell/sourcemap-codec@1.5.0", "", {}, "sha512-gv3ZRaISU3fjPAgNsriBRqGWQL6quFx04YMPW/zD8XMLsU32mhCCbfbO6KZFLjvYpCZ8zyDEgqsgf+PwPaM7GQ=="], + "@jridgewell/sourcemap-codec": ["@jridgewell/sourcemap-codec@1.5.5", "", {}, "sha512-cYQ9310grqxueWbl+WuIUIaiUaDcj7WOq5fVhEljNVgRfOUhY9fy2zTvfoqWsnebh8Sl70VScFbICvJnLKB0Og=="], "@jridgewell/trace-mapping": ["@jridgewell/trace-mapping@0.3.30", "", { "dependencies": { "@jridgewell/resolve-uri": "^3.1.0", "@jridgewell/sourcemap-codec": "^1.4.14" } }, "sha512-GQ7Nw5G2lTu/BtHTKfXhKHok2WGetd4XYcVKGx00SjAk8GMwgJM3zr6zORiPGuOE+/vkc90KtTosSSvaCjKb2Q=="], - "@kirick/lint": ["@kirick/lint@0.2.7", "", { "dependencies": { "@stylistic/eslint-plugin": "^4.4.0", "eslint": "9.27.0", "eslint-plugin-jsdoc": "50.6.17", "eslint-plugin-n": "^17.18.0", "eslint-plugin-promise": "^7.2.1", "eslint-plugin-unicorn": "59.0.1", "eslint-plugin-vue": "^10.1.0", "typescript-eslint": "8.32.1" }, "bin": { "lint": "dist/main.js" } }, "sha512-ZX0C0W0nZBXRJDpGWPrpOonQUkvPyh0XWkVqK36/aEwPLbZcQJ2yGKFvtbL40ehrUObzfRZjExOuFEWVzWv9cw=="], + "@kirick/lint": ["@kirick/lint@0.2.12", "", { "dependencies": { "@stylistic/eslint-plugin": "5.5.0", "eslint": "9.38.0", "eslint-plugin-jsdoc": "61.1.9", "eslint-plugin-n": "17.23.1", "eslint-plugin-promise": "7.2.1", "eslint-plugin-unicorn": "62.0.0", "eslint-plugin-vue": "10.5.1", "typescript-eslint": "8.46.2" }, "bin": { "lint": "dist/main.js" } }, "sha512-eE//5Z21/Sdb8JjhL2x27ZPDjaVLWmaIJ50zUJC0d08u6VPqCLPMVryYDM3NLJn8G9YrBLqmKDQ9X+0+dsuOWw=="], - "@napi-rs/wasm-runtime": ["@napi-rs/wasm-runtime@1.0.3", "", { "dependencies": { "@emnapi/core": "^1.4.5", "@emnapi/runtime": "^1.4.5", "@tybys/wasm-util": "^0.10.0" } }, "sha512-rZxtMsLwjdXkMUGC3WwsPwLNVqVqnTJT6MNIB6e+5fhMcSCPP0AOsNWuMQ5mdCq6HNjs/ZeWAEchpqeprqBD2Q=="], + "@napi-rs/wasm-runtime": ["@napi-rs/wasm-runtime@1.0.7", "", { "dependencies": { "@emnapi/core": "^1.5.0", "@emnapi/runtime": "^1.5.0", "@tybys/wasm-util": "^0.10.1" } }, "sha512-SeDnOO0Tk7Okiq6DbXmmBODgOAb9dp9gjlphokTUxmt8U3liIP1ZsozBahH69j/RJv+Rfs6IwUKHTgQYJ/HBAw=="], "@nodelib/fs.scandir": ["@nodelib/fs.scandir@2.1.5", "", { "dependencies": { "@nodelib/fs.stat": "2.0.5", "run-parallel": "^1.1.9" } }, "sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g=="], @@ -154,97 +162,111 @@ "@nodelib/fs.walk": ["@nodelib/fs.walk@1.2.8", "", { "dependencies": { "@nodelib/fs.scandir": "2.1.5", "fastq": "^1.6.0" } }, "sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg=="], - "@oxc-project/runtime": ["@oxc-project/runtime@0.82.3", "", {}, "sha512-LNh5GlJvYHAnMurO+EyA8jJwN1rki7l3PSHuosDh2I7h00T6/u9rCkUjg/SvPmT1CZzvhuW0y+gf7jcqUy/Usg=="], + "@oxc-project/types": ["@oxc-project/types@0.95.0", "", {}, "sha512-vACy7vhpMPhjEJhULNxrdR0D943TkA/MigMpJCHmBHvMXxRStRi/dPtTlfQ3uDwWSzRpT8z+7ImjZVf8JWBocQ=="], - "@oxc-project/types": ["@oxc-project/types@0.82.3", "", {}, "sha512-6nCUxBnGX0c6qfZW5MaF6/fmu5dHJDMiMPaioKHKs5mi5+8/FHQ7WGjgQIz1zxpmceMYfdIXkOaLYE+ejbuOtA=="], + "@oxlint/darwin-arm64": ["@oxlint/darwin-arm64@1.24.0", "", { "os": "darwin", "cpu": "arm64" }, "sha512-1Kd2+Ai1ttskhbJR+DNU4Y4YEDyP/cd50nWt2rAe2aE78dMOalaVGps3s8UnJkXpDL9ZqkgOHVDE5Doj2lxatw=="], - "@oxlint/darwin-arm64": ["@oxlint/darwin-arm64@1.3.0", "", { "os": "darwin", "cpu": "arm64" }, "sha512-TcCaETXYfiEfS+u/gZNND4WwEEtnJJjqg8BIC56WiCQDduYTvmmbQ0vxtqdNXlFzlvmRpZCSs7qaqXNy8/8FLA=="], + "@oxlint/darwin-x64": ["@oxlint/darwin-x64@1.24.0", "", { "os": "darwin", "cpu": "x64" }, "sha512-/R9VbnuTp7bLIBh6ucDHjx0po0wLQODLqzy+L/Frn5z4ifMVdE63DB+LHO8QAj+WEQleQq3u/MMms7RFPulCLA=="], - "@oxlint/darwin-x64": ["@oxlint/darwin-x64@1.3.0", "", { "os": "darwin", "cpu": "x64" }, "sha512-REgq9s1ZWuh++Vi+mUPNddLTp/D+iu+T8nLd3QM1dzQoBD/SZ7wRX3Mdv8QGT/m8dknmDBQuKAP6T47ox9HRSA=="], + "@oxlint/linux-arm64-gnu": ["@oxlint/linux-arm64-gnu@1.24.0", "", { "os": "linux", "cpu": "arm64" }, "sha512-fA90bIQ1b44eNg0uULlTonqsADVIBnMz169mav6IhfZL9V6DpBCUWrV+8tEQCxbDvYC0WY1guBpPo2QWUnC/Dw=="], - "@oxlint/linux-arm64-gnu": ["@oxlint/linux-arm64-gnu@1.3.0", "", { "os": "linux", "cpu": "arm64" }, "sha512-QAS8AWKDcDeUe8mJaw/pF2D9+js8FbFTo75AiekZKNm9V6QAAiCkyvesmILD8RrStw9aV2D/apOD71vsfcDoGA=="], + "@oxlint/linux-arm64-musl": ["@oxlint/linux-arm64-musl@1.24.0", "", { "os": "linux", "cpu": "arm64" }, "sha512-p7Bv9FTQ1lf4Z7OiIFwiy+cY2fxN6IJc0+2gJ4z2fpaQ0J2rQQcKdJ5RLQTxf+tAu7hyqjc6bf61EAGa9lb/GA=="], - "@oxlint/linux-arm64-musl": ["@oxlint/linux-arm64-musl@1.3.0", "", { "os": "linux", "cpu": "arm64" }, "sha512-rAbz0KFkk5GPdERoFO4ZUZmVkECnHXjRG0O2MeT5zY7ddlyZUjEk1cWjw+HCtWVdKkqhZJeNFMuEiRLkpzBIIw=="], + "@oxlint/linux-x64-gnu": ["@oxlint/linux-x64-gnu@1.24.0", "", { "os": "linux", "cpu": "x64" }, "sha512-wIQOpTONiJ9pYPnLEq7UFuml8mpmSFTfUveNbT2rw9iXfj2nLMf7NIqGnUYQdvnnOi+maag9uei/WImXIm9LQQ=="], - "@oxlint/linux-x64-gnu": ["@oxlint/linux-x64-gnu@1.3.0", "", { "os": "linux", "cpu": "x64" }, "sha512-6uLO1WsJwCtVNGHtjXwg2TRvxQYttYJKMjSdv6RUXGWY1AI+/+yHzvu+phU/F40uNC7CFhFnqWDuPaSZ49hdAQ=="], + "@oxlint/linux-x64-musl": ["@oxlint/linux-x64-musl@1.24.0", "", { "os": "linux", "cpu": "x64" }, "sha512-HxcDX/SpTH7yC/Rn2MinjSHZmNpn79yJkBid792DWjP9bo0CnlNXOXMPXsbm+WqptvqQ9yUPCxf7KascUvxLyQ=="], - "@oxlint/linux-x64-musl": ["@oxlint/linux-x64-musl@1.3.0", "", { "os": "linux", "cpu": "x64" }, "sha512-+vrmJUHgtJmgIo+L9eTP04NI/OQNCOZtQo6I49qGWc9cpr+0MnIh9KMcyAOxmzVTF5g+CF1I/1bUz4pk4I3LDw=="], + "@oxlint/win32-arm64": ["@oxlint/win32-arm64@1.24.0", "", { "os": "win32", "cpu": "arm64" }, "sha512-P1KtZ/xL+TcNTTmOtEsVrpqAdmpu2UCRAILjoqQyrYvI/CW6SdvoJfMBTntKOZaB52Peq2BHTgsYovON8q4FfQ=="], - "@oxlint/win32-arm64": ["@oxlint/win32-arm64@1.3.0", "", { "os": "win32", "cpu": "arm64" }, "sha512-k+ETUVl+O3b8Rcd2PP5V3LqQ2QoN/TOX2f19XXHZEynbVLY3twLYPb3hLdXqoo7CKRq3RJdTfn1upHH48/qrZQ=="], - - "@oxlint/win32-x64": ["@oxlint/win32-x64@1.3.0", "", { "os": "win32", "cpu": "x64" }, "sha512-nWSgK0fT02TQ/BiAUCd13BaobtHySkCDcQaL+NOmhgeb0tNWjtYiktuluahaIqFcYJPWczVlbs8DU/Eqo8vsug=="], + "@oxlint/win32-x64": ["@oxlint/win32-x64@1.24.0", "", { "os": "win32", "cpu": "x64" }, "sha512-JMbMm7i1esFl12fRdOQwoeEeufWXxihOme8pZpI6jrwWK1kCIANMb5agI5Lkjf5vToQOP3DLXYc29aDm16fw6g=="], "@publint/pack": ["@publint/pack@0.1.2", "", {}, "sha512-S+9ANAvUmjutrshV4jZjaiG8XQyuJIZ8a4utWmN/vW1sgQ9IfBnPndwkmQYw53QmouOIytT874u65HEmu6H5jw=="], "@quansync/fs": ["@quansync/fs@0.1.5", "", { "dependencies": { "quansync": "^0.2.11" } }, "sha512-lNS9hL2aS2NZgNW7BBj+6EBl4rOf8l+tQ0eRY6JWCI8jI2kc53gSoqbjojU0OnAWhzoXiOjFyGsHcDGePB3lhA=="], - "@rolldown/binding-android-arm64": ["@rolldown/binding-android-arm64@1.0.0-beta.34", "", { "os": "android", "cpu": "arm64" }, "sha512-jf5GNe5jP3Sr1Tih0WKvg2bzvh5T/1TA0fn1u32xSH7ca/p5t+/QRr4VRFCV/na5vjwKEhwWrChsL2AWlY+eoA=="], + "@rolldown/binding-android-arm64": ["@rolldown/binding-android-arm64@1.0.0-beta.45", "", { "os": "android", "cpu": "arm64" }, "sha512-bfgKYhFiXJALeA/riil908+2vlyWGdwa7Ju5S+JgWZYdR4jtiPOGdM6WLfso1dojCh+4ZWeiTwPeV9IKQEX+4g=="], + + "@rolldown/binding-darwin-arm64": ["@rolldown/binding-darwin-arm64@1.0.0-beta.45", "", { "os": "darwin", "cpu": "arm64" }, "sha512-xjCv4CRVsSnnIxTuyH1RDJl5OEQ1c9JYOwfDAHddjJDxCw46ZX9q80+xq7Eok7KC4bRSZudMJllkvOKv0T9SeA=="], - "@rolldown/binding-darwin-arm64": ["@rolldown/binding-darwin-arm64@1.0.0-beta.34", "", { "os": "darwin", "cpu": "arm64" }, "sha512-2F/TqH4QuJQ34tgWxqBjFL3XV1gMzeQgUO8YRtCPGBSP0GhxtoFzsp7KqmQEothsxztlv+KhhT9Dbg3HHwHViQ=="], + "@rolldown/binding-darwin-x64": ["@rolldown/binding-darwin-x64@1.0.0-beta.45", "", { "os": "darwin", "cpu": "x64" }, "sha512-ddcO9TD3D/CLUa/l8GO8LHzBOaZqWg5ClMy3jICoxwCuoz47h9dtqPsIeTiB6yR501LQTeDsjA4lIFd7u3Ljfw=="], - "@rolldown/binding-darwin-x64": ["@rolldown/binding-darwin-x64@1.0.0-beta.34", "", { "os": "darwin", "cpu": "x64" }, "sha512-E1QuFslgLWbHQ8Qli/AqUKdfg0pockQPwRxVbhNQ74SciZEZpzLaujkdmOLSccMlSXDfFCF8RPnMoRAzQ9JV8Q=="], + "@rolldown/binding-freebsd-x64": ["@rolldown/binding-freebsd-x64@1.0.0-beta.45", "", { "os": "freebsd", "cpu": "x64" }, "sha512-MBTWdrzW9w+UMYDUvnEuh0pQvLENkl2Sis15fHTfHVW7ClbGuez+RWopZudIDEGkpZXdeI4CkRXk+vdIIebrmg=="], - "@rolldown/binding-freebsd-x64": ["@rolldown/binding-freebsd-x64@1.0.0-beta.34", "", { "os": "freebsd", "cpu": "x64" }, "sha512-VS8VInNCwnkpI9WeQaWu3kVBq9ty6g7KrHdLxYMzeqz24+w9hg712TcWdqzdY6sn+24lUoMD9jTZrZ/qfVpk0g=="], + "@rolldown/binding-linux-arm-gnueabihf": ["@rolldown/binding-linux-arm-gnueabihf@1.0.0-beta.45", "", { "os": "linux", "cpu": "arm" }, "sha512-4YgoCFiki1HR6oSg+GxxfzfnVCesQxLF1LEnw9uXS/MpBmuog0EOO2rYfy69rWP4tFZL9IWp6KEfGZLrZ7aUog=="], - "@rolldown/binding-linux-arm-gnueabihf": ["@rolldown/binding-linux-arm-gnueabihf@1.0.0-beta.34", "", { "os": "linux", "cpu": "arm" }, "sha512-4St4emjcnULnxJYb/5ZDrH/kK/j6PcUgc3eAqH5STmTrcF+I9m/X2xvSF2a2bWv1DOQhxBewThu0KkwGHdgu5w=="], + "@rolldown/binding-linux-arm64-gnu": ["@rolldown/binding-linux-arm64-gnu@1.0.0-beta.45", "", { "os": "linux", "cpu": "arm64" }, "sha512-LE1gjAwQRrbCOorJJ7LFr10s5vqYf5a00V5Ea9wXcT2+56n5YosJkcp8eQ12FxRBv2YX8dsdQJb+ZTtYJwb6XQ=="], - "@rolldown/binding-linux-arm64-gnu": ["@rolldown/binding-linux-arm64-gnu@1.0.0-beta.34", "", { "os": "linux", "cpu": "arm64" }, "sha512-a737FTqhFUoWfnebS2SnQ2BS50p0JdukdkUBwy2J06j4hZ6Eej0zEB8vTfAqoCjn8BQKkXBy+3Sx0IRkgwz1gA=="], + "@rolldown/binding-linux-arm64-musl": ["@rolldown/binding-linux-arm64-musl@1.0.0-beta.45", "", { "os": "linux", "cpu": "arm64" }, "sha512-tdy8ThO/fPp40B81v0YK3QC+KODOmzJzSUOO37DinQxzlTJ026gqUSOM8tzlVixRbQJltgVDCTYF8HNPRErQTA=="], - "@rolldown/binding-linux-arm64-musl": ["@rolldown/binding-linux-arm64-musl@1.0.0-beta.34", "", { "os": "linux", "cpu": "arm64" }, "sha512-NH+FeQWKyuw0k+PbXqpFWNfvD8RPvfJk766B/njdaWz4TmiEcSB0Nb6guNw1rBpM1FmltQYb3fFnTumtC6pRfA=="], + "@rolldown/binding-linux-x64-gnu": ["@rolldown/binding-linux-x64-gnu@1.0.0-beta.45", "", { "os": "linux", "cpu": "x64" }, "sha512-lS082ROBWdmOyVY/0YB3JmsiClaWoxvC+dA8/rbhyB9VLkvVEaihLEOr4CYmrMse151C4+S6hCw6oa1iewox7g=="], - "@rolldown/binding-linux-x64-gnu": ["@rolldown/binding-linux-x64-gnu@1.0.0-beta.34", "", { "os": "linux", "cpu": "x64" }, "sha512-Q3RSCivp8pNadYK8ke3hLnQk08BkpZX9BmMjgwae2FWzdxhxxUiUzd9By7kneUL0vRQ4uRnhD9VkFQ+Haeqdvw=="], + "@rolldown/binding-linux-x64-musl": ["@rolldown/binding-linux-x64-musl@1.0.0-beta.45", "", { "os": "linux", "cpu": "x64" }, "sha512-Hi73aYY0cBkr1/SvNQqH8Cd+rSV6S9RB5izCv0ySBcRnd/Wfn5plguUoGYwBnhHgFbh6cPw9m2dUVBR6BG1gxA=="], - "@rolldown/binding-linux-x64-musl": ["@rolldown/binding-linux-x64-musl@1.0.0-beta.34", "", { "os": "linux", "cpu": "x64" }, "sha512-wDd/HrNcVoBhWWBUW3evJHoo7GJE/RofssBy3Dsiip05YUBmokQVrYAyrboOY4dzs/lJ7HYeBtWQ9hj8wlyF0A=="], + "@rolldown/binding-openharmony-arm64": ["@rolldown/binding-openharmony-arm64@1.0.0-beta.45", "", { "os": "none", "cpu": "arm64" }, "sha512-fljEqbO7RHHogNDxYtTzr+GNjlfOx21RUyGmF+NrkebZ8emYYiIqzPxsaMZuRx0rgZmVmliOzEp86/CQFDKhJQ=="], - "@rolldown/binding-openharmony-arm64": ["@rolldown/binding-openharmony-arm64@1.0.0-beta.34", "", { "os": "none", "cpu": "arm64" }, "sha512-dH3FTEV6KTNWpYSgjSXZzeX7vLty9oBYn6R3laEdhwZftQwq030LKL+5wyQdlbX5pnbh4h127hpv3Hl1+sj8dg=="], + "@rolldown/binding-wasm32-wasi": ["@rolldown/binding-wasm32-wasi@1.0.0-beta.45", "", { "dependencies": { "@napi-rs/wasm-runtime": "^1.0.7" }, "cpu": "none" }, "sha512-ZJDB7lkuZE9XUnWQSYrBObZxczut+8FZ5pdanm8nNS1DAo8zsrPuvGwn+U3fwU98WaiFsNrA4XHngesCGr8tEQ=="], - "@rolldown/binding-wasm32-wasi": ["@rolldown/binding-wasm32-wasi@1.0.0-beta.34", "", { "dependencies": { "@napi-rs/wasm-runtime": "^1.0.3" }, "cpu": "none" }, "sha512-y5BUf+QtO0JsIDKA51FcGwvhJmv89BYjUl8AmN7jqD6k/eU55mH6RJYnxwCsODq5m7KSSTigVb6O7/GqB8wbPw=="], + "@rolldown/binding-win32-arm64-msvc": ["@rolldown/binding-win32-arm64-msvc@1.0.0-beta.45", "", { "os": "win32", "cpu": "arm64" }, "sha512-zyzAjItHPUmxg6Z8SyRhLdXlJn3/D9KL5b9mObUrBHhWS/GwRH4665xCiFqeuktAhhWutqfc+rOV2LjK4VYQGQ=="], - "@rolldown/binding-win32-arm64-msvc": ["@rolldown/binding-win32-arm64-msvc@1.0.0-beta.34", "", { "os": "win32", "cpu": "arm64" }, "sha512-ga5hFhdTwpaNxEiuxZHWnD3ed0GBAzbgzS5tRHpe0ObptxM1a9Xrq6TVfNQirBLwb5Y7T/FJmJi3pmdLy95ljg=="], + "@rolldown/binding-win32-ia32-msvc": ["@rolldown/binding-win32-ia32-msvc@1.0.0-beta.45", "", { "os": "win32", "cpu": "ia32" }, "sha512-wODcGzlfxqS6D7BR0srkJk3drPwXYLu7jPHN27ce2c4PUnVVmJnp9mJzUQGT4LpmHmmVdMZ+P6hKvyTGBzc1CA=="], - "@rolldown/binding-win32-ia32-msvc": ["@rolldown/binding-win32-ia32-msvc@1.0.0-beta.34", "", { "os": "win32", "cpu": "ia32" }, "sha512-4/MBp9T9eRnZskxWr8EXD/xHvLhdjWaeX/qY9LPRG1JdCGV3DphkLTy5AWwIQ5jhAy2ZNJR5z2fYRlpWU0sIyQ=="], + "@rolldown/binding-win32-x64-msvc": ["@rolldown/binding-win32-x64-msvc@1.0.0-beta.45", "", { "os": "win32", "cpu": "x64" }, "sha512-wiU40G1nQo9rtfvF9jLbl79lUgjfaD/LTyUEw2Wg/gdF5OhjzpKMVugZQngO+RNdwYaNj+Fs+kWBWfp4VXPMHA=="], - "@rolldown/binding-win32-x64-msvc": ["@rolldown/binding-win32-x64-msvc@1.0.0-beta.34", "", { "os": "win32", "cpu": "x64" }, "sha512-7O5iUBX6HSBKlQU4WykpUoEmb0wQmonb6ziKFr3dJTHud2kzDnWMqk344T0qm3uGv9Ddq6Re/94pInxo1G2d4w=="], + "@rolldown/pluginutils": ["@rolldown/pluginutils@1.0.0-beta.45", "", {}, "sha512-Le9ulGCrD8ggInzWw/k2J8QcbPz7eGIOWqfJ2L+1R0Opm7n6J37s2hiDWlh6LJN0Lk9L5sUzMvRHKW7UxBZsQA=="], - "@rolldown/pluginutils": ["@rolldown/pluginutils@1.0.0-beta.34", "", {}, "sha512-LyAREkZHP5pMom7c24meKmJCdhf2hEyvam2q0unr3or9ydwDL+DJ8chTF6Av/RFPb3rH8UFBdMzO5MxTZW97oA=="], + "@rollup/rollup-android-arm-eabi": ["@rollup/rollup-android-arm-eabi@4.52.5", "", { "os": "android", "cpu": "arm" }, "sha512-8c1vW4ocv3UOMp9K+gToY5zL2XiiVw3k7f1ksf4yO1FlDFQ1C2u72iACFnSOceJFsWskc2WZNqeRhFRPzv+wtQ=="], - "@rollup/rollup-android-arm-eabi": ["@rollup/rollup-android-arm-eabi@4.21.2", "", { "os": "android", "cpu": "arm" }, "sha512-fSuPrt0ZO8uXeS+xP3b+yYTCBUd05MoSp2N/MFOgjhhUhMmchXlpTQrTpI8T+YAwAQuK7MafsCOxW7VrPMrJcg=="], + "@rollup/rollup-android-arm64": ["@rollup/rollup-android-arm64@4.52.5", "", { "os": "android", "cpu": "arm64" }, "sha512-mQGfsIEFcu21mvqkEKKu2dYmtuSZOBMmAl5CFlPGLY94Vlcm+zWApK7F/eocsNzp8tKmbeBP8yXyAbx0XHsFNA=="], - "@rollup/rollup-android-arm64": ["@rollup/rollup-android-arm64@4.21.2", "", { "os": "android", "cpu": "arm64" }, "sha512-xGU5ZQmPlsjQS6tzTTGwMsnKUtu0WVbl0hYpTPauvbRAnmIvpInhJtgjj3mcuJpEiuUw4v1s4BimkdfDWlh7gA=="], + "@rollup/rollup-darwin-arm64": ["@rollup/rollup-darwin-arm64@4.52.5", "", { "os": "darwin", "cpu": "arm64" }, "sha512-takF3CR71mCAGA+v794QUZ0b6ZSrgJkArC+gUiG6LB6TQty9T0Mqh3m2ImRBOxS2IeYBo4lKWIieSvnEk2OQWA=="], - "@rollup/rollup-darwin-arm64": ["@rollup/rollup-darwin-arm64@4.21.2", "", { "os": "darwin", "cpu": "arm64" }, "sha512-99AhQ3/ZMxU7jw34Sq8brzXqWH/bMnf7ZVhvLk9QU2cOepbQSVTns6qoErJmSiAvU3InRqC2RRZ5ovh1KN0d0Q=="], + "@rollup/rollup-darwin-x64": ["@rollup/rollup-darwin-x64@4.52.5", "", { "os": "darwin", "cpu": "x64" }, "sha512-W901Pla8Ya95WpxDn//VF9K9u2JbocwV/v75TE0YIHNTbhqUTv9w4VuQ9MaWlNOkkEfFwkdNhXgcLqPSmHy0fA=="], - "@rollup/rollup-darwin-x64": ["@rollup/rollup-darwin-x64@4.21.2", "", { "os": "darwin", "cpu": "x64" }, "sha512-ZbRaUvw2iN/y37x6dY50D8m2BnDbBjlnMPotDi/qITMJ4sIxNY33HArjikDyakhSv0+ybdUxhWxE6kTI4oX26w=="], + "@rollup/rollup-freebsd-arm64": ["@rollup/rollup-freebsd-arm64@4.52.5", "", { "os": "freebsd", "cpu": "arm64" }, "sha512-QofO7i7JycsYOWxe0GFqhLmF6l1TqBswJMvICnRUjqCx8b47MTo46W8AoeQwiokAx3zVryVnxtBMcGcnX12LvA=="], - "@rollup/rollup-linux-arm-gnueabihf": ["@rollup/rollup-linux-arm-gnueabihf@4.21.2", "", { "os": "linux", "cpu": "arm" }, "sha512-ztRJJMiE8nnU1YFcdbd9BcH6bGWG1z+jP+IPW2oDUAPxPjo9dverIOyXz76m6IPA6udEL12reYeLojzW2cYL7w=="], + "@rollup/rollup-freebsd-x64": ["@rollup/rollup-freebsd-x64@4.52.5", "", { "os": "freebsd", "cpu": "x64" }, "sha512-jr21b/99ew8ujZubPo9skbrItHEIE50WdV86cdSoRkKtmWa+DDr6fu2c/xyRT0F/WazZpam6kk7IHBerSL7LDQ=="], - "@rollup/rollup-linux-arm-musleabihf": ["@rollup/rollup-linux-arm-musleabihf@4.21.2", "", { "os": "linux", "cpu": "arm" }, "sha512-flOcGHDZajGKYpLV0JNc0VFH361M7rnV1ee+NTeC/BQQ1/0pllYcFmxpagltANYt8FYf9+kL6RSk80Ziwyhr7w=="], + "@rollup/rollup-linux-arm-gnueabihf": ["@rollup/rollup-linux-arm-gnueabihf@4.52.5", "", { "os": "linux", "cpu": "arm" }, "sha512-PsNAbcyv9CcecAUagQefwX8fQn9LQ4nZkpDboBOttmyffnInRy8R8dSg6hxxl2Re5QhHBf6FYIDhIj5v982ATQ=="], - "@rollup/rollup-linux-arm64-gnu": ["@rollup/rollup-linux-arm64-gnu@4.21.2", "", { "os": "linux", "cpu": "arm64" }, "sha512-69CF19Kp3TdMopyteO/LJbWufOzqqXzkrv4L2sP8kfMaAQ6iwky7NoXTp7bD6/irKgknDKM0P9E/1l5XxVQAhw=="], + "@rollup/rollup-linux-arm-musleabihf": ["@rollup/rollup-linux-arm-musleabihf@4.52.5", "", { "os": "linux", "cpu": "arm" }, "sha512-Fw4tysRutyQc/wwkmcyoqFtJhh0u31K+Q6jYjeicsGJJ7bbEq8LwPWV/w0cnzOqR2m694/Af6hpFayLJZkG2VQ=="], - "@rollup/rollup-linux-arm64-musl": ["@rollup/rollup-linux-arm64-musl@4.21.2", "", { "os": "linux", "cpu": "arm64" }, "sha512-48pD/fJkTiHAZTnZwR0VzHrao70/4MlzJrq0ZsILjLW/Ab/1XlVUStYyGt7tdyIiVSlGZbnliqmult/QGA2O2w=="], + "@rollup/rollup-linux-arm64-gnu": ["@rollup/rollup-linux-arm64-gnu@4.52.5", "", { "os": "linux", "cpu": "arm64" }, "sha512-a+3wVnAYdQClOTlyapKmyI6BLPAFYs0JM8HRpgYZQO02rMR09ZcV9LbQB+NL6sljzG38869YqThrRnfPMCDtZg=="], - "@rollup/rollup-linux-powerpc64le-gnu": ["@rollup/rollup-linux-powerpc64le-gnu@4.21.2", "", { "os": "linux", "cpu": "ppc64" }, "sha512-cZdyuInj0ofc7mAQpKcPR2a2iu4YM4FQfuUzCVA2u4HI95lCwzjoPtdWjdpDKyHxI0UO82bLDoOaLfpZ/wviyQ=="], + "@rollup/rollup-linux-arm64-musl": ["@rollup/rollup-linux-arm64-musl@4.52.5", "", { "os": "linux", "cpu": "arm64" }, "sha512-AvttBOMwO9Pcuuf7m9PkC1PUIKsfaAJ4AYhy944qeTJgQOqJYJ9oVl2nYgY7Rk0mkbsuOpCAYSs6wLYB2Xiw0Q=="], - "@rollup/rollup-linux-riscv64-gnu": ["@rollup/rollup-linux-riscv64-gnu@4.21.2", "", { "os": "linux", "cpu": "none" }, "sha512-RL56JMT6NwQ0lXIQmMIWr1SW28z4E4pOhRRNqwWZeXpRlykRIlEpSWdsgNWJbYBEWD84eocjSGDu/XxbYeCmwg=="], + "@rollup/rollup-linux-loong64-gnu": ["@rollup/rollup-linux-loong64-gnu@4.52.5", "", { "os": "linux", "cpu": "none" }, "sha512-DkDk8pmXQV2wVrF6oq5tONK6UHLz/XcEVow4JTTerdeV1uqPeHxwcg7aFsfnSm9L+OO8WJsWotKM2JJPMWrQtA=="], - "@rollup/rollup-linux-s390x-gnu": ["@rollup/rollup-linux-s390x-gnu@4.21.2", "", { "os": "linux", "cpu": "s390x" }, "sha512-PMxkrWS9z38bCr3rWvDFVGD6sFeZJw4iQlhrup7ReGmfn7Oukrr/zweLhYX6v2/8J6Cep9IEA/SmjXjCmSbrMQ=="], + "@rollup/rollup-linux-ppc64-gnu": ["@rollup/rollup-linux-ppc64-gnu@4.52.5", "", { "os": "linux", "cpu": "ppc64" }, "sha512-W/b9ZN/U9+hPQVvlGwjzi+Wy4xdoH2I8EjaCkMvzpI7wJUs8sWJ03Rq96jRnHkSrcHTpQe8h5Tg3ZzUPGauvAw=="], - "@rollup/rollup-linux-x64-gnu": ["@rollup/rollup-linux-x64-gnu@4.21.2", "", { "os": "linux", "cpu": "x64" }, "sha512-B90tYAUoLhU22olrafY3JQCFLnT3NglazdwkHyxNDYF/zAxJt5fJUB/yBoWFoIQ7SQj+KLe3iL4BhOMa9fzgpw=="], + "@rollup/rollup-linux-riscv64-gnu": ["@rollup/rollup-linux-riscv64-gnu@4.52.5", "", { "os": "linux", "cpu": "none" }, "sha512-sjQLr9BW7R/ZiXnQiWPkErNfLMkkWIoCz7YMn27HldKsADEKa5WYdobaa1hmN6slu9oWQbB6/jFpJ+P2IkVrmw=="], - "@rollup/rollup-linux-x64-musl": ["@rollup/rollup-linux-x64-musl@4.21.2", "", { "os": "linux", "cpu": "x64" }, "sha512-7twFizNXudESmC9oneLGIUmoHiiLppz/Xs5uJQ4ShvE6234K0VB1/aJYU3f/4g7PhssLGKBVCC37uRkkOi8wjg=="], + "@rollup/rollup-linux-riscv64-musl": ["@rollup/rollup-linux-riscv64-musl@4.52.5", "", { "os": "linux", "cpu": "none" }, "sha512-hq3jU/kGyjXWTvAh2awn8oHroCbrPm8JqM7RUpKjalIRWWXE01CQOf/tUNWNHjmbMHg/hmNCwc/Pz3k1T/j/Lg=="], - "@rollup/rollup-win32-arm64-msvc": ["@rollup/rollup-win32-arm64-msvc@4.21.2", "", { "os": "win32", "cpu": "arm64" }, "sha512-9rRero0E7qTeYf6+rFh3AErTNU1VCQg2mn7CQcI44vNUWM9Ze7MSRS/9RFuSsox+vstRt97+x3sOhEey024FRQ=="], + "@rollup/rollup-linux-s390x-gnu": ["@rollup/rollup-linux-s390x-gnu@4.52.5", "", { "os": "linux", "cpu": "s390x" }, "sha512-gn8kHOrku8D4NGHMK1Y7NA7INQTRdVOntt1OCYypZPRt6skGbddska44K8iocdpxHTMMNui5oH4elPH4QOLrFQ=="], - "@rollup/rollup-win32-ia32-msvc": ["@rollup/rollup-win32-ia32-msvc@4.21.2", "", { "os": "win32", "cpu": "ia32" }, "sha512-5rA4vjlqgrpbFVVHX3qkrCo/fZTj1q0Xxpg+Z7yIo3J2AilW7t2+n6Q8Jrx+4MrYpAnjttTYF8rr7bP46BPzRw=="], + "@rollup/rollup-linux-x64-gnu": ["@rollup/rollup-linux-x64-gnu@4.52.5", "", { "os": "linux", "cpu": "x64" }, "sha512-hXGLYpdhiNElzN770+H2nlx+jRog8TyynpTVzdlc6bndktjKWyZyiCsuDAlpd+j+W+WNqfcyAWz9HxxIGfZm1Q=="], - "@rollup/rollup-win32-x64-msvc": ["@rollup/rollup-win32-x64-msvc@4.21.2", "", { "os": "win32", "cpu": "x64" }, "sha512-6UUxd0+SKomjdzuAcp+HAmxw1FlGBnl1v2yEPSabtx4lBfdXHDVsW7+lQkgz9cNFJGY3AWR7+V8P5BqkD9L9nA=="], + "@rollup/rollup-linux-x64-musl": ["@rollup/rollup-linux-x64-musl@4.52.5", "", { "os": "linux", "cpu": "x64" }, "sha512-arCGIcuNKjBoKAXD+y7XomR9gY6Mw7HnFBv5Rw7wQRvwYLR7gBAgV7Mb2QTyjXfTveBNFAtPt46/36vV9STLNg=="], - "@stylistic/eslint-plugin": ["@stylistic/eslint-plugin@4.4.0", "", { "dependencies": { "@typescript-eslint/utils": "^8.32.1", "eslint-visitor-keys": "^4.2.0", "espree": "^10.3.0", "estraverse": "^5.3.0", "picomatch": "^4.0.2" }, "peerDependencies": { "eslint": ">=9.0.0" } }, "sha512-bIh/d9X+OQLCAMdhHtps+frvyjvAM4B1YlSJzcEEhl7wXLIqPar3ngn9DrHhkBOrTA/z9J0bUMtctAspe0dxdQ=="], + "@rollup/rollup-openharmony-arm64": ["@rollup/rollup-openharmony-arm64@4.52.5", "", { "os": "none", "cpu": "arm64" }, "sha512-QoFqB6+/9Rly/RiPjaomPLmR/13cgkIGfA40LHly9zcH1S0bN2HVFYk3a1eAyHQyjs3ZJYlXvIGtcCs5tko9Cw=="], - "@tybys/wasm-util": ["@tybys/wasm-util@0.10.0", "", { "dependencies": { "tslib": "^2.4.0" } }, "sha512-VyyPYFlOMNylG45GoAe0xDoLwWuowvf92F9kySqzYh8vmYm7D2u4iUJKa1tOUpS70Ku13ASrOkS4ScXFsTaCNQ=="], + "@rollup/rollup-win32-arm64-msvc": ["@rollup/rollup-win32-arm64-msvc@4.52.5", "", { "os": "win32", "cpu": "arm64" }, "sha512-w0cDWVR6MlTstla1cIfOGyl8+qb93FlAVutcor14Gf5Md5ap5ySfQ7R9S/NjNaMLSFdUnKGEasmVnu3lCMqB7w=="], - "@types/bun": ["@types/bun@1.2.21", "", { "dependencies": { "bun-types": "1.2.21" } }, "sha512-NiDnvEqmbfQ6dmZ3EeUO577s4P5bf4HCTXtI6trMc6f6RzirY5IrF3aIookuSpyslFzrnvv2lmEWv5HyC1X79A=="], + "@rollup/rollup-win32-ia32-msvc": ["@rollup/rollup-win32-ia32-msvc@4.52.5", "", { "os": "win32", "cpu": "ia32" }, "sha512-Aufdpzp7DpOTULJCuvzqcItSGDH73pF3ko/f+ckJhxQyHtp67rHw3HMNxoIdDMUITJESNE6a8uh4Lo4SLouOUg=="], + + "@rollup/rollup-win32-x64-gnu": ["@rollup/rollup-win32-x64-gnu@4.52.5", "", { "os": "win32", "cpu": "x64" }, "sha512-UGBUGPFp1vkj6p8wCRraqNhqwX/4kNQPS57BCFc8wYh0g94iVIW33wJtQAx3G7vrjjNtRaxiMUylM0ktp/TRSQ=="], + + "@rollup/rollup-win32-x64-msvc": ["@rollup/rollup-win32-x64-msvc@4.52.5", "", { "os": "win32", "cpu": "x64" }, "sha512-TAcgQh2sSkykPRWLrdyy2AiceMckNf5loITqXxFI5VuQjS5tSuw3WlwdN8qv8vzjLAUTvYaH/mVjSFpbkFbpTg=="], + + "@sindresorhus/base62": ["@sindresorhus/base62@1.0.0", "", {}, "sha512-TeheYy0ILzBEI/CO55CP6zJCSdSWeRtGnHy8U8dWSUH4I68iqTsy7HkMktR4xakThc9jotkPQUXT4ITdbV7cHA=="], + + "@standard-schema/spec": ["@standard-schema/spec@1.0.0", "", {}, "sha512-m2bOd0f2RT9k8QJx1JN85cZYyH1RqFBdlwtkSlf4tBDYLCiiZnv1fIIwacK6cqwXavOydf0NPToMQgpKq+dVlA=="], + + "@stylistic/eslint-plugin": ["@stylistic/eslint-plugin@5.5.0", "", { "dependencies": { "@eslint-community/eslint-utils": "^4.9.0", "@typescript-eslint/types": "^8.46.1", "eslint-visitor-keys": "^4.2.1", "espree": "^10.4.0", "estraverse": "^5.3.0", "picomatch": "^4.0.3" }, "peerDependencies": { "eslint": ">=9.0.0" } }, "sha512-IeZF+8H0ns6prg4VrkhgL+yrvDXWDH2cKchrbh80ejG9dQgZWp10epHMbgRuQvgchLII/lfh6Xn3lu6+6L86Hw=="], + + "@tybys/wasm-util": ["@tybys/wasm-util@0.10.1", "", { "dependencies": { "tslib": "^2.4.0" } }, "sha512-9tTaPJLSiejZKx+Bmog4uSubteqTvFrVrURwkmHixBo0G4seD0zUxp98E1DzUBJxLQ3NPwXrGKDiVjwx/DpPsg=="], + + "@types/bun": ["@types/bun@1.3.1", "", { "dependencies": { "bun-types": "1.3.1" } }, "sha512-4jNMk2/K9YJtfqwoAa28c8wK+T7nvJFOjxI4h/7sORWcypRNxBpr+TPNaCfVWq70tLCJsqoFwcf0oI0JU/fvMQ=="], "@types/chai": ["@types/chai@5.2.2", "", { "dependencies": { "@types/deep-eql": "*" } }, "sha512-8kB30R7Hwqf40JPiKhVzodJs2Qc1ZJ5zuT3uzw5Hq/dhNCl3G3l83jfpdI1e20BP348+fV7VIL/+FxaXkqBmWg=="], @@ -258,37 +280,41 @@ "@types/react": ["@types/react@19.1.12", "", { "dependencies": { "csstype": "^3.0.2" } }, "sha512-cMoR+FoAf/Jyq6+Df2/Z41jISvGZZ2eTlnsaJRptmZ76Caldwy1odD4xTr/gNV9VLj0AWgg/nmkevIyUfIIq5w=="], - "@typescript-eslint/eslint-plugin": ["@typescript-eslint/eslint-plugin@8.32.1", "", { "dependencies": { "@eslint-community/regexpp": "^4.10.0", "@typescript-eslint/scope-manager": "8.32.1", "@typescript-eslint/type-utils": "8.32.1", "@typescript-eslint/utils": "8.32.1", "@typescript-eslint/visitor-keys": "8.32.1", "graphemer": "^1.4.0", "ignore": "^7.0.0", "natural-compare": "^1.4.0", "ts-api-utils": "^2.1.0" }, "peerDependencies": { "@typescript-eslint/parser": "^8.0.0 || ^8.0.0-alpha.0", "eslint": "^8.57.0 || ^9.0.0", "typescript": ">=4.8.4 <5.9.0" } }, "sha512-6u6Plg9nP/J1GRpe/vcjjabo6Uc5YQPAMxsgQyGC/I0RuukiG1wIe3+Vtg3IrSCVJDmqK3j8adrtzXSENRtFgg=="], + "@typescript-eslint/eslint-plugin": ["@typescript-eslint/eslint-plugin@8.46.2", "", { "dependencies": { "@eslint-community/regexpp": "^4.10.0", "@typescript-eslint/scope-manager": "8.46.2", "@typescript-eslint/type-utils": "8.46.2", "@typescript-eslint/utils": "8.46.2", "@typescript-eslint/visitor-keys": "8.46.2", "graphemer": "^1.4.0", "ignore": "^7.0.0", "natural-compare": "^1.4.0", "ts-api-utils": "^2.1.0" }, "peerDependencies": { "@typescript-eslint/parser": "^8.46.2", "eslint": "^8.57.0 || ^9.0.0", "typescript": ">=4.8.4 <6.0.0" } }, "sha512-ZGBMToy857/NIPaaCucIUQgqueOiq7HeAKkhlvqVV4lm089zUFW6ikRySx2v+cAhKeUCPuWVHeimyk6Dw1iY3w=="], + + "@typescript-eslint/parser": ["@typescript-eslint/parser@8.46.2", "", { "dependencies": { "@typescript-eslint/scope-manager": "8.46.2", "@typescript-eslint/types": "8.46.2", "@typescript-eslint/typescript-estree": "8.46.2", "@typescript-eslint/visitor-keys": "8.46.2", "debug": "^4.3.4" }, "peerDependencies": { "eslint": "^8.57.0 || ^9.0.0", "typescript": ">=4.8.4 <6.0.0" } }, "sha512-BnOroVl1SgrPLywqxyqdJ4l3S2MsKVLDVxZvjI1Eoe8ev2r3kGDo+PcMihNmDE+6/KjkTubSJnmqGZZjQSBq/g=="], - "@typescript-eslint/parser": ["@typescript-eslint/parser@8.32.1", "", { "dependencies": { "@typescript-eslint/scope-manager": "8.32.1", "@typescript-eslint/types": "8.32.1", "@typescript-eslint/typescript-estree": "8.32.1", "@typescript-eslint/visitor-keys": "8.32.1", "debug": "^4.3.4" }, "peerDependencies": { "eslint": "^8.57.0 || ^9.0.0", "typescript": ">=4.8.4 <5.9.0" } }, "sha512-LKMrmwCPoLhM45Z00O1ulb6jwyVr2kr3XJp+G+tSEZcbauNnScewcQwtJqXDhXeYPDEjZ8C1SjXm015CirEmGg=="], + "@typescript-eslint/project-service": ["@typescript-eslint/project-service@8.46.2", "", { "dependencies": { "@typescript-eslint/tsconfig-utils": "^8.46.2", "@typescript-eslint/types": "^8.46.2", "debug": "^4.3.4" }, "peerDependencies": { "typescript": ">=4.8.4 <6.0.0" } }, "sha512-PULOLZ9iqwI7hXcmL4fVfIsBi6AN9YxRc0frbvmg8f+4hQAjQ5GYNKK0DIArNo+rOKmR/iBYwkpBmnIwin4wBg=="], - "@typescript-eslint/scope-manager": ["@typescript-eslint/scope-manager@8.32.1", "", { "dependencies": { "@typescript-eslint/types": "8.32.1", "@typescript-eslint/visitor-keys": "8.32.1" } }, "sha512-7IsIaIDeZn7kffk7qXC3o6Z4UblZJKV3UBpkvRNpr5NSyLji7tvTcvmnMNYuYLyh26mN8W723xpo3i4MlD33vA=="], + "@typescript-eslint/scope-manager": ["@typescript-eslint/scope-manager@8.46.2", "", { "dependencies": { "@typescript-eslint/types": "8.46.2", "@typescript-eslint/visitor-keys": "8.46.2" } }, "sha512-LF4b/NmGvdWEHD2H4MsHD8ny6JpiVNDzrSZr3CsckEgCbAGZbYM4Cqxvi9L+WqDMT+51Ozy7lt2M+d0JLEuBqA=="], - "@typescript-eslint/type-utils": ["@typescript-eslint/type-utils@8.32.1", "", { "dependencies": { "@typescript-eslint/typescript-estree": "8.32.1", "@typescript-eslint/utils": "8.32.1", "debug": "^4.3.4", "ts-api-utils": "^2.1.0" }, "peerDependencies": { "eslint": "^8.57.0 || ^9.0.0", "typescript": ">=4.8.4 <5.9.0" } }, "sha512-mv9YpQGA8iIsl5KyUPi+FGLm7+bA4fgXaeRcFKRDRwDMu4iwrSHeDPipwueNXhdIIZltwCJv+NkxftECbIZWfA=="], + "@typescript-eslint/tsconfig-utils": ["@typescript-eslint/tsconfig-utils@8.46.2", "", { "peerDependencies": { "typescript": ">=4.8.4 <6.0.0" } }, "sha512-a7QH6fw4S57+F5y2FIxxSDyi5M4UfGF+Jl1bCGd7+L4KsaUY80GsiF/t0UoRFDHAguKlBaACWJRmdrc6Xfkkag=="], - "@typescript-eslint/types": ["@typescript-eslint/types@8.32.1", "", {}, "sha512-YmybwXUJcgGqgAp6bEsgpPXEg6dcCyPyCSr0CAAueacR/CCBi25G3V8gGQ2kRzQRBNol7VQknxMs9HvVa9Rvfg=="], + "@typescript-eslint/type-utils": ["@typescript-eslint/type-utils@8.46.2", "", { "dependencies": { "@typescript-eslint/types": "8.46.2", "@typescript-eslint/typescript-estree": "8.46.2", "@typescript-eslint/utils": "8.46.2", "debug": "^4.3.4", "ts-api-utils": "^2.1.0" }, "peerDependencies": { "eslint": "^8.57.0 || ^9.0.0", "typescript": ">=4.8.4 <6.0.0" } }, "sha512-HbPM4LbaAAt/DjxXaG9yiS9brOOz6fabal4uvUmaUYe6l3K1phQDMQKBRUrr06BQkxkvIZVVHttqiybM9nJsLA=="], - "@typescript-eslint/typescript-estree": ["@typescript-eslint/typescript-estree@8.32.1", "", { "dependencies": { "@typescript-eslint/types": "8.32.1", "@typescript-eslint/visitor-keys": "8.32.1", "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": "^2.1.0" }, "peerDependencies": { "typescript": ">=4.8.4 <5.9.0" } }, "sha512-Y3AP9EIfYwBb4kWGb+simvPaqQoT5oJuzzj9m0i6FCY6SPvlomY2Ei4UEMm7+FXtlNJbor80ximyslzaQF6xhg=="], + "@typescript-eslint/types": ["@typescript-eslint/types@8.46.2", "", {}, "sha512-lNCWCbq7rpg7qDsQrd3D6NyWYu+gkTENkG5IKYhUIcxSb59SQC/hEQ+MrG4sTgBVghTonNWq42bA/d4yYumldQ=="], - "@typescript-eslint/utils": ["@typescript-eslint/utils@8.32.1", "", { "dependencies": { "@eslint-community/eslint-utils": "^4.7.0", "@typescript-eslint/scope-manager": "8.32.1", "@typescript-eslint/types": "8.32.1", "@typescript-eslint/typescript-estree": "8.32.1" }, "peerDependencies": { "eslint": "^8.57.0 || ^9.0.0", "typescript": ">=4.8.4 <5.9.0" } }, "sha512-DsSFNIgLSrc89gpq1LJB7Hm1YpuhK086DRDJSNrewcGvYloWW1vZLHBTIvarKZDcAORIy/uWNx8Gad+4oMpkSA=="], + "@typescript-eslint/typescript-estree": ["@typescript-eslint/typescript-estree@8.46.2", "", { "dependencies": { "@typescript-eslint/project-service": "8.46.2", "@typescript-eslint/tsconfig-utils": "8.46.2", "@typescript-eslint/types": "8.46.2", "@typescript-eslint/visitor-keys": "8.46.2", "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": "^2.1.0" }, "peerDependencies": { "typescript": ">=4.8.4 <6.0.0" } }, "sha512-f7rW7LJ2b7Uh2EiQ+7sza6RDZnajbNbemn54Ob6fRwQbgcIn+GWfyuHDHRYgRoZu1P4AayVScrRW+YfbTvPQoQ=="], - "@typescript-eslint/visitor-keys": ["@typescript-eslint/visitor-keys@8.32.1", "", { "dependencies": { "@typescript-eslint/types": "8.32.1", "eslint-visitor-keys": "^4.2.0" } }, "sha512-ar0tjQfObzhSaW3C3QNmTc5ofj0hDoNQ5XWrCy6zDyabdr0TWhCkClp+rywGNj/odAFBVzzJrK4tEq5M4Hmu4w=="], + "@typescript-eslint/utils": ["@typescript-eslint/utils@8.46.2", "", { "dependencies": { "@eslint-community/eslint-utils": "^4.7.0", "@typescript-eslint/scope-manager": "8.46.2", "@typescript-eslint/types": "8.46.2", "@typescript-eslint/typescript-estree": "8.46.2" }, "peerDependencies": { "eslint": "^8.57.0 || ^9.0.0", "typescript": ">=4.8.4 <6.0.0" } }, "sha512-sExxzucx0Tud5tE0XqR0lT0psBQvEpnpiul9XbGUB1QwpWJJAps1O/Z7hJxLGiZLBKMCutjTzDgmd1muEhBnVg=="], - "@vitest/expect": ["@vitest/expect@3.2.4", "", { "dependencies": { "@types/chai": "^5.2.2", "@vitest/spy": "3.2.4", "@vitest/utils": "3.2.4", "chai": "^5.2.0", "tinyrainbow": "^2.0.0" } }, "sha512-Io0yyORnB6sikFlt8QW5K7slY4OjqNX9jmJQ02QDda8lyM6B5oNgVWoSoKPac8/kgnCUzuHQKrSLtu/uOqqrig=="], + "@typescript-eslint/visitor-keys": ["@typescript-eslint/visitor-keys@8.46.2", "", { "dependencies": { "@typescript-eslint/types": "8.46.2", "eslint-visitor-keys": "^4.2.1" } }, "sha512-tUFMXI4gxzzMXt4xpGJEsBsTox0XbNQ1y94EwlD/CuZwFcQP79xfQqMhau9HsRc/J0cAPA/HZt1dZPtGn9V/7w=="], - "@vitest/mocker": ["@vitest/mocker@3.2.4", "", { "dependencies": { "@vitest/spy": "3.2.4", "estree-walker": "^3.0.3", "magic-string": "^0.30.17" }, "peerDependencies": { "msw": "^2.4.9", "vite": "^5.0.0 || ^6.0.0 || ^7.0.0-0" }, "optionalPeers": ["msw", "vite"] }, "sha512-46ryTE9RZO/rfDd7pEqFl7etuyzekzEhUbTW3BvmeO/BcCMEgq59BKhek3dXDWgAj4oMK6OZi+vRr1wPW6qjEQ=="], + "@vitest/expect": ["@vitest/expect@4.0.4", "", { "dependencies": { "@standard-schema/spec": "^1.0.0", "@types/chai": "^5.2.2", "@vitest/spy": "4.0.4", "@vitest/utils": "4.0.4", "chai": "^6.0.1", "tinyrainbow": "^3.0.3" } }, "sha512-0ioMscWJtfpyH7+P82sGpAi3Si30OVV73jD+tEqXm5+rIx9LgnfdaOn45uaFkKOncABi/PHL00Yn0oW/wK4cXw=="], - "@vitest/pretty-format": ["@vitest/pretty-format@3.2.4", "", { "dependencies": { "tinyrainbow": "^2.0.0" } }, "sha512-IVNZik8IVRJRTr9fxlitMKeJeXFFFN0JaB9PHPGQ8NKQbGpfjlTx9zO4RefN8gp7eqjNy8nyK3NZmBzOPeIxtA=="], + "@vitest/mocker": ["@vitest/mocker@4.0.4", "", { "dependencies": { "@vitest/spy": "4.0.4", "estree-walker": "^3.0.3", "magic-string": "^0.30.19" }, "peerDependencies": { "msw": "^2.4.9", "vite": "^6.0.0 || ^7.0.0-0" }, "optionalPeers": ["msw", "vite"] }, "sha512-UTtKgpjWj+pvn3lUM55nSg34098obGhSHH+KlJcXesky8b5wCUgg7s60epxrS6yAG8slZ9W8T9jGWg4PisMf5Q=="], - "@vitest/runner": ["@vitest/runner@3.2.4", "", { "dependencies": { "@vitest/utils": "3.2.4", "pathe": "^2.0.3", "strip-literal": "^3.0.0" } }, "sha512-oukfKT9Mk41LreEW09vt45f8wx7DordoWUZMYdY/cyAk7w5TWkTRCNZYF7sX7n2wB7jyGAl74OxgwhPgKaqDMQ=="], + "@vitest/pretty-format": ["@vitest/pretty-format@4.0.4", "", { "dependencies": { "tinyrainbow": "^3.0.3" } }, "sha512-lHI2rbyrLVSd1TiHGJYyEtbOBo2SDndIsN3qY4o4xe2pBxoJLD6IICghNCvD7P+BFin6jeyHXiUICXqgl6vEaQ=="], - "@vitest/snapshot": ["@vitest/snapshot@3.2.4", "", { "dependencies": { "@vitest/pretty-format": "3.2.4", "magic-string": "^0.30.17", "pathe": "^2.0.3" } }, "sha512-dEYtS7qQP2CjU27QBC5oUOxLE/v5eLkGqPE0ZKEIDGMs4vKWe7IjgLOeauHsR0D5YuuycGRO5oSRXnwnmA78fQ=="], + "@vitest/runner": ["@vitest/runner@4.0.4", "", { "dependencies": { "@vitest/utils": "4.0.4", "pathe": "^2.0.3" } }, "sha512-99EDqiCkncCmvIZj3qJXBZbyoQ35ghOwVWNnQ5nj0Hnsv4Qm40HmrMJrceewjLVvsxV/JSU4qyx2CGcfMBmXJw=="], - "@vitest/spy": ["@vitest/spy@3.2.4", "", { "dependencies": { "tinyspy": "^4.0.3" } }, "sha512-vAfasCOe6AIK70iP5UD11Ac4siNUNJ9i/9PZ3NKx07sG6sUxeag1LWdNrMWeKKYBLlzuK+Gn65Yd5nyL6ds+nw=="], + "@vitest/snapshot": ["@vitest/snapshot@4.0.4", "", { "dependencies": { "@vitest/pretty-format": "4.0.4", "magic-string": "^0.30.19", "pathe": "^2.0.3" } }, "sha512-XICqf5Gi4648FGoBIeRgnHWSNDp+7R5tpclGosFaUUFzY6SfcpsfHNMnC7oDu/iOLBxYfxVzaQpylEvpgii3zw=="], - "@vitest/utils": ["@vitest/utils@3.2.4", "", { "dependencies": { "@vitest/pretty-format": "3.2.4", "loupe": "^3.1.4", "tinyrainbow": "^2.0.0" } }, "sha512-fB2V0JFrQSMsCo9HiSq3Ezpdv4iYaXRG1Sx8edX3MwxfyNn83mKiGzOcH+Fkxt4MHxr3y42fQi1oeAInqgX2QA=="], + "@vitest/spy": ["@vitest/spy@4.0.4", "", {}, "sha512-G9L13AFyYECo40QG7E07EdYnZZYCKMTSp83p9W8Vwed0IyCG1GnpDLxObkx8uOGPXfDpdeVf24P1Yka8/q1s9g=="], - "acorn": ["acorn@8.14.1", "", { "bin": { "acorn": "bin/acorn" } }, "sha512-OvQ/2pUDKmgfCg++xsTX1wGxfTaszcHVcTctW4UJB4hibJx2HXxxO5UmVgyjMa+ZDsiaf5wWLXYpRWMmBI0QHg=="], + "@vitest/utils": ["@vitest/utils@4.0.4", "", { "dependencies": { "@vitest/pretty-format": "4.0.4", "tinyrainbow": "^3.0.3" } }, "sha512-4bJLmSvZLyVbNsYFRpPYdJViG9jZyRvMZ35IF4ymXbRZoS+ycYghmwTGiscTXduUg2lgKK7POWIyXJNute1hjw=="], + + "acorn": ["acorn@8.15.0", "", { "bin": { "acorn": "bin/acorn" } }, "sha512-NZyJarBfL7nWwIq+FDL6Zp/yHEhePMNnnJ0y3qfieCrmNvYct8uvtiV41UvlSe6apAfk0fY1FbWx+NwfmpvtTg=="], "acorn-jsx": ["acorn-jsx@5.3.2", "", { "peerDependencies": { "acorn": "^6.0.0 || ^7.0.0 || ^8.0.0" } }, "sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ=="], @@ -296,19 +322,19 @@ "ansi-styles": ["ansi-styles@4.3.0", "", { "dependencies": { "color-convert": "^2.0.1" } }, "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg=="], - "ansis": ["ansis@4.1.0", "", {}, "sha512-BGcItUBWSMRgOCe+SVZJ+S7yTRG0eGt9cXAHev72yuGcY23hnLA7Bky5L/xLyPINoSN95geovfBkqoTlNZYa7w=="], + "ansis": ["ansis@4.2.0", "", {}, "sha512-HqZ5rWlFjGiV0tDm3UxxgNRqsOTniqoKZu0pIAfh7TZQMGuZK+hH0drySty0si0QXj1ieop4+SkSfPZBPPkHig=="], "are-docs-informative": ["are-docs-informative@0.0.2", "", {}, "sha512-ixiS0nLNNG5jNQzgZJNoUpBKdo9yTYZMGJ+QgT2jmjR7G7+QHRCc4v6LQ3NgE7EBJq+o0ams3waJwkrlBom8Ig=="], "argparse": ["argparse@2.0.1", "", {}, "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q=="], - "assertion-error": ["assertion-error@2.0.1", "", {}, "sha512-Izi8RQcffqCeNVgFigKli1ssklIbpHnCYc6AknXGYoB6grJqyeby7jv12JUQgmTAnIDnbck1uxksT4dzN3PWBA=="], - - "ast-kit": ["ast-kit@2.1.2", "", { "dependencies": { "@babel/parser": "^7.28.0", "pathe": "^2.0.3" } }, "sha512-cl76xfBQM6pztbrFWRnxbrDm9EOqDr1BF6+qQnnDZG2Co2LjyUktkN9GTJfBAfdae+DbT2nJf2nCGAdDDN7W2g=="], + "ast-kit": ["ast-kit@2.1.3", "", { "dependencies": { "@babel/parser": "^7.28.4", "pathe": "^2.0.3" } }, "sha512-TH+b3Lv6pUjy/Nu0m6A2JULtdzLpmqF9x1Dhj00ZoEiML8qvVA9j1flkzTKNYgdEhWrjDwtWNpyyCUbfQe514g=="], "balanced-match": ["balanced-match@1.0.2", "", {}, "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw=="], - "birpc": ["birpc@2.5.0", "", {}, "sha512-VSWO/W6nNQdyP520F1mhf+Lc2f8pjGQOtoHHm7Ze8Go1kX7akpVIrtTa0fn+HB0QJEDVacl6aO08YE0PgXfdnQ=="], + "baseline-browser-mapping": ["baseline-browser-mapping@2.8.20", "", { "bin": { "baseline-browser-mapping": "dist/cli.js" } }, "sha512-JMWsdF+O8Orq3EMukbUN1QfbLK9mX2CkUmQBcW2T0s8OmdAUL5LLM/6wFwSrqXzlXB13yhyK9gTKS1rIizOduQ=="], + + "birpc": ["birpc@2.6.1", "", {}, "sha512-LPnFhlDpdSH6FJhJyn4M0kFO7vtQ5iPw24FnG0y21q09xC7e8+1LeR31S1MAIrDAHp4m7aas4bEkTDTvMAtebQ=="], "boolbase": ["boolbase@1.0.0", "", {}, "sha512-JZOSA7Mo9sNGB8+UjSgzdLtokWAky1zbztM3WRLCbZ70/3cTANmQmOdR7y2g+J0e2WXywy1yS468tY+IruqEww=="], @@ -316,27 +342,27 @@ "braces": ["braces@3.0.3", "", { "dependencies": { "fill-range": "^7.1.1" } }, "sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA=="], - "browserslist": ["browserslist@4.24.5", "", { "dependencies": { "caniuse-lite": "^1.0.30001716", "electron-to-chromium": "^1.5.149", "node-releases": "^2.0.19", "update-browserslist-db": "^1.1.3" }, "bin": { "browserslist": "cli.js" } }, "sha512-FDToo4Wo82hIdgc1CQ+NQD0hEhmpPjrZ3hiUgwgOG6IuTdlpr8jdjyG24P6cNP1yJpTLzS5OcGgSw0xmDU1/Tw=="], + "browserslist": ["browserslist@4.27.0", "", { "dependencies": { "baseline-browser-mapping": "^2.8.19", "caniuse-lite": "^1.0.30001751", "electron-to-chromium": "^1.5.238", "node-releases": "^2.0.26", "update-browserslist-db": "^1.1.4" }, "bin": { "browserslist": "cli.js" } }, "sha512-AXVQwdhot1eqLihwasPElhX2tAZiBjWdJ9i/Zcj2S6QYIjkx62OKSfnobkriB81C3l4w0rVy3Nt4jaTBltYEpw=="], "builtin-modules": ["builtin-modules@5.0.0", "", {}, "sha512-bkXY9WsVpY7CvMhKSR6pZilZu9Ln5WDrKVBUXf2S443etkmEO4V58heTecXcUIsNsi4Rx8JUO4NfX1IcQl4deg=="], - "bun-types": ["bun-types@1.2.21", "", { "dependencies": { "@types/node": "*" }, "peerDependencies": { "@types/react": "^19" } }, "sha512-sa2Tj77Ijc/NTLS0/Odjq/qngmEPZfbfnOERi0KRUYhT9R8M4VBioWVmMWE5GrYbKMc+5lVybXygLdibHaqVqw=="], + "bun-types": ["bun-types@1.3.1", "", { "dependencies": { "@types/node": "*" }, "peerDependencies": { "@types/react": "^19" } }, "sha512-NMrcy7smratanWJ2mMXdpatalovtxVggkj11bScuWuiOoXTiKIu2eVS1/7qbyI/4yHedtsn175n4Sm4JcdHLXw=="], "cac": ["cac@6.7.14", "", {}, "sha512-b6Ilus+c3RrdDk+JhLKUAQfzzgLEPy6wcXqS7f/xe1EETvsDP6GORG7SFuOs6cID5YkqchW/LXZbX5bc8j7ZcQ=="], "callsites": ["callsites@3.1.0", "", {}, "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ=="], - "caniuse-lite": ["caniuse-lite@1.0.30001718", "", {}, "sha512-AflseV1ahcSunK53NfEs9gFWgOEmzr0f+kaMFA4xiLZlr9Hzt7HxcSpIFcnNCUkz6R6dWKa54rUz3HUmI3nVcw=="], + "caniuse-lite": ["caniuse-lite@1.0.30001751", "", {}, "sha512-A0QJhug0Ly64Ii3eIqHu5X51ebln3k4yTUkY1j8drqpWHVreg/VLijN48cZ1bYPiqOQuqpkIKnzr/Ul8V+p6Cw=="], - "chai": ["chai@5.2.0", "", { "dependencies": { "assertion-error": "^2.0.1", "check-error": "^2.1.1", "deep-eql": "^5.0.1", "loupe": "^3.1.0", "pathval": "^2.0.0" } }, "sha512-mCuXncKXk5iCLhfhwTc0izo0gtEmpz5CtG2y8GiOINBlMVS6v8TMRc5TaLWKS6692m9+dVVfzgeVxR5UxWHTYw=="], + "chai": ["chai@6.2.0", "", {}, "sha512-aUTnJc/JipRzJrNADXVvpVqi6CO0dn3nx4EVPxijri+fj3LUUDyZQOgVeW54Ob3Y1Xh9Iz8f+CgaCl8v0mn9bA=="], "chalk": ["chalk@4.1.2", "", { "dependencies": { "ansi-styles": "^4.1.0", "supports-color": "^7.1.0" } }, "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA=="], - "check-error": ["check-error@2.1.1", "", {}, "sha512-OAlb+T7V4Op9OwdkjmguYRqncdlx5JiofwOAUkmTF+jNdHwzTaTs4sRAGpzLF3oOz5xAyDGrPgeIDFQmDOTiJw=="], + "change-case": ["change-case@5.4.4", "", {}, "sha512-HRQyTk2/YPEkt9TnUPbOpr64Uw3KOicFWPVBb+xiHvd6eBx/qPr9xqfBFDT8P2vWsvvz4jbEkfDe71W3VyNu2w=="], "chokidar": ["chokidar@4.0.3", "", { "dependencies": { "readdirp": "^4.0.1" } }, "sha512-Qgzu8kfBvo+cA4962jnP1KkS6Dop5NS6g7R5LFYJr4b8Ub94PPQXUksCw9PvXoeXPRRddRNC5C1JQUR2SMGtnA=="], - "ci-info": ["ci-info@4.2.0", "", {}, "sha512-cYY9mypksY8NRqgDB1XD1RiJL338v/551niynFTGkZOO2LHuB2OmOYxDIe/ttN9AHwrqdum1360G3ald0W9kCg=="], + "ci-info": ["ci-info@4.3.1", "", {}, "sha512-Wdy2Igu8OcBpI2pZePZ5oWjPC38tmDVx5WKUXKwlLYkA0ozo85sLsLvkBbBn/sZaSCMFOGZJ14fvW9t5/d7kdA=="], "clean-regexp": ["clean-regexp@1.0.0", "", { "dependencies": { "escape-string-regexp": "^1.0.5" } }, "sha512-GfisEZEJvzKrmGWkvfhgzcz/BllN1USeqD2V6tg14OAOgaCD2Z/PUEuxnAZ/nPvmaHRG7a8y77p1T/IRQ4D1Hw=="], @@ -350,7 +376,7 @@ "confbox": ["confbox@0.2.2", "", {}, "sha512-1NB+BKqhtNipMsov4xI/NnhCKp9XG9NamYp5PVm9klAT0fsrNPjaFICsCFhNhwZJKNh7zB/3q8qXz0E9oaMNtQ=="], - "core-js-compat": ["core-js-compat@3.42.0", "", { "dependencies": { "browserslist": "^4.24.4" } }, "sha512-bQasjMfyDGyaeWKBIu33lHh9qlSR0MFE/Nmc6nMjf/iU9b3rSMdAYz1Baxrv4lPdGUsTqZudHA4jIGSJy0SWZQ=="], + "core-js-compat": ["core-js-compat@3.46.0", "", { "dependencies": { "browserslist": "^4.26.3" } }, "sha512-p9hObIIEENxSV8xIu+V68JjSeARg6UVMG5mR+JEUguG3sI6MsiS1njz2jHmyJDvA+8jX/sytkBHup6kxhM9law=="], "cross-spawn": ["cross-spawn@7.0.6", "", { "dependencies": { "path-key": "^3.1.0", "shebang-command": "^2.0.0", "which": "^2.0.1" } }, "sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA=="], @@ -360,19 +386,15 @@ "debug": ["debug@4.4.1", "", { "dependencies": { "ms": "^2.1.3" } }, "sha512-KcKCqiftBJcZr++7ykoDIEwSa3XWowTfNPo92BYxjXiyYEVrUQh2aLyhxBCwww+heortUFxEJYcRzosstTEBYQ=="], - "deep-eql": ["deep-eql@5.0.2", "", {}, "sha512-h5k/5U50IJJFpzfL6nO9jaaumfjO/f2NjK/oYB2Djzm4p9L+3T9qWpZqZ2hAbLPuuYq9wrU08WQyBTL5GbPk5Q=="], - "deep-is": ["deep-is@0.1.4", "", {}, "sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ=="], "defu": ["defu@6.1.4", "", {}, "sha512-mEQCMmwJu317oSz8CwdIOdwf3xMif1ttiM8LTufzc3g6kR+9Pe236twL8j3IYT1F7GfRgGcW6MWxzZjLIkuHIg=="], - "detect-libc": ["detect-libc@2.0.4", "", {}, "sha512-3UDv+G9CsCKO1WKMGw9fwq/SWJYbI0c5Y7LU1AXYoDdbhE2AHQ6N6Nb34sG8Fj7T5APy8qXDCKuuIHd1BR0tVA=="], - "diff": ["diff@8.0.2", "", {}, "sha512-sSuxWU5j5SR9QQji/o2qMvqRNYRDOcBTgsJ/DeCf4iSN4gW+gNMXM7wFIP+fdXZxoNiAnHUTGjCr+TSWXdRDKg=="], "dts-resolver": ["dts-resolver@2.1.2", "", { "peerDependencies": { "oxc-resolver": ">=11.0.0" }, "optionalPeers": ["oxc-resolver"] }, "sha512-xeXHBQkn2ISSXxbJWD828PFjtyg+/UrMDo7W4Ffcs7+YWCquxU8YjV1KoxuiL+eJ5pg3ll+bC6flVv61L3LKZg=="], - "electron-to-chromium": ["electron-to-chromium@1.5.159", "", {}, "sha512-CEvHptWAMV5p6GJ0Lq8aheyvVbfzVrv5mmidu1D3pidoVNkB3tTBsTMVtPJ+rzRK5oV229mCLz9Zj/hNvU8GBA=="], + "electron-to-chromium": ["electron-to-chromium@1.5.243", "", {}, "sha512-ZCphxFW3Q1TVhcgS9blfut1PX8lusVi2SvXQgmEEnK4TCmE1JhH2JkjJN+DNt0pJJwfBri5AROBnz2b/C+YU9g=="], "empathic": ["empathic@2.0.0", "", {}, "sha512-i6UzDscO/XfAcNYD75CfICkmfLedpyPDdozrLMmQc5ORaQcdMoc21OnlEylMIqI7U8eniKrPMxxtj8k0vhmJhA=="], @@ -380,33 +402,33 @@ "es-module-lexer": ["es-module-lexer@1.7.0", "", {}, "sha512-jEQoCwk8hyb2AZziIOLhDqpm5+2ww5uIE6lkO/6jcOCusfk6LhMHpXXfBLXTZ7Ydyt0j4VoUQv6uGNYbdW+kBA=="], - "esbuild": ["esbuild@0.21.5", "", { "optionalDependencies": { "@esbuild/aix-ppc64": "0.21.5", "@esbuild/android-arm": "0.21.5", "@esbuild/android-arm64": "0.21.5", "@esbuild/android-x64": "0.21.5", "@esbuild/darwin-arm64": "0.21.5", "@esbuild/darwin-x64": "0.21.5", "@esbuild/freebsd-arm64": "0.21.5", "@esbuild/freebsd-x64": "0.21.5", "@esbuild/linux-arm": "0.21.5", "@esbuild/linux-arm64": "0.21.5", "@esbuild/linux-ia32": "0.21.5", "@esbuild/linux-loong64": "0.21.5", "@esbuild/linux-mips64el": "0.21.5", "@esbuild/linux-ppc64": "0.21.5", "@esbuild/linux-riscv64": "0.21.5", "@esbuild/linux-s390x": "0.21.5", "@esbuild/linux-x64": "0.21.5", "@esbuild/netbsd-x64": "0.21.5", "@esbuild/openbsd-x64": "0.21.5", "@esbuild/sunos-x64": "0.21.5", "@esbuild/win32-arm64": "0.21.5", "@esbuild/win32-ia32": "0.21.5", "@esbuild/win32-x64": "0.21.5" }, "bin": { "esbuild": "bin/esbuild" } }, "sha512-mg3OPMV4hXywwpoDxu3Qda5xCKQi+vCTZq8S9J/EpkhB2HzKXq4SNFZE3+NK93JYxc8VMSep+lOUSC/RVKaBqw=="], + "esbuild": ["esbuild@0.25.11", "", { "optionalDependencies": { "@esbuild/aix-ppc64": "0.25.11", "@esbuild/android-arm": "0.25.11", "@esbuild/android-arm64": "0.25.11", "@esbuild/android-x64": "0.25.11", "@esbuild/darwin-arm64": "0.25.11", "@esbuild/darwin-x64": "0.25.11", "@esbuild/freebsd-arm64": "0.25.11", "@esbuild/freebsd-x64": "0.25.11", "@esbuild/linux-arm": "0.25.11", "@esbuild/linux-arm64": "0.25.11", "@esbuild/linux-ia32": "0.25.11", "@esbuild/linux-loong64": "0.25.11", "@esbuild/linux-mips64el": "0.25.11", "@esbuild/linux-ppc64": "0.25.11", "@esbuild/linux-riscv64": "0.25.11", "@esbuild/linux-s390x": "0.25.11", "@esbuild/linux-x64": "0.25.11", "@esbuild/netbsd-arm64": "0.25.11", "@esbuild/netbsd-x64": "0.25.11", "@esbuild/openbsd-arm64": "0.25.11", "@esbuild/openbsd-x64": "0.25.11", "@esbuild/openharmony-arm64": "0.25.11", "@esbuild/sunos-x64": "0.25.11", "@esbuild/win32-arm64": "0.25.11", "@esbuild/win32-ia32": "0.25.11", "@esbuild/win32-x64": "0.25.11" }, "bin": { "esbuild": "bin/esbuild" } }, "sha512-KohQwyzrKTQmhXDW1PjCv3Tyspn9n5GcY2RTDqeORIdIJY8yKIF7sTSopFmn/wpMPW4rdPXI0UE5LJLuq3bx0Q=="], "escalade": ["escalade@3.2.0", "", {}, "sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA=="], "escape-string-regexp": ["escape-string-regexp@4.0.0", "", {}, "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA=="], - "eslint": ["eslint@9.27.0", "", { "dependencies": { "@eslint-community/eslint-utils": "^4.2.0", "@eslint-community/regexpp": "^4.12.1", "@eslint/config-array": "^0.20.0", "@eslint/config-helpers": "^0.2.1", "@eslint/core": "^0.14.0", "@eslint/eslintrc": "^3.3.1", "@eslint/js": "9.27.0", "@eslint/plugin-kit": "^0.3.1", "@humanfs/node": "^0.16.6", "@humanwhocodes/module-importer": "^1.0.1", "@humanwhocodes/retry": "^0.4.2", "@types/estree": "^1.0.6", "@types/json-schema": "^7.0.15", "ajv": "^6.12.4", "chalk": "^4.0.0", "cross-spawn": "^7.0.6", "debug": "^4.3.2", "escape-string-regexp": "^4.0.0", "eslint-scope": "^8.3.0", "eslint-visitor-keys": "^4.2.0", "espree": "^10.3.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" }, "peerDependencies": { "jiti": "*" }, "optionalPeers": ["jiti"], "bin": { "eslint": "bin/eslint.js" } }, "sha512-ixRawFQuMB9DZ7fjU3iGGganFDp3+45bPOdaRurcFHSXO1e/sYwUX/FtQZpLZJR6SjMoJH8hR2pPEAfDyCoU2Q=="], + "eslint": ["eslint@9.38.0", "", { "dependencies": { "@eslint-community/eslint-utils": "^4.8.0", "@eslint-community/regexpp": "^4.12.1", "@eslint/config-array": "^0.21.1", "@eslint/config-helpers": "^0.4.1", "@eslint/core": "^0.16.0", "@eslint/eslintrc": "^3.3.1", "@eslint/js": "9.38.0", "@eslint/plugin-kit": "^0.4.0", "@humanfs/node": "^0.16.6", "@humanwhocodes/module-importer": "^1.0.1", "@humanwhocodes/retry": "^0.4.2", "@types/estree": "^1.0.6", "ajv": "^6.12.4", "chalk": "^4.0.0", "cross-spawn": "^7.0.6", "debug": "^4.3.2", "escape-string-regexp": "^4.0.0", "eslint-scope": "^8.4.0", "eslint-visitor-keys": "^4.2.1", "espree": "^10.4.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" }, "peerDependencies": { "jiti": "*" }, "optionalPeers": ["jiti"], "bin": { "eslint": "bin/eslint.js" } }, "sha512-t5aPOpmtJcZcz5UJyY2GbvpDlsK5E8JqRqoKtfiKE3cNh437KIqfJr3A3AKf5k64NPx6d0G3dno6XDY05PqPtw=="], "eslint-compat-utils": ["eslint-compat-utils@0.5.1", "", { "dependencies": { "semver": "^7.5.4" }, "peerDependencies": { "eslint": ">=6.0.0" } }, "sha512-3z3vFexKIEnjHE3zCMRo6fn/e44U7T1khUjg+Hp0ZQMCigh28rALD0nPFBcGZuiLC5rLZa2ubQHDRln09JfU2Q=="], "eslint-plugin-es-x": ["eslint-plugin-es-x@7.8.0", "", { "dependencies": { "@eslint-community/eslint-utils": "^4.1.2", "@eslint-community/regexpp": "^4.11.0", "eslint-compat-utils": "^0.5.1" }, "peerDependencies": { "eslint": ">=8" } }, "sha512-7Ds8+wAAoV3T+LAKeu39Y5BzXCrGKrcISfgKEqTS4BDN8SFEDQd0S43jiQ8vIa3wUKD07qitZdfzlenSi8/0qQ=="], - "eslint-plugin-jsdoc": ["eslint-plugin-jsdoc@50.6.17", "", { "dependencies": { "@es-joy/jsdoccomment": "~0.50.1", "are-docs-informative": "^0.0.2", "comment-parser": "1.4.1", "debug": "^4.3.6", "escape-string-regexp": "^4.0.0", "espree": "^10.1.0", "esquery": "^1.6.0", "parse-imports-exports": "^0.2.4", "semver": "^7.6.3", "spdx-expression-parse": "^4.0.0" }, "peerDependencies": { "eslint": "^7.0.0 || ^8.0.0 || ^9.0.0" } }, "sha512-hq+VQylhd12l8qjexyriDsejZhqiP33WgMTy2AmaGZ9+MrMWVqPECsM87GPxgHfQn0zw+YTuhqjUfk1f+q67aQ=="], + "eslint-plugin-jsdoc": ["eslint-plugin-jsdoc@61.1.9", "", { "dependencies": { "@es-joy/jsdoccomment": "~0.76.0", "@es-joy/resolve.exports": "1.0.0", "are-docs-informative": "^0.0.2", "comment-parser": "1.4.1", "debug": "^4.4.3", "escape-string-regexp": "^4.0.0", "espree": "^10.4.0", "esquery": "^1.6.0", "html-entities": "^2.6.0", "object-deep-merge": "^2.0.0", "parse-imports-exports": "^0.2.4", "semver": "^7.7.3", "spdx-expression-parse": "^4.0.0", "to-valid-identifier": "^1.0.0" }, "peerDependencies": { "eslint": "^7.0.0 || ^8.0.0 || ^9.0.0" } }, "sha512-X2AzSGbq1CzBRgKcVAu2qzOV9ogqygkUDk5AX6eNK5G+kY3I5Op5E5b99fE+FN0/bGnk2KGcsMIG6ZLF+di69A=="], - "eslint-plugin-n": ["eslint-plugin-n@17.18.0", "", { "dependencies": { "@eslint-community/eslint-utils": "^4.5.0", "enhanced-resolve": "^5.17.1", "eslint-plugin-es-x": "^7.8.0", "get-tsconfig": "^4.8.1", "globals": "^15.11.0", "ignore": "^5.3.2", "minimatch": "^9.0.5", "semver": "^7.6.3" }, "peerDependencies": { "eslint": ">=8.23.0" } }, "sha512-hvZ/HusueqTJ7VDLoCpjN0hx4N4+jHIWTXD4TMLHy9F23XkDagR9v+xQWRWR57yY55GPF8NnD4ox9iGTxirY8A=="], + "eslint-plugin-n": ["eslint-plugin-n@17.23.1", "", { "dependencies": { "@eslint-community/eslint-utils": "^4.5.0", "enhanced-resolve": "^5.17.1", "eslint-plugin-es-x": "^7.8.0", "get-tsconfig": "^4.8.1", "globals": "^15.11.0", "globrex": "^0.1.2", "ignore": "^5.3.2", "semver": "^7.6.3", "ts-declaration-location": "^1.0.6" }, "peerDependencies": { "eslint": ">=8.23.0" } }, "sha512-68PealUpYoHOBh332JLLD9Sj7OQUDkFpmcfqt8R9sySfFSeuGJjMTJQvCRRB96zO3A/PELRLkPrzsHmzEFQQ5A=="], "eslint-plugin-promise": ["eslint-plugin-promise@7.2.1", "", { "dependencies": { "@eslint-community/eslint-utils": "^4.4.0" }, "peerDependencies": { "eslint": "^7.0.0 || ^8.0.0 || ^9.0.0" } }, "sha512-SWKjd+EuvWkYaS+uN2csvj0KoP43YTu7+phKQ5v+xw6+A0gutVX2yqCeCkC3uLCJFiPfR2dD8Es5L7yUsmvEaA=="], - "eslint-plugin-unicorn": ["eslint-plugin-unicorn@59.0.1", "", { "dependencies": { "@babel/helper-validator-identifier": "^7.25.9", "@eslint-community/eslint-utils": "^4.5.1", "@eslint/plugin-kit": "^0.2.7", "ci-info": "^4.2.0", "clean-regexp": "^1.0.0", "core-js-compat": "^3.41.0", "esquery": "^1.6.0", "find-up-simple": "^1.0.1", "globals": "^16.0.0", "indent-string": "^5.0.0", "is-builtin-module": "^5.0.0", "jsesc": "^3.1.0", "pluralize": "^8.0.0", "regexp-tree": "^0.1.27", "regjsparser": "^0.12.0", "semver": "^7.7.1", "strip-indent": "^4.0.0" }, "peerDependencies": { "eslint": ">=9.22.0" } }, "sha512-EtNXYuWPUmkgSU2E7Ttn57LbRREQesIP1BiLn7OZLKodopKfDXfBUkC/0j6mpw2JExwf43Uf3qLSvrSvppgy8Q=="], + "eslint-plugin-unicorn": ["eslint-plugin-unicorn@62.0.0", "", { "dependencies": { "@babel/helper-validator-identifier": "^7.28.5", "@eslint-community/eslint-utils": "^4.9.0", "@eslint/plugin-kit": "^0.4.0", "change-case": "^5.4.4", "ci-info": "^4.3.1", "clean-regexp": "^1.0.0", "core-js-compat": "^3.46.0", "esquery": "^1.6.0", "find-up-simple": "^1.0.1", "globals": "^16.4.0", "indent-string": "^5.0.0", "is-builtin-module": "^5.0.0", "jsesc": "^3.1.0", "pluralize": "^8.0.0", "regexp-tree": "^0.1.27", "regjsparser": "^0.13.0", "semver": "^7.7.3", "strip-indent": "^4.1.1" }, "peerDependencies": { "eslint": ">=9.38.0" } }, "sha512-HIlIkGLkvf29YEiS/ImuDZQbP12gWyx5i3C6XrRxMvVdqMroCI9qoVYCoIl17ChN+U89pn9sVwLxhIWj5nEc7g=="], - "eslint-plugin-vue": ["eslint-plugin-vue@10.1.0", "", { "dependencies": { "@eslint-community/eslint-utils": "^4.4.0", "natural-compare": "^1.4.0", "nth-check": "^2.1.1", "postcss-selector-parser": "^6.0.15", "semver": "^7.6.3", "xml-name-validator": "^4.0.0" }, "peerDependencies": { "eslint": "^8.57.0 || ^9.0.0", "vue-eslint-parser": "^10.0.0" } }, "sha512-/VTiJ1eSfNLw6lvG9ENySbGmcVvz6wZ9nA7ZqXlLBY2RkaF15iViYKxglWiIch12KiLAj0j1iXPYU6W4wTROFA=="], + "eslint-plugin-vue": ["eslint-plugin-vue@10.5.1", "", { "dependencies": { "@eslint-community/eslint-utils": "^4.4.0", "natural-compare": "^1.4.0", "nth-check": "^2.1.1", "postcss-selector-parser": "^6.0.15", "semver": "^7.6.3", "xml-name-validator": "^4.0.0" }, "peerDependencies": { "@stylistic/eslint-plugin": "^2.0.0 || ^3.0.0 || ^4.0.0 || ^5.0.0", "@typescript-eslint/parser": "^7.0.0 || ^8.0.0", "eslint": "^8.57.0 || ^9.0.0", "vue-eslint-parser": "^10.0.0" }, "optionalPeers": ["@stylistic/eslint-plugin", "@typescript-eslint/parser"] }, "sha512-SbR9ZBUFKgvWAbq3RrdCtWaW0IKm6wwUiApxf3BVTNfqUIo4IQQmreMg2iHFJJ6C/0wss3LXURBJ1OwS/MhFcQ=="], - "eslint-scope": ["eslint-scope@8.3.0", "", { "dependencies": { "esrecurse": "^4.3.0", "estraverse": "^5.2.0" } }, "sha512-pUNxi75F8MJ/GdeKtVLSbYg4ZI34J6C0C7sbL4YOp2exGwen7ZsuBqKzUhXd0qMQ362yET3z+uPwKeg/0C2XCQ=="], + "eslint-scope": ["eslint-scope@8.4.0", "", { "dependencies": { "esrecurse": "^4.3.0", "estraverse": "^5.2.0" } }, "sha512-sNXOfKCn74rt8RICKMvJS7XKV/Xk9kA7DyJr8mJik3S7Cwgy3qlkkmyS2uQB3jiJg6VNdZd/pDBJu0nvG2NlTg=="], - "eslint-visitor-keys": ["eslint-visitor-keys@4.2.0", "", {}, "sha512-UyLnSehNt62FFhSwjZlHmeokpRK59rcz29j+F1/aDgbkbRTk7wIc9XzdoasMUbRNKDM0qQt/+BJ4BrpFeABemw=="], + "eslint-visitor-keys": ["eslint-visitor-keys@4.2.1", "", {}, "sha512-Uhdk5sfqcee/9H/rCOJikYz67o0a2Tw2hGRPOG2Y1R2dg7brRe1uG0yaNQDHu+TO/uQPF/5eCapvYSmHUjt7JQ=="], - "espree": ["espree@10.3.0", "", { "dependencies": { "acorn": "^8.14.0", "acorn-jsx": "^5.3.2", "eslint-visitor-keys": "^4.2.0" } }, "sha512-0QYC8b24HWY8zjRnDTL6RiHfDbAWn63qb4LMj1Z4b076A4une81+z03Kg7l7mn/48PUTqoLptSXez8oknU8Clg=="], + "espree": ["espree@10.4.0", "", { "dependencies": { "acorn": "^8.15.0", "acorn-jsx": "^5.3.2", "eslint-visitor-keys": "^4.2.1" } }, "sha512-j6PAQ2uUr79PZhBjP5C5fhl8e39FmRnOjsD5lGnWrFU8i2G776tBK7+nP8KuQUTTyAZUwfQqXAgrVH5MbH9CYQ=="], "esquery": ["esquery@1.6.0", "", { "dependencies": { "estraverse": "^5.1.0" } }, "sha512-ca9pw9fomFcKPvFLXhBKUK90ZvGibiGOvRJNbjljY7s7uq/5YO4BOzcYtJqExdx99rF6aAcnRxHmcUHcz6sQsg=="], @@ -418,7 +440,7 @@ "esutils": ["esutils@2.0.3", "", {}, "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g=="], - "expect-type": ["expect-type@1.2.1", "", {}, "sha512-/kP8CAwxzLVEeFrMm4kMmy4CCDlpipyA7MYLVrdJIkV0fYF0UaigQHRsxHiuY/GEea+bh4KSv3TIlgr+2UL6bw=="], + "expect-type": ["expect-type@1.2.2", "", {}, "sha512-JhFGDVJ7tmDJItKhYgJCGLOWjuK9vPxiXoUFLwLDc99NlmklilbiQJwoctZtt13+xMw91MCk/REan6MWHqDjyA=="], "exsolve": ["exsolve@1.0.7", "", {}, "sha512-VO5fQUzZtI6C+vx4w/4BWJpg3s/5l+6pRQEHzFRM8WFi4XffSP1Z+4qi7GbjWbvRQEbdIco5mIMq+zX4rPuLrw=="], @@ -432,7 +454,7 @@ "fastq": ["fastq@1.17.1", "", { "dependencies": { "reusify": "^1.0.4" } }, "sha512-sRVD3lWVIXWg6By68ZN7vho9a1pQcN/WBFaAAsDDFzlJjvoGx0P8z7V1t72grFJfJhu3YPZBuu25f7Kaw2jN1w=="], - "fdir": ["fdir@6.4.4", "", { "peerDependencies": { "picomatch": "^3 || ^4" }, "optionalPeers": ["picomatch"] }, "sha512-1NZP+GK4GfuAv3PqKvxQRDMjdSRZjnkq7KfhlNrCNNlZ0ygQFpebfrnfnq/W7fpUnAv9aGWmY1zKx7FYL3gwhg=="], + "fdir": ["fdir@6.5.0", "", { "peerDependencies": { "picomatch": "^3 || ^4" }, "optionalPeers": ["picomatch"] }, "sha512-tIbYtZbucOs0BRGqPJkshJUYdL+SDH7dVM8gjy+ERp3WAUjLEFJE+02kanyHtwjWOnwrKYBiwAmM0p4kLJAnXg=="], "file-entry-cache": ["file-entry-cache@8.0.0", "", { "dependencies": { "flat-cache": "^4.0.0" } }, "sha512-XXTUwCvisa5oacNGRP9SfNtYBNAMi+RPwBFmblZEF7N7swHYQS6/Zfk7SRwx4D5j3CH211YNRco1DEMNVfZCnQ=="], @@ -454,6 +476,8 @@ "globals": ["globals@15.15.0", "", {}, "sha512-7ACyT3wmyp3I61S4fG682L0VA2RGD9otkqGJIwNUMF1SWUombIIk+af1unuDYgMm082aHYwD+mzJvv9Iu8dsgg=="], + "globrex": ["globrex@0.1.2", "", {}, "sha512-uHJgbwAMwNFf5mLst7IWLNg14x1CkeqglJb/K3doi4dw6q2IvAAmM/Y81kevy83wP+Sst+nutFTYOGg3d1lsxg=="], + "graceful-fs": ["graceful-fs@4.2.11", "", {}, "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ=="], "graphemer": ["graphemer@1.4.0", "", {}, "sha512-EtKwoO6kxCL9WO5xipiHTZlSzBm7WLT627TqC/uVRd0HKmq8NXyebnNYxDoBi7wt8eTWrUrKXCOVaFq9x1kgag=="], @@ -462,6 +486,8 @@ "hookable": ["hookable@5.5.3", "", {}, "sha512-Yc+BQe8SvoXH1643Qez1zqLRmbA5rCL+sSmk6TVos0LWVfNIB7PGncdlId77WzLGSIB5KaWgTaNTs2lNVEI6VQ=="], + "html-entities": ["html-entities@2.6.0", "", {}, "sha512-kig+rMn/QOVRvr7c86gQ8lWXq+Hkv6CbAH1hLu+RG338StTpE8Z0b44SDVaqVu7HGKf27frdmUYEs9hTUX/cLQ=="], + "ignore": ["ignore@5.3.2", "", {}, "sha512-hsBTNUqQTDwkWtcdYI2i06Y/nUBEsNEDJKjWdigLvegy8kDuJAS8uRlpkkcQpyEXL0Z/pjDy5HBmMjRCJ2gq+g=="], "import-fresh": ["import-fresh@3.3.0", "", { "dependencies": { "parent-module": "^1.0.0", "resolve-from": "^4.0.0" } }, "sha512-veYYhQa+D1QBKznvhUHxb8faxlrwUnxseDAbAp457E0wLNio2bOSKnjYDhMj+YiAq61xrMGhQk9iXVk5FzgQMw=="], @@ -488,7 +514,7 @@ "js-yaml": ["js-yaml@4.1.0", "", { "dependencies": { "argparse": "^2.0.1" }, "bin": { "js-yaml": "bin/js-yaml.js" } }, "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA=="], - "jsdoc-type-pratt-parser": ["jsdoc-type-pratt-parser@4.1.0", "", {}, "sha512-Hicd6JK5Njt2QB6XYFS7ok9e37O8AYk3jTcppG4YVQnYjOemymvTcmc7OWsmq/Qqj5TdRFO5/x/tIPmBeRtGHg=="], + "jsdoc-type-pratt-parser": ["jsdoc-type-pratt-parser@6.10.0", "", {}, "sha512-+LexoTRyYui5iOhJGn13N9ZazL23nAHGkXsa1p/C8yeq79WRfLBag6ZZ0FQG2aRoc9yfo59JT9EYCQonOkHKkQ=="], "jsesc": ["jsesc@3.1.0", "", { "bin": { "jsesc": "bin/jsesc" } }, "sha512-/sM3dO2FOzXjKQhJuo0Q173wf2KOo8t4I8vHy6lF9poUp7bKT0/NHE8fPX23PwfhnykfqnC2xRxOnVw5XuGIaA=="], @@ -502,63 +528,39 @@ "levn": ["levn@0.4.1", "", { "dependencies": { "prelude-ls": "^1.2.1", "type-check": "~0.4.0" } }, "sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ=="], - "lightningcss": ["lightningcss@1.30.1", "", { "dependencies": { "detect-libc": "^2.0.3" }, "optionalDependencies": { "lightningcss-darwin-arm64": "1.30.1", "lightningcss-darwin-x64": "1.30.1", "lightningcss-freebsd-x64": "1.30.1", "lightningcss-linux-arm-gnueabihf": "1.30.1", "lightningcss-linux-arm64-gnu": "1.30.1", "lightningcss-linux-arm64-musl": "1.30.1", "lightningcss-linux-x64-gnu": "1.30.1", "lightningcss-linux-x64-musl": "1.30.1", "lightningcss-win32-arm64-msvc": "1.30.1", "lightningcss-win32-x64-msvc": "1.30.1" } }, "sha512-xi6IyHML+c9+Q3W0S4fCQJOym42pyurFiJUHEcEyHS0CeKzia4yZDEsLlqOFykxOdHpNy0NmvVO31vcSqAxJCg=="], - - "lightningcss-darwin-arm64": ["lightningcss-darwin-arm64@1.30.1", "", { "os": "darwin", "cpu": "arm64" }, "sha512-c8JK7hyE65X1MHMN+Viq9n11RRC7hgin3HhYKhrMyaXflk5GVplZ60IxyoVtzILeKr+xAJwg6zK6sjTBJ0FKYQ=="], - - "lightningcss-darwin-x64": ["lightningcss-darwin-x64@1.30.1", "", { "os": "darwin", "cpu": "x64" }, "sha512-k1EvjakfumAQoTfcXUcHQZhSpLlkAuEkdMBsI/ivWw9hL+7FtilQc0Cy3hrx0AAQrVtQAbMI7YjCgYgvn37PzA=="], - - "lightningcss-freebsd-x64": ["lightningcss-freebsd-x64@1.30.1", "", { "os": "freebsd", "cpu": "x64" }, "sha512-kmW6UGCGg2PcyUE59K5r0kWfKPAVy4SltVeut+umLCFoJ53RdCUWxcRDzO1eTaxf/7Q2H7LTquFHPL5R+Gjyig=="], - - "lightningcss-linux-arm-gnueabihf": ["lightningcss-linux-arm-gnueabihf@1.30.1", "", { "os": "linux", "cpu": "arm" }, "sha512-MjxUShl1v8pit+6D/zSPq9S9dQ2NPFSQwGvxBCYaBYLPlCWuPh9/t1MRS8iUaR8i+a6w7aps+B4N0S1TYP/R+Q=="], - - "lightningcss-linux-arm64-gnu": ["lightningcss-linux-arm64-gnu@1.30.1", "", { "os": "linux", "cpu": "arm64" }, "sha512-gB72maP8rmrKsnKYy8XUuXi/4OctJiuQjcuqWNlJQ6jZiWqtPvqFziskH3hnajfvKB27ynbVCucKSm2rkQp4Bw=="], - - "lightningcss-linux-arm64-musl": ["lightningcss-linux-arm64-musl@1.30.1", "", { "os": "linux", "cpu": "arm64" }, "sha512-jmUQVx4331m6LIX+0wUhBbmMX7TCfjF5FoOH6SD1CttzuYlGNVpA7QnrmLxrsub43ClTINfGSYyHe2HWeLl5CQ=="], - - "lightningcss-linux-x64-gnu": ["lightningcss-linux-x64-gnu@1.30.1", "", { "os": "linux", "cpu": "x64" }, "sha512-piWx3z4wN8J8z3+O5kO74+yr6ze/dKmPnI7vLqfSqI8bccaTGY5xiSGVIJBDd5K5BHlvVLpUB3S2YCfelyJ1bw=="], - - "lightningcss-linux-x64-musl": ["lightningcss-linux-x64-musl@1.30.1", "", { "os": "linux", "cpu": "x64" }, "sha512-rRomAK7eIkL+tHY0YPxbc5Dra2gXlI63HL+v1Pdi1a3sC+tJTcFrHX+E86sulgAXeI7rSzDYhPSeHHjqFhqfeQ=="], - - "lightningcss-win32-arm64-msvc": ["lightningcss-win32-arm64-msvc@1.30.1", "", { "os": "win32", "cpu": "arm64" }, "sha512-mSL4rqPi4iXq5YVqzSsJgMVFENoa4nGTT/GjO2c0Yl9OuQfPsIfncvLrEW6RbbB24WtZ3xP/2CCmI3tNkNV4oA=="], - - "lightningcss-win32-x64-msvc": ["lightningcss-win32-x64-msvc@1.30.1", "", { "os": "win32", "cpu": "x64" }, "sha512-PVqXh48wh4T53F/1CCu8PIPCxLzWyCnn/9T5W1Jpmdy5h9Cwd+0YQS6/LwhHXSafuc61/xg9Lv5OrCby6a++jg=="], - "locate-path": ["locate-path@6.0.0", "", { "dependencies": { "p-locate": "^5.0.0" } }, "sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw=="], "lodash": ["lodash@4.17.21", "", {}, "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg=="], "lodash.merge": ["lodash.merge@4.6.2", "", {}, "sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ=="], - "loupe": ["loupe@3.2.1", "", {}, "sha512-CdzqowRJCeLU72bHvWqwRBBlLcMEtIvGrlvef74kMnV2AolS9Y8xUv1I0U/MNAWMhBlKIoyuEgoJ0t/bbwHbLQ=="], - - "magic-string": ["magic-string@0.30.17", "", { "dependencies": { "@jridgewell/sourcemap-codec": "^1.5.0" } }, "sha512-sNPKHvyjVf7gyjwS4xGTaW/mCnF8wnjtifKBEhxfZ7E/S8tQ0rssrwGNn6q8JH/ohItJfSQp9mBtQYuTlH5QnA=="], + "magic-string": ["magic-string@0.30.21", "", { "dependencies": { "@jridgewell/sourcemap-codec": "^1.5.5" } }, "sha512-vd2F4YUyEXKGcLHoq+TEyCjxueSeHnFxyyjNp80yg0XV4vUhnDer/lvvlqM/arB5bXQN5K2/3oinyCRyx8T2CQ=="], "merge2": ["merge2@1.4.1", "", {}, "sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg=="], "micromatch": ["micromatch@4.0.8", "", { "dependencies": { "braces": "^3.0.3", "picomatch": "^2.3.1" } }, "sha512-PXwfBhYu0hBCPw8Dn0E+WDYb7af3dSLVWKi3HGv84IdF4TyFoC0ysxFd0Goxw7nSv4T/PzEJQxsYsEiFCKo2BA=="], - "min-indent": ["min-indent@1.0.1", "", {}, "sha512-I9jwMn07Sy/IwOj3zVkVik2JTvgpaykDZEigL6Rx6N9LbMywwUSMtxET+7lVoDLLd3O3IXwJwvuuns8UB/HeAg=="], - "minimatch": ["minimatch@3.1.2", "", { "dependencies": { "brace-expansion": "^1.1.7" } }, "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw=="], "mri": ["mri@1.2.0", "", {}, "sha512-tzzskb3bG8LvYGFF/mDTpq3jpI6Q9wc3LEmBaghu+DdCssd1FakN7Bc0hVNmEyGq1bq3RgfkCb3cmQLpNPOroA=="], "ms": ["ms@2.1.3", "", {}, "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA=="], - "nanoid": ["nanoid@3.3.7", "", { "bin": { "nanoid": "bin/nanoid.cjs" } }, "sha512-eSRppjcPIatRIMC1U6UngP8XFcz8MQWGQdt1MTBQ7NaAmvXDfvNxbvWV3x2y6CdEUciCSsDHDQZbhYaB8QEo2g=="], + "nanoid": ["nanoid@3.3.11", "", { "bin": { "nanoid": "bin/nanoid.cjs" } }, "sha512-N8SpfPUnUp1bK+PMYW8qSWdl9U+wwNWI4QKxOYDy9JAro3WMX7p2OeVRF9v+347pnakNevPmiHhNmZ2HbFA76w=="], "natural-compare": ["natural-compare@1.4.0", "", {}, "sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw=="], "neoevents": ["neoevents@0.3.0", "", {}, "sha512-et9vcJ8ElRUbgxeJXAw++1noXVY302fxRvwEoIDll9KiQAeySjTQBdLtATvtE17MgbitLjjixI5UcFOS92EI+w=="], - "node-releases": ["node-releases@2.0.19", "", {}, "sha512-xxOWJsBKtzAq7DY0J+DTzuz58K8e7sJbdgwkbMWQe8UYB6ekmsQ45q0M/tJDsGaZmbC+l7n57UV8Hl5tHxO9uw=="], + "node-releases": ["node-releases@2.0.26", "", {}, "sha512-S2M9YimhSjBSvYnlr5/+umAnPHE++ODwt5e2Ij6FoX45HA/s4vHdkDx1eax2pAPeAOqu4s9b7ppahsyEFdVqQA=="], "nth-check": ["nth-check@2.1.1", "", { "dependencies": { "boolbase": "^1.0.0" } }, "sha512-lqjrjmaOoAnWfMmBPL+XNnynZh2+swxiX3WUE0s4yEHI6m+AwrK2UZOimIRl3X/4QctVqS8AiZjFqyOGrMXb/w=="], + "object-deep-merge": ["object-deep-merge@2.0.0", "", {}, "sha512-3DC3UMpeffLTHiuXSy/UG4NOIYTLlY9u3V82+djSCLYClWobZiS4ivYzpIUWrRY/nfsJ8cWsKyG3QfyLePmhvg=="], + "optionator": ["optionator@0.9.4", "", { "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" } }, "sha512-6IpQ7mKUxRcZNLIObR0hz7lxsapSSIYNZJwXPGeF0mTVqGKFIXj1DQcMoT22S3ROcLyY/rz0PWaWZ9ayWmad9g=="], - "oxlint": ["oxlint@1.3.0", "", { "optionalDependencies": { "@oxlint/darwin-arm64": "1.3.0", "@oxlint/darwin-x64": "1.3.0", "@oxlint/linux-arm64-gnu": "1.3.0", "@oxlint/linux-arm64-musl": "1.3.0", "@oxlint/linux-x64-gnu": "1.3.0", "@oxlint/linux-x64-musl": "1.3.0", "@oxlint/win32-arm64": "1.3.0", "@oxlint/win32-x64": "1.3.0" }, "bin": { "oxlint": "bin/oxlint", "oxc_language_server": "bin/oxc_language_server" } }, "sha512-PzAOmPxnXYpVF1q6h9pkOPH6uJ/44XrtFWJ8JcEMpoEq9HISNelD3lXhACtOAW8CArjLy/qSlu2KkyPxnXgctA=="], + "oxlint": ["oxlint@1.24.0", "", { "optionalDependencies": { "@oxlint/darwin-arm64": "1.24.0", "@oxlint/darwin-x64": "1.24.0", "@oxlint/linux-arm64-gnu": "1.24.0", "@oxlint/linux-arm64-musl": "1.24.0", "@oxlint/linux-x64-gnu": "1.24.0", "@oxlint/linux-x64-musl": "1.24.0", "@oxlint/win32-arm64": "1.24.0", "@oxlint/win32-x64": "1.24.0" }, "peerDependencies": { "oxlint-tsgolint": ">=0.2.0" }, "optionalPeers": ["oxlint-tsgolint"], "bin": { "oxlint": "bin/oxlint", "oxc_language_server": "bin/oxc_language_server" } }, "sha512-swXlnHT7ywcCApkctIbgOSjDYHwMa12yMU0iXevfDuHlYkRUcbQrUv6nhM5v6B0+Be3zTBMNDGPAMQv0oznzRQ=="], "p-limit": ["p-limit@3.1.0", "", { "dependencies": { "yocto-queue": "^0.1.0" } }, "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ=="], @@ -578,23 +580,21 @@ "pathe": ["pathe@2.0.3", "", {}, "sha512-WUjGcAqP1gQacoQe+OBJsFA7Ld4DyXuUIjZ5cc75cLHvJ7dtNsTugphxIADwspS+AraAUePCKrSVtPLFj/F88w=="], - "pathval": ["pathval@2.0.0", "", {}, "sha512-vE7JKRyES09KiunauX7nd2Q9/L7lhok4smP9RZTDeD4MVs72Dp2qNFVz39Nz5a0FVEW0BJR6C0DYrq6unoziZA=="], - "picocolors": ["picocolors@1.1.1", "", {}, "sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA=="], - "picomatch": ["picomatch@4.0.2", "", {}, "sha512-M7BAV6Rlcy5u+m6oPhAPFgJTzAioX/6B0DxyvDlo9l8+T3nLKbrczg2WLUyzd45L8RqfUMyGPzekbMvX2Ldkwg=="], + "picomatch": ["picomatch@4.0.3", "", {}, "sha512-5gTmgEY/sqK6gFXLIsQNH19lWb4ebPDLA4SdLP7dsWkIXHWlG66oPuVvXSGFPppYZz8ZDZq0dYYrbHfBCVUb1Q=="], "pkg-types": ["pkg-types@2.3.0", "", { "dependencies": { "confbox": "^0.2.2", "exsolve": "^1.0.7", "pathe": "^2.0.3" } }, "sha512-SIqCzDRg0s9npO5XQ3tNZioRY1uK06lA41ynBC1YmFTmnY6FjUjVt6s4LoADmwoig1qqD0oK8h1p/8mlMx8Oig=="], "pluralize": ["pluralize@8.0.0", "", {}, "sha512-Nc3IT5yHzflTfbjgqWcCPpo7DaKy4FnpB0l/zCAW0Tc7jxAiuqSxHasntB3D7887LSrA93kDJ9IXovxJYxyLCA=="], - "postcss": ["postcss@8.4.45", "", { "dependencies": { "nanoid": "^3.3.7", "picocolors": "^1.0.1", "source-map-js": "^1.2.0" } }, "sha512-7KTLTdzdZZYscUc65XmjFiB73vBhBfbPztCYdUNvlaso9PrzjzcmjqBPR0lNGkcVlcO4BjiO5rK/qNz+XAen1Q=="], + "postcss": ["postcss@8.5.6", "", { "dependencies": { "nanoid": "^3.3.11", "picocolors": "^1.1.1", "source-map-js": "^1.2.1" } }, "sha512-3Ybi1tAuwAP9s0r1UQ2J4n5Y0G05bJkpUIO0/bI9MhwmD70S5aTWbXGBwxHrelT+XM1k6dM0pk+SwNkpTRN7Pg=="], "postcss-selector-parser": ["postcss-selector-parser@6.1.2", "", { "dependencies": { "cssesc": "^3.0.0", "util-deprecate": "^1.0.2" } }, "sha512-Q8qQfPiZ+THO/3ZrOrO0cJJKfpYCagtMUkXbnEfmgUjwXg6z/WBeOyS9APBBPCTSiDV+s4SwQGu8yFsiMRIudg=="], "prelude-ls": ["prelude-ls@1.2.1", "", {}, "sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g=="], - "publint": ["publint@0.3.12", "", { "dependencies": { "@publint/pack": "^0.1.2", "package-manager-detector": "^1.1.0", "picocolors": "^1.1.1", "sade": "^1.8.1" }, "bin": { "publint": "src/cli.js" } }, "sha512-1w3MMtL9iotBjm1mmXtG3Nk06wnq9UhGNRpQ2j6n1Zq7YAD6gnxMMZMIxlRPAydVjVbjSm+n0lhwqsD1m4LD5w=="], + "publint": ["publint@0.3.15", "", { "dependencies": { "@publint/pack": "^0.1.2", "package-manager-detector": "^1.3.0", "picocolors": "^1.1.1", "sade": "^1.8.1" }, "bin": { "publint": "src/cli.js" } }, "sha512-xPbRAPW+vqdiaKy5sVVY0uFAu3LaviaPO3pZ9FaRx59l9+U/RKR1OEbLhkug87cwiVKxPXyB4txsv5cad67u+A=="], "punycode": ["punycode@2.3.1", "", {}, "sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg=="], @@ -606,7 +606,9 @@ "regexp-tree": ["regexp-tree@0.1.27", "", { "bin": { "regexp-tree": "bin/regexp-tree" } }, "sha512-iETxpjK6YoRWJG5o6hXLwvjYAoW+FEZn9os0PD/b6AP6xQwsa/Y7lCVgIixBbUPMfhu+i2LtdeAqVTgGlQarfA=="], - "regjsparser": ["regjsparser@0.12.0", "", { "dependencies": { "jsesc": "~3.0.2" }, "bin": { "regjsparser": "bin/parser" } }, "sha512-cnE+y8bz4NhMjISKbgeVJtqNbtf5QpjZP+Bslo+UqkIt9QPnX9q095eiRRASJG1/tz6dlNr6Z5NsBiWYokp6EQ=="], + "regjsparser": ["regjsparser@0.13.0", "", { "dependencies": { "jsesc": "~3.1.0" }, "bin": { "regjsparser": "bin/parser" } }, "sha512-NZQZdC5wOE/H3UT28fVGL+ikOZcEzfMGk/c3iN9UGxzWHMa1op7274oyiUVrAG4B2EuFhus8SvkaYnhvW92p9Q=="], + + "reserved-identifiers": ["reserved-identifiers@1.2.0", "", {}, "sha512-yE7KUfFvaBFzGPs5H3Ops1RevfUEsDc5Iz65rOwWg4lE8HJSYtle77uul3+573457oHvBKuHYDl/xqUkKpEEdw=="], "resolve-from": ["resolve-from@4.0.0", "", {}, "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g=="], @@ -614,17 +616,17 @@ "reusify": ["reusify@1.0.4", "", {}, "sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw=="], - "rolldown": ["rolldown@1.0.0-beta.34", "", { "dependencies": { "@oxc-project/runtime": "=0.82.3", "@oxc-project/types": "=0.82.3", "@rolldown/pluginutils": "1.0.0-beta.34", "ansis": "^4.0.0" }, "optionalDependencies": { "@rolldown/binding-android-arm64": "1.0.0-beta.34", "@rolldown/binding-darwin-arm64": "1.0.0-beta.34", "@rolldown/binding-darwin-x64": "1.0.0-beta.34", "@rolldown/binding-freebsd-x64": "1.0.0-beta.34", "@rolldown/binding-linux-arm-gnueabihf": "1.0.0-beta.34", "@rolldown/binding-linux-arm64-gnu": "1.0.0-beta.34", "@rolldown/binding-linux-arm64-musl": "1.0.0-beta.34", "@rolldown/binding-linux-x64-gnu": "1.0.0-beta.34", "@rolldown/binding-linux-x64-musl": "1.0.0-beta.34", "@rolldown/binding-openharmony-arm64": "1.0.0-beta.34", "@rolldown/binding-wasm32-wasi": "1.0.0-beta.34", "@rolldown/binding-win32-arm64-msvc": "1.0.0-beta.34", "@rolldown/binding-win32-ia32-msvc": "1.0.0-beta.34", "@rolldown/binding-win32-x64-msvc": "1.0.0-beta.34" }, "bin": { "rolldown": "bin/cli.mjs" } }, "sha512-Wwh7EwalMzzX3Yy3VN58VEajeR2Si8+HDNMf706jPLIqU7CxneRW+dQVfznf5O0TWTnJyu4npelwg2bzTXB1Nw=="], + "rolldown": ["rolldown@1.0.0-beta.45", "", { "dependencies": { "@oxc-project/types": "=0.95.0", "@rolldown/pluginutils": "1.0.0-beta.45" }, "optionalDependencies": { "@rolldown/binding-android-arm64": "1.0.0-beta.45", "@rolldown/binding-darwin-arm64": "1.0.0-beta.45", "@rolldown/binding-darwin-x64": "1.0.0-beta.45", "@rolldown/binding-freebsd-x64": "1.0.0-beta.45", "@rolldown/binding-linux-arm-gnueabihf": "1.0.0-beta.45", "@rolldown/binding-linux-arm64-gnu": "1.0.0-beta.45", "@rolldown/binding-linux-arm64-musl": "1.0.0-beta.45", "@rolldown/binding-linux-x64-gnu": "1.0.0-beta.45", "@rolldown/binding-linux-x64-musl": "1.0.0-beta.45", "@rolldown/binding-openharmony-arm64": "1.0.0-beta.45", "@rolldown/binding-wasm32-wasi": "1.0.0-beta.45", "@rolldown/binding-win32-arm64-msvc": "1.0.0-beta.45", "@rolldown/binding-win32-ia32-msvc": "1.0.0-beta.45", "@rolldown/binding-win32-x64-msvc": "1.0.0-beta.45" }, "bin": { "rolldown": "bin/cli.mjs" } }, "sha512-iMmuD72XXLf26Tqrv1cryNYLX6NNPLhZ3AmNkSf8+xda0H+yijjGJ+wVT9UdBUHOpKzq9RjKtQKRCWoEKQQBZQ=="], - "rolldown-plugin-dts": ["rolldown-plugin-dts@0.15.10", "", { "dependencies": { "@babel/generator": "^7.28.3", "@babel/parser": "^7.28.3", "@babel/types": "^7.28.2", "ast-kit": "^2.1.2", "birpc": "^2.5.0", "debug": "^4.4.1", "dts-resolver": "^2.1.2", "get-tsconfig": "^4.10.1" }, "peerDependencies": { "@typescript/native-preview": ">=7.0.0-dev.20250601.1", "rolldown": "^1.0.0-beta.9", "typescript": "^5.0.0", "vue-tsc": "~3.0.3" }, "optionalPeers": ["@typescript/native-preview", "typescript", "vue-tsc"] }, "sha512-8cPVAVQUo9tYAoEpc3jFV9RxSil13hrRRg8cHC9gLXxRMNtWPc1LNMSDXzjyD+5Vny49sDZH77JlXp/vlc4I3g=="], + "rolldown-plugin-dts": ["rolldown-plugin-dts@0.17.3", "", { "dependencies": { "@babel/generator": "^7.28.5", "@babel/parser": "^7.28.5", "@babel/types": "^7.28.5", "ast-kit": "^2.1.3", "birpc": "^2.6.1", "debug": "^4.4.3", "dts-resolver": "^2.1.2", "get-tsconfig": "^4.13.0", "magic-string": "^0.30.21" }, "peerDependencies": { "@ts-macro/tsc": "^0.3.6", "@typescript/native-preview": ">=7.0.0-dev.20250601.1", "rolldown": "^1.0.0-beta.44", "typescript": "^5.0.0", "vue-tsc": "~3.1.0" }, "optionalPeers": ["@ts-macro/tsc", "@typescript/native-preview", "typescript", "vue-tsc"] }, "sha512-8mGnNUVNrqEdTnrlcaDxs4sAZg0No6njO+FuhQd4L56nUbJO1tHxOoKDH3mmMJg7f/BhEj/1KjU5W9kZ9zM/kQ=="], - "rollup": ["rollup@4.21.2", "", { "dependencies": { "@types/estree": "1.0.5" }, "optionalDependencies": { "@rollup/rollup-android-arm-eabi": "4.21.2", "@rollup/rollup-android-arm64": "4.21.2", "@rollup/rollup-darwin-arm64": "4.21.2", "@rollup/rollup-darwin-x64": "4.21.2", "@rollup/rollup-linux-arm-gnueabihf": "4.21.2", "@rollup/rollup-linux-arm-musleabihf": "4.21.2", "@rollup/rollup-linux-arm64-gnu": "4.21.2", "@rollup/rollup-linux-arm64-musl": "4.21.2", "@rollup/rollup-linux-powerpc64le-gnu": "4.21.2", "@rollup/rollup-linux-riscv64-gnu": "4.21.2", "@rollup/rollup-linux-s390x-gnu": "4.21.2", "@rollup/rollup-linux-x64-gnu": "4.21.2", "@rollup/rollup-linux-x64-musl": "4.21.2", "@rollup/rollup-win32-arm64-msvc": "4.21.2", "@rollup/rollup-win32-ia32-msvc": "4.21.2", "@rollup/rollup-win32-x64-msvc": "4.21.2", "fsevents": "~2.3.2" }, "bin": { "rollup": "dist/bin/rollup" } }, "sha512-e3TapAgYf9xjdLvKQCkQTnbTKd4a6jwlpQSJJFokHGaX2IVjoEqkIIhiQfqsi0cdwlOD+tQGuOd5AJkc5RngBw=="], + "rollup": ["rollup@4.52.5", "", { "dependencies": { "@types/estree": "1.0.8" }, "optionalDependencies": { "@rollup/rollup-android-arm-eabi": "4.52.5", "@rollup/rollup-android-arm64": "4.52.5", "@rollup/rollup-darwin-arm64": "4.52.5", "@rollup/rollup-darwin-x64": "4.52.5", "@rollup/rollup-freebsd-arm64": "4.52.5", "@rollup/rollup-freebsd-x64": "4.52.5", "@rollup/rollup-linux-arm-gnueabihf": "4.52.5", "@rollup/rollup-linux-arm-musleabihf": "4.52.5", "@rollup/rollup-linux-arm64-gnu": "4.52.5", "@rollup/rollup-linux-arm64-musl": "4.52.5", "@rollup/rollup-linux-loong64-gnu": "4.52.5", "@rollup/rollup-linux-ppc64-gnu": "4.52.5", "@rollup/rollup-linux-riscv64-gnu": "4.52.5", "@rollup/rollup-linux-riscv64-musl": "4.52.5", "@rollup/rollup-linux-s390x-gnu": "4.52.5", "@rollup/rollup-linux-x64-gnu": "4.52.5", "@rollup/rollup-linux-x64-musl": "4.52.5", "@rollup/rollup-openharmony-arm64": "4.52.5", "@rollup/rollup-win32-arm64-msvc": "4.52.5", "@rollup/rollup-win32-ia32-msvc": "4.52.5", "@rollup/rollup-win32-x64-gnu": "4.52.5", "@rollup/rollup-win32-x64-msvc": "4.52.5", "fsevents": "~2.3.2" }, "bin": { "rollup": "dist/bin/rollup" } }, "sha512-3GuObel8h7Kqdjt0gxkEzaifHTqLVW56Y/bjN7PSQtkKr0w3V/QYSdt6QWYtd7A1xUtYQigtdUfgj1RvWVtorw=="], "run-parallel": ["run-parallel@1.2.0", "", { "dependencies": { "queue-microtask": "^1.2.2" } }, "sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA=="], "sade": ["sade@1.8.1", "", { "dependencies": { "mri": "^1.1.0" } }, "sha512-xal3CZX1Xlo/k4ApwCFrHVACi9fBqJ7V+mwhBsuf/1IOKbBy098Fex+Wa/5QMubw09pSZ/u8EY8PWgevJsXp1A=="], - "semver": ["semver@7.7.2", "", { "bin": { "semver": "bin/semver.js" } }, "sha512-RF0Fw+rO5AMf9MAyaRXI4AV0Ulj5lMHqVxxdSgiVbixSCXoEmmX/jk0CuJw4+3SqroYO9VoUh+HcuJivvtJemA=="], + "semver": ["semver@7.7.3", "", { "bin": { "semver": "bin/semver.js" } }, "sha512-SdsKMrI9TdgjdweUSR9MweHA4EJ8YxHn8DFaDisvhVlUOe4BF1tLD7GAj0lIqWVl+dPb/rExr0Btby5loQm20Q=="], "shebang-command": ["shebang-command@2.0.0", "", { "dependencies": { "shebang-regex": "^3.0.0" } }, "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA=="], @@ -632,7 +634,7 @@ "siginfo": ["siginfo@2.0.0", "", {}, "sha512-ybx0WO1/8bSBLEWXZvEd7gMW3Sn3JFlW3TvX1nREbDLRNQNaeNN8WK0meBwPdAaOI7TtRRRJn/Es1zhrrCHu7g=="], - "source-map-js": ["source-map-js@1.2.0", "", {}, "sha512-itJW8lvSA0TXEphiRoawsCksnlf8SyvmFzIhltqAHluXd88pkCd+cXJVHTDwdCr0IzwptSm035IHQktUu1QUMg=="], + "source-map-js": ["source-map-js@1.2.1", "", {}, "sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA=="], "spdx-exceptions": ["spdx-exceptions@2.5.0", "", {}, "sha512-PiU42r+xO4UbUS1buo3LPJkjlO7430Xn5SVAhdpzzsPHsjbYVflnnFdATgabnLude+Cqu25p6N+g2lw/PFsa4w=="], @@ -644,12 +646,10 @@ "std-env": ["std-env@3.9.0", "", {}, "sha512-UGvjygr6F6tpH7o2qyqR6QYpwraIjKSdtzyBdyytFOHmPZY917kwdwLG0RbOjWOnKmnm3PeHjaoLLMie7kPLQw=="], - "strip-indent": ["strip-indent@4.0.0", "", { "dependencies": { "min-indent": "^1.0.1" } }, "sha512-mnVSV2l+Zv6BLpSD/8V87CW/y9EmmbYzGCIavsnsI6/nwn26DwffM/yztm30Z/I2DY9wdS3vXVCMnHDgZaVNoA=="], + "strip-indent": ["strip-indent@4.1.1", "", {}, "sha512-SlyRoSkdh1dYP0PzclLE7r0M9sgbFKKMFXpFRUMNuKhQSbC6VQIGzq3E0qsfvGJaUFJPGv6Ws1NZ/haTAjfbMA=="], "strip-json-comments": ["strip-json-comments@3.1.1", "", {}, "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig=="], - "strip-literal": ["strip-literal@3.0.0", "", { "dependencies": { "js-tokens": "^9.0.1" } }, "sha512-TcccoMhJOM3OebGhSBEmp3UZ2SfDMZUEBdRA/9ynfLi8yYajyWX3JiXArcJt4Umh4vISpspkQIY8ZZoCqjbviA=="], - "supports-color": ["supports-color@7.2.0", "", { "dependencies": { "has-flag": "^4.0.0" } }, "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw=="], "tapable": ["tapable@2.2.1", "", {}, "sha512-GNzQvQTOIP6RyTfE2Qxb8ZVlNmw0n88vp1szwWRimP02mnTsx3Wtn5qRdqY9w2XduFNUgvOwhNnQsjwCp+kqaQ=="], @@ -658,21 +658,21 @@ "tinyexec": ["tinyexec@1.0.1", "", {}, "sha512-5uC6DDlmeqiOwCPmK9jMSdOuZTh8bU39Ys6yidB+UTt5hfZUPGAypSgFRiEp+jbi9qH40BLDvy85jIU88wKSqw=="], - "tinyglobby": ["tinyglobby@0.2.14", "", { "dependencies": { "fdir": "^6.4.4", "picomatch": "^4.0.2" } }, "sha512-tX5e7OM1HnYr2+a2C/4V0htOcSQcoSTH9KgJnVvNm5zm/cyEWKJ7j7YutsH9CxMdtOkkLFy2AHrMci9IM8IPZQ=="], + "tinyglobby": ["tinyglobby@0.2.15", "", { "dependencies": { "fdir": "^6.5.0", "picomatch": "^4.0.3" } }, "sha512-j2Zq4NyQYG5XMST4cbs02Ak8iJUdxRM0XI5QyxXuZOzKOINmWurp3smXu3y5wDcJrptwpSjgXHzIQxR0omXljQ=="], - "tinypool": ["tinypool@1.1.1", "", {}, "sha512-Zba82s87IFq9A9XmjiX5uZA/ARWDrB03OHlq+Vw1fSdt0I+4/Kutwy8BP4Y/y/aORMo61FQ0vIb5j44vSo5Pkg=="], - - "tinyrainbow": ["tinyrainbow@2.0.0", "", {}, "sha512-op4nsTR47R6p0vMUUoYl/a+ljLFVtlfaXkLQmqfLR1qHma1h/ysYk4hEXZ880bf2CYgTskvTa/e196Vd5dDQXw=="], - - "tinyspy": ["tinyspy@4.0.3", "", {}, "sha512-t2T/WLB2WRgZ9EpE4jgPJ9w+i66UZfDc8wHh0xrwiRNN+UwH98GIJkTeZqX9rg0i0ptwzqW+uYeIF0T4F8LR7A=="], + "tinyrainbow": ["tinyrainbow@3.0.3", "", {}, "sha512-PSkbLUoxOFRzJYjjxHJt9xro7D+iilgMX/C9lawzVuYiIdcihh9DXmVibBe8lmcFrRi/VzlPjBxbN7rH24q8/Q=="], "to-regex-range": ["to-regex-range@5.0.1", "", { "dependencies": { "is-number": "^7.0.0" } }, "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ=="], + "to-valid-identifier": ["to-valid-identifier@1.0.0", "", { "dependencies": { "@sindresorhus/base62": "^1.0.0", "reserved-identifiers": "^1.0.0" } }, "sha512-41wJyvKep3yT2tyPqX/4blcfybknGB4D+oETKLs7Q76UiPqRpUJK3hr1nxelyYO0PHKVzJwlu0aCeEAsGI6rpw=="], + "tree-kill": ["tree-kill@1.2.2", "", { "bin": { "tree-kill": "cli.js" } }, "sha512-L0Orpi8qGpRG//Nd+H90vFB+3iHnue1zSSGmNOOCh1GLJ7rUKVwV2HvijphGQS2UmhUZewS9VgvxYIdgr+fG1A=="], "ts-api-utils": ["ts-api-utils@2.1.0", "", { "peerDependencies": { "typescript": ">=4.8.4" } }, "sha512-CUgTZL1irw8u29bzrOD/nH85jqyc74D6SshFgujOIA7osm2Rz7dYH77agkx7H4FBNxDq7Cjf+IjaX/8zwFW+ZQ=="], - "tsdown": ["tsdown@0.14.2", "", { "dependencies": { "ansis": "^4.1.0", "cac": "^6.7.14", "chokidar": "^4.0.3", "debug": "^4.4.1", "diff": "^8.0.2", "empathic": "^2.0.0", "hookable": "^5.5.3", "rolldown": "latest", "rolldown-plugin-dts": "^0.15.8", "semver": "^7.7.2", "tinyexec": "^1.0.1", "tinyglobby": "^0.2.14", "tree-kill": "^1.2.2", "unconfig": "^7.3.3" }, "peerDependencies": { "@arethetypeswrong/core": "^0.18.1", "publint": "^0.3.0", "typescript": "^5.0.0", "unplugin-lightningcss": "^0.4.0", "unplugin-unused": "^0.5.0" }, "optionalPeers": ["@arethetypeswrong/core", "publint", "typescript", "unplugin-lightningcss", "unplugin-unused"], "bin": { "tsdown": "dist/run.mjs" } }, "sha512-6ThtxVZoTlR5YJov5rYvH8N1+/S/rD/pGfehdCLGznGgbxz+73EASV1tsIIZkLw2n+SXcERqHhcB/OkyxdKv3A=="], + "ts-declaration-location": ["ts-declaration-location@1.0.7", "", { "dependencies": { "picomatch": "^4.0.2" }, "peerDependencies": { "typescript": ">=4.0.0" } }, "sha512-EDyGAwH1gO0Ausm9gV6T2nUvBgXT5kGoCMJPllOaooZ+4VvJiKBdZE7wK18N1deEowhcUptS+5GXZK8U/fvpwA=="], + + "tsdown": ["tsdown@0.15.12", "", { "dependencies": { "ansis": "^4.2.0", "cac": "^6.7.14", "chokidar": "^4.0.3", "debug": "^4.4.3", "diff": "^8.0.2", "empathic": "^2.0.0", "hookable": "^5.5.3", "rolldown": "1.0.0-beta.45", "rolldown-plugin-dts": "^0.17.2", "semver": "^7.7.3", "tinyexec": "^1.0.1", "tinyglobby": "^0.2.15", "tree-kill": "^1.2.2", "unconfig": "^7.3.3" }, "peerDependencies": { "@arethetypeswrong/core": "^0.18.1", "publint": "^0.3.0", "typescript": "^5.0.0", "unplugin-lightningcss": "^0.4.0", "unplugin-unused": "^0.5.0", "unrun": "^0.2.1" }, "optionalPeers": ["@arethetypeswrong/core", "publint", "typescript", "unplugin-lightningcss", "unplugin-unused", "unrun"], "bin": { "tsdown": "dist/run.mjs" } }, "sha512-c8VLlQm8/lFrOAg5VMVeN4NAbejZyVQkzd+ErjuaQgJFI/9MhR9ivr0H/CM7UlOF1+ELlF6YaI7sU/4itgGQ8w=="], "tslib": ["tslib@2.7.0", "", {}, "sha512-gLXCKdN1/j47AiHiOkJN69hJmcbGTHI0ImLmbYLHykhgeN0jVGola9yVjFgzCUklsZQMW55o+dW7IXv3RCXDzA=="], @@ -680,9 +680,9 @@ "type-fest": ["type-fest@4.41.0", "", {}, "sha512-TeTSQ6H5YHvpqVwBRcnLDCBnDOHWYu7IvGbHT6N8AOymcr9PJGjc1GTtiWZTYg0NCgYwvnYWEkVChQAr9bjfwA=="], - "typescript": ["typescript@5.9.2", "", { "bin": { "tsc": "bin/tsc", "tsserver": "bin/tsserver" } }, "sha512-CWBzXQrc/qOkhidw1OzBTQuYRbfyxDXJMVJ1XNwUHGROVmuaeiEm3OslpZ1RV96d7SKKjZKrSJu3+t/xlw3R9A=="], + "typescript": ["typescript@5.9.3", "", { "bin": { "tsc": "bin/tsc", "tsserver": "bin/tsserver" } }, "sha512-jl1vZzPDinLr9eUt3J/t7V6FgNEw9QjvBPdysz9KfQDD41fQrC2Y4vKQdiaUpFT4bXlb1RHhLpp8wtm6M5TgSw=="], - "typescript-eslint": ["typescript-eslint@8.32.1", "", { "dependencies": { "@typescript-eslint/eslint-plugin": "8.32.1", "@typescript-eslint/parser": "8.32.1", "@typescript-eslint/utils": "8.32.1" }, "peerDependencies": { "eslint": "^8.57.0 || ^9.0.0", "typescript": ">=4.8.4 <5.9.0" } }, "sha512-D7el+eaDHAmXvrZBy1zpzSNIRqnCOrkwTgZxTu3MUqRWk8k0q9m9Ho4+vPf7iHtgUfrK/o8IZaEApsxPlHTFCg=="], + "typescript-eslint": ["typescript-eslint@8.46.2", "", { "dependencies": { "@typescript-eslint/eslint-plugin": "8.46.2", "@typescript-eslint/parser": "8.46.2", "@typescript-eslint/typescript-estree": "8.46.2", "@typescript-eslint/utils": "8.46.2" }, "peerDependencies": { "eslint": "^8.57.0 || ^9.0.0", "typescript": ">=4.8.4 <6.0.0" } }, "sha512-vbw8bOmiuYNdzzV3lsiWv6sRwjyuKJMQqWulBOU7M0RrxedXledX8G8kBbQeiOYDnTfiXz0Y4081E1QMNB6iQg=="], "unconfig": ["unconfig@7.3.3", "", { "dependencies": { "@quansync/fs": "^0.1.5", "defu": "^6.1.4", "jiti": "^2.5.1", "quansync": "^0.2.11" } }, "sha512-QCkQoOnJF8L107gxfHL0uavn7WD9b3dpBcFX6HtfQYmjw2YzWxGuFQ0N0J6tE9oguCBJn9KOvfqYDCMPHIZrBA=="], @@ -690,9 +690,9 @@ "unplugin": ["unplugin@2.3.10", "", { "dependencies": { "@jridgewell/remapping": "^2.3.5", "acorn": "^8.15.0", "picomatch": "^4.0.3", "webpack-virtual-modules": "^0.6.2" } }, "sha512-6NCPkv1ClwH+/BGE9QeoTIl09nuiAt0gS28nn1PvYXsGKRwM2TCbFA2QiilmehPDTXIe684k4rZI1yl3A1PCUw=="], - "unplugin-unused": ["unplugin-unused@0.5.2", "", { "dependencies": { "js-tokens": "^9.0.1", "picocolors": "^1.1.1", "pkg-types": "^2.2.0", "unplugin": "^2.3.6" } }, "sha512-fn0DZrp96+NYo4U5UbLp1ZmZpBk/Z1RhjG2LvXfQxxw82dzciBxmx04ZgATxLZDD4HcGhdWlLIm2Gz1SVIBhDQ=="], + "unplugin-unused": ["unplugin-unused@0.5.4", "", { "dependencies": { "js-tokens": "^9.0.1", "pkg-types": "^2.3.0", "unplugin": "^2.3.10" } }, "sha512-R11StgC5j43CECdjHFbc6Ep4MgM97xuI7rku/nCw7OpIEw9sG4btxvR7Ld4RViwAF+eEQjSebesE+jTJTFFWmQ=="], - "update-browserslist-db": ["update-browserslist-db@1.1.3", "", { "dependencies": { "escalade": "^3.2.0", "picocolors": "^1.1.1" }, "peerDependencies": { "browserslist": ">= 4.21.0" }, "bin": { "update-browserslist-db": "cli.js" } }, "sha512-UxhIZQ+QInVdunkDAaiazvvT/+fXL5Osr0JZlJulepYu6Jd7qJtDZjlur0emRlT71EN3ScPoE7gvsuIKKNavKw=="], + "update-browserslist-db": ["update-browserslist-db@1.1.4", "", { "dependencies": { "escalade": "^3.2.0", "picocolors": "^1.1.1" }, "peerDependencies": { "browserslist": ">= 4.21.0" }, "bin": { "update-browserslist-db": "cli.js" } }, "sha512-q0SPT4xyU84saUX+tomz1WLkxUbuaJnR1xWt17M7fJtEJigJeWUNGUqrauFXsHnqev9y9JTRGwk13tFBuKby4A=="], "uri-js": ["uri-js@4.4.1", "", { "dependencies": { "punycode": "^2.1.0" } }, "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg=="], @@ -700,11 +700,9 @@ "valibot": ["valibot@1.1.0", "", { "peerDependencies": { "typescript": ">=5" }, "optionalPeers": ["typescript"] }, "sha512-Nk8lX30Qhu+9txPYTwM0cFlWLdPFsFr6LblzqIySfbZph9+BFsAHsNvHOymEviUepeIW6KFHzpX8TKhbptBXXw=="], - "vite": ["vite@5.4.3", "", { "dependencies": { "esbuild": "^0.21.3", "postcss": "^8.4.43", "rollup": "^4.20.0" }, "optionalDependencies": { "fsevents": "~2.3.3" }, "peerDependencies": { "@types/node": "^18.0.0 || >=20.0.0", "less": "*", "lightningcss": "^1.21.0", "sass": "*", "sass-embedded": "*", "stylus": "*", "sugarss": "*", "terser": "^5.4.0" }, "optionalPeers": ["@types/node", "less", "lightningcss", "sass", "sass-embedded", "stylus", "sugarss", "terser"], "bin": { "vite": "bin/vite.js" } }, "sha512-IH+nl64eq9lJjFqU+/yrRnrHPVTlgy42/+IzbOdaFDVlyLgI/wDlf+FCobXLX1cT0X5+7LMyH1mIy2xJdLfo8Q=="], + "vite": ["vite@7.1.12", "", { "dependencies": { "esbuild": "^0.25.0", "fdir": "^6.5.0", "picomatch": "^4.0.3", "postcss": "^8.5.6", "rollup": "^4.43.0", "tinyglobby": "^0.2.15" }, "optionalDependencies": { "fsevents": "~2.3.3" }, "peerDependencies": { "@types/node": "^20.19.0 || >=22.12.0", "jiti": ">=1.21.0", "less": "^4.0.0", "lightningcss": "^1.21.0", "sass": "^1.70.0", "sass-embedded": "^1.70.0", "stylus": ">=0.54.8", "sugarss": "^5.0.0", "terser": "^5.16.0", "tsx": "^4.8.1", "yaml": "^2.4.2" }, "optionalPeers": ["@types/node", "jiti", "less", "lightningcss", "sass", "sass-embedded", "stylus", "sugarss", "terser", "tsx", "yaml"], "bin": { "vite": "bin/vite.js" } }, "sha512-ZWyE8YXEXqJrrSLvYgrRP7p62OziLW7xI5HYGWFzOvupfAlrLvURSzv/FyGyy0eidogEM3ujU+kUG1zuHgb6Ug=="], - "vite-node": ["vite-node@3.2.4", "", { "dependencies": { "cac": "^6.7.14", "debug": "^4.4.1", "es-module-lexer": "^1.7.0", "pathe": "^2.0.3", "vite": "^5.0.0 || ^6.0.0 || ^7.0.0-0" }, "bin": { "vite-node": "vite-node.mjs" } }, "sha512-EbKSKh+bh1E1IFxeO0pg1n4dvoOTt0UDiXMd/qn++r98+jPO1xtJilvXldeuQ8giIB5IkpjCgMleHMNEsGH6pg=="], - - "vitest": ["vitest@3.2.4", "", { "dependencies": { "@types/chai": "^5.2.2", "@vitest/expect": "3.2.4", "@vitest/mocker": "3.2.4", "@vitest/pretty-format": "^3.2.4", "@vitest/runner": "3.2.4", "@vitest/snapshot": "3.2.4", "@vitest/spy": "3.2.4", "@vitest/utils": "3.2.4", "chai": "^5.2.0", "debug": "^4.4.1", "expect-type": "^1.2.1", "magic-string": "^0.30.17", "pathe": "^2.0.3", "picomatch": "^4.0.2", "std-env": "^3.9.0", "tinybench": "^2.9.0", "tinyexec": "^0.3.2", "tinyglobby": "^0.2.14", "tinypool": "^1.1.1", "tinyrainbow": "^2.0.0", "vite": "^5.0.0 || ^6.0.0 || ^7.0.0-0", "vite-node": "3.2.4", "why-is-node-running": "^2.3.0" }, "peerDependencies": { "@edge-runtime/vm": "*", "@types/debug": "^4.1.12", "@types/node": "^18.0.0 || ^20.0.0 || >=22.0.0", "@vitest/browser": "3.2.4", "@vitest/ui": "3.2.4", "happy-dom": "*", "jsdom": "*" }, "optionalPeers": ["@edge-runtime/vm", "@types/debug", "@types/node", "@vitest/browser", "@vitest/ui", "happy-dom", "jsdom"], "bin": { "vitest": "vitest.mjs" } }, "sha512-LUCP5ev3GURDysTWiP47wRRUpLKMOfPh+yKTx3kVIEiu5KOMeqzpnYNsKyOoVrULivR8tLcks4+lga33Whn90A=="], + "vitest": ["vitest@4.0.4", "", { "dependencies": { "@vitest/expect": "4.0.4", "@vitest/mocker": "4.0.4", "@vitest/pretty-format": "4.0.4", "@vitest/runner": "4.0.4", "@vitest/snapshot": "4.0.4", "@vitest/spy": "4.0.4", "@vitest/utils": "4.0.4", "debug": "^4.4.3", "es-module-lexer": "^1.7.0", "expect-type": "^1.2.2", "magic-string": "^0.30.19", "pathe": "^2.0.3", "picomatch": "^4.0.3", "std-env": "^3.9.0", "tinybench": "^2.9.0", "tinyexec": "^0.3.2", "tinyglobby": "^0.2.15", "tinyrainbow": "^3.0.3", "vite": "^6.0.0 || ^7.0.0", "why-is-node-running": "^2.3.0" }, "peerDependencies": { "@edge-runtime/vm": "*", "@types/debug": "^4.1.12", "@types/node": "^20.0.0 || ^22.0.0 || >=24.0.0", "@vitest/browser-playwright": "4.0.4", "@vitest/browser-preview": "4.0.4", "@vitest/browser-webdriverio": "4.0.4", "@vitest/ui": "4.0.4", "happy-dom": "*", "jsdom": "*" }, "optionalPeers": ["@edge-runtime/vm", "@types/debug", "@types/node", "@vitest/browser-playwright", "@vitest/browser-preview", "@vitest/browser-webdriverio", "@vitest/ui", "happy-dom", "jsdom"], "bin": { "vitest": "vitest.mjs" } }, "sha512-hV31h0/bGbtmDQc0KqaxsTO1v4ZQeF8ojDFuy4sZhFadwAqqvJA0LDw68QUocctI5EDpFMql/jVWKuPYHIf2Ew=="], "vue-eslint-parser": ["vue-eslint-parser@9.4.3", "", { "dependencies": { "debug": "^4.3.4", "eslint-scope": "^7.1.1", "eslint-visitor-keys": "^3.3.0", "espree": "^9.3.1", "esquery": "^1.4.0", "lodash": "^4.17.21", "semver": "^7.3.6" }, "peerDependencies": { "eslint": ">=6.0.0" } }, "sha512-2rYRLWlIpaiN8xbPiDyXZXRgLGOtWxERV7ND5fFAv5qo1D2N9Fu9MNajBNc6o13lZ+24DAWCkQCvj4klgmcITg=="], @@ -720,23 +718,37 @@ "yocto-queue": ["yocto-queue@0.1.0", "", {}, "sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q=="], + "@es-joy/jsdoccomment/@types/estree": ["@types/estree@1.0.8", "", {}, "sha512-dWHzHa2WqEXI/O1E9OjrocMTKJl2mSrEolh1Iomrv6U+JuNwaHXsXx9bLu5gG7BUWFIN0skIQJQ/L1rIex4X6w=="], + "@eslint-community/eslint-utils/eslint-visitor-keys": ["eslint-visitor-keys@3.4.3", "", {}, "sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag=="], + "@eslint/config-array/debug": ["debug@4.4.3", "", { "dependencies": { "ms": "^2.1.3" } }, "sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA=="], + + "@eslint/eslintrc/espree": ["espree@10.3.0", "", { "dependencies": { "acorn": "^8.14.0", "acorn-jsx": "^5.3.2", "eslint-visitor-keys": "^4.2.0" } }, "sha512-0QYC8b24HWY8zjRnDTL6RiHfDbAWn63qb4LMj1Z4b076A4une81+z03Kg7l7mn/48PUTqoLptSXez8oknU8Clg=="], + "@eslint/eslintrc/globals": ["globals@14.0.0", "", {}, "sha512-oahGvuMGQlPw/ivIYBjVSrWAfWLBeku5tpPE2fOPLi+WHffIWbuh2tCjhyQhTBPMf5E9jDEH4FOmTYgYwbKwtQ=="], "@humanfs/node/@humanwhocodes/retry": ["@humanwhocodes/retry@0.3.0", "", {}, "sha512-d2CGZR2o7fS6sWB7DG/3a95bGKQyHMACZ5aW8qGkkqQpUoZV6C0X7Pc7l4ZNMZkfNBf4VWNe9E1jRsf0G146Ew=="], + "@jridgewell/gen-mapping/@jridgewell/sourcemap-codec": ["@jridgewell/sourcemap-codec@1.5.0", "", {}, "sha512-gv3ZRaISU3fjPAgNsriBRqGWQL6quFx04YMPW/zD8XMLsU32mhCCbfbO6KZFLjvYpCZ8zyDEgqsgf+PwPaM7GQ=="], + "@jridgewell/remapping/@jridgewell/gen-mapping": ["@jridgewell/gen-mapping@0.3.8", "", { "dependencies": { "@jridgewell/set-array": "^1.2.1", "@jridgewell/sourcemap-codec": "^1.4.10", "@jridgewell/trace-mapping": "^0.3.24" } }, "sha512-imAbBGkb+ebQyxKgzv5Hu2nmROxoDOXHh80evxdoXNOrvAnVx7zimzc1Oo5h9RlfV4vPXaE2iM5pOFbvOCClWA=="], "@jridgewell/remapping/@jridgewell/trace-mapping": ["@jridgewell/trace-mapping@0.3.25", "", { "dependencies": { "@jridgewell/resolve-uri": "^3.1.0", "@jridgewell/sourcemap-codec": "^1.4.14" } }, "sha512-vNk6aEwybGtawWmy/PzwnGDOjCkLWSD2wqvjGGAgOAwCGWySYXfYoxt00IJkTF+8Lb57DwOb3Aa0o9CApepiYQ=="], - "@typescript-eslint/eslint-plugin/@eslint-community/regexpp": ["@eslint-community/regexpp@4.11.0", "", {}, "sha512-G/M/tIiMrTAxEWRfLfQJMmGNX28IxBg4PBz8XqQhqUHLFI6TL2htpIB1iQCj144V5ee/JaKyT9/WZ0MGZWfA7A=="], + "@jridgewell/trace-mapping/@jridgewell/sourcemap-codec": ["@jridgewell/sourcemap-codec@1.5.0", "", {}, "sha512-gv3ZRaISU3fjPAgNsriBRqGWQL6quFx04YMPW/zD8XMLsU32mhCCbfbO6KZFLjvYpCZ8zyDEgqsgf+PwPaM7GQ=="], "@typescript-eslint/eslint-plugin/ignore": ["ignore@7.0.4", "", {}, "sha512-gJzzk+PQNznz8ysRrC0aOkBNVRBDtE1n53IqyqEf3PXrYwomFs5q4pGMizBMJF+ykh03insJ27hB8gSrD2Hn8A=="], - "@typescript-eslint/typescript-estree/minimatch": ["minimatch@9.0.5", "", { "dependencies": { "brace-expansion": "^2.0.1" } }, "sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow=="], + "@typescript-eslint/parser/debug": ["debug@4.4.3", "", { "dependencies": { "ms": "^2.1.3" } }, "sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA=="], + + "@typescript-eslint/project-service/debug": ["debug@4.4.3", "", { "dependencies": { "ms": "^2.1.3" } }, "sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA=="], + + "@typescript-eslint/type-utils/debug": ["debug@4.4.3", "", { "dependencies": { "ms": "^2.1.3" } }, "sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA=="], - "chai/loupe": ["loupe@3.1.3", "", {}, "sha512-kkIp7XSkP78ZxJEsSxW3712C6teJVoeHHwgo9zJ380de7IYyJ2ISlxojcH2pC5OFLewESmnRi/+XCDIEEVyoug=="], + "@typescript-eslint/typescript-estree/debug": ["debug@4.4.3", "", { "dependencies": { "ms": "^2.1.3" } }, "sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA=="], + + "@typescript-eslint/typescript-estree/minimatch": ["minimatch@9.0.5", "", { "dependencies": { "brace-expansion": "^2.0.1" } }, "sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow=="], "clean-regexp/escape-string-regexp": ["escape-string-regexp@1.0.5", "", {}, "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg=="], @@ -746,13 +758,11 @@ "eslint-plugin-es-x/@eslint-community/regexpp": ["@eslint-community/regexpp@4.11.0", "", {}, "sha512-G/M/tIiMrTAxEWRfLfQJMmGNX28IxBg4PBz8XqQhqUHLFI6TL2htpIB1iQCj144V5ee/JaKyT9/WZ0MGZWfA7A=="], - "eslint-plugin-n/minimatch": ["minimatch@9.0.5", "", { "dependencies": { "brace-expansion": "^2.0.1" } }, "sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow=="], + "eslint-plugin-jsdoc/debug": ["debug@4.4.3", "", { "dependencies": { "ms": "^2.1.3" } }, "sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA=="], "eslint-plugin-promise/@eslint-community/eslint-utils": ["@eslint-community/eslint-utils@4.4.0", "", { "dependencies": { "eslint-visitor-keys": "^3.3.0" }, "peerDependencies": { "eslint": "^6.0.0 || ^7.0.0 || >=8.0.0" } }, "sha512-1/sA4dwrzBAyeUoQ6oxahHKmrZvsnLCg4RfxW3ZFGGmQkSNQPFNLV9CUEFQP1x9EYXHTo5p6xdhZM1Ne9p/AfA=="], - "eslint-plugin-unicorn/@eslint/plugin-kit": ["@eslint/plugin-kit@0.2.8", "", { "dependencies": { "@eslint/core": "^0.13.0", "levn": "^0.4.1" } }, "sha512-ZAoA40rNMPwSm+AeHpCq8STiNAwzWLJuP8Xv4CHIc9wv/PSuExjMrmjfYNj682vW0OOiZ1HKxzvjQr9XZIisQA=="], - - "eslint-plugin-unicorn/globals": ["globals@16.2.0", "", {}, "sha512-O+7l9tPdHCU320IigZZPj5zmRCFG9xHmx9cU8FqU2Rp+JN714seHV+2S9+JslCpY4gJwU2vOGox0wzgae/MCEg=="], + "eslint-plugin-unicorn/globals": ["globals@16.4.0", "", {}, "sha512-ob/2LcVVaVGCYN+r14cnwnoDPUufjiYgSqRhiFD0Q1iI4Odora5RE8Iv1D24hAz5oMophRGkGz+yuvQmmUMnMw=="], "estree-walker/@types/estree": ["@types/estree@1.0.5", "", {}, "sha512-/kYRxGDLWzHOB7q+wtSUQlFrtcdUccpfy+X+9iMBpHK8QLLhx2wIPYuS5DYtR9Wa/YlZAbIovy7qVdB1Aq6Lyw=="], @@ -760,17 +770,17 @@ "micromatch/picomatch": ["picomatch@2.3.1", "", {}, "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA=="], - "postcss/picocolors": ["picocolors@1.1.0", "", {}, "sha512-TQ92mBOW0l3LeMeyLV6mzy/kWr8lkd/hp3mTg7wYK7zJhuBStmGMBG0BdeDZS/dZx1IukaX6Bk11zcln25o1Aw=="], + "rolldown-plugin-dts/debug": ["debug@4.4.3", "", { "dependencies": { "ms": "^2.1.3" } }, "sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA=="], - "regjsparser/jsesc": ["jsesc@3.0.2", "", { "bin": { "jsesc": "bin/jsesc" } }, "sha512-xKqzzWXDttJuOcawBt4KnKHHIf5oQ/Cxax+0PWFG+DFDgHNAdi+TXECADI+RYiFUMmx8792xsMbbgXj4CwnP4g=="], + "rolldown-plugin-dts/get-tsconfig": ["get-tsconfig@4.13.0", "", { "dependencies": { "resolve-pkg-maps": "^1.0.0" } }, "sha512-1VKTZJCwBrvbd+Wn3AOgQP/2Av+TfTCOlE4AcRJE72W1ksZXbAx8PPBR9RzgTeSPzlPMHrbANMH3LbltH73wxQ=="], - "rollup/@types/estree": ["@types/estree@1.0.5", "", {}, "sha512-/kYRxGDLWzHOB7q+wtSUQlFrtcdUccpfy+X+9iMBpHK8QLLhx2wIPYuS5DYtR9Wa/YlZAbIovy7qVdB1Aq6Lyw=="], + "rollup/@types/estree": ["@types/estree@1.0.8", "", {}, "sha512-dWHzHa2WqEXI/O1E9OjrocMTKJl2mSrEolh1Iomrv6U+JuNwaHXsXx9bLu5gG7BUWFIN0skIQJQ/L1rIex4X6w=="], - "unconfig/jiti": ["jiti@2.5.1", "", { "bin": { "jiti": "lib/jiti-cli.mjs" } }, "sha512-twQoecYPiVA5K/h6SxtORw/Bs3ar+mLUtoPSc7iMXzQzK8d7eJ/R09wmTwAjiamETn1cXYPGfNnu7DMoHgu12w=="], + "tsdown/debug": ["debug@4.4.3", "", { "dependencies": { "ms": "^2.1.3" } }, "sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA=="], - "unplugin/acorn": ["acorn@8.15.0", "", { "bin": { "acorn": "bin/acorn" } }, "sha512-NZyJarBfL7nWwIq+FDL6Zp/yHEhePMNnnJ0y3qfieCrmNvYct8uvtiV41UvlSe6apAfk0fY1FbWx+NwfmpvtTg=="], + "unconfig/jiti": ["jiti@2.5.1", "", { "bin": { "jiti": "lib/jiti-cli.mjs" } }, "sha512-twQoecYPiVA5K/h6SxtORw/Bs3ar+mLUtoPSc7iMXzQzK8d7eJ/R09wmTwAjiamETn1cXYPGfNnu7DMoHgu12w=="], - "unplugin/picomatch": ["picomatch@4.0.3", "", {}, "sha512-5gTmgEY/sqK6gFXLIsQNH19lWb4ebPDLA4SdLP7dsWkIXHWlG66oPuVvXSGFPppYZz8ZDZq0dYYrbHfBCVUb1Q=="], + "vitest/debug": ["debug@4.4.3", "", { "dependencies": { "ms": "^2.1.3" } }, "sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA=="], "vitest/tinyexec": ["tinyexec@0.3.2", "", {}, "sha512-KQQR9yN7R5+OSwaK0XQoj22pwHoTlgYqmUscPYoknOoWCWfj/5/ABTMRi69FrKU5ffPVh5QcFikpWJI/P1ocHA=="], @@ -784,16 +794,20 @@ "vue-eslint-parser/semver": ["semver@7.6.3", "", { "bin": { "semver": "bin/semver.js" } }, "sha512-oVekP1cKtI+CTDvHWYFUcMtsK/00wmAEfyqKfNdARm8u1wNVhSgaX7A8d4UuIlUI5e84iEwOhs7ZPYRmzU9U6A=="], + "@eslint/eslintrc/espree/acorn": ["acorn@8.14.1", "", { "bin": { "acorn": "bin/acorn" } }, "sha512-OvQ/2pUDKmgfCg++xsTX1wGxfTaszcHVcTctW4UJB4hibJx2HXxxO5UmVgyjMa+ZDsiaf5wWLXYpRWMmBI0QHg=="], + + "@eslint/eslintrc/espree/eslint-visitor-keys": ["eslint-visitor-keys@4.2.0", "", {}, "sha512-UyLnSehNt62FFhSwjZlHmeokpRK59rcz29j+F1/aDgbkbRTk7wIc9XzdoasMUbRNKDM0qQt/+BJ4BrpFeABemw=="], + + "@jridgewell/remapping/@jridgewell/gen-mapping/@jridgewell/sourcemap-codec": ["@jridgewell/sourcemap-codec@1.5.0", "", {}, "sha512-gv3ZRaISU3fjPAgNsriBRqGWQL6quFx04YMPW/zD8XMLsU32mhCCbfbO6KZFLjvYpCZ8zyDEgqsgf+PwPaM7GQ=="], + + "@jridgewell/remapping/@jridgewell/trace-mapping/@jridgewell/sourcemap-codec": ["@jridgewell/sourcemap-codec@1.5.0", "", {}, "sha512-gv3ZRaISU3fjPAgNsriBRqGWQL6quFx04YMPW/zD8XMLsU32mhCCbfbO6KZFLjvYpCZ8zyDEgqsgf+PwPaM7GQ=="], + "@typescript-eslint/typescript-estree/minimatch/brace-expansion": ["brace-expansion@2.0.1", "", { "dependencies": { "balanced-match": "^1.0.0" } }, "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA=="], "eslint-plugin-es-x/@eslint-community/eslint-utils/eslint-visitor-keys": ["eslint-visitor-keys@3.4.3", "", {}, "sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag=="], - "eslint-plugin-n/minimatch/brace-expansion": ["brace-expansion@2.0.1", "", { "dependencies": { "balanced-match": "^1.0.0" } }, "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA=="], - "eslint-plugin-promise/@eslint-community/eslint-utils/eslint-visitor-keys": ["eslint-visitor-keys@3.4.3", "", {}, "sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag=="], - "eslint-plugin-unicorn/@eslint/plugin-kit/@eslint/core": ["@eslint/core@0.13.0", "", { "dependencies": { "@types/json-schema": "^7.0.15" } }, "sha512-yfkgDw1KR66rkT5A8ci4irzDysN7FRpq3ttJolR88OqQikAWqwA8j5VZyas+vjyBNFIJ7MfybJ9plMILI2UrCw=="], - "vue-eslint-parser/debug/ms": ["ms@2.1.2", "", {}, "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w=="], "vue-eslint-parser/espree/acorn": ["acorn@8.12.1", "", { "bin": { "acorn": "bin/acorn" } }, "sha512-tcpGyI9zbizT9JbV6oYE477V6mTlXvvi0T0G3SNIYE2apm/G5huBa1+K89VGeovbg+jycCrfhl3ADxErOuO6Jg=="], diff --git a/dist/dev.cjs b/dist/dev.cjs index 5d9cd99..208eaac 100644 --- a/dist/dev.cjs +++ b/dist/dev.cjs @@ -1,5 +1,6 @@ const require_record = require('./record-D97pjgdq.cjs'); -const neoevents = require_record.__toESM(require("neoevents")); +let neoevents = require("neoevents"); +neoevents = require_record.__toESM(neoevents); //#region src/driver.ts var HyperAPIDriver = class extends neoevents.NeoEventTarget { diff --git a/dist/dev.d.cts b/dist/dev.d.cts index 8d6592b..b4c30d2 100644 --- a/dist/dev.d.cts +++ b/dist/dev.d.cts @@ -1,2 +1,2 @@ -import { BaseRecord, EmptyObject, HyperAPIDriver, HyperAPIErrorData, HyperAPIMethod, HyperAPIModule, HyperAPIModuleResponse, HyperAPIRequest, HyperAPIRequestArgs, HyperAPIResponse, isHyperApiMethod, isRecord } from "./driver-B9cVUC-_.cjs"; +import { c as HyperAPIErrorData, d as BaseRecord, f as EmptyObject, h as isHyperApiMethod, i as HyperAPIModuleResponse, l as HyperAPIRequest, m as HyperAPIMethod, n as HyperAPIResponse, p as isRecord, r as HyperAPIModule, t as HyperAPIDriver, u as HyperAPIRequestArgs } from "./driver-DO8IdV_Q.cjs"; export { type BaseRecord, type EmptyObject, HyperAPIDriver, type HyperAPIErrorData, type HyperAPIMethod, type HyperAPIModule, type HyperAPIModuleResponse, type HyperAPIRequest, type HyperAPIRequestArgs, type HyperAPIResponse, isHyperApiMethod, isRecord }; \ No newline at end of file diff --git a/dist/dev.d.ts b/dist/dev.d.ts index ab8cf9c..429610f 100644 --- a/dist/dev.d.ts +++ b/dist/dev.d.ts @@ -1,2 +1,2 @@ -import { BaseRecord, EmptyObject, HyperAPIDriver, HyperAPIErrorData, HyperAPIMethod, HyperAPIModule, HyperAPIModuleResponse, HyperAPIRequest, HyperAPIRequestArgs, HyperAPIResponse, isHyperApiMethod, isRecord } from "./driver--QMVe1BB.js"; +import { c as HyperAPIErrorData, d as BaseRecord, f as EmptyObject, h as isHyperApiMethod, i as HyperAPIModuleResponse, l as HyperAPIRequest, m as HyperAPIMethod, n as HyperAPIResponse, p as isRecord, r as HyperAPIModule, t as HyperAPIDriver, u as HyperAPIRequestArgs } from "./driver-D8sen_tB.js"; export { type BaseRecord, type EmptyObject, HyperAPIDriver, type HyperAPIErrorData, type HyperAPIMethod, type HyperAPIModule, type HyperAPIModuleResponse, type HyperAPIRequest, type HyperAPIRequestArgs, type HyperAPIResponse, isHyperApiMethod, isRecord }; \ No newline at end of file diff --git a/dist/dev.js b/dist/dev.js index ab7ac6b..5e97483 100644 --- a/dist/dev.js +++ b/dist/dev.js @@ -1,4 +1,4 @@ -import { isRecord } from "./record-DFObD9mD.js"; +import { n as isRecord } from "./record-BeJ2ZKAR.js"; import { NeoEvent, NeoEventTarget } from "neoevents"; //#region src/driver.ts diff --git a/dist/driver--QMVe1BB.d.ts b/dist/driver-D8sen_tB.d.ts similarity index 87% rename from dist/driver--QMVe1BB.d.ts rename to dist/driver-D8sen_tB.d.ts index 378cb3f..dbedd29 100644 --- a/dist/driver--QMVe1BB.d.ts +++ b/dist/driver-D8sen_tB.d.ts @@ -19,12 +19,6 @@ type EmptyObject = Record; * @returns - */ declare function isRecord(value: unknown): value is BaseRecord; -/** -* Checks if there are common keys in both object. -* @param value1 - -* @param value2 - -* @returns - -*/ //#endregion //#region src/request.d.ts type HyperAPIRequestArgs = BaseRecord; @@ -83,11 +77,6 @@ declare class HyperAPIModule, ReqExtra e //#endregion //#region src/response.d.ts type HyperAPIResponse = HyperAPIModuleResponse | HyperAPIError; -/** -* Checks if the given value is a HyperAPIResponse. -* @param response - The value to check. -* @returns True if the value is a HyperAPIResponse, false otherwise. -*/ //#endregion //#region src/driver.d.ts declare class HyperAPIDriver extends NeoEventTarget<{ @@ -99,4 +88,4 @@ declare class HyperAPIDriver extend protected emitRequest(request: R): Promise; } //#endregion -export { BaseRecord, EmptyObject, Extend, HyperAPIDriver, HyperAPIError, HyperAPIErrorData, HyperAPIMethod, HyperAPIModule, HyperAPIModuleResponse, HyperAPIRequest, HyperAPIRequestArgs, HyperAPIResponse, Join, isHyperApiMethod, isRecord }; \ No newline at end of file +export { Extend as a, HyperAPIErrorData as c, BaseRecord as d, EmptyObject as f, isHyperApiMethod as h, HyperAPIModuleResponse as i, HyperAPIRequest as l, HyperAPIMethod as m, HyperAPIResponse as n, Join as o, isRecord as p, HyperAPIModule as r, HyperAPIError as s, HyperAPIDriver as t, HyperAPIRequestArgs as u }; \ No newline at end of file diff --git a/dist/driver-B9cVUC-_.d.cts b/dist/driver-DO8IdV_Q.d.cts similarity index 87% rename from dist/driver-B9cVUC-_.d.cts rename to dist/driver-DO8IdV_Q.d.cts index 378cb3f..dbedd29 100644 --- a/dist/driver-B9cVUC-_.d.cts +++ b/dist/driver-DO8IdV_Q.d.cts @@ -19,12 +19,6 @@ type EmptyObject = Record; * @returns - */ declare function isRecord(value: unknown): value is BaseRecord; -/** -* Checks if there are common keys in both object. -* @param value1 - -* @param value2 - -* @returns - -*/ //#endregion //#region src/request.d.ts type HyperAPIRequestArgs = BaseRecord; @@ -83,11 +77,6 @@ declare class HyperAPIModule, ReqExtra e //#endregion //#region src/response.d.ts type HyperAPIResponse = HyperAPIModuleResponse | HyperAPIError; -/** -* Checks if the given value is a HyperAPIResponse. -* @param response - The value to check. -* @returns True if the value is a HyperAPIResponse, false otherwise. -*/ //#endregion //#region src/driver.d.ts declare class HyperAPIDriver extends NeoEventTarget<{ @@ -99,4 +88,4 @@ declare class HyperAPIDriver extend protected emitRequest(request: R): Promise; } //#endregion -export { BaseRecord, EmptyObject, Extend, HyperAPIDriver, HyperAPIError, HyperAPIErrorData, HyperAPIMethod, HyperAPIModule, HyperAPIModuleResponse, HyperAPIRequest, HyperAPIRequestArgs, HyperAPIResponse, Join, isHyperApiMethod, isRecord }; \ No newline at end of file +export { Extend as a, HyperAPIErrorData as c, BaseRecord as d, EmptyObject as f, isHyperApiMethod as h, HyperAPIModuleResponse as i, HyperAPIRequest as l, HyperAPIMethod as m, HyperAPIResponse as n, Join as o, isRecord as p, HyperAPIModule as r, HyperAPIError as s, HyperAPIDriver as t, HyperAPIRequestArgs as u }; \ No newline at end of file diff --git a/dist/main.cjs b/dist/main.cjs index 6657bc7..a984f5c 100644 --- a/dist/main.cjs +++ b/dist/main.cjs @@ -1,7 +1,10 @@ const require_record = require('./record-D97pjgdq.cjs'); -const node_path = require_record.__toESM(require("node:path")); -const itty_router = require_record.__toESM(require("itty-router")); -const node_fs = require_record.__toESM(require("node:fs")); +let node_path = require("node:path"); +node_path = require_record.__toESM(node_path); +let itty_router = require("itty-router"); +itty_router = require_record.__toESM(itty_router); +let node_fs = require("node:fs"); +node_fs = require_record.__toESM(node_fs); //#region src/error.ts var HyperAPIError = class extends Error { @@ -130,13 +133,10 @@ var HyperAPIModule = class { return this; } async _run(request) { - let request_result = request; + const request_result = request; for (const fn of this.chain) { const request_add = await fn(request_result); - if (request_add) request_result = { - ...request_result, - ...request_add - }; + if (request_add) Object.assign(request_result, request_add); } return request_result; } @@ -303,10 +303,9 @@ function readFiles(path_given, _state) { /** * Sorts the routes in the given result. * @param result The result to sort. -* @returns - */ function sortRoutes(result) { - return result.sort((a, b) => { + result.sort((a, b) => { if (a.specificity.type !== b.specificity.type) return a.specificity.type - b.specificity.type; if (a.specificity.static_length !== b.specificity.static_length) return b.specificity.static_length - a.specificity.static_length; if (a.specificity.position !== b.specificity.position) return a.specificity.position - b.specificity.position; @@ -323,8 +322,7 @@ function sortRoutes(result) { */ function createRouter(path_root) { const router = (0, itty_router.IttyRouter)(); - const routes = readFiles(path_root); - fillRouter(routes, router); + fillRouter(readFiles(path_root), router); return router; } /** @@ -333,14 +331,15 @@ function createRouter(path_root) { * @param router The IttyRouter to attach to. */ function fillRouter(routes, router) { - for (const route of routes) if ("method" in route) router[route.method](route.route, (request) => ({ - async getHandler() { - const module_ = await import(route.path); - return module_.default; - }, - path: route.path, - args: request.params - })); + for (const route of routes) if ("method" in route) router[route.method](route.route, (request) => { + return { + async getHandler() { + return (await import(route.path)).default; + }, + path: route.path, + args: request.params + }; + }); else if ("children" in route) fillRouter(route.children, router); } /** @@ -357,11 +356,10 @@ async function useRouter(router, method, path) { url }); if (result) return result; - const result_unknown = await router.fetch({ + return await router.fetch({ method: "UNKNOWN", url - }); - return result_unknown ? "INVALID" : "NOT_EXISTS"; + }) ? "INVALID" : "NOT_EXISTS"; } //#endregion @@ -402,7 +400,7 @@ var HyperAPI = class { return this; } async processRequest(request) { - let request_external = {}; + const request_external = {}; try { if (request.path.startsWith("/") !== true) request.path = `/${request.path}`; for (const fn of this.hooks_before_router) { @@ -410,10 +408,7 @@ var HyperAPI = class { ...request, ...request_external }); - if (request_added !== void 0) request_external = { - ...request_external, - ...request_added - }; + if (request_added !== void 0) Object.assign(request_external, request_added); } const router_response = await useRouter(this.router, request.method, request.path); if (router_response === "INVALID") throw new HyperAPIUnknownMethodNotAllowedError(); @@ -423,8 +418,7 @@ var HyperAPI = class { ...request.args, ...router_response.args }; - const handler = await router_response.getHandler(); - const { response } = await handler._run({ + const { response } = await (await router_response.getHandler())._run({ ...request, ...request_external }); diff --git a/dist/main.d.cts b/dist/main.d.cts index 05e85ad..fc05f5b 100644 --- a/dist/main.d.cts +++ b/dist/main.d.cts @@ -1,4 +1,4 @@ -import { BaseRecord, EmptyObject, Extend, HyperAPIDriver, HyperAPIError, HyperAPIErrorData, HyperAPIModule, HyperAPIRequest, HyperAPIResponse, Join } from "./driver-B9cVUC-_.cjs"; +import { a as Extend, c as HyperAPIErrorData, d as BaseRecord, f as EmptyObject, l as HyperAPIRequest, n as HyperAPIResponse, o as Join, r as HyperAPIModule, s as HyperAPIError, t as HyperAPIDriver } from "./driver-DO8IdV_Q.cjs"; import { Promisable } from "type-fest"; //#region src/api-errors.d.ts diff --git a/dist/main.d.ts b/dist/main.d.ts index 8814c32..b694d68 100644 --- a/dist/main.d.ts +++ b/dist/main.d.ts @@ -1,4 +1,4 @@ -import { BaseRecord, EmptyObject, Extend, HyperAPIDriver, HyperAPIError, HyperAPIErrorData, HyperAPIModule, HyperAPIRequest, HyperAPIResponse, Join } from "./driver--QMVe1BB.js"; +import { a as Extend, c as HyperAPIErrorData, d as BaseRecord, f as EmptyObject, l as HyperAPIRequest, n as HyperAPIResponse, o as Join, r as HyperAPIModule, s as HyperAPIError, t as HyperAPIDriver } from "./driver-D8sen_tB.js"; import { Promisable } from "type-fest"; //#region src/api-errors.d.ts diff --git a/dist/main.js b/dist/main.js index 159c96b..14e982d 100644 --- a/dist/main.js +++ b/dist/main.js @@ -1,4 +1,4 @@ -import { hasCommonKeys, isRecord } from "./record-DFObD9mD.js"; +import { n as isRecord, t as hasCommonKeys } from "./record-BeJ2ZKAR.js"; import nodePath from "node:path"; import { IttyRouter } from "itty-router"; import { readdirSync } from "node:fs"; @@ -130,13 +130,10 @@ var HyperAPIModule = class { return this; } async _run(request) { - let request_result = request; + const request_result = request; for (const fn of this.chain) { const request_add = await fn(request_result); - if (request_add) request_result = { - ...request_result, - ...request_add - }; + if (request_add) Object.assign(request_result, request_add); } return request_result; } @@ -303,10 +300,9 @@ function readFiles(path_given, _state) { /** * Sorts the routes in the given result. * @param result The result to sort. -* @returns - */ function sortRoutes(result) { - return result.sort((a, b) => { + result.sort((a, b) => { if (a.specificity.type !== b.specificity.type) return a.specificity.type - b.specificity.type; if (a.specificity.static_length !== b.specificity.static_length) return b.specificity.static_length - a.specificity.static_length; if (a.specificity.position !== b.specificity.position) return a.specificity.position - b.specificity.position; @@ -323,8 +319,7 @@ function sortRoutes(result) { */ function createRouter(path_root) { const router = IttyRouter(); - const routes = readFiles(path_root); - fillRouter(routes, router); + fillRouter(readFiles(path_root), router); return router; } /** @@ -333,14 +328,15 @@ function createRouter(path_root) { * @param router The IttyRouter to attach to. */ function fillRouter(routes, router) { - for (const route of routes) if ("method" in route) router[route.method](route.route, (request) => ({ - async getHandler() { - const module_ = await import(route.path); - return module_.default; - }, - path: route.path, - args: request.params - })); + for (const route of routes) if ("method" in route) router[route.method](route.route, (request) => { + return { + async getHandler() { + return (await import(route.path)).default; + }, + path: route.path, + args: request.params + }; + }); else if ("children" in route) fillRouter(route.children, router); } /** @@ -357,11 +353,10 @@ async function useRouter(router, method, path) { url }); if (result) return result; - const result_unknown = await router.fetch({ + return await router.fetch({ method: "UNKNOWN", url - }); - return result_unknown ? "INVALID" : "NOT_EXISTS"; + }) ? "INVALID" : "NOT_EXISTS"; } //#endregion @@ -402,7 +397,7 @@ var HyperAPI = class { return this; } async processRequest(request) { - let request_external = {}; + const request_external = {}; try { if (request.path.startsWith("/") !== true) request.path = `/${request.path}`; for (const fn of this.hooks_before_router) { @@ -410,10 +405,7 @@ var HyperAPI = class { ...request, ...request_external }); - if (request_added !== void 0) request_external = { - ...request_external, - ...request_added - }; + if (request_added !== void 0) Object.assign(request_external, request_added); } const router_response = await useRouter(this.router, request.method, request.path); if (router_response === "INVALID") throw new HyperAPIUnknownMethodNotAllowedError(); @@ -423,8 +415,7 @@ var HyperAPI = class { ...request.args, ...router_response.args }; - const handler = await router_response.getHandler(); - const { response } = await handler._run({ + const { response } = await (await router_response.getHandler())._run({ ...request, ...request_external }); diff --git a/dist/record-DFObD9mD.js b/dist/record-BeJ2ZKAR.js similarity index 92% rename from dist/record-DFObD9mD.js rename to dist/record-BeJ2ZKAR.js index 44f6073..6ef675a 100644 --- a/dist/record-DFObD9mD.js +++ b/dist/record-BeJ2ZKAR.js @@ -19,4 +19,4 @@ function hasCommonKeys(value1, value2) { } //#endregion -export { hasCommonKeys, isRecord }; \ No newline at end of file +export { isRecord as n, hasCommonKeys as t }; \ No newline at end of file diff --git a/eslint.config.js b/eslint.config.js index 7d4be0e..32edb10 100644 --- a/eslint.config.js +++ b/eslint.config.js @@ -1,4 +1,6 @@ import { configCommon } from '@kirick/lint/eslint/common'; import { configNode } from '@kirick/lint/eslint/node'; +import { configOxlint } from '@kirick/lint/eslint/oxlint'; +import { defineConfig } from 'eslint/config'; -export default [...configCommon, ...configNode]; +export default defineConfig([...configCommon, ...configNode, ...configOxlint]); diff --git a/package.json b/package.json index fc7bd68..0e8bd0a 100644 --- a/package.json +++ b/package.json @@ -34,17 +34,17 @@ "type-fest": "4.41.0" }, "devDependencies": { - "@biomejs/biome": "2.1.1", - "@kirick/lint": "0.2.7", - "@types/bun": "1.2.21", - "eslint": "9.27.0", - "oxlint": "1.3.0", - "publint": "0.3.12", - "tsdown": "0.14.2", - "typescript": "5.9.2", - "unplugin-unused": "0.5.2", + "@biomejs/biome": "2.3.1", + "@kirick/lint": "0.2.12", + "@types/bun": "1.3.1", + "eslint": "9.38.0", + "oxlint": "1.24.0", + "publint": "0.3.15", + "tsdown": "0.15.12", + "typescript": "5.9.3", + "unplugin-unused": "0.5.4", "valibot": "1.1.0", - "vitest": "3.2.4" + "vitest": "4.0.4" }, "scripts": { "build": "tsdown src/main.ts src/dev.ts --publint --unused --dts --format esm --format cjs", diff --git a/src/error.test.ts b/src/error.test.ts index e9c6132..4dd1022 100644 --- a/src/error.test.ts +++ b/src/error.test.ts @@ -1,5 +1,3 @@ -/* eslint-disable @typescript-eslint/no-explicit-any */ - import { expect, test } from 'vitest'; import { HyperAPIBusyError } from './api-errors.js'; import { HyperAPIError } from './error.js'; @@ -11,6 +9,7 @@ test('data', () => { expect(error.data?.foo).toBe('bar'); }); +// oxlint-disable-next-line typescript/no-explicit-any class HyperAPICustomError extends HyperAPIError { code = 1001; description = 'This is a custom error'; diff --git a/src/main.test.ts b/src/main.test.ts index ec602e4..2c6b02e 100644 --- a/src/main.test.ts +++ b/src/main.test.ts @@ -1,3 +1,5 @@ +// oxlint-disable max-lines-per-function, max-nested-callbacks + import { describe, expect, expectTypeOf, test, vi } from 'vitest'; import { HyperAPITestDriver, TestRequest } from '../test/driver.js'; import { HyperAPI } from './main.js'; diff --git a/src/main.ts b/src/main.ts index 4126442..9fca57f 100644 --- a/src/main.ts +++ b/src/main.ts @@ -98,7 +98,7 @@ export class HyperAPI< // console.log('Processing request:', request); - let request_external = {} as ReqExtra; + const request_external = {} as ReqExtra; try { if (request.path.startsWith('/') !== true) { @@ -113,10 +113,7 @@ export class HyperAPI< ...request_external, }); if (request_added !== undefined) { - request_external = { - ...request_external, - ...request_added, - }; + Object.assign(request_external, request_added); } } @@ -172,7 +169,7 @@ export class HyperAPI< } } - // eslint-disable-next-line class-methods-use-this + // oxlint-disable-next-line class-methods-use-this module(): HyperAPIModule { return new HyperAPIModule(); } diff --git a/src/module.ts b/src/module.ts index d76a59e..5c5ffca 100644 --- a/src/module.ts +++ b/src/module.ts @@ -66,15 +66,12 @@ export class HyperAPIModule< async _run( request: Req, ): Promise>> { - let request_result = request; + const request_result = request; for (const fn of this.chain) { // oxlint-disable-next-line no-await-in-loop const request_add = await fn(request_result as Join); if (request_add) { - request_result = { - ...request_result, - ...request_add, - }; + Object.assign(request_result, request_add); } } diff --git a/src/response.ts b/src/response.ts index 7b5eeda..f86f2c4 100644 --- a/src/response.ts +++ b/src/response.ts @@ -2,7 +2,7 @@ import { HyperAPIError } from './error.js'; import type { HyperAPIModuleResponse } from './module.js'; import { isRecord } from './utils/record.js'; -// eslint-disable-next-line @typescript-eslint/no-explicit-any +// oxlint-disable-next-line typescript/no-explicit-any export type HyperAPIResponse = HyperAPIModuleResponse | HyperAPIError; /** @@ -14,10 +14,10 @@ export function isHyperAPIResponse( response: unknown, ): response is HyperAPIResponse { return ( - response instanceof HyperAPIError || - response instanceof Response || - isRecord(response) || - Array.isArray(response) || - response === undefined + response instanceof HyperAPIError + || response instanceof Response + || isRecord(response) + || Array.isArray(response) + || response === undefined ); } diff --git a/src/router.ts b/src/router.ts index afb48d9..d153241 100644 --- a/src/router.ts +++ b/src/router.ts @@ -22,7 +22,7 @@ type HyperAPIIttyRouter = IttyRouterType< * @returns The new IttyRouter. */ export function createRouter(path_root: string): HyperAPIIttyRouter { - // eslint-disable-next-line new-cap + // oxlint-disable-next-line new-cap const router: HyperAPIIttyRouter = IttyRouter(); const routes = readFiles(path_root); @@ -42,18 +42,18 @@ function fillRouter(routes: WalkResult, router: HyperAPIIttyRouter) { for (const route of routes) { if ('method' in route) { // console.log('[fillRouter]', route.method, route.route); - router[route.method]( - route.route, - (request) => - ({ - async getHandler() { - const module_ = await import(route.path); - return module_.default; - }, - path: route.path, - args: request.params, - }) as HyperAPIIttyRouterResponse, - ); + router[route.method](route.route, (request) => { + const r_ = { + async getHandler() { + const module_ = await import(route.path); + return module_.default; + }, + path: route.path, + args: request.params, + } as HyperAPIIttyRouterResponse; + + return r_; + }); } else if ('children' in route) { fillRouter(route.children, router); } diff --git a/src/router/file-tree.ts b/src/router/file-tree.ts index d177566..b3a3ef7 100644 --- a/src/router/file-tree.ts +++ b/src/router/file-tree.ts @@ -150,10 +150,9 @@ export function readFiles(path_given: string, _state?: WalkState): WalkResult { /** * Sorts the routes in the given result. * @param result The result to sort. - * @returns - */ function sortRoutes(result: WalkResult) { - return result.sort((a, b) => { + result.sort((a, b) => { if (a.specificity.type !== b.specificity.type) { return a.specificity.type - b.specificity.type; } diff --git a/src/utils/methods.ts b/src/utils/methods.ts index fa1bf95..8ebc0fa 100644 --- a/src/utils/methods.ts +++ b/src/utils/methods.ts @@ -15,13 +15,13 @@ export type HyperAPIMethod = */ export function isHyperApiMethod(method: unknown): method is HyperAPIMethod { return ( - method === 'DELETE' || - method === 'GET' || - method === 'HEAD' || - method === 'OPTIONS' || - method === 'PATCH' || - method === 'POST' || - method === 'PUT' || - method === 'UNKNOWN' + method === 'DELETE' + || method === 'GET' + || method === 'HEAD' + || method === 'OPTIONS' + || method === 'PATCH' + || method === 'POST' + || method === 'PUT' + || method === 'UNKNOWN' ); } diff --git a/src/utils/record.ts b/src/utils/record.ts index ef92494..3cd9f70 100644 --- a/src/utils/record.ts +++ b/src/utils/record.ts @@ -8,11 +8,11 @@ export type EmptyObject = Record; */ export function isRecord(value: unknown): value is BaseRecord { return ( - typeof value === 'object' && - value !== null && - !Array.isArray(value) && - value.constructor === Object && - Object.prototype.toString.call(value) === '[object Object]' + typeof value === 'object' + && value !== null + && !Array.isArray(value) + && value.constructor === Object + && Object.prototype.toString.call(value) === '[object Object]' ); } diff --git a/test/hyper-api/router/slug/x-[slug]-x.ts b/test/hyper-api/router/slug/x-[slug]-x.ts index 542c056..a044295 100644 --- a/test/hyper-api/router/slug/x-[slug]-x.ts +++ b/test/hyper-api/router/slug/x-[slug]-x.ts @@ -1,5 +1,3 @@ -/* eslint-disable unicorn/filename-case */ - import { hyperApi } from '../../../server.js'; export default hyperApi.module().action((request) => { diff --git a/test/hyper-api/router/slug/x-[slug].ts b/test/hyper-api/router/slug/x-[slug].ts index 542c056..a044295 100644 --- a/test/hyper-api/router/slug/x-[slug].ts +++ b/test/hyper-api/router/slug/x-[slug].ts @@ -1,5 +1,3 @@ -/* eslint-disable unicorn/filename-case */ - import { hyperApi } from '../../../server.js'; export default hyperApi.module().action((request) => { diff --git a/tsconfig.json b/tsconfig.json index 9e0fdab..2520a05 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -11,7 +11,7 @@ "noImplicitOverride": true, "module": "preserve", "noEmit": true, - "lib": ["es2022"], + "lib": ["es2023"], "declaration": true, "isolatedDeclarations": true }, From 1aa5ffd2e603040e99f80f84b028a386ead5cca5 Mon Sep 17 00:00:00 2001 From: Daniil Kirichenko Date: Thu, 30 Oct 2025 15:59:36 +0100 Subject: [PATCH 57/57] Update tsconfig --- package.json | 4 ++-- src/error.test.ts | 4 ++-- src/main.test.ts | 4 ++-- src/utils/types.test.ts | 4 ++-- test/tsconfig.json | 7 ------- tsconfig.base.json | 19 +++++++++++++++++++ tsconfig.json | 23 +++++------------------ tsconfig.main.json | 8 ++++++++ tsconfig.test.json | 4 ++++ 9 files changed, 44 insertions(+), 33 deletions(-) delete mode 100644 test/tsconfig.json create mode 100644 tsconfig.base.json create mode 100644 tsconfig.main.json create mode 100644 tsconfig.test.json diff --git a/package.json b/package.json index 0e8bd0a..76701b7 100644 --- a/package.json +++ b/package.json @@ -47,9 +47,9 @@ "vitest": "4.0.4" }, "scripts": { - "build": "tsdown src/main.ts src/dev.ts --publint --unused --dts --format esm --format cjs", + "build": "tsdown src/main.ts src/dev.ts --clean --tsconfig tsconfig.main.json --publint --unused --dts --format esm --format cjs", "check": "bun run lint && bun run build && bun run test", - "lint": "biome format && oxlint && eslint . && tsc && (cd test && tsc)", + "lint": "biome format && oxlint && eslint . && tsc -b", "test": "npm run test:vitest && bun test --coverage", "test:vitest": "vitest run --no-file-parallelism" }, diff --git a/src/error.test.ts b/src/error.test.ts index 4dd1022..1feadd9 100644 --- a/src/error.test.ts +++ b/src/error.test.ts @@ -11,8 +11,8 @@ test('data', () => { // oxlint-disable-next-line typescript/no-explicit-any class HyperAPICustomError extends HyperAPIError { - code = 1001; - description = 'This is a custom error'; + override code = 1001; + override description = 'This is a custom error'; } test('custom error', () => { diff --git a/src/main.test.ts b/src/main.test.ts index 2c6b02e..f4eca4d 100644 --- a/src/main.test.ts +++ b/src/main.test.ts @@ -1,9 +1,9 @@ // oxlint-disable max-lines-per-function, max-nested-callbacks import { describe, expect, expectTypeOf, test, vi } from 'vitest'; -import { HyperAPITestDriver, TestRequest } from '../test/driver.js'; +import { HyperAPITestDriver, type TestRequest } from '../test/driver.js'; import { HyperAPI } from './main.js'; -import { HyperAPIResponse } from './response.js'; +import type { HyperAPIResponse } from './response.js'; test('HyperAPI constructor', () => { const driver = new HyperAPITestDriver(); diff --git a/src/utils/types.test.ts b/src/utils/types.test.ts index 9e2e9c0..c6fbe69 100644 --- a/src/utils/types.test.ts +++ b/src/utils/types.test.ts @@ -1,6 +1,6 @@ import { expectTypeOf, test } from 'vitest'; -import { EmptyObject } from './record.js'; -import { Extend } from './types.js'; +import type { EmptyObject } from './record.js'; +import type { Extend } from './types.js'; test('Extend', () => { // type T = Extend<{ a: string }, { b: number }>; diff --git a/test/tsconfig.json b/test/tsconfig.json deleted file mode 100644 index a1ca658..0000000 --- a/test/tsconfig.json +++ /dev/null @@ -1,7 +0,0 @@ -{ - "extends": "../tsconfig.json", - "compilerOptions": { - "isolatedDeclarations": false - }, - "include": ["./**/*.ts", "../src/**/*.test.ts"] -} diff --git a/tsconfig.base.json b/tsconfig.base.json new file mode 100644 index 0000000..e666180 --- /dev/null +++ b/tsconfig.base.json @@ -0,0 +1,19 @@ +{ + "compilerOptions": { + "esModuleInterop": true, + "skipLibCheck": true, + "target": "es2022", + "moduleDetection": "force", + "isolatedModules": true, + "verbatimModuleSyntax": true, + "strict": true, + "noUncheckedIndexedAccess": true, + "noImplicitOverride": true, + "module": "preserve", + "noEmit": true, + "lib": ["es2022"], + "declaration": true, + "isolatedDeclarations": false, + "tsBuildInfoFile": "/dev/null" + } +} diff --git a/tsconfig.json b/tsconfig.json index 2520a05..4e14791 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -1,20 +1,7 @@ { - "compilerOptions": { - "esModuleInterop": true, - "skipLibCheck": true, - "target": "es2022", - "moduleDetection": "force", - "isolatedModules": true, - "verbatimModuleSyntax": true, - "strict": true, - "noUncheckedIndexedAccess": true, - "noImplicitOverride": true, - "module": "preserve", - "noEmit": true, - "lib": ["es2023"], - "declaration": true, - "isolatedDeclarations": true - }, - "include": ["src/"], - "exclude": ["**/*.test.ts"] + "files": [], + "references": [ + { "path": "./tsconfig.main.json" }, + { "path": "./tsconfig.test.json" } + ] } diff --git a/tsconfig.main.json b/tsconfig.main.json new file mode 100644 index 0000000..256535f --- /dev/null +++ b/tsconfig.main.json @@ -0,0 +1,8 @@ +{ + "extends": "./tsconfig.base.json", + "compilerOptions": { + "isolatedDeclarations": true + }, + "include": ["src/**/*.ts"], + "exclude": ["src/**/*.test.ts"] +} diff --git a/tsconfig.test.json b/tsconfig.test.json new file mode 100644 index 0000000..4d33b90 --- /dev/null +++ b/tsconfig.test.json @@ -0,0 +1,4 @@ +{ + "extends": "./tsconfig.base.json", + "include": ["src/**/*.test.ts", "test/**/*.ts"] +}