diff --git a/.dependency-cruiser.cjs b/.dependency-cruiser.cjs new file mode 100644 index 000000000..0219b9b96 --- /dev/null +++ b/.dependency-cruiser.cjs @@ -0,0 +1,380 @@ +/** @type {import('dependency-cruiser').IConfiguration} */ +module.exports = { + forbidden: [ + { + name: 'no-circular', + severity: 'warn', + comment: + 'This dependency is part of a circular relationship. You might want to revise ' + + 'your solution (i.e. use dependency inversion, make sure the modules have a single responsibility) ', + from: {}, + to: { + circular: true, + }, + }, + { + name: 'no-orphans', + comment: + "This is an orphan module - it's likely not used (anymore?). Either use it or " + + "remove it. If it's logical this module is an orphan (i.e. it's a config file), " + + 'add an exception for it in your dependency-cruiser configuration. By default ' + + 'this rule does not scrutinize dot-files (e.g. .eslintrc.js), TypeScript declaration ' + + 'files (.d.ts), tsconfig.json and some of the babel and webpack configs.', + severity: 'warn', + from: { + orphan: true, + pathNot: [ + '(^|/)[.][^/]+[.](?:js|cjs|mjs|ts|cts|mts|json)$', // dot files + '[.]d[.]ts$', // TypeScript declaration files + '(^|/)tsconfig[.]json$', // TypeScript config + '(^|/)(?:babel|webpack)[.]config[.](?:js|cjs|mjs|ts|cts|mts|json)$', // other configs + ], + }, + to: {}, + }, + { + name: 'no-deprecated-core', + comment: + 'A module depends on a node core module that has been deprecated. Find an alternative - these are ' + + "bound to exist - node doesn't deprecate lightly.", + severity: 'warn', + from: {}, + to: { + dependencyTypes: ['core'], + path: [ + '^v8/tools/codemap$', + '^v8/tools/consarray$', + '^v8/tools/csvparser$', + '^v8/tools/logreader$', + '^v8/tools/profile_view$', + '^v8/tools/profile$', + '^v8/tools/SourceMap$', + '^v8/tools/splaytree$', + '^v8/tools/tickprocessor-driver$', + '^v8/tools/tickprocessor$', + '^node-inspect/lib/_inspect$', + '^node-inspect/lib/internal/inspect_client$', + '^node-inspect/lib/internal/inspect_repl$', + '^async_hooks$', + '^punycode$', + '^domain$', + '^constants$', + '^sys$', + '^_linklist$', + '^_stream_wrap$', + ], + }, + }, + { + name: 'not-to-deprecated', + comment: + 'This module uses a (version of an) npm module that has been deprecated. Either upgrade to a later ' + + 'version of that module, or find an alternative. Deprecated modules are a security risk.', + severity: 'warn', + from: {}, + to: { + dependencyTypes: ['deprecated'], + }, + }, + { + name: 'no-non-package-json', + severity: 'error', + comment: + "This module depends on an npm package that isn't in the 'dependencies' section of your package.json. " + + "That's problematic as the package either (1) won't be available on live (2 - worse) will be " + + 'available on live with an non-guaranteed version. Fix it by adding the package to the dependencies ' + + 'in your package.json.', + from: {}, + to: { + dependencyTypes: ['npm-no-pkg', 'npm-unknown'], + }, + }, + { + name: 'not-to-unresolvable', + comment: + "This module depends on a module that cannot be found ('resolved to disk'). If it's an npm " + + 'module: add it to your package.json. In all other cases you likely already know what to do.', + severity: 'error', + from: {}, + to: { + couldNotResolve: true, + }, + }, + { + name: 'no-duplicate-dep-types', + comment: + "Likely this module depends on an external ('npm') package that occurs more than once " + + 'in your package.json i.e. bot as a devDependencies and in dependencies. This will cause ' + + 'maintenance problems later on.', + severity: 'warn', + from: {}, + to: { + moreThanOneDependencyType: true, + // as it's pretty common to have a type import be a type only import + // _and_ (e.g.) a devDependency - don't consider type-only dependency + // types for this rule + dependencyTypesNot: ['type-only'], + }, + }, + + /* rules you might want to tweak for your specific situation: */ + + { + name: 'not-to-spec', + comment: + 'This module depends on a spec (test) file. The sole responsibility of a spec file is to test code. ' + + "If there's something in a spec that's of use to other modules, it doesn't have that single " + + 'responsibility anymore. Factor it out into (e.g.) a separate utility/ helper or a mock.', + severity: 'error', + from: {}, + to: { + path: '[.](?:spec|test)[.](?:js|mjs|cjs|jsx|ts|mts|cts|tsx)$', + }, + }, + { + name: 'not-to-dev-dep', + severity: 'error', + comment: + "This module depends on an npm package from the 'devDependencies' section of your " + + 'package.json. It looks like something that ships to production, though. To prevent problems ' + + "with npm packages that aren't there on production declare it (only!) in the 'dependencies'" + + 'section of your package.json. If this module is development only - add it to the ' + + 'from.pathNot re of the not-to-dev-dep rule in the dependency-cruiser configuration', + from: { + path: '^(src)', + pathNot: '[.](?:spec|test)[.](?:js|mjs|cjs|jsx|ts|mts|cts|tsx)$', + }, + to: { + dependencyTypes: ['npm-dev'], + // type only dependencies are not a problem as they don't end up in the + // production code or are ignored by the runtime. + dependencyTypesNot: ['type-only'], + pathNot: ['node_modules/@types/'], + }, + }, + { + name: 'optional-deps-used', + severity: 'info', + comment: + 'This module depends on an npm package that is declared as an optional dependency ' + + "in your package.json. As this makes sense in limited situations only, it's flagged here. " + + "If you're using an optional dependency here by design - add an exception to your" + + 'dependency-cruiser configuration.', + from: {}, + to: { + dependencyTypes: ['npm-optional'], + }, + }, + { + name: 'peer-deps-used', + comment: + 'This module depends on an npm package that is declared as a peer dependency ' + + 'in your package.json. This makes sense if your package is e.g. a plugin, but in ' + + 'other cases - maybe not so much. If the use of a peer dependency is intentional ' + + 'add an exception to your dependency-cruiser configuration.', + severity: 'warn', + from: {}, + to: { + dependencyTypes: ['npm-peer'], + }, + }, + ], + options: { + /* Which modules not to follow further when encountered */ + doNotFollow: { + /* path: an array of regular expressions in strings to match against */ + path: ['node_modules'], + }, + + /* Which modules to exclude */ + // exclude : { + // /* path: an array of regular expressions in strings to match against */ + // path: '', + // }, + + /* Which modules to exclusively include (array of regular expressions in strings) + dependency-cruiser will skip everything not matching this pattern + */ + // includeOnly : [''], + + /* List of module systems to cruise. + When left out dependency-cruiser will fall back to the list of _all_ + module systems it knows of. It's the default because it's the safe option + It might come at a performance penalty, though. + moduleSystems: ['amd', 'cjs', 'es6', 'tsd'] + + As in practice only commonjs ('cjs') and ecmascript modules ('es6') + are widely used, you can limit the moduleSystems to those. + */ + + // moduleSystems: ['cjs', 'es6'], + + /* + false: don't look at JSDoc imports (the default) + true: dependency-cruiser will detect dependencies in JSDoc-style + import statements. Implies "parser": "tsc", so the dependency-cruiser + will use the typescript parser for JavaScript files. + + For this to work the typescript compiler will need to be installed in the + same spot as you're running dependency-cruiser from. + */ + // detectJSDocImports: true, + + /* prefix for links in html and svg output (e.g. 'https://github.com/you/yourrepo/blob/main/' + to open it on your online repo or `vscode://file/${process.cwd()}/` to + open it in visual studio code), + */ + // prefix: `vscode://file/${process.cwd()}/`, + + /* false (the default): ignore dependencies that only exist before typescript-to-javascript compilation + true: also detect dependencies that only exist before typescript-to-javascript compilation + "specify": for each dependency identify whether it only exists before compilation or also after + */ + tsPreCompilationDeps: true, + + /* list of extensions to scan that aren't javascript or compile-to-javascript. + Empty by default. Only put extensions in here that you want to take into + account that are _not_ parsable. + */ + // extraExtensionsToScan: [".json", ".jpg", ".png", ".svg", ".webp"], + + /* if true combines the package.jsons found from the module up to the base + folder the cruise is initiated from. Useful for how (some) mono-repos + manage dependencies & dependency definitions. + */ + // combinedDependencies: false, + + /* if true leave symlinks untouched, otherwise use the realpath */ + // preserveSymlinks: false, + + /* TypeScript project file ('tsconfig.json') to use for + (1) compilation and + (2) resolution (e.g. with the paths property) + + The (optional) fileName attribute specifies which file to take (relative to + dependency-cruiser's current working directory). When not provided + defaults to './tsconfig.json'. + */ + tsConfig: { + fileName: 'tsconfig.json', + }, + + /* Webpack configuration to use to get resolve options from. + + The (optional) fileName attribute specifies which file to take (relative + to dependency-cruiser's current working directory. When not provided defaults + to './webpack.conf.js'. + + The (optional) `env` and `arguments` attributes contain the parameters + to be passed if your webpack config is a function and takes them (see + webpack documentation for details) + */ + // webpackConfig: { + // fileName: 'webpack.config.js', + // env: {}, + // arguments: {} + // }, + + /* Babel config ('.babelrc', '.babelrc.json', '.babelrc.json5', ...) to use + for compilation + */ + // babelConfig: { + // fileName: '.babelrc', + // }, + + /* List of strings you have in use in addition to cjs/ es6 requires + & imports to declare module dependencies. Use this e.g. if you've + re-declared require, use a require-wrapper or use window.require as + a hack. + */ + // exoticRequireStrings: [], + + /* options to pass on to enhanced-resolve, the package dependency-cruiser + uses to resolve module references to disk. The values below should be + suitable for most situations + + If you use webpack: you can also set these in webpack.conf.js. The set + there will override the ones specified here. + */ + enhancedResolveOptions: { + /* What to consider as an 'exports' field in package.jsons */ + exportsFields: ['exports'], + /* List of conditions to check for in the exports field. + Only works when the 'exportsFields' array is non-empty. + */ + conditionNames: ['import', 'require', 'node', 'default', 'types'], + /* + The extensions, by default are the same as the ones dependency-cruiser + can access (run `npx depcruise --info` to see which ones that are in + _your_ environment). If that list is larger than you need you can pass + the extensions you actually use (e.g. [".js", ".jsx"]). This can speed + up module resolution, which is the most expensive step. + */ + // extensions: [".js", ".jsx", ".ts", ".tsx", ".d.ts"], + /* What to consider a 'main' field in package.json */ + mainFields: ['module', 'main', 'types', 'typings'], + /* + A list of alias fields in package.jsons + See [this specification](https://github.com/defunctzombie/package-browser-field-spec) and + the webpack [resolve.alias](https://webpack.js.org/configuration/resolve/#resolvealiasfields) + documentation + + Defaults to an empty array (= don't use alias fields). + */ + // aliasFields: ["browser"], + }, + + /* + skipAnalysisNotInRules will make dependency-cruiser execute + analysis strictly necessary for checking the rule set only. + + See https://github.com/sverweij/dependency-cruiser/blob/main/doc/options-reference.md#skipanalysisnotinrules + for details + */ + skipAnalysisNotInRules: true, + + reporterOptions: { + dot: { + /* pattern of modules that can be consolidated in the detailed + graphical dependency graph. The default pattern in this configuration + collapses everything in node_modules to one folder deep so you see + the external modules, but their innards. + */ + collapsePattern: 'node_modules/(?:@[^/]+/[^/]+|[^/]+)', + + /* Options to tweak the appearance of your graph.See + https://github.com/sverweij/dependency-cruiser/blob/main/doc/options-reference.md#reporteroptions + for details and some examples. If you don't specify a theme + dependency-cruiser falls back to a built-in one. + */ + // theme: { + // graph: { + // /* splines: "ortho" gives straight lines, but is slow on big graphs + // splines: "true" gives bezier curves (fast, not as nice as ortho) + // */ + // splines: "true" + // }, + // } + }, + archi: { + /* pattern of modules that can be consolidated in the high level + graphical dependency graph. If you use the high level graphical + dependency graph reporter (`archi`) you probably want to tweak + this collapsePattern to your situation. + */ + collapsePattern: + '^(?:packages|src|lib(s?)|app(s?)|bin|test(s?)|spec(s?))/[^/]+|node_modules/(?:@[^/]+/[^/]+|[^/]+)', + + /* Options to tweak the appearance of your graph. If you don't specify a + theme for 'archi' dependency-cruiser will use the one specified in the + dot section above and otherwise use the default one. + */ + // theme: { }, + }, + text: { + highlightFocused: true, + }, + }, + }, +}; +// generated: dependency-cruiser@16.9.0 on 2025-01-08T13:17:47.949Z diff --git a/.lintstagedrc.json b/.lintstagedrc.json index f21a4dd69..ffa891040 100644 --- a/.lintstagedrc.json +++ b/.lintstagedrc.json @@ -1,3 +1,3 @@ { - "*.{js,jsx,ts,tsx}": ["yarn fix:code"] + "*.{js,jsx,ts,tsx}": ["npm run fix:code"] } diff --git a/package-lock.json b/package-lock.json index d98696650..bee426a6e 100644 --- a/package-lock.json +++ b/package-lock.json @@ -18,6 +18,7 @@ "@types/node": "^18.15.11", "@vitest/coverage-v8": "^1.1.1", "benchmark": "^2.1.4", + "dependency-cruiser": "^16.9.0", "eslint": "^8.50.0", "generate-changelog": "^1.8.0", "husky": "^4.3.8", @@ -32,20 +33,12 @@ "vitest": "^1.1.1" } }, - "node_modules/@aashutoshrathi/word-wrap": { - "version": "1.2.6", - "resolved": "https://registry.npmjs.org/@aashutoshrathi/word-wrap/-/word-wrap-1.2.6.tgz", - "integrity": "sha512-1Yjs2SvM8TflER/OD3cOjhWWOZb58A2t7wpE2S9XfBYTiIl+XFhQG2bjy4Pu1I+EAlCNUzRDYDdFwFYUKvXcIA==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, "node_modules/@ampproject/remapping": { "version": "2.3.0", "resolved": "https://registry.npmjs.org/@ampproject/remapping/-/remapping-2.3.0.tgz", "integrity": "sha512-30iZtAPgz+LTIYoeivqYo853f02jBYSd5uGnGpkFV0M3xOt9aN73erkgYAmZU43x4VfqcnLxW9Kpg3R5LC4YYw==", "dev": true, + "license": "Apache-2.0", "dependencies": { "@jridgewell/gen-mapping": "^0.3.5", "@jridgewell/trace-mapping": "^0.3.24" @@ -55,12 +48,14 @@ } }, "node_modules/@babel/code-frame": { - "version": "7.24.2", - "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.24.2.tgz", - "integrity": "sha512-y5+tLQyV8pg3fsiln67BVLD1P13Eg4lh5RW9mF0zUuvLrv9uIQ4MCL+CRT+FTsBlBjcIan6PGsLcBN0m3ClUyQ==", + "version": "7.26.2", + "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.26.2.tgz", + "integrity": "sha512-RJlIHRueQgwWitWgF8OdFYGZX328Ax5BCemNGlqHfplnRT9ESi8JkFlvaVYbS+UubVY6dpv87Fs2u5M29iNFVQ==", "dev": true, + "license": "MIT", "dependencies": { - "@babel/highlight": "^7.24.2", + "@babel/helper-validator-identifier": "^7.25.9", + "js-tokens": "^4.0.0", "picocolors": "^1.0.0" }, "engines": { @@ -68,114 +63,34 @@ } }, "node_modules/@babel/helper-string-parser": { - "version": "7.24.1", - "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.24.1.tgz", - "integrity": "sha512-2ofRCjnnA9y+wk8b9IAREroeUP02KHp431N2mhKniy2yKIDKpbrHv9eXwm8cBeWQYcJmzv5qKCu65P47eCF7CQ==", + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.25.9.tgz", + "integrity": "sha512-4A/SCr/2KLd5jrtOMFzaKjVtAei3+2r/NChoBNoZ3EyP/+GlhoaEGoWOZUmFmoITP7zOJyHIMm+DYRd8o3PvHA==", "dev": true, + "license": "MIT", "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/helper-validator-identifier": { - "version": "7.22.20", - "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.22.20.tgz", - "integrity": "sha512-Y4OZ+ytlatR8AI+8KZfKuL5urKp7qey08ha31L8b3BwewJAoJamTzyvxPR/5D+KkdJCGPq/+8TukHBlY10FX9A==", + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.25.9.tgz", + "integrity": "sha512-Ed61U6XJc3CVRfkERJWDz4dJwKe7iLmmJsbOGu9wSloNSFttHV0I8g6UAgb7qnK5ly5bGLPd4oXZlxCdANBOWQ==", "dev": true, + "license": "MIT", "engines": { "node": ">=6.9.0" } }, - "node_modules/@babel/highlight": { - "version": "7.24.2", - "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.24.2.tgz", - "integrity": "sha512-Yac1ao4flkTxTteCDZLEvdxg2fZfz1v8M4QpaGypq/WPDqg3ijHYbDfs+LG5hvzSoqaSZ9/Z9lKSP3CjZjv+pA==", - "dev": true, - "dependencies": { - "@babel/helper-validator-identifier": "^7.22.20", - "chalk": "^2.4.2", - "js-tokens": "^4.0.0", - "picocolors": "^1.0.0" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/highlight/node_modules/ansi-styles": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", - "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", - "dev": true, - "dependencies": { - "color-convert": "^1.9.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/@babel/highlight/node_modules/chalk": { - "version": "2.4.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", - "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", - "dev": true, - "dependencies": { - "ansi-styles": "^3.2.1", - "escape-string-regexp": "^1.0.5", - "supports-color": "^5.3.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/@babel/highlight/node_modules/color-convert": { - "version": "1.9.3", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", - "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", - "dev": true, - "dependencies": { - "color-name": "1.1.3" - } - }, - "node_modules/@babel/highlight/node_modules/color-name": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", - "integrity": "sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==", - "dev": true - }, - "node_modules/@babel/highlight/node_modules/escape-string-regexp": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", - "integrity": "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==", - "dev": true, - "engines": { - "node": ">=0.8.0" - } - }, - "node_modules/@babel/highlight/node_modules/has-flag": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", - "integrity": "sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==", - "dev": true, - "engines": { - "node": ">=4" - } - }, - "node_modules/@babel/highlight/node_modules/supports-color": { - "version": "5.5.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", - "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "node_modules/@babel/parser": { + "version": "7.26.5", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.26.5.tgz", + "integrity": "sha512-SRJ4jYmXRqV1/Xc+TIVG84WjHBXKlxO9sHQnA2Pf12QQEAp1LOh6kDzNHXcUnbH1QI0FDoPPVOt+vyUDucxpaw==", "dev": true, + "license": "MIT", "dependencies": { - "has-flag": "^3.0.0" + "@babel/types": "^7.26.5" }, - "engines": { - "node": ">=4" - } - }, - "node_modules/@babel/parser": { - "version": "7.24.4", - "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.24.4.tgz", - "integrity": "sha512-zTvEBcghmeBma9QIGunWevvBAp4/Qu9Bdq+2k0Ot4fVMD6v3dsC9WOcRSKk7tRRyBM/53yKMJko9xOatGQAwSg==", - "dev": true, "bin": { "parser": "bin/babel-parser.js" }, @@ -184,14 +99,14 @@ } }, "node_modules/@babel/types": { - "version": "7.24.0", - "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.24.0.tgz", - "integrity": "sha512-+j7a5c253RfKh8iABBhywc8NSfP5LURe7Uh4qpsh6jc+aLJguvmIUBdjSdEMQv2bENrCR5MfRdjGo7vzS/ob7w==", + "version": "7.26.5", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.26.5.tgz", + "integrity": "sha512-L6mZmwFDK6Cjh1nRCLXpa6no13ZIioJDz7mdkzHv399pThrTa/k0nUlNaenOeh2kWu/iaOQYElEpKPUswUa9Vg==", "dev": true, + "license": "MIT", "dependencies": { - "@babel/helper-string-parser": "^7.23.4", - "@babel/helper-validator-identifier": "^7.22.20", - "to-fast-properties": "^2.0.0" + "@babel/helper-string-parser": "^7.25.9", + "@babel/helper-validator-identifier": "^7.25.9" }, "engines": { "node": ">=6.9.0" @@ -201,13 +116,15 @@ "version": "0.2.3", "resolved": "https://registry.npmjs.org/@bcoe/v8-coverage/-/v8-coverage-0.2.3.tgz", "integrity": "sha512-0hYQ8SB4Db5zvZB4axdMHGwEaQjkZzFjQiN9LVYvIFB2nSUHW9tYpxWriPrWDASIxiaXax83REcLxuSdnGPZtw==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/@cspotcode/source-map-support": { "version": "0.8.1", "resolved": "https://registry.npmjs.org/@cspotcode/source-map-support/-/source-map-support-0.8.1.tgz", "integrity": "sha512-IchNf6dN4tHoMFIn/7OE8LWZ19Y6q/67Bmf6vnGREv8RSbBVb9LPJxEcnwrcwX6ixSvaiGoomAUvu4YSxXrVgw==", "dev": true, + "license": "MIT", "dependencies": { "@jridgewell/trace-mapping": "0.3.9" }, @@ -220,6 +137,7 @@ "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.9.tgz", "integrity": "sha512-3Belt6tdc8bPgAtbcmdtNJlirVoTmEb5e2gC94PnkwEW9jI6CAHUeoG85tjWP5WquqfavoMtMwiG4P926ZKKuQ==", "dev": true, + "license": "MIT", "dependencies": { "@jridgewell/resolve-uri": "^3.0.3", "@jridgewell/sourcemap-codec": "^1.4.10" @@ -233,6 +151,7 @@ "ppc64" ], "dev": true, + "license": "MIT", "optional": true, "os": [ "aix" @@ -249,6 +168,7 @@ "arm" ], "dev": true, + "license": "MIT", "optional": true, "os": [ "android" @@ -265,6 +185,7 @@ "arm64" ], "dev": true, + "license": "MIT", "optional": true, "os": [ "android" @@ -281,6 +202,7 @@ "x64" ], "dev": true, + "license": "MIT", "optional": true, "os": [ "android" @@ -297,6 +219,7 @@ "arm64" ], "dev": true, + "license": "MIT", "optional": true, "os": [ "darwin" @@ -313,6 +236,7 @@ "x64" ], "dev": true, + "license": "MIT", "optional": true, "os": [ "darwin" @@ -329,6 +253,7 @@ "arm64" ], "dev": true, + "license": "MIT", "optional": true, "os": [ "freebsd" @@ -345,6 +270,7 @@ "x64" ], "dev": true, + "license": "MIT", "optional": true, "os": [ "freebsd" @@ -361,6 +287,7 @@ "arm" ], "dev": true, + "license": "MIT", "optional": true, "os": [ "linux" @@ -377,6 +304,7 @@ "arm64" ], "dev": true, + "license": "MIT", "optional": true, "os": [ "linux" @@ -393,6 +321,7 @@ "ia32" ], "dev": true, + "license": "MIT", "optional": true, "os": [ "linux" @@ -409,6 +338,7 @@ "loong64" ], "dev": true, + "license": "MIT", "optional": true, "os": [ "linux" @@ -425,6 +355,7 @@ "mips64el" ], "dev": true, + "license": "MIT", "optional": true, "os": [ "linux" @@ -441,6 +372,7 @@ "ppc64" ], "dev": true, + "license": "MIT", "optional": true, "os": [ "linux" @@ -457,6 +389,7 @@ "riscv64" ], "dev": true, + "license": "MIT", "optional": true, "os": [ "linux" @@ -473,6 +406,7 @@ "s390x" ], "dev": true, + "license": "MIT", "optional": true, "os": [ "linux" @@ -489,6 +423,7 @@ "x64" ], "dev": true, + "license": "MIT", "optional": true, "os": [ "linux" @@ -505,6 +440,7 @@ "x64" ], "dev": true, + "license": "MIT", "optional": true, "os": [ "netbsd" @@ -521,6 +457,7 @@ "x64" ], "dev": true, + "license": "MIT", "optional": true, "os": [ "openbsd" @@ -537,6 +474,7 @@ "x64" ], "dev": true, + "license": "MIT", "optional": true, "os": [ "sunos" @@ -553,6 +491,7 @@ "arm64" ], "dev": true, + "license": "MIT", "optional": true, "os": [ "win32" @@ -569,6 +508,7 @@ "ia32" ], "dev": true, + "license": "MIT", "optional": true, "os": [ "win32" @@ -585,6 +525,7 @@ "x64" ], "dev": true, + "license": "MIT", "optional": true, "os": [ "win32" @@ -594,25 +535,30 @@ } }, "node_modules/@eslint-community/eslint-utils": { - "version": "4.4.0", - "resolved": "https://registry.npmjs.org/@eslint-community/eslint-utils/-/eslint-utils-4.4.0.tgz", - "integrity": "sha512-1/sA4dwrzBAyeUoQ6oxahHKmrZvsnLCg4RfxW3ZFGGmQkSNQPFNLV9CUEFQP1x9EYXHTo5p6xdhZM1Ne9p/AfA==", + "version": "4.4.1", + "resolved": "https://registry.npmjs.org/@eslint-community/eslint-utils/-/eslint-utils-4.4.1.tgz", + "integrity": "sha512-s3O3waFUrMV8P/XaF/+ZTp1X9XBZW1a4B97ZnjQF2KYWaFD2A8KyFBsrsfSjEmjn3RGWAIuvlneuZm3CUK3jbA==", "dev": true, + "license": "MIT", "dependencies": { - "eslint-visitor-keys": "^3.3.0" + "eslint-visitor-keys": "^3.4.3" }, "engines": { "node": "^12.22.0 || ^14.17.0 || >=16.0.0" }, + "funding": { + "url": "https://opencollective.com/eslint" + }, "peerDependencies": { "eslint": "^6.0.0 || ^7.0.0 || >=8.0.0" } }, "node_modules/@eslint-community/regexpp": { - "version": "4.10.0", - "resolved": "https://registry.npmjs.org/@eslint-community/regexpp/-/regexpp-4.10.0.tgz", - "integrity": "sha512-Cu96Sd2By9mCNTx2iyKOmq10v22jUVQv0lQnlGNy16oE9589yE+QADPbrMGCkA51cKZSg3Pu/aTJVTGfL/qjUA==", + "version": "4.12.1", + "resolved": "https://registry.npmjs.org/@eslint-community/regexpp/-/regexpp-4.12.1.tgz", + "integrity": "sha512-CCZCDJuduB9OUkFkY2IgppNZMi2lBQgD2qzwXkEia16cge2pijY/aXi96CJMquDMn3nJdlPV1A5KrJEXwfLNzQ==", "dev": true, + "license": "MIT", "engines": { "node": "^12.0.0 || ^14.0.0 || >=16.0.0" } @@ -622,6 +568,7 @@ "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-2.1.4.tgz", "integrity": "sha512-269Z39MS6wVJtsoUl10L60WdkhJVdPG24Q4eZTH3nnF6lpvSShEK3wQjDX9JRWAUPvPh7COouPpU9IrqaZFvtQ==", "dev": true, + "license": "MIT", "dependencies": { "ajv": "^6.12.4", "debug": "^4.3.2", @@ -640,24 +587,74 @@ "url": "https://opencollective.com/eslint" } }, + "node_modules/@eslint/eslintrc/node_modules/ajv": { + "version": "6.12.6", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", + "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", + "dev": true, + "license": "MIT", + "dependencies": { + "fast-deep-equal": "^3.1.1", + "fast-json-stable-stringify": "^2.0.0", + "json-schema-traverse": "^0.4.1", + "uri-js": "^4.2.2" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/epoberezkin" + } + }, + "node_modules/@eslint/eslintrc/node_modules/brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "dev": true, + "license": "MIT", + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "node_modules/@eslint/eslintrc/node_modules/json-schema-traverse": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", + "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", + "dev": true, + "license": "MIT" + }, + "node_modules/@eslint/eslintrc/node_modules/minimatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "dev": true, + "license": "ISC", + "dependencies": { + "brace-expansion": "^1.1.7" + }, + "engines": { + "node": "*" + } + }, "node_modules/@eslint/js": { "version": "8.57.1", "resolved": "https://registry.npmjs.org/@eslint/js/-/js-8.57.1.tgz", "integrity": "sha512-d9zaMRSTIKDLhctzH12MtXvJKSSUhaHcjV+2Z+GK+EEY7XKpP5yR4x+N3TAcHTcu963nIr+TMcCb4DBCYX1z6Q==", "dev": true, + "license": "MIT", "engines": { "node": "^12.22.0 || ^14.17.0 || >=16.0.0" } }, "node_modules/@gerrit0/mini-shiki": { - "version": "1.24.1", - "resolved": "https://registry.npmjs.org/@gerrit0/mini-shiki/-/mini-shiki-1.24.1.tgz", - "integrity": "sha512-PNP/Gjv3VqU7z7DjRgO3F9Ok5frTKqtpV+LJW1RzMcr2zpRk0ulhEWnbcNGXzPC7BZyWMIHrkfQX2GZRfxrn6Q==", + "version": "1.26.1", + "resolved": "https://registry.npmjs.org/@gerrit0/mini-shiki/-/mini-shiki-1.26.1.tgz", + "integrity": "sha512-gHFUvv9f1fU2Piou/5Y7Sx5moYxcERbC7CXc6rkDLQTUBg5Dgg9L4u29/nHqfoQ3Y9R0h0BcOhd14uOEZIBP7Q==", "dev": true, + "license": "MIT", "dependencies": { - "@shikijs/engine-oniguruma": "^1.24.0", - "@shikijs/types": "^1.24.0", - "@shikijs/vscode-textmate": "^9.3.0" + "@shikijs/engine-oniguruma": "^1.26.1", + "@shikijs/types": "^1.26.1", + "@shikijs/vscode-textmate": "^10.0.1" } }, "node_modules/@humanwhocodes/config-array": { @@ -666,6 +663,7 @@ "integrity": "sha512-DZLEEqFWQFiyK6h5YIeynKx7JlvCYWL0cImfSRXZ9l4Sg2efkFGTuFf6vzXjK1cq6IYkU+Eg/JizXw+TD2vRNw==", "deprecated": "Use @eslint/config-array instead", "dev": true, + "license": "Apache-2.0", "dependencies": { "@humanwhocodes/object-schema": "^2.0.3", "debug": "^4.3.1", @@ -675,11 +673,36 @@ "node": ">=10.10.0" } }, + "node_modules/@humanwhocodes/config-array/node_modules/brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "dev": true, + "license": "MIT", + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "node_modules/@humanwhocodes/config-array/node_modules/minimatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "dev": true, + "license": "ISC", + "dependencies": { + "brace-expansion": "^1.1.7" + }, + "engines": { + "node": "*" + } + }, "node_modules/@humanwhocodes/module-importer": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/@humanwhocodes/module-importer/-/module-importer-1.0.1.tgz", "integrity": "sha512-bxveV4V8v5Yb4ncFTT3rPSgZBOpCkjfK0y4oVVVJwIuDVBRMDXrPyXRL988i5ap9m9bnyEEjWfm5WkBmtffLfA==", "dev": true, + "license": "Apache-2.0", "engines": { "node": ">=12.22" }, @@ -693,13 +716,15 @@ "resolved": "https://registry.npmjs.org/@humanwhocodes/object-schema/-/object-schema-2.0.3.tgz", "integrity": "sha512-93zYdMES/c1D69yZiKDBj0V24vqNzB/koF26KPaagAfd3P/4gUlh3Dys5ogAK+Exi9QyzlD8x/08Zt7wIKcDcA==", "deprecated": "Use @eslint/object-schema instead", - "dev": true + "dev": true, + "license": "BSD-3-Clause" }, "node_modules/@isaacs/cliui": { "version": "8.0.2", "resolved": "https://registry.npmjs.org/@isaacs/cliui/-/cliui-8.0.2.tgz", "integrity": "sha512-O8jcjabXaleOG9DQ0+ARXWZBTfnP4WNAqzuiJK7ll44AmxGKv/J2M4TPjxjY3znBCfvBXFzucm1twdyFybFqEA==", "dev": true, + "license": "ISC", "dependencies": { "string-width": "^5.1.2", "string-width-cjs": "npm:string-width@^4.2.0", @@ -713,10 +738,11 @@ } }, "node_modules/@isaacs/cliui/node_modules/ansi-regex": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.0.1.tgz", - "integrity": "sha512-n5M855fKb2SsfMIiFFoVrABHJC8QtHwVx+mHWP3QcEqBHYienj5dHSgjbxtC0WEZXYt4wcD6zrQElDPhFuZgfA==", + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.1.0.tgz", + "integrity": "sha512-7HSX4QQb4CspciLpVFwyRe79O3xsIZDDLER21kERQ71oaPodF8jL725AgJMFAYbooIqolJoRLuM81SpeUkpkvA==", "dev": true, + "license": "MIT", "engines": { "node": ">=12" }, @@ -729,6 +755,7 @@ "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-6.2.1.tgz", "integrity": "sha512-bN798gFfQX+viw3R7yrGWRqnrN2oRkEkUjjl4JNn4E8GxxbjtG3FbrEIIY3l8/hrwUwIeCZvi4QuOTP4MErVug==", "dev": true, + "license": "MIT", "engines": { "node": ">=12" }, @@ -740,13 +767,15 @@ "version": "9.2.2", "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-9.2.2.tgz", "integrity": "sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/@isaacs/cliui/node_modules/string-width": { "version": "5.1.2", "resolved": "https://registry.npmjs.org/string-width/-/string-width-5.1.2.tgz", "integrity": "sha512-HnLOCR3vjcY8beoNLtcjZ5/nxn2afmME6lhrDrebokqMap+XbeW8n9TXpPDOqdGK5qcI3oT0GKTW6wC7EMiVqA==", "dev": true, + "license": "MIT", "dependencies": { "eastasianwidth": "^0.2.0", "emoji-regex": "^9.2.2", @@ -764,6 +793,7 @@ "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.1.0.tgz", "integrity": "sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==", "dev": true, + "license": "MIT", "dependencies": { "ansi-regex": "^6.0.1" }, @@ -779,6 +809,7 @@ "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-8.1.0.tgz", "integrity": "sha512-si7QWI6zUMq56bESFvagtmzMdGOtoxfR+Sez11Mobfc7tm+VkUckk9bW2UeffTGVUbOksxmSw0AA2gs8g71NCQ==", "dev": true, + "license": "MIT", "dependencies": { "ansi-styles": "^6.1.0", "string-width": "^5.0.1", @@ -796,6 +827,7 @@ "resolved": "https://registry.npmjs.org/@istanbuljs/schema/-/schema-0.1.3.tgz", "integrity": "sha512-ZXRY4jNvVgSVQ8DL3LTcakaAtXwTVUxE81hslsyD2AtoXW/wVob10HkOJ1X/pAlcI7D+2YoZKg5do8G/w6RYgA==", "dev": true, + "license": "MIT", "engines": { "node": ">=8" } @@ -805,6 +837,7 @@ "resolved": "https://registry.npmjs.org/@jest/schemas/-/schemas-29.6.3.tgz", "integrity": "sha512-mo5j5X+jIZmJQveBKeS/clAueipV7KgiX1vMgCxam1RNYiqE1w62n0/tJJnHtjW8ZHcQco5gY85jA3mi0L+nSA==", "dev": true, + "license": "MIT", "dependencies": { "@sinclair/typebox": "^0.27.8" }, @@ -813,10 +846,11 @@ } }, "node_modules/@jridgewell/gen-mapping": { - "version": "0.3.5", - "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.5.tgz", - "integrity": "sha512-IzL8ZoEDIBRWEzlCcRhOaCupYyN5gdIK+Q6fbFdPDg6HqX6jpkItn7DFIpW9LQzXG6Df9sA7+OKnq0qlz/GaQg==", + "version": "0.3.8", + "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.8.tgz", + "integrity": "sha512-imAbBGkb+ebQyxKgzv5Hu2nmROxoDOXHh80evxdoXNOrvAnVx7zimzc1Oo5h9RlfV4vPXaE2iM5pOFbvOCClWA==", "dev": true, + "license": "MIT", "dependencies": { "@jridgewell/set-array": "^1.2.1", "@jridgewell/sourcemap-codec": "^1.4.10", @@ -831,6 +865,7 @@ "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.2.tgz", "integrity": "sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw==", "dev": true, + "license": "MIT", "engines": { "node": ">=6.0.0" } @@ -840,21 +875,24 @@ "resolved": "https://registry.npmjs.org/@jridgewell/set-array/-/set-array-1.2.1.tgz", "integrity": "sha512-R8gLRTZeyp03ymzP/6Lil/28tGeGEzhx1q2k703KGWRAI1VdvPIXdG70VJc2pAMw3NA6JKL5hhFu1sJX0Mnn/A==", "dev": true, + "license": "MIT", "engines": { "node": ">=6.0.0" } }, "node_modules/@jridgewell/sourcemap-codec": { - "version": "1.4.15", - "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.15.tgz", - "integrity": "sha512-eF2rxCRulEKXHTRiDrDy6erMYWqNw4LPdQ8UQA4huuxaQsVeRPFl2oM8oDGxMFhJUWZf9McpLtJasDDZb/Bpeg==", - "dev": true + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.5.0.tgz", + "integrity": "sha512-gv3ZRaISU3fjPAgNsriBRqGWQL6quFx04YMPW/zD8XMLsU32mhCCbfbO6KZFLjvYpCZ8zyDEgqsgf+PwPaM7GQ==", + "dev": true, + "license": "MIT" }, "node_modules/@jridgewell/trace-mapping": { "version": "0.3.25", "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.25.tgz", "integrity": "sha512-vNk6aEwybGtawWmy/PzwnGDOjCkLWSD2wqvjGGAgOAwCGWySYXfYoxt00IJkTF+8Lb57DwOb3Aa0o9CApepiYQ==", "dev": true, + "license": "MIT", "dependencies": { "@jridgewell/resolve-uri": "^3.1.0", "@jridgewell/sourcemap-codec": "^1.4.14" @@ -865,6 +903,7 @@ "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz", "integrity": "sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==", "dev": true, + "license": "MIT", "dependencies": { "@nodelib/fs.stat": "2.0.5", "run-parallel": "^1.1.9" @@ -878,6 +917,7 @@ "resolved": "https://registry.npmjs.org/@nodelib/fs.stat/-/fs.stat-2.0.5.tgz", "integrity": "sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==", "dev": true, + "license": "MIT", "engines": { "node": ">= 8" } @@ -887,6 +927,7 @@ "resolved": "https://registry.npmjs.org/@nodelib/fs.walk/-/fs.walk-1.2.8.tgz", "integrity": "sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==", "dev": true, + "license": "MIT", "dependencies": { "@nodelib/fs.scandir": "2.1.5", "fastq": "^1.6.0" @@ -895,21 +936,12 @@ "node": ">= 8" } }, - "node_modules/@pkgjs/parseargs": { - "version": "0.11.0", - "resolved": "https://registry.npmjs.org/@pkgjs/parseargs/-/parseargs-0.11.0.tgz", - "integrity": "sha512-+1VkjdD0QBLPodGrJUeqarH8VAIvQODIbwh9XpP5Syisf7YoQgsJKPNFoqqLQlu+VQ/tVSshMR6loPMn8U+dPg==", - "dev": true, - "optional": true, - "engines": { - "node": ">=14" - } - }, "node_modules/@pkgr/core": { "version": "0.1.1", "resolved": "https://registry.npmjs.org/@pkgr/core/-/core-0.1.1.tgz", "integrity": "sha512-cq8o4cWH0ibXh9VGi5P20Tu9XF/0fFXl9EUinr9QfTM7a7p0oTA4iJRCQWppXR1Pg8dSM0UCItCkPwsk9qWWYA==", "dev": true, + "license": "MIT", "engines": { "node": "^12.20.0 || ^14.18.0 || >=16.0.0" }, @@ -918,277 +950,344 @@ } }, "node_modules/@rollup/rollup-android-arm-eabi": { - "version": "4.22.4", - "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.22.4.tgz", - "integrity": "sha512-Fxamp4aEZnfPOcGA8KSNEohV8hX7zVHOemC8jVBoBUHu5zpJK/Eu3uJwt6BMgy9fkvzxDaurgj96F/NiLukF2w==", + "version": "4.30.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.30.1.tgz", + "integrity": "sha512-pSWY+EVt3rJ9fQ3IqlrEUtXh3cGqGtPDH1FQlNZehO2yYxCHEX1SPsz1M//NXwYfbTlcKr9WObLnJX9FsS9K1Q==", "cpu": [ "arm" ], "dev": true, + "license": "MIT", "optional": true, "os": [ "android" ] }, "node_modules/@rollup/rollup-android-arm64": { - "version": "4.22.4", - "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.22.4.tgz", - "integrity": "sha512-VXoK5UMrgECLYaMuGuVTOx5kcuap1Jm8g/M83RnCHBKOqvPPmROFJGQaZhGccnsFtfXQ3XYa4/jMCJvZnbJBdA==", + "version": "4.30.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.30.1.tgz", + "integrity": "sha512-/NA2qXxE3D/BRjOJM8wQblmArQq1YoBVJjrjoTSBS09jgUisq7bqxNHJ8kjCHeV21W/9WDGwJEWSN0KQ2mtD/w==", "cpu": [ "arm64" ], "dev": true, + "license": "MIT", "optional": true, "os": [ "android" ] }, "node_modules/@rollup/rollup-darwin-arm64": { - "version": "4.22.4", - "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.22.4.tgz", - "integrity": "sha512-xMM9ORBqu81jyMKCDP+SZDhnX2QEVQzTcC6G18KlTQEzWK8r/oNZtKuZaCcHhnsa6fEeOBionoyl5JsAbE/36Q==", + "version": "4.30.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.30.1.tgz", + "integrity": "sha512-r7FQIXD7gB0WJ5mokTUgUWPl0eYIH0wnxqeSAhuIwvnnpjdVB8cRRClyKLQr7lgzjctkbp5KmswWszlwYln03Q==", "cpu": [ "arm64" ], "dev": true, + "license": "MIT", "optional": true, "os": [ "darwin" ] }, "node_modules/@rollup/rollup-darwin-x64": { - "version": "4.22.4", - "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.22.4.tgz", - "integrity": "sha512-aJJyYKQwbHuhTUrjWjxEvGnNNBCnmpHDvrb8JFDbeSH3m2XdHcxDd3jthAzvmoI8w/kSjd2y0udT+4okADsZIw==", + "version": "4.30.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.30.1.tgz", + "integrity": "sha512-x78BavIwSH6sqfP2xeI1hd1GpHL8J4W2BXcVM/5KYKoAD3nNsfitQhvWSw+TFtQTLZ9OmlF+FEInEHyubut2OA==", "cpu": [ "x64" ], "dev": true, + "license": "MIT", "optional": true, "os": [ "darwin" ] }, + "node_modules/@rollup/rollup-freebsd-arm64": { + "version": "4.30.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-arm64/-/rollup-freebsd-arm64-4.30.1.tgz", + "integrity": "sha512-HYTlUAjbO1z8ywxsDFWADfTRfTIIy/oUlfIDmlHYmjUP2QRDTzBuWXc9O4CXM+bo9qfiCclmHk1x4ogBjOUpUQ==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ] + }, + "node_modules/@rollup/rollup-freebsd-x64": { + "version": "4.30.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-x64/-/rollup-freebsd-x64-4.30.1.tgz", + "integrity": "sha512-1MEdGqogQLccphhX5myCJqeGNYTNcmTyaic9S7CG3JhwuIByJ7J05vGbZxsizQthP1xpVx7kd3o31eOogfEirw==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ] + }, "node_modules/@rollup/rollup-linux-arm-gnueabihf": { - "version": "4.22.4", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.22.4.tgz", - "integrity": "sha512-j63YtCIRAzbO+gC2L9dWXRh5BFetsv0j0va0Wi9epXDgU/XUi5dJKo4USTttVyK7fGw2nPWK0PbAvyliz50SCQ==", + "version": "4.30.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.30.1.tgz", + "integrity": "sha512-PaMRNBSqCx7K3Wc9QZkFx5+CX27WFpAMxJNiYGAXfmMIKC7jstlr32UhTgK6T07OtqR+wYlWm9IxzennjnvdJg==", "cpu": [ "arm" ], "dev": true, + "license": "MIT", "optional": true, "os": [ "linux" ] }, "node_modules/@rollup/rollup-linux-arm-musleabihf": { - "version": "4.22.4", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-musleabihf/-/rollup-linux-arm-musleabihf-4.22.4.tgz", - "integrity": "sha512-dJnWUgwWBX1YBRsuKKMOlXCzh2Wu1mlHzv20TpqEsfdZLb3WoJW2kIEsGwLkroYf24IrPAvOT/ZQ2OYMV6vlrg==", + "version": "4.30.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-musleabihf/-/rollup-linux-arm-musleabihf-4.30.1.tgz", + "integrity": "sha512-B8Rcyj9AV7ZlEFqvB5BubG5iO6ANDsRKlhIxySXcF1axXYUyqwBok+XZPgIYGBgs7LDXfWfifxhw0Ik57T0Yug==", "cpu": [ "arm" ], "dev": true, + "license": "MIT", "optional": true, "os": [ "linux" ] }, "node_modules/@rollup/rollup-linux-arm64-gnu": { - "version": "4.22.4", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.22.4.tgz", - "integrity": "sha512-AdPRoNi3NKVLolCN/Sp4F4N1d98c4SBnHMKoLuiG6RXgoZ4sllseuGioszumnPGmPM2O7qaAX/IJdeDU8f26Aw==", + "version": "4.30.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.30.1.tgz", + "integrity": "sha512-hqVyueGxAj3cBKrAI4aFHLV+h0Lv5VgWZs9CUGqr1z0fZtlADVV1YPOij6AhcK5An33EXaxnDLmJdQikcn5NEw==", "cpu": [ "arm64" ], "dev": true, + "license": "MIT", "optional": true, "os": [ "linux" ] }, "node_modules/@rollup/rollup-linux-arm64-musl": { - "version": "4.22.4", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.22.4.tgz", - "integrity": "sha512-Gl0AxBtDg8uoAn5CCqQDMqAx22Wx22pjDOjBdmG0VIWX3qUBHzYmOKh8KXHL4UpogfJ14G4wk16EQogF+v8hmA==", + "version": "4.30.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.30.1.tgz", + "integrity": "sha512-i4Ab2vnvS1AE1PyOIGp2kXni69gU2DAUVt6FSXeIqUCPIR3ZlheMW3oP2JkukDfu3PsexYRbOiJrY+yVNSk9oA==", "cpu": [ "arm64" ], "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-loongarch64-gnu": { + "version": "4.30.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-loongarch64-gnu/-/rollup-linux-loongarch64-gnu-4.30.1.tgz", + "integrity": "sha512-fARcF5g296snX0oLGkVxPmysetwUk2zmHcca+e9ObOovBR++9ZPOhqFUM61UUZ2EYpXVPN1redgqVoBB34nTpQ==", + "cpu": [ + "loong64" + ], + "dev": true, + "license": "MIT", "optional": true, "os": [ "linux" ] }, "node_modules/@rollup/rollup-linux-powerpc64le-gnu": { - "version": "4.22.4", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-powerpc64le-gnu/-/rollup-linux-powerpc64le-gnu-4.22.4.tgz", - "integrity": "sha512-3aVCK9xfWW1oGQpTsYJJPF6bfpWfhbRnhdlyhak2ZiyFLDaayz0EP5j9V1RVLAAxlmWKTDfS9wyRyY3hvhPoOg==", + "version": "4.30.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-powerpc64le-gnu/-/rollup-linux-powerpc64le-gnu-4.30.1.tgz", + "integrity": "sha512-GLrZraoO3wVT4uFXh67ElpwQY0DIygxdv0BNW9Hkm3X34wu+BkqrDrkcsIapAY+N2ATEbvak0XQ9gxZtCIA5Rw==", "cpu": [ "ppc64" ], "dev": true, + "license": "MIT", "optional": true, "os": [ "linux" ] }, "node_modules/@rollup/rollup-linux-riscv64-gnu": { - "version": "4.22.4", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.22.4.tgz", - "integrity": "sha512-ePYIir6VYnhgv2C5Xe9u+ico4t8sZWXschR6fMgoPUK31yQu7hTEJb7bCqivHECwIClJfKgE7zYsh1qTP3WHUA==", + "version": "4.30.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.30.1.tgz", + "integrity": "sha512-0WKLaAUUHKBtll0wvOmh6yh3S0wSU9+yas923JIChfxOaaBarmb/lBKPF0w/+jTVozFnOXJeRGZ8NvOxvk/jcw==", "cpu": [ "riscv64" ], "dev": true, + "license": "MIT", "optional": true, "os": [ "linux" ] }, "node_modules/@rollup/rollup-linux-s390x-gnu": { - "version": "4.22.4", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-s390x-gnu/-/rollup-linux-s390x-gnu-4.22.4.tgz", - "integrity": "sha512-GqFJ9wLlbB9daxhVlrTe61vJtEY99/xB3C8e4ULVsVfflcpmR6c8UZXjtkMA6FhNONhj2eA5Tk9uAVw5orEs4Q==", + "version": "4.30.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-s390x-gnu/-/rollup-linux-s390x-gnu-4.30.1.tgz", + "integrity": "sha512-GWFs97Ruxo5Bt+cvVTQkOJ6TIx0xJDD/bMAOXWJg8TCSTEK8RnFeOeiFTxKniTc4vMIaWvCplMAFBt9miGxgkA==", "cpu": [ "s390x" ], "dev": true, + "license": "MIT", "optional": true, "os": [ "linux" ] }, "node_modules/@rollup/rollup-linux-x64-gnu": { - "version": "4.22.4", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.22.4.tgz", - "integrity": "sha512-87v0ol2sH9GE3cLQLNEy0K/R0pz1nvg76o8M5nhMR0+Q+BBGLnb35P0fVz4CQxHYXaAOhE8HhlkaZfsdUOlHwg==", + "version": "4.30.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.30.1.tgz", + "integrity": "sha512-UtgGb7QGgXDIO+tqqJ5oZRGHsDLO8SlpE4MhqpY9Llpzi5rJMvrK6ZGhsRCST2abZdBqIBeXW6WPD5fGK5SDwg==", "cpu": [ "x64" ], "dev": true, + "license": "MIT", "optional": true, "os": [ "linux" ] }, "node_modules/@rollup/rollup-linux-x64-musl": { - "version": "4.22.4", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.22.4.tgz", - "integrity": "sha512-UV6FZMUgePDZrFjrNGIWzDo/vABebuXBhJEqrHxrGiU6HikPy0Z3LfdtciIttEUQfuDdCn8fqh7wiFJjCNwO+g==", + "version": "4.30.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.30.1.tgz", + "integrity": "sha512-V9U8Ey2UqmQsBT+xTOeMzPzwDzyXmnAoO4edZhL7INkwQcaW1Ckv3WJX3qrrp/VHaDkEWIBWhRwP47r8cdrOow==", "cpu": [ "x64" ], "dev": true, + "license": "MIT", "optional": true, "os": [ "linux" ] }, "node_modules/@rollup/rollup-win32-arm64-msvc": { - "version": "4.22.4", - "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.22.4.tgz", - "integrity": "sha512-BjI+NVVEGAXjGWYHz/vv0pBqfGoUH0IGZ0cICTn7kB9PyjrATSkX+8WkguNjWoj2qSr1im/+tTGRaY+4/PdcQw==", + "version": "4.30.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.30.1.tgz", + "integrity": "sha512-WabtHWiPaFF47W3PkHnjbmWawnX/aE57K47ZDT1BXTS5GgrBUEpvOzq0FI0V/UYzQJgdb8XlhVNH8/fwV8xDjw==", "cpu": [ "arm64" ], "dev": true, + "license": "MIT", "optional": true, "os": [ "win32" ] }, "node_modules/@rollup/rollup-win32-ia32-msvc": { - "version": "4.22.4", - "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.22.4.tgz", - "integrity": "sha512-SiWG/1TuUdPvYmzmYnmd3IEifzR61Tragkbx9D3+R8mzQqDBz8v+BvZNDlkiTtI9T15KYZhP0ehn3Dld4n9J5g==", + "version": "4.30.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.30.1.tgz", + "integrity": "sha512-pxHAU+Zv39hLUTdQQHUVHf4P+0C47y/ZloorHpzs2SXMRqeAWmGghzAhfOlzFHHwjvgokdFAhC4V+6kC1lRRfw==", "cpu": [ "ia32" ], "dev": true, + "license": "MIT", "optional": true, "os": [ "win32" ] }, "node_modules/@rollup/rollup-win32-x64-msvc": { - "version": "4.22.4", - "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.22.4.tgz", - "integrity": "sha512-j8pPKp53/lq9lMXN57S8cFz0MynJk8OWNuUnXct/9KCpKU7DgU3bYMJhwWmcqC0UU29p8Lr0/7KEVcaM6bf47Q==", + "version": "4.30.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.30.1.tgz", + "integrity": "sha512-D6qjsXGcvhTjv0kI4fU8tUuBDF/Ueee4SVX79VfNDXZa64TfCW1Slkb6Z7O1p7vflqZjcmOVdZlqf8gvJxc6og==", "cpu": [ "x64" ], "dev": true, + "license": "MIT", "optional": true, "os": [ "win32" ] }, "node_modules/@shikijs/engine-oniguruma": { - "version": "1.24.0", - "resolved": "https://registry.npmjs.org/@shikijs/engine-oniguruma/-/engine-oniguruma-1.24.0.tgz", - "integrity": "sha512-Eua0qNOL73Y82lGA4GF5P+G2+VXX9XnuUxkiUuwcxQPH4wom+tE39kZpBFXfUuwNYxHSkrSxpB1p4kyRW0moSg==", + "version": "1.26.1", + "resolved": "https://registry.npmjs.org/@shikijs/engine-oniguruma/-/engine-oniguruma-1.26.1.tgz", + "integrity": "sha512-F5XuxN1HljLuvfXv7d+mlTkV7XukC1cawdtOo+7pKgPD83CAB1Sf8uHqP3PK0u7njFH0ZhoXE1r+0JzEgAQ+kg==", "dev": true, + "license": "MIT", "dependencies": { - "@shikijs/types": "1.24.0", - "@shikijs/vscode-textmate": "^9.3.0" + "@shikijs/types": "1.26.1", + "@shikijs/vscode-textmate": "^10.0.1" } }, "node_modules/@shikijs/types": { - "version": "1.24.0", - "resolved": "https://registry.npmjs.org/@shikijs/types/-/types-1.24.0.tgz", - "integrity": "sha512-aptbEuq1Pk88DMlCe+FzXNnBZ17LCiLIGWAeCWhoFDzia5Q5Krx3DgnULLiouSdd6+LUM39XwXGppqYE0Ghtug==", + "version": "1.26.1", + "resolved": "https://registry.npmjs.org/@shikijs/types/-/types-1.26.1.tgz", + "integrity": "sha512-d4B00TKKAMaHuFYgRf3L0gwtvqpW4hVdVwKcZYbBfAAQXspgkbWqnFfuFl3MDH6gLbsubOcr+prcnsqah3ny7Q==", "dev": true, + "license": "MIT", "dependencies": { - "@shikijs/vscode-textmate": "^9.3.0", + "@shikijs/vscode-textmate": "^10.0.1", "@types/hast": "^3.0.4" } }, "node_modules/@shikijs/vscode-textmate": { - "version": "9.3.0", - "resolved": "https://registry.npmjs.org/@shikijs/vscode-textmate/-/vscode-textmate-9.3.0.tgz", - "integrity": "sha512-jn7/7ky30idSkd/O5yDBfAnVt+JJpepofP/POZ1iMOxK59cOfqIgg/Dj0eFsjOTMw+4ycJN0uhZH/Eb0bs/EUA==", - "dev": true + "version": "10.0.1", + "resolved": "https://registry.npmjs.org/@shikijs/vscode-textmate/-/vscode-textmate-10.0.1.tgz", + "integrity": "sha512-fTIQwLF+Qhuws31iw7Ncl1R3HUDtGwIipiJ9iU+UsDUwMhegFcQKQHd51nZjb7CArq0MvON8rbgCGQYWHUKAdg==", + "dev": true, + "license": "MIT" }, "node_modules/@sinclair/typebox": { "version": "0.27.8", "resolved": "https://registry.npmjs.org/@sinclair/typebox/-/typebox-0.27.8.tgz", "integrity": "sha512-+Fj43pSMwJs4KRrH/938Uf+uAELIgVBmQzg/q1YG10djyfA3TnrU8N8XzqCh/okZdszqBQTZf96idMfE5lnwTA==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/@tsconfig/node10": { "version": "1.0.11", "resolved": "https://registry.npmjs.org/@tsconfig/node10/-/node10-1.0.11.tgz", "integrity": "sha512-DcRjDCujK/kCk/cUe8Xz8ZSpm8mS3mNNpta+jGCA6USEDfktlNvm1+IuZ9eTcDbNk41BHwpHHeW+N1lKCz4zOw==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/@tsconfig/node12": { "version": "1.0.11", "resolved": "https://registry.npmjs.org/@tsconfig/node12/-/node12-1.0.11.tgz", "integrity": "sha512-cqefuRsh12pWyGsIoBKJA9luFu3mRxCA+ORZvA4ktLSzIuCUtWVxGIuXigEwO5/ywWFMZ2QEGKWvkZG1zDMTag==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/@tsconfig/node14": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/@tsconfig/node14/-/node14-1.0.3.tgz", "integrity": "sha512-ysT8mhdixWK6Hw3i1V2AeRqZ5WfXg1G43mqoYlM2nc6388Fq5jcXyr5mRsqViLx/GJYdoL0bfXD8nmF+Zn/Iow==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/@tsconfig/node16": { "version": "1.0.4", "resolved": "https://registry.npmjs.org/@tsconfig/node16/-/node16-1.0.4.tgz", "integrity": "sha512-vxhUy4J8lyeyinH7Azl1pdd43GJhZH/tP2weN8TntQblOY+A0XbT8DJk1/oCPuOOyg/Ja757rG0CgHcWC8OfMA==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/@tstv/eslint-config": { - "version": "3.2.3", - "resolved": "https://registry.npmjs.org/@tstv/eslint-config/-/eslint-config-3.2.3.tgz", - "integrity": "sha512-atMHlBvk7XBE81Pi4haskUctNY4fUyIaGsvCVprpTP6/EZKzk4+Bl5T7Ggkl6YBMcjE1Ozh0aqxfetdP71R/5w==", + "version": "3.2.4", + "resolved": "https://registry.npmjs.org/@tstv/eslint-config/-/eslint-config-3.2.4.tgz", + "integrity": "sha512-5Qhf4V5LJxyxkNr7/fbjEl0cJJljlbodPT3aROXa3utdr6NiX/jHBYvmKpXMvhz4TuoCn3ntB4eSjzGuJaQnaQ==", "dev": true, + "license": "MIT", "dependencies": { - "@typescript-eslint/eslint-plugin": "8.16.0", - "@typescript-eslint/parser": "8.16.0", + "@typescript-eslint/eslint-plugin": "8.19.0", + "@typescript-eslint/parser": "8.19.0", "eslint-config-prettier": "9.1.0", "eslint-plugin-prettier": "5.2.1", "eslint-plugin-sort-keys-fix": "1.1.2" @@ -1201,33 +1300,38 @@ "version": "2.1.5", "resolved": "https://registry.npmjs.org/@types/benchmark/-/benchmark-2.1.5.tgz", "integrity": "sha512-cKio2eFB3v7qmKcvIHLUMw/dIx/8bhWPuzpzRT4unCPRTD8VdA9Zb0afxpcxOqR4PixRS7yT42FqGS8BYL8g1w==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/@types/big.js": { "version": "6.2.2", "resolved": "https://registry.npmjs.org/@types/big.js/-/big.js-6.2.2.tgz", - "integrity": "sha512-e2cOW9YlVzFY2iScnGBBkplKsrn2CsObHQ2Hiw4V1sSyiGbgWL8IyqE3zFi1Pt5o1pdAtYkDAIsF3KKUPjdzaA==" + "integrity": "sha512-e2cOW9YlVzFY2iScnGBBkplKsrn2CsObHQ2Hiw4V1sSyiGbgWL8IyqE3zFi1Pt5o1pdAtYkDAIsF3KKUPjdzaA==", + "license": "MIT" }, "node_modules/@types/estree": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.5.tgz", - "integrity": "sha512-/kYRxGDLWzHOB7q+wtSUQlFrtcdUccpfy+X+9iMBpHK8QLLhx2wIPYuS5DYtR9Wa/YlZAbIovy7qVdB1Aq6Lyw==", - "dev": true + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.6.tgz", + "integrity": "sha512-AYnb1nQyY49te+VRAVgmzfcgjYS91mY5P0TKUDCLEM+gNnA+3T6rWITXRLYCpahpqSQbN5cE+gHpnPyXjHWxcw==", + "dev": true, + "license": "MIT" }, "node_modules/@types/hast": { "version": "3.0.4", "resolved": "https://registry.npmjs.org/@types/hast/-/hast-3.0.4.tgz", "integrity": "sha512-WPs+bbQw5aCj+x6laNGWLH3wviHtoCv/P3+otBhbOhJgG8qtpdAMlTCxLtsTWA7LH1Oh/bFCHsBn0TPS5m30EQ==", "dev": true, + "license": "MIT", "dependencies": { "@types/unist": "*" } }, "node_modules/@types/node": { - "version": "18.19.68", - "resolved": "https://registry.npmjs.org/@types/node/-/node-18.19.68.tgz", - "integrity": "sha512-QGtpFH1vB99ZmTa63K4/FU8twThj4fuVSBkGddTp7uIL/cuoLWIUSL2RcOaigBhfR+hg5pgGkBnkoOxrTVBMKw==", + "version": "18.19.70", + "resolved": "https://registry.npmjs.org/@types/node/-/node-18.19.70.tgz", + "integrity": "sha512-RE+K0+KZoEpDUbGGctnGdkrLFwi1eYKTlIHNl2Um98mUkGsm1u2Ff6Ltd0e8DktTtC98uy7rSj+hO8t/QuLoVQ==", "dev": true, + "license": "MIT", "dependencies": { "undici-types": "~5.26.4" } @@ -1236,25 +1340,28 @@ "version": "4.0.2", "resolved": "https://registry.npmjs.org/@types/parse-json/-/parse-json-4.0.2.tgz", "integrity": "sha512-dISoDXWWQwUquiKsyZ4Ng+HX2KsPL7LyHKHQwgGFEA3IaKac4Obd+h2a/a6waisAoepJlBcx9paWqjA8/HVjCw==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/@types/unist": { "version": "3.0.3", "resolved": "https://registry.npmjs.org/@types/unist/-/unist-3.0.3.tgz", "integrity": "sha512-ko/gIFJRv177XgZsZcBwnqJN5x/Gien8qNOn0D5bQU/zAzVf9Zt3BlcUiLqhV9y4ARk0GbT3tnUiPNgnTXzc/Q==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/@typescript-eslint/eslint-plugin": { - "version": "8.16.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-8.16.0.tgz", - "integrity": "sha512-5YTHKV8MYlyMI6BaEG7crQ9BhSc8RxzshOReKwZwRWN0+XvvTOm+L/UYLCYxFpfwYuAAqhxiq4yae0CMFwbL7Q==", + "version": "8.19.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-8.19.0.tgz", + "integrity": "sha512-NggSaEZCdSrFddbctrVjkVZvFC6KGfKfNK0CU7mNK/iKHGKbzT4Wmgm08dKpcZECBu9f5FypndoMyRHkdqfT1Q==", "dev": true, + "license": "MIT", "dependencies": { "@eslint-community/regexpp": "^4.10.0", - "@typescript-eslint/scope-manager": "8.16.0", - "@typescript-eslint/type-utils": "8.16.0", - "@typescript-eslint/utils": "8.16.0", - "@typescript-eslint/visitor-keys": "8.16.0", + "@typescript-eslint/scope-manager": "8.19.0", + "@typescript-eslint/type-utils": "8.19.0", + "@typescript-eslint/utils": "8.19.0", + "@typescript-eslint/visitor-keys": "8.19.0", "graphemer": "^1.4.0", "ignore": "^5.3.1", "natural-compare": "^1.4.0", @@ -1269,24 +1376,21 @@ }, "peerDependencies": { "@typescript-eslint/parser": "^8.0.0 || ^8.0.0-alpha.0", - "eslint": "^8.57.0 || ^9.0.0" - }, - "peerDependenciesMeta": { - "typescript": { - "optional": true - } + "eslint": "^8.57.0 || ^9.0.0", + "typescript": ">=4.8.4 <5.8.0" } }, "node_modules/@typescript-eslint/parser": { - "version": "8.16.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-8.16.0.tgz", - "integrity": "sha512-D7DbgGFtsqIPIFMPJwCad9Gfi/hC0PWErRRHFnaCWoEDYi5tQUDiJCTmGUbBiLzjqAck4KcXt9Ayj0CNlIrF+w==", + "version": "8.19.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-8.19.0.tgz", + "integrity": "sha512-6M8taKyOETY1TKHp0x8ndycipTVgmp4xtg5QpEZzXxDhNvvHOJi5rLRkLr8SK3jTgD5l4fTlvBiRdfsuWydxBw==", "dev": true, + "license": "MIT", "dependencies": { - "@typescript-eslint/scope-manager": "8.16.0", - "@typescript-eslint/types": "8.16.0", - "@typescript-eslint/typescript-estree": "8.16.0", - "@typescript-eslint/visitor-keys": "8.16.0", + "@typescript-eslint/scope-manager": "8.19.0", + "@typescript-eslint/types": "8.19.0", + "@typescript-eslint/typescript-estree": "8.19.0", + "@typescript-eslint/visitor-keys": "8.19.0", "debug": "^4.3.4" }, "engines": { @@ -1297,22 +1401,19 @@ "url": "https://opencollective.com/typescript-eslint" }, "peerDependencies": { - "eslint": "^8.57.0 || ^9.0.0" - }, - "peerDependenciesMeta": { - "typescript": { - "optional": true - } + "eslint": "^8.57.0 || ^9.0.0", + "typescript": ">=4.8.4 <5.8.0" } }, "node_modules/@typescript-eslint/scope-manager": { - "version": "8.16.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-8.16.0.tgz", - "integrity": "sha512-mwsZWubQvBki2t5565uxF0EYvG+FwdFb8bMtDuGQLdCCnGPrDEDvm1gtfynuKlnpzeBRqdFCkMf9jg1fnAK8sg==", + "version": "8.19.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-8.19.0.tgz", + "integrity": "sha512-hkoJiKQS3GQ13TSMEiuNmSCvhz7ujyqD1x3ShbaETATHrck+9RaDdUbt+osXaUuns9OFwrDTTrjtwsU8gJyyRA==", "dev": true, + "license": "MIT", "dependencies": { - "@typescript-eslint/types": "8.16.0", - "@typescript-eslint/visitor-keys": "8.16.0" + "@typescript-eslint/types": "8.19.0", + "@typescript-eslint/visitor-keys": "8.19.0" }, "engines": { "node": "^18.18.0 || ^20.9.0 || >=21.1.0" @@ -1323,13 +1424,14 @@ } }, "node_modules/@typescript-eslint/type-utils": { - "version": "8.16.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-8.16.0.tgz", - "integrity": "sha512-IqZHGG+g1XCWX9NyqnI/0CX5LL8/18awQqmkZSl2ynn8F76j579dByc0jhfVSnSnhf7zv76mKBQv9HQFKvDCgg==", + "version": "8.19.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-8.19.0.tgz", + "integrity": "sha512-TZs0I0OSbd5Aza4qAMpp1cdCYVnER94IziudE3JU328YUHgWu9gwiwhag+fuLeJ2LkWLXI+F/182TbG+JaBdTg==", "dev": true, + "license": "MIT", "dependencies": { - "@typescript-eslint/typescript-estree": "8.16.0", - "@typescript-eslint/utils": "8.16.0", + "@typescript-eslint/typescript-estree": "8.19.0", + "@typescript-eslint/utils": "8.19.0", "debug": "^4.3.4", "ts-api-utils": "^1.3.0" }, @@ -1341,89 +1443,62 @@ "url": "https://opencollective.com/typescript-eslint" }, "peerDependencies": { - "eslint": "^8.57.0 || ^9.0.0" - }, - "peerDependenciesMeta": { - "typescript": { - "optional": true - } + "eslint": "^8.57.0 || ^9.0.0", + "typescript": ">=4.8.4 <5.8.0" } }, "node_modules/@typescript-eslint/types": { - "version": "8.16.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-8.16.0.tgz", - "integrity": "sha512-NzrHj6thBAOSE4d9bsuRNMvk+BvaQvmY4dDglgkgGC0EW/tB3Kelnp3tAKH87GEwzoxgeQn9fNGRyFJM/xd+GQ==", + "version": "8.19.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-8.19.0.tgz", + "integrity": "sha512-8XQ4Ss7G9WX8oaYvD4OOLCjIQYgRQxO+qCiR2V2s2GxI9AUpo7riNwo6jDhKtTcaJjT8PY54j2Yb33kWtSJsmA==", "dev": true, + "license": "MIT", "engines": { - "node": "^18.18.0 || ^20.9.0 || >=21.1.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - } - }, - "node_modules/@typescript-eslint/typescript-estree": { - "version": "8.16.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-8.16.0.tgz", - "integrity": "sha512-E2+9IzzXMc1iaBy9zmo+UYvluE3TW7bCGWSF41hVWUE01o8nzr1rvOQYSxelxr6StUvRcTMe633eY8mXASMaNw==", - "dev": true, - "dependencies": { - "@typescript-eslint/types": "8.16.0", - "@typescript-eslint/visitor-keys": "8.16.0", - "debug": "^4.3.4", - "fast-glob": "^3.3.2", - "is-glob": "^4.0.3", - "minimatch": "^9.0.4", - "semver": "^7.6.0", - "ts-api-utils": "^1.3.0" - }, - "engines": { - "node": "^18.18.0 || ^20.9.0 || >=21.1.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - }, - "peerDependenciesMeta": { - "typescript": { - "optional": true - } - } - }, - "node_modules/@typescript-eslint/typescript-estree/node_modules/brace-expansion": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", - "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", - "dev": true, - "dependencies": { - "balanced-match": "^1.0.0" + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" } }, - "node_modules/@typescript-eslint/typescript-estree/node_modules/minimatch": { - "version": "9.0.5", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.5.tgz", - "integrity": "sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow==", + "node_modules/@typescript-eslint/typescript-estree": { + "version": "8.19.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-8.19.0.tgz", + "integrity": "sha512-WW9PpDaLIFW9LCbucMSdYUuGeFUz1OkWYS/5fwZwTA+l2RwlWFdJvReQqMUMBw4yJWJOfqd7An9uwut2Oj8sLw==", "dev": true, + "license": "MIT", "dependencies": { - "brace-expansion": "^2.0.1" + "@typescript-eslint/types": "8.19.0", + "@typescript-eslint/visitor-keys": "8.19.0", + "debug": "^4.3.4", + "fast-glob": "^3.3.2", + "is-glob": "^4.0.3", + "minimatch": "^9.0.4", + "semver": "^7.6.0", + "ts-api-utils": "^1.3.0" }, "engines": { - "node": ">=16 || 14 >=14.17" + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" }, "funding": { - "url": "https://github.com/sponsors/isaacs" + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "typescript": ">=4.8.4 <5.8.0" } }, "node_modules/@typescript-eslint/utils": { - "version": "8.16.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-8.16.0.tgz", - "integrity": "sha512-C1zRy/mOL8Pj157GiX4kaw7iyRLKfJXBR3L82hk5kS/GyHcOFmy4YUq/zfZti72I9wnuQtA/+xzft4wCC8PJdA==", + "version": "8.19.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-8.19.0.tgz", + "integrity": "sha512-PTBG+0oEMPH9jCZlfg07LCB2nYI0I317yyvXGfxnvGvw4SHIOuRnQ3kadyyXY6tGdChusIHIbM5zfIbp4M6tCg==", "dev": true, + "license": "MIT", "dependencies": { "@eslint-community/eslint-utils": "^4.4.0", - "@typescript-eslint/scope-manager": "8.16.0", - "@typescript-eslint/types": "8.16.0", - "@typescript-eslint/typescript-estree": "8.16.0" + "@typescript-eslint/scope-manager": "8.19.0", + "@typescript-eslint/types": "8.19.0", + "@typescript-eslint/typescript-estree": "8.19.0" }, "engines": { "node": "^18.18.0 || ^20.9.0 || >=21.1.0" @@ -1433,21 +1508,18 @@ "url": "https://opencollective.com/typescript-eslint" }, "peerDependencies": { - "eslint": "^8.57.0 || ^9.0.0" - }, - "peerDependenciesMeta": { - "typescript": { - "optional": true - } + "eslint": "^8.57.0 || ^9.0.0", + "typescript": ">=4.8.4 <5.8.0" } }, "node_modules/@typescript-eslint/visitor-keys": { - "version": "8.16.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-8.16.0.tgz", - "integrity": "sha512-pq19gbaMOmFE3CbL0ZB8J8BFCo2ckfHBfaIsaOZgBIF4EoISJIdLX5xRhd0FGB0LlHReNRuzoJoMGpTjq8F2CQ==", + "version": "8.19.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-8.19.0.tgz", + "integrity": "sha512-mCFtBbFBJDCNCWUl5y6sZSCHXw1DEFEk3c/M3nRK2a4XUB8StGFtmcEMizdjKuBzB6e/smJAAWYug3VrdLMr1w==", "dev": true, + "license": "MIT", "dependencies": { - "@typescript-eslint/types": "8.16.0", + "@typescript-eslint/types": "8.19.0", "eslint-visitor-keys": "^4.2.0" }, "engines": { @@ -1463,6 +1535,7 @@ "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-4.2.0.tgz", "integrity": "sha512-UyLnSehNt62FFhSwjZlHmeokpRK59rcz29j+F1/aDgbkbRTk7wIc9XzdoasMUbRNKDM0qQt/+BJ4BrpFeABemw==", "dev": true, + "license": "Apache-2.0", "engines": { "node": "^18.18.0 || ^20.9.0 || >=21.1.0" }, @@ -1471,16 +1544,18 @@ } }, "node_modules/@ungap/structured-clone": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/@ungap/structured-clone/-/structured-clone-1.2.0.tgz", - "integrity": "sha512-zuVdFrMJiuCDQUMCzQaD6KL28MjnqqN8XnAqiEq9PNm/hCPTSGfrXCOfwj1ow4LFb/tNymJPwsNbVePc1xFqrQ==", - "dev": true + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/@ungap/structured-clone/-/structured-clone-1.2.1.tgz", + "integrity": "sha512-fEzPV3hSkSMltkw152tJKNARhOupqbH96MZWyRjNaYZOMIzbrTeQDG+MTc6Mr2pgzFQzFxAfmhGDNP5QK++2ZA==", + "dev": true, + "license": "ISC" }, "node_modules/@vitest/coverage-v8": { "version": "1.6.0", "resolved": "https://registry.npmjs.org/@vitest/coverage-v8/-/coverage-v8-1.6.0.tgz", "integrity": "sha512-KvapcbMY/8GYIG0rlwwOKCVNRc0OL20rrhFkg/CHNzncV03TE2XWvO5w9uZYoxNiMEBacAJt3unSOiZ7svePew==", "dev": true, + "license": "MIT", "dependencies": { "@ampproject/remapping": "^2.2.1", "@bcoe/v8-coverage": "^0.2.3", @@ -1508,6 +1583,7 @@ "resolved": "https://registry.npmjs.org/@vitest/expect/-/expect-1.6.0.tgz", "integrity": "sha512-ixEvFVQjycy/oNgHjqsL6AZCDduC+tflRluaHIzKIsdbzkLn2U/iBnVeJwB6HsIjQBdfMR8Z0tRxKUsvFJEeWQ==", "dev": true, + "license": "MIT", "dependencies": { "@vitest/spy": "1.6.0", "@vitest/utils": "1.6.0", @@ -1522,6 +1598,7 @@ "resolved": "https://registry.npmjs.org/@vitest/runner/-/runner-1.6.0.tgz", "integrity": "sha512-P4xgwPjwesuBiHisAVz/LSSZtDjOTPYZVmNAnpHHSR6ONrf8eCJOFRvUwdHn30F5M1fxhqtl7QZQUk2dprIXAg==", "dev": true, + "license": "MIT", "dependencies": { "@vitest/utils": "1.6.0", "p-limit": "^5.0.0", @@ -1536,6 +1613,7 @@ "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-5.0.0.tgz", "integrity": "sha512-/Eaoq+QyLSiXQ4lyYV23f14mZRQcXnxfHrN0vCai+ak9G0pp9iEQukIIZq5NccEvwRB8PUnZT0KsOoDCINS1qQ==", "dev": true, + "license": "MIT", "dependencies": { "yocto-queue": "^1.0.0" }, @@ -1547,10 +1625,11 @@ } }, "node_modules/@vitest/runner/node_modules/yocto-queue": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-1.0.0.tgz", - "integrity": "sha512-9bnSc/HEW2uRy67wc+T8UwauLuPJVn28jb+GtJY16iiKWyvmYJRXVT4UamsAEGQfPohgr2q4Tq0sQbQlxTfi1g==", + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-1.1.1.tgz", + "integrity": "sha512-b4JR1PFR10y1mKjhHY9LaGo6tmrgjit7hxVIeAmyMw3jegXR4dhYqLaQF5zMXZxY7tLpMyJeLjr1C4rLmkVe8g==", "dev": true, + "license": "MIT", "engines": { "node": ">=12.20" }, @@ -1563,6 +1642,7 @@ "resolved": "https://registry.npmjs.org/@vitest/snapshot/-/snapshot-1.6.0.tgz", "integrity": "sha512-+Hx43f8Chus+DCmygqqfetcAZrDJwvTj0ymqjQq4CvmpKFSTVteEOBzCusu1x2tt4OJcvBflyHUE0DZSLgEMtQ==", "dev": true, + "license": "MIT", "dependencies": { "magic-string": "^0.30.5", "pathe": "^1.1.1", @@ -1577,6 +1657,7 @@ "resolved": "https://registry.npmjs.org/@vitest/spy/-/spy-1.6.0.tgz", "integrity": "sha512-leUTap6B/cqi/bQkXUu6bQV5TZPx7pmMBKBQiI0rJA8c3pB56ZsaTbREnF7CJfmvAS4V2cXIBAh/3rVwrrCYgw==", "dev": true, + "license": "MIT", "dependencies": { "tinyspy": "^2.2.0" }, @@ -1589,6 +1670,7 @@ "resolved": "https://registry.npmjs.org/@vitest/utils/-/utils-1.6.0.tgz", "integrity": "sha512-21cPiuGMoMZwiOHa2i4LXkMkMkCGzA+MVFV70jRwHo95dL4x/ts5GZhML1QWuy7yfp3WzK3lRvZi3JnXTYqrBw==", "dev": true, + "license": "MIT", "dependencies": { "diff-sequences": "^29.6.3", "estree-walker": "^3.0.3", @@ -1600,10 +1682,11 @@ } }, "node_modules/acorn": { - "version": "8.11.3", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.11.3.tgz", - "integrity": "sha512-Y9rRfJG5jcKOE0CLisYbojUjIrIEE7AGMzA/Sm4BslANhbS+cDMpgBdcPT91oJ7OuJ9hYJBx59RjbhxVnrF8Xg==", + "version": "8.14.0", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.14.0.tgz", + "integrity": "sha512-cl669nCJTZBsL97OF4kUQm5g5hC2uihk0NxY3WENAC0TYdILVkAyHymAntgxGkl7K+t0cXIrH5siy5S4XkFycA==", "dev": true, + "license": "MIT", "bin": { "acorn": "bin/acorn" }, @@ -1616,29 +1699,55 @@ "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.3.2.tgz", "integrity": "sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==", "dev": true, + "license": "MIT", "peerDependencies": { "acorn": "^6.0.0 || ^7.0.0 || ^8.0.0" } }, + "node_modules/acorn-jsx-walk": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/acorn-jsx-walk/-/acorn-jsx-walk-2.0.0.tgz", + "integrity": "sha512-uuo6iJj4D4ygkdzd6jPtcxs8vZgDX9YFIkqczGImoypX2fQ4dVImmu3UzA4ynixCIMTrEOWW+95M2HuBaCEOVA==", + "dev": true, + "license": "MIT" + }, + "node_modules/acorn-loose": { + "version": "8.4.0", + "resolved": "https://registry.npmjs.org/acorn-loose/-/acorn-loose-8.4.0.tgz", + "integrity": "sha512-M0EUka6rb+QC4l9Z3T0nJEzNOO7JcoJlYMrBlyBCiFSXRyxjLKayd4TbQs2FDRWQU1h9FR7QVNHt+PEaoNL5rQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "acorn": "^8.11.0" + }, + "engines": { + "node": ">=0.4.0" + } + }, "node_modules/acorn-walk": { - "version": "8.3.2", - "resolved": "https://registry.npmjs.org/acorn-walk/-/acorn-walk-8.3.2.tgz", - "integrity": "sha512-cjkyv4OtNCIeqhHrfS81QWXoCBPExR/J62oyEqepVw8WaQeSqpW2uhuLPh1m9eWhDuOo/jUXVTlifvesOWp/4A==", + "version": "8.3.4", + "resolved": "https://registry.npmjs.org/acorn-walk/-/acorn-walk-8.3.4.tgz", + "integrity": "sha512-ueEepnujpqee2o5aIYnvHU6C0A42MNdsIDeqy5BydrkuC5R1ZuUFnm27EeFJGoEHJQgn3uleRvmTXaJgfXbt4g==", "dev": true, + "license": "MIT", + "dependencies": { + "acorn": "^8.11.0" + }, "engines": { "node": ">=0.4.0" } }, "node_modules/ajv": { - "version": "6.12.6", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", - "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", + "version": "8.17.1", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.17.1.tgz", + "integrity": "sha512-B/gBuNg5SiMTrPkC+A2+cW0RszwxYmn6VYxB/inlBStS5nx6xHIt/ehKRhIMhqusl7a8LjQoZnjCs5vhwxOQ1g==", "dev": true, + "license": "MIT", "dependencies": { - "fast-deep-equal": "^3.1.1", - "fast-json-stable-stringify": "^2.0.0", - "json-schema-traverse": "^0.4.1", - "uri-js": "^4.2.2" + "fast-deep-equal": "^3.1.3", + "fast-uri": "^3.0.1", + "json-schema-traverse": "^1.0.0", + "require-from-string": "^2.0.2" }, "funding": { "type": "github", @@ -1650,6 +1759,7 @@ "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-7.0.0.tgz", "integrity": "sha512-GdYO7a61mR0fOlAsvC9/rIHf7L96sBc6dEWzeOu+KAea5bZyQRPIpojrVoI4AXGJS/ycu/fBTdLrUkA4ODrvjw==", "dev": true, + "license": "MIT", "dependencies": { "environment": "^1.0.0" }, @@ -1665,6 +1775,7 @@ "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", "dev": true, + "license": "MIT", "engines": { "node": ">=8" } @@ -1674,6 +1785,7 @@ "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", "dev": true, + "license": "MIT", "dependencies": { "color-convert": "^2.0.1" }, @@ -1688,19 +1800,22 @@ "version": "4.1.3", "resolved": "https://registry.npmjs.org/arg/-/arg-4.1.3.tgz", "integrity": "sha512-58S9QDqG0Xx27YwPSt9fJxivjYl432YCwfDMfZ+71RAqUrZef7LrKQZ3LHLOwCS4FLNBplP533Zx895SeOCHvA==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/argparse": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==", - "dev": true + "dev": true, + "license": "Python-2.0" }, "node_modules/assertion-error": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/assertion-error/-/assertion-error-1.1.0.tgz", "integrity": "sha512-jgsaNduz+ndvGyFt3uSuWqvy4lCnIJiovtouQN5JZHOKCS2QuhEdbcQHFhVksz2N2U9hXJo8odG7ETyWlEeuDw==", "dev": true, + "license": "MIT", "engines": { "node": "*" } @@ -1709,13 +1824,15 @@ "version": "1.0.2", "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/benchmark": { "version": "2.1.4", "resolved": "https://registry.npmjs.org/benchmark/-/benchmark-2.1.4.tgz", "integrity": "sha512-l9MlfN4M1K/H2fbhfMy3B7vJd6AGKJVQn2h6Sg/Yx+KckoUA7ewS5Vv6TjSq18ooE1kS9hhAlQRH3AkXIh/aOQ==", "dev": true, + "license": "MIT", "dependencies": { "lodash": "^4.17.4", "platform": "^1.3.3" @@ -1725,6 +1842,7 @@ "version": "6.2.2", "resolved": "https://registry.npmjs.org/big.js/-/big.js-6.2.2.tgz", "integrity": "sha512-y/ie+Faknx7sZA5MfGA2xKlu0GDv8RWrXGsmlteyJQ2lvoKv9GBK/fpRMc2qlSoBAgNxrixICFCBefIq8WCQpQ==", + "license": "MIT", "engines": { "node": "*" }, @@ -1737,16 +1855,17 @@ "version": "3.7.2", "resolved": "https://registry.npmjs.org/bluebird/-/bluebird-3.7.2.tgz", "integrity": "sha512-XpNj6GDQzdfW+r2Wnn7xiSAd7TM3jzkxGXBGTtWKuSXv1xUV+azxAm8jdWZN06QTQk+2N2XB9jRDkvbmQmcRtg==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/brace-expansion": { - "version": "1.1.11", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", - "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", + "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", "dev": true, + "license": "MIT", "dependencies": { - "balanced-match": "^1.0.0", - "concat-map": "0.0.1" + "balanced-match": "^1.0.0" } }, "node_modules/braces": { @@ -1754,6 +1873,7 @@ "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.3.tgz", "integrity": "sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==", "dev": true, + "license": "MIT", "dependencies": { "fill-range": "^7.1.1" }, @@ -1766,6 +1886,7 @@ "resolved": "https://registry.npmjs.org/cac/-/cac-6.7.14.tgz", "integrity": "sha512-b6Ilus+c3RrdDk+JhLKUAQfzzgLEPy6wcXqS7f/xe1EETvsDP6GORG7SFuOs6cID5YkqchW/LXZbX5bc8j7ZcQ==", "dev": true, + "license": "MIT", "engines": { "node": ">=8" } @@ -1775,15 +1896,17 @@ "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz", "integrity": "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==", "dev": true, + "license": "MIT", "engines": { "node": ">=6" } }, "node_modules/chai": { - "version": "4.4.1", - "resolved": "https://registry.npmjs.org/chai/-/chai-4.4.1.tgz", - "integrity": "sha512-13sOfMv2+DWduEU+/xbun3LScLoqN17nBeTLUsmDfKdoiC1fr0n9PU4guu4AhRcOVFk/sW8LyZWHuhWtQZiF+g==", + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/chai/-/chai-4.5.0.tgz", + "integrity": "sha512-RITGBfijLkBddZvnn8jdqoTypxvqbOLYQkGGxXzeFjVHvudaPw0HNFD9x928/eUwYWd2dPCugVqspGALTZZQKw==", "dev": true, + "license": "MIT", "dependencies": { "assertion-error": "^1.1.0", "check-error": "^1.0.3", @@ -1791,7 +1914,7 @@ "get-func-name": "^2.0.2", "loupe": "^2.3.6", "pathval": "^1.1.1", - "type-detect": "^4.0.8" + "type-detect": "^4.1.0" }, "engines": { "node": ">=4" @@ -1802,6 +1925,7 @@ "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", "dev": true, + "license": "MIT", "dependencies": { "ansi-styles": "^4.1.0", "supports-color": "^7.1.0" @@ -1818,6 +1942,7 @@ "resolved": "https://registry.npmjs.org/check-error/-/check-error-1.0.3.tgz", "integrity": "sha512-iKEoDYaRmd1mxM90a2OEfWhjsjPpYPuQ+lMYsoxB126+t8fw7ySEO48nmDg5COTjxDI65/Y2OWpeEHk3ZOe8zg==", "dev": true, + "license": "MIT", "dependencies": { "get-func-name": "^2.0.2" }, @@ -1829,13 +1954,15 @@ "version": "2.0.0", "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-2.0.0.tgz", "integrity": "sha512-5tK7EtrZ0N+OLFMthtqOj4fI2Jeb88C4CAZPu25LDVUgXJ0A3Js4PMGqrn0JU1W0Mh1/Z8wZzYPxqUrXeBboCQ==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/cli-cursor": { "version": "5.0.0", "resolved": "https://registry.npmjs.org/cli-cursor/-/cli-cursor-5.0.0.tgz", "integrity": "sha512-aCj4O5wKyszjMmDT4tZj93kxyydN/K5zPWSCe6/0AV/AA1pqe5ZBIw0a2ZfPQV7lL5/yb5HsUreJ6UFAF1tEQw==", "dev": true, + "license": "MIT", "dependencies": { "restore-cursor": "^5.0.0" }, @@ -1851,6 +1978,7 @@ "resolved": "https://registry.npmjs.org/cli-truncate/-/cli-truncate-4.0.0.tgz", "integrity": "sha512-nPdaFdQ0h/GEigbPClz11D0v/ZJEwxmeVZGeMo3Z5StPtUTkA9o1lD6QwoirYiSDzbcwn2XcjwmCp68W1IS4TA==", "dev": true, + "license": "MIT", "dependencies": { "slice-ansi": "^5.0.0", "string-width": "^7.0.0" @@ -1867,6 +1995,7 @@ "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", "dev": true, + "license": "MIT", "dependencies": { "color-name": "~1.1.4" }, @@ -1878,37 +2007,53 @@ "version": "1.1.4", "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/colorette": { "version": "2.0.20", "resolved": "https://registry.npmjs.org/colorette/-/colorette-2.0.20.tgz", "integrity": "sha512-IfEDxwoWIjkeXL1eXcDiow4UbKjhLdq6/EuSVR9GMN7KVH3r9gQ83e73hsz1Nd1T3ijd5xv1wcWRYO+D6kCI2w==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/commander": { - "version": "2.20.3", - "resolved": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz", - "integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==", - "dev": true + "version": "13.0.0", + "resolved": "https://registry.npmjs.org/commander/-/commander-13.0.0.tgz", + "integrity": "sha512-oPYleIY8wmTVzkvQq10AEok6YcTC4sRUBl8F9gVuwchGVUCTbl/vhLTaQqutuuySYOsu8YTgV+OxKc/8Yvx+mQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=18" + } }, "node_modules/compare-versions": { "version": "3.6.0", "resolved": "https://registry.npmjs.org/compare-versions/-/compare-versions-3.6.0.tgz", "integrity": "sha512-W6Af2Iw1z4CB7q4uU4hv646dW9GQuBM+YpC0UvUCWSD8w90SJjp+ujJuXaEMtAXBtSqGfMPuFOVn4/+FlaqfBA==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/concat-map": { "version": "0.0.1", "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==", - "dev": true + "dev": true, + "license": "MIT" + }, + "node_modules/confbox": { + "version": "0.1.8", + "resolved": "https://registry.npmjs.org/confbox/-/confbox-0.1.8.tgz", + "integrity": "sha512-RMtmw0iFkeR4YV+fUOSucriAQNb9g8zFR52MWCtl+cCZOFRNL6zeB395vPzFhEjjn4fMxXudmELnl/KF/WrK6w==", + "dev": true, + "license": "MIT" }, "node_modules/cosmiconfig": { "version": "7.1.0", "resolved": "https://registry.npmjs.org/cosmiconfig/-/cosmiconfig-7.1.0.tgz", "integrity": "sha512-AdmX6xUzdNASswsFtmwSt7Vj8po9IuqXm0UXz7QKPuEUmPB4XyjGfaAr2PSuELMwkRMVH1EpIkX5bTZGRB3eCA==", "dev": true, + "license": "MIT", "dependencies": { "@types/parse-json": "^4.0.0", "import-fresh": "^3.2.1", @@ -1924,13 +2069,15 @@ "version": "1.1.1", "resolved": "https://registry.npmjs.org/create-require/-/create-require-1.1.1.tgz", "integrity": "sha512-dcKFX3jn0MpIaXjisoRvexIJVEKzaq7z2rZKxf+MSr9TkdmHmsU4m2lcLojrj/FHl8mk5VxMmYA+ftRkP/3oKQ==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/cross-spawn": { - "version": "7.0.3", - "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz", - "integrity": "sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==", + "version": "7.0.6", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.6.tgz", + "integrity": "sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA==", "dev": true, + "license": "MIT", "dependencies": { "path-key": "^3.1.0", "shebang-command": "^2.0.0", @@ -1945,6 +2092,7 @@ "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.0.tgz", "integrity": "sha512-6WTZ/IxCY/T6BALoZHaE4ctp9xm+Z5kY/pzYaCHRFeyVhojxlrm+46y68HA6hr0TcwEssoxNiDEUJQjfPZ/RYA==", "dev": true, + "license": "MIT", "dependencies": { "ms": "^2.1.3" }, @@ -1958,10 +2106,11 @@ } }, "node_modules/deep-eql": { - "version": "4.1.3", - "resolved": "https://registry.npmjs.org/deep-eql/-/deep-eql-4.1.3.tgz", - "integrity": "sha512-WaEtAOpRA1MQ0eohqZjpGD8zdI0Ovsm8mmFhaDN8dvDZzyoUMcYDnf5Y6iu7HTXxf8JDS23qWa4a+hKCDyOPzw==", + "version": "4.1.4", + "resolved": "https://registry.npmjs.org/deep-eql/-/deep-eql-4.1.4.tgz", + "integrity": "sha512-SUwdGfqdKOwxCPeVYjwSyRpJ7Z+fhpwIAtmCUdZIWZ/YP5R9WAsyuSgpLVDi9bjWoN2LXHNss/dk3urXtdQxGg==", "dev": true, + "license": "MIT", "dependencies": { "type-detect": "^4.0.0" }, @@ -1973,13 +2122,67 @@ "version": "0.1.4", "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.4.tgz", "integrity": "sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==", - "dev": true + "dev": true, + "license": "MIT" + }, + "node_modules/dependency-cruiser": { + "version": "16.9.0", + "resolved": "https://registry.npmjs.org/dependency-cruiser/-/dependency-cruiser-16.9.0.tgz", + "integrity": "sha512-Gc/xHNOBq1nk5i7FPCuexCD0m2OXB/WEfiSHfNYQaQaHZiZltnl5Ixp/ZG38Jvi8aEhKBQTHV4Aw6gmR7rWlOw==", + "dev": true, + "license": "MIT", + "dependencies": { + "acorn": "^8.14.0", + "acorn-jsx": "^5.3.2", + "acorn-jsx-walk": "^2.0.0", + "acorn-loose": "^8.4.0", + "acorn-walk": "^8.3.4", + "ajv": "^8.17.1", + "commander": "^13.0.0", + "enhanced-resolve": "^5.18.0", + "ignore": "^7.0.0", + "interpret": "^3.1.1", + "is-installed-globally": "^1.0.0", + "json5": "^2.2.3", + "memoize": "^10.0.0", + "picocolors": "^1.1.1", + "picomatch": "^4.0.2", + "prompts": "^2.4.2", + "rechoir": "^0.8.0", + "safe-regex": "^2.1.1", + "semver": "^7.6.3", + "teamcity-service-messages": "^0.1.14", + "tsconfig-paths-webpack-plugin": "^4.2.0", + "watskeburt": "^4.2.2" + }, + "bin": { + "depcruise": "bin/dependency-cruise.mjs", + "depcruise-baseline": "bin/depcruise-baseline.mjs", + "depcruise-fmt": "bin/depcruise-fmt.mjs", + "depcruise-wrap-stream-in-html": "bin/wrap-stream-in-html.mjs", + "dependency-cruise": "bin/dependency-cruise.mjs", + "dependency-cruiser": "bin/dependency-cruise.mjs" + }, + "engines": { + "node": "^18.17||>=20" + } + }, + "node_modules/dependency-cruiser/node_modules/ignore": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/ignore/-/ignore-7.0.0.tgz", + "integrity": "sha512-lcX8PNQygAa22u/0BysEY8VhaFRzlOkvdlKczDPnJvrkJD1EuqzEky5VYYKM2iySIuaVIDv9N190DfSreSLw2A==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 4" + } }, "node_modules/diff": { "version": "4.0.2", "resolved": "https://registry.npmjs.org/diff/-/diff-4.0.2.tgz", "integrity": "sha512-58lmxKSA4BNyLz+HHMUzlOEpg09FV+ev6ZMe3vJihgdxzgcwZ8VoEEPmALCZG9LmqfVoNMMKpttIYTVG6uDY7A==", "dev": true, + "license": "BSD-3-Clause", "engines": { "node": ">=0.3.1" } @@ -1989,6 +2192,7 @@ "resolved": "https://registry.npmjs.org/diff-sequences/-/diff-sequences-29.6.3.tgz", "integrity": "sha512-EjePK1srD3P08o2j4f0ExnylqRs5B9tJjcp9t1krH2qRi8CCdsYfwe9JgSLurFBWwq4uOlipzfk5fHNvwFKr8Q==", "dev": true, + "license": "MIT", "engines": { "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } @@ -1998,6 +2202,7 @@ "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-3.0.0.tgz", "integrity": "sha512-yS+Q5i3hBf7GBkd4KG8a7eBNNWNGLTaEwwYWUijIYM7zrlYDM0BFXHjjPWlWZ1Rg7UaddZeIDmi9jF3HmqiQ2w==", "dev": true, + "license": "Apache-2.0", "dependencies": { "esutils": "^2.0.2" }, @@ -2009,19 +2214,36 @@ "version": "0.2.0", "resolved": "https://registry.npmjs.org/eastasianwidth/-/eastasianwidth-0.2.0.tgz", "integrity": "sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/emoji-regex": { "version": "10.4.0", "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-10.4.0.tgz", "integrity": "sha512-EC+0oUMY1Rqm4O6LLrgjtYDvcVYTy7chDnM4Q7030tP4Kwj3u/pR6gP9ygnp2CJMK5Gq+9Q2oqmrFJAz01DXjw==", - "dev": true + "dev": true, + "license": "MIT" + }, + "node_modules/enhanced-resolve": { + "version": "5.18.0", + "resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-5.18.0.tgz", + "integrity": "sha512-0/r0MySGYG8YqlayBZ6MuCfECmHFdJ5qyPh8s8wa5Hnm6SaFLSK1VYCbj+NKp090Nm1caZhD+QTnmxO7esYGyQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "graceful-fs": "^4.2.4", + "tapable": "^2.2.0" + }, + "engines": { + "node": ">=10.13.0" + } }, "node_modules/entities": { "version": "4.5.0", "resolved": "https://registry.npmjs.org/entities/-/entities-4.5.0.tgz", "integrity": "sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw==", "dev": true, + "license": "BSD-2-Clause", "engines": { "node": ">=0.12" }, @@ -2034,6 +2256,7 @@ "resolved": "https://registry.npmjs.org/environment/-/environment-1.1.0.tgz", "integrity": "sha512-xUtoPkMggbz0MPyPiIWr1Kp4aeWJjDZ6SMvURhimjdZgsRuDplF5/s9hcgGhyXMhs+6vpnuoiZ2kFiu3FMnS8Q==", "dev": true, + "license": "MIT", "engines": { "node": ">=18" }, @@ -2046,6 +2269,7 @@ "resolved": "https://registry.npmjs.org/error-ex/-/error-ex-1.3.2.tgz", "integrity": "sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g==", "dev": true, + "license": "MIT", "dependencies": { "is-arrayish": "^0.2.1" } @@ -2056,6 +2280,7 @@ "integrity": "sha512-mg3OPMV4hXywwpoDxu3Qda5xCKQi+vCTZq8S9J/EpkhB2HzKXq4SNFZE3+NK93JYxc8VMSep+lOUSC/RVKaBqw==", "dev": true, "hasInstallScript": true, + "license": "MIT", "bin": { "esbuild": "bin/esbuild" }, @@ -2093,6 +2318,7 @@ "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz", "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==", "dev": true, + "license": "MIT", "engines": { "node": ">=10" }, @@ -2104,7 +2330,9 @@ "version": "8.57.1", "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.57.1.tgz", "integrity": "sha512-ypowyDxpVSYpkXr9WPv2PAZCtNip1Mv5KTW0SCurXv/9iOpcrH9PaqUElksqEB6pChqHGDRCFTyrZlGhnLNGiA==", + "deprecated": "This version is no longer supported. Please see https://eslint.org/version-support for other options.", "dev": true, + "license": "MIT", "dependencies": { "@eslint-community/eslint-utils": "^4.2.0", "@eslint-community/regexpp": "^4.6.1", @@ -2160,6 +2388,7 @@ "resolved": "https://registry.npmjs.org/eslint-config-prettier/-/eslint-config-prettier-9.1.0.tgz", "integrity": "sha512-NSWl5BFQWEPi1j4TjVNItzYV7dZXZ+wP6I6ZhrBGpChQhZRUaElihE9uRRkcbRnNb76UMKDF3r+WTmNcGPKsqw==", "dev": true, + "license": "MIT", "bin": { "eslint-config-prettier": "bin/cli.js" }, @@ -2172,6 +2401,7 @@ "resolved": "https://registry.npmjs.org/eslint-plugin-prettier/-/eslint-plugin-prettier-5.2.1.tgz", "integrity": "sha512-gH3iR3g4JfF+yYPaJYkN7jEl9QbweL/YfkoRlNnuIEHEz1vHVlCmWOS+eGGiRuzHQXdJFCOTxRgvju9b8VUmrw==", "dev": true, + "license": "MIT", "dependencies": { "prettier-linter-helpers": "^1.0.0", "synckit": "^0.9.1" @@ -2202,6 +2432,7 @@ "resolved": "https://registry.npmjs.org/eslint-plugin-sort-keys-fix/-/eslint-plugin-sort-keys-fix-1.1.2.tgz", "integrity": "sha512-DNPHFGCA0/hZIsfODbeLZqaGY/+q3vgtshF85r+YWDNCQ2apd9PNs/zL6ttKm0nD1IFwvxyg3YOTI7FHl4unrw==", "dev": true, + "license": "ISC", "dependencies": { "espree": "^6.1.2", "esutils": "^2.0.2", @@ -2217,6 +2448,7 @@ "resolved": "https://registry.npmjs.org/acorn/-/acorn-7.4.1.tgz", "integrity": "sha512-nQyp0o1/mNdbTO1PO6kHkwSrmgZ0MT/jCCpNiwbUjGoRN4dlBhqJtoQuCnEOKzgTVwg0ZWiCoQy6SxMebQVh8A==", "dev": true, + "license": "MIT", "bin": { "acorn": "bin/acorn" }, @@ -2229,6 +2461,7 @@ "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-1.3.0.tgz", "integrity": "sha512-6J72N8UNa462wa/KFODt/PJ3IU60SDpC3QXC1Hjc1BXXpfL2C9R5+AU7jhe0F6GREqVMh4Juu+NY7xn+6dipUQ==", "dev": true, + "license": "Apache-2.0", "engines": { "node": ">=4" } @@ -2238,6 +2471,7 @@ "resolved": "https://registry.npmjs.org/espree/-/espree-6.2.1.tgz", "integrity": "sha512-ysCxRQY3WaXJz9tdbWOwuWr5Y/XrPTGX9Kiz3yoUXwW0VZ4w30HTkQLaGx/+ttFjF8i+ACbArnB4ce68a9m5hw==", "dev": true, + "license": "BSD-2-Clause", "dependencies": { "acorn": "^7.1.1", "acorn-jsx": "^5.2.0", @@ -2252,6 +2486,7 @@ "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-7.2.2.tgz", "integrity": "sha512-dOt21O7lTMhDM+X9mB4GX+DZrZtCUJPL/wlcTqxyrx5IvO0IYtILdtrQGQp+8n5S0gwSVmOf9NQrjMOgfQZlIg==", "dev": true, + "license": "BSD-2-Clause", "dependencies": { "esrecurse": "^4.3.0", "estraverse": "^5.2.0" @@ -2268,6 +2503,7 @@ "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.4.3.tgz", "integrity": "sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag==", "dev": true, + "license": "Apache-2.0", "engines": { "node": "^12.22.0 || ^14.17.0 || >=16.0.0" }, @@ -2275,11 +2511,60 @@ "url": "https://opencollective.com/eslint" } }, + "node_modules/eslint/node_modules/ajv": { + "version": "6.12.6", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", + "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", + "dev": true, + "license": "MIT", + "dependencies": { + "fast-deep-equal": "^3.1.1", + "fast-json-stable-stringify": "^2.0.0", + "json-schema-traverse": "^0.4.1", + "uri-js": "^4.2.2" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/epoberezkin" + } + }, + "node_modules/eslint/node_modules/brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "dev": true, + "license": "MIT", + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "node_modules/eslint/node_modules/json-schema-traverse": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", + "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", + "dev": true, + "license": "MIT" + }, + "node_modules/eslint/node_modules/minimatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "dev": true, + "license": "ISC", + "dependencies": { + "brace-expansion": "^1.1.7" + }, + "engines": { + "node": "*" + } + }, "node_modules/espree": { "version": "9.6.1", "resolved": "https://registry.npmjs.org/espree/-/espree-9.6.1.tgz", "integrity": "sha512-oruZaFkjorTpF32kDSI5/75ViwGeZginGGy2NoOSg3Q9bnwlnmDm4HLnkl0RE3n+njDXR037aY1+x58Z/zFdwQ==", "dev": true, + "license": "BSD-2-Clause", "dependencies": { "acorn": "^8.9.0", "acorn-jsx": "^5.3.2", @@ -2293,10 +2578,11 @@ } }, "node_modules/esquery": { - "version": "1.5.0", - "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.5.0.tgz", - "integrity": "sha512-YQLXUplAwJgCydQ78IMJywZCceoqk1oH01OERdSAJc/7U2AylwjhSCLDEtqwg811idIS/9fIU5GjG73IgjKMVg==", + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.6.0.tgz", + "integrity": "sha512-ca9pw9fomFcKPvFLXhBKUK90ZvGibiGOvRJNbjljY7s7uq/5YO4BOzcYtJqExdx99rF6aAcnRxHmcUHcz6sQsg==", "dev": true, + "license": "BSD-3-Clause", "dependencies": { "estraverse": "^5.1.0" }, @@ -2309,6 +2595,7 @@ "resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.3.0.tgz", "integrity": "sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==", "dev": true, + "license": "BSD-2-Clause", "dependencies": { "estraverse": "^5.2.0" }, @@ -2321,6 +2608,7 @@ "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz", "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==", "dev": true, + "license": "BSD-2-Clause", "engines": { "node": ">=4.0" } @@ -2330,6 +2618,7 @@ "resolved": "https://registry.npmjs.org/estree-walker/-/estree-walker-3.0.3.tgz", "integrity": "sha512-7RUKfXgSMMkzt6ZuXmqapOurLGPPfgj6l9uRZ7lRGolvk0y2yocc35LdcxKC5PQZdn2DMqioAQ2NoWcrTKmm6g==", "dev": true, + "license": "MIT", "dependencies": { "@types/estree": "^1.0.0" } @@ -2339,6 +2628,7 @@ "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz", "integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==", "dev": true, + "license": "BSD-2-Clause", "engines": { "node": ">=0.10.0" } @@ -2347,13 +2637,15 @@ "version": "5.0.1", "resolved": "https://registry.npmjs.org/eventemitter3/-/eventemitter3-5.0.1.tgz", "integrity": "sha512-GWkBvjiSZK87ELrYOSESUYeVIc9mvLLf/nXalMOS5dYrgZq9o5OVkbZAVM06CVxYsCwH9BDZFPlQTlPA1j4ahA==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/execa": { "version": "8.0.1", "resolved": "https://registry.npmjs.org/execa/-/execa-8.0.1.tgz", "integrity": "sha512-VyhnebXciFV2DESc+p6B+y0LjSm0krU4OgJN44qFAhBY0TJ+1V61tYD2+wHusZ6F9n5K+vl8k0sTy7PEfV4qpg==", "dev": true, + "license": "MIT", "dependencies": { "cross-spawn": "^7.0.3", "get-stream": "^8.0.1", @@ -2376,25 +2668,28 @@ "version": "3.1.3", "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/fast-diff": { "version": "1.3.0", "resolved": "https://registry.npmjs.org/fast-diff/-/fast-diff-1.3.0.tgz", "integrity": "sha512-VxPP4NqbUjj6MaAOafWeUn2cXWLcCtljklUtZf0Ind4XQ+QPtmA0b18zZy0jIQx+ExRVCR/ZQpBmik5lXshNsw==", - "dev": true + "dev": true, + "license": "Apache-2.0" }, "node_modules/fast-glob": { - "version": "3.3.2", - "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.3.2.tgz", - "integrity": "sha512-oX2ruAFQwf/Orj8m737Y5adxDQO0LAB7/S5MnxCdTNDd4p6BsyIVsv9JQsATbTSq8KHRpLwIHbVlUNatxd+1Ow==", + "version": "3.3.3", + "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.3.3.tgz", + "integrity": "sha512-7MptL8U0cqcFdzIzwOTHoilX9x5BrNqye7Z/LuC7kCMRio1EMSyqRK3BEAUD7sXRq4iT4AzTVuZdhgQ2TCvYLg==", "dev": true, + "license": "MIT", "dependencies": { "@nodelib/fs.stat": "^2.0.2", "@nodelib/fs.walk": "^1.2.3", "glob-parent": "^5.1.2", "merge2": "^1.3.0", - "micromatch": "^4.0.4" + "micromatch": "^4.0.8" }, "engines": { "node": ">=8.6.0" @@ -2405,6 +2700,7 @@ "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", "dev": true, + "license": "ISC", "dependencies": { "is-glob": "^4.0.1" }, @@ -2416,19 +2712,39 @@ "version": "2.1.0", "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz", "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/fast-levenshtein": { "version": "2.0.6", "resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz", "integrity": "sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==", - "dev": true + "dev": true, + "license": "MIT" + }, + "node_modules/fast-uri": { + "version": "3.0.5", + "resolved": "https://registry.npmjs.org/fast-uri/-/fast-uri-3.0.5.tgz", + "integrity": "sha512-5JnBCWpFlMo0a3ciDy/JckMzzv1U9coZrIhedq+HXxxUfDTAiS0LA8OKVao4G9BxmCVck/jtA5r3KAtRWEyD8Q==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/fastify" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/fastify" + } + ], + "license": "BSD-3-Clause" }, "node_modules/fastq": { - "version": "1.17.1", - "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.17.1.tgz", - "integrity": "sha512-sRVD3lWVIXWg6By68ZN7vho9a1pQcN/WBFaAAsDDFzlJjvoGx0P8z7V1t72grFJfJhu3YPZBuu25f7Kaw2jN1w==", + "version": "1.18.0", + "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.18.0.tgz", + "integrity": "sha512-QKHXPW0hD8g4UET03SdOdunzSouc9N4AuHdsX8XNcTsuz+yYFILVNIX4l9yHABMhiEI9Db0JTTIpu0wB+Y1QQw==", "dev": true, + "license": "ISC", "dependencies": { "reusify": "^1.0.4" } @@ -2438,6 +2754,7 @@ "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-6.0.1.tgz", "integrity": "sha512-7Gps/XWymbLk2QLYK4NzpMOrYjMhdIxXuIvy2QBsLE6ljuodKvdkWs/cpyJJ3CVIVpH0Oi1Hvg1ovbMzLdFBBg==", "dev": true, + "license": "MIT", "dependencies": { "flat-cache": "^3.0.4" }, @@ -2450,6 +2767,7 @@ "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.1.1.tgz", "integrity": "sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==", "dev": true, + "license": "MIT", "dependencies": { "to-regex-range": "^5.0.1" }, @@ -2462,6 +2780,7 @@ "resolved": "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz", "integrity": "sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==", "dev": true, + "license": "MIT", "dependencies": { "locate-path": "^6.0.0", "path-exists": "^4.0.0" @@ -2478,6 +2797,7 @@ "resolved": "https://registry.npmjs.org/find-versions/-/find-versions-4.0.0.tgz", "integrity": "sha512-wgpWy002tA+wgmO27buH/9KzyEOQnKsG/R0yrcjPT9BOFm0zRBVQbZ95nRGXWMywS8YR5knRbpohio0bcJABxQ==", "dev": true, + "license": "MIT", "dependencies": { "semver-regex": "^3.1.2" }, @@ -2493,6 +2813,7 @@ "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-3.2.0.tgz", "integrity": "sha512-CYcENa+FtcUKLmhhqyctpclsq7QF38pKjZHsGNiSQF5r4FtoKDWabFDl3hzaEQMvT1LHEysw5twgLvpYYb4vbw==", "dev": true, + "license": "MIT", "dependencies": { "flatted": "^3.2.9", "keyv": "^4.5.3", @@ -2502,11 +2823,24 @@ "node": "^10.12.0 || >=12.0.0" } }, + "node_modules/flat-cache/node_modules/brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "dev": true, + "license": "MIT", + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, "node_modules/flat-cache/node_modules/glob": { "version": "7.2.3", "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", + "deprecated": "Glob versions prior to v9 are no longer supported", "dev": true, + "license": "ISC", "dependencies": { "fs.realpath": "^1.0.0", "inflight": "^1.0.4", @@ -2522,11 +2856,26 @@ "url": "https://github.com/sponsors/isaacs" } }, + "node_modules/flat-cache/node_modules/minimatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "dev": true, + "license": "ISC", + "dependencies": { + "brace-expansion": "^1.1.7" + }, + "engines": { + "node": "*" + } + }, "node_modules/flat-cache/node_modules/rimraf": { "version": "3.0.2", "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==", + "deprecated": "Rimraf versions prior to v4 are no longer supported", "dev": true, + "license": "ISC", "dependencies": { "glob": "^7.1.3" }, @@ -2538,16 +2887,18 @@ } }, "node_modules/flatted": { - "version": "3.3.1", - "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.3.1.tgz", - "integrity": "sha512-X8cqMLLie7KsNUDSdzeN8FYK9rEt4Dt67OsG/DNGnYTSDBG4uFAJFBnUeiV+zCVAvwFy56IjM9sH51jVaEhNxw==", - "dev": true + "version": "3.3.2", + "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.3.2.tgz", + "integrity": "sha512-AiwGJM8YcNOaobumgtng+6NHuOqC3A7MixFeDafM3X9cIUM+xUXoS5Vfgf+OihAYe20fxqNM9yPBXJzRtZ/4eA==", + "dev": true, + "license": "ISC" }, "node_modules/foreground-child": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/foreground-child/-/foreground-child-3.2.1.tgz", - "integrity": "sha512-PXUUyLqrR2XCWICfv6ukppP96sdFwWbNEnfEMt7jNsISjMsvaLNinAHNDYyvkyU+SZG2BTSbT5NjG+vZslfGTA==", + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/foreground-child/-/foreground-child-3.3.0.tgz", + "integrity": "sha512-Ld2g8rrAyMYFXBhEqMz8ZAHBi4J4uS1i/CxGMDnjyFWddMXLVcDp051DZfu+t7+ab7Wv6SMqpWmyFIj5UbfFvg==", "dev": true, + "license": "ISC", "dependencies": { "cross-spawn": "^7.0.0", "signal-exit": "^4.0.1" @@ -2563,7 +2914,8 @@ "version": "1.0.0", "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", "integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==", - "dev": true + "dev": true, + "license": "ISC" }, "node_modules/fsevents": { "version": "2.3.3", @@ -2571,6 +2923,7 @@ "integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==", "dev": true, "hasInstallScript": true, + "license": "MIT", "optional": true, "os": [ "darwin" @@ -2579,11 +2932,22 @@ "node": "^8.16.0 || ^10.6.0 || >=11.0.0" } }, + "node_modules/function-bind": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz", + "integrity": "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==", + "dev": true, + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/generate-changelog": { "version": "1.8.0", "resolved": "https://registry.npmjs.org/generate-changelog/-/generate-changelog-1.8.0.tgz", "integrity": "sha512-msgpxeB75Ziyg3wGsZuPNl7c5RxChMKmYcAX5obnhUow90dBZW3nLic6nxGtst7Bpx453oS6zAIHcX7F3QVasw==", "dev": true, + "license": "MIT", "dependencies": { "bluebird": "^3.0.6", "commander": "^2.9.0", @@ -2594,11 +2958,19 @@ "generate-changelog": "bin/generate" } }, + "node_modules/generate-changelog/node_modules/commander": { + "version": "2.20.3", + "resolved": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz", + "integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==", + "dev": true, + "license": "MIT" + }, "node_modules/get-east-asian-width": { "version": "1.3.0", "resolved": "https://registry.npmjs.org/get-east-asian-width/-/get-east-asian-width-1.3.0.tgz", "integrity": "sha512-vpeMIQKxczTD/0s2CdEWHcb0eeJe6TFjxb+J5xgX7hScxqrGuyjmv4c1D4A/gelKfyox0gJJwIHF+fLjeaM8kQ==", "dev": true, + "license": "MIT", "engines": { "node": ">=18" }, @@ -2611,6 +2983,7 @@ "resolved": "https://registry.npmjs.org/get-func-name/-/get-func-name-2.0.2.tgz", "integrity": "sha512-8vXOvuE167CtIc3OyItco7N/dpRtBbYOsPsXCz7X/PMnlGjYjSGuZJgM1Y7mmew7BKf9BqvLX2tnOVy1BBUsxQ==", "dev": true, + "license": "MIT", "engines": { "node": "*" } @@ -2620,6 +2993,7 @@ "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-8.0.1.tgz", "integrity": "sha512-VaUJspBffn/LMCJVoMvSAdmscJyS1auj5Zulnn5UoYcY531UWmdwhRWkcGKnGU93m5HSXP9LP2usOryrBtQowA==", "dev": true, + "license": "MIT", "engines": { "node": ">=16" }, @@ -2631,13 +3005,15 @@ "version": "1.5.0", "resolved": "https://registry.npmjs.org/github-url-from-git/-/github-url-from-git-1.5.0.tgz", "integrity": "sha512-WWOec4aRI7YAykQ9+BHmzjyNlkfJFG8QLXnDTsLz/kZefq7qkzdfo4p6fkYYMIq1aj+gZcQs/1HQhQh3DPPxlQ==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/glob": { - "version": "11.0.0", - "resolved": "https://registry.npmjs.org/glob/-/glob-11.0.0.tgz", - "integrity": "sha512-9UiX/Bl6J2yaBbxKoEBRm4Cipxgok8kQYcOPEhScPwebu2I0HoQOuYdIO6S3hLuWoZgpDpwQZMzTFxgpkyT76g==", + "version": "11.0.1", + "resolved": "https://registry.npmjs.org/glob/-/glob-11.0.1.tgz", + "integrity": "sha512-zrQDm8XPnYEKawJScsnM0QzobJxlT/kHOOlRTio8IH/GrmxRE5fjllkzdaHclIuNjUQTJYH2xHNIGfdpJkDJUw==", "dev": true, + "license": "ISC", "dependencies": { "foreground-child": "^3.1.0", "jackspeak": "^4.0.1", @@ -2661,6 +3037,7 @@ "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-6.0.2.tgz", "integrity": "sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==", "dev": true, + "license": "ISC", "dependencies": { "is-glob": "^4.0.3" }, @@ -2668,20 +3045,12 @@ "node": ">=10.13.0" } }, - "node_modules/glob/node_modules/brace-expansion": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", - "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", - "dev": true, - "dependencies": { - "balanced-match": "^1.0.0" - } - }, "node_modules/glob/node_modules/minimatch": { "version": "10.0.1", "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-10.0.1.tgz", "integrity": "sha512-ethXTt3SGGR+95gudmqJ1eNhRO7eGEGIgYA9vnPatK4/etz2MEVDno5GMCibdMTuBMyElzIlgxMna3K94XDIDQ==", "dev": true, + "license": "ISC", "dependencies": { "brace-expansion": "^2.0.1" }, @@ -2692,11 +3061,28 @@ "url": "https://github.com/sponsors/isaacs" } }, + "node_modules/global-directory": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/global-directory/-/global-directory-4.0.1.tgz", + "integrity": "sha512-wHTUcDUoZ1H5/0iVqEudYW4/kAlN5cZ3j/bXn0Dpbizl9iaUVeWSHqiOjsgk6OW2bkLclbBjzewBz6weQ1zA2Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "ini": "4.1.1" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/globals": { "version": "13.24.0", "resolved": "https://registry.npmjs.org/globals/-/globals-13.24.0.tgz", "integrity": "sha512-AhO5QUcj8llrbG09iWhPU2B204J1xnPeL8kQmVorSsy+Sjj1sk8gIyh6cUocGmH4L0UuhAJy+hJMRA4mgA4mFQ==", "dev": true, + "license": "MIT", "dependencies": { "type-fest": "^0.20.2" }, @@ -2707,32 +3093,56 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/graceful-fs": { + "version": "4.2.11", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.11.tgz", + "integrity": "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==", + "dev": true, + "license": "ISC" + }, "node_modules/graphemer": { "version": "1.4.0", "resolved": "https://registry.npmjs.org/graphemer/-/graphemer-1.4.0.tgz", "integrity": "sha512-EtKwoO6kxCL9WO5xipiHTZlSzBm7WLT627TqC/uVRd0HKmq8NXyebnNYxDoBi7wt8eTWrUrKXCOVaFq9x1kgag==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/has-flag": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", "dev": true, + "license": "MIT", "engines": { "node": ">=8" } }, + "node_modules/hasown": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.2.tgz", + "integrity": "sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "function-bind": "^1.1.2" + }, + "engines": { + "node": ">= 0.4" + } + }, "node_modules/html-escaper": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/html-escaper/-/html-escaper-2.0.2.tgz", "integrity": "sha512-H2iMtd0I4Mt5eYiapRdIDjp+XzelXQ0tFE4JS7YFwFevXXMmOp9myNrUvCg0D6ws8iqkRPBfKHgbwig1SmlLfg==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/human-signals": { "version": "5.0.0", "resolved": "https://registry.npmjs.org/human-signals/-/human-signals-5.0.0.tgz", "integrity": "sha512-AXcZb6vzzrFAUE61HnN4mpLqd/cSIwNQjtNWR0euPm6y0iqx3G4gOXaIDdtdDwZmhwe82LA6+zinmW4UBWVePQ==", "dev": true, + "license": "Apache-2.0", "engines": { "node": ">=16.17.0" } @@ -2743,6 +3153,7 @@ "integrity": "sha512-LCqqsB0PzJQ/AlCgfrfzRe3e3+NvmefAdKQhRYpxS4u6clblBoDdzzvHi8fmxKRzvMxPY/1WZWzomPZww0Anow==", "dev": true, "hasInstallScript": true, + "license": "MIT", "dependencies": { "chalk": "^4.0.0", "ci-info": "^2.0.0", @@ -2768,10 +3179,11 @@ } }, "node_modules/ignore": { - "version": "5.3.1", - "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.3.1.tgz", - "integrity": "sha512-5Fytz/IraMjqpwfd34ke28PTVMjZjJG2MPn5t7OE4eUCUNf8BAa7b5WUS9/Qvr6mwOQS7Mk6vdsMno5he+T8Xw==", + "version": "5.3.2", + "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.3.2.tgz", + "integrity": "sha512-hsBTNUqQTDwkWtcdYI2i06Y/nUBEsNEDJKjWdigLvegy8kDuJAS8uRlpkkcQpyEXL0Z/pjDy5HBmMjRCJ2gq+g==", "dev": true, + "license": "MIT", "engines": { "node": ">= 4" } @@ -2781,6 +3193,7 @@ "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.0.tgz", "integrity": "sha512-veYYhQa+D1QBKznvhUHxb8faxlrwUnxseDAbAp457E0wLNio2bOSKnjYDhMj+YiAq61xrMGhQk9iXVk5FzgQMw==", "dev": true, + "license": "MIT", "dependencies": { "parent-module": "^1.0.0", "resolve-from": "^4.0.0" @@ -2797,6 +3210,7 @@ "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz", "integrity": "sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==", "dev": true, + "license": "MIT", "engines": { "node": ">=0.8.19" } @@ -2805,7 +3219,9 @@ "version": "1.0.6", "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", "integrity": "sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==", + "deprecated": "This module is not supported, and leaks memory. Do not use it. Check out lru-cache if you want a good and tested way to coalesce async requests by a key value, which is much more comprehensive and powerful.", "dev": true, + "license": "ISC", "dependencies": { "once": "^1.3.0", "wrappy": "1" @@ -2815,19 +3231,58 @@ "version": "2.0.4", "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", - "dev": true + "dev": true, + "license": "ISC" + }, + "node_modules/ini": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/ini/-/ini-4.1.1.tgz", + "integrity": "sha512-QQnnxNyfvmHFIsj7gkPcYymR8Jdw/o7mp5ZFihxn6h8Ci6fh3Dx4E1gPjpQEpIuPo9XVNY/ZUwh4BPMjGyL01g==", + "dev": true, + "license": "ISC", + "engines": { + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + } + }, + "node_modules/interpret": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/interpret/-/interpret-3.1.1.tgz", + "integrity": "sha512-6xwYfHbajpoF0xLW+iwLkhwgvLoZDfjYfoFNu8ftMoXINzwuymNLd9u/KmwtdT2GbR+/Cz66otEGEVVUHX9QLQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=10.13.0" + } }, "node_modules/is-arrayish": { "version": "0.2.1", "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz", "integrity": "sha512-zz06S8t0ozoDXMG+ube26zeCTNXcKIPJZJi8hBrF4idCLms4CG9QtK7qBl1boi5ODzFpjswb5JPmHCbMpjaYzg==", - "dev": true + "dev": true, + "license": "MIT" + }, + "node_modules/is-core-module": { + "version": "2.16.1", + "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.16.1.tgz", + "integrity": "sha512-UfoeMA6fIJ8wTYFEUjelnaGI67v6+N7qXJEvQuIGa99l4xsCruSYOVSQ0uPANn4dAzm8lkYPaKLrrijLq7x23w==", + "dev": true, + "license": "MIT", + "dependencies": { + "hasown": "^2.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } }, "node_modules/is-extglob": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", "integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==", "dev": true, + "license": "MIT", "engines": { "node": ">=0.10.0" } @@ -2837,6 +3292,7 @@ "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-4.0.0.tgz", "integrity": "sha512-O4L094N2/dZ7xqVdrXhh9r1KODPJpFms8B5sGdJLPy664AgvXsreZUyCQQNItZRDlYug4xStLjNp/sz3HvBowQ==", "dev": true, + "license": "MIT", "engines": { "node": ">=12" }, @@ -2849,6 +3305,7 @@ "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz", "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==", "dev": true, + "license": "MIT", "dependencies": { "is-extglob": "^2.1.1" }, @@ -2856,11 +3313,42 @@ "node": ">=0.10.0" } }, + "node_modules/is-installed-globally": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-installed-globally/-/is-installed-globally-1.0.0.tgz", + "integrity": "sha512-K55T22lfpQ63N4KEN57jZUAaAYqYHEe8veb/TycJRk9DdSCLLcovXz/mL6mOnhQaZsQGwPhuFopdQIlqGSEjiQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "global-directory": "^4.0.1", + "is-path-inside": "^4.0.0" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/is-installed-globally/node_modules/is-path-inside": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/is-path-inside/-/is-path-inside-4.0.0.tgz", + "integrity": "sha512-lJJV/5dYS+RcL8uQdBDW9c9uWFLLBNRyFhnAKXw5tVqLlKZ4RMGZKv+YQ/IA3OhD+RpbJa1LLFM1FQPGyIXvOA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/is-number": { "version": "7.0.0", "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", "dev": true, + "license": "MIT", "engines": { "node": ">=0.12.0" } @@ -2870,6 +3358,7 @@ "resolved": "https://registry.npmjs.org/is-path-inside/-/is-path-inside-3.0.3.tgz", "integrity": "sha512-Fd4gABb+ycGAmKou8eMftCupSir5lRxqf4aD/vd0cD2qc4HL07OjCeuHMr8Ro4CoMaeCKDB0/ECBOVWjTwUvPQ==", "dev": true, + "license": "MIT", "engines": { "node": ">=8" } @@ -2879,6 +3368,7 @@ "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-3.0.0.tgz", "integrity": "sha512-LnQR4bZ9IADDRSkvpqMGvt/tEJWclzklNgSw48V5EAaAeDd6qGvN8ei6k5p0tvxSR171VmGyHuTiAOfxAbr8kA==", "dev": true, + "license": "MIT", "engines": { "node": "^12.20.0 || ^14.13.1 || >=16.0.0" }, @@ -2890,13 +3380,15 @@ "version": "2.0.0", "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==", - "dev": true + "dev": true, + "license": "ISC" }, "node_modules/istanbul-lib-coverage": { "version": "3.2.2", "resolved": "https://registry.npmjs.org/istanbul-lib-coverage/-/istanbul-lib-coverage-3.2.2.tgz", "integrity": "sha512-O8dpsF+r0WV/8MNRKfnmrtCWhuKjxrq2w+jpzBL5UZKTi2LeVWnWOmWRxFlesJONmc+wLAGvKQZEOanko0LFTg==", "dev": true, + "license": "BSD-3-Clause", "engines": { "node": ">=8" } @@ -2906,6 +3398,7 @@ "resolved": "https://registry.npmjs.org/istanbul-lib-report/-/istanbul-lib-report-3.0.1.tgz", "integrity": "sha512-GCfE1mtsHGOELCU8e/Z7YWzpmybrx/+dSTfLrvY8qRmaY6zXTKWn6WQIjaAFw069icm6GVMNkgu0NzI4iPZUNw==", "dev": true, + "license": "BSD-3-Clause", "dependencies": { "istanbul-lib-coverage": "^3.0.0", "make-dir": "^4.0.0", @@ -2916,10 +3409,11 @@ } }, "node_modules/istanbul-lib-source-maps": { - "version": "5.0.4", - "resolved": "https://registry.npmjs.org/istanbul-lib-source-maps/-/istanbul-lib-source-maps-5.0.4.tgz", - "integrity": "sha512-wHOoEsNJTVltaJp8eVkm8w+GVkVNHT2YDYo53YdzQEL2gWm1hBX5cGFR9hQJtuGLebidVX7et3+dmDZrmclduw==", + "version": "5.0.6", + "resolved": "https://registry.npmjs.org/istanbul-lib-source-maps/-/istanbul-lib-source-maps-5.0.6.tgz", + "integrity": "sha512-yg2d+Em4KizZC5niWhQaIomgf5WlL4vOOjZ5xGCmF8SnPE/mDWWXgvRExdcpCgh9lLRRa1/fSYp2ymmbJ1pI+A==", "dev": true, + "license": "BSD-3-Clause", "dependencies": { "@jridgewell/trace-mapping": "^0.3.23", "debug": "^4.1.1", @@ -2934,6 +3428,7 @@ "resolved": "https://registry.npmjs.org/istanbul-reports/-/istanbul-reports-3.1.7.tgz", "integrity": "sha512-BewmUXImeuRk2YY0PVbxgKAysvhRPUQE0h5QRM++nVWyubKGV0l8qQ5op8+B2DOmwSe63Jivj0BjkPQVf8fP5g==", "dev": true, + "license": "BSD-3-Clause", "dependencies": { "html-escaper": "^2.0.0", "istanbul-lib-report": "^3.0.0" @@ -2943,10 +3438,11 @@ } }, "node_modules/jackspeak": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/jackspeak/-/jackspeak-4.0.1.tgz", - "integrity": "sha512-cub8rahkh0Q/bw1+GxP7aeSe29hHHn2V4m29nnDlvCdlgU+3UGxkZp7Z53jLUdpX3jdTO0nJZUDl3xvbWc2Xog==", + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/jackspeak/-/jackspeak-4.0.2.tgz", + "integrity": "sha512-bZsjR/iRjl1Nk1UkjGpAzLNfQtzuijhn2g+pbZb98HQ1Gk8vM9hfbxeMBP+M2/UUdwj0RqGG3mlvk2MsAqwvEw==", "dev": true, + "license": "BlueOak-1.0.0", "dependencies": { "@isaacs/cliui": "^8.0.2" }, @@ -2955,22 +3451,21 @@ }, "funding": { "url": "https://github.com/sponsors/isaacs" - }, - "optionalDependencies": { - "@pkgjs/parseargs": "^0.11.0" } }, "node_modules/js-tokens": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/js-yaml": { "version": "4.1.0", "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz", "integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==", "dev": true, + "license": "MIT", "dependencies": { "argparse": "^2.0.1" }, @@ -2982,46 +3477,69 @@ "version": "3.0.1", "resolved": "https://registry.npmjs.org/json-buffer/-/json-buffer-3.0.1.tgz", "integrity": "sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/json-parse-even-better-errors": { "version": "2.3.1", "resolved": "https://registry.npmjs.org/json-parse-even-better-errors/-/json-parse-even-better-errors-2.3.1.tgz", "integrity": "sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/json-schema-traverse": { - "version": "0.4.1", - "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", - "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", - "dev": true + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz", + "integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==", + "dev": true, + "license": "MIT" }, "node_modules/json-stable-stringify-without-jsonify": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz", "integrity": "sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw==", - "dev": true + "dev": true, + "license": "MIT" }, - "node_modules/jsonc-parser": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/jsonc-parser/-/jsonc-parser-3.2.1.tgz", - "integrity": "sha512-AilxAyFOAcK5wA1+LeaySVBrHsGQvUFCDWXKpZjzaL0PqW+xfBOttn8GNtWKFWqneyMZj41MWF9Kl6iPWLwgOA==", - "dev": true + "node_modules/json5": { + "version": "2.2.3", + "resolved": "https://registry.npmjs.org/json5/-/json5-2.2.3.tgz", + "integrity": "sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg==", + "dev": true, + "license": "MIT", + "bin": { + "json5": "lib/cli.js" + }, + "engines": { + "node": ">=6" + } }, "node_modules/keyv": { "version": "4.5.4", "resolved": "https://registry.npmjs.org/keyv/-/keyv-4.5.4.tgz", "integrity": "sha512-oxVHkHR/EJf2CNXnWxRLW6mg7JyCCUcG0DtEGmL2ctUo1PNTin1PUil+r/+4r5MpVgC/fn1kjsx7mjSujKqIpw==", "dev": true, + "license": "MIT", "dependencies": { "json-buffer": "3.0.1" } }, + "node_modules/kleur": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/kleur/-/kleur-3.0.3.tgz", + "integrity": "sha512-eTIzlVOSUR+JxdDFepEYcBMtZ9Qqdef+rnzWdRZuMbOywu5tO2w2N7rqjoANZ5k9vywhL6Br1VRjUIgTQx4E8w==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6" + } + }, "node_modules/levn": { "version": "0.4.1", "resolved": "https://registry.npmjs.org/levn/-/levn-0.4.1.tgz", "integrity": "sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==", "dev": true, + "license": "MIT", "dependencies": { "prelude-ls": "^1.2.1", "type-check": "~0.4.0" @@ -3035,6 +3553,7 @@ "resolved": "https://registry.npmjs.org/lilconfig/-/lilconfig-3.1.3.tgz", "integrity": "sha512-/vlFKAoH5Cgt3Ie+JLhRbwOsCQePABiU3tJ1egGvyQ+33R/vcwM2Zl2QR/LzjsBeItPt3oSVXapn+m4nQDvpzw==", "dev": true, + "license": "MIT", "engines": { "node": ">=14" }, @@ -3046,13 +3565,15 @@ "version": "1.2.4", "resolved": "https://registry.npmjs.org/lines-and-columns/-/lines-and-columns-1.2.4.tgz", "integrity": "sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/linkify-it": { "version": "5.0.0", "resolved": "https://registry.npmjs.org/linkify-it/-/linkify-it-5.0.0.tgz", "integrity": "sha512-5aHCbzQRADcdP+ATqnDuhhJ/MRIqDkZX5pyjFHRRysS8vZ5AbqGEoFIb6pYHPZ+L/OC2Lc+xT8uHVVR5CAK/wQ==", "dev": true, + "license": "MIT", "dependencies": { "uc.micro": "^2.0.0" } @@ -3062,6 +3583,7 @@ "resolved": "https://registry.npmjs.org/lint-staged/-/lint-staged-15.3.0.tgz", "integrity": "sha512-vHFahytLoF2enJklgtOtCtIjZrKD/LoxlaUusd5nh7dWv/dkKQJY74ndFSzxCdv7g0ueGg1ORgTSt4Y9LPZn9A==", "dev": true, + "license": "MIT", "dependencies": { "chalk": "~5.4.1", "commander": "~12.1.0", @@ -3089,6 +3611,7 @@ "resolved": "https://registry.npmjs.org/chalk/-/chalk-5.4.1.tgz", "integrity": "sha512-zgVZuo2WcZgfUEmsn6eO3kINexW8RAE4maiQ8QNs8CtpPCSyMiYsULR3HQYkm3w8FIA3SberyMJMSldGsW+U3w==", "dev": true, + "license": "MIT", "engines": { "node": "^12.17.0 || ^14.13 || >=16.0.0" }, @@ -3101,6 +3624,7 @@ "resolved": "https://registry.npmjs.org/commander/-/commander-12.1.0.tgz", "integrity": "sha512-Vw8qHK3bZM9y/P10u3Vib8o/DdkvA2OtPtZvD871QKjy74Wj1WSKFILMPRPSdUSx5RFK1arlJzEtA4PkFgnbuA==", "dev": true, + "license": "MIT", "engines": { "node": ">=18" } @@ -3110,6 +3634,7 @@ "resolved": "https://registry.npmjs.org/yaml/-/yaml-2.6.1.tgz", "integrity": "sha512-7r0XPzioN/Q9kXBro/XPnA6kznR73DHq+GXh5ON7ZozRO6aMjbmiBuKste2wslTFkC5d1dw0GooOCepZXJ2SAg==", "dev": true, + "license": "ISC", "bin": { "yaml": "bin.mjs" }, @@ -3122,6 +3647,7 @@ "resolved": "https://registry.npmjs.org/listr2/-/listr2-8.2.5.tgz", "integrity": "sha512-iyAZCeyD+c1gPyE9qpFu8af0Y+MRtmKOncdGoA2S5EY8iFq99dmmvkNnHiWo+pj0s7yH7l3KPIgee77tKpXPWQ==", "dev": true, + "license": "MIT", "dependencies": { "cli-truncate": "^4.0.0", "colorette": "^2.0.20", @@ -3135,13 +3661,14 @@ } }, "node_modules/local-pkg": { - "version": "0.5.0", - "resolved": "https://registry.npmjs.org/local-pkg/-/local-pkg-0.5.0.tgz", - "integrity": "sha512-ok6z3qlYyCDS4ZEU27HaU6x/xZa9Whf8jD4ptH5UZTQYZVYeb9bnZ3ojVhiJNLiXK1Hfc0GNbLXcmZ5plLDDBg==", + "version": "0.5.1", + "resolved": "https://registry.npmjs.org/local-pkg/-/local-pkg-0.5.1.tgz", + "integrity": "sha512-9rrA30MRRP3gBD3HTGnC6cDFpaE1kVDWxWgqWJUN0RvDNAo+Nz/9GxB+nHOH0ifbVFy0hSA1V6vFDvnx54lTEQ==", "dev": true, + "license": "MIT", "dependencies": { - "mlly": "^1.4.2", - "pkg-types": "^1.0.3" + "mlly": "^1.7.3", + "pkg-types": "^1.2.1" }, "engines": { "node": ">=14" @@ -3155,6 +3682,7 @@ "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz", "integrity": "sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==", "dev": true, + "license": "MIT", "dependencies": { "p-locate": "^5.0.0" }, @@ -3169,19 +3697,22 @@ "version": "4.17.21", "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz", "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/lodash.merge": { "version": "4.6.2", "resolved": "https://registry.npmjs.org/lodash.merge/-/lodash.merge-4.6.2.tgz", "integrity": "sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/log-update": { "version": "6.1.0", "resolved": "https://registry.npmjs.org/log-update/-/log-update-6.1.0.tgz", "integrity": "sha512-9ie8ItPR6tjY5uYJh8K/Zrv/RMZ5VOlOWvtZdEHYSTFKZfIBPQa9tOAEeAWhd+AnIneLJ22w5fjOYtoutpWq5w==", "dev": true, + "license": "MIT", "dependencies": { "ansi-escapes": "^7.0.0", "cli-cursor": "^5.0.0", @@ -3201,6 +3732,7 @@ "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.1.0.tgz", "integrity": "sha512-7HSX4QQb4CspciLpVFwyRe79O3xsIZDDLER21kERQ71oaPodF8jL725AgJMFAYbooIqolJoRLuM81SpeUkpkvA==", "dev": true, + "license": "MIT", "engines": { "node": ">=12" }, @@ -3213,6 +3745,7 @@ "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-6.2.1.tgz", "integrity": "sha512-bN798gFfQX+viw3R7yrGWRqnrN2oRkEkUjjl4JNn4E8GxxbjtG3FbrEIIY3l8/hrwUwIeCZvi4QuOTP4MErVug==", "dev": true, + "license": "MIT", "engines": { "node": ">=12" }, @@ -3225,6 +3758,7 @@ "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-5.0.0.tgz", "integrity": "sha512-OVa3u9kkBbw7b8Xw5F9P+D/T9X+Z4+JruYVNapTjPYZYUznQ5YfWeFkOj606XYYW8yugTfC8Pj0hYqvi4ryAhA==", "dev": true, + "license": "MIT", "dependencies": { "get-east-asian-width": "^1.0.0" }, @@ -3240,6 +3774,7 @@ "resolved": "https://registry.npmjs.org/slice-ansi/-/slice-ansi-7.1.0.tgz", "integrity": "sha512-bSiSngZ/jWeX93BqeIAbImyTbEihizcwNjFoRUIY/T1wWQsfsm2Vw1agPKylXvQTU7iASGdHhyqRlqQzfz+Htg==", "dev": true, + "license": "MIT", "dependencies": { "ansi-styles": "^6.2.1", "is-fullwidth-code-point": "^5.0.0" @@ -3256,6 +3791,7 @@ "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.1.0.tgz", "integrity": "sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==", "dev": true, + "license": "MIT", "dependencies": { "ansi-regex": "^6.0.1" }, @@ -3271,15 +3807,17 @@ "resolved": "https://registry.npmjs.org/loupe/-/loupe-2.3.7.tgz", "integrity": "sha512-zSMINGVYkdpYSOBmLi0D1Uo7JU9nVdQKrHxC8eYlV+9YKK9WePqAlL7lSlorG/U2Fw1w0hTBmaa/jrQ3UbPHtA==", "dev": true, + "license": "MIT", "dependencies": { "get-func-name": "^2.0.1" } }, "node_modules/lru-cache": { - "version": "11.0.0", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-11.0.0.tgz", - "integrity": "sha512-Qv32eSV1RSCfhY3fpPE2GNZ8jgM9X7rdAfemLWqTUxwiyIC4jJ6Sy0fZ8H+oLWevO6i4/bizg7c8d8i6bxrzbA==", + "version": "11.0.2", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-11.0.2.tgz", + "integrity": "sha512-123qHRfJBmo2jXDbo/a5YOQrJoHF/GNQTLzQ5+IdK5pWpceK17yRc6ozlWd25FxvGKQbIUs91fDFkXmDHTKcyA==", "dev": true, + "license": "ISC", "engines": { "node": "20 || >=22" } @@ -3288,28 +3826,28 @@ "version": "2.3.9", "resolved": "https://registry.npmjs.org/lunr/-/lunr-2.3.9.tgz", "integrity": "sha512-zTU3DaZaF3Rt9rhN3uBMGQD3dD2/vFQqnvZCDv4dl5iOzq2IZQqTxu90r4E5J+nP70J3ilqVCrbho2eWaeW8Ow==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/magic-string": { - "version": "0.30.9", - "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.30.9.tgz", - "integrity": "sha512-S1+hd+dIrC8EZqKyT9DstTH/0Z+f76kmmvZnkfQVmOpDEF9iVgdYif3Q/pIWHmCoo59bQVGW0kVL3e2nl+9+Sw==", + "version": "0.30.17", + "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.30.17.tgz", + "integrity": "sha512-sNPKHvyjVf7gyjwS4xGTaW/mCnF8wnjtifKBEhxfZ7E/S8tQ0rssrwGNn6q8JH/ohItJfSQp9mBtQYuTlH5QnA==", "dev": true, + "license": "MIT", "dependencies": { - "@jridgewell/sourcemap-codec": "^1.4.15" - }, - "engines": { - "node": ">=12" + "@jridgewell/sourcemap-codec": "^1.5.0" } }, "node_modules/magicast": { - "version": "0.3.4", - "resolved": "https://registry.npmjs.org/magicast/-/magicast-0.3.4.tgz", - "integrity": "sha512-TyDF/Pn36bBji9rWKHlZe+PZb6Mx5V8IHCSxk7X4aljM4e/vyDvZZYwHewdVaqiA0nb3ghfHU/6AUpDxWoER2Q==", + "version": "0.3.5", + "resolved": "https://registry.npmjs.org/magicast/-/magicast-0.3.5.tgz", + "integrity": "sha512-L0WhttDl+2BOsybvEOLK7fW3UA0OQ0IQ2d6Zl2x/a6vVRs3bAY0ECOSHHeL5jD+SbOpOCUEi0y1DgHEn9Qn1AQ==", "dev": true, + "license": "MIT", "dependencies": { - "@babel/parser": "^7.24.4", - "@babel/types": "^7.24.0", + "@babel/parser": "^7.25.4", + "@babel/types": "^7.25.4", "source-map-js": "^1.2.0" } }, @@ -3318,6 +3856,7 @@ "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-4.0.0.tgz", "integrity": "sha512-hXdUTZYIVOt1Ex//jAQi+wTZZpUpwBj/0QsOzqegb3rGMMeJiSEu5xLHnYfBrRV4RH2+OCSOO95Is/7x1WJ4bw==", "dev": true, + "license": "MIT", "dependencies": { "semver": "^7.5.3" }, @@ -3332,13 +3871,15 @@ "version": "1.3.6", "resolved": "https://registry.npmjs.org/make-error/-/make-error-1.3.6.tgz", "integrity": "sha512-s8UhlNe7vPKomQhC1qFelMokr/Sc3AgNbso3n74mVPA5LTZwkB9NlXf4XPamLxJE8h0gh73rM94xvwRT2CVInw==", - "dev": true + "dev": true, + "license": "ISC" }, "node_modules/markdown-it": { "version": "14.1.0", "resolved": "https://registry.npmjs.org/markdown-it/-/markdown-it-14.1.0.tgz", "integrity": "sha512-a54IwgWPaeBCAAsv13YgmALOF1elABB08FxO9i+r4VFk5Vl4pKokRPeX8u5TCgSsPi6ec1otfLjdOpVcgbpshg==", "dev": true, + "license": "MIT", "dependencies": { "argparse": "^2.0.1", "entities": "^4.4.0", @@ -3355,19 +3896,38 @@ "version": "2.0.0", "resolved": "https://registry.npmjs.org/mdurl/-/mdurl-2.0.0.tgz", "integrity": "sha512-Lf+9+2r+Tdp5wXDXC4PcIBjTDtq4UKjCPMQhKIuzpJNW0b96kVqSwW0bT7FhRSfmAiFYgP+SCRvdrDozfh0U5w==", - "dev": true + "dev": true, + "license": "MIT" + }, + "node_modules/memoize": { + "version": "10.0.0", + "resolved": "https://registry.npmjs.org/memoize/-/memoize-10.0.0.tgz", + "integrity": "sha512-H6cBLgsi6vMWOcCpvVCdFFnl3kerEXbrYh9q+lY6VXvQSmM6CkmV08VOwT+WE2tzIEqRPFfAq3fm4v/UIW6mSA==", + "dev": true, + "license": "MIT", + "dependencies": { + "mimic-function": "^5.0.0" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sindresorhus/memoize?sponsor=1" + } }, "node_modules/merge-stream": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/merge-stream/-/merge-stream-2.0.0.tgz", "integrity": "sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/merge2": { "version": "1.4.1", "resolved": "https://registry.npmjs.org/merge2/-/merge2-1.4.1.tgz", "integrity": "sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==", "dev": true, + "license": "MIT", "engines": { "node": ">= 8" } @@ -3377,6 +3937,7 @@ "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.8.tgz", "integrity": "sha512-PXwfBhYu0hBCPw8Dn0E+WDYb7af3dSLVWKi3HGv84IdF4TyFoC0ysxFd0Goxw7nSv4T/PzEJQxsYsEiFCKo2BA==", "dev": true, + "license": "MIT", "dependencies": { "braces": "^3.0.3", "picomatch": "^2.3.1" @@ -3385,11 +3946,25 @@ "node": ">=8.6" } }, + "node_modules/micromatch/node_modules/picomatch": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", + "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8.6" + }, + "funding": { + "url": "https://github.com/sponsors/jonschlinkert" + } + }, "node_modules/mimic-fn": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-4.0.0.tgz", "integrity": "sha512-vqiC06CuhBTUdZH+RYl8sFrL096vA45Ok5ISO6sE/Mr1jRbGH4Csnhi8f3wKVl7x8mO4Au7Ir9D3Oyv1VYMFJw==", "dev": true, + "license": "MIT", "engines": { "node": ">=12" }, @@ -3402,6 +3977,7 @@ "resolved": "https://registry.npmjs.org/mimic-function/-/mimic-function-5.0.1.tgz", "integrity": "sha512-VP79XUPxV2CigYP3jWwAUFSku2aKqBH7uTAapFWCBqutsbmDo96KY5o8uh6U+/YSIn5OxJnXp73beVkpqMIGhA==", "dev": true, + "license": "MIT", "engines": { "node": ">=18" }, @@ -3410,15 +3986,29 @@ } }, "node_modules/minimatch": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", - "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "version": "9.0.5", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.5.tgz", + "integrity": "sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow==", "dev": true, + "license": "ISC", "dependencies": { - "brace-expansion": "^1.1.7" + "brace-expansion": "^2.0.1" }, "engines": { - "node": "*" + "node": ">=16 || 14 >=14.17" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/minimist": { + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.8.tgz", + "integrity": "sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==", + "dev": true, + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, "node_modules/minipass": { @@ -3426,20 +4016,22 @@ "resolved": "https://registry.npmjs.org/minipass/-/minipass-7.1.2.tgz", "integrity": "sha512-qOOzS1cBTWYF4BH8fVePDBOO9iptMnGUEZwNc/cMWnTV2nVLZ7VoNWEPHkYczZA0pdoA7dl6e7FL659nX9S2aw==", "dev": true, + "license": "ISC", "engines": { "node": ">=16 || 14 >=14.17" } }, "node_modules/mlly": { - "version": "1.6.1", - "resolved": "https://registry.npmjs.org/mlly/-/mlly-1.6.1.tgz", - "integrity": "sha512-vLgaHvaeunuOXHSmEbZ9izxPx3USsk8KCQ8iC+aTlp5sKRSoZvwhHh5L9VbKSaVC6sJDqbyohIS76E2VmHIPAA==", + "version": "1.7.3", + "resolved": "https://registry.npmjs.org/mlly/-/mlly-1.7.3.tgz", + "integrity": "sha512-xUsx5n/mN0uQf4V548PKQ+YShA4/IW0KI1dZhrNrPCLG+xizETbHTkOa1f8/xut9JRPp8kQuMnz0oqwkTiLo/A==", "dev": true, + "license": "MIT", "dependencies": { - "acorn": "^8.11.3", + "acorn": "^8.14.0", "pathe": "^1.1.2", - "pkg-types": "^1.0.3", - "ufo": "^1.3.2" + "pkg-types": "^1.2.1", + "ufo": "^1.5.4" } }, "node_modules/mri": { @@ -3447,6 +4039,7 @@ "resolved": "https://registry.npmjs.org/mri/-/mri-1.2.0.tgz", "integrity": "sha512-tzzskb3bG8LvYGFF/mDTpq3jpI6Q9wc3LEmBaghu+DdCssd1FakN7Bc0hVNmEyGq1bq3RgfkCb3cmQLpNPOroA==", "dev": true, + "license": "MIT", "engines": { "node": ">=4" } @@ -3455,12 +4048,13 @@ "version": "2.1.3", "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/nanoid": { - "version": "3.3.7", - "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.7.tgz", - "integrity": "sha512-eSRppjcPIatRIMC1U6UngP8XFcz8MQWGQdt1MTBQ7NaAmvXDfvNxbvWV3x2y6CdEUciCSsDHDQZbhYaB8QEo2g==", + "version": "3.3.8", + "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.8.tgz", + "integrity": "sha512-WNLf5Sd8oZxOm+TzppcYk8gVOgP+l58xNy58D0nbUnOxOWRWvlcCV4kUF7ltmI6PsrLl/BgKEyS4mqsGChFN0w==", "dev": true, "funding": [ { @@ -3468,6 +4062,7 @@ "url": "https://github.com/sponsors/ai" } ], + "license": "MIT", "bin": { "nanoid": "bin/nanoid.cjs" }, @@ -3479,13 +4074,15 @@ "version": "1.4.0", "resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz", "integrity": "sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/npm-run-path": { "version": "5.3.0", "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-5.3.0.tgz", "integrity": "sha512-ppwTtiJZq0O/ai0z7yfudtBpWIoxM8yE6nHi1X47eFR2EWORqfbu6CnPlNsjeN683eT0qG6H/Pyf9fCcvjnnnQ==", "dev": true, + "license": "MIT", "dependencies": { "path-key": "^4.0.0" }, @@ -3501,6 +4098,7 @@ "resolved": "https://registry.npmjs.org/path-key/-/path-key-4.0.0.tgz", "integrity": "sha512-haREypq7xkM7ErfgIyA0z+Bj4AGKlMSdlQE2jvJo6huWD1EdkKYV+G/T4nq0YEF2vgTT8kqMFKo1uHn950r4SQ==", "dev": true, + "license": "MIT", "engines": { "node": ">=12" }, @@ -3513,6 +4111,7 @@ "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", "integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==", "dev": true, + "license": "ISC", "dependencies": { "wrappy": "1" } @@ -3522,6 +4121,7 @@ "resolved": "https://registry.npmjs.org/onetime/-/onetime-6.0.0.tgz", "integrity": "sha512-1FlR+gjXK7X+AsAHso35MnyN5KqGwJRi/31ft6x0M194ht7S+rWAvd7PHss9xSKMzE0asv1pyIHaJYq+BbacAQ==", "dev": true, + "license": "MIT", "dependencies": { "mimic-fn": "^4.0.0" }, @@ -3537,22 +4137,24 @@ "resolved": "https://registry.npmjs.org/opencollective-postinstall/-/opencollective-postinstall-2.0.3.tgz", "integrity": "sha512-8AV/sCtuzUeTo8gQK5qDZzARrulB3egtLzFgteqB2tcT4Mw7B8Kt7JcDHmltjz6FOAHsvTevk70gZEbhM4ZS9Q==", "dev": true, + "license": "MIT", "bin": { "opencollective-postinstall": "index.js" } }, "node_modules/optionator": { - "version": "0.9.3", - "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.9.3.tgz", - "integrity": "sha512-JjCoypp+jKn1ttEFExxhetCKeJt9zhAgAve5FXHixTvFDW/5aEktX9bufBKLRRMdU7bNtpLfcGu94B3cdEJgjg==", + "version": "0.9.4", + "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.9.4.tgz", + "integrity": "sha512-6IpQ7mKUxRcZNLIObR0hz7lxsapSSIYNZJwXPGeF0mTVqGKFIXj1DQcMoT22S3ROcLyY/rz0PWaWZ9ayWmad9g==", "dev": true, + "license": "MIT", "dependencies": { - "@aashutoshrathi/word-wrap": "^1.2.3", "deep-is": "^0.1.3", "fast-levenshtein": "^2.0.6", "levn": "^0.4.1", "prelude-ls": "^1.2.1", - "type-check": "^0.4.0" + "type-check": "^0.4.0", + "word-wrap": "^1.2.5" }, "engines": { "node": ">= 0.8.0" @@ -3563,6 +4165,7 @@ "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz", "integrity": "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==", "dev": true, + "license": "MIT", "dependencies": { "yocto-queue": "^0.1.0" }, @@ -3578,6 +4181,7 @@ "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-5.0.0.tgz", "integrity": "sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==", "dev": true, + "license": "MIT", "dependencies": { "p-limit": "^3.0.2" }, @@ -3589,16 +4193,18 @@ } }, "node_modules/package-json-from-dist": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/package-json-from-dist/-/package-json-from-dist-1.0.0.tgz", - "integrity": "sha512-dATvCeZN/8wQsGywez1mzHtTlP22H8OEfPrVMLNr4/eGa+ijtLn/6M5f0dY8UKNrC2O9UCU6SSoG3qRKnt7STw==", - "dev": true + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/package-json-from-dist/-/package-json-from-dist-1.0.1.tgz", + "integrity": "sha512-UEZIS3/by4OC8vL3P2dTXRETpebLI2NiI5vIrjaD/5UtrkFX/tNbwjTSRAGC/+7CAo2pIcBaRgWmcBBHcsaCIw==", + "dev": true, + "license": "BlueOak-1.0.0" }, "node_modules/parent-module": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz", "integrity": "sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==", "dev": true, + "license": "MIT", "dependencies": { "callsites": "^3.0.0" }, @@ -3611,6 +4217,7 @@ "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-5.2.0.tgz", "integrity": "sha512-ayCKvm/phCGxOkYRSCM82iDwct8/EonSEgCSxWxD7ve6jHggsFl4fZVQBPRNgQoKiuV/odhFrGzQXZwbifC8Rg==", "dev": true, + "license": "MIT", "dependencies": { "@babel/code-frame": "^7.0.0", "error-ex": "^1.3.1", @@ -3629,6 +4236,7 @@ "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==", "dev": true, + "license": "MIT", "engines": { "node": ">=8" } @@ -3638,6 +4246,7 @@ "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", "integrity": "sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==", "dev": true, + "license": "MIT", "engines": { "node": ">=0.10.0" } @@ -3647,15 +4256,24 @@ "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==", "dev": true, + "license": "MIT", "engines": { "node": ">=8" } }, + "node_modules/path-parse": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz", + "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==", + "dev": true, + "license": "MIT" + }, "node_modules/path-scurry": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/path-scurry/-/path-scurry-2.0.0.tgz", "integrity": "sha512-ypGJsmGtdXUOeM5u93TyeIEfEhM6s+ljAhrk5vAvSx8uyY/02OvrZnA0YNGUrPXfpJMgI1ODd3nwz8Npx4O4cg==", "dev": true, + "license": "BlueOak-1.0.0", "dependencies": { "lru-cache": "^11.0.0", "minipass": "^7.1.2" @@ -3672,6 +4290,7 @@ "resolved": "https://registry.npmjs.org/path-type/-/path-type-4.0.0.tgz", "integrity": "sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==", "dev": true, + "license": "MIT", "engines": { "node": ">=8" } @@ -3680,30 +4299,34 @@ "version": "1.1.2", "resolved": "https://registry.npmjs.org/pathe/-/pathe-1.1.2.tgz", "integrity": "sha512-whLdWMYL2TwI08hn8/ZqAbrVemu0LNaNNJZX73O6qaIdCTfXutsLhMkjdENX0qhsQ9uIimo4/aQOmXkoon2nDQ==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/pathval": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/pathval/-/pathval-1.1.1.tgz", "integrity": "sha512-Dp6zGqpTdETdR63lehJYPeIOqpiNBNtc7BpWSLrOje7UaIsE5aY92r/AunQA7rsXvet3lrJ3JnZX29UPTKXyKQ==", "dev": true, + "license": "MIT", "engines": { "node": "*" } }, "node_modules/picocolors": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.1.0.tgz", - "integrity": "sha512-TQ92mBOW0l3LeMeyLV6mzy/kWr8lkd/hp3mTg7wYK7zJhuBStmGMBG0BdeDZS/dZx1IukaX6Bk11zcln25o1Aw==", - "dev": true + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.1.1.tgz", + "integrity": "sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==", + "dev": true, + "license": "ISC" }, "node_modules/picomatch": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", - "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==", + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.2.tgz", + "integrity": "sha512-M7BAV6Rlcy5u+m6oPhAPFgJTzAioX/6B0DxyvDlo9l8+T3nLKbrczg2WLUyzd45L8RqfUMyGPzekbMvX2Ldkwg==", "dev": true, + "license": "MIT", "engines": { - "node": ">=8.6" + "node": ">=12" }, "funding": { "url": "https://github.com/sponsors/jonschlinkert" @@ -3714,6 +4337,7 @@ "resolved": "https://registry.npmjs.org/pidtree/-/pidtree-0.6.0.tgz", "integrity": "sha512-eG2dWTVw5bzqGRztnHExczNxt5VGsE6OwTeCG3fdUf9KBsZzO3R5OIIIzWR+iZA0NtZ+RDVdaoE2dK1cn6jH4g==", "dev": true, + "license": "MIT", "bin": { "pidtree": "bin/pidtree.js" }, @@ -3726,6 +4350,7 @@ "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-5.0.0.tgz", "integrity": "sha512-NPE8TDbzl/3YQYY7CSS228s3g2ollTFnc+Qi3tqmqJp9Vg2ovUpixcJEo2HJScN2Ez+kEaal6y70c0ehqJBJeA==", "dev": true, + "license": "MIT", "dependencies": { "find-up": "^5.0.0" }, @@ -3734,35 +4359,38 @@ } }, "node_modules/pkg-types": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/pkg-types/-/pkg-types-1.0.3.tgz", - "integrity": "sha512-nN7pYi0AQqJnoLPC9eHFQ8AcyaixBUOwvqc5TDnIKCMEE6I0y8P7OKA7fPexsXGCGxQDl/cmrLAp26LhcwxZ4A==", + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/pkg-types/-/pkg-types-1.3.0.tgz", + "integrity": "sha512-kS7yWjVFCkIw9hqdJBoMxDdzEngmkr5FXeWZZfQ6GoYacjVnsW6l2CcYW/0ThD0vF4LPJgVYnrg4d0uuhwYQbg==", "dev": true, + "license": "MIT", "dependencies": { - "jsonc-parser": "^3.2.0", - "mlly": "^1.2.0", - "pathe": "^1.1.0" + "confbox": "^0.1.8", + "mlly": "^1.7.3", + "pathe": "^1.1.2" } }, "node_modules/platform": { "version": "1.3.6", "resolved": "https://registry.npmjs.org/platform/-/platform-1.3.6.tgz", "integrity": "sha512-fnWVljUchTro6RiCFvCXBbNhJc2NijN7oIQxbwsyL0buWJPG85v81ehlHI9fXrJsMNgTofEoWIQeClKpgxFLrg==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/please-upgrade-node": { "version": "3.2.0", "resolved": "https://registry.npmjs.org/please-upgrade-node/-/please-upgrade-node-3.2.0.tgz", "integrity": "sha512-gQR3WpIgNIKwBMVLkpMUeR3e1/E1y42bqDQZfql+kDeXd8COYfM8PQA4X6y7a8u9Ua9FHmsrrmirW2vHs45hWg==", "dev": true, + "license": "MIT", "dependencies": { "semver-compare": "^1.0.0" } }, "node_modules/postcss": { - "version": "8.4.47", - "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.47.tgz", - "integrity": "sha512-56rxCq7G/XfB4EkXq9Egn5GCqugWvDFjafDOThIdMBsI15iqPqR5r15TfSr1YPYeEI19YeaXMCbY6u88Y76GLQ==", + "version": "8.4.49", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.49.tgz", + "integrity": "sha512-OCVPnIObs4N29kxTjzLfUryOkvZEq+pf8jTF0lg8E7uETuWHA+v7j3c/xJmiqpX450191LlmZfUKkXxkTry7nA==", "dev": true, "funding": [ { @@ -3778,9 +4406,10 @@ "url": "https://github.com/sponsors/ai" } ], + "license": "MIT", "dependencies": { "nanoid": "^3.3.7", - "picocolors": "^1.1.0", + "picocolors": "^1.1.1", "source-map-js": "^1.2.1" }, "engines": { @@ -3792,6 +4421,7 @@ "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.2.1.tgz", "integrity": "sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==", "dev": true, + "license": "MIT", "engines": { "node": ">= 0.8.0" } @@ -3801,6 +4431,7 @@ "resolved": "https://registry.npmjs.org/prettier/-/prettier-3.4.2.tgz", "integrity": "sha512-e9MewbtFo+Fevyuxn/4rrcDAaq0IYxPGLvObpQjiZBMAzB9IGmzlnG9RZy3FFas+eBMu2vA0CszMeduow5dIuQ==", "dev": true, + "license": "MIT", "bin": { "prettier": "bin/prettier.cjs" }, @@ -3816,6 +4447,7 @@ "resolved": "https://registry.npmjs.org/prettier-linter-helpers/-/prettier-linter-helpers-1.0.0.tgz", "integrity": "sha512-GbK2cP9nraSSUF9N2XwUwqfzlAFlMNYYl+ShE/V+H8a9uNl/oUqB1w2EL54Jh0OlyRSd8RfWYJ3coVS4TROP2w==", "dev": true, + "license": "MIT", "dependencies": { "fast-diff": "^1.1.2" }, @@ -3828,6 +4460,7 @@ "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-29.7.0.tgz", "integrity": "sha512-Pdlw/oPxN+aXdmM9R00JVC9WVFoCLTKJvDVLgmJ+qAffBMxsV85l/Lu7sNx4zSzPyoL2euImuEwHhOXdEgNFZQ==", "dev": true, + "license": "MIT", "dependencies": { "@jest/schemas": "^29.6.3", "ansi-styles": "^5.0.0", @@ -3842,6 +4475,7 @@ "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-5.2.0.tgz", "integrity": "sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA==", "dev": true, + "license": "MIT", "engines": { "node": ">=10" }, @@ -3854,6 +4488,7 @@ "resolved": "https://registry.npmjs.org/pretty-quick/-/pretty-quick-4.0.0.tgz", "integrity": "sha512-M+2MmeufXb/M7Xw3Afh1gxcYpj+sK0AxEfnfF958ktFeAyi5MsKY5brymVURQLgPLV1QaF5P4pb2oFJ54H3yzQ==", "dev": true, + "license": "MIT", "dependencies": { "execa": "^5.1.1", "find-up": "^5.0.0", @@ -3878,6 +4513,7 @@ "resolved": "https://registry.npmjs.org/execa/-/execa-5.1.1.tgz", "integrity": "sha512-8uSpZZocAZRBAPIEINJj3Lo9HyGitllczc27Eh5YYojjMFMn8yHMDMaUHE2Jqfq05D/wucwI4JGURyXt1vchyg==", "dev": true, + "license": "MIT", "dependencies": { "cross-spawn": "^7.0.3", "get-stream": "^6.0.0", @@ -3901,6 +4537,7 @@ "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-6.0.1.tgz", "integrity": "sha512-ts6Wi+2j3jQjqi70w5AlN8DFnkSwC+MqmxEzdEALB2qXZYV3X/b1CTfgPLGJNMeAWxdPfU8FO1ms3NUfaHCPYg==", "dev": true, + "license": "MIT", "engines": { "node": ">=10" }, @@ -3913,6 +4550,7 @@ "resolved": "https://registry.npmjs.org/human-signals/-/human-signals-2.1.0.tgz", "integrity": "sha512-B4FFZ6q/T2jhhksgkbEW3HBvWIfDW85snkQgawt07S7J5QXTk6BkNV+0yAeZrM5QpMAdYlocGoljn0sJ/WQkFw==", "dev": true, + "license": "Apache-2.0", "engines": { "node": ">=10.17.0" } @@ -3922,6 +4560,7 @@ "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-2.0.1.tgz", "integrity": "sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg==", "dev": true, + "license": "MIT", "engines": { "node": ">=8" }, @@ -3934,6 +4573,7 @@ "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-2.1.0.tgz", "integrity": "sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==", "dev": true, + "license": "MIT", "engines": { "node": ">=6" } @@ -3943,6 +4583,7 @@ "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-4.0.1.tgz", "integrity": "sha512-S48WzZW777zhNIrn7gxOlISNAqi9ZC/uQFnRdbeIHhZhCA6UqpkOT8T1G7BvfdgP4Er8gF4sUbaS0i7QvIfCWw==", "dev": true, + "license": "MIT", "dependencies": { "path-key": "^3.0.0" }, @@ -3955,6 +4596,7 @@ "resolved": "https://registry.npmjs.org/onetime/-/onetime-5.1.2.tgz", "integrity": "sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg==", "dev": true, + "license": "MIT", "dependencies": { "mimic-fn": "^2.1.0" }, @@ -3970,6 +4612,7 @@ "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-3.0.1.tgz", "integrity": "sha512-I3EurrIQMlRc9IaAZnqRR044Phh2DXY+55o7uJ0V+hYZAcQYSuFWsc9q5PvyDHUSCe1Qxn/iBz+78s86zWnGag==", "dev": true, + "license": "MIT", "engines": { "node": ">=10" }, @@ -3981,22 +4624,39 @@ "version": "3.0.7", "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.7.tgz", "integrity": "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==", - "dev": true + "dev": true, + "license": "ISC" }, "node_modules/pretty-quick/node_modules/strip-final-newline": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/strip-final-newline/-/strip-final-newline-2.0.0.tgz", "integrity": "sha512-BrpvfNAE3dcvq7ll3xVumzjKjZQ5tI1sEUIKr3Uoks0XUl45St3FlatVqef9prk4jRDzhW6WZg+3bk93y6pLjA==", "dev": true, + "license": "MIT", "engines": { "node": ">=6" } }, + "node_modules/prompts": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/prompts/-/prompts-2.4.2.tgz", + "integrity": "sha512-NxNv/kLguCA7p3jE8oL2aEBsrJWgAakBpgmgK6lpPWV+WuOmY6r2/zbAVnP+T8bQlA0nzHXSJSJW0Hq7ylaD2Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "kleur": "^3.0.3", + "sisteransi": "^1.0.5" + }, + "engines": { + "node": ">= 6" + } + }, "node_modules/punycode": { "version": "2.3.1", "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.1.tgz", "integrity": "sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==", "dev": true, + "license": "MIT", "engines": { "node": ">=6" } @@ -4006,6 +4666,7 @@ "resolved": "https://registry.npmjs.org/punycode.js/-/punycode.js-2.3.1.tgz", "integrity": "sha512-uxFIHU0YlHYhDQtV4R9J6a52SLx28BCjT+4ieh7IGbgwVJWO+km431c4yRlREUAsAmt/uMjQUyQHNEPf0M39CA==", "dev": true, + "license": "MIT", "engines": { "node": ">=6" } @@ -4028,28 +4689,86 @@ "type": "consulting", "url": "https://feross.org/support" } - ] + ], + "license": "MIT" }, "node_modules/react-is": { "version": "18.3.1", "resolved": "https://registry.npmjs.org/react-is/-/react-is-18.3.1.tgz", "integrity": "sha512-/LLMVyas0ljjAtoYiPqYiL8VWXzUUdThrmU5+n20DZv+a+ClRoevUzw5JxU+Ieh5/c87ytoTBV9G1FiKfNJdmg==", - "dev": true + "dev": true, + "license": "MIT" + }, + "node_modules/rechoir": { + "version": "0.8.0", + "resolved": "https://registry.npmjs.org/rechoir/-/rechoir-0.8.0.tgz", + "integrity": "sha512-/vxpCXddiX8NGfGO/mTafwjq4aFa/71pvamip0++IQk3zG8cbCj0fifNPrjjF1XMXUne91jL9OoxmdykoEtifQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "resolve": "^1.20.0" + }, + "engines": { + "node": ">= 10.13.0" + } + }, + "node_modules/regexp-tree": { + "version": "0.1.27", + "resolved": "https://registry.npmjs.org/regexp-tree/-/regexp-tree-0.1.27.tgz", + "integrity": "sha512-iETxpjK6YoRWJG5o6hXLwvjYAoW+FEZn9os0PD/b6AP6xQwsa/Y7lCVgIixBbUPMfhu+i2LtdeAqVTgGlQarfA==", + "dev": true, + "license": "MIT", + "bin": { + "regexp-tree": "bin/regexp-tree" + } + }, + "node_modules/require-from-string": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/require-from-string/-/require-from-string-2.0.2.tgz", + "integrity": "sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } }, "node_modules/requireindex": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/requireindex/-/requireindex-1.2.0.tgz", "integrity": "sha512-L9jEkOi3ASd9PYit2cwRfyppc9NoABujTP8/5gFcbERmo5jUoAKovIC3fsF17pkTnGsrByysqX+Kxd2OTNI1ww==", "dev": true, + "license": "MIT", "engines": { "node": ">=0.10.5" } }, + "node_modules/resolve": { + "version": "1.22.10", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.10.tgz", + "integrity": "sha512-NPRy+/ncIMeDlTAsuqwKIiferiawhefFJtkNSW0qZJEqMEb+qBt/77B/jGeeek+F0uOeN05CDa6HXbbIgtVX4w==", + "dev": true, + "license": "MIT", + "dependencies": { + "is-core-module": "^2.16.0", + "path-parse": "^1.0.7", + "supports-preserve-symlinks-flag": "^1.0.0" + }, + "bin": { + "resolve": "bin/resolve" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/resolve-from": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz", "integrity": "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==", "dev": true, + "license": "MIT", "engines": { "node": ">=4" } @@ -4059,6 +4778,7 @@ "resolved": "https://registry.npmjs.org/restore-cursor/-/restore-cursor-5.1.0.tgz", "integrity": "sha512-oMA2dcrw6u0YfxJQXm342bFKX/E4sG9rbTzO9ptUcR/e8A33cHuvStiYOwH7fszkZlZ1z/ta9AAoPk2F4qIOHA==", "dev": true, + "license": "MIT", "dependencies": { "onetime": "^7.0.0", "signal-exit": "^4.1.0" @@ -4075,6 +4795,7 @@ "resolved": "https://registry.npmjs.org/onetime/-/onetime-7.0.0.tgz", "integrity": "sha512-VXJjc87FScF88uafS3JllDgvAm+c/Slfz06lorj2uAY34rlUu0Nt+v8wreiImcrgAjjIHp1rXpTDlLOGw29WwQ==", "dev": true, + "license": "MIT", "dependencies": { "mimic-function": "^5.0.0" }, @@ -4090,6 +4811,7 @@ "resolved": "https://registry.npmjs.org/reusify/-/reusify-1.0.4.tgz", "integrity": "sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw==", "dev": true, + "license": "MIT", "engines": { "iojs": ">=1.0.0", "node": ">=0.10.0" @@ -4099,13 +4821,15 @@ "version": "1.4.1", "resolved": "https://registry.npmjs.org/rfdc/-/rfdc-1.4.1.tgz", "integrity": "sha512-q1b3N5QkRUWUl7iyylaaj3kOpIT0N2i9MqIEQXP73GVsN9cw3fdx8X63cEmWhJGi2PPCF23Ijp7ktmd39rawIA==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/rimraf": { "version": "6.0.1", "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-6.0.1.tgz", "integrity": "sha512-9dkvaxAsk/xNXSJzMgFqqMCuFgt2+KsOFek3TMLfo8NCPfWpBmqwyNn5Y+NX56QUYfCtsyhF3ayiboEoUmJk/A==", "dev": true, + "license": "ISC", "dependencies": { "glob": "^11.0.0", "package-json-from-dist": "^1.0.0" @@ -4121,12 +4845,13 @@ } }, "node_modules/rollup": { - "version": "4.22.4", - "resolved": "https://registry.npmjs.org/rollup/-/rollup-4.22.4.tgz", - "integrity": "sha512-vD8HJ5raRcWOyymsR6Z3o6+RzfEPCnVLMFJ6vRslO1jt4LO6dUo5Qnpg7y4RkZFM2DMe3WUirkI5c16onjrc6A==", + "version": "4.30.1", + "resolved": "https://registry.npmjs.org/rollup/-/rollup-4.30.1.tgz", + "integrity": "sha512-mlJ4glW020fPuLi7DkM/lN97mYEZGWeqBnrljzN0gs7GLctqX3lNWxKQ7Gl712UAX+6fog/L3jh4gb7R6aVi3w==", "dev": true, + "license": "MIT", "dependencies": { - "@types/estree": "1.0.5" + "@types/estree": "1.0.6" }, "bin": { "rollup": "dist/bin/rollup" @@ -4136,22 +4861,25 @@ "npm": ">=8.0.0" }, "optionalDependencies": { - "@rollup/rollup-android-arm-eabi": "4.22.4", - "@rollup/rollup-android-arm64": "4.22.4", - "@rollup/rollup-darwin-arm64": "4.22.4", - "@rollup/rollup-darwin-x64": "4.22.4", - "@rollup/rollup-linux-arm-gnueabihf": "4.22.4", - "@rollup/rollup-linux-arm-musleabihf": "4.22.4", - "@rollup/rollup-linux-arm64-gnu": "4.22.4", - "@rollup/rollup-linux-arm64-musl": "4.22.4", - "@rollup/rollup-linux-powerpc64le-gnu": "4.22.4", - "@rollup/rollup-linux-riscv64-gnu": "4.22.4", - "@rollup/rollup-linux-s390x-gnu": "4.22.4", - "@rollup/rollup-linux-x64-gnu": "4.22.4", - "@rollup/rollup-linux-x64-musl": "4.22.4", - "@rollup/rollup-win32-arm64-msvc": "4.22.4", - "@rollup/rollup-win32-ia32-msvc": "4.22.4", - "@rollup/rollup-win32-x64-msvc": "4.22.4", + "@rollup/rollup-android-arm-eabi": "4.30.1", + "@rollup/rollup-android-arm64": "4.30.1", + "@rollup/rollup-darwin-arm64": "4.30.1", + "@rollup/rollup-darwin-x64": "4.30.1", + "@rollup/rollup-freebsd-arm64": "4.30.1", + "@rollup/rollup-freebsd-x64": "4.30.1", + "@rollup/rollup-linux-arm-gnueabihf": "4.30.1", + "@rollup/rollup-linux-arm-musleabihf": "4.30.1", + "@rollup/rollup-linux-arm64-gnu": "4.30.1", + "@rollup/rollup-linux-arm64-musl": "4.30.1", + "@rollup/rollup-linux-loongarch64-gnu": "4.30.1", + "@rollup/rollup-linux-powerpc64le-gnu": "4.30.1", + "@rollup/rollup-linux-riscv64-gnu": "4.30.1", + "@rollup/rollup-linux-s390x-gnu": "4.30.1", + "@rollup/rollup-linux-x64-gnu": "4.30.1", + "@rollup/rollup-linux-x64-musl": "4.30.1", + "@rollup/rollup-win32-arm64-msvc": "4.30.1", + "@rollup/rollup-win32-ia32-msvc": "4.30.1", + "@rollup/rollup-win32-x64-msvc": "4.30.1", "fsevents": "~2.3.2" } }, @@ -4174,18 +4902,27 @@ "url": "https://feross.org/support" } ], + "license": "MIT", "dependencies": { "queue-microtask": "^1.2.2" } }, - "node_modules/semver": { - "version": "7.6.0", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.0.tgz", - "integrity": "sha512-EnwXhrlwXMk9gKu5/flx5sv/an57AkRplG3hTK68W7FRDN+k+OWBj65M7719OkA82XLBxrcX0KSHj+X5COhOVg==", + "node_modules/safe-regex": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/safe-regex/-/safe-regex-2.1.1.tgz", + "integrity": "sha512-rx+x8AMzKb5Q5lQ95Zoi6ZbJqwCLkqi3XuJXp5P3rT8OEc6sZCJG5AE5dU3lsgRr/F4Bs31jSlVN+j5KrsGu9A==", "dev": true, + "license": "MIT", "dependencies": { - "lru-cache": "^6.0.0" - }, + "regexp-tree": "~0.1.1" + } + }, + "node_modules/semver": { + "version": "7.6.3", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.3.tgz", + "integrity": "sha512-oVekP1cKtI+CTDvHWYFUcMtsK/00wmAEfyqKfNdARm8u1wNVhSgaX7A8d4UuIlUI5e84iEwOhs7ZPYRmzU9U6A==", + "dev": true, + "license": "ISC", "bin": { "semver": "bin/semver.js" }, @@ -4197,13 +4934,15 @@ "version": "1.0.0", "resolved": "https://registry.npmjs.org/semver-compare/-/semver-compare-1.0.0.tgz", "integrity": "sha512-YM3/ITh2MJ5MtzaM429anh+x2jiLVjqILF4m4oyQB18W7Ggea7BfqdH/wGMK7dDiMghv/6WG7znWMwUDzJiXow==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/semver-regex": { "version": "3.1.4", "resolved": "https://registry.npmjs.org/semver-regex/-/semver-regex-3.1.4.tgz", "integrity": "sha512-6IiqeZNgq01qGf0TId0t3NvKzSvUsjcpdEO3AQNeIjR6A2+ckTnQlDpl4qu1bjRv0RzN3FP9hzFmws3lKqRWkA==", "dev": true, + "license": "MIT", "engines": { "node": ">=8" }, @@ -4211,23 +4950,12 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/semver/node_modules/lru-cache": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", - "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", - "dev": true, - "dependencies": { - "yallist": "^4.0.0" - }, - "engines": { - "node": ">=10" - } - }, "node_modules/shebang-command": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", "dev": true, + "license": "MIT", "dependencies": { "shebang-regex": "^3.0.0" }, @@ -4240,6 +4968,7 @@ "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz", "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==", "dev": true, + "license": "MIT", "engines": { "node": ">=8" } @@ -4248,13 +4977,15 @@ "version": "2.0.0", "resolved": "https://registry.npmjs.org/siginfo/-/siginfo-2.0.0.tgz", "integrity": "sha512-ybx0WO1/8bSBLEWXZvEd7gMW3Sn3JFlW3TvX1nREbDLRNQNaeNN8WK0meBwPdAaOI7TtRRRJn/Es1zhrrCHu7g==", - "dev": true + "dev": true, + "license": "ISC" }, "node_modules/signal-exit": { "version": "4.1.0", "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-4.1.0.tgz", "integrity": "sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==", "dev": true, + "license": "ISC", "engines": { "node": ">=14" }, @@ -4262,11 +4993,19 @@ "url": "https://github.com/sponsors/isaacs" } }, + "node_modules/sisteransi": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/sisteransi/-/sisteransi-1.0.5.tgz", + "integrity": "sha512-bLGGlR1QxBcynn2d5YmDX4MGjlZvy2MRBDRNHLJ8VI6l6+9FUiyTFNJ0IveOSP0bcXgVDPRcfGqA0pjaqUpfVg==", + "dev": true, + "license": "MIT" + }, "node_modules/slash": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/slash/-/slash-3.0.0.tgz", "integrity": "sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==", "dev": true, + "license": "MIT", "engines": { "node": ">=8" } @@ -4276,6 +5015,7 @@ "resolved": "https://registry.npmjs.org/slice-ansi/-/slice-ansi-5.0.0.tgz", "integrity": "sha512-FC+lgizVPfie0kkhqUScwRu1O/lF6NOgJmlCgK+/LYxDCTk8sGelYaHDhFcDN+Sn3Cv+3VSa4Byeo+IMCzpMgQ==", "dev": true, + "license": "MIT", "dependencies": { "ansi-styles": "^6.0.0", "is-fullwidth-code-point": "^4.0.0" @@ -4292,6 +5032,7 @@ "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-6.2.1.tgz", "integrity": "sha512-bN798gFfQX+viw3R7yrGWRqnrN2oRkEkUjjl4JNn4E8GxxbjtG3FbrEIIY3l8/hrwUwIeCZvi4QuOTP4MErVug==", "dev": true, + "license": "MIT", "engines": { "node": ">=12" }, @@ -4304,6 +5045,7 @@ "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.2.1.tgz", "integrity": "sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA==", "dev": true, + "license": "BSD-3-Clause", "engines": { "node": ">=0.10.0" } @@ -4312,19 +5054,22 @@ "version": "0.0.2", "resolved": "https://registry.npmjs.org/stackback/-/stackback-0.0.2.tgz", "integrity": "sha512-1XMJE5fQo1jGH6Y/7ebnwPOBEkIEnT4QF32d5R1+VXdXveM0IBMJt8zfaxX1P3QhVwrYe+576+jkANtSS2mBbw==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/std-env": { - "version": "3.7.0", - "resolved": "https://registry.npmjs.org/std-env/-/std-env-3.7.0.tgz", - "integrity": "sha512-JPbdCEQLj1w5GilpiHAx3qJvFndqybBysA3qUOnznweH4QbNYUsW/ea8QzSrnh0vNsezMMw5bcVool8lM0gwzg==", - "dev": true + "version": "3.8.0", + "resolved": "https://registry.npmjs.org/std-env/-/std-env-3.8.0.tgz", + "integrity": "sha512-Bc3YwwCB+OzldMxOXJIIvC6cPRWr/LxOp48CdQTOkPyk/t4JWWJbrilwBd7RJzKV8QW7tJkcgAmeuLLJugl5/w==", + "dev": true, + "license": "MIT" }, "node_modules/string-argv": { "version": "0.3.2", "resolved": "https://registry.npmjs.org/string-argv/-/string-argv-0.3.2.tgz", "integrity": "sha512-aqD2Q0144Z+/RqG52NeHEkZauTAUWJO8c6yTftGJKO3Tja5tUgIfmIl6kExvhtxSDP7fXB6DvzkfMpCd/F3G+Q==", "dev": true, + "license": "MIT", "engines": { "node": ">=0.6.19" } @@ -4334,6 +5079,7 @@ "resolved": "https://registry.npmjs.org/string-width/-/string-width-7.2.0.tgz", "integrity": "sha512-tsaTIkKW9b4N+AEj+SVA+WhJzV7/zMhcSu78mLKWSk7cXMOSHsBKFWUs0fWwq8QyK3MgJBQRX6Gbi4kYbdvGkQ==", "dev": true, + "license": "MIT", "dependencies": { "emoji-regex": "^10.3.0", "get-east-asian-width": "^1.0.0", @@ -4352,6 +5098,7 @@ "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", "dev": true, + "license": "MIT", "dependencies": { "emoji-regex": "^8.0.0", "is-fullwidth-code-point": "^3.0.0", @@ -4365,13 +5112,15 @@ "version": "8.0.0", "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/string-width-cjs/node_modules/is-fullwidth-code-point": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", "dev": true, + "license": "MIT", "engines": { "node": ">=8" } @@ -4381,6 +5130,7 @@ "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.1.0.tgz", "integrity": "sha512-7HSX4QQb4CspciLpVFwyRe79O3xsIZDDLER21kERQ71oaPodF8jL725AgJMFAYbooIqolJoRLuM81SpeUkpkvA==", "dev": true, + "license": "MIT", "engines": { "node": ">=12" }, @@ -4393,6 +5143,7 @@ "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.1.0.tgz", "integrity": "sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==", "dev": true, + "license": "MIT", "dependencies": { "ansi-regex": "^6.0.1" }, @@ -4408,6 +5159,7 @@ "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", "dev": true, + "license": "MIT", "dependencies": { "ansi-regex": "^5.0.1" }, @@ -4421,6 +5173,7 @@ "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", "dev": true, + "license": "MIT", "dependencies": { "ansi-regex": "^5.0.1" }, @@ -4428,11 +5181,22 @@ "node": ">=8" } }, + "node_modules/strip-bom": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-3.0.0.tgz", + "integrity": "sha512-vavAMRXOgBVNF6nyEEmL3DBK19iRpDcoIwW+swQ+CbGiu7lju6t+JklA1MHweoWtadgt4ISVUsXLyDq34ddcwA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=4" + } + }, "node_modules/strip-final-newline": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/strip-final-newline/-/strip-final-newline-3.0.0.tgz", "integrity": "sha512-dOESqjYr96iWYylGObzd39EuNTa5VJxyvVAEm5Jnh7KGo75V43Hk1odPQkNDyXNmUR6k+gEiDVXnjB8HJ3crXw==", "dev": true, + "license": "MIT", "engines": { "node": ">=12" }, @@ -4445,6 +5209,7 @@ "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz", "integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==", "dev": true, + "license": "MIT", "engines": { "node": ">=8" }, @@ -4453,28 +5218,31 @@ } }, "node_modules/strip-literal": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/strip-literal/-/strip-literal-2.1.0.tgz", - "integrity": "sha512-Op+UycaUt/8FbN/Z2TWPBLge3jWrP3xj10f3fnYxf052bKuS3EKs1ZQcVGjnEMdsNVAM+plXRdmjrZ/KgG3Skw==", + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/strip-literal/-/strip-literal-2.1.1.tgz", + "integrity": "sha512-631UJ6O00eNGfMiWG78ck80dfBab8X6IVFB51jZK5Icd7XAs60Z5y7QdSd/wGIklnWvRbUNloVzhOKKmutxQ6Q==", "dev": true, + "license": "MIT", "dependencies": { - "js-tokens": "^9.0.0" + "js-tokens": "^9.0.1" }, "funding": { "url": "https://github.com/sponsors/antfu" } }, "node_modules/strip-literal/node_modules/js-tokens": { - "version": "9.0.0", - "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-9.0.0.tgz", - "integrity": "sha512-WriZw1luRMlmV3LGJaR6QOJjWwgLUTf89OwT2lUOyjX2dJGBwgmIkbcz+7WFZjrZM635JOIR517++e/67CP9dQ==", - "dev": true + "version": "9.0.1", + "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-9.0.1.tgz", + "integrity": "sha512-mxa9E9ITFOt0ban3j6L5MpjwegGz6lBQmM1IJkWeBZGcMxto50+eWdjC/52xDbS2vy0k7vIMK0Fe2wfL9OQSpQ==", + "dev": true, + "license": "MIT" }, "node_modules/supports-color": { "version": "7.2.0", "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", "dev": true, + "license": "MIT", "dependencies": { "has-flag": "^4.0.0" }, @@ -4482,11 +5250,25 @@ "node": ">=8" } }, + "node_modules/supports-preserve-symlinks-flag": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz", + "integrity": "sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/synckit": { "version": "0.9.2", "resolved": "https://registry.npmjs.org/synckit/-/synckit-0.9.2.tgz", "integrity": "sha512-vrozgXDQwYO72vHjUb/HnFbQx1exDjoKzqx23aXEg2a9VIg2TSFZ8FmeZpTjUCFMYw7mpX4BE2SFu8wI7asYsw==", "dev": true, + "license": "MIT", "dependencies": { "@pkgr/core": "^0.1.0", "tslib": "^2.6.2" @@ -4498,11 +5280,29 @@ "url": "https://opencollective.com/unts" } }, + "node_modules/tapable": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/tapable/-/tapable-2.2.1.tgz", + "integrity": "sha512-GNzQvQTOIP6RyTfE2Qxb8ZVlNmw0n88vp1szwWRimP02mnTsx3Wtn5qRdqY9w2XduFNUgvOwhNnQsjwCp+kqaQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/teamcity-service-messages": { + "version": "0.1.14", + "resolved": "https://registry.npmjs.org/teamcity-service-messages/-/teamcity-service-messages-0.1.14.tgz", + "integrity": "sha512-29aQwaHqm8RMX74u2o/h1KbMLP89FjNiMxD9wbF2BbWOnbM+q+d1sCEC+MqCc4QW3NJykn77OMpTFw/xTHIc0w==", + "dev": true, + "license": "MIT" + }, "node_modules/test-exclude": { "version": "6.0.0", "resolved": "https://registry.npmjs.org/test-exclude/-/test-exclude-6.0.0.tgz", "integrity": "sha512-cAGWPIyOHU6zlmg88jwm7VRyXnMN7iV68OGAbYDk/Mh/xC/pzVPlQtY6ngoIH/5/tciuhGfvESU8GrHrcxD56w==", "dev": true, + "license": "ISC", "dependencies": { "@istanbuljs/schema": "^0.1.2", "glob": "^7.1.4", @@ -4512,11 +5312,24 @@ "node": ">=8" } }, + "node_modules/test-exclude/node_modules/brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "dev": true, + "license": "MIT", + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, "node_modules/test-exclude/node_modules/glob": { "version": "7.2.3", "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", + "deprecated": "Glob versions prior to v9 are no longer supported", "dev": true, + "license": "ISC", "dependencies": { "fs.realpath": "^1.0.0", "inflight": "^1.0.4", @@ -4532,23 +5345,39 @@ "url": "https://github.com/sponsors/isaacs" } }, + "node_modules/test-exclude/node_modules/minimatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "dev": true, + "license": "ISC", + "dependencies": { + "brace-expansion": "^1.1.7" + }, + "engines": { + "node": "*" + } + }, "node_modules/text-table": { "version": "0.2.0", "resolved": "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz", "integrity": "sha512-N+8UisAXDGk8PFXP4HAzVR9nbfmVJ3zYLAWiTIoqC5v5isinhr+r5uaO8+7r3BMfuNIufIsA7RdpVgacC2cSpw==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/tinybench": { - "version": "2.7.0", - "resolved": "https://registry.npmjs.org/tinybench/-/tinybench-2.7.0.tgz", - "integrity": "sha512-Qgayeb106x2o4hNzNjsZEfFziw8IbKqtbXBjVh7VIZfBxfD5M4gWtpyx5+YTae2gJ6Y6Dz/KLepiv16RFeQWNA==", - "dev": true + "version": "2.9.0", + "resolved": "https://registry.npmjs.org/tinybench/-/tinybench-2.9.0.tgz", + "integrity": "sha512-0+DUvqWMValLmha6lr4kD8iAMK1HzV0/aKnCtWb9v9641TnP/MFb7Pc2bxoxQjTXAErryXVgUOfv2YqNllqGeg==", + "dev": true, + "license": "MIT" }, "node_modules/tinypool": { "version": "0.8.4", "resolved": "https://registry.npmjs.org/tinypool/-/tinypool-0.8.4.tgz", "integrity": "sha512-i11VH5gS6IFeLY3gMBQ00/MmLncVP7JLXOw1vlgkytLmJK7QnEr7NXf0LBdxfmNPAeyetukOk0bOYrJrFGjYJQ==", "dev": true, + "license": "MIT", "engines": { "node": ">=14.0.0" } @@ -4558,24 +5387,17 @@ "resolved": "https://registry.npmjs.org/tinyspy/-/tinyspy-2.2.1.tgz", "integrity": "sha512-KYad6Vy5VDWV4GH3fjpseMQ/XU2BhIYP7Vzd0LG44qRWm/Yt2WCOTicFdvmgo6gWaqooMQCawTtILVQJupKu7A==", "dev": true, + "license": "MIT", "engines": { "node": ">=14.0.0" } }, - "node_modules/to-fast-properties": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/to-fast-properties/-/to-fast-properties-2.0.0.tgz", - "integrity": "sha512-/OaKK0xYrs3DmxRYqL/yDc+FxFUVYhDlXMhRmv3z915w2HF1tnN1omB354j8VUGO/hbRzyD6Y3sA7v7GS/ceog==", - "dev": true, - "engines": { - "node": ">=4" - } - }, "node_modules/to-regex-range": { "version": "5.0.1", "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", "dev": true, + "license": "MIT", "dependencies": { "is-number": "^7.0.0" }, @@ -4588,6 +5410,7 @@ "resolved": "https://registry.npmjs.org/ts-api-utils/-/ts-api-utils-1.4.3.tgz", "integrity": "sha512-i3eMG77UTMD0hZhgRS562pv83RC6ukSAC2GMNWc+9dieh/+jDM5u5YG+NHX6VNDRHQcHwmsTHctP9LhbC3WxVw==", "dev": true, + "license": "MIT", "engines": { "node": ">=16" }, @@ -4600,6 +5423,7 @@ "resolved": "https://registry.npmjs.org/ts-node/-/ts-node-10.9.2.tgz", "integrity": "sha512-f0FFpIdcHgn8zcPSbf1dRevwt047YMnaiJM3u2w2RewrB+fob/zePZcrOyQoLMMO7aBIddLcQIEK5dYjkLnGrQ==", "dev": true, + "license": "MIT", "dependencies": { "@cspotcode/source-map-support": "^0.8.0", "@tsconfig/node10": "^1.0.7", @@ -4638,17 +5462,50 @@ } } }, + "node_modules/tsconfig-paths": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/tsconfig-paths/-/tsconfig-paths-4.2.0.tgz", + "integrity": "sha512-NoZ4roiN7LnbKn9QqE1amc9DJfzvZXxF4xDavcOWt1BPkdx+m+0gJuPM+S0vCe7zTJMYUP0R8pO2XMr+Y8oLIg==", + "dev": true, + "license": "MIT", + "dependencies": { + "json5": "^2.2.2", + "minimist": "^1.2.6", + "strip-bom": "^3.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/tsconfig-paths-webpack-plugin": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/tsconfig-paths-webpack-plugin/-/tsconfig-paths-webpack-plugin-4.2.0.tgz", + "integrity": "sha512-zbem3rfRS8BgeNK50Zz5SIQgXzLafiHjOwUAvk/38/o1jHn/V5QAgVUcz884or7WYcPaH3N2CIfUc2u0ul7UcA==", + "dev": true, + "license": "MIT", + "dependencies": { + "chalk": "^4.1.0", + "enhanced-resolve": "^5.7.0", + "tapable": "^2.2.1", + "tsconfig-paths": "^4.1.2" + }, + "engines": { + "node": ">=10.13.0" + } + }, "node_modules/tslib": { - "version": "2.6.2", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.2.tgz", - "integrity": "sha512-AEYxH93jGFPn/a2iVAwW87VuUIkR1FVUKB77NwMF7nBTDkDrrT/Hpt/IrCJ0QXhW27jTBDcf5ZY7w6RiqTMw2Q==", - "dev": true + "version": "2.8.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz", + "integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==", + "dev": true, + "license": "0BSD" }, "node_modules/type-check": { "version": "0.4.0", "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.4.0.tgz", "integrity": "sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==", "dev": true, + "license": "MIT", "dependencies": { "prelude-ls": "^1.2.1" }, @@ -4657,10 +5514,11 @@ } }, "node_modules/type-detect": { - "version": "4.0.8", - "resolved": "https://registry.npmjs.org/type-detect/-/type-detect-4.0.8.tgz", - "integrity": "sha512-0fr/mIH1dlO+x7TlcMy+bIDqKPsw/70tVyeHW787goQjhmqaZe10uwLujubK9q9Lg6Fiho1KUKDYz0Z7k7g5/g==", + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/type-detect/-/type-detect-4.1.0.tgz", + "integrity": "sha512-Acylog8/luQ8L7il+geoSxhEkazvkslg7PSNKOX59mbB9cOveP5aq9h74Y7YU8yDpJwetzQQrfIwtf4Wp4LKcw==", "dev": true, + "license": "MIT", "engines": { "node": ">=4" } @@ -4670,6 +5528,7 @@ "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.20.2.tgz", "integrity": "sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ==", "dev": true, + "license": "(MIT OR CC0-1.0)", "engines": { "node": ">=10" }, @@ -4682,6 +5541,7 @@ "resolved": "https://registry.npmjs.org/typedoc/-/typedoc-0.27.6.tgz", "integrity": "sha512-oBFRoh2Px6jFx366db0lLlihcalq/JzyCVp7Vaq1yphL/tbgx2e+bkpkCgJPunaPvPwoTOXSwasfklWHm7GfAw==", "dev": true, + "license": "Apache-2.0", "dependencies": { "@gerrit0/mini-shiki": "^1.24.0", "lunr": "^2.3.9", @@ -4700,10 +5560,11 @@ } }, "node_modules/typedoc-plugin-markdown": { - "version": "4.4.0", - "resolved": "https://registry.npmjs.org/typedoc-plugin-markdown/-/typedoc-plugin-markdown-4.4.0.tgz", - "integrity": "sha512-4207DYcxJGWQRrEVTza7XkIo7ldhuEzJBaZO6dX5ogUGlvWeRTo4uiN+R1F11ttJGh4toLtxrpoi2wTTP+nEwA==", + "version": "4.4.1", + "resolved": "https://registry.npmjs.org/typedoc-plugin-markdown/-/typedoc-plugin-markdown-4.4.1.tgz", + "integrity": "sha512-fx23nSCvewI9IR8lzIYtzDphETcgTDuxKcmHKGD4lo36oexC+B1k4NaCOY58Snqb4OlE8OXDAGVcQXYYuLRCNw==", "dev": true, + "license": "MIT", "engines": { "node": ">= 18" }, @@ -4711,35 +5572,12 @@ "typedoc": "0.27.x" } }, - "node_modules/typedoc/node_modules/brace-expansion": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", - "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", - "dev": true, - "dependencies": { - "balanced-match": "^1.0.0" - } - }, - "node_modules/typedoc/node_modules/minimatch": { - "version": "9.0.5", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.5.tgz", - "integrity": "sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow==", - "dev": true, - "dependencies": { - "brace-expansion": "^2.0.1" - }, - "engines": { - "node": ">=16 || 14 >=14.17" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, "node_modules/typedoc/node_modules/yaml": { - "version": "2.6.1", - "resolved": "https://registry.npmjs.org/yaml/-/yaml-2.6.1.tgz", - "integrity": "sha512-7r0XPzioN/Q9kXBro/XPnA6kznR73DHq+GXh5ON7ZozRO6aMjbmiBuKste2wslTFkC5d1dw0GooOCepZXJ2SAg==", + "version": "2.7.0", + "resolved": "https://registry.npmjs.org/yaml/-/yaml-2.7.0.tgz", + "integrity": "sha512-+hSoy/QHluxmC9kCIJyL/uyFmLmc+e5CFR5Wa+bpIhIj85LVb9ZH2nVnqrHoSvKogwODv0ClqZkmiSSaIH5LTA==", "dev": true, + "license": "ISC", "bin": { "yaml": "bin.mjs" }, @@ -4748,10 +5586,11 @@ } }, "node_modules/typescript": { - "version": "5.7.2", - "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.7.2.tgz", - "integrity": "sha512-i5t66RHxDvVN40HfDd1PsEThGNnlMCMT3jMUuoh9/0TaqWevNontacunWyN02LA9/fIbEWlcHZcgTKb9QoaLfg==", + "version": "5.7.3", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.7.3.tgz", + "integrity": "sha512-84MVSjMEHP+FQRPy3pX9sTVV/INIex71s9TL2Gm5FG/WG1SqXeKyZ0k7/blY/4FdOzI12CBy1vGc4og/eus0fw==", "dev": true, + "license": "Apache-2.0", "bin": { "tsc": "bin/tsc", "tsserver": "bin/tsserver" @@ -4764,25 +5603,29 @@ "version": "2.1.0", "resolved": "https://registry.npmjs.org/uc.micro/-/uc.micro-2.1.0.tgz", "integrity": "sha512-ARDJmphmdvUk6Glw7y9DQ2bFkKBHwQHLi2lsaH6PPmz/Ka9sFOBsBluozhDltWmnv9u/cF6Rt87znRTPV+yp/A==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/ufo": { - "version": "1.5.3", - "resolved": "https://registry.npmjs.org/ufo/-/ufo-1.5.3.tgz", - "integrity": "sha512-Y7HYmWaFwPUmkoQCUIAYpKqkOf+SbVj/2fJJZ4RJMCfZp0rTGwRbzQD+HghfnhKOjL9E01okqz+ncJskGYfBNw==", - "dev": true + "version": "1.5.4", + "resolved": "https://registry.npmjs.org/ufo/-/ufo-1.5.4.tgz", + "integrity": "sha512-UsUk3byDzKd04EyoZ7U4DOlxQaD14JUKQl6/P7wiX4FNvUfm3XL246n9W5AmqwW5RSFJ27NAuM0iLscAOYUiGQ==", + "dev": true, + "license": "MIT" }, "node_modules/undici-types": { "version": "5.26.5", "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-5.26.5.tgz", "integrity": "sha512-JlCMO+ehdEIKqlFxk6IfVoAUVmgz7cU7zD/h9XZ0qzeosSHmUJVOzSQvvYSYWXkFXC+IfLKSIffhv0sVZup6pA==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/uri-js": { "version": "4.4.1", "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz", "integrity": "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==", "dev": true, + "license": "BSD-2-Clause", "dependencies": { "punycode": "^2.1.0" } @@ -4791,13 +5634,15 @@ "version": "3.0.1", "resolved": "https://registry.npmjs.org/v8-compile-cache-lib/-/v8-compile-cache-lib-3.0.1.tgz", "integrity": "sha512-wa7YjyUGfNZngI/vtK0UHAN+lgDCxBPCylVXGp0zu59Fz5aiGtNXaq3DhIov063MorB+VfufLh3JlF2KdTK3xg==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/vite": { - "version": "5.4.6", - "resolved": "https://registry.npmjs.org/vite/-/vite-5.4.6.tgz", - "integrity": "sha512-IeL5f8OO5nylsgzd9tq4qD2QqI0k2CQLGrWD0rCN0EQJZpBK5vJAx0I+GDkMOXxQX/OfFHMuLIx6ddAxGX/k+Q==", + "version": "5.4.11", + "resolved": "https://registry.npmjs.org/vite/-/vite-5.4.11.tgz", + "integrity": "sha512-c7jFQRklXua0mTzneGW9QVyxFjUgwcihC4bXEtujIo2ouWCe1Ajt/amn2PCxYnhYfd5k09JX3SB7OYWFKYqj8Q==", "dev": true, + "license": "MIT", "dependencies": { "esbuild": "^0.21.3", "postcss": "^8.4.43", @@ -4857,6 +5702,7 @@ "resolved": "https://registry.npmjs.org/vite-node/-/vite-node-1.6.0.tgz", "integrity": "sha512-de6HJgzC+TFzOu0NTC4RAIsyf/DY/ibWDYQUcuEA84EMHhcefTUGkjFHKKEJhQN4A+6I0u++kr3l36ZF2d7XRw==", "dev": true, + "license": "MIT", "dependencies": { "cac": "^6.7.14", "debug": "^4.3.4", @@ -4879,6 +5725,7 @@ "resolved": "https://registry.npmjs.org/vitest/-/vitest-1.6.0.tgz", "integrity": "sha512-H5r/dN06swuFnzNFhq/dnz37bPXnq8xB2xB5JOVk8K09rUtoeNN+LHWkoQ0A/i3hvbUKKcCei9KpbxqHMLhLLA==", "dev": true, + "license": "MIT", "dependencies": { "@vitest/expect": "1.6.0", "@vitest/runner": "1.6.0", @@ -4939,11 +5786,25 @@ } } }, + "node_modules/watskeburt": { + "version": "4.2.2", + "resolved": "https://registry.npmjs.org/watskeburt/-/watskeburt-4.2.2.tgz", + "integrity": "sha512-AOCg1UYxWpiHW1tUwqpJau8vzarZYTtzl2uu99UptBmbzx6kOzCGMfRLF6KIRX4PYekmryn89MzxlRNkL66YyA==", + "dev": true, + "license": "MIT", + "bin": { + "watskeburt": "dist/run-cli.js" + }, + "engines": { + "node": "^18||>=20" + } + }, "node_modules/which": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", "dev": true, + "license": "ISC", "dependencies": { "isexe": "^2.0.0" }, @@ -4959,15 +5820,17 @@ "resolved": "https://registry.npmjs.org/which-pm-runs/-/which-pm-runs-1.1.0.tgz", "integrity": "sha512-n1brCuqClxfFfq/Rb0ICg9giSZqCS+pLtccdag6C2HyufBrh3fBOiy9nb6ggRMvWOVH5GrdJskj5iGTZNxd7SA==", "dev": true, + "license": "MIT", "engines": { "node": ">=4" } }, "node_modules/why-is-node-running": { - "version": "2.2.2", - "resolved": "https://registry.npmjs.org/why-is-node-running/-/why-is-node-running-2.2.2.tgz", - "integrity": "sha512-6tSwToZxTOcotxHeA+qGCq1mVzKR3CwcJGmVcY+QE8SHy6TnpFnh8PAvPNHYr7EcuVeG0QSMxtYCuO1ta/G/oA==", + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/why-is-node-running/-/why-is-node-running-2.3.0.tgz", + "integrity": "sha512-hUrmaWBdVDcxvYqnyh09zunKzROWjbZTiNy8dBEjkS7ehEDQibXJ7XvlmtbwuTclUiIyN+CyXQD4Vmko8fNm8w==", "dev": true, + "license": "MIT", "dependencies": { "siginfo": "^2.0.0", "stackback": "0.0.2" @@ -4979,11 +5842,22 @@ "node": ">=8" } }, + "node_modules/word-wrap": { + "version": "1.2.5", + "resolved": "https://registry.npmjs.org/word-wrap/-/word-wrap-1.2.5.tgz", + "integrity": "sha512-BN22B5eaMMI9UMtjrGd5g5eCYPpCPDUy0FJXbYsaT5zYxjFOckS53SQDE3pWkVoWpHXVb3BrYcEN4Twa55B5cA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, "node_modules/wrap-ansi": { "version": "9.0.0", "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-9.0.0.tgz", "integrity": "sha512-G8ura3S+3Z2G+mkgNRq8dqaFZAuxfsxpBB8OCTGRTCtp+l/v9nbFNmCUP1BZMts3G1142MsZfn6eeUKrr4PD1Q==", "dev": true, + "license": "MIT", "dependencies": { "ansi-styles": "^6.2.1", "string-width": "^7.0.0", @@ -5002,6 +5876,7 @@ "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", "dev": true, + "license": "MIT", "dependencies": { "ansi-styles": "^4.0.0", "string-width": "^4.1.0", @@ -5018,13 +5893,15 @@ "version": "8.0.0", "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/wrap-ansi-cjs/node_modules/is-fullwidth-code-point": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", "dev": true, + "license": "MIT", "engines": { "node": ">=8" } @@ -5034,6 +5911,7 @@ "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", "dev": true, + "license": "MIT", "dependencies": { "emoji-regex": "^8.0.0", "is-fullwidth-code-point": "^3.0.0", @@ -5048,6 +5926,7 @@ "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.1.0.tgz", "integrity": "sha512-7HSX4QQb4CspciLpVFwyRe79O3xsIZDDLER21kERQ71oaPodF8jL725AgJMFAYbooIqolJoRLuM81SpeUkpkvA==", "dev": true, + "license": "MIT", "engines": { "node": ">=12" }, @@ -5060,6 +5939,7 @@ "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-6.2.1.tgz", "integrity": "sha512-bN798gFfQX+viw3R7yrGWRqnrN2oRkEkUjjl4JNn4E8GxxbjtG3FbrEIIY3l8/hrwUwIeCZvi4QuOTP4MErVug==", "dev": true, + "license": "MIT", "engines": { "node": ">=12" }, @@ -5072,6 +5952,7 @@ "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.1.0.tgz", "integrity": "sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==", "dev": true, + "license": "MIT", "dependencies": { "ansi-regex": "^6.0.1" }, @@ -5086,19 +5967,15 @@ "version": "1.0.2", "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==", - "dev": true - }, - "node_modules/yallist": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", - "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", - "dev": true + "dev": true, + "license": "ISC" }, "node_modules/yaml": { "version": "1.10.2", "resolved": "https://registry.npmjs.org/yaml/-/yaml-1.10.2.tgz", "integrity": "sha512-r3vXyErRCYJ7wg28yvBY5VSoAF8ZvlcW9/BwUzEtUsjvX/DKs24dIkuwjtuprwJJHsbyUbLApepYTR1BN4uHrg==", "dev": true, + "license": "ISC", "engines": { "node": ">= 6" } @@ -5108,6 +5985,7 @@ "resolved": "https://registry.npmjs.org/yn/-/yn-3.1.1.tgz", "integrity": "sha512-Ux4ygGWsu2c7isFWe8Yu1YluJmqVhxqK2cLXNQA5AcC3QfbGNpM7fu0Y8b/z16pXLnFxZYvWhd3fhBY9DLmC6Q==", "dev": true, + "license": "MIT", "engines": { "node": ">=6" } @@ -5117,6 +5995,7 @@ "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz", "integrity": "sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==", "dev": true, + "license": "MIT", "engines": { "node": ">=10" }, diff --git a/package.json b/package.json index c72052606..dd25f6d40 100644 --- a/package.json +++ b/package.json @@ -13,6 +13,7 @@ "@types/node": "^18.15.11", "@vitest/coverage-v8": "^1.1.1", "benchmark": "^2.1.4", + "dependency-cruiser": "^16.9.0", "eslint": "^8.50.0", "generate-changelog": "^1.8.0", "husky": "^4.3.8", @@ -87,8 +88,9 @@ "release:minor": "generate-changelog -m -x \"chore,test\" && npm run changelog:commit && npm run docs:release && npm version minor", "release:patch": "generate-changelog -p -x \"chore,test\" && npm run changelog:commit && npm run docs:release && npm version patch", "start:benchmark": "tsc --noEmit && node --no-warnings=ExperimentalWarning --loader ts-node/esm/transpile-only ./src/start/startBenchmark.ts", - "test": "npm run test:dev -- --coverage", + "test": "npm run test:types && npm run test:imports && npm run test:dev -- --coverage", "test:dev": "vitest run --passWithNoTests", + "test:imports": "depcruise src --include-only \"^src\"", "test:types": "npm run lint:types" }, "type": "module", diff --git a/src/ABANDS/AccelerationBands.test.ts b/src/ABANDS/AccelerationBands.test.ts index fbac91572..3a4591427 100644 --- a/src/ABANDS/AccelerationBands.test.ts +++ b/src/ABANDS/AccelerationBands.test.ts @@ -48,8 +48,8 @@ describe('AccelerationBands', () => { for (const candle of candles) { const {close, high, low} = candle; - accBands.update({close, high, low}); - fasterAccBands.update({close, high, low}); + accBands.add({close, high, low}); + fasterAccBands.add({close, high, low}); } let result = accBands.getResult(); @@ -70,8 +70,8 @@ describe('AccelerationBands', () => { // See: https://github.com/QuantConnect/Lean/blob/master/Tests/TestData/spy_acceleration_bands_20_4.txt#L22 const candle: HighLowCloseNumber = {close: 195, high: 195.03, low: 189.12}; - accBands.update(candle); - fasterAccBands.update(candle); + accBands.add(candle); + fasterAccBands.add(candle); result = accBands.getResult(); fasterResult = fasterAccBands.getResult(); @@ -108,11 +108,16 @@ describe('AccelerationBands', () => { describe('update', () => { it("doesn't crash when supplying zeroes", () => { const accBands = new AccelerationBands(20, 2); - return accBands.update({ - close: 0, - high: 0, - low: 0, - }); + return accBands.updates( + [ + { + close: 0, + high: 0, + low: 0, + }, + ], + false + ); }); }); }); @@ -120,10 +125,15 @@ describe('AccelerationBands', () => { describe('FaserAccelerationBands', () => { it("doesn't crash when supplying zeroes", () => { const accBands = new FasterAccelerationBands(20, 2); - return accBands.update({ - close: 0, - high: 0, - low: 0, - }); + return accBands.updates( + [ + { + close: 0, + high: 0, + low: 0, + }, + ], + false + ); }); }); diff --git a/src/ABANDS/AccelerationBands.ts b/src/ABANDS/AccelerationBands.ts index 21445b65e..f9b96f452 100644 --- a/src/ABANDS/AccelerationBands.ts +++ b/src/ABANDS/AccelerationBands.ts @@ -1,13 +1,12 @@ -import {Big} from '../index.js'; +import Big from 'big.js'; +import {TechnicalIndicator} from '../Indicator.js'; +import type {FasterMovingAverage, MovingAverage} from '../MA/MovingAverage.js'; +import type {FasterMovingAverageTypes, MovingAverageTypes} from '../MA/MovingAverageTypes.js'; import {FasterSMA, SMA} from '../SMA/SMA.js'; -import {NotEnoughDataError} from '../error/index.js'; import type {BandsResult, FasterBandsResult} from '../util/BandsResult.js'; -import type {Indicator} from '../Indicator.js'; -import type {FasterMovingAverageTypes, MovingAverageTypes} from '../MA/MovingAverageTypes.js'; -import type {FasterMovingAverage, MovingAverage} from '../MA/MovingAverage.js'; import type {HighLowClose, HighLowCloseNumber} from '../util/index.js'; -export class AccelerationBands implements Indicator { +export class AccelerationBands extends TechnicalIndicator { private readonly lowerBand: MovingAverage; private readonly middleBand: MovingAverage; private readonly upperBand: MovingAverage; @@ -37,41 +36,40 @@ export class AccelerationBands implements Indicator { public readonly width: number, SmoothingIndicator: MovingAverageTypes = SMA ) { + super(); this.lowerBand = new SmoothingIndicator(interval); this.middleBand = new SmoothingIndicator(interval); this.upperBand = new SmoothingIndicator(interval); } - get isStable(): boolean { + override get isStable(): boolean { return this.middleBand.isStable; } - update({high, low, close}: HighLowClose): void { + update({high, low, close}: HighLowClose, replace: boolean) { const highPlusLow = new Big(high).plus(low); const coefficient = highPlusLow.eq(0) ? new Big(0) : new Big(high).minus(low).div(highPlusLow).mul(this.width); // (Low * (1 - width * (High - Low)/ (High + Low))) - this.lowerBand.update(new Big(low).mul(new Big(1).minus(coefficient))); + this.lowerBand.update(new Big(low).mul(new Big(1).minus(coefficient)), replace); // (Close) - this.middleBand.update(close); + this.middleBand.update(close, replace); // (High * ( 1 + width * (High - Low) / (High + Low))) - this.upperBand.update(new Big(high).mul(new Big(1).plus(coefficient))); - } + this.upperBand.update(new Big(high).mul(new Big(1).plus(coefficient)), replace); - getResult(): BandsResult { - if (!this.isStable) { - throw new NotEnoughDataError(); + if (this.isStable) { + return (this.result = { + lower: this.lowerBand.getResult(), + middle: this.middleBand.getResult(), + upper: this.upperBand.getResult(), + }); } - return { - lower: this.lowerBand.getResult(), - middle: this.middleBand.getResult(), - upper: this.upperBand.getResult(), - }; + return null; } } -export class FasterAccelerationBands implements Indicator { +export class FasterAccelerationBands extends TechnicalIndicator { private readonly lowerBand: FasterMovingAverage; private readonly middleBand: FasterMovingAverage; private readonly upperBand: FasterMovingAverage; @@ -81,33 +79,32 @@ export class FasterAccelerationBands implements Indicator { + // Test data verified with: + // https://github.com/jesse-ai/jesse/blob/8e502d070c24bed29db80e1d0938781d8cdb1046/tests/data/test_candles_indicators.py#L4351 + const candles = [ + [1563408000000, 210.8, 225.73, 229.65, 205.71, 609081.49094], + [1563494400000, 225.75, 220.73, 226.23, 212.52, 371622.21865], + [1563580800000, 220.84, 228.2, 235.09, 219.78, 325393.97225], + [1563667200000, 228.25, 225.38, 229.66, 216.99, 270046.1519], + [1563753600000, 225.49, 217.51, 228.34, 212.25, 271310.40446], + [1563840000000, 217.59, 212.48, 219.55, 208.36, 317876.48242], + [1563926400000, 212.55, 216.31, 218.28, 202.0, 331162.6484], + [1564012800000, 216.31, 219.14, 225.12, 215.23, 280370.29627], + [1564099200000, 219.14, 218.81, 220.0, 212.71, 197781.98653], + [1564185600000, 218.81, 207.3, 223.3, 203.0, 301209.41113], + [1564272000000, 207.3, 211.62, 213.52, 198.24, 218801.16693], + [1564358400000, 211.58, 210.89, 215.83, 206.59, 226941.28], + [1564444800000, 210.84, 209.58, 214.36, 204.4, 222683.79393], + [1564531200000, 209.57, 218.42, 218.79, 209.2, 207213.55658], + [1564617600000, 218.42, 216.84, 219.39, 210.54, 186806.18844], + [1564704000000, 216.8, 217.61, 222.18, 214.31, 206867.03039], + [1564790400000, 217.69, 222.14, 224.51, 216.62, 181591.95296], + [1564876800000, 222.14, 221.79, 223.34, 216.9, 135622.0258], + [1564963200000, 221.79, 233.54, 236.25, 221.79, 307956.27211], + [1565049600000, 233.53, 226.28, 239.15, 223.03, 341279.08159], + [1565136000000, 226.31, 226.1, 231.25, 220.95, 279104.7037], + [1565222400000, 226.11, 221.39, 228.5, 215.51, 236886.35423], + [1565308800000, 221.38, 210.53, 221.79, 207.3, 232062.12757], + [1565395200000, 210.52, 206.48, 215.0, 202.6, 252614.02389], + [1565481600000, 206.48, 216.42, 216.94, 206.14, 188474.09048], + [1565568000000, 216.41, 211.41, 216.81, 209.75, 122760.94619], + [1565654400000, 211.58, 209.3, 214.3, 204.0, 166922.48201], + [1565740800000, 209.31, 187.1, 209.9, 183.49, 325228.98931], + [1565827200000, 187.08, 188.03, 189.95, 181.23, 237953.09426], + [1565913600000, 187.98, 184.88, 188.39, 178.04, 282177.01584], + [1566000000000, 184.83, 185.59, 187.0, 181.83, 138799.61508], + [1566086400000, 185.67, 194.33, 197.91, 183.35, 175363.5062], + [1566172800000, 194.32, 202.28, 203.59, 192.7, 239541.5978], + [1566259200000, 202.24, 196.6, 202.75, 194.45, 189297.75494], + [1566345600000, 196.55, 187.45, 197.2, 179.53, 284973.64194], + [1566432000000, 187.45, 190.35, 195.14, 182.8, 245575.98772], + [1566518400000, 190.36, 194.02, 196.19, 188.16, 192548.51552], + [1566604800000, 194.02, 190.6, 194.09, 185.63, 167806.34294], + [1566691200000, 190.6, 186.54, 192.4, 182.8, 169862.91522], + [1566777600000, 186.54, 188.67, 193.7, 186.0, 254397.79472], + [1566864000000, 188.61, 187.24, 189.49, 184.75, 157898.563], + [1566950400000, 187.3, 173.03, 188.25, 166.48, 334480.61761], + [1567036800000, 173.03, 169.01, 173.5, 163.61, 295241.216], + [1567123200000, 169.03, 168.5, 170.77, 165.55, 238616.68868], + [1567209600000, 168.48, 171.57, 174.98, 165.63, 194999.19583], + [1567296000000, 171.52, 170.74, 173.42, 167.61, 191140.52368], + [1567382400000, 170.73, 178.05, 181.0, 170.02, 294627.31247], + [1567468800000, 178.0, 178.75, 183.0, 174.09, 327857.85447], + [1567555200000, 178.79, 174.72, 180.14, 173.0, 286226.25171], + [1567641600000, 174.7, 173.75, 176.19, 168.1, 232753.83596], + [1567728000000, 173.74, 169.08, 177.87, 165.0, 315822.37984], + [1567814400000, 169.11, 177.62, 180.8, 168.3, 253831.23169], + [1567900800000, 177.58, 181.19, 184.18, 176.13, 290083.47501], + [1567987200000, 181.18, 180.54, 185.38, 176.01, 273729.94868], + [1568073600000, 180.52, 179.81, 184.36, 177.0, 238387.50999], + [1568160000000, 179.87, 178.28, 182.8, 173.0, 278555.46708], + [1568246400000, 178.3, 180.72, 182.38, 176.62, 203543.13663], + [1568332800000, 180.71, 180.95, 181.38, 177.54, 264422.54059], + [1568419200000, 180.96, 188.13, 188.79, 179.75, 279371.83423], + [1568505600000, 188.14, 189.03, 190.45, 185.76, 288928.60827], + [1568592000000, 189.05, 197.22, 199.44, 188.3, 551006.81686], + [1568678400000, 197.23, 207.84, 215.13, 195.74, 715863.2262], + [1568764800000, 207.85, 210.21, 217.27, 207.66, 539028.51013], + [1568851200000, 210.27, 220.24, 223.94, 202.3, 844358.82155], + [1568937600000, 220.26, 218.03, 221.54, 212.05, 437804.12669], + [1569024000000, 218.01, 215.05, 221.5, 213.2, 417891.5242], + [1569110400000, 215.04, 211.2, 215.61, 206.1, 445388.94787], + [1569196800000, 211.2, 201.29, 211.68, 198.65, 392437.07084], + [1569283200000, 201.25, 165.81, 202.98, 150.03, 1478218.82714], + [1569369600000, 165.72, 169.96, 174.85, 161.88, 879001.46213], + [1569456000000, 169.96, 165.92, 171.01, 152.11, 779942.17148], + [1569542400000, 165.92, 173.79, 176.72, 161.03, 634932.96707], + [1569628800000, 173.83, 173.49, 175.49, 168.0, 521775.46593], + [1569715200000, 173.5, 169.24, 174.5, 164.12, 410855.12176], + [1569801600000, 169.26, 180.85, 181.24, 165.01, 580295.3997], + [1569888000000, 180.89, 175.66, 185.53, 173.19, 609819.60828], + [1569974400000, 175.65, 180.24, 181.29, 173.65, 348268.1162], + [1570060800000, 180.24, 174.69, 180.72, 169.55, 354756.78478], + [1570147200000, 174.71, 175.55, 178.98, 170.74, 333897.63876], + [1570233600000, 175.55, 176.25, 176.71, 172.02, 278488.61771], + [1570320000000, 176.23, 170.1, 177.04, 167.68, 314932.39629], + [1570406400000, 170.08, 179.85, 182.32, 168.68, 496523.48038], + [1570492800000, 179.88, 180.6, 184.87, 177.0, 400832.37828], + [1570579200000, 180.61, 192.62, 195.53, 178.96, 562506.82189], + [1570665600000, 192.61, 191.14, 194.2, 186.88, 436588.58452], + [1570752000000, 191.18, 180.72, 196.65, 179.41, 621693.63125], + [1570838400000, 180.65, 179.68, 184.64, 177.59, 290415.22038], + [1570924800000, 179.65, 180.99, 184.95, 178.52, 247589.23231], + [1571011200000, 180.98, 186.72, 187.54, 180.43, 279732.84612], + [1571097600000, 186.7, 180.49, 188.37, 175.96, 405466.38109], + [1571184000000, 180.52, 174.47, 181.44, 171.81, 347764.93459], + [1571270400000, 174.52, 177.16, 178.96, 172.61, 298795.8198], + [1571356800000, 177.17, 172.74, 177.44, 168.66, 319602.48508], + [1571443200000, 172.78, 171.79, 174.98, 169.44, 296918.73026], + [1571529600000, 171.84, 175.22, 176.88, 169.21, 299141.07152], + [1571616000000, 175.18, 173.98, 177.9, 171.59, 270608.51385], + [1571702400000, 174.0, 171.2, 175.04, 170.3, 255429.41624], + [1571788800000, 171.19, 162.35, 171.49, 153.45, 746955.09806], + [1571875200000, 162.35, 160.38, 163.72, 158.72, 387310.83766], + [1571961600000, 160.39, 181.5, 187.78, 160.25, 904832.86059], + [1572048000000, 181.53, 179.49, 197.74, 173.8, 1211737.43684], + [1572134400000, 179.42, 183.75, 188.7, 176.22, 724423.40525], + [1572220800000, 183.84, 181.72, 189.48, 180.35, 582179.44545], + [1572307200000, 181.67, 190.46, 192.74, 181.26, 529964.5054], + [1572393600000, 190.45, 183.13, 191.71, 179.28, 537770.43056], + [1572480000000, 183.14, 182.18, 185.27, 177.66, 410969.86104], + [1572566400000, 182.19, 182.85, 184.5, 177.02, 331519.76963], + [1572652800000, 182.86, 182.91, 186.0, 181.53, 179864.39739], + [1572739200000, 182.9, 181.54, 184.7, 178.95, 232621.52147], + [1572825600000, 181.53, 185.71, 188.64, 180.36, 321175.29134], + [1572912000000, 185.71, 188.68, 192.51, 182.22, 389668.6472], + [1572998400000, 188.65, 191.16, 195.09, 187.72, 343219.9224], + [1573084800000, 191.16, 186.68, 192.27, 184.59, 309882.08206], + [1573171200000, 186.67, 183.74, 188.26, 181.41, 365029.75027], + [1573257600000, 183.71, 184.89, 185.79, 182.63, 192073.38044], + [1573344000000, 184.86, 188.96, 191.58, 183.3, 274940.53448], + [1573430400000, 188.96, 184.98, 190.19, 184.06, 255579.93429], + [1573516800000, 184.98, 187.09, 187.65, 182.41, 256782.63119], + [1573603200000, 187.09, 188.11, 189.66, 185.3, 197273.84001], + [1573689600000, 188.07, 184.92, 188.72, 183.34, 245505.29971], + [1573776000000, 184.93, 180.0, 186.7, 177.67, 407466.78964], + [1573862400000, 179.99, 182.37, 183.46, 179.3, 172801.52576], + [1573948800000, 182.37, 183.82, 186.09, 180.0, 198892.4372], + [1574035200000, 183.82, 178.2, 184.06, 175.01, 293551.23632], + [1574121600000, 178.2, 175.94, 178.52, 172.65, 275886.6411], + [1574208000000, 175.93, 174.72, 177.41, 173.5, 216315.93309], + [1574294400000, 174.75, 161.01, 175.85, 157.26, 473895.92992], + [1574380800000, 161.02, 149.56, 162.79, 138.0, 977977.23794], + [1574467200000, 149.55, 151.84, 154.33, 146.11, 369721.0996], + [1574553600000, 151.84, 139.96, 152.86, 138.62, 352319.21558], + [1574640000000, 139.99, 145.69, 151.5, 131.45, 749675.41303], + [1574726400000, 145.81, 147.47, 149.97, 143.37, 354023.04298], + [1574812800000, 147.47, 152.62, 155.54, 140.84, 564796.4284], + [1574899200000, 152.61, 150.72, 154.63, 149.09, 317714.56326], + [1574985600000, 150.69, 154.57, 157.6, 150.23, 328712.25558], + [1575072000000, 154.54, 151.37, 155.25, 149.7, 226863.41299], + [1575158400000, 151.43, 150.73, 152.49, 145.79, 344178.14088], + [1575244800000, 150.72, 148.65, 151.42, 146.71, 233839.0973], + [1575331200000, 148.66, 147.17, 149.93, 145.77, 196329.22503], + [1575417600000, 147.19, 145.38, 151.98, 143.15, 434430.62379], + [1575504000000, 145.45, 148.1, 149.02, 143.64, 299073.53972], + [1575590400000, 148.11, 148.45, 149.77, 145.74, 220674.68581], + [1575676800000, 148.46, 147.14, 149.49, 146.85, 140471.68588], + [1575763200000, 147.16, 150.44, 151.62, 146.11, 205301.6026], + [1575849600000, 150.44, 147.38, 151.19, 146.56, 243775.99249], + [1575936000000, 147.4, 145.56, 148.57, 143.81, 203215.84937], + [1576022400000, 145.53, 143.39, 146.34, 142.12, 157843.10484], + [1576108800000, 143.41, 144.87, 145.85, 139.24, 261615.30437], + [1576195200000, 144.87, 144.8, 146.0, 142.8, 160695.18556], + [1576281600000, 144.8, 141.79, 145.07, 141.18, 126232.59201], + [1576368000000, 141.79, 142.46, 144.12, 139.92, 151189.65877], + [1576454400000, 142.46, 132.73, 142.72, 127.93, 471018.85942], + [1576540800000, 132.72, 121.88, 132.98, 119.11, 563257.36001], + [1576627200000, 121.88, 132.78, 134.87, 116.26, 884960.91334], + [1576713600000, 132.8, 128.1, 134.0, 125.69, 420674.8172], + [1576800000000, 128.1, 128.19, 129.39, 125.84, 213897.4673], + [1576886400000, 128.19, 126.99, 128.4, 126.5, 135196.11641], + [1576972800000, 127.0, 132.09, 133.07, 126.82, 253140.72413], + [1577059200000, 132.12, 127.8, 135.1, 126.0, 421600.75655], + [1577145600000, 127.8, 127.75, 129.69, 126.61, 200637.10098], + [1577232000000, 127.7, 125.09, 127.84, 123.07, 225004.4909], + [1577318400000, 125.09, 125.58, 132.26, 124.32, 274986.52097], + [1577404800000, 125.58, 126.29, 127.1, 121.91, 240012.37451], + [1577491200000, 126.28, 128.11, 129.68, 125.84, 196893.52277], + [1577577600000, 128.11, 134.36, 138.07, 127.52, 316347.26666], + [1577664000000, 134.36, 131.59, 136.24, 130.3, 320347.21956], + [1577750400000, 131.61, 129.16, 133.68, 128.17, 264933.98418], + [1577836800000, 129.16, 130.77, 133.05, 128.68, 144770.52197], + [1577923200000, 130.72, 127.19, 130.78, 126.38, 213757.05806], + [1578009600000, 127.19, 134.35, 135.14, 125.88, 413055.18895], + [1578096000000, 134.37, 134.2, 135.85, 132.5, 184276.17102], + [1578182400000, 134.2, 135.37, 138.19, 134.19, 254120.45343], + [1578268800000, 135.37, 144.15, 144.41, 134.86, 408020.27375], + [1578355200000, 144.14, 142.8, 145.31, 138.76, 447762.17281], + [1578441600000, 142.8, 140.72, 147.77, 137.03, 570465.57764], + [1578528000000, 140.76, 137.74, 141.5, 135.3, 366076.06569], + [1578614400000, 137.73, 144.84, 145.17, 135.32, 409403.59507], + [1578700800000, 144.83, 142.38, 148.05, 142.09, 368350.57939], + [1578787200000, 142.4, 146.54, 146.6, 141.76, 229541.86137], + [1578873600000, 146.56, 143.58, 147.0, 142.27, 207996.61865], + [1578960000000, 143.58, 165.64, 171.7, 143.51, 1108476.31186], + [1579046400000, 165.6, 166.4, 171.98, 159.2, 721687.80381], + [1579132800000, 166.4, 164.21, 167.4, 157.8, 456170.86719], + [1579219200000, 164.24, 169.85, 174.81, 162.14, 767180.67853], + [1579305600000, 169.92, 174.14, 179.5, 164.92, 688783.17982], + [1579392000000, 174.1, 166.79, 178.05, 161.66, 624681.28604], + [1579478400000, 166.79, 166.87, 169.33, 161.24, 358092.8841], + [1579564800000, 166.86, 169.49, 170.32, 164.8, 308007.6353], + [1579651200000, 169.48, 168.07, 171.47, 166.03, 272240.90286], + [1579737600000, 168.07, 162.81, 168.2, 159.21, 373414.34985], + [1579824000000, 162.85, 162.54, 164.45, 155.55, 430013.19902], + [1579910400000, 162.51, 160.35, 162.79, 157.61, 219921.65197], + [1579996800000, 160.36, 167.86, 168.08, 159.41, 251582.55758], + [1580083200000, 167.91, 170.08, 172.56, 165.22, 365894.81917], + [1580169600000, 170.04, 175.64, 176.2, 170.03, 473433.89609], + [1580256000000, 175.58, 173.72, 178.45, 173.33, 317382.90161], + [1580342400000, 173.68, 184.69, 187.0, 170.93, 477721.6609], + [1580428800000, 184.71, 179.99, 185.82, 175.22, 385596.53365], + [1580515200000, 179.94, 183.6, 184.28, 179.23, 259370.12902], + [1580601600000, 183.63, 188.44, 193.43, 179.1, 552621.13619], + [1580688000000, 188.48, 189.69, 195.19, 186.62, 417175.95781], + [1580774400000, 189.74, 188.91, 191.6, 184.69, 366389.69686], + [1580860800000, 188.91, 203.78, 207.61, 188.19, 550942.11417], + [1580947200000, 203.78, 213.19, 216.33, 201.02, 608240.2233], + [1581033600000, 213.16, 223.33, 225.0, 213.14, 629361.15466], + [1581120000000, 223.36, 223.05, 227.75, 213.22, 548551.87465], + [1581206400000, 223.01, 228.49, 230.65, 222.86, 350336.24399], + [1581292800000, 228.53, 222.89, 229.4, 216.37, 510415.49949], + [1581379200000, 222.89, 236.69, 239.15, 218.17, 595576.90276], + [1581465600000, 236.69, 265.74, 275.34, 236.69, 1038073.74782], + [1581552000000, 265.74, 268.32, 277.69, 256.08, 1089679.1537], + [1581638400000, 268.34, 285.15, 287.15, 260.28, 734944.32266], + [1581724800000, 285.11, 264.88, 288.41, 261.86, 860813.14274], + [1581811200000, 264.91, 258.85, 274.0, 237.41, 1110118.46395], + [1581897600000, 258.89, 267.85, 268.77, 242.0, 1110371.39094], + [1581984000000, 267.9, 282.61, 285.88, 258.0, 1115523.43992], + [1582070400000, 282.64, 258.45, 285.0, 251.56, 705973.72988], + [1582156800000, 258.44, 256.96, 264.33, 245.34, 972969.71691], + [1582243200000, 256.97, 265.27, 268.24, 253.61, 525827.8734], + [1582329600000, 265.32, 261.57, 266.81, 256.0, 313062.52133], + [1582416000000, 261.55, 274.48, 275.68, 261.02, 444740.82883], + [1582502400000, 274.5, 265.52, 277.2, 257.09, 696591.72983], + [1582588800000, 265.47, 246.67, 266.22, 244.44, 774791.01027], + [1582675200000, 246.67, 223.93, 250.32, 215.66, 1395879.41507], + [1582761600000, 223.98, 227.79, 238.3, 210.0, 1273793.11658], + [1582848000000, 227.73, 226.76, 234.67, 214.01, 1054994.92397], + [1582934400000, 226.76, 217.21, 233.0, 217.0, 546866.6851], + [1583020800000, 217.29, 217.81, 227.89, 212.36, 715016.01941], + [1583107200000, 217.81, 231.97, 234.4, 216.07, 810051.4833], + [1583193600000, 232.1, 223.91, 232.46, 219.57, 741498.54825], + [1583280000000, 223.84, 224.26, 228.85, 220.23, 443780.33772], + [1583366400000, 224.26, 228.38, 234.09, 224.23, 601479.87587], + [1583452800000, 228.38, 244.88, 245.16, 227.33, 628147.3257], + [1583539200000, 244.93, 237.23, 251.93, 236.0, 633748.89662], + [1583625600000, 237.23, 199.43, 237.23, 195.5, 1278973.53741], + [1583712000000, 199.43, 202.81, 208.62, 190.0, 1661331.83553], + [1583798400000, 202.79, 200.7, 206.2, 195.54, 1020260.107], + [1583884800000, 200.74, 194.61, 203.18, 181.73, 1079824.90167], + [1583971200000, 194.61, 107.82, 195.55, 101.2, 3814533.14046], + ]; + + const mappedCandles = candles.map(c => ({ + high: c[3], + low: c[4], + })); + + describe('replace', () => { + it('replaces the most recently added value', () => { + const ac = new AC(5, 34, 5); + const acWithReplace = new AC(5, 34, 5); + + ac.updates(mappedCandles, false); + acWithReplace.updates(mappedCandles, false); + + const correct = { + high: 200, + low: 100, + }; + const wrong = { + high: 5_000, + low: 3_000, + }; + + ac.add(correct); + acWithReplace.add(wrong); + acWithReplace.replace(correct); + + expect(acWithReplace.getResult().toFixed()).toBe(ac.getResult().toFixed()); + }); + }); + describe('getResult', () => { it('works with a signal line of SMA(5)', () => { const ac = new AC(5, 34, 5); const fasterAC = new FasterAC(5, 34, 5); - // Test data verified with: - // https://github.com/jesse-ai/jesse/blob/8e502d070c24bed29db80e1d0938781d8cdb1046/tests/data/test_candles_indicators.py#L4351 - const candles = [ - [1563408000000, 210.8, 225.73, 229.65, 205.71, 609081.49094], - [1563494400000, 225.75, 220.73, 226.23, 212.52, 371622.21865], - [1563580800000, 220.84, 228.2, 235.09, 219.78, 325393.97225], - [1563667200000, 228.25, 225.38, 229.66, 216.99, 270046.1519], - [1563753600000, 225.49, 217.51, 228.34, 212.25, 271310.40446], - [1563840000000, 217.59, 212.48, 219.55, 208.36, 317876.48242], - [1563926400000, 212.55, 216.31, 218.28, 202.0, 331162.6484], - [1564012800000, 216.31, 219.14, 225.12, 215.23, 280370.29627], - [1564099200000, 219.14, 218.81, 220.0, 212.71, 197781.98653], - [1564185600000, 218.81, 207.3, 223.3, 203.0, 301209.41113], - [1564272000000, 207.3, 211.62, 213.52, 198.24, 218801.16693], - [1564358400000, 211.58, 210.89, 215.83, 206.59, 226941.28], - [1564444800000, 210.84, 209.58, 214.36, 204.4, 222683.79393], - [1564531200000, 209.57, 218.42, 218.79, 209.2, 207213.55658], - [1564617600000, 218.42, 216.84, 219.39, 210.54, 186806.18844], - [1564704000000, 216.8, 217.61, 222.18, 214.31, 206867.03039], - [1564790400000, 217.69, 222.14, 224.51, 216.62, 181591.95296], - [1564876800000, 222.14, 221.79, 223.34, 216.9, 135622.0258], - [1564963200000, 221.79, 233.54, 236.25, 221.79, 307956.27211], - [1565049600000, 233.53, 226.28, 239.15, 223.03, 341279.08159], - [1565136000000, 226.31, 226.1, 231.25, 220.95, 279104.7037], - [1565222400000, 226.11, 221.39, 228.5, 215.51, 236886.35423], - [1565308800000, 221.38, 210.53, 221.79, 207.3, 232062.12757], - [1565395200000, 210.52, 206.48, 215.0, 202.6, 252614.02389], - [1565481600000, 206.48, 216.42, 216.94, 206.14, 188474.09048], - [1565568000000, 216.41, 211.41, 216.81, 209.75, 122760.94619], - [1565654400000, 211.58, 209.3, 214.3, 204.0, 166922.48201], - [1565740800000, 209.31, 187.1, 209.9, 183.49, 325228.98931], - [1565827200000, 187.08, 188.03, 189.95, 181.23, 237953.09426], - [1565913600000, 187.98, 184.88, 188.39, 178.04, 282177.01584], - [1566000000000, 184.83, 185.59, 187.0, 181.83, 138799.61508], - [1566086400000, 185.67, 194.33, 197.91, 183.35, 175363.5062], - [1566172800000, 194.32, 202.28, 203.59, 192.7, 239541.5978], - [1566259200000, 202.24, 196.6, 202.75, 194.45, 189297.75494], - [1566345600000, 196.55, 187.45, 197.2, 179.53, 284973.64194], - [1566432000000, 187.45, 190.35, 195.14, 182.8, 245575.98772], - [1566518400000, 190.36, 194.02, 196.19, 188.16, 192548.51552], - [1566604800000, 194.02, 190.6, 194.09, 185.63, 167806.34294], - [1566691200000, 190.6, 186.54, 192.4, 182.8, 169862.91522], - [1566777600000, 186.54, 188.67, 193.7, 186.0, 254397.79472], - [1566864000000, 188.61, 187.24, 189.49, 184.75, 157898.563], - [1566950400000, 187.3, 173.03, 188.25, 166.48, 334480.61761], - [1567036800000, 173.03, 169.01, 173.5, 163.61, 295241.216], - [1567123200000, 169.03, 168.5, 170.77, 165.55, 238616.68868], - [1567209600000, 168.48, 171.57, 174.98, 165.63, 194999.19583], - [1567296000000, 171.52, 170.74, 173.42, 167.61, 191140.52368], - [1567382400000, 170.73, 178.05, 181.0, 170.02, 294627.31247], - [1567468800000, 178.0, 178.75, 183.0, 174.09, 327857.85447], - [1567555200000, 178.79, 174.72, 180.14, 173.0, 286226.25171], - [1567641600000, 174.7, 173.75, 176.19, 168.1, 232753.83596], - [1567728000000, 173.74, 169.08, 177.87, 165.0, 315822.37984], - [1567814400000, 169.11, 177.62, 180.8, 168.3, 253831.23169], - [1567900800000, 177.58, 181.19, 184.18, 176.13, 290083.47501], - [1567987200000, 181.18, 180.54, 185.38, 176.01, 273729.94868], - [1568073600000, 180.52, 179.81, 184.36, 177.0, 238387.50999], - [1568160000000, 179.87, 178.28, 182.8, 173.0, 278555.46708], - [1568246400000, 178.3, 180.72, 182.38, 176.62, 203543.13663], - [1568332800000, 180.71, 180.95, 181.38, 177.54, 264422.54059], - [1568419200000, 180.96, 188.13, 188.79, 179.75, 279371.83423], - [1568505600000, 188.14, 189.03, 190.45, 185.76, 288928.60827], - [1568592000000, 189.05, 197.22, 199.44, 188.3, 551006.81686], - [1568678400000, 197.23, 207.84, 215.13, 195.74, 715863.2262], - [1568764800000, 207.85, 210.21, 217.27, 207.66, 539028.51013], - [1568851200000, 210.27, 220.24, 223.94, 202.3, 844358.82155], - [1568937600000, 220.26, 218.03, 221.54, 212.05, 437804.12669], - [1569024000000, 218.01, 215.05, 221.5, 213.2, 417891.5242], - [1569110400000, 215.04, 211.2, 215.61, 206.1, 445388.94787], - [1569196800000, 211.2, 201.29, 211.68, 198.65, 392437.07084], - [1569283200000, 201.25, 165.81, 202.98, 150.03, 1478218.82714], - [1569369600000, 165.72, 169.96, 174.85, 161.88, 879001.46213], - [1569456000000, 169.96, 165.92, 171.01, 152.11, 779942.17148], - [1569542400000, 165.92, 173.79, 176.72, 161.03, 634932.96707], - [1569628800000, 173.83, 173.49, 175.49, 168.0, 521775.46593], - [1569715200000, 173.5, 169.24, 174.5, 164.12, 410855.12176], - [1569801600000, 169.26, 180.85, 181.24, 165.01, 580295.3997], - [1569888000000, 180.89, 175.66, 185.53, 173.19, 609819.60828], - [1569974400000, 175.65, 180.24, 181.29, 173.65, 348268.1162], - [1570060800000, 180.24, 174.69, 180.72, 169.55, 354756.78478], - [1570147200000, 174.71, 175.55, 178.98, 170.74, 333897.63876], - [1570233600000, 175.55, 176.25, 176.71, 172.02, 278488.61771], - [1570320000000, 176.23, 170.1, 177.04, 167.68, 314932.39629], - [1570406400000, 170.08, 179.85, 182.32, 168.68, 496523.48038], - [1570492800000, 179.88, 180.6, 184.87, 177.0, 400832.37828], - [1570579200000, 180.61, 192.62, 195.53, 178.96, 562506.82189], - [1570665600000, 192.61, 191.14, 194.2, 186.88, 436588.58452], - [1570752000000, 191.18, 180.72, 196.65, 179.41, 621693.63125], - [1570838400000, 180.65, 179.68, 184.64, 177.59, 290415.22038], - [1570924800000, 179.65, 180.99, 184.95, 178.52, 247589.23231], - [1571011200000, 180.98, 186.72, 187.54, 180.43, 279732.84612], - [1571097600000, 186.7, 180.49, 188.37, 175.96, 405466.38109], - [1571184000000, 180.52, 174.47, 181.44, 171.81, 347764.93459], - [1571270400000, 174.52, 177.16, 178.96, 172.61, 298795.8198], - [1571356800000, 177.17, 172.74, 177.44, 168.66, 319602.48508], - [1571443200000, 172.78, 171.79, 174.98, 169.44, 296918.73026], - [1571529600000, 171.84, 175.22, 176.88, 169.21, 299141.07152], - [1571616000000, 175.18, 173.98, 177.9, 171.59, 270608.51385], - [1571702400000, 174.0, 171.2, 175.04, 170.3, 255429.41624], - [1571788800000, 171.19, 162.35, 171.49, 153.45, 746955.09806], - [1571875200000, 162.35, 160.38, 163.72, 158.72, 387310.83766], - [1571961600000, 160.39, 181.5, 187.78, 160.25, 904832.86059], - [1572048000000, 181.53, 179.49, 197.74, 173.8, 1211737.43684], - [1572134400000, 179.42, 183.75, 188.7, 176.22, 724423.40525], - [1572220800000, 183.84, 181.72, 189.48, 180.35, 582179.44545], - [1572307200000, 181.67, 190.46, 192.74, 181.26, 529964.5054], - [1572393600000, 190.45, 183.13, 191.71, 179.28, 537770.43056], - [1572480000000, 183.14, 182.18, 185.27, 177.66, 410969.86104], - [1572566400000, 182.19, 182.85, 184.5, 177.02, 331519.76963], - [1572652800000, 182.86, 182.91, 186.0, 181.53, 179864.39739], - [1572739200000, 182.9, 181.54, 184.7, 178.95, 232621.52147], - [1572825600000, 181.53, 185.71, 188.64, 180.36, 321175.29134], - [1572912000000, 185.71, 188.68, 192.51, 182.22, 389668.6472], - [1572998400000, 188.65, 191.16, 195.09, 187.72, 343219.9224], - [1573084800000, 191.16, 186.68, 192.27, 184.59, 309882.08206], - [1573171200000, 186.67, 183.74, 188.26, 181.41, 365029.75027], - [1573257600000, 183.71, 184.89, 185.79, 182.63, 192073.38044], - [1573344000000, 184.86, 188.96, 191.58, 183.3, 274940.53448], - [1573430400000, 188.96, 184.98, 190.19, 184.06, 255579.93429], - [1573516800000, 184.98, 187.09, 187.65, 182.41, 256782.63119], - [1573603200000, 187.09, 188.11, 189.66, 185.3, 197273.84001], - [1573689600000, 188.07, 184.92, 188.72, 183.34, 245505.29971], - [1573776000000, 184.93, 180.0, 186.7, 177.67, 407466.78964], - [1573862400000, 179.99, 182.37, 183.46, 179.3, 172801.52576], - [1573948800000, 182.37, 183.82, 186.09, 180.0, 198892.4372], - [1574035200000, 183.82, 178.2, 184.06, 175.01, 293551.23632], - [1574121600000, 178.2, 175.94, 178.52, 172.65, 275886.6411], - [1574208000000, 175.93, 174.72, 177.41, 173.5, 216315.93309], - [1574294400000, 174.75, 161.01, 175.85, 157.26, 473895.92992], - [1574380800000, 161.02, 149.56, 162.79, 138.0, 977977.23794], - [1574467200000, 149.55, 151.84, 154.33, 146.11, 369721.0996], - [1574553600000, 151.84, 139.96, 152.86, 138.62, 352319.21558], - [1574640000000, 139.99, 145.69, 151.5, 131.45, 749675.41303], - [1574726400000, 145.81, 147.47, 149.97, 143.37, 354023.04298], - [1574812800000, 147.47, 152.62, 155.54, 140.84, 564796.4284], - [1574899200000, 152.61, 150.72, 154.63, 149.09, 317714.56326], - [1574985600000, 150.69, 154.57, 157.6, 150.23, 328712.25558], - [1575072000000, 154.54, 151.37, 155.25, 149.7, 226863.41299], - [1575158400000, 151.43, 150.73, 152.49, 145.79, 344178.14088], - [1575244800000, 150.72, 148.65, 151.42, 146.71, 233839.0973], - [1575331200000, 148.66, 147.17, 149.93, 145.77, 196329.22503], - [1575417600000, 147.19, 145.38, 151.98, 143.15, 434430.62379], - [1575504000000, 145.45, 148.1, 149.02, 143.64, 299073.53972], - [1575590400000, 148.11, 148.45, 149.77, 145.74, 220674.68581], - [1575676800000, 148.46, 147.14, 149.49, 146.85, 140471.68588], - [1575763200000, 147.16, 150.44, 151.62, 146.11, 205301.6026], - [1575849600000, 150.44, 147.38, 151.19, 146.56, 243775.99249], - [1575936000000, 147.4, 145.56, 148.57, 143.81, 203215.84937], - [1576022400000, 145.53, 143.39, 146.34, 142.12, 157843.10484], - [1576108800000, 143.41, 144.87, 145.85, 139.24, 261615.30437], - [1576195200000, 144.87, 144.8, 146.0, 142.8, 160695.18556], - [1576281600000, 144.8, 141.79, 145.07, 141.18, 126232.59201], - [1576368000000, 141.79, 142.46, 144.12, 139.92, 151189.65877], - [1576454400000, 142.46, 132.73, 142.72, 127.93, 471018.85942], - [1576540800000, 132.72, 121.88, 132.98, 119.11, 563257.36001], - [1576627200000, 121.88, 132.78, 134.87, 116.26, 884960.91334], - [1576713600000, 132.8, 128.1, 134.0, 125.69, 420674.8172], - [1576800000000, 128.1, 128.19, 129.39, 125.84, 213897.4673], - [1576886400000, 128.19, 126.99, 128.4, 126.5, 135196.11641], - [1576972800000, 127.0, 132.09, 133.07, 126.82, 253140.72413], - [1577059200000, 132.12, 127.8, 135.1, 126.0, 421600.75655], - [1577145600000, 127.8, 127.75, 129.69, 126.61, 200637.10098], - [1577232000000, 127.7, 125.09, 127.84, 123.07, 225004.4909], - [1577318400000, 125.09, 125.58, 132.26, 124.32, 274986.52097], - [1577404800000, 125.58, 126.29, 127.1, 121.91, 240012.37451], - [1577491200000, 126.28, 128.11, 129.68, 125.84, 196893.52277], - [1577577600000, 128.11, 134.36, 138.07, 127.52, 316347.26666], - [1577664000000, 134.36, 131.59, 136.24, 130.3, 320347.21956], - [1577750400000, 131.61, 129.16, 133.68, 128.17, 264933.98418], - [1577836800000, 129.16, 130.77, 133.05, 128.68, 144770.52197], - [1577923200000, 130.72, 127.19, 130.78, 126.38, 213757.05806], - [1578009600000, 127.19, 134.35, 135.14, 125.88, 413055.18895], - [1578096000000, 134.37, 134.2, 135.85, 132.5, 184276.17102], - [1578182400000, 134.2, 135.37, 138.19, 134.19, 254120.45343], - [1578268800000, 135.37, 144.15, 144.41, 134.86, 408020.27375], - [1578355200000, 144.14, 142.8, 145.31, 138.76, 447762.17281], - [1578441600000, 142.8, 140.72, 147.77, 137.03, 570465.57764], - [1578528000000, 140.76, 137.74, 141.5, 135.3, 366076.06569], - [1578614400000, 137.73, 144.84, 145.17, 135.32, 409403.59507], - [1578700800000, 144.83, 142.38, 148.05, 142.09, 368350.57939], - [1578787200000, 142.4, 146.54, 146.6, 141.76, 229541.86137], - [1578873600000, 146.56, 143.58, 147.0, 142.27, 207996.61865], - [1578960000000, 143.58, 165.64, 171.7, 143.51, 1108476.31186], - [1579046400000, 165.6, 166.4, 171.98, 159.2, 721687.80381], - [1579132800000, 166.4, 164.21, 167.4, 157.8, 456170.86719], - [1579219200000, 164.24, 169.85, 174.81, 162.14, 767180.67853], - [1579305600000, 169.92, 174.14, 179.5, 164.92, 688783.17982], - [1579392000000, 174.1, 166.79, 178.05, 161.66, 624681.28604], - [1579478400000, 166.79, 166.87, 169.33, 161.24, 358092.8841], - [1579564800000, 166.86, 169.49, 170.32, 164.8, 308007.6353], - [1579651200000, 169.48, 168.07, 171.47, 166.03, 272240.90286], - [1579737600000, 168.07, 162.81, 168.2, 159.21, 373414.34985], - [1579824000000, 162.85, 162.54, 164.45, 155.55, 430013.19902], - [1579910400000, 162.51, 160.35, 162.79, 157.61, 219921.65197], - [1579996800000, 160.36, 167.86, 168.08, 159.41, 251582.55758], - [1580083200000, 167.91, 170.08, 172.56, 165.22, 365894.81917], - [1580169600000, 170.04, 175.64, 176.2, 170.03, 473433.89609], - [1580256000000, 175.58, 173.72, 178.45, 173.33, 317382.90161], - [1580342400000, 173.68, 184.69, 187.0, 170.93, 477721.6609], - [1580428800000, 184.71, 179.99, 185.82, 175.22, 385596.53365], - [1580515200000, 179.94, 183.6, 184.28, 179.23, 259370.12902], - [1580601600000, 183.63, 188.44, 193.43, 179.1, 552621.13619], - [1580688000000, 188.48, 189.69, 195.19, 186.62, 417175.95781], - [1580774400000, 189.74, 188.91, 191.6, 184.69, 366389.69686], - [1580860800000, 188.91, 203.78, 207.61, 188.19, 550942.11417], - [1580947200000, 203.78, 213.19, 216.33, 201.02, 608240.2233], - [1581033600000, 213.16, 223.33, 225.0, 213.14, 629361.15466], - [1581120000000, 223.36, 223.05, 227.75, 213.22, 548551.87465], - [1581206400000, 223.01, 228.49, 230.65, 222.86, 350336.24399], - [1581292800000, 228.53, 222.89, 229.4, 216.37, 510415.49949], - [1581379200000, 222.89, 236.69, 239.15, 218.17, 595576.90276], - [1581465600000, 236.69, 265.74, 275.34, 236.69, 1038073.74782], - [1581552000000, 265.74, 268.32, 277.69, 256.08, 1089679.1537], - [1581638400000, 268.34, 285.15, 287.15, 260.28, 734944.32266], - [1581724800000, 285.11, 264.88, 288.41, 261.86, 860813.14274], - [1581811200000, 264.91, 258.85, 274.0, 237.41, 1110118.46395], - [1581897600000, 258.89, 267.85, 268.77, 242.0, 1110371.39094], - [1581984000000, 267.9, 282.61, 285.88, 258.0, 1115523.43992], - [1582070400000, 282.64, 258.45, 285.0, 251.56, 705973.72988], - [1582156800000, 258.44, 256.96, 264.33, 245.34, 972969.71691], - [1582243200000, 256.97, 265.27, 268.24, 253.61, 525827.8734], - [1582329600000, 265.32, 261.57, 266.81, 256.0, 313062.52133], - [1582416000000, 261.55, 274.48, 275.68, 261.02, 444740.82883], - [1582502400000, 274.5, 265.52, 277.2, 257.09, 696591.72983], - [1582588800000, 265.47, 246.67, 266.22, 244.44, 774791.01027], - [1582675200000, 246.67, 223.93, 250.32, 215.66, 1395879.41507], - [1582761600000, 223.98, 227.79, 238.3, 210.0, 1273793.11658], - [1582848000000, 227.73, 226.76, 234.67, 214.01, 1054994.92397], - [1582934400000, 226.76, 217.21, 233.0, 217.0, 546866.6851], - [1583020800000, 217.29, 217.81, 227.89, 212.36, 715016.01941], - [1583107200000, 217.81, 231.97, 234.4, 216.07, 810051.4833], - [1583193600000, 232.1, 223.91, 232.46, 219.57, 741498.54825], - [1583280000000, 223.84, 224.26, 228.85, 220.23, 443780.33772], - [1583366400000, 224.26, 228.38, 234.09, 224.23, 601479.87587], - [1583452800000, 228.38, 244.88, 245.16, 227.33, 628147.3257], - [1583539200000, 244.93, 237.23, 251.93, 236.0, 633748.89662], - [1583625600000, 237.23, 199.43, 237.23, 195.5, 1278973.53741], - [1583712000000, 199.43, 202.81, 208.62, 190.0, 1661331.83553], - [1583798400000, 202.79, 200.7, 206.2, 195.54, 1020260.107], - [1583884800000, 200.74, 194.61, 203.18, 181.73, 1079824.90167], - [1583971200000, 194.61, 107.82, 195.55, 101.2, 3814533.14046], - ]; - - for (const candle of candles) { - const [, , , high, low] = candle; - const input: HighLowNumber = {high, low}; - ac.update(input); - fasterAC.update(input); + for (const candle of mappedCandles) { + ac.add(candle); + fasterAC.add(candle); } // Result verified with: diff --git a/src/AC/AC.ts b/src/AC/AC.ts index 64f78b8e6..0de6a1adf 100644 --- a/src/AC/AC.ts +++ b/src/AC/AC.ts @@ -1,9 +1,8 @@ -import {BigIndicatorSeries, NumberIndicatorSeries} from '../Indicator.js'; import {AO, FasterAO} from '../AO/AO.js'; -import {FasterSMA, SMA} from '../SMA/SMA.js'; +import {BigIndicatorSeries, NumberIndicatorSeries} from '../Indicator.js'; import {FasterMOM, MOM} from '../MOM/MOM.js'; +import {FasterSMA, SMA} from '../SMA/SMA.js'; import type {HighLow, HighLowNumber} from '../util/index.js'; -import type {Big} from '../index.js'; /** * Accelerator Oscillator (AC) @@ -33,16 +32,17 @@ export class AC extends BigIndicatorSeries { this.signal = new SMA(signalInterval); } - override update(input: HighLow, replace: boolean = false): void | Big { - const ao = this.ao.update(input); + update(input: HighLow, replace: boolean) { + const ao = this.ao.update(input, replace); if (ao) { - this.signal.update(ao); + this.signal.update(ao, replace); if (this.signal.isStable) { const result = this.setResult(ao.sub(this.signal.getResult()), replace); - this.momentum.update(result); - return this.result; + this.momentum.update(result, replace); + return result; } } + return null; } } @@ -62,15 +62,16 @@ export class FasterAC extends NumberIndicatorSeries { this.signal = new FasterSMA(signalInterval); } - override update(input: HighLowNumber, replace: boolean = false): void | number { - const ao = this.ao.update(input); + update(input: HighLowNumber, replace: boolean) { + const ao = this.ao.update(input, replace); if (ao) { - this.signal.update(ao); + this.signal.update(ao, replace); if (this.signal.isStable) { const result = this.setResult(ao - this.signal.getResult(), replace); - this.momentum.update(result); - return this.result; + this.momentum.update(result, replace); + return result; } } + return null; } } diff --git a/src/ADX/ADX.test.ts b/src/ADX/ADX.test.ts index 8f7f30b0e..543f245b3 100644 --- a/src/ADX/ADX.test.ts +++ b/src/ADX/ADX.test.ts @@ -1,36 +1,59 @@ import {ADX, FasterADX} from './ADX.js'; describe('ADX', () => { + // Test data verified with: + // https://tulipindicators.org/adx + const candles = [ + {close: 81.59, high: 82.15, low: 81.29}, + {close: 81.06, high: 81.89, low: 80.64}, + {close: 82.87, high: 83.03, low: 81.31}, + {close: 83.0, high: 83.3, low: 82.65}, + {close: 83.61, high: 83.85, low: 83.07}, + {close: 83.15, high: 83.9, low: 83.11}, + {close: 82.84, high: 83.33, low: 82.49}, + {close: 83.99, high: 84.3, low: 82.3}, + {close: 84.55, high: 84.84, low: 84.15}, + {close: 84.36, high: 85.0, low: 84.11}, + {close: 85.53, high: 85.9, low: 84.03}, + {close: 86.54, high: 86.58, low: 85.39}, + {close: 86.89, high: 86.98, low: 85.76}, + {close: 87.77, high: 88.0, low: 87.17}, + {close: 87.29, high: 87.87, low: 87.01}, + ]; + + describe('replace', () => { + it('replaces the most recently added value', () => { + const interval = 5; + const adx = new ADX(interval); + const adxWithReplace = new ADX(interval); + + adx.updates(candles, false); + adxWithReplace.updates(candles, false); + + const correct = {close: 90, high: 90, low: 90}; + const wrong = {close: 1_000, high: 1_000, low: 1_000}; + + adx.add(correct); + adxWithReplace.add(wrong); + + expect(adx.getResult().toFixed()).not.toBe(adxWithReplace.getResult().toFixed()); + + adxWithReplace.replace(correct); + + expect(adx.getResult().toFixed()).toBe(adxWithReplace.getResult().toFixed()); + }); + }); + describe('getResult', () => { it('calculates the Average Directional Index (ADX)', () => { - // Test data verified with: - // https://tulipindicators.org/adx - const candles = [ - {close: 81.59, high: 82.15, low: 81.29}, - {close: 81.06, high: 81.89, low: 80.64}, - {close: 82.87, high: 83.03, low: 81.31}, - {close: 83.0, high: 83.3, low: 82.65}, - {close: 83.61, high: 83.85, low: 83.07}, - {close: 83.15, high: 83.9, low: 83.11}, - {close: 82.84, high: 83.33, low: 82.49}, - {close: 83.99, high: 84.3, low: 82.3}, - {close: 84.55, high: 84.84, low: 84.15}, - {close: 84.36, high: 85.0, low: 84.11}, - {close: 85.53, high: 85.9, low: 84.03}, - {close: 86.54, high: 86.58, low: 85.39}, - {close: 86.89, high: 86.98, low: 85.76}, - {close: 87.77, high: 88.0, low: 87.17}, - {close: 87.29, high: 87.87, low: 87.01}, - ]; - const expectations = [41.38, 44.29, 49.42, 54.92, 59.99, 65.29, 67.36]; const adx = new ADX(5); const fasterADX = new FasterADX(5); for (const candle of candles) { - adx.update(candle); - fasterADX.update(candle); + adx.add(candle); + fasterADX.add(candle); if (adx.isStable && fasterADX.isStable) { const expected = expectations.shift(); expect(adx.getResult().toFixed(2)).toBe(`${expected}`); diff --git a/src/ADX/ADX.ts b/src/ADX/ADX.ts index e8a024f51..5665455fb 100644 --- a/src/ADX/ADX.ts +++ b/src/ADX/ADX.ts @@ -1,4 +1,4 @@ -import type {Big} from '../index.js'; +import type {Big} from 'big.js'; import {BigIndicatorSeries, NumberIndicatorSeries} from '../Indicator.js'; import type {FasterMovingAverage, MovingAverage} from '../MA/MovingAverage.js'; import type {HighLowClose, HighLowCloseNumber} from '../util/HighLowClose.js'; @@ -50,14 +50,18 @@ export class ADX extends BigIndicatorSeries { return this.dx.pdi; } - update(candle: HighLowClose, replace: boolean = false): Big | void { - const result = this.dx.update(candle); - if (result) { - this.adx.update(result); + update(candle: HighLowClose, replace: boolean) { + const result = this.dx.update(candle, replace); + + if (result !== null) { + this.adx.update(result, replace); } + if (this.adx.isStable) { return this.setResult(this.adx.getResult(), replace); } + + return null; } } @@ -82,13 +86,17 @@ export class FasterADX extends NumberIndicatorSeries { return this.dx.pdi; } - update(candle: HighLowCloseNumber, replace: boolean = false): void | number { - const result = this.dx.update(candle); - if (result !== undefined) { - this.adx.update(result); + update(candle: HighLowCloseNumber, replace: boolean) { + const result = this.dx.update(candle, replace); + + if (result !== null) { + this.adx.update(result, replace); } + if (this.adx.isStable) { return this.setResult(this.adx.getResult(), replace); } + + return null; } } diff --git a/src/AO/AO.test.ts b/src/AO/AO.test.ts index 1f7cf87d0..59b0ea3df 100644 --- a/src/AO/AO.test.ts +++ b/src/AO/AO.test.ts @@ -43,8 +43,8 @@ describe('AO', () => { high: highs[i], low: lows[i], }; - const result = ao.update(candle); - const fasterResult = fasterAO.update(candle); + const result = ao.add(candle); + const fasterResult = fasterAO.add(candle); if (ao.isStable && fasterAO.isStable) { expect(result).not.toBeUndefined(); expect(fasterResult).not.toBeUndefined(); @@ -83,11 +83,11 @@ describe('AO', () => { const fasterAO = new FasterAO(shortInterval, longInterval); lows.forEach((low, index) => { - ao.update({ + ao.add({ high: highs[index], low, }); - fasterAO.update({ + fasterAO.add({ high: highs[index], low, }); @@ -108,12 +108,12 @@ describe('AO', () => { const latestLow = '-11.50'; const latestHigh = '749.69'; - ao.update(latestValue); + ao.add(latestValue); expect(ao.getResult()?.toFixed(2)).toBe(latestResult); expect(ao.lowest?.toFixed(2)).toBe(latestLow); expect(ao.highest?.toFixed(2), 'new record high').toBe(latestHigh); - fasterAO.update(latestValue); + fasterAO.add(latestValue); expect(fasterAO.getResult()?.toFixed(2)).toBe(latestResult); expect(fasterAO.lowest?.toFixed(2)).toBe(latestLow); expect(fasterAO.highest?.toFixed(2), 'new record high').toBe(latestHigh); diff --git a/src/AO/AO.ts b/src/AO/AO.ts index 5d9d44a0e..9fb1f800d 100644 --- a/src/AO/AO.ts +++ b/src/AO/AO.ts @@ -1,9 +1,9 @@ import {BigIndicatorSeries, NumberIndicatorSeries} from '../Indicator.js'; -import {Big} from '../index.js'; import {FasterSMA, SMA} from '../SMA/SMA.js'; import type {HighLow, HighLowNumber} from '../util/index.js'; import type {FasterMovingAverageTypes, MovingAverageTypes} from '../MA/MovingAverageTypes.js'; import type {FasterMovingAverage, MovingAverage} from '../MA/MovingAverage.js'; +import Big from 'big.js'; /** * Awesome Oscillator (AO) @@ -33,7 +33,7 @@ export class AO extends BigIndicatorSeries { this.long = new SmoothingIndicator(longInterval); } - override update({low, high}: HighLow, replace: boolean = false): void | Big { + update({low, high}: HighLow, replace: boolean) { const candleSum = new Big(low).add(high); const medianPrice = candleSum.div(2); @@ -43,6 +43,8 @@ export class AO extends BigIndicatorSeries { if (this.long.isStable) { return this.setResult(this.short.getResult().sub(this.long.getResult()), replace); } + + return null; } } @@ -60,7 +62,7 @@ export class FasterAO extends NumberIndicatorSeries { this.long = new SmoothingIndicator(longInterval); } - override update({low, high}: HighLowNumber, replace: boolean = false): void | number { + update({low, high}: HighLowNumber, replace: boolean) { const medianPrice = (low + high) / 2; this.short.update(medianPrice, replace); @@ -69,5 +71,7 @@ export class FasterAO extends NumberIndicatorSeries { if (this.long.isStable) { return this.setResult(this.short.getResult() - this.long.getResult(), replace); } + + return null; } } diff --git a/src/ATR/ATR.test.ts b/src/ATR/ATR.test.ts index 4cc0fe31c..0d166fb6e 100644 --- a/src/ATR/ATR.test.ts +++ b/src/ATR/ATR.test.ts @@ -35,6 +35,29 @@ describe('ATR', () => { '1.14', ] as const; + describe('replace', () => { + it('replaces the most recently added value', () => { + const interval = 5; + const correct = {close: 3, high: 4, low: 1}; + const wrong = {close: 1_111, high: 9_999, low: 0}; + + const atr = new ATR(interval); + const atrWithReplace = new ATR(interval); + + atr.updates(candles, false); + atrWithReplace.updates(candles, false); + + atr.add(correct); + atrWithReplace.add(wrong); + + expect(atr.getResult().toFixed()).not.toBe(atrWithReplace.getResult().toFixed()); + + atrWithReplace.replace(correct); + + expect(atr.getResult().toFixed()).toBe(atrWithReplace.getResult().toFixed()); + }); + }); + describe('getResult', () => { it('calculates the Average True Range (ATR)', () => { const interval = 5; @@ -43,8 +66,8 @@ describe('ATR', () => { for (let i = 0; i < candles.length; i++) { const candle = candles[i]; - atr.update(candle); - fasterATR.update(candle); + atr.add(candle); + fasterATR.add(candle); if (atr.isStable && fasterATR.isStable) { const expected = expectations[i - (interval - 1)]; expect(atr.getResult().toFixed(2)).toBe(expected!); @@ -83,8 +106,8 @@ describe('ATR', () => { const fasterATR = new FasterATR(interval); for (const candle of candles) { - atr.update(candle); - fasterATR.update(candle); + atr.add(candle); + fasterATR.add(candle); } expect(atr.getResult().toFixed(2)).toBe('1.14'); @@ -101,12 +124,12 @@ describe('ATR', () => { const latestLow = '1.01'; const latestHigh = '250.85'; - atr.update(latestValue); + atr.add(latestValue); expect(atr.getResult().toFixed(2)).toBe(latestResult); expect(atr.lowest?.toFixed(2)).toBe(latestLow); expect(atr.highest?.toFixed(2), 'new record high').toBe(latestHigh); - fasterATR.update(latestValue); + fasterATR.add(latestValue); expect(fasterATR.getResult().toFixed(2)).toBe(latestResult); expect(fasterATR.lowest?.toFixed(2)).toBe(latestLow); expect(fasterATR.highest?.toFixed(2), 'new record high').toBe(latestHigh); diff --git a/src/ATR/ATR.ts b/src/ATR/ATR.ts index 6474a3f3b..14f276094 100644 --- a/src/ATR/ATR.ts +++ b/src/ATR/ATR.ts @@ -1,9 +1,8 @@ -import type {Big} from '../index.js'; import {BigIndicatorSeries, NumberIndicatorSeries} from '../Indicator.js'; import type {FasterMovingAverage, MovingAverage} from '../MA/MovingAverage.js'; import type {FasterMovingAverageTypes, MovingAverageTypes} from '../MA/MovingAverageTypes.js'; import {FasterTR, TR} from '../TR/TR.js'; -import type {HighLowClose, HighLowCloseNumber} from '../util/index.js'; +import type {HighLowClose, HighLowCloseNumber} from '../util/HighLowClose.js'; import {FasterWSMA, WSMA} from '../WSMA/WSMA.js'; /** @@ -41,12 +40,13 @@ export class ATR extends BigIndicatorSeries { this.smoothing = new SmoothingIndicator(interval); } - override update(candle: HighLowClose, replace: boolean = false): Big | void { + update(candle: HighLowClose, replace: boolean) { const trueRange = this.tr.update(candle, replace); this.smoothing.update(trueRange, replace); if (this.smoothing.isStable) { return this.setResult(this.smoothing.getResult(), replace); } + return null; } } @@ -63,11 +63,13 @@ export class FasterATR extends NumberIndicatorSeries { this.smoothing = new SmoothingIndicator(interval); } - update(candle: HighLowCloseNumber, replace: boolean = false): number | void { + update(candle: HighLowCloseNumber, replace: boolean) { const trueRange = this.tr.update(candle, replace); this.smoothing.update(trueRange, replace); if (this.smoothing.isStable) { return this.setResult(this.smoothing.getResult(), replace); } + + return null; } } diff --git a/src/BBANDS/BollingerBands.test.ts b/src/BBANDS/BollingerBands.test.ts index 3136fb14d..4a622c711 100644 --- a/src/BBANDS/BollingerBands.test.ts +++ b/src/BBANDS/BollingerBands.test.ts @@ -7,16 +7,15 @@ describe('BollingerBands', () => { describe('prices', () => { it('does not cache more prices than necessary to fill the interval', () => { const bb = new BollingerBands(3); - bb.update(1); - bb.update(2); + bb.updates([1, 2], false); expect(bb.prices.length).toBe(2); - bb.update(3); + bb.add(3); expect(bb.prices.length).toBe(3); - bb.update(4); + bb.add(4); expect(bb.prices.length).toBe(3); - bb.update(5); + bb.add(5); expect(bb.prices.length).toBe(3); - bb.update(6); + bb.add(6); expect(bb.prices.length).toBe(3); }); }); @@ -26,7 +25,7 @@ describe('BollingerBands', () => { const bb = new BollingerBands(20); data.prices.forEach((price, index) => { - bb.update(new Big(price)); + bb.add(new Big(price)); if (!bb.isStable) { return; @@ -126,7 +125,7 @@ describe('BollingerBands', () => { for (let i = 0; i < inputs.length; i++) { const price = inputs[i]; - bb.update(price); + bb.add(price); if (bb.isStable) { const {lower, middle, upper} = bb.getResult(); const expectedLow = expectedLows[i]; @@ -150,9 +149,7 @@ describe('FasterBollingerBands', () => { 81.59, 81.06, 82.87, 83.0, 83.61, 83.15, 82.84, 83.99, 84.55, 84.36, 85.53, 86.54, 86.89, 87.77, 87.29, ]; const fasterBB = new FasterBollingerBands(5, 2); - for (const price of prices) { - fasterBB.update(price); - } + fasterBB.updates(prices, false); expect(fasterBB.isStable).toBe(true); const actual = fasterBB.getResult(); expect(actual.lower.toFixed(2)).toBe('85.29'); diff --git a/src/BBANDS/BollingerBands.ts b/src/BBANDS/BollingerBands.ts index ecc16af34..1fdc4eacf 100644 --- a/src/BBANDS/BollingerBands.ts +++ b/src/BBANDS/BollingerBands.ts @@ -1,9 +1,9 @@ -import {Big, type BigSource} from '../index.js'; +import type {BigSource} from 'big.js'; +import Big from 'big.js'; +import {TechnicalIndicator} from '../Indicator.js'; import {SMA} from '../SMA/SMA.js'; -import {NotEnoughDataError} from '../error/index.js'; import type {BandsResult, FasterBandsResult} from '../util/BandsResult.js'; -import type {Indicator} from '../Indicator.js'; -import {getFasterAverage, getFasterStandardDeviation, getStandardDeviation} from '../util/index.js'; +import {getFasterAverage, getFasterStandardDeviation, getStandardDeviation, pushUpdate} from '../util/index.js'; /** * Bollinger Bands (BBANDS) @@ -20,9 +20,9 @@ import {getFasterAverage, getFasterStandardDeviation, getStandardDeviation} from * * @see https://www.investopedia.com/terms/b/bollingerbands.asp */ -export class BollingerBands implements Indicator { +export class BollingerBands extends TechnicalIndicator { + // TODO: Use "getFixedArray" public readonly prices: Big[] = []; - private result: BandsResult | undefined; /** * @param interval - The time period to be used in calculating the Middle Band @@ -32,14 +32,12 @@ export class BollingerBands implements Indicator { constructor( public readonly interval: number, public readonly deviationMultiplier: number = 2 - ) {} - - get isStable(): boolean { - return this.result !== undefined; + ) { + super(); } - update(price: BigSource): void | BandsResult { - this.prices.push(new Big(price)); + update(price: BigSource, replace: boolean) { + pushUpdate(this.prices, replace, new Big(price)); if (this.prices.length > this.interval) { this.prices.shift(); @@ -53,28 +51,23 @@ export class BollingerBands implements Indicator { upper: middle.add(standardDeviation.times(this.deviationMultiplier)), }); } - } - getResult(): BandsResult { - if (this.result === undefined) { - throw new NotEnoughDataError(); - } - - return this.result; + return null; } } -export class FasterBollingerBands implements Indicator { +export class FasterBollingerBands extends TechnicalIndicator { public readonly prices: number[] = []; - private result: FasterBandsResult | undefined; constructor( public readonly interval: number, public readonly deviationMultiplier: number = 2 - ) {} + ) { + super(); + } - update(price: number): void | FasterBandsResult { - this.prices.push(price); + update(price: number, replace: boolean) { + pushUpdate(this.prices, replace, price); if (this.prices.length > this.interval) { this.prices.shift(); @@ -88,17 +81,7 @@ export class FasterBollingerBands implements Indicator { upper: middle + standardDeviation * this.deviationMultiplier, }); } - } - - getResult(): FasterBandsResult { - if (this.result === undefined) { - throw new NotEnoughDataError(); - } - - return this.result; - } - get isStable(): boolean { - return this.result !== undefined; + return null; } } diff --git a/src/BBW/BollingerBandsWidth.test.ts b/src/BBW/BollingerBandsWidth.test.ts index d8a4f389f..4e76fbae0 100644 --- a/src/BBW/BollingerBandsWidth.test.ts +++ b/src/BBW/BollingerBandsWidth.test.ts @@ -47,8 +47,8 @@ describe('BollingerBandsWidth', () => { const fasterBBW = new FasterBollingerBandsWidth(new FasterBollingerBands(20, 2)); for (const {close} of candles) { - bbw.update(close); - fasterBBW.update(close); + bbw.add(close); + fasterBBW.add(close); if (bbw.isStable) { const expected = expectations.shift()!; expect(bbw.getResult().toFixed(2)).toBe(`${expected}`); diff --git a/src/BBW/BollingerBandsWidth.ts b/src/BBW/BollingerBandsWidth.ts index 613e64205..9384390cb 100644 --- a/src/BBW/BollingerBandsWidth.ts +++ b/src/BBW/BollingerBandsWidth.ts @@ -1,6 +1,6 @@ import {BigIndicatorSeries, NumberIndicatorSeries} from '../Indicator.js'; -import type {Big, BigSource} from '../index.js'; import type {BollingerBands, FasterBollingerBands} from '../BBANDS/BollingerBands.js'; +import type {BigSource} from 'big.js'; /** * The Bollinger Bands Width (BBW) indicator, developed by John A. Bollinger, merges the information of Bollinger Bands @@ -14,11 +14,13 @@ export class BollingerBandsWidth extends BigIndicatorSeries { super(); } - override update(price: BigSource): void | Big { - const result = this.bollingerBands.update(price); + update(price: BigSource, replace: boolean) { + const result = this.bollingerBands.update(price, replace); if (result) { - return this.setResult(result.upper.minus(result.lower).div(result.middle), false); + return this.setResult(result.upper.minus(result.lower).div(result.middle), replace); } + + return null; } } @@ -27,10 +29,12 @@ export class FasterBollingerBandsWidth extends NumberIndicatorSeries { super(); } - override update(price: number): void | number { - const result = this.bollingerBands.update(price); - if (result !== undefined) { - return this.setResult((result.upper - result.lower) / result.middle, false); + update(price: number, replace: boolean) { + const result = this.bollingerBands.update(price, replace); + if (result) { + return this.setResult((result.upper - result.lower) / result.middle, replace); } + + return null; } } diff --git a/src/CCI/CCI.test.ts b/src/CCI/CCI.test.ts index 9fd6aedcb..2deb9ecc4 100644 --- a/src/CCI/CCI.test.ts +++ b/src/CCI/CCI.test.ts @@ -4,7 +4,12 @@ import {NotEnoughDataError} from '../error/index.js'; describe('CCI', () => { // Test data verified with: // https://tulipindicators.org/cci + // @see https://github.com/TulipCharts/tulipindicators/blob/v0.9.1/tests/untest.txt#L99-L102 const candles = [ + {close: 81.59, high: 82.15, low: 81.29}, + {close: 81.06, high: 81.89, low: 80.64}, + {close: 82.87, high: 83.03, low: 81.31}, + {close: 83.0, high: 83.3, low: 82.65}, {close: 83.61, high: 83.85, low: 83.07}, {close: 83.15, high: 83.9, low: 83.11}, {close: 82.84, high: 83.33, low: 82.49}, @@ -17,19 +22,56 @@ describe('CCI', () => { {close: 87.77, high: 88.0, low: 87.17}, {close: 87.29, high: 87.87, low: 87.01}, ]; - const expectations = ['166.67', '82.02', '95.50', '130.91', '99.16', '116.34', '71.93']; + const expectations = [ + '105.01', + '64.24', + '-29.63', + '69.54', + // @see https://github.com/TulipCharts/tulipindicators/blob/v0.9.1/tests/untest.txt#L103 + '166.67', + '82.02', + '95.50', + '130.91', + '99.16', + '116.34', + '71.93', + ]; + + describe('replace', () => { + it('replaces the most recently added value', () => { + const interval = 5; + const cci = new CCI(interval); + const cciWithReplace = new CCI(interval); + + const correct = {close: 87.0, high: 89.89, low: 87.0}; + const wrong = {close: 3_333, high: 5_555, low: 1_111}; + + cci.updates(candles, false); + cciWithReplace.updates(candles, false); + + cci.add(correct); + cciWithReplace.add(wrong); + + expect(cci.getResult().toFixed()).not.toBe(cciWithReplace.getResult().toFixed()); + + cciWithReplace.replace(correct); + + expect(cci.getResult().toFixed()).toBe(cciWithReplace.getResult().toFixed()); + }); + }); describe('getResult', () => { it('calculates the Commodity Channel Index (CCI)', () => { - const cci = new CCI(5); - const fasterCCI = new FasterCCI(5); + const interval = 5; + const cci = new CCI(interval); + const fasterCCI = new FasterCCI(interval); for (const candle of candles) { - cci.update(candle); - fasterCCI.update(candle); + cci.add(candle); + fasterCCI.add(candle); if (cci.isStable && fasterCCI.isStable) { const expected = expectations.shift(); - expect(cci.getResult().toFixed(2)).toBe(expected!); - expect(fasterCCI.getResult().toFixed(2)).toBe(expected!); + expect(cci.getResult().toFixed(2)).toBe(expected); + expect(fasterCCI.getResult().toFixed(2)).toBe(expected); } } const actual = cci.getResult().toFixed(2); @@ -40,13 +82,13 @@ describe('CCI', () => { const cci = new CCI(5); const fasterCCI = new FasterCCI(5); for (const candle of candles) { - cci.update(candle); - fasterCCI.update(candle); + cci.add(candle); + fasterCCI.add(candle); } expect(cci.highest?.toFixed(2)).toBe('166.67'); - expect(cci.lowest?.toFixed(2)).toBe('71.93'); + expect(cci.lowest?.toFixed(2)).toBe('-29.63'); expect(fasterCCI.highest?.toFixed(2)).toBe('166.67'); - expect(fasterCCI.lowest?.toFixed(2)).toBe('71.93'); + expect(fasterCCI.lowest?.toFixed(2)).toBe('-29.63'); }); it('throws an error when there is not enough input data', () => { diff --git a/src/CCI/CCI.ts b/src/CCI/CCI.ts index c11216595..85ed96364 100644 --- a/src/CCI/CCI.ts +++ b/src/CCI/CCI.ts @@ -1,8 +1,9 @@ import {BigIndicatorSeries, NumberIndicatorSeries} from '../Indicator.js'; -import {Big, type BigSource} from '../index.js'; -import type {HighLowClose, HighLowCloseNumber} from '../util/index.js'; +import {getFixedArray, pushUpdate, type HighLowClose, type HighLowCloseNumber} from '../util/index.js'; import {FasterSMA, SMA} from '../SMA/SMA.js'; import {FasterMAD, MAD} from '../MAD/MAD.js'; +import type {BigSource} from 'big.js'; +import Big from 'big.js'; /** * Commodity Channel Index (CCI) @@ -13,73 +14,82 @@ import {FasterMAD, MAD} from '../MAD/MAD.js'; * which makes it an oscillator. Values above +100 imply an overbought condition, while values below −100 imply an * oversold condition. * + * Note: Traders often combine CCI with other indicators to confirm trends or signals, as using it alone can lead to false signals. + * It’s particularly useful in volatile markets or when identifying shorter-term trading opportunities. + * * According to * [Investopia.com](https://www.investopedia.com/articles/active-trading/031914/how-traders-can-utilize-cci-commodity-channel-index-trade-stock-trends.asp#multiple-timeframe-cci-strategy), * traders often buy when the CCI dips below -100 and then rallies back above -100 to sell the security when it moves * above +100 and then drops back below +100. * + * Interpretation: + * -100 and below: Indicates an oversold condition or the start of a strong downtrend. + * +100 and above: Indicates an overbought condition or the start of a strong uptrend. + * Values near 0 often signal a lack of clear momentum. + * * @see https://en.wikipedia.org/wiki/Commodity_channel_index */ export class CCI extends BigIndicatorSeries { public readonly prices: BigSource[] = []; private readonly sma: SMA; - private readonly typicalPrices: Big[] = []; + private readonly typicalPrices: Big[]; constructor(public readonly interval: number) { super(); this.sma = new SMA(this.interval); + this.typicalPrices = getFixedArray(interval); } - update(candle: HighLowClose): void | Big { - const typicalPrice = this.cacheTypicalPrice(candle); - this.sma.update(typicalPrice); + update(candle: HighLowClose, replace: boolean) { + const typicalPrice = this.cacheTypicalPrice(candle, replace); + this.sma.update(typicalPrice, replace); + if (this.sma.isStable) { const mean = this.sma.getResult(); const meanDeviation = MAD.getResultFromBatch(this.typicalPrices, mean); const numerator = typicalPrice.minus(mean); const denominator = new Big(0.015).mul(meanDeviation); - return this.setResult(numerator.div(denominator), false); + const result = numerator.div(denominator); + return this.setResult(result, replace); } + + return null; } - private cacheTypicalPrice({high, low, close}: HighLowClose): Big { + private cacheTypicalPrice({high, low, close}: HighLowClose, replace: boolean): Big { const typicalPrice = new Big(high).plus(low).plus(close).div(3); - this.typicalPrices.push(typicalPrice); - if (this.typicalPrices.length > this.interval) { - this.typicalPrices.shift(); - } - return typicalPrice; + return pushUpdate(this.typicalPrices, replace, typicalPrice); } } export class FasterCCI extends NumberIndicatorSeries { public readonly prices: number[] = []; private readonly sma: FasterSMA; - private readonly typicalPrices: number[] = []; + private readonly typicalPrices: number[]; constructor(public readonly interval: number) { super(); this.sma = new FasterSMA(this.interval); + this.typicalPrices = getFixedArray(interval); } - override update(candle: HighLowCloseNumber): void | number { - const typicalPrice = this.cacheTypicalPrice(candle); - this.sma.update(typicalPrice); + update(candle: HighLowCloseNumber, replace: boolean) { + const typicalPrice = this.cacheTypicalPrice(candle, replace); + this.sma.update(typicalPrice, replace); + if (this.sma.isStable) { const mean = this.sma.getResult(); const meanDeviation = FasterMAD.getResultFromBatch(this.typicalPrices, mean); const numerator = typicalPrice - mean; const denominator = 0.015 * meanDeviation; - return this.setResult(numerator / denominator, false); + return this.setResult(numerator / denominator, replace); } + + return null; } - private cacheTypicalPrice({high, low, close}: HighLowCloseNumber): number { + private cacheTypicalPrice({high, low, close}: HighLowCloseNumber, replace: boolean): number { const typicalPrice = (high + low + close) / 3; - this.typicalPrices.push(typicalPrice); - if (this.typicalPrices.length > this.interval) { - this.typicalPrices.shift(); - } - return typicalPrice; + return pushUpdate(this.typicalPrices, replace, typicalPrice); } } diff --git a/src/CG/CG.test.ts b/src/CG/CG.test.ts index 290b42006..a18f03214 100644 --- a/src/CG/CG.test.ts +++ b/src/CG/CG.test.ts @@ -5,16 +5,16 @@ describe('CG', () => { describe('prices', () => { it('does not cache more prices than necessary to fill the interval', () => { const cg = new CG(3, 6); - cg.update(1); - cg.update(2); + cg.add(1); + cg.add(2); expect(cg.prices.length).toBe(2); - cg.update(3); + cg.add(3); expect(cg.prices.length).toBe(3); - cg.update(4); + cg.add(4); expect(cg.prices.length).toBe(3); - cg.update(5); + cg.add(5); expect(cg.prices.length).toBe(3); - cg.update(6); + cg.add(6); expect(cg.prices.length).toBe(3); }); }); @@ -22,14 +22,14 @@ describe('CG', () => { describe('isStable', () => { it('is stable when the inputs can fill the signal interval', () => { const cg = new CG(5, 6); - cg.update(10); - cg.update(20); - cg.update(30); - cg.update(40); + cg.add(10); + cg.add(20); + cg.add(30); + cg.add(40); expect(cg.isStable).toBe(false); - cg.update(50); + cg.add(50); expect(cg.isStable).toBe(false); - cg.update(60); + cg.add(60); expect(cg.isStable).toBe(true); }); }); @@ -41,8 +41,8 @@ describe('CG', () => { const values = [100, 110, 120, 130, 140, 150, 160, 170, 180, 190, 200]; for (const value of values) { - cg.update(value); - fasterCG.update(value); + cg.add(value); + fasterCG.add(value); } // Add the latest value @@ -51,13 +51,13 @@ describe('CG', () => { const latestLow = '3.0851'; const latestHigh = '3.1176'; - cg.update(latestValue); + cg.add(latestValue); expect(cg.prices.length).toBe(5); expect(cg.getResult().toFixed(4)).toBe(latestResult); expect(cg.lowest?.toFixed(4)).toBe(latestLow); expect(cg.highest?.toFixed(4)).toBe(latestHigh); - fasterCG.update(latestValue); + fasterCG.add(latestValue); expect(fasterCG.prices.length).toBe(5); expect(fasterCG.getResult().toFixed(4)).toBe(latestResult); expect(fasterCG.lowest?.toFixed(4)).toBe(latestLow); @@ -102,15 +102,15 @@ describe('CG', () => { const fasterCG = new FasterCG(5, 10); const values = [100, 110, 120, 130, 140, 150, 160, 170, 180, 190, 200]; for (const value of values) { - cg.update(value); - fasterCG.update(value); + cg.add(value); + fasterCG.add(value); } let cgResult = cg.getResult(); let signalResult = cg.signal.getResult(); expect(cgResult.gt(signalResult)).toBe(true); [150, 110, 90, 130].forEach(price => { - cg.update(price); - fasterCG.update(price); + cg.add(price); + fasterCG.add(price); }); expect(cg.isStable).toBe(true); @@ -143,11 +143,11 @@ describe('CG', () => { it('is protected against division by zero errors', () => { const cg = new CG(1, 1); - cg.update(0); + cg.add(0); expect(cg.getResult().valueOf()).toBe('0'); const fasterCG = new FasterCG(1, 1); - fasterCG.update(0); + fasterCG.add(0); expect(fasterCG.getResult().valueOf()).toBe(0); }); }); diff --git a/src/CG/CG.ts b/src/CG/CG.ts index e2d9e9915..8a465068a 100644 --- a/src/CG/CG.ts +++ b/src/CG/CG.ts @@ -1,6 +1,8 @@ +import type {BigSource} from 'big.js'; +import Big from 'big.js'; import {BigIndicatorSeries, NumberIndicatorSeries} from '../Indicator.js'; -import {Big, type BigSource} from '../index.js'; import {FasterSMA, SMA} from '../SMA/SMA.js'; +import {pushUpdate} from '../util/pushUpdate.js'; /** * Center of Gravity (CG) @@ -17,7 +19,7 @@ import {FasterSMA, SMA} from '../SMA/SMA.js'; */ export class CG extends BigIndicatorSeries { public signal: SMA; - + // TODO: Use "getFixedArray" public readonly prices: Big[] = []; override get isStable(): boolean { @@ -32,12 +34,8 @@ export class CG extends BigIndicatorSeries { this.signal = new SMA(signalInterval); } - override update(price: BigSource, replace: boolean = false): void | Big { - if (this.prices.length && replace) { - this.prices[this.prices.length - 1] = new Big(price); - } else { - this.prices.push(new Big(price)); - } + update(price: BigSource, replace: boolean) { + pushUpdate(this.prices, replace, new Big(price)); if (this.prices.length > this.interval) { this.prices.shift(); @@ -59,6 +57,8 @@ export class CG extends BigIndicatorSeries { if (this.signal.isStable) { return this.setResult(cg, replace); } + + return null; } } @@ -79,12 +79,8 @@ export class FasterCG extends NumberIndicatorSeries { this.signal = new FasterSMA(signalInterval); } - override update(price: number, replace: boolean = false): void | number { - if (this.prices.length && replace) { - this.prices[this.prices.length - 1] = price; - } else { - this.prices.push(price); - } + update(price: number, replace: boolean) { + pushUpdate(this.prices, replace, price); if (this.prices.length > this.interval) { this.prices.shift(); @@ -106,5 +102,7 @@ export class FasterCG extends NumberIndicatorSeries { if (this.signal.isStable) { return this.setResult(cg, replace); } + + return null; } } diff --git a/src/DEMA/DEMA.test.ts b/src/DEMA/DEMA.test.ts index 4cbfb8500..044af316a 100644 --- a/src/DEMA/DEMA.test.ts +++ b/src/DEMA/DEMA.test.ts @@ -17,28 +17,28 @@ describe('DEMA', () => { it('can replace recently added values', () => { const dema = new DEMA(10); const fasterDEMA = new FasterDEMA(10); - dema.update(81); - fasterDEMA.update(81); - dema.update(24); - fasterDEMA.update(24); - dema.update(75); - fasterDEMA.update(75); - dema.update(21); - fasterDEMA.update(21); - dema.update(34); - fasterDEMA.update(34); - dema.update(25); - fasterDEMA.update(25); - dema.update(72); - fasterDEMA.update(72); - dema.update(92); - fasterDEMA.update(92); - dema.update(100); - fasterDEMA.update(100); + dema.add(81); + fasterDEMA.add(81); + dema.add(24); + fasterDEMA.add(24); + dema.add(75); + fasterDEMA.add(75); + dema.add(21); + fasterDEMA.add(21); + dema.add(34); + fasterDEMA.add(34); + dema.add(25); + fasterDEMA.add(25); + dema.add(72); + fasterDEMA.add(72); + dema.add(92); + fasterDEMA.add(92); + dema.add(100); + fasterDEMA.add(100); dema.update(99, true); fasterDEMA.update(99, true); - dema.update(2); - fasterDEMA.update(2); + dema.add(2); + fasterDEMA.add(2); expect(dema.isStable).toBe(true); expect(fasterDEMA.isStable).toBe(true); @@ -59,8 +59,8 @@ describe('DEMA', () => { const fasterDEMA = new FasterDEMA(10); prices.forEach((price, index) => { - dema.update(price); - fasterDEMA.update(price); + dema.add(price); + fasterDEMA.add(price); if (dema.isStable) { const result = new Big(dema10results[index]); expect(dema.getResult().toPrecision(12)).toEqual(result.toPrecision(12)); @@ -94,8 +94,8 @@ describe('DEMA', () => { it('is stable when there are enough inputs to fill the interval', () => { const dema = new DEMA(2); expect(dema.isStable).toBe(false); - dema.update(1); - dema.update(2); + dema.add(1); + dema.add(2); expect(dema.isStable).toBe(true); expect(dema.lowest?.toFixed(2)).toBe('1.00'); expect(dema.highest?.toFixed(2)).toBe('1.89'); diff --git a/src/DEMA/DEMA.ts b/src/DEMA/DEMA.ts index 39c594398..fad623ba0 100644 --- a/src/DEMA/DEMA.ts +++ b/src/DEMA/DEMA.ts @@ -1,4 +1,4 @@ -import type {Big, BigSource} from '../index.js'; +import type {BigSource} from 'big.js'; import {EMA, FasterEMA} from '../EMA/EMA.js'; import {BigIndicatorSeries, NumberIndicatorSeries} from '../Indicator.js'; @@ -22,7 +22,7 @@ export class DEMA extends BigIndicatorSeries { this.outer = new EMA(interval); } - override update(price: BigSource, replace: boolean = false): Big { + update(price: BigSource, replace: boolean): Big { const innerResult = this.inner.update(price, replace); const outerResult = this.outer.update(innerResult, replace); return this.setResult(innerResult.times(2).sub(outerResult), replace); @@ -43,7 +43,7 @@ export class FasterDEMA extends NumberIndicatorSeries { this.outer = new FasterEMA(interval); } - override update(price: number, replace: boolean = false): number { + update(price: number, replace: boolean): number { const innerResult = this.inner.update(price, replace); const outerResult = this.outer.update(innerResult, replace); return this.setResult(innerResult * 2 - outerResult, replace); diff --git a/src/DMA/DMA.test.ts b/src/DMA/DMA.test.ts index 490875312..045689f03 100644 --- a/src/DMA/DMA.test.ts +++ b/src/DMA/DMA.test.ts @@ -7,24 +7,14 @@ describe('DMA', () => { it('can replace recently added values', () => { const dma = new DMA(3, 6, SMA); const fasterDMA = new FasterDMA(3, 6, FasterSMA); - dma.update(41); - dma.update(37); - dma.update(20.9); - dma.update(100); - dma.update(30.71); - dma.update(40); + dma.updates([41, 37, 20.9, 100, 30.71, 40], false); dma.update(30, true); expect(dma.isStable).toBe(true); expect(dma.getResult().short.toFixed(8)).toBe('53.57000000'); expect(dma.getResult().long.toFixed(8)).toBe('43.26833333'); - fasterDMA.update(41); - fasterDMA.update(37); - fasterDMA.update(20.9); - fasterDMA.update(100); - fasterDMA.update(30.71); - fasterDMA.update(40); + fasterDMA.updates([41, 37, 20.9, 100, 30.71, 40], false); fasterDMA.update(30, true); expect(fasterDMA.isStable).toBe(true); @@ -36,24 +26,24 @@ describe('DMA', () => { describe('constructor', () => { it('can be used with simple moving averages', () => { const dma = new DMA(3, 6, SMA); - dma.update(41); - dma.update(37); - dma.update(20.9); - dma.update(100); - dma.update(30.71); - dma.update(30); + dma.add(41); + dma.add(37); + dma.add(20.9); + dma.add(100); + dma.add(30.71); + dma.add(30); expect(dma.getResult().short.toFixed(8)).toBe('53.57000000'); expect(dma.getResult().long.toFixed(8)).toBe('43.26833333'); }); it('can be used with exponential moving averages', () => { const dma = new DMA(3, 6, EMA); - dma.update(41); - dma.update(37); - dma.update(20.9); - dma.update(100); - dma.update(30.71); - dma.update(30); + dma.add(41); + dma.add(37); + dma.add(20.9); + dma.add(100); + dma.add(30.71); + dma.add(30); expect(dma.getResult().short.toFixed(8)).toBe('38.92125000'); expect(dma.getResult().long.toFixed(8)).toBe('41.96735289'); }); @@ -62,23 +52,23 @@ describe('DMA', () => { describe('isStable', () => { it('is dependant on the long interval (SMA)', () => { const dma = new DMA(3, 5); - dma.update(40); - dma.update(30); - dma.update(20); + dma.add(40); + dma.add(30); + dma.add(20); expect(dma.isStable).toBe(false); - dma.update(10); - dma.update(30); + dma.add(10); + dma.add(30); expect(dma.isStable).toBe(true); }); it('is dependant on the long interval (EMA)', () => { const dma = new DMA(3, 5, EMA); - dma.update(40); - dma.update(30); - dma.update(20); + dma.add(40); + dma.add(30); + dma.add(20); expect(dma.isStable).toBe(false); - dma.update(10); - dma.update(30); + dma.add(10); + dma.add(30); expect(dma.isStable).toBe(true); }); }); @@ -91,8 +81,8 @@ describe('DMA', () => { for (const oneHour of nineHours) { const price = oneHour.close; - dma.update(price); - fasterDMA.update(parseFloat(price)); + dma.add(price); + fasterDMA.add(parseFloat(price)); } const {short, long} = dma.getResult(); diff --git a/src/DMA/DMA.ts b/src/DMA/DMA.ts index 29ddae1a6..b41dca86c 100644 --- a/src/DMA/DMA.ts +++ b/src/DMA/DMA.ts @@ -1,5 +1,5 @@ -import type {Big, BigSource} from '../index.js'; -import type {Indicator} from '../Indicator.js'; +import type {BigSource} from 'big.js'; +import {TechnicalIndicator} from '../Indicator.js'; import type {FasterMovingAverage, MovingAverage} from '../MA/MovingAverage.js'; import type {FasterMovingAverageTypes, MovingAverageTypes} from '../MA/MovingAverageTypes.js'; import {FasterSMA, SMA} from '../SMA/SMA.js'; @@ -23,54 +23,60 @@ export interface FasterDMAResult { * * @see https://faculty.fuqua.duke.edu/~charvey/Teaching/BA453_2002/CCAM/CCAM.htm#_Toc2634228 */ -export class DMA implements Indicator { +export class DMA extends TechnicalIndicator { public readonly short: MovingAverage; public readonly long: MovingAverage; constructor(short: number, long: number, Indicator: MovingAverageTypes = SMA) { + super(); this.short = new Indicator(short); this.long = new Indicator(long); } - get isStable(): boolean { + override get isStable(): boolean { return this.long.isStable; } - update(price: BigSource, replace: boolean = false): void { + update(price: BigSource, replace: boolean) { this.short.update(price, replace); this.long.update(price, replace); - } - getResult(): DMAResult { - return { - long: this.long.getResult(), - short: this.short.getResult(), - }; + if (this.isStable) { + return (this.result = { + long: this.long.getResult(), + short: this.short.getResult(), + }); + } + + return null; } } -export class FasterDMA implements Indicator { +export class FasterDMA extends TechnicalIndicator { public readonly short: FasterMovingAverage; public readonly long: FasterMovingAverage; constructor(short: number, long: number, SmoothingIndicator: FasterMovingAverageTypes = FasterSMA) { + super(); this.short = new SmoothingIndicator(short); this.long = new SmoothingIndicator(long); } - get isStable(): boolean { + override get isStable(): boolean { return this.long.isStable; } - update(price: number, replace: boolean = false): void { + update(price: number, replace: boolean) { this.short.update(price, replace); this.long.update(price, replace); - } - getResult(): FasterDMAResult { - return { - long: this.long.getResult(), - short: this.short.getResult(), - }; + if (this.isStable) { + return (this.result = { + long: this.long.getResult(), + short: this.short.getResult(), + }); + } + + return null; } } diff --git a/src/DX/DX.test.ts b/src/DX/DX.test.ts index 54628d9e5..98fe7baa9 100644 --- a/src/DX/DX.test.ts +++ b/src/DX/DX.test.ts @@ -1,50 +1,90 @@ import {DX, FasterDX} from './DX.js'; describe('DX', () => { - describe('getResult', () => { - it('calculates the Directional Movement Index (DX)', () => { - // Test data verified with: - // https://tulipindicators.org/dx - const candles = [ - {close: 81.59, high: 82.15, low: 81.29}, - {close: 81.06, high: 81.89, low: 80.64}, - {close: 82.87, high: 83.03, low: 81.31}, - {close: 83.0, high: 83.3, low: 82.65}, - {close: 83.61, high: 83.85, low: 83.07}, - {close: 83.15, high: 83.9, low: 83.11}, - {close: 82.84, high: 83.33, low: 82.49}, - {close: 83.99, high: 84.3, low: 82.3}, - {close: 84.55, high: 84.84, low: 84.15}, - {close: 84.36, high: 85.0, low: 84.11}, - {close: 85.53, high: 85.9, low: 84.03}, - {close: 86.54, high: 86.58, low: 85.39}, - {close: 86.89, high: 86.98, low: 85.76}, - {close: 87.77, high: 88.0, low: 87.17}, - {close: 87.29, high: 87.87, low: 87.01}, - ]; + // Test data verified with: + // https://tulipindicators.org/dx + // @see https://github.com/TulipCharts/tulipindicators/blob/v0.9.1/tests/untest.txt#L167-L168 + const candles = [ + {close: 81.59, high: 82.15, low: 81.29}, + {close: 81.06, high: 81.89, low: 80.64}, + {close: 82.87, high: 83.03, low: 81.31}, + {close: 83.0, high: 83.3, low: 82.65}, + {close: 83.61, high: 83.85, low: 83.07}, + {close: 83.15, high: 83.9, low: 83.11}, + {close: 82.84, high: 83.33, low: 82.49}, + {close: 83.99, high: 84.3, low: 82.3}, + {close: 84.55, high: 84.84, low: 84.15}, + {close: 84.36, high: 85.0, low: 84.11}, + {close: 85.53, high: 85.9, low: 84.03}, + {close: 86.54, high: 86.58, low: 85.39}, + {close: 86.89, high: 86.98, low: 85.76}, + {close: 87.77, high: 88.0, low: 87.17}, + {close: 87.29, high: 87.87, low: 87.01}, + ]; - const expectations = [ - '50.19', - '51.36', - '11.09', - '41.52', - '52.77', - '55.91', - '69.96', - '76.90', // The official TI page has a rounding mistake here - '80.26', - '86.51', - '75.61', - ]; + // @see https://github.com/TulipCharts/tulipindicators/blob/v0.9.1/tests/untest.txt#L169 + const expectations = [ + '50.19', + '51.36', + '11.09', + '41.52', + '52.77', + '55.91', + '69.96', + '76.90', // The official TI page has a rounding mistake here + '80.26', + '86.51', + '75.61', + ]; - const dx = new DX(5); - const fasterDX = new FasterDX(5); + describe('replace', () => { + it('replaces the most recently added value', () => { + const interval = 5; + + const correct = {close: 1_000, high: 1_000, low: 1_000}; + const wrong = {close: 9_000, high: 9_000, low: 9_000}; + + const dx = new DX(interval); + const fasterDX = new FasterDX(interval); + + const dxWithReplace = new DX(interval); + const fasterDXWithReplace = new FasterDX(interval); + + dx.updates(candles, false); + fasterDX.updates(candles, false); + + dxWithReplace.updates(candles, false); + fasterDXWithReplace.updates(candles, false); + + dx.add(correct); + fasterDX.add(correct); + + dxWithReplace.add(wrong); + fasterDXWithReplace.add(wrong); + + // We need to verify the four decimal places, as the results are otherwise too similar: + expect(dx.getResult().toFixed(4)).not.toBe(dxWithReplace.getResult().toFixed(4)); + expect(fasterDX.getResult().toFixed(4)).not.toBe(fasterDXWithReplace.getResult().toFixed(4)); + + dxWithReplace.replace(correct); + fasterDXWithReplace.replace(correct); + + expect(dx.getResult().toFixed(4)).toBe(dxWithReplace.getResult().toFixed(4)); + expect(fasterDX.getResult().toFixed(4)).toBe(fasterDXWithReplace.getResult().toFixed(4)); + }); + }); + + describe('getResult', () => { + it('calculates the Directional Movement Index (DX)', () => { + const interval = 5; + const dx = new DX(interval); + const fasterDX = new FasterDX(interval); for (const candle of candles) { - dx.update(candle); - fasterDX.update(candle); + dx.add(candle); + fasterDX.add(candle); if (dx.isStable && fasterDX.isStable) { - const expected = expectations.shift()!; + const expected = expectations.shift(); expect(dx.getResult().toFixed(2)).toBe(expected); expect(fasterDX.getResult().toFixed(2)).toBe(expected); } @@ -75,10 +115,8 @@ describe('DX', () => { const dx = new DX(5); const fasterDX = new FasterDX(5); - for (const candle of candles) { - dx.update(candle); - fasterDX.update(candle); - } + dx.updates(candles, false); + fasterDX.updates(candles, false); expect(dx.isStable).toBe(true); expect(fasterDX.isStable).toBe(true); diff --git a/src/DX/DX.ts b/src/DX/DX.ts index 8e79471e2..e2a98aa8e 100644 --- a/src/DX/DX.ts +++ b/src/DX/DX.ts @@ -1,10 +1,11 @@ import {BigIndicatorSeries, NumberIndicatorSeries} from '../Indicator.js'; -import type {HighLowClose, HighLowCloseNumber} from '../util/index.js'; -import {Big, type BigSource} from '../index.js'; import type {FasterMovingAverage, MovingAverage} from '../MA/MovingAverage.js'; import type {FasterMovingAverageTypes, MovingAverageTypes} from '../MA/MovingAverageTypes.js'; import {FasterWSMA, WSMA} from '../WSMA/WSMA.js'; import {ATR, FasterATR} from '../ATR/ATR.js'; +import type {BigSource} from 'big.js'; +import Big from 'big.js'; +import type {HighLowClose, HighLowCloseNumber} from '../util/HighLowClose.js'; /** * Directional Movement Index (DMI / DX) @@ -23,6 +24,7 @@ export class DX extends BigIndicatorSeries { private readonly movesUp: MovingAverage; private readonly movesDown: MovingAverage; private previousCandle?: HighLowClose; + private secondLastCandle?: HighLowClose; private readonly atr: ATR; /** Minus Directional Indicator (-DI) */ public mdi?: Big; @@ -39,17 +41,24 @@ export class DX extends BigIndicatorSeries { this.movesUp = new SmoothingIndicator(this.interval); } - private updateState(candle: HighLowClose, pdm: BigSource = 0, mdm: BigSource = 0): void { - this.atr.update(candle); - this.movesDown.update(mdm); - this.movesUp.update(pdm); + private updateState(candle: HighLowClose, pdm: BigSource, mdm: BigSource, replace: boolean): void { + this.atr.update(candle, replace); + this.movesDown.update(mdm, replace); + this.movesUp.update(pdm, replace); + if (this.previousCandle) { + this.secondLastCandle = this.previousCandle; + } this.previousCandle = candle; } - update(candle: HighLowClose): Big | void { + update(candle: HighLowClose, replace: boolean) { if (!this.previousCandle) { - this.updateState(candle); - return; + this.updateState(candle, 0, 0, replace); + return null; + } + + if (this.secondLastCandle && replace) { + this.previousCandle = this.secondLastCandle; } const currentHigh = new Big(candle.high); @@ -73,7 +82,7 @@ export class DX extends BigIndicatorSeries { // Minus Directional Movement (-DM) const mdm = noLowerLows || highsRiseFaster ? new Big(0) : lowerLow; - this.updateState(candle, pdm, mdm); + this.updateState(candle, pdm, mdm, replace); if (this.movesUp.isStable) { this.pdi = this.movesUp.getResult().div(this.atr.getResult()); @@ -84,11 +93,13 @@ export class DX extends BigIndicatorSeries { // Prevent division by zero if (dmSum.eq(0)) { - return this.setResult(new Big(0), false); + return this.setResult(new Big(0), replace); } - return this.setResult(dmDiff.div(dmSum).mul(100), false); + return this.setResult(dmDiff.div(dmSum).mul(100), replace); } + + return null; } } @@ -96,6 +107,7 @@ export class FasterDX extends NumberIndicatorSeries { private readonly movesUp: FasterMovingAverage; private readonly movesDown: FasterMovingAverage; private previousCandle?: HighLowCloseNumber; + private secondLastCandle?: HighLowCloseNumber; private readonly atr: FasterATR; public mdi?: number; public pdi?: number; @@ -110,17 +122,24 @@ export class FasterDX extends NumberIndicatorSeries { this.movesUp = new SmoothingIndicator(this.interval); } - private updateState(candle: HighLowCloseNumber, pdm: number = 0, mdm: number = 0): void { - this.atr.update(candle); - this.movesUp.update(pdm); - this.movesDown.update(mdm); + private updateState(candle: HighLowCloseNumber, pdm: number, mdm: number, replace: boolean): void { + this.atr.update(candle, replace); + this.movesUp.update(pdm, replace); + this.movesDown.update(mdm, replace); + if (this.previousCandle) { + this.secondLastCandle = this.previousCandle; + } this.previousCandle = candle; } - update(candle: HighLowCloseNumber): number | void { + update(candle: HighLowCloseNumber, replace: boolean) { if (!this.previousCandle) { - this.updateState(candle); - return; + this.updateState(candle, 0, 0, replace); + return null; + } + + if (this.secondLastCandle && replace) { + this.previousCandle = this.secondLastCandle; } const currentHigh = candle.high; @@ -142,7 +161,7 @@ export class FasterDX extends NumberIndicatorSeries { const mdm = noLowerLows || highsRiseFaster ? 0 : lowerLow; - this.updateState(candle, pdm, mdm); + this.updateState(candle, pdm, mdm, replace); if (this.movesUp.isStable) { this.pdi = this.movesUp.getResult() / this.atr.getResult(); @@ -152,10 +171,12 @@ export class FasterDX extends NumberIndicatorSeries { const dmSum = this.pdi + this.mdi; if (dmSum === 0) { - return this.setResult(0, false); + return this.setResult(0, replace); } - return this.setResult((dmDiff / dmSum) * 100, false); + return this.setResult((dmDiff / dmSum) * 100, replace); } + + return null; } } diff --git a/src/EMA/EMA.test.ts b/src/EMA/EMA.test.ts index 6e131ba12..5fa8389e4 100644 --- a/src/EMA/EMA.test.ts +++ b/src/EMA/EMA.test.ts @@ -22,18 +22,37 @@ describe('EMA', () => { ] as const; describe('replace', () => { + it('replaces the most recently added value', () => { + const interval = 5; + const ema = new EMA(interval); + const emaWithReplace = new EMA(interval); + + const subset = [prices[0], prices[1], prices[2]]; + + ema.updates([...subset, prices[3], prices[4]], false); + + emaWithReplace.updates([...subset, '8239239'], false); + emaWithReplace.replace(prices[3]); + emaWithReplace.add(prices[4]); + + const actual = emaWithReplace.getResult().toFixed(); + const expected = ema.getResult().toFixed(); + + expect(actual).toBe(expected); + }); + it('replaces recently added values', () => { const interval = 5; const ema = new EMA(interval); const fasterEMA = new FasterEMA(interval); - ema.update('81.59'); - fasterEMA.update(81.59); - ema.update('81.06'); - fasterEMA.update(81.06); - ema.update('82.87'); - fasterEMA.update(82.87); - ema.update('83.0'); - fasterEMA.update(83.0); + ema.add('81.59'); + fasterEMA.add(81.59); + ema.add('81.06'); + fasterEMA.add(81.06); + ema.add('82.87'); + fasterEMA.add(82.87); + ema.add('83.0'); + fasterEMA.add(83.0); // Add the latest value const latestValue = 90; @@ -41,12 +60,12 @@ describe('EMA', () => { const latestLow = '81.41'; const latestHigh = '84.84'; - ema.update(latestValue); + ema.add(latestValue); expect(ema.getResult()?.toFixed(2)).toBe(latestResult); expect(ema.lowest?.toFixed(2)).toBe(latestLow); expect(ema.highest?.toFixed(2)).toBe(latestHigh); - fasterEMA.update(latestValue); + fasterEMA.add(latestValue); expect(fasterEMA.getResult()?.toFixed(2)).toBe(latestResult); expect(fasterEMA.lowest?.toFixed(2)).toBe(latestLow); expect(fasterEMA.highest?.toFixed(2)).toBe(latestHigh); @@ -82,18 +101,18 @@ describe('EMA', () => { it('will simply add prices when there are no prices to replace', () => { const ema = new EMA(5); ema.update(prices[0], true); - ema.update(prices[1]); - ema.update(prices[2]); - ema.update(prices[3]); - ema.update(prices[4]); + ema.add(prices[1]); + ema.add(prices[2]); + ema.add(prices[3]); + ema.add(prices[4]); expect(ema.getResult().toFixed(2)).toBe('82.71'); const fasterEMA = new FasterEMA(5); fasterEMA.update(prices[0], true); - fasterEMA.update(prices[1]); - fasterEMA.update(prices[2]); - fasterEMA.update(prices[3]); - fasterEMA.update(prices[4]); + fasterEMA.add(prices[1]); + fasterEMA.add(prices[2]); + fasterEMA.add(prices[3]); + fasterEMA.add(prices[4]); }); }); @@ -104,8 +123,8 @@ describe('EMA', () => { const fasterEMA = new FasterEMA(interval); for (let i = 0; i < prices.length; i++) { const price = prices[i]; - ema.update(price); - fasterEMA.update(price); + ema.add(price); + fasterEMA.add(price); if (ema.isStable && fasterEMA.isStable) { const expected = expectations[i - (interval - 1)]; expect(ema.getResult().toFixed(2)).toBe(expected); diff --git a/src/EMA/EMA.ts b/src/EMA/EMA.ts index f0f69497c..9eca55a1e 100644 --- a/src/EMA/EMA.ts +++ b/src/EMA/EMA.ts @@ -1,6 +1,7 @@ -import {Big, type BigSource} from '../index.js'; +import type {BigSource} from 'big.js'; import {FasterMovingAverage, MovingAverage} from '../MA/MovingAverage.js'; import {NotEnoughDataError} from '../error/index.js'; +import Big from 'big.js'; /** * Exponential Moving Average (EMA) @@ -15,12 +16,12 @@ export class EMA extends MovingAverage { private pricesCounter = 0; private readonly weightFactor: number; - constructor(public readonly interval: number) { + constructor(public override readonly interval: number) { super(interval); this.weightFactor = 2 / (this.interval + 1); } - update(_price: BigSource, replace: boolean = false): Big { + update(_price: BigSource, replace: boolean): Big { if (!replace) { this.pricesCounter++; } else if (replace && this.pricesCounter === 0) { @@ -62,12 +63,12 @@ export class FasterEMA extends FasterMovingAverage { private pricesCounter = 0; private readonly weightFactor: number; - constructor(public readonly interval: number) { + constructor(public override readonly interval: number) { super(interval); this.weightFactor = 2 / (this.interval + 1); } - update(price: number, replace: boolean = false): number { + update(price: number, replace: boolean): number { if (!replace) { this.pricesCounter++; } else if (replace && this.pricesCounter === 0) { diff --git a/src/Indicator.test.ts b/src/Indicator.test.ts index e29b7325c..4713dbfe7 100644 --- a/src/Indicator.test.ts +++ b/src/Indicator.test.ts @@ -6,7 +6,7 @@ describe('Indicator', () => { class IndicatorTestClass extends BigIndicatorSeries { public readonly inputs: Big[] = []; - update(input: BigSource, replace: boolean = false): void | Big { + update(input: BigSource, replace: boolean) { if (replace) { this.inputs.pop(); } @@ -20,7 +20,7 @@ describe('Indicator', () => { it('is unstable when no values are entered', () => { const itc = new IndicatorTestClass(); expect(itc.isStable).toBe(false); - itc.update(1); + itc.add(1); expect(itc.isStable).toBe(true); }); }); @@ -38,8 +38,7 @@ describe('Indicator', () => { it('returns the cross sum', () => { const itc = new IndicatorTestClass(); - itc.update(20); - itc.update(40); + itc.updates([20, 40], false); expect(itc.getResult().toString()).toBe('30'); }); }); @@ -50,7 +49,7 @@ describe('Indicator', () => { expect(itc.lowest).toBeUndefined(); expect(itc.highest).toBeUndefined(); - itc.update(100); + itc.add(100); expect(itc.inputs.length).toBe(1); expect(itc.getResult().toString()).toBe('100'); expect(itc.lowest?.toString()).toBe('100'); @@ -68,7 +67,7 @@ describe('Indicator', () => { expect(itc.lowest?.toString()).toBe('60'); expect(itc.highest?.toString()).toBe('60'); - itc.update(20); + itc.add(20); expect(itc.inputs.length).toBe(2); expect(itc.getResult().toString()).toBe('40'); expect(itc.lowest?.toString(), 'lowest cross sum seen (60+20/2)').toBe('40'); @@ -81,7 +80,7 @@ describe('Indicator', () => { expect(itc.lowest?.toString(), 'lowest cross sum seen (60+20/2)').toBe('40'); expect(itc.highest?.toString(), 'highest cross sum seen (60/1)').toBe('60'); - itc.update(211); + itc.add(211); expect(itc.inputs.length).toBe(3); expect(itc.getResult().toString()).toBe('97'); expect(itc.lowest?.toString()).toBe('40'); diff --git a/src/Indicator.ts b/src/Indicator.ts index 759d76fbb..14c845b1e 100644 --- a/src/Indicator.ts +++ b/src/Indicator.ts @@ -1,45 +1,59 @@ -import {NotEnoughDataError} from './error/index.js'; -import type {Big, BigSource} from './index.js'; +import type {BigSource} from 'big.js'; +import {NotEnoughDataError} from './error/NotEnoughDataError.js'; +import {getLastFromForEach} from './util/getLastFromForEach.js'; -export interface Indicator { +interface Indicator { getResult(): Result; - isStable: boolean; - - update(input: Input): void | Result; + add(input: Input): Result | null; + replace(input: Input): Result | null; + update(input: Input, replace: boolean): Result | null; + updates(input: Input[], replace: boolean): Result | null; } -/** - * Tracks results of an indicator over time and memorizes the highest & lowest result. - */ -export interface IndicatorSeries extends Indicator { - highest?: Result; - lowest?: Result; -} +export abstract class TechnicalIndicator implements Indicator { + protected result: Result | undefined; -export abstract class BigIndicatorSeries implements IndicatorSeries { - /** Highest return value over the lifetime (not interval!) of the indicator. */ - protected previousHighest?: Big; - highest?: Big; - /** Lowest return value over the lifetime (not interval!) of the indicator. */ - protected previousLowest?: Big; - lowest?: Big; - /** Previous results can be useful, if a user wants to update a recent value instead of adding a new value. Essential for real-time data like growing candlesticks. */ - protected previousResult?: Big; - protected result?: Big; + getResult() { + if (this.result === undefined) { + throw new NotEnoughDataError(); + } + + return this.result; + } get isStable(): boolean { return this.result !== undefined; } - getResult(): Big { - if (this.result === undefined) { - throw new NotEnoughDataError(); - } + add(input: Input) { + return this.update(input, false); + } - return this.result; + replace(input: Input) { + return this.update(input, true); } + abstract update(input: Input, replace: boolean): Result | null; + + updates(inputs: readonly Input[], replace: boolean = false) { + return getLastFromForEach(inputs, input => this.update(input, replace)); + } +} + +/** + * Tracks results of an indicator over time and memorizes the highest & lowest result. + */ +export abstract class BaseIndicatorSeries extends TechnicalIndicator { + protected previousHighest?: Result; + highest?: Result; + protected previousLowest?: Result; + lowest?: Result; + protected previousResult?: Result; + protected abstract setResult(value: Result, replace: boolean): Result; +} + +export abstract class BigIndicatorSeries extends BaseIndicatorSeries { protected setResult(value: Big, replace: boolean): Big { // Load cached values when replacing the latest value if (replace) { @@ -73,36 +87,9 @@ export abstract class BigIndicatorSeries implements Indicator // Set new result return (this.result = value); } - - abstract update(input: Input, replace?: boolean): void | Big; - - replace(input: Input) { - return this.update(input, true); - } } -export abstract class NumberIndicatorSeries implements IndicatorSeries { - /** Highest return value over the lifetime (not interval!) of the indicator. */ - protected previousHighest?: number; - highest?: number; - /** Lowest return value over the lifetime (not interval!) of the indicator. */ - protected previousLowest?: number; - lowest?: number; - protected previousResult?: number; - protected result?: number; - - get isStable(): boolean { - return this.result !== undefined; - } - - getResult(): number { - if (this.result === undefined) { - throw new NotEnoughDataError(); - } - - return this.result; - } - +export abstract class NumberIndicatorSeries extends BaseIndicatorSeries { protected setResult(value: number, replace: boolean): number { // Load cached values when replacing the latest value if (replace) { @@ -136,10 +123,4 @@ export abstract class NumberIndicatorSeries implements Indicator // Set new result return (this.result = value); } - - abstract update(input: Input, replace?: boolean): void | number; - - replace(input: Input) { - return this.update(input, true); - } } diff --git a/src/MA/MovingAverage.test.ts b/src/MA/MovingAverage.test.ts index 92c5c695e..786c1ef1b 100644 --- a/src/MA/MovingAverage.test.ts +++ b/src/MA/MovingAverage.test.ts @@ -4,7 +4,7 @@ class MyAverage extends FasterMovingAverage { iterations = 0; total = 0; - update(price: number): number | void { + update(price: number) { if (this.result === undefined) { this.result = 0; } @@ -19,8 +19,8 @@ describe('FasterMovingAverage', () => { const average = new MyAverage(Infinity); expect(average.isStable).toBe(false); expect(() => average.getResult()).toThrowError(); - average.update(50); - average.update(100); + average.add(50); + average.add(100); const result = average.getResult(); expect(result).toBe(75); }); diff --git a/src/MA/MovingAverage.ts b/src/MA/MovingAverage.ts index 6d546c3d5..3e07b6f94 100644 --- a/src/MA/MovingAverage.ts +++ b/src/MA/MovingAverage.ts @@ -1,4 +1,3 @@ -import type {Big, BigSource} from '../index.js'; import {BigIndicatorSeries, NumberIndicatorSeries} from '../Indicator.js'; /** @@ -13,32 +12,10 @@ export abstract class MovingAverage extends BigIndicatorSeries { constructor(public readonly interval: number) { super(); } - - updates(prices: BigSource[]): Big | void { - prices.forEach(price => this.update(price)); - return this.result; - } - - abstract update(price: BigSource, replace?: boolean): Big | void; - - replace(price: BigSource) { - return this.update(price, true); - } } export abstract class FasterMovingAverage extends NumberIndicatorSeries { constructor(public readonly interval: number) { super(); } - - updates(prices: number[]): number | void { - prices.forEach(price => this.update(price)); - return this.result; - } - - abstract update(price: number, replace?: boolean): number | void; - - replace(price: number) { - return this.update(price, true); - } } diff --git a/src/MACD/MACD.test.ts b/src/MACD/MACD.test.ts index 1abe8f6c5..478e06a09 100644 --- a/src/MACD/MACD.test.ts +++ b/src/MACD/MACD.test.ts @@ -2,6 +2,37 @@ import {FasterMACD, MACD} from './MACD.js'; import {Big, DEMA, EMA, FasterEMA, NotEnoughDataError} from '../index.js'; describe('MACD', () => { + describe('replace', () => { + it('replaces the most recently added value', () => { + const macd = new MACD({ + indicator: EMA, + longInterval: 5, + shortInterval: 2, + signalInterval: 9, + }); + const macdWithReplace = new MACD({ + indicator: EMA, + longInterval: 5, + shortInterval: 2, + signalInterval: 9, + }); + + const subset = ['10', '20', '80', '81.59', '81.06', '82.87', '83.0']; + + macd.updates([...subset, '90', '83.61'], false); + + macdWithReplace.updates([...subset, '100'], false); + macdWithReplace.replace(90); + macdWithReplace.add('83.61'); + + expect(macdWithReplace.short.getResult().toFixed(), 'short').toBe(macd.short.getResult().toFixed()); + expect(macdWithReplace.long.getResult().toFixed(), 'long').toBe(macd.long.getResult().toFixed()); + expect(macdWithReplace.getResult().histogram.toFixed(), 'histogram').toBe(macd.getResult().histogram.toFixed()); + expect(macdWithReplace.getResult().macd.toFixed(), 'macd').toBe(macd.getResult().macd.toFixed()); + expect(macdWithReplace.getResult().signal.toFixed(), 'signal').toBe(macd.getResult().signal.toFixed()); + }); + }); + describe('update', () => { it('can replace recently added values', () => { const macd = new MACD({ @@ -12,18 +43,14 @@ describe('MACD', () => { }); const fasterMACD = new FasterMACD(new FasterEMA(2), new FasterEMA(5), new FasterEMA(9)); - macd.update('81.59'); - fasterMACD.update(81.59); - macd.update('81.06'); - fasterMACD.update(81.06); - macd.update('82.87'); - fasterMACD.update(82.87); - macd.update('83.0'); - fasterMACD.update(83.0); - macd.update('90'); // this value gets replaced with the next call - fasterMACD.update(90); // this value gets replaced with the next call - macd.update('83.61', true); - fasterMACD.update(83.61, true); + const subset = [81.59, 81.06, 82.87, 83.0]; + macd.updates(subset, false); + fasterMACD.updates(subset, false); + + macd.add('90'); // this value gets replaced with the next call + fasterMACD.add(90); // this value gets replaced with the next call + macd.replace('83.61'); + fasterMACD.replace(83.61); expect(macd.isStable).toBe(true); expect(fasterMACD.isStable).toBe(true); @@ -106,8 +133,8 @@ describe('MACD', () => { const fasterMACD = new FasterMACD(new FasterEMA(2), new FasterEMA(5), new FasterEMA(9)); for (const [index, input] of Object.entries(prices)) { - macd.update(input); - fasterMACD.update(input); + macd.add(input); + fasterMACD.add(input); const key = parseInt(index, 10); const expectedMacd = expectedMacds[key]; @@ -193,7 +220,7 @@ describe('MACD', () => { expect(mockedPrices.length).toBe(longInterval); expect(macd.isStable).toBe(false); - mockedPrices.forEach(price => macd.update(price)); + macd.updates(mockedPrices, false); expect(macd.isStable).toBe(true); }); diff --git a/src/MACD/MACD.ts b/src/MACD/MACD.ts index 258dcf9ff..841447e86 100644 --- a/src/MACD/MACD.ts +++ b/src/MACD/MACD.ts @@ -1,6 +1,9 @@ +import type {BigSource} from 'big.js'; +import Big from 'big.js'; +import type {DEMA, FasterDEMA} from '../DEMA/DEMA.js'; import type {EMA, FasterEMA} from '../EMA/EMA.js'; -import {Big, NotEnoughDataError, type BigSource, type DEMA, type FasterDEMA} from '../index.js'; -import type {Indicator} from '../Indicator.js'; +import {TechnicalIndicator} from '../Indicator.js'; +import {pushUpdate} from '../util/pushUpdate.js'; export type MACDConfig = { indicator: typeof EMA | typeof DEMA; @@ -30,31 +33,24 @@ export type FasterMACDResult = { * * @see https://www.investopedia.com/terms/m/macd.asp */ -export class MACD implements Indicator { +export class MACD extends TechnicalIndicator { + // TODO: Use "getFixedArray" public readonly prices: BigSource[] = []; public readonly long: EMA | DEMA; public readonly short: EMA | DEMA; private readonly signal: EMA | DEMA; - private result: MACDResult | undefined; constructor(config: MACDConfig) { + super(); this.long = new config.indicator(config.longInterval); this.short = new config.indicator(config.shortInterval); this.signal = new config.indicator(config.signalInterval); } - get isStable(): boolean { - return this.result !== undefined; - } - - update(_price: BigSource, replace: boolean = false): void | MACDResult { + update(_price: BigSource, replace: boolean) { const price = new Big(_price); - if (this.prices.length && replace) { - this.prices[this.prices.length - 1] = price; - } else { - this.prices.push(price); - } + pushUpdate(this.prices, replace, price); const short = this.short.update(price, replace); const long = this.long.update(price, replace); @@ -74,7 +70,7 @@ export class MACD implements Indicator { * A short (usually 9 periods) EMA of MACD is plotted along side to act as a signal line to identify turns in the * indicator. It gets updated once the long EMA has enough input data. */ - const signal = this.signal.update(macd); + const signal = this.signal.update(macd, replace); /** * The MACD histogram is calculated as the MACD indicator minus the signal line (usually 9 periods) EMA. @@ -85,45 +81,23 @@ export class MACD implements Indicator { signal, }); } - } - - getResult(): MACDResult { - if (!this.isStable || this.result === undefined) { - throw new NotEnoughDataError(); - } - - return this.result; + return null; } } -export class FasterMACD implements Indicator { +export class FasterMACD extends TechnicalIndicator { public readonly prices: number[] = []; - private result: FasterMACDResult | undefined; constructor( public readonly short: FasterEMA | FasterDEMA, public readonly long: FasterEMA | FasterDEMA, public readonly signal: FasterEMA | FasterDEMA - ) {} - - getResult(): FasterMACDResult { - if (this.result === undefined) { - throw new NotEnoughDataError(); - } - - return this.result; + ) { + super(); } - get isStable(): boolean { - return this.result !== undefined; - } - - update(price: number, replace: boolean = false): void | FasterMACDResult { - if (this.prices.length && replace) { - this.prices[this.prices.length - 1] = price; - } else { - this.prices.push(price); - } + update(price: number, replace: boolean) { + pushUpdate(this.prices, replace, price); const short = this.short.update(price, replace); const long = this.long.update(price, replace); @@ -142,5 +116,6 @@ export class FasterMACD implements Indicator { signal, }); } + return null; } } diff --git a/src/MAD/MAD.test.ts b/src/MAD/MAD.test.ts index 0bf4f4935..ee190a58e 100644 --- a/src/MAD/MAD.test.ts +++ b/src/MAD/MAD.test.ts @@ -13,22 +13,22 @@ describe('MAD', () => { it('can replace recently added values', () => { const mad = new MAD(5); const fasterMAD = new FasterMAD(5); - mad.update(81.59); - fasterMAD.update(81.59); - mad.update(81.06); - fasterMAD.update(81.06); - mad.update(82.87); - fasterMAD.update(82.87); - mad.update(83.0); - fasterMAD.update(83.0); - mad.update(83.61); - fasterMAD.update(83.61); - mad.update(83.15); - fasterMAD.update(83.15); - mad.update(82.84); - fasterMAD.update(82.84); - mad.update(90); - fasterMAD.update(90); + mad.add(81.59); + fasterMAD.add(81.59); + mad.add(81.06); + fasterMAD.add(81.06); + mad.add(82.87); + fasterMAD.add(82.87); + mad.add(83.0); + fasterMAD.add(83.0); + mad.add(83.61); + fasterMAD.add(83.61); + mad.add(83.15); + fasterMAD.add(83.15); + mad.add(82.84); + fasterMAD.add(82.84); + mad.add(90); + fasterMAD.add(90); mad.update(83.99, true); fasterMAD.update(83.99, true); @@ -48,8 +48,8 @@ describe('MAD', () => { const mad = new MAD(5); const fasterMAD = new FasterMAD(5); for (const price of prices) { - mad.update(price); - fasterMAD.update(price); + mad.add(price); + fasterMAD.add(price); } const actual = mad.getResult().valueOf(); expect(actual).toBe('3.6'); @@ -60,8 +60,8 @@ describe('MAD', () => { const mad = new MAD(5); const fasterMAD = new FasterMAD(5); for (const price of prices) { - mad.update(price); - fasterMAD.update(price); + mad.add(price); + fasterMAD.add(price); if (mad.isStable && fasterMAD.isStable) { const expected = expectations.shift()!; expect(mad.getResult().toFixed(2)).toBe(expected); @@ -76,8 +76,8 @@ describe('MAD', () => { const mad = new MAD(5); const fasterMAD = new FasterMAD(5); for (const price of prices) { - mad.update(price); - fasterMAD.update(price); + mad.add(price); + fasterMAD.add(price); } expect(mad.highest!.valueOf()).toBe('1.0184'); expect(mad.lowest!.valueOf()).toBe('0.2288'); diff --git a/src/MAD/MAD.ts b/src/MAD/MAD.ts index 34673c979..81c6b1d94 100644 --- a/src/MAD/MAD.ts +++ b/src/MAD/MAD.ts @@ -1,6 +1,7 @@ -import {Big, type BigSource} from '../index.js'; +import type {BigSource} from 'big.js'; +import Big from 'big.js'; import {BigIndicatorSeries, NumberIndicatorSeries} from '../Indicator.js'; -import {getAverage, getFasterAverage} from '../util/index.js'; +import {getAverage, getFasterAverage, pushUpdate} from '../util/index.js'; /** * Mean Absolute Deviation (MAD) @@ -12,18 +13,15 @@ import {getAverage, getFasterAverage} from '../util/index.js'; * @see https://en.wikipedia.org/wiki/Average_absolute_deviation */ export class MAD extends BigIndicatorSeries { + // TODO: Use "getFixedArray" public readonly prices: BigSource[] = []; constructor(public readonly interval: number) { super(); } - override update(price: BigSource, replace: boolean = false): void | Big { - if (this.prices.length && replace) { - this.prices[this.prices.length - 1] = price; - } else { - this.prices.push(price); - } + update(price: BigSource, replace: boolean) { + pushUpdate(this.prices, replace, price); if (this.prices.length > this.interval) { this.prices.shift(); @@ -32,6 +30,8 @@ export class MAD extends BigIndicatorSeries { if (this.prices.length === this.interval) { return this.setResult(MAD.getResultFromBatch(this.prices), replace); } + + return null; } static getResultFromBatch(prices: BigSource[], average?: BigSource): Big { @@ -52,12 +52,8 @@ export class FasterMAD extends NumberIndicatorSeries { super(); } - override update(price: number, replace: boolean = false): void | number { - if (this.prices.length && replace) { - this.prices[this.prices.length - 1] = price; - } else { - this.prices.push(price); - } + update(price: number, replace: boolean) { + pushUpdate(this.prices, replace, price); if (this.prices.length > this.interval) { this.prices.shift(); @@ -72,6 +68,8 @@ export class FasterMAD extends NumberIndicatorSeries { } return this.setResult(sum / this.interval, replace); } + + return null; } static getResultFromBatch(prices: number[], average?: number): number { diff --git a/src/MOM/MOM.test.ts b/src/MOM/MOM.test.ts index 04fc78b19..9a721b3ae 100644 --- a/src/MOM/MOM.test.ts +++ b/src/MOM/MOM.test.ts @@ -7,18 +7,18 @@ describe('MOM', () => { const momentum = new MOM(5); const fasterMomentum = new FasterMOM(5); - momentum.update('81.59'); - fasterMomentum.update(81.59); - momentum.update('81.06'); - fasterMomentum.update(81.06); - momentum.update('82.87'); - fasterMomentum.update(82.87); - momentum.update('83.0'); - fasterMomentum.update(83.0); - momentum.update('83.61'); - fasterMomentum.update(83.61); - momentum.update('90'); - fasterMomentum.update(90); + momentum.add('81.59'); + fasterMomentum.add(81.59); + momentum.add('81.06'); + fasterMomentum.add(81.06); + momentum.add('82.87'); + fasterMomentum.add(82.87); + momentum.add('83.0'); + fasterMomentum.add(83.0); + momentum.add('83.61'); + fasterMomentum.add(83.61); + momentum.add('90'); + fasterMomentum.add(90); momentum.update('83.15', true); fasterMomentum.update(83.15, true); @@ -42,8 +42,8 @@ describe('MOM', () => { const fasterMomentum = new FasterMOM(5); for (const input of inputs) { - momentum.update(input); - fasterMomentum.update(input); + momentum.add(input); + fasterMomentum.add(input); if (momentum.isStable && fasterMomentum.isStable) { const actual = momentum.getResult().toFixed(3); const expected = outputs.shift()!; diff --git a/src/MOM/MOM.ts b/src/MOM/MOM.ts index d79d2ce3a..2c9d9ff39 100644 --- a/src/MOM/MOM.ts +++ b/src/MOM/MOM.ts @@ -1,6 +1,8 @@ +import type {BigSource} from 'big.js'; +import Big from 'big.js'; import {BigIndicatorSeries, NumberIndicatorSeries} from '../Indicator.js'; -import {Big, type BigSource} from '../index.js'; import {getFixedArray} from '../util/getFixedArray.js'; +import {pushUpdate} from '../util/pushUpdate.js'; /** * Momentum Indicator (MOM / MTM) @@ -21,15 +23,14 @@ export class MOM extends BigIndicatorSeries { this.history = getFixedArray(this.historyLength); } - override update(value: BigSource, replace: boolean = false): void | Big { - if (this.history.length && replace) { - this.history[this.history.length - 1] = value; - } else { - this.history.push(value); - } + update(value: BigSource, replace: boolean) { + pushUpdate(this.history, replace, value); + if (this.history.length === this.historyLength) { return this.setResult(new Big(value).minus(this.history[0]), replace); } + + return null; } } @@ -43,14 +44,13 @@ export class FasterMOM extends NumberIndicatorSeries { this.history = getFixedArray(this.historyLength); } - override update(value: number, replace: boolean = false): void | number { - if (this.history.length && replace) { - this.history[this.history.length - 1] = value; - } else { - this.history.push(value); - } + update(value: number, replace: boolean) { + pushUpdate(this.history, replace, value); + if (this.history.length === this.historyLength) { return this.setResult(value - this.history[0], replace); } + + return null; } } diff --git a/src/OBV/OBV.test.ts b/src/OBV/OBV.test.ts index e1eb89951..bbdcbbe9b 100644 --- a/src/OBV/OBV.test.ts +++ b/src/OBV/OBV.test.ts @@ -29,8 +29,8 @@ describe('OBV', () => { const obv = new OBV(); const fasterOBV = new FasterOBV(); for (const candle of candles) { - obv.update(candle); - fasterOBV.update(candle); + obv.add(candle); + fasterOBV.add(candle); if (obv.isStable && fasterOBV.isStable) { const expected = expectations.shift(); expect(obv.getResult().toFixed(3)).toBe(expected!); diff --git a/src/OBV/OBV.ts b/src/OBV/OBV.ts index aa36114f1..190e45b56 100644 --- a/src/OBV/OBV.ts +++ b/src/OBV/OBV.ts @@ -1,6 +1,7 @@ -import {Big} from '../index.js'; +import Big from 'big.js'; import {BigIndicatorSeries, NumberIndicatorSeries} from '../Indicator.js'; -import type {OpenHighLowCloseVolume, OpenHighLowCloseVolumeNumber} from '../util/index.js'; +import type {OpenHighLowCloseVolume, OpenHighLowCloseVolumeNumber} from '../util/HighLowClose.js'; +import {pushUpdate} from '../util/pushUpdate.js'; /** * On-Balance Volume (OBV) @@ -14,11 +15,11 @@ import type {OpenHighLowCloseVolume, OpenHighLowCloseVolumeNumber} from '../util export class OBV extends BigIndicatorSeries { public readonly candles: OpenHighLowCloseVolume[] = []; - override update(candle: OpenHighLowCloseVolume): Big | void { - this.candles.push(candle); + update(candle: OpenHighLowCloseVolume, replace: boolean) { + pushUpdate(this.candles, replace, candle); if (this.candles.length === 1) { - return; + return null; } const prevCandle = this.candles[this.candles.length - 2]; @@ -27,18 +28,18 @@ export class OBV extends BigIndicatorSeries { const currentPrice = new Big(candle.close); const nextResult = currentPrice.gt(prevPrice) ? candle.volume : currentPrice.lt(prevPrice) ? -candle.volume : 0; - return this.setResult(prevResult.add(nextResult), false); + return this.setResult(prevResult.add(nextResult), replace); } } export class FasterOBV extends NumberIndicatorSeries { public readonly candles: OpenHighLowCloseVolumeNumber[] = []; - update(candle: OpenHighLowCloseVolumeNumber): void | number { - this.candles.push(candle); + update(candle: OpenHighLowCloseVolumeNumber, replace: boolean) { + pushUpdate(this.candles, replace, candle); if (this.candles.length === 1) { - return; + return null; } const prevCandle = this.candles[this.candles.length - 2]; diff --git a/src/ROC/ROC.test.ts b/src/ROC/ROC.test.ts index 7d6b490ea..6ba5189b0 100644 --- a/src/ROC/ROC.test.ts +++ b/src/ROC/ROC.test.ts @@ -20,8 +20,8 @@ describe('ROC', () => { const fasterROC = new FasterROC(5); for (const price of prices) { - roc.update(price); - fasterROC.update(price); + roc.add(price); + fasterROC.add(price); if (roc.isStable) { const expected = expectations.shift()!; @@ -42,7 +42,7 @@ describe('ROC', () => { const prices = [1000, 900, 800, 700, 600, 500, 400, 300, 200, 100]; prices.forEach(price => { - roc.update(new Big(price)); + roc.add(new Big(price)); }); expect(roc.lowest?.toFixed(2)).toBe('-0.83'); @@ -78,7 +78,7 @@ describe('ROC', () => { expect(mockedPrices.length).toBe(interval + 1); expect(indicator.isStable).toBe(false); - mockedPrices.forEach(price => indicator.update(price)); + mockedPrices.forEach(price => indicator.add(price)); expect(indicator.isStable).toBe(true); }); diff --git a/src/ROC/ROC.ts b/src/ROC/ROC.ts index 9b9891c54..d949f0daa 100644 --- a/src/ROC/ROC.ts +++ b/src/ROC/ROC.ts @@ -1,5 +1,7 @@ -import {Big, type BigSource} from '../index.js'; +import type {BigSource} from 'big.js'; import {BigIndicatorSeries, NumberIndicatorSeries} from '../Indicator.js'; +import Big from 'big.js'; +import {pushUpdate} from '../util/pushUpdate.js'; /** * Rate Of Change Indicator (ROC) @@ -11,14 +13,15 @@ import {BigIndicatorSeries, NumberIndicatorSeries} from '../Indicator.js'; * @see https://www.investopedia.com/terms/r/rateofchange.asp */ export class ROC extends BigIndicatorSeries { + // TODO: Use "getFixedArray" public readonly prices: Big[] = []; constructor(public readonly interval: number) { super(); } - override update(price: BigSource, replace: boolean = false): Big | void { - this.prices.push(new Big(price)); + update(price: BigSource, replace: boolean) { + pushUpdate(this.prices, replace, price); /** * The priceHistory needs to have N prices in it before a result can be calculated with the following value. For @@ -29,6 +32,8 @@ export class ROC extends BigIndicatorSeries { return this.setResult(new Big(price).sub(comparePrice).div(comparePrice), replace); } + + return null; } } @@ -39,13 +44,15 @@ export class FasterROC extends NumberIndicatorSeries { super(); } - override update(price: number, replace: boolean = false): void | number { - this.prices.push(price); + update(price: number, replace: boolean) { + pushUpdate(this.prices, replace, price); if (this.prices.length > this.interval) { const comparePrice = this.prices.shift()!; return this.setResult((price - comparePrice) / comparePrice, replace); } + + return null; } } diff --git a/src/RSI/RSI.test.ts b/src/RSI/RSI.test.ts index b91c35c2e..c6dbbceee 100644 --- a/src/RSI/RSI.test.ts +++ b/src/RSI/RSI.test.ts @@ -6,22 +6,22 @@ describe('RSI', () => { it('can replace recently added values', () => { const rsi = new RSI(5); const fasterRSI = new FasterRSI(5); - rsi.update('81.59'); - fasterRSI.update(81.59); - rsi.update('81.06'); - fasterRSI.update(81.06); - rsi.update('82.87'); - fasterRSI.update(82.87); - rsi.update('83.0'); - fasterRSI.update(83.0); - rsi.update('83.61'); - fasterRSI.update(83.61); - rsi.update('83.15'); - fasterRSI.update(83.15); - rsi.update('82.84'); - fasterRSI.update(82.84); - rsi.update('90'); // this value gets replaced with the next call - fasterRSI.update(90); // this value gets replaced with the next call + rsi.add('81.59'); + fasterRSI.add(81.59); + rsi.add('81.06'); + fasterRSI.add(81.06); + rsi.add('82.87'); + fasterRSI.add(82.87); + rsi.add('83.0'); + fasterRSI.add(83.0); + rsi.add('83.61'); + fasterRSI.add(83.61); + rsi.add('83.15'); + fasterRSI.add(83.15); + rsi.add('82.84'); + fasterRSI.add(82.84); + rsi.add('90'); // this value gets replaced with the next call + fasterRSI.add(90); // this value gets replaced with the next call rsi.update('83.99', true); fasterRSI.update(83.99, true); @@ -55,8 +55,8 @@ describe('RSI', () => { const rsi = new RSI(5); const fasterRSI = new FasterRSI(5); for (const price of prices) { - rsi.update(price); - fasterRSI.update(price); + rsi.add(price); + fasterRSI.add(price); if (rsi.isStable && fasterRSI.isStable) { const expected = expectations.shift(); expect(rsi.getResult().toFixed(3)).toBe(expected!); @@ -77,22 +77,20 @@ describe('RSI', () => { }); it('catches division by zero errors', () => { + const updates = [2, 2, 2]; + const rsi = new RSI(2); - rsi.update(2); - rsi.update(2); - rsi.update(2); + rsi.updates(updates, false); expect(rsi.getResult().valueOf()).toBe('100'); const fasterRSI = new FasterRSI(2); - fasterRSI.update(2); - fasterRSI.update(2); - fasterRSI.update(2); + fasterRSI.updates(updates, false); expect(fasterRSI.getResult().valueOf()).toBe(100); }); it('throws an error when there is not enough input data', () => { const rsi = new RSI(2); - rsi.update(0); + rsi.add(0); expect(rsi.isStable).toBe(false); try { rsi.getResult(); diff --git a/src/RSI/RSI.ts b/src/RSI/RSI.ts index 1e3de797b..a8f25f9a1 100644 --- a/src/RSI/RSI.ts +++ b/src/RSI/RSI.ts @@ -1,8 +1,10 @@ -import {Big, type BigSource} from '../index.js'; import type {FasterMovingAverage, MovingAverage} from '../MA/MovingAverage.js'; import {BigIndicatorSeries, NumberIndicatorSeries} from '../Indicator.js'; import type {FasterMovingAverageTypes, MovingAverageTypes} from '../MA/MovingAverageTypes.js'; import {FasterWSMA, WSMA} from '../WSMA/WSMA.js'; +import type {BigSource} from 'big.js'; +import Big from 'big.js'; +import {pushUpdate} from '../util/pushUpdate.js'; /** * Relative Strength Index (RSI) @@ -22,6 +24,7 @@ import {FasterWSMA, WSMA} from '../WSMA/WSMA.js'; * @see https://www.investopedia.com/terms/r/rsi.asp */ export class RSI extends BigIndicatorSeries { + // TODO: Use "getFixedArray" private readonly previousPrices: BigSource[] = []; private readonly avgGain: MovingAverage; private readonly avgLoss: MovingAverage; @@ -36,18 +39,12 @@ export class RSI extends BigIndicatorSeries { this.avgLoss = new SmoothingIndicator(this.interval); } - override update(price: BigSource, replace: boolean = false): void | Big { - if (this.previousPrices.length && replace) { - // Replace the last price with the provided price - this.previousPrices[this.previousPrices.length - 1] = price; - } else { - // Add the price to the list of previous prices - this.previousPrices.push(price); - } + update(price: BigSource, replace: boolean) { + pushUpdate(this.previousPrices, replace, price); // Ensure at least 2 prices are available for calculation if (this.previousPrices.length < 2) { - return; + return null; } const currentPrice = new Big(price); @@ -61,6 +58,11 @@ export class RSI extends BigIndicatorSeries { this.avgGain.update(new Big(0), replace); // price went down, therefore no gain } + // Avoids memory leaks + if (this.previousPrices.length > this.interval) { + this.previousPrices.shift(); + } + if (this.avgGain.isStable) { const avgLoss = this.avgLoss.getResult(); // Prevent division by zero: https://github.com/bennycode/trading-signals/issues/378 @@ -70,6 +72,8 @@ export class RSI extends BigIndicatorSeries { const relativeStrength = this.avgGain.getResult().div(avgLoss); return this.setResult(this.maxValue.minus(this.maxValue.div(relativeStrength.add(1))), replace); } + + return null; } } @@ -88,18 +92,12 @@ export class FasterRSI extends NumberIndicatorSeries { this.avgLoss = new SmoothingIndicator(this.interval); } - override update(price: number, replace: boolean = false): void | number { - if (this.previousPrices.length && replace) { - // Replace the last price with the provided price - this.previousPrices[this.previousPrices.length - 1] = price; - } else { - // Add the price to the list of previous prices - this.previousPrices.push(price); - } + update(price: number, replace: boolean) { + pushUpdate(this.previousPrices, replace, price); // Ensure at least 2 prices are available for calculation if (this.previousPrices.length < 2) { - return; + return null; } const currentPrice = price; @@ -113,6 +111,11 @@ export class FasterRSI extends NumberIndicatorSeries { this.avgGain.update(0, replace); } + // Avoids memory leaks + if (this.previousPrices.length > this.interval) { + this.previousPrices.shift(); + } + if (this.avgGain.isStable) { const avgLoss = this.avgLoss.getResult(); // Prevent division by zero: https://github.com/bennycode/trading-signals/issues/378 @@ -122,5 +125,7 @@ export class FasterRSI extends NumberIndicatorSeries { const relativeStrength = this.avgGain.getResult() / avgLoss; return this.setResult(this.maxValue - this.maxValue / (relativeStrength + 1), replace); } + + return null; } } diff --git a/src/SMA/SMA.test.ts b/src/SMA/SMA.test.ts index d8142744d..0a9a967af 100644 --- a/src/SMA/SMA.test.ts +++ b/src/SMA/SMA.test.ts @@ -5,16 +5,16 @@ describe('SMA', () => { describe('prices', () => { it('does not cache more prices than necessary to fill the interval', () => { const sma = new SMA(3); - sma.update(1); - sma.update(2); + sma.add(1); + sma.add(2); expect(sma.prices.length).toBe(2); - sma.update(3); + sma.add(3); expect(sma.prices.length).toBe(3); - sma.update(4); + sma.add(4); expect(sma.prices.length).toBe(3); - sma.update(5); + sma.add(5); expect(sma.prices.length).toBe(3); - sma.update(6); + sma.add(6); expect(sma.prices.length).toBe(3); }); }); @@ -26,11 +26,11 @@ describe('SMA', () => { const sma = new SMA(interval); const fasterSMA = new FasterSMA(interval); - sma.update(20); - fasterSMA.update(20); + sma.add(20); + fasterSMA.add(20); - sma.update(30); - fasterSMA.update(30); + sma.add(30); + fasterSMA.add(30); // Add the latest value const latestValue = 40; @@ -38,12 +38,12 @@ describe('SMA', () => { const latestLow = '25.00'; const latestHigh = '35.00'; - sma.update(latestValue); + sma.add(latestValue); expect(sma.getResult().toFixed(2)).toBe(latestResult); expect(sma.lowest?.toFixed(2)).toBe(latestLow); expect(sma.highest?.toFixed(2)).toBe(latestHigh); - fasterSMA.update(latestValue); + fasterSMA.add(latestValue); expect(fasterSMA.getResult().toFixed(2)).toBe(latestResult); expect(fasterSMA.lowest?.toFixed(2)).toBe(latestLow); expect(fasterSMA.highest?.toFixed(2)).toBe(latestHigh); @@ -84,8 +84,8 @@ describe('SMA', () => { const sma = new SMA(interval); const fasterSMA = new FasterSMA(interval); - sma.updates(prices); - fasterSMA.updates(prices); + sma.updates(prices, false); + fasterSMA.updates(prices, false); expect(sma.getResult().toFixed()).toBe('3'); expect(fasterSMA.getResult().toFixed()).toBe('3'); @@ -95,13 +95,13 @@ describe('SMA', () => { describe('isStable', () => { it('knows when there is enough input data', () => { const sma = new SMA(3); - sma.update(40); - sma.update(30); + sma.add(40); + sma.add(30); expect(sma.isStable).toBe(false); - sma.update(20); + sma.add(20); expect(sma.isStable).toBe(true); - sma.update('10'); - sma.update(new Big(30)); + sma.add('10'); + sma.add(new Big(30)); expect(sma.getResult().valueOf()).toBe('20'); expect(sma.lowest?.toFixed(2)).toBe('20.00'); expect(sma.highest?.toFixed(2)).toBe('30.00'); @@ -135,8 +135,8 @@ describe('SMA', () => { for (let i = 0; i < prices.length; i++) { const price = prices[i]; - const result = sma.update(price); - const fasterResult = fasterSMA.update(price); + const result = sma.add(price); + const fasterResult = fasterSMA.add(price); if (result && fasterResult) { const expected = expectations[i - (interval - 1)]; diff --git a/src/SMA/SMA.ts b/src/SMA/SMA.ts index 5c75e033e..f23b2f23c 100644 --- a/src/SMA/SMA.ts +++ b/src/SMA/SMA.ts @@ -1,5 +1,7 @@ -import {Big, type BigSource} from '../index.js'; +import type {BigSource} from 'big.js'; import {FasterMovingAverage, MovingAverage} from '../MA/MovingAverage.js'; +import {pushUpdate} from '../util/pushUpdate.js'; +import Big from 'big.js'; /** * Simple Moving Average (SMA) @@ -11,14 +13,11 @@ import {FasterMovingAverage, MovingAverage} from '../MA/MovingAverage.js'; * @see https://www.investopedia.com/terms/s/sma.asp */ export class SMA extends MovingAverage { + // TODO: Use "getFixedArray" public readonly prices: BigSource[] = []; - override update(price: BigSource, replace: boolean = false): Big | void { - if (this.prices.length && replace) { - this.prices[this.prices.length - 1] = price; - } else { - this.prices.push(price); - } + update(price: BigSource, replace: boolean) { + pushUpdate(this.prices, replace, price); if (this.prices.length > this.interval) { this.prices.shift(); @@ -27,6 +26,8 @@ export class SMA extends MovingAverage { if (this.prices.length === this.interval) { return this.setResult(SMA.getResultFromBatch(this.prices), replace); } + + return null; } static getResultFromBatch(prices: BigSource[]): Big { @@ -38,12 +39,8 @@ export class SMA extends MovingAverage { export class FasterSMA extends FasterMovingAverage { public readonly prices: number[] = []; - update(price: number, replace: boolean = false): void | number { - if (this.prices.length && replace) { - this.prices[this.prices.length - 1] = price; - } else { - this.prices.push(price); - } + update(price: number, replace: boolean) { + pushUpdate(this.prices, replace, price); if (this.prices.length > this.interval) { this.prices.shift(); @@ -53,5 +50,7 @@ export class FasterSMA extends FasterMovingAverage { const sum = this.prices.reduce((a, b) => a + b, 0); return this.setResult(sum / this.prices.length, replace); } + + return null; } } diff --git a/src/STOCH/StochasticOscillator.test.ts b/src/STOCH/StochasticOscillator.test.ts index f0151be03..1984d23c6 100644 --- a/src/STOCH/StochasticOscillator.test.ts +++ b/src/STOCH/StochasticOscillator.test.ts @@ -32,11 +32,11 @@ describe('StochasticOscillator', () => { const fasterStoch = new FasterStochasticOscillator(5, 3, 3); for (const candle of candles) { - const stochResult = stoch.update(candle); - const fasterStochResult = fasterStoch.update(candle); + const stochResult = stoch.add(candle); + const fasterStochResult = fasterStoch.add(candle); if (fasterStoch.isStable && fasterStochResult && stoch.isStable && stochResult) { - const stochD = stochDs.shift()!; - const stochK = stochKs.shift()!; + const stochD = stochDs.shift(); + const stochK = stochKs.shift(); expect(stochResult.stochD.toFixed(2)).toEqual(stochD); expect(fasterStochResult.stochD.toFixed(2)).toEqual(stochD); @@ -58,12 +58,12 @@ describe('StochasticOscillator', () => { it('throws an error when there is not enough input data', () => { const stoch = new StochasticOscillator(5, 3, 3); - stoch.update({close: 1, high: 1, low: 1}); - stoch.update({close: 1, high: 2, low: 1}); - stoch.update({close: 1, high: 3, low: 1}); - stoch.update({close: 1, high: 4, low: 1}); - stoch.update({close: 1, high: 5, low: 1}); // Emits 1st of 3 required values for %d period - stoch.update({close: 1, high: 6, low: 1}); // Emits 2nd of 3 required values for %d period + stoch.add({close: 1, high: 1, low: 1}); + stoch.add({close: 1, high: 2, low: 1}); + stoch.add({close: 1, high: 3, low: 1}); + stoch.add({close: 1, high: 4, low: 1}); + stoch.add({close: 1, high: 5, low: 1}); // Emits 1st of 3 required values for %d period + stoch.add({close: 1, high: 6, low: 1}); // Emits 2nd of 3 required values for %d period try { stoch.getResult(); @@ -84,21 +84,31 @@ describe('StochasticOscillator', () => { it('prevents division by zero errors when highest high and lowest low have the same value', () => { const stoch = new StochasticOscillator(5, 3, 3); - stoch.update({close: 100, high: 100, low: 100}); - stoch.update({close: 100, high: 100, low: 100}); - stoch.update({close: 100, high: 100, low: 100}); - stoch.update({close: 100, high: 100, low: 100}); - stoch.update({close: 100, high: 100, low: 100}); - stoch.update({close: 100, high: 100, low: 100}); - stoch.update({close: 100, high: 100, low: 100}); - stoch.update({close: 100, high: 100, low: 100}); - const result = stoch.update({close: 100, high: 100, low: 100})!; - expect(result.stochK.toFixed(2)).toBe('0.00'); - expect(result.stochD.toFixed(2)).toBe('0.00'); + stoch.updates( + [ + {close: 100, high: 100, low: 100}, + {close: 100, high: 100, low: 100}, + {close: 100, high: 100, low: 100}, + {close: 100, high: 100, low: 100}, + {close: 100, high: 100, low: 100}, + {close: 100, high: 100, low: 100}, + {close: 100, high: 100, low: 100}, + {close: 100, high: 100, low: 100}, + ], + false + ); + const result = stoch.add({close: 100, high: 100, low: 100}); + expect(result?.stochK.toFixed(2)).toBe('0.00'); + expect(result?.stochD.toFixed(2)).toBe('0.00'); const fasterStoch = new FasterStochasticOscillator(1, 2, 2); - fasterStoch.update({close: 100, high: 100, low: 100}); - fasterStoch.update({close: 100, high: 100, low: 100}); + fasterStoch.updates( + [ + {close: 100, high: 100, low: 100}, + {close: 100, high: 100, low: 100}, + ], + false + ); const {stochK, stochD} = fasterStoch.getResult(); expect(stochK.toFixed(2)).toBe('0.00'); expect(stochD.toFixed(2)).toBe('0.00'); diff --git a/src/STOCH/StochasticOscillator.ts b/src/STOCH/StochasticOscillator.ts index 534aa1cda..effe41399 100644 --- a/src/STOCH/StochasticOscillator.ts +++ b/src/STOCH/StochasticOscillator.ts @@ -1,10 +1,10 @@ -import type {Indicator} from '../Indicator.js'; -import {Big} from '../index.js'; +import Big from 'big.js'; +import {TechnicalIndicator} from '../Indicator.js'; import {FasterSMA, SMA} from '../SMA/SMA.js'; import {getMaximum} from '../util/getMaximum.js'; import {getMinimum} from '../util/getMinimum.js'; -import {NotEnoughDataError} from '../error/index.js'; -import type {HighLowClose, HighLowCloseNumber} from '../util/index.js'; +import type {HighLowClose, HighLowCloseNumber} from '../util/HighLowClose.js'; +import {pushUpdate} from '../util/pushUpdate.js'; export interface StochasticResult { /** Slow stochastic indicator (%D) */ @@ -37,12 +37,11 @@ export interface FasterStochasticResult { * @see https://en.wikipedia.org/wiki/Stochastic_oscillator * @see https://www.investopedia.com/terms/s/stochasticoscillator.asp */ -export class StochasticOscillator implements Indicator { +export class StochasticOscillator extends TechnicalIndicator { private readonly periodM: SMA; private readonly periodP: SMA; - + // TODO: Use "getFixedArray" private readonly candles: HighLowClose[] = []; - private result?: StochasticResult; /** * Constructs a Stochastic Oscillator. @@ -56,20 +55,13 @@ export class StochasticOscillator implements Indicator this.n) { this.candles.shift(); @@ -82,8 +74,8 @@ export class StochasticOscillator implements Indicator { +export class FasterStochasticOscillator extends TechnicalIndicator { public readonly candles: HighLowCloseNumber[] = []; - private result: FasterStochasticResult | undefined; private readonly periodM: FasterSMA; private readonly periodP: FasterSMA; @@ -114,24 +103,13 @@ export class FasterStochasticOscillator implements Indicator this.n) { this.candles.shift(); @@ -144,14 +122,17 @@ export class FasterStochasticOscillator implements Indicator { + describe('replace', () => { + it('replaces the most recently added value', () => { + const interval = 2; + const stochRSI = new StochasticRSI(interval); + const stochRSIWithReplace = new StochasticRSI(interval); + + stochRSI.updates([2, 2, 2, 2], false); + stochRSIWithReplace.updates([2, 2, 2, 1], false); + stochRSIWithReplace.replace(2); + + expect(stochRSI.getResult().valueOf()).toBe(stochRSIWithReplace.getResult().valueOf()); + }); + }); + describe('getResult', () => { it('calculates the Stochastic RSI', () => { // Test data verified with: @@ -9,11 +23,12 @@ describe('StochasticRSI', () => { 81.59, 81.06, 82.87, 83.0, 83.61, 83.15, 82.84, 83.99, 84.55, 84.36, 85.53, 86.54, 86.89, 87.77, 87.29, ]; const expectations = ['0.658', '1.000', '1.000', '1.000', '1.000', '0.000']; - const stochRSI = new StochasticRSI(5); - const fasterStochRSI = new FasterStochasticRSI(5); + const interval = 5; + const stochRSI = new StochasticRSI(interval); + const fasterStochRSI = new FasterStochasticRSI(interval); for (const price of prices) { - const result = stochRSI.update(price); - const fasterResult = fasterStochRSI.update(price); + const result = stochRSI.add(price); + const fasterResult = fasterStochRSI.add(price); if (result && fasterResult) { const expected = expectations.shift(); expect(result.toFixed(3)).toBe(expected!); @@ -34,18 +49,13 @@ describe('StochasticRSI', () => { }); it('catches division by zero errors', () => { - const stochRSI = new StochasticRSI(2); - stochRSI.update(2); - stochRSI.update(2); - stochRSI.update(2); - stochRSI.update(2); + const interval = 2; + const stochRSI = new StochasticRSI(interval); + stochRSI.updates([2, 2, 2, 2], false); expect(stochRSI.getResult().valueOf()).toBe('100'); - const fasterStochRSI = new FasterStochasticRSI(2); - fasterStochRSI.update(2); - fasterStochRSI.update(2); - fasterStochRSI.update(2); - fasterStochRSI.update(2); + const fasterStochRSI = new FasterStochasticRSI(interval); + fasterStochRSI.updates([2, 2, 2, 2], false); expect(fasterStochRSI.getResult().valueOf()).toBe(100); }); }); diff --git a/src/STOCH/StochasticRSI.ts b/src/STOCH/StochasticRSI.ts index c357018a7..f96daff28 100644 --- a/src/STOCH/StochasticRSI.ts +++ b/src/STOCH/StochasticRSI.ts @@ -1,9 +1,10 @@ import {BigIndicatorSeries, NumberIndicatorSeries} from '../Indicator.js'; import {FasterRSI, RSI} from '../RSI/RSI.js'; -import {Big, type BigSource} from '../index.js'; import {FasterPeriod, Period} from '../util/Period.js'; import type {FasterMovingAverageTypes, MovingAverageTypes} from '../MA/MovingAverageTypes.js'; import {FasterWSMA, WSMA} from '../WSMA/WSMA.js'; +import type {BigSource} from 'big.js'; +import Big from 'big.js'; /** * Stochastic RSI (STOCHRSI) @@ -33,22 +34,24 @@ export class StochasticRSI extends BigIndicatorSeries { this.rsi = new RSI(interval, SmoothingIndicator); } - override update(price: BigSource, replace: boolean = false): void | Big { - const rsiResult = this.rsi.update(price); + update(price: BigSource, replace: boolean) { + const rsiResult = this.rsi.update(price, replace); if (rsiResult) { - const periodResult = this.period.update(rsiResult); + const periodResult = this.period.update(rsiResult, replace); if (periodResult) { const min = periodResult.lowest; const max = periodResult.highest; const denominator = max.minus(min); // Prevent division by zero: https://github.com/bennycode/trading-signals/issues/378 if (denominator.eq(0)) { - return this.setResult(new Big(100), replace); + return this.setResult(new Big(100), false); } const numerator = rsiResult.minus(min); - return this.setResult(numerator.div(denominator), replace); + return this.setResult(numerator.div(denominator), false); } } + + return null; } } @@ -65,10 +68,10 @@ export class FasterStochasticRSI extends NumberIndicatorSeries { this.rsi = new FasterRSI(interval, SmoothingIndicator); } - override update(price: number, replace: boolean = false): void | number { - const rsiResult = this.rsi.update(price); - if (rsiResult !== undefined) { - const periodResult = this.period.update(rsiResult); + update(price: number, replace: boolean) { + const rsiResult = this.rsi.update(price, replace); + if (rsiResult) { + const periodResult = this.period.update(rsiResult, replace); if (periodResult) { const min = periodResult.lowest; const max = periodResult.highest; @@ -81,5 +84,7 @@ export class FasterStochasticRSI extends NumberIndicatorSeries { return this.setResult(numerator / denominator, replace); } } + + return null; } } diff --git a/src/TR/TR.test.ts b/src/TR/TR.test.ts index 14e5d3b0c..f4a6bef2a 100644 --- a/src/TR/TR.test.ts +++ b/src/TR/TR.test.ts @@ -44,8 +44,8 @@ describe('TR', () => { const fasterTR = new FasterTR(); candles.forEach((candle, i) => { - tr.update(candle); - fasterTR.update(candle); + tr.add(candle); + fasterTR.add(candle); if (tr.isStable && fasterTR.isStable) { const expected = expectations[i]; expect(tr.getResult().toFixed(2)).toBe(expected!); @@ -74,8 +74,8 @@ describe('TR', () => { // Update candles except last one. candles.slice(-1).forEach(candle => { - tr.update(candle); - fasterTR.update(candle); + tr.add(candle); + fasterTR.add(candle); }); const lastCandle = candles.at(-1); @@ -85,8 +85,8 @@ describe('TR', () => { // Add the latest value if (lastCandle) { - tr.update(lastCandle); - fasterTR.update(lastCandle); + tr.add(lastCandle); + fasterTR.add(lastCandle); } expect(tr.getResult().toFixed(2)).toBe(latestResult); diff --git a/src/TR/TR.ts b/src/TR/TR.ts index 842c22159..8fd7a4097 100644 --- a/src/TR/TR.ts +++ b/src/TR/TR.ts @@ -1,6 +1,7 @@ -import {Big} from '../index.js'; +import Big from 'big.js'; import {BigIndicatorSeries, NumberIndicatorSeries} from '../Indicator.js'; -import {getMaximum, type HighLowClose, type HighLowCloseNumber} from '../util/index.js'; +import {getMaximum} from '../util/getMaximum.js'; +import type {HighLowClose, HighLowCloseNumber} from '../util/HighLowClose.js'; /** * True Range (TR) @@ -15,24 +16,25 @@ import {getMaximum, type HighLowClose, type HighLowCloseNumber} from '../util/in */ export class TR extends BigIndicatorSeries { private previousCandle?: HighLowClose; - private twoPreviousCandle?: HighLowClose; + private secondLastCandle?: HighLowClose; - update(candle: HighLowClose, replace: boolean = false): Big { + update(candle: HighLowClose, replace: boolean): Big { const high = new Big(candle.high); const highLow = high.minus(candle.low); if (this.previousCandle && replace) { - this.previousCandle = this.twoPreviousCandle; + this.previousCandle = this.secondLastCandle; } if (this.previousCandle) { const highClose = high.minus(this.previousCandle.close).abs(); const lowClose = new Big(candle.low).minus(this.previousCandle.close).abs(); - this.twoPreviousCandle = this.previousCandle; + this.secondLastCandle = this.previousCandle; this.previousCandle = candle; return this.setResult(getMaximum([highLow, highClose, lowClose]), replace); } - this.twoPreviousCandle = this.previousCandle; + + this.secondLastCandle = this.previousCandle; this.previousCandle = candle; return this.setResult(highLow, replace); @@ -43,7 +45,7 @@ export class FasterTR extends NumberIndicatorSeries { private previousCandle?: HighLowCloseNumber; private twoPreviousCandle?: HighLowCloseNumber; - update(candle: HighLowCloseNumber, replace: boolean = false): number { + update(candle: HighLowCloseNumber, replace: boolean): number { const {high, low} = candle; const highLow = high - low; diff --git a/src/WMA/WMA.test.ts b/src/WMA/WMA.test.ts index a532d42db..a7849787a 100644 --- a/src/WMA/WMA.test.ts +++ b/src/WMA/WMA.test.ts @@ -6,26 +6,26 @@ describe('WMA', () => { it('does not cache more prices than necessary to fill the interval', () => { const wma = new WMA(3); const fasterWMA = new FasterWMA(3); - wma.update(1); - fasterWMA.update(1); - wma.update(2); - fasterWMA.update(2); + wma.add(1); + fasterWMA.add(1); + wma.add(2); + fasterWMA.add(2); expect(wma.prices.length).toBe(2); expect(fasterWMA.prices.length).toBe(2); - wma.update(3); - fasterWMA.update(3); + wma.add(3); + fasterWMA.add(3); expect(wma.prices.length).toBe(3); expect(fasterWMA.prices.length).toBe(3); - wma.update(4); - fasterWMA.update(4); + wma.add(4); + fasterWMA.add(4); expect(wma.prices.length).toBe(3); expect(fasterWMA.prices.length).toBe(3); - wma.update(5); - fasterWMA.update(5); + wma.add(5); + fasterWMA.add(5); expect(wma.prices.length).toBe(3); expect(fasterWMA.prices.length).toBe(3); - wma.update(6); - fasterWMA.update(6); + wma.add(6); + fasterWMA.add(6); expect(wma.prices.length).toBe(3); expect(fasterWMA.prices.length).toBe(3); }); @@ -38,14 +38,14 @@ describe('WMA', () => { const wma = new WMA(interval); const fasterWMA = new FasterWMA(interval); - wma.update(11); - fasterWMA.update(11); - wma.update(12); - fasterWMA.update(12); - wma.update(13); - fasterWMA.update(13); - wma.update(14); - fasterWMA.update(14); + wma.add(11); + fasterWMA.add(11); + wma.add(12); + fasterWMA.add(12); + wma.add(13); + fasterWMA.add(13); + wma.add(14); + fasterWMA.add(14); // Add the latest value const latestValue = 15; @@ -53,12 +53,12 @@ describe('WMA', () => { const latestLow = '12.33'; const latestHigh = '14.33'; - wma.update(latestValue); + wma.add(latestValue); expect(wma.getResult().toFixed(2)).toBe(latestResult); expect(wma.lowest?.toFixed(2)).toBe(latestLow); expect(wma.highest?.toFixed(2)).toBe(latestHigh); - fasterWMA.update(latestValue); + fasterWMA.add(latestValue); expect(fasterWMA.getResult().toFixed(2)).toBe(latestResult); expect(fasterWMA.lowest?.toFixed(2)).toBe(latestLow); expect(fasterWMA.highest?.toFixed(2)).toBe(latestHigh); @@ -99,8 +99,8 @@ describe('WMA', () => { const wma = new WMA(interval); const fasterWMA = new FasterWMA(interval); - wma.updates(prices); - fasterWMA.updates(prices); + wma.updates(prices, false); + fasterWMA.updates(prices, false); expect(wma.getResult().toFixed()).toBe('74'); expect(fasterWMA.getResult().toFixed()).toBe('74'); @@ -110,13 +110,13 @@ describe('WMA', () => { describe('isStable', () => { it('knows when there is enough input data', () => { const wma = new WMA(3); - wma.update(30); - wma.update(60); + wma.add(30); + wma.add(60); expect(wma.isStable).toBe(false); - wma.update(90); + wma.add(90); expect(wma.isStable).toBe(true); - wma.update('120'); - wma.update(new Big(60)); + wma.add('120'); + wma.add(new Big(60)); expect(wma.getResult().valueOf()).toBe('85'); expect(wma.lowest?.toFixed(2)).toBe('70.00'); expect(wma.highest?.toFixed(2)).toBe('100.00'); @@ -131,8 +131,8 @@ describe('WMA', () => { const fasterWMA = new FasterWMA(5); for (const price of prices) { - const result = wma.update(price); - const fasterResult = fasterWMA.update(price); + const result = wma.add(price); + const fasterResult = fasterWMA.add(price); if (result && fasterResult) { const expected = expectations.shift()!; diff --git a/src/WMA/WMA.ts b/src/WMA/WMA.ts index bdcc2624f..381ce393b 100644 --- a/src/WMA/WMA.ts +++ b/src/WMA/WMA.ts @@ -1,5 +1,7 @@ -import {Big, type BigSource} from '../index.js'; +import type {BigSource} from 'big.js'; +import Big from 'big.js'; import {FasterMovingAverage, MovingAverage} from '../MA/MovingAverage.js'; +import {pushUpdate} from '../util/pushUpdate.js'; /** * Weighted Moving Average (WMA) @@ -11,18 +13,15 @@ import {FasterMovingAverage, MovingAverage} from '../MA/MovingAverage.js'; * @see https://corporatefinanceinstitute.com/resources/career-map/sell-side/capital-markets/weighted-moving-average-wma/ */ export class WMA extends MovingAverage { + // TODO: Use "getFixedArray" public readonly prices: BigSource[] = []; - constructor(public readonly interval: number) { + constructor(public override readonly interval: number) { super(interval); } - override update(price: BigSource, replace: boolean = false): Big | void { - if (this.prices.length && replace) { - this.prices[this.prices.length - 1] = price; - } else { - this.prices.push(price); - } + update(price: BigSource, replace: boolean) { + pushUpdate(this.prices, replace, price); if (this.prices.length > this.interval) { this.prices.shift(); @@ -40,22 +39,20 @@ export class WMA extends MovingAverage { return this.setResult(weightedMa, replace); } + + return null; } } export class FasterWMA extends FasterMovingAverage { public readonly prices: number[] = []; - constructor(public readonly interval: number) { + constructor(public override readonly interval: number) { super(interval); } - override update(price: number, replace: boolean = false): number | void { - if (this.prices.length && replace) { - this.prices[this.prices.length - 1] = price; - } else { - this.prices.push(price); - } + update(price: number, replace: boolean) { + pushUpdate(this.prices, replace, price); if (this.prices.length > this.interval) { this.prices.shift(); @@ -74,5 +71,7 @@ export class FasterWMA extends FasterMovingAverage { return this.setResult(weightedMa, replace); } + + return null; } } diff --git a/src/WSMA/WSMA.test.ts b/src/WSMA/WSMA.test.ts index 8640a355b..98c5c763a 100644 --- a/src/WSMA/WSMA.test.ts +++ b/src/WSMA/WSMA.test.ts @@ -3,20 +3,40 @@ import {NotEnoughDataError} from '../error/index.js'; describe('WSMA', () => { describe('replace', () => { + it('replaces the most recently added value', () => { + const interval = 3; + + const wsma = new WSMA(interval); + const wsmaWithReplace = new WSMA(interval); + + const subset = [11, 12, 13]; + + wsma.updates([...subset, 14, 15], false); + + wsmaWithReplace.updates([...subset, 50], false); + wsmaWithReplace.replace(14); + wsmaWithReplace.add(15); + + const actual = wsmaWithReplace.getResult().toFixed(); + const expected = wsma.getResult().toFixed(); + + expect(actual).toBe(expected); + }); + it('replaces recently added values', () => { const interval = 3; const wsma = new WSMA(interval); const fasterWSMA = new FasterWSMA(interval); - wsma.update(11); - fasterWSMA.update(11); - wsma.update(12); - fasterWSMA.update(12); - wsma.update(13); - fasterWSMA.update(13); - wsma.update(14); - fasterWSMA.update(14); + wsma.add(11); + fasterWSMA.add(11); + wsma.add(12); + fasterWSMA.add(12); + wsma.add(13); + fasterWSMA.add(13); + wsma.add(14); + fasterWSMA.add(14); // Add the latest value const latestValue = 15; @@ -24,12 +44,12 @@ describe('WSMA', () => { const latestLow = '12.00'; const latestHigh = '13.44'; - wsma.update(latestValue); + wsma.add(latestValue); expect(wsma.getResult().toFixed(2)).toBe(latestResult); expect(wsma.lowest?.toFixed(2)).toBe(latestLow); expect(wsma.highest?.toFixed(2)).toBe(latestHigh); - fasterWSMA.update(latestValue); + fasterWSMA.add(latestValue); expect(fasterWSMA.getResult().toFixed(2)).toBe(latestResult); expect(fasterWSMA.lowest?.toFixed(2)).toBe(latestLow); expect(fasterWSMA.highest?.toFixed(2)).toBe(latestHigh); @@ -72,7 +92,7 @@ describe('WSMA', () => { const wsma = new WSMA(5); for (const price of prices) { - wsma.update(price); + wsma.add(price); if (wsma.isStable) { const expected = expectations.shift(); expect(wsma.getResult().toFixed(2)).toBe(expected); @@ -109,8 +129,8 @@ describe('WSMA', () => { for (let i = 0; i < prices.length; i++) { const price = prices[i]; - wsma.update(price); - fasterWSMA.update(price); + wsma.add(price); + fasterWSMA.add(price); if (wsma.isStable && fasterWSMA.isStable) { const expected = expectations[i]; expect(wsma.getResult().toFixed(4)).toBe(expected); @@ -144,8 +164,8 @@ describe('WSMA', () => { it('throws an error when there is not enough input data', () => { const wsma = new WSMA(3); - wsma.update(1); - wsma.update(2); + wsma.add(1); + wsma.add(2); try { wsma.getResult(); @@ -164,8 +184,8 @@ describe('WSMA', () => { const wsma = new WSMA(interval); const fasterWSMA = new FasterWSMA(interval); - wsma.updates(prices); - fasterWSMA.updates(prices); + wsma.updates(prices, false); + fasterWSMA.updates(prices, false); expect(wsma.getResult().toFixed(2)).toBe('18.97'); expect(fasterWSMA.getResult().toFixed(2)).toBe('18.97'); @@ -175,10 +195,10 @@ describe('WSMA', () => { describe('isStable', () => { it('is stable when the inputs can fill the signal interval', () => { const wsma = new WSMA(3); - wsma.update(1); - wsma.update(2); + wsma.add(1); + wsma.add(2); expect(wsma.isStable).toBe(false); - wsma.update(3); + wsma.add(3); expect(wsma.isStable).toBe(true); }); }); diff --git a/src/WSMA/WSMA.ts b/src/WSMA/WSMA.ts index f01e45c4e..12bbb9984 100644 --- a/src/WSMA/WSMA.ts +++ b/src/WSMA/WSMA.ts @@ -1,7 +1,8 @@ -import {Big, type BigSource} from '../index.js'; import {MovingAverage} from '../MA/MovingAverage.js'; import {FasterSMA, SMA} from '../SMA/SMA.js'; import {NumberIndicatorSeries} from '../Indicator.js'; +import type {BigSource} from 'big.js'; +import Big from 'big.js'; /** * Wilder's Smoothed Moving Average (WSMA) @@ -22,28 +23,26 @@ export class WSMA extends MovingAverage { private readonly indicator: SMA; private readonly smoothingFactor: Big; - constructor(public readonly interval: number) { + constructor(public override readonly interval: number) { super(interval); this.indicator = new SMA(interval); this.smoothingFactor = new Big(1).div(this.interval); } - updates(prices: BigSource[]): Big | void { - prices.forEach(price => this.update(price)); - return this.result; - } - - update(price: BigSource, replace: boolean = false): Big | void { + update(price: BigSource, replace: boolean) { const sma = this.indicator.update(price, replace); + if (replace && this.previousResult) { const smoothed = new Big(price).minus(this.previousResult).mul(this.smoothingFactor); return this.setResult(smoothed.plus(this.previousResult), replace); - } else if (!replace && this.result) { + } else if (!replace && this.result !== undefined) { const smoothed = new Big(price).minus(this.result).mul(this.smoothingFactor); return this.setResult(smoothed.plus(this.result), replace); - } else if (this.result === undefined && sma) { + } else if (this.result === undefined && sma !== null) { return this.setResult(sma, replace); } + + return null; } } @@ -57,21 +56,18 @@ export class FasterWSMA extends NumberIndicatorSeries { this.smoothingFactor = 1 / this.interval; } - updates(prices: number[]): number | void { - prices.forEach(price => this.update(price)); - return this.result; - } - - update(price: number, replace: boolean = false): number | void { - const sma = this.indicator.update(price); + update(price: number, replace: boolean) { + const sma = this.indicator.update(price, replace); if (replace && this.previousResult !== undefined) { const smoothed = (price - this.previousResult) * this.smoothingFactor; return this.setResult(smoothed + this.previousResult, replace); } else if (!replace && this.result !== undefined) { const smoothed = (price - this.result) * this.smoothingFactor; return this.setResult(smoothed + this.result, replace); - } else if (this.result === undefined && sma !== undefined) { + } else if (this.result === undefined && sma !== null) { return this.setResult(sma, replace); } + + return null; } } diff --git a/src/index.ts b/src/index.ts index 9b78ef3a1..5a087c403 100644 --- a/src/index.ts +++ b/src/index.ts @@ -1,4 +1,7 @@ export {default as Big, type BigSource} from 'big.js'; +export * from './Indicator.js'; +export * from './MA/MovingAverage.js'; +export * from './MA/MovingAverageTypes.js'; export * from './ABANDS/AccelerationBands.js'; export * from './AC/AC.js'; export * from './ADX/ADX.js'; @@ -13,9 +16,6 @@ export * from './DMA/DMA.js'; export * from './DX/DX.js'; export * from './EMA/EMA.js'; export * from './error/index.js'; -export * from './Indicator.js'; -export * from './MA/MovingAverage.js'; -export * from './MA/MovingAverageTypes.js'; export * from './MACD/MACD.js'; export * from './MAD/MAD.js'; export * from './MOM/MOM.js'; diff --git a/src/start/startBenchmark.ts b/src/start/startBenchmark.ts index 413ebab3f..c8c54c3c6 100644 --- a/src/start/startBenchmark.ts +++ b/src/start/startBenchmark.ts @@ -76,157 +76,157 @@ new Benchmark.Suite('Technical Indicators') .add('AccelerationBands', () => { const accBands = new AccelerationBands(interval, 4); for (const candle of floatCandles) { - accBands.update(candle); + accBands.add(candle); } }) .add('FasterAccelerationBands', () => { const fasterAccBands = new FasterAccelerationBands(interval, 4); for (const candle of floatCandles) { - fasterAccBands.update(candle); + fasterAccBands.add(candle); } }) .add('AC', () => { const ac = new AC(shortInterval, longInterval, interval); for (const candle of floatCandles) { - ac.update(candle); + ac.add(candle); } }) .add('FasterAC', () => { const fasterAC = new FasterAC(shortInterval, longInterval, interval); for (const candle of floatCandles) { - fasterAC.update(candle); + fasterAC.add(candle); } }) .add('ADX', () => { const adx = new ADX(interval); for (const candle of floatCandles) { - adx.update(candle); + adx.add(candle); } }) .add('FasterADX', () => { const fasterADX = new FasterADX(interval); for (const candle of floatCandles) { - fasterADX.update(candle); + fasterADX.add(candle); } }) .add('AO', () => { const ao = new AO(shortInterval, interval); for (const candle of floatCandles) { - ao.update(candle); + ao.add(candle); } }) .add('FasterAO', () => { const fasterAO = new FasterAO(shortInterval, interval); for (const candle of floatCandles) { - fasterAO.update(candle); + fasterAO.add(candle); } }) .add('ATR', () => { const atr = new ATR(interval); for (const candle of floatCandles) { - atr.update(candle); + atr.add(candle); } }) .add('FasterATR', () => { const fasterATR = new FasterATR(interval); for (const candle of floatCandles) { - fasterATR.update(candle); + fasterATR.add(candle); } }) .add('BollingerBands', () => { const bb = new BollingerBands(interval, 2); for (const price of prices) { - bb.update(price); + bb.add(price); } }) .add('FasterBollingerBands', () => { const fasterBB = new FasterBollingerBands(interval, 2); for (const price of prices) { - fasterBB.update(price); + fasterBB.add(price); } }) .add('BollingerBandsWidth', () => { const bbw = new BollingerBandsWidth(new BollingerBands(interval, 2)); for (const price of prices) { - bbw.update(price); + bbw.add(price); } }) .add('FasterBollingerBandsWidth', () => { const fasterBBW = new FasterBollingerBandsWidth(new FasterBollingerBands(interval, 2)); for (const price of prices) { - fasterBBW.update(price); + fasterBBW.add(price); } }) .add('CCI', () => { const cci = new CCI(interval); for (const candle of floatCandles) { - cci.update(candle); + cci.add(candle); } }) .add('FasterCCI', () => { const fasterCCI = new FasterCCI(interval); for (const candle of floatCandles) { - fasterCCI.update(candle); + fasterCCI.add(candle); } }) .add('CG', () => { const cg = new CG(shortInterval, interval); for (const price of prices) { - cg.update(price); + cg.add(price); } }) .add('FasterCG', () => { const fasterCG = new FasterCG(shortInterval, interval); for (const price of prices) { - fasterCG.update(price); + fasterCG.add(price); } }) .add('DEMA', () => { const dema = new DEMA(interval); for (const price of prices) { - dema.update(price); + dema.add(price); } }) .add('FasterDEMA', () => { const fasterDEMA = new FasterDEMA(interval); for (const price of prices) { - fasterDEMA.update(price); + fasterDEMA.add(price); } }) .add('DMA', () => { const dma = new DMA(3, 6); for (const price of prices) { - dma.update(price); + dma.add(price); } }) .add('FasterDMA', () => { const fasterDMA = new FasterDMA(3, 6); for (const price of prices) { - fasterDMA.update(price); + fasterDMA.add(price); } }) .add('DX', () => { const dx = new DX(interval); for (const candle of floatCandles) { - dx.update(candle); + dx.add(candle); } }) .add('FasterDX', () => { const fasterDX = new FasterDX(interval); for (const candle of floatCandles) { - fasterDX.update(candle); + fasterDX.add(candle); } }) .add('EMA', () => { const ema = new EMA(interval); for (const price of prices) { - ema.update(price); + ema.add(price); } }) .add('FasterEMA', () => { const fasterEMA = new FasterEMA(interval); for (const price of prices) { - fasterEMA.update(price); + fasterEMA.add(price); } }) .add('MACD', () => { @@ -237,157 +237,157 @@ new Benchmark.Suite('Technical Indicators') signalInterval: 9, }); for (const price of prices) { - mad.update(price); + mad.add(price); } }) .add('FasterMACD', () => { const fasterMACD = new FasterMACD(new FasterEMA(2), new FasterEMA(5), new FasterEMA(9)); for (const price of prices) { - fasterMACD.update(price); + fasterMACD.add(price); } }) .add('MAD', () => { const mad = new MAD(interval); for (const price of prices) { - mad.update(price); + mad.add(price); } }) .add('FasterMAD', () => { const fasterMad = new FasterMAD(interval); for (const price of prices) { - fasterMad.update(price); + fasterMad.add(price); } }) .add('MOM', () => { const mom = new MOM(interval); for (const price of prices) { - mom.update(price); + mom.add(price); } }) .add('FasterMOM', () => { const fasterMOM = new FasterMOM(interval); for (const price of prices) { - fasterMOM.update(price); + fasterMOM.add(price); } }) .add('OBV', () => { const obv = new OBV(); for (const candle of floatCandles) { - obv.update(candle); + obv.add(candle); } }) .add('FasterOBV', () => { const fasterOBV = new FasterOBV(); for (const candle of floatCandles) { - fasterOBV.update(candle); + fasterOBV.add(candle); } }) .add('Period', () => { const period = new Period(interval); for (const price of prices) { - period.update(price); + period.add(price); } }) .add('FasterPeriod', () => { const fasterPeriod = new FasterPeriod(interval); for (const price of prices) { - fasterPeriod.update(price); + fasterPeriod.add(price); } }) .add('ROC', () => { const roc = new ROC(interval); for (const price of prices) { - roc.update(price); + roc.add(price); } }) .add('FasterROC', () => { const fasterROC = new FasterROC(interval); for (const price of prices) { - fasterROC.update(price); + fasterROC.add(price); } }) .add('RSI', () => { const rsi = new RSI(interval); for (const price of prices) { - rsi.update(price); + rsi.add(price); } }) .add('FasterRSI', () => { const fasterRSI = new FasterRSI(interval); for (const price of prices) { - fasterRSI.update(price); + fasterRSI.add(price); } }) .add('SMA', () => { const sma = new SMA(interval); for (const price of prices) { - sma.update(price); + sma.add(price); } }) .add('FasterSMA', () => { const fasterSMA = new FasterSMA(interval); for (const price of prices) { - fasterSMA.update(price); + fasterSMA.add(price); } }) .add('StochasticOscillator', () => { const stoch = new StochasticOscillator(shortInterval, interval, interval); for (const candle of candles) { - stoch.update(candle); + stoch.add(candle); } }) .add('FasterStochasticOscillator', () => { const fasterStoch = new FasterStochasticOscillator(shortInterval, interval, interval); for (const candle of floatCandles) { - fasterStoch.update(candle); + fasterStoch.add(candle); } }) .add('StochasticRSI', () => { const stochRSI = new StochasticRSI(interval); for (const price of prices) { - stochRSI.update(price); + stochRSI.add(price); } }) .add('FasterStochasticRSI', () => { const fasterStochRSI = new FasterStochasticRSI(interval); for (const price of prices) { - fasterStochRSI.update(price); + fasterStochRSI.add(price); } }) .add('TR', () => { const tr = new TR(); for (const candle of floatCandles) { - tr.update(candle); + tr.add(candle); } }) .add('FasterTR', () => { const fasterTR = new FasterTR(); for (const candle of floatCandles) { - fasterTR.update(candle); + fasterTR.add(candle); } }) .add('WSMA', () => { const wsma = new WSMA(interval); for (const price of prices) { - wsma.update(price); + wsma.add(price); } }) .add('FasterWSMA', () => { const fasterWSMA = new FasterWSMA(interval); for (const price of prices) { - fasterWSMA.update(price); + fasterWSMA.add(price); } }) .add('WMA', () => { const wma = new WMA(interval); for (const price of prices) { - wma.update(price); + wma.add(price); } }) .add('FasterWMA', () => { const fasterWMA = new FasterWMA(interval); for (const price of prices) { - fasterWMA.update(price); + fasterWMA.add(price); } }) .add('getAverage', () => { diff --git a/src/util/BandsResult.ts b/src/util/BandsResult.ts index 63cebb8c6..f36328a02 100644 --- a/src/util/BandsResult.ts +++ b/src/util/BandsResult.ts @@ -1,4 +1,4 @@ -import type {Big} from '../index.js'; +import type {Big} from 'big.js'; export interface BandsResult { lower: Big; diff --git a/src/util/HighLowClose.ts b/src/util/HighLowClose.ts index 4e15a6aa3..c4252a447 100644 --- a/src/util/HighLowClose.ts +++ b/src/util/HighLowClose.ts @@ -1,4 +1,4 @@ -import type {BigSource} from '../index.js'; +import type {BigSource} from 'big.js'; export type HighLow = {high: BigSource; low: BigSource}; diff --git a/src/util/Period.test.ts b/src/util/Period.test.ts index 9ce3d921d..5bc3c8819 100644 --- a/src/util/Period.test.ts +++ b/src/util/Period.test.ts @@ -1,22 +1,59 @@ +import {NotEnoughDataError} from '../error/NotEnoughDataError.js'; import {FasterPeriod, Period} from './Period.js'; describe('Period', () => { + describe('replace', () => { + it('replaces the most recently added value', () => { + const interval = 5; + const expectedLow = '30'; + const expectedHigh = '70'; + + const period = new Period(interval); + const periodWithReplace = new Period(interval); + const fasterPeriodWithReplace = new FasterPeriod(interval); + + const subset = [30, 40, 50, 60]; + period.updates([...subset, 70], false); + periodWithReplace.updates([...subset, 90], false); + periodWithReplace.replace(70); + fasterPeriodWithReplace.updates([...subset, 90], false); + fasterPeriodWithReplace.replace(70); + + expect(periodWithReplace.lowest?.toFixed()).toBe(expectedLow); + expect(periodWithReplace.highest?.toFixed()).toBe(expectedHigh); + expect(fasterPeriodWithReplace.highest?.toFixed()).toBe(expectedHigh); + }); + }); + describe('getResult', () => { it('returns the highest and lowest value of the current period', () => { - const period = new Period(2); - period.update(72); - period.update(1337); + const values = [72, 1337]; + const interval = 2; + const period = new Period(interval); + period.updates(values, false); const {highest, lowest} = period.getResult(); expect(lowest.valueOf()).toBe('72'); expect(highest.valueOf()).toBe('1337'); - const fasterPeriod = new FasterPeriod(2); - fasterPeriod.update(72); - fasterPeriod.update(1337); + expect(period.lowest?.valueOf()).toBe('72'); + expect(period.highest?.valueOf()).toBe('1337'); + + const fasterPeriod = new FasterPeriod(interval); + fasterPeriod.updates(values, false); const {highest: fastestHighest, lowest: fastestLowest} = fasterPeriod.getResult(); expect(fastestLowest).toBe(72); expect(fastestHighest).toBe(1337); }); + + it('throws an error when there is not enough input data', () => { + const period = new Period(2); + try { + period.getResult(); + throw new Error('Expected error'); + } catch (error) { + expect(error).toBeInstanceOf(NotEnoughDataError); + } + }); }); describe('isStable', () => { @@ -39,11 +76,12 @@ describe('Period', () => { '84.36', '85.53', ]; - const period = new Period(5); - const fasterPeriod = new FasterPeriod(5); + const interval = 5; + const period = new Period(interval); + const fasterPeriod = new FasterPeriod(interval); for (const price of prices) { - period.update(price); - fasterPeriod.update(price); + period.add(price); + fasterPeriod.add(price); if (period.isStable) { const expected = lowest.shift(); expect(period.lowest?.toFixed(2)).toBe(expected); diff --git a/src/util/Period.ts b/src/util/Period.ts index 88f88691e..079c2ead3 100644 --- a/src/util/Period.ts +++ b/src/util/Period.ts @@ -1,8 +1,10 @@ -import {Big, type BigSource} from '../index.js'; -import type {Indicator} from '../Indicator.js'; +import type {BigSource} from 'big.js'; +import Big from 'big.js'; +import {TechnicalIndicator} from '../Indicator.js'; import {getFixedArray} from './getFixedArray.js'; -import {getMinimum} from './getMinimum.js'; import {getMaximum} from './getMaximum.js'; +import {getMinimum} from './getMinimum.js'; +import {pushUpdate} from './pushUpdate.js'; export interface PeriodResult { highest: Big; @@ -14,66 +16,74 @@ export interface FasterPeriodResult { lowest: number; } -export class Period implements Indicator { - public values: Big[]; +export class Period extends TechnicalIndicator { + private readonly values: Big[]; /** Highest return value during the current period. */ - public highest?: Big; + private _highest?: Big; /** Lowest return value during the current period. */ - public lowest?: Big; + private _lowest?: Big; + + get highest() { + return this._highest; + } + + get lowest() { + return this._lowest; + } constructor(public readonly interval: number) { + super(); this.values = getFixedArray(interval); } - getResult(): PeriodResult { - return { - highest: this.highest!, - lowest: this.lowest!, - }; - } + update(value: BigSource, replace: boolean) { + pushUpdate(this.values, replace, new Big(value)); - update(value: BigSource): PeriodResult | void { - this.values.push(new Big(value)); - if (this.isStable) { - this.lowest = getMinimum(this.values); - this.highest = getMaximum(this.values); - return this.getResult(); + if (this.values.length === this.interval) { + this._lowest = getMinimum(this.values); + this._highest = getMaximum(this.values); + return (this.result = { + highest: this._highest, + lowest: this._lowest, + }); } - } - get isStable(): boolean { - return this.values.length === this.interval; + return null; } } -export class FasterPeriod implements Indicator { +export class FasterPeriod extends TechnicalIndicator { public values: number[]; /** Highest return value during the current period. */ - public highest?: number; + private _highest?: number; /** Lowest return value during the current period. */ - public lowest?: number; + private _lowest?: number; - constructor(public readonly interval: number) { - this.values = getFixedArray(interval); + get highest() { + return this._highest; } - getResult(): FasterPeriodResult { - return { - highest: this.highest!, - lowest: this.lowest!, - }; + get lowest() { + return this._lowest; } - update(value: number): FasterPeriodResult | void { - this.values.push(value); - if (this.isStable) { - this.lowest = Math.min(...this.values); - this.highest = Math.max(...this.values); - return this.getResult(); - } + constructor(public readonly interval: number) { + super(); + this.values = getFixedArray(interval); } - get isStable(): boolean { - return this.values.length === this.interval; + update(value: number, replace: boolean) { + pushUpdate(this.values, replace, value); + + if (this.values.length === this.interval) { + this._lowest = Math.min(...this.values); + this._highest = Math.max(...this.values); + return (this.result = { + highest: this._highest, + lowest: this._lowest, + }); + } + + return null; } } diff --git a/src/util/getAverage.ts b/src/util/getAverage.ts index 1f68640bf..ccc8bc40c 100644 --- a/src/util/getAverage.ts +++ b/src/util/getAverage.ts @@ -1,4 +1,5 @@ -import {Big, type BigSource} from '../index.js'; +import type {BigSource} from 'big.js'; +import Big from 'big.js'; /** * Return the mean / average value. diff --git a/src/util/getLastFromForEach.test.ts b/src/util/getLastFromForEach.test.ts new file mode 100644 index 000000000..c207bd094 --- /dev/null +++ b/src/util/getLastFromForEach.test.ts @@ -0,0 +1,9 @@ +import {getLastFromForEach} from './getLastFromForEach.js'; + +describe('getLastFromForEach', () => { + it('returns the last value from an forEach execution', () => { + const array = [1, 2, 3, 4]; + const result = getLastFromForEach(array, value => value * 2); + expect(result).toBe(8); + }); +}); diff --git a/src/util/getLastFromForEach.ts b/src/util/getLastFromForEach.ts new file mode 100644 index 000000000..ad5552a0e --- /dev/null +++ b/src/util/getLastFromForEach.ts @@ -0,0 +1,12 @@ +export function getLastFromForEach( + array: readonly T[], + callback: (value: T, index: number, array: readonly T[]) => R +): R | null { + let lastValue: R | null = null; + + array.forEach((item, index) => { + lastValue = callback(item, index, array); + }); + + return lastValue; +} diff --git a/src/util/getMaximum.ts b/src/util/getMaximum.ts index d2bbecd25..b252722d6 100644 --- a/src/util/getMaximum.ts +++ b/src/util/getMaximum.ts @@ -1,4 +1,5 @@ -import {Big, type BigSource} from '../index.js'; +import Big from 'big.js'; +import type {BigSource} from 'big.js'; export function getMaximum(values: BigSource[]): Big { let max = new Big(Number.MIN_SAFE_INTEGER); diff --git a/src/util/getMinimum.ts b/src/util/getMinimum.ts index 76be88478..4c96c14e0 100644 --- a/src/util/getMinimum.ts +++ b/src/util/getMinimum.ts @@ -1,4 +1,5 @@ -import {Big, type BigSource} from '../index.js'; +import Big from 'big.js'; +import type {BigSource} from 'big.js'; export function getMinimum(values: BigSource[]): Big { let min = new Big(Number.MAX_SAFE_INTEGER); diff --git a/src/util/getStandardDeviation.ts b/src/util/getStandardDeviation.ts index fb4cfeeed..780148a4f 100644 --- a/src/util/getStandardDeviation.ts +++ b/src/util/getStandardDeviation.ts @@ -1,5 +1,6 @@ +import type {BigSource} from 'big.js'; +import Big from 'big.js'; import {getFasterAverage, getAverage} from './getAverage.js'; -import {Big, type BigSource} from '../index.js'; /** * Standard deviation calculates how prices for a collection of prices are spread out from the average price of these diff --git a/src/util/index.ts b/src/util/index.ts index 96eacad70..003f964ff 100644 --- a/src/util/index.ts +++ b/src/util/index.ts @@ -1,8 +1,11 @@ export * from './BandsResult.js'; export * from './getAverage.js'; export * from './getFixedArray.js'; +export * from './getLastFromForEach.js'; export * from './getMaximum.js'; export * from './getMinimum.js'; export * from './getStandardDeviation.js'; +export * from './getStreaks.js'; export * from './HighLowClose.js'; export * from './Period.js'; +export * from './pushUpdate.js'; diff --git a/src/util/pushUpdate.ts b/src/util/pushUpdate.ts new file mode 100644 index 000000000..9899a385f --- /dev/null +++ b/src/util/pushUpdate.ts @@ -0,0 +1,12 @@ +/** + * Adds an item to the array or replaces the last item in the array. + */ +export function pushUpdate(array: T[], replace: boolean, item: T) { + if (array.length > 0 && replace === true) { + array[array.length - 1] = item; + } else { + array.push(item); + } + + return item; +} diff --git a/tsconfig.json b/tsconfig.json index ee25594ad..6aefa2dae 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -9,6 +9,7 @@ "moduleResolution": "nodenext", "newLine": "lf", "noEmitOnError": true, + "noImplicitOverride": true, "noImplicitReturns": true, "noUnusedLocals": true, "noUnusedParameters": true, diff --git a/vitest.config.ts b/vitest.config.ts index e7bac83fb..bf8f2e052 100644 --- a/vitest.config.ts +++ b/vitest.config.ts @@ -1,7 +1,13 @@ import {defineConfig} from 'vitest/config'; export default defineConfig({ + esbuild: { + // Allows using the "accessor" keyword in TypeScript: + // https://github.com/vitest-dev/vitest/issues/5976#issuecomment-2190804966 + target: 'es2022', + }, test: { + bail: 1, coverage: { include: ['**/*.{ts,tsx}', '!**/*.d.ts', '!**/cli.ts', '!**/index.ts', '!**/start*.ts'], provider: 'v8',